aboutsummaryrefslogtreecommitdiff
path: root/src/rpc.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2011-08-26 14:37:23 -0400
committerGavin Andresen <gavinandresen@gmail.com>2011-08-31 12:55:16 -0400
commit6cc4a62c0e696dcb9d90ba0504f688e4f644a10f (patch)
tree5b365769be7c8be7caf6c31c4bdb1b4798be9ef4 /src/rpc.cpp
parentb0243da77c6ee8d8ca59b4423f333a179bff02cf (diff)
Fix rpc-hanging deadlocks
Collapsed multiple wallet mutexes to a single cs_wallet, to avoid deadlocks with wallet methods that acquired locks in different order. Also change master RPC call handler to acquire cs_main and cs_wallet locks before executing RPC calls; requiring each RPC call to acquire the right set of locks in the right order was too error-prone.
Diffstat (limited to 'src/rpc.cpp')
-rw-r--r--src/rpc.cpp633
1 files changed, 280 insertions, 353 deletions
diff --git a/src/rpc.cpp b/src/rpc.cpp
index 62b2f82fb1..5eb5669acb 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -346,55 +346,50 @@ Value getnewaddress(const Array& params, bool fHelp)
CBitcoinAddress address(pwalletMain->GetOrReuseKeyFromPool());
// This could be done in the same main CS as GetKeyFromKeyPool.
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
- pwalletMain->SetAddressBookName(address, strAccount);
+ pwalletMain->SetAddressBookName(address, strAccount);
return address.ToString();
}
-// requires cs_main, cs_mapWallet, cs_mapAddressBook locks
CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
{
CWalletDB walletdb(pwalletMain->strWalletFile);
CAccount account;
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
- {
- walletdb.ReadAccount(strAccount, account);
+ walletdb.ReadAccount(strAccount, account);
- bool bKeyUsed = false;
+ bool bKeyUsed = false;
- // Check if the current key has been used
- if (!account.vchPubKey.empty())
+ // Check if the current key has been used
+ if (!account.vchPubKey.empty())
+ {
+ CScript scriptPubKey;
+ scriptPubKey.SetBitcoinAddress(account.vchPubKey);
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
+ it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
+ ++it)
{
- CScript scriptPubKey;
- scriptPubKey.SetBitcoinAddress(account.vchPubKey);
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
- it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
- ++it)
- {
- const CWalletTx& wtx = (*it).second;
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- if (txout.scriptPubKey == scriptPubKey)
- bKeyUsed = true;
- }
+ const CWalletTx& wtx = (*it).second;
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+ if (txout.scriptPubKey == scriptPubKey)
+ bKeyUsed = true;
}
+ }
- // Generate a new key
- if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
+ // Generate a new key
+ if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
+ {
+ if (pwalletMain->GetKeyPoolSize() < 1)
{
- if (pwalletMain->GetKeyPoolSize() < 1)
- {
- if (bKeyUsed || bForceNew)
- throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
- }
- else
- {
- account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
- pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
- walletdb.WriteAccount(strAccount, account);
- }
+ if (bKeyUsed || bForceNew)
+ throw JSONRPCError(-12, "Error: Keypool ran out, please call topupkeypool first");
+ }
+ else
+ {
+ account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
+ pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
+ walletdb.WriteAccount(strAccount, account);
}
}
@@ -413,12 +408,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
Value ret;
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
- {
- ret = GetAccountAddress(strAccount).ToString();
- }
+ ret = GetAccountAddress(strAccount).ToString();
return ret;
}
@@ -442,20 +432,15 @@ Value setaccount(const Array& params, bool fHelp)
strAccount = AccountFromValue(params[1]);
// Detect when changing the account of an address that is the 'unused current key' of another account:
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+ if (pwalletMain->mapAddressBook.count(address))
{
- if (pwalletMain->mapAddressBook.count(address))
- {
- string strOldAccount = pwalletMain->mapAddressBook[address];
- if (address == GetAccountAddress(strOldAccount))
- GetAccountAddress(strOldAccount, true);
- }
-
- pwalletMain->SetAddressBookName(address, strAccount);
+ string strOldAccount = pwalletMain->mapAddressBook[address];
+ if (address == GetAccountAddress(strOldAccount))
+ GetAccountAddress(strOldAccount, true);
}
+ pwalletMain->SetAddressBookName(address, strAccount);
+
return Value::null;
}
@@ -472,12 +457,9 @@ Value getaccount(const Array& params, bool fHelp)
throw JSONRPCError(-5, "Invalid bitcoin address");
string strAccount;
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
- {
- map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
- if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
- strAccount = (*mi).second;
- }
+ map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
+ if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
+ strAccount = (*mi).second;
return strAccount;
}
@@ -493,15 +475,12 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
// Find all addresses that have the given account
Array ret;
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
- {
- const CBitcoinAddress& address = item.first;
- const string& strName = item.second;
- if (strName == strAccount)
- ret.push_back(address.ToString());
- }
+ const CBitcoinAddress& address = item.first;
+ const string& strName = item.second;
+ if (strName == strAccount)
+ ret.push_back(address.ToString());
}
return ret;
}
@@ -548,16 +527,12 @@ Value sendtoaddress(const Array& params, bool fHelp)
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
- {
- if(pwalletMain->IsLocked())
- throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+ if (pwalletMain->IsLocked())
+ throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
- string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
- if (strError != "")
- throw JSONRPCError(-4, strError);
- }
+ string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
+ if (strError != "")
+ throw JSONRPCError(-4, strError);
return wtx.GetHash().GetHex();
}
@@ -586,19 +561,16 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
// Tally
int64 nAmount = 0;
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
- continue;
+ const CWalletTx& wtx = (*it).second;
+ if (wtx.IsCoinBase() || !wtx.IsFinal())
+ continue;
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- if (txout.scriptPubKey == scriptPubKey)
- if (wtx.GetDepthInMainChain() >= nMinDepth)
- nAmount += txout.nValue;
- }
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+ if (txout.scriptPubKey == scriptPubKey)
+ if (wtx.GetDepthInMainChain() >= nMinDepth)
+ nAmount += txout.nValue;
}
return ValueFromAmount(nAmount);
@@ -607,15 +579,12 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
{
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
- {
- const CBitcoinAddress& address = item.first;
- const string& strName = item.second;
- if (strName == strAccount)
- setAddress.insert(address);
- }
+ const CBitcoinAddress& address = item.first;
+ const string& strName = item.second;
+ if (strName == strAccount)
+ setAddress.insert(address);
}
}
@@ -639,21 +608,18 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
// Tally
int64 nAmount = 0;
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
- continue;
+ const CWalletTx& wtx = (*it).second;
+ if (wtx.IsCoinBase() || !wtx.IsFinal())
+ continue;
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- {
- CBitcoinAddress address;
- if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
- if (wtx.GetDepthInMainChain() >= nMinDepth)
- nAmount += txout.nValue;
- }
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+ {
+ CBitcoinAddress address;
+ if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
+ if (wtx.GetDepthInMainChain() >= nMinDepth)
+ nAmount += txout.nValue;
}
}
@@ -664,27 +630,25 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
{
int64 nBalance = 0;
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- {
- // Tally wallet transactions
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (!wtx.IsFinal())
- continue;
- int64 nGenerated, nReceived, nSent, nFee;
- wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
+ // Tally wallet transactions
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+ {
+ const CWalletTx& wtx = (*it).second;
+ if (!wtx.IsFinal())
+ continue;
- if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
- nBalance += nReceived;
- nBalance += nGenerated - nSent - nFee;
- }
+ int64 nGenerated, nReceived, nSent, nFee;
+ wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
- // Tally internal accounting entries
- nBalance += walletdb.GetAccountCreditDebit(strAccount);
+ if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+ nBalance += nReceived;
+ nBalance += nGenerated - nSent - nFee;
}
+ // Tally internal accounting entries
+ nBalance += walletdb.GetAccountCreditDebit(strAccount);
+
return nBalance;
}
@@ -763,33 +727,31 @@ Value movecmd(const Array& params, bool fHelp)
if (params.size() > 4)
strComment = params[4].get_str();
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- {
- CWalletDB walletdb(pwalletMain->strWalletFile);
- walletdb.TxnBegin();
-
- int64 nNow = GetAdjustedTime();
-
- // Debit
- CAccountingEntry debit;
- debit.strAccount = strFrom;
- debit.nCreditDebit = -nAmount;
- debit.nTime = nNow;
- debit.strOtherAccount = strTo;
- debit.strComment = strComment;
- walletdb.WriteAccountingEntry(debit);
-
- // Credit
- CAccountingEntry credit;
- credit.strAccount = strTo;
- credit.nCreditDebit = nAmount;
- credit.nTime = nNow;
- credit.strOtherAccount = strFrom;
- credit.strComment = strComment;
- walletdb.WriteAccountingEntry(credit);
-
- walletdb.TxnCommit();
- }
+ CWalletDB walletdb(pwalletMain->strWalletFile);
+ walletdb.TxnBegin();
+
+ int64 nNow = GetAdjustedTime();
+
+ // Debit
+ CAccountingEntry debit;
+ debit.strAccount = strFrom;
+ debit.nCreditDebit = -nAmount;
+ debit.nTime = nNow;
+ debit.strOtherAccount = strTo;
+ debit.strComment = strComment;
+ walletdb.WriteAccountingEntry(debit);
+
+ // Credit
+ CAccountingEntry credit;
+ credit.strAccount = strTo;
+ credit.nCreditDebit = nAmount;
+ credit.nTime = nNow;
+ credit.strOtherAccount = strFrom;
+ credit.strComment = strComment;
+ walletdb.WriteAccountingEntry(credit);
+
+ walletdb.TxnCommit();
+
return true;
}
@@ -822,23 +784,18 @@ Value sendfrom(const Array& params, bool fHelp)
if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
wtx.mapValue["to"] = params[5].get_str();
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
- {
- if(pwalletMain->IsLocked())
- throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
-
- // Check funds
- int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
- if (nAmount > nBalance)
- throw JSONRPCError(-6, "Account has insufficient funds");
-
- // Send
- string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
- if (strError != "")
- throw JSONRPCError(-4, strError);
- }
+ if (pwalletMain->IsLocked())
+ throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+
+ // Check funds
+ int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
+ if (nAmount > nBalance)
+ throw JSONRPCError(-6, "Account has insufficient funds");
+
+ // Send
+ string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
+ if (strError != "")
+ throw JSONRPCError(-4, strError);
return wtx.GetHash().GetHex();
}
@@ -889,31 +846,26 @@ Value sendmany(const Array& params, bool fHelp)
vecSend.push_back(make_pair(scriptPubKey, nAmount));
}
- CRITICAL_BLOCK(cs_main)
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
+ if (pwalletMain->IsLocked())
+ throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+
+ // Check funds
+ int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
+ if (totalAmount > nBalance)
+ throw JSONRPCError(-6, "Account has insufficient funds");
+
+ // Send
+ CReserveKey keyChange(pwalletMain);
+ int64 nFeeRequired = 0;
+ bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
+ if (!fCreated)
{
- if(pwalletMain->IsLocked())
- throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
-
- // Check funds
- int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
- if (totalAmount > nBalance)
- throw JSONRPCError(-6, "Account has insufficient funds");
-
- // Send
- CReserveKey keyChange(pwalletMain);
- int64 nFeeRequired = 0;
- bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
- if (!fCreated)
- {
- if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
- throw JSONRPCError(-6, "Insufficient funds");
- throw JSONRPCError(-4, "Transaction creation failed");
- }
- if (!pwalletMain->CommitTransaction(wtx, keyChange))
- throw JSONRPCError(-4, "Transaction commit failed");
+ if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
+ throw JSONRPCError(-6, "Insufficient funds");
+ throw JSONRPCError(-4, "Transaction creation failed");
}
+ if (!pwalletMain->CommitTransaction(wtx, keyChange))
+ throw JSONRPCError(-4, "Transaction commit failed");
return wtx.GetHash().GetHex();
}
@@ -944,68 +896,62 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Tally
map<CBitcoinAddress, tallyitem> mapTally;
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- const CWalletTx& wtx = (*it).second;
- if (wtx.IsCoinBase() || !wtx.IsFinal())
- continue;
+ const CWalletTx& wtx = (*it).second;
+ if (wtx.IsCoinBase() || !wtx.IsFinal())
+ continue;
- int nDepth = wtx.GetDepthInMainChain();
- if (nDepth < nMinDepth)
- continue;
+ int nDepth = wtx.GetDepthInMainChain();
+ if (nDepth < nMinDepth)
+ continue;
- BOOST_FOREACH(const CTxOut& txout, wtx.vout)
- {
- CBitcoinAddress address;
- if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
- continue;
+ BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+ {
+ CBitcoinAddress address;
+ if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
+ continue;
- tallyitem& item = mapTally[address];
- item.nAmount += txout.nValue;
- item.nConf = min(item.nConf, nDepth);
- }
+ tallyitem& item = mapTally[address];
+ item.nAmount += txout.nValue;
+ item.nConf = min(item.nConf, nDepth);
}
}
// Reply
Array ret;
map<string, tallyitem> mapAccountTally;
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
{
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
- {
- const CBitcoinAddress& address = item.first;
- const string& strAccount = item.second;
- map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
- if (it == mapTally.end() && !fIncludeEmpty)
- continue;
+ const CBitcoinAddress& address = item.first;
+ const string& strAccount = item.second;
+ map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
+ if (it == mapTally.end() && !fIncludeEmpty)
+ continue;
- int64 nAmount = 0;
- int nConf = INT_MAX;
- if (it != mapTally.end())
- {
- nAmount = (*it).second.nAmount;
- nConf = (*it).second.nConf;
- }
+ int64 nAmount = 0;
+ int nConf = INT_MAX;
+ if (it != mapTally.end())
+ {
+ nAmount = (*it).second.nAmount;
+ nConf = (*it).second.nConf;
+ }
- if (fByAccounts)
- {
- tallyitem& item = mapAccountTally[strAccount];
- item.nAmount += nAmount;
- item.nConf = min(item.nConf, nConf);
- }
- else
- {
- Object obj;
- obj.push_back(Pair("address", address.ToString()));
- obj.push_back(Pair("account", strAccount));
- obj.push_back(Pair("label", strAccount)); // deprecated
- obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
- obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
- ret.push_back(obj);
- }
+ if (fByAccounts)
+ {
+ tallyitem& item = mapAccountTally[strAccount];
+ item.nAmount += nAmount;
+ item.nConf = min(item.nConf, nConf);
+ }
+ else
+ {
+ Object obj;
+ obj.push_back(Pair("address", address.ToString()));
+ obj.push_back(Pair("account", strAccount));
+ obj.push_back(Pair("label", strAccount)); // deprecated
+ obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
+ obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
+ ret.push_back(obj);
}
}
@@ -1107,27 +1053,23 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
{
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
+ string account;
+ if (pwalletMain->mapAddressBook.count(r.first))
+ account = pwalletMain->mapAddressBook[r.first];
+ if (fAllAccounts || (account == strAccount))
{
- string account;
- if (pwalletMain->mapAddressBook.count(r.first))
- account = pwalletMain->mapAddressBook[r.first];
- if (fAllAccounts || (account == strAccount))
- {
- Object entry;
- entry.push_back(Pair("account", account));
- entry.push_back(Pair("address", r.first.ToString()));
- entry.push_back(Pair("category", "receive"));
- entry.push_back(Pair("amount", ValueFromAmount(r.second)));
- if (fLong)
- WalletTxToJSON(wtx, entry);
- ret.push_back(entry);
- }
+ Object entry;
+ entry.push_back(Pair("account", account));
+ entry.push_back(Pair("address", r.first.ToString()));
+ entry.push_back(Pair("category", "receive"));
+ entry.push_back(Pair("amount", ValueFromAmount(r.second)));
+ if (fLong)
+ WalletTxToJSON(wtx, entry);
+ ret.push_back(entry);
}
}
-
}
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
@@ -1167,41 +1109,38 @@ Value listtransactions(const Array& params, bool fHelp)
Array ret;
CWalletDB walletdb(pwalletMain->strWalletFile);
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- {
- // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
- typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
- typedef multimap<int64, TxPair > TxItems;
- TxItems txByTime;
+ // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
+ typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
+ typedef multimap<int64, TxPair > TxItems;
+ TxItems txByTime;
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
- {
- CWalletTx* wtx = &((*it).second);
- txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
- }
- list<CAccountingEntry> acentries;
- walletdb.ListAccountCreditDebit(strAccount, acentries);
- BOOST_FOREACH(CAccountingEntry& entry, acentries)
- {
- txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
- }
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+ {
+ CWalletTx* wtx = &((*it).second);
+ txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
+ }
+ list<CAccountingEntry> acentries;
+ walletdb.ListAccountCreditDebit(strAccount, acentries);
+ BOOST_FOREACH(CAccountingEntry& entry, acentries)
+ {
+ txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
+ }
- // Now: iterate backwards until we have nCount items to return:
- TxItems::reverse_iterator it = txByTime.rbegin();
- if (txByTime.size() > nFrom) std::advance(it, nFrom);
- for (; it != txByTime.rend(); ++it)
- {
- CWalletTx *const pwtx = (*it).second.first;
- if (pwtx != 0)
- ListTransactions(*pwtx, strAccount, 0, true, ret);
- CAccountingEntry *const pacentry = (*it).second.second;
- if (pacentry != 0)
- AcentryToJSON(*pacentry, strAccount, ret);
-
- if (ret.size() >= nCount) break;
- }
- // ret is now newest to oldest
+ // Now: iterate backwards until we have nCount items to return:
+ TxItems::reverse_iterator it = txByTime.rbegin();
+ if (txByTime.size() > nFrom) std::advance(it, nFrom);
+ for (; it != txByTime.rend(); ++it)
+ {
+ CWalletTx *const pwtx = (*it).second.first;
+ if (pwtx != 0)
+ ListTransactions(*pwtx, strAccount, 0, true, ret);
+ CAccountingEntry *const pacentry = (*it).second.second;
+ if (pacentry != 0)
+ AcentryToJSON(*pacentry, strAccount, ret);
+
+ if (ret.size() >= nCount) break;
}
+ // ret is now newest to oldest
// Make sure we return only last nCount items (sends-to-self might give us an extra):
if (ret.size() > nCount)
@@ -1227,34 +1166,30 @@ Value listaccounts(const Array& params, bool fHelp)
nMinDepth = params[0].get_int();
map<string, int64> mapAccountBalances;
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
- {
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
- if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
- mapAccountBalances[entry.second] = 0;
- }
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
+ if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
+ mapAccountBalances[entry.second] = 0;
+ }
- for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+ for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+ {
+ const CWalletTx& wtx = (*it).second;
+ int64 nGeneratedImmature, nGeneratedMature, nFee;
+ string strSentAccount;
+ list<pair<CBitcoinAddress, int64> > listReceived;
+ list<pair<CBitcoinAddress, int64> > listSent;
+ wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
+ mapAccountBalances[strSentAccount] -= nFee;
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
+ mapAccountBalances[strSentAccount] -= s.second;
+ if (wtx.GetDepthInMainChain() >= nMinDepth)
{
- const CWalletTx& wtx = (*it).second;
- int64 nGeneratedImmature, nGeneratedMature, nFee;
- string strSentAccount;
- list<pair<CBitcoinAddress, int64> > listReceived;
- list<pair<CBitcoinAddress, int64> > listSent;
- wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
- mapAccountBalances[strSentAccount] -= nFee;
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
- mapAccountBalances[strSentAccount] -= s.second;
- if (wtx.GetDepthInMainChain() >= nMinDepth)
- {
- mapAccountBalances[""] += nGeneratedMature;
- BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
- if (pwalletMain->mapAddressBook.count(r.first))
- mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
- else
- mapAccountBalances[""] += r.second;
- }
+ mapAccountBalances[""] += nGeneratedMature;
+ BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
+ if (pwalletMain->mapAddressBook.count(r.first))
+ mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
+ else
+ mapAccountBalances[""] += r.second;
}
}
@@ -1281,27 +1216,25 @@ Value gettransaction(const Array& params, bool fHelp)
hash.SetHex(params[0].get_str());
Object entry;
- CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
- {
- if (!pwalletMain->mapWallet.count(hash))
- throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
- const CWalletTx& wtx = pwalletMain->mapWallet[hash];
- int64 nCredit = wtx.GetCredit();
- int64 nDebit = wtx.GetDebit();
- int64 nNet = nCredit - nDebit;
- int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
+ if (!pwalletMain->mapWallet.count(hash))
+ throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
+ const CWalletTx& wtx = pwalletMain->mapWallet[hash];
- entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
- if (wtx.IsFromMe())
- entry.push_back(Pair("fee", ValueFromAmount(nFee)));
+ int64 nCredit = wtx.GetCredit();
+ int64 nDebit = wtx.GetDebit();
+ int64 nNet = nCredit - nDebit;
+ int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
- WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
+ entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
+ if (wtx.IsFromMe())
+ entry.push_back(Pair("fee", ValueFromAmount(nFee)));
- Array details;
- ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
- entry.push_back(Pair("details", details));
- }
+ WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
+
+ Array details;
+ ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
+ entry.push_back(Pair("details", details));
return entry;
}
@@ -1332,13 +1265,10 @@ Value keypoolrefill(const Array& params, bool fHelp)
"keypoolrefill\n"
"Fills the keypool.");
- CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
- {
- if (pwalletMain->IsLocked())
- throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+ if (pwalletMain->IsLocked())
+ throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
- pwalletMain->TopUpKeyPool();
- }
+ pwalletMain->TopUpKeyPool();
if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
throw JSONRPCError(-4, "Error refreshing keypool.");
@@ -1407,24 +1337,21 @@ Value walletpassphrase(const Array& params, bool fHelp)
mlock(&strWalletPass[0], strWalletPass.capacity());
strWalletPass = params[0].get_str();
- CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
+ if (strWalletPass.length() > 0)
{
- if (strWalletPass.length() > 0)
+ if (!pwalletMain->Unlock(strWalletPass))
{
- if (!pwalletMain->Unlock(strWalletPass))
- {
- fill(strWalletPass.begin(), strWalletPass.end(), '\0');
- munlock(&strWalletPass[0], strWalletPass.capacity());
- throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
- }
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
munlock(&strWalletPass[0], strWalletPass.capacity());
+ throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
}
- else
- throw runtime_error(
- "walletpassphrase <passphrase> <timeout>\n"
- "Stores the wallet decryption key in memory for <timeout> seconds.");
+ fill(strWalletPass.begin(), strWalletPass.end(), '\0');
+ munlock(&strWalletPass[0], strWalletPass.capacity());
}
+ else
+ throw runtime_error(
+ "walletpassphrase <passphrase> <timeout>\n"
+ "Stores the wallet decryption key in memory for <timeout> seconds.");
CreateThread(ThreadTopUpKeyPool, NULL);
int* pnSleepTime = new int(params[1].get_int());
@@ -1553,11 +1480,8 @@ Value validateaddress(const Array& params, bool fHelp)
string currentAddress = address.ToString();
ret.push_back(Pair("address", currentAddress));
ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
- CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
- {
- if (pwalletMain->mapAddressBook.count(address))
- ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
- }
+ if (pwalletMain->mapAddressBook.count(address))
+ ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
}
return ret;
}
@@ -2233,7 +2157,10 @@ void ThreadRPCServer2(void* parg)
try
{
// Execute
- Value result = (*(*mi).second)(params, false);
+ Value result;
+ CRITICAL_BLOCK(cs_main)
+ CRITICAL_BLOCK(pwalletMain->cs_wallet)
+ result = (*(*mi).second)(params, false);
// Send reply
string strReply = JSONRPCReply(result, Value::null, id);