Merge branch 'deadlock-fixes' of https://github.com/jgarzik/bitcoin
This commit is contained in:
commit
57b7fe4e6f
4 changed files with 87 additions and 69 deletions
2
db.cpp
2
db.cpp
|
@ -668,8 +668,8 @@ bool CWalletDB::LoadWallet()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
//// todo: shouldn't we catch exceptions and try to recover and continue?
|
||||||
CRITICAL_BLOCK(cs_mapKeys)
|
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
CRITICAL_BLOCK(cs_mapKeys)
|
||||||
{
|
{
|
||||||
// Get cursor
|
// Get cursor
|
||||||
Dbc* pcursor = GetCursor();
|
Dbc* pcursor = GetCursor();
|
||||||
|
|
38
main.cpp
38
main.cpp
|
@ -4046,35 +4046,35 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// requires cs_main lock
|
||||||
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||||
{
|
{
|
||||||
CRITICAL_BLOCK(cs_main)
|
CReserveKey reservekey;
|
||||||
|
int64 nFeeRequired;
|
||||||
|
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
||||||
{
|
{
|
||||||
CReserveKey reservekey;
|
string strError;
|
||||||
int64 nFeeRequired;
|
if (nValue + nFeeRequired > GetBalance())
|
||||||
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
|
strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str());
|
||||||
{
|
else
|
||||||
string strError;
|
strError = _("Error: Transaction creation failed ");
|
||||||
if (nValue + nFeeRequired > GetBalance())
|
printf("SendMoney() : %s", strError.c_str());
|
||||||
strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str());
|
return strError;
|
||||||
else
|
|
||||||
strError = _("Error: Transaction creation failed ");
|
|
||||||
printf("SendMoney() : %s", strError.c_str());
|
|
||||||
return strError;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
|
||||||
return "ABORTED";
|
|
||||||
|
|
||||||
if (!CommitTransaction(wtxNew, reservekey))
|
|
||||||
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
|
||||||
|
return "ABORTED";
|
||||||
|
|
||||||
|
if (!CommitTransaction(wtxNew, reservekey))
|
||||||
|
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
|
||||||
|
|
||||||
MainFrameRepaint();
|
MainFrameRepaint();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// requires cs_main lock
|
||||||
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
|
||||||
{
|
{
|
||||||
// Check amount
|
// Check amount
|
||||||
|
|
87
rpc.cpp
87
rpc.cpp
|
@ -315,46 +315,45 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// requires cs_main, cs_mapWallet locks
|
||||||
string GetAccountAddress(string strAccount, bool bForceNew=false)
|
string GetAccountAddress(string strAccount, bool bForceNew=false)
|
||||||
{
|
{
|
||||||
string strAddress;
|
string strAddress;
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CWalletDB walletdb;
|
||||||
|
walletdb.TxnBegin();
|
||||||
|
|
||||||
|
CAccount account;
|
||||||
|
walletdb.ReadAccount(strAccount, account);
|
||||||
|
|
||||||
|
// Check if the current key has been used
|
||||||
|
if (!account.vchPubKey.empty())
|
||||||
{
|
{
|
||||||
CWalletDB walletdb;
|
CScript scriptPubKey;
|
||||||
walletdb.TxnBegin();
|
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
||||||
|
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
|
||||||
CAccount account;
|
it != mapWallet.end() && !account.vchPubKey.empty();
|
||||||
walletdb.ReadAccount(strAccount, account);
|
++it)
|
||||||
|
|
||||||
// Check if the current key has been used
|
|
||||||
if (!account.vchPubKey.empty())
|
|
||||||
{
|
{
|
||||||
CScript scriptPubKey;
|
const CWalletTx& wtx = (*it).second;
|
||||||
scriptPubKey.SetBitcoinAddress(account.vchPubKey);
|
foreach(const CTxOut& txout, wtx.vout)
|
||||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
|
if (txout.scriptPubKey == scriptPubKey)
|
||||||
it != mapWallet.end() && !account.vchPubKey.empty();
|
account.vchPubKey.clear();
|
||||||
++it)
|
|
||||||
{
|
|
||||||
const CWalletTx& wtx = (*it).second;
|
|
||||||
foreach(const CTxOut& txout, wtx.vout)
|
|
||||||
if (txout.scriptPubKey == scriptPubKey)
|
|
||||||
account.vchPubKey.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a new key
|
|
||||||
if (account.vchPubKey.empty() || bForceNew)
|
|
||||||
{
|
|
||||||
account.vchPubKey = GetKeyFromKeyPool();
|
|
||||||
string strAddress = PubKeyToAddress(account.vchPubKey);
|
|
||||||
SetAddressBookName(strAddress, strAccount);
|
|
||||||
walletdb.WriteAccount(strAccount, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
walletdb.TxnCommit();
|
|
||||||
strAddress = PubKeyToAddress(account.vchPubKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate a new key
|
||||||
|
if (account.vchPubKey.empty() || bForceNew)
|
||||||
|
{
|
||||||
|
account.vchPubKey = GetKeyFromKeyPool();
|
||||||
|
string strAddress = PubKeyToAddress(account.vchPubKey);
|
||||||
|
SetAddressBookName(strAddress, strAccount);
|
||||||
|
walletdb.WriteAccount(strAccount, account);
|
||||||
|
}
|
||||||
|
|
||||||
|
walletdb.TxnCommit();
|
||||||
|
strAddress = PubKeyToAddress(account.vchPubKey);
|
||||||
|
|
||||||
return strAddress;
|
return strAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +367,15 @@ Value getaccountaddress(const Array& params, bool fHelp)
|
||||||
// Parse the account first so we don't generate a key if there's an error
|
// Parse the account first so we don't generate a key if there's an error
|
||||||
string strAccount = AccountFromValue(params[0]);
|
string strAccount = AccountFromValue(params[0]);
|
||||||
|
|
||||||
return GetAccountAddress(strAccount);
|
Value ret;
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
|
{
|
||||||
|
ret = GetAccountAddress(strAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,6 +399,8 @@ Value setaccount(const Array& params, bool fHelp)
|
||||||
strAccount = AccountFromValue(params[1]);
|
strAccount = AccountFromValue(params[1]);
|
||||||
|
|
||||||
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
CRITICAL_BLOCK(cs_mapAddressBook)
|
CRITICAL_BLOCK(cs_mapAddressBook)
|
||||||
{
|
{
|
||||||
if (mapAddressBook.count(strAddress))
|
if (mapAddressBook.count(strAddress))
|
||||||
|
@ -475,9 +484,13 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
||||||
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
|
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
|
||||||
wtx.mapValue["to"] = params[3].get_str();
|
wtx.mapValue["to"] = params[3].get_str();
|
||||||
|
|
||||||
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
CRITICAL_BLOCK(cs_main)
|
||||||
if (strError != "")
|
{
|
||||||
throw JSONRPCError(-4, strError);
|
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
|
||||||
|
if (strError != "")
|
||||||
|
throw JSONRPCError(-4, strError);
|
||||||
|
}
|
||||||
|
|
||||||
return wtx.GetHash().GetHex();
|
return wtx.GetHash().GetHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,6 +765,7 @@ Value sendfrom(const Array& params, bool fHelp)
|
||||||
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
|
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
|
||||||
wtx.mapValue["to"] = params[5].get_str();
|
wtx.mapValue["to"] = params[5].get_str();
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
{
|
{
|
||||||
// Check funds
|
// Check funds
|
||||||
|
@ -808,6 +822,7 @@ Value sendmany(const Array& params, bool fHelp)
|
||||||
vecSend.push_back(make_pair(scriptPubKey, nAmount));
|
vecSend.push_back(make_pair(scriptPubKey, nAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
{
|
{
|
||||||
// Check funds
|
// Check funds
|
||||||
|
|
29
ui.cpp
29
ui.cpp
|
@ -1934,20 +1934,23 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event)
|
||||||
|
|
||||||
if (fBitcoinAddress)
|
if (fBitcoinAddress)
|
||||||
{
|
{
|
||||||
// Send to bitcoin address
|
CRITICAL_BLOCK(cs_main)
|
||||||
CScript scriptPubKey;
|
{
|
||||||
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
// Send to bitcoin address
|
||||||
|
CScript scriptPubKey;
|
||||||
|
scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
|
|
||||||
string strError = SendMoney(scriptPubKey, nValue, wtx, true);
|
string strError = SendMoney(scriptPubKey, nValue, wtx, true);
|
||||||
if (strError == "")
|
if (strError == "")
|
||||||
wxMessageBox(_("Payment sent "), _("Sending..."));
|
wxMessageBox(_("Payment sent "), _("Sending..."));
|
||||||
else if (strError == "ABORTED")
|
else if (strError == "ABORTED")
|
||||||
return; // leave send dialog open
|
return; // leave send dialog open
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wxMessageBox(strError + " ", _("Sending..."));
|
wxMessageBox(strError + " ", _("Sending..."));
|
||||||
EndModal(false);
|
EndModal(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue