@ -331,71 +331,59 @@ Value getnewaddress(const Array& params, bool fHelp)
" If [account] is specified (recommended), it is added to the address book "
" If [account] is specified (recommended), it is added to the address book "
" so payments received with the address will be credited to [account]. " ) ;
" so payments received with the address will be credited to [account]. " ) ;
if ( ! pwalletMain - > IsLocked ( ) )
pwalletMain - > TopUpKeyPool ( ) ;
if ( pwalletMain - > GetKeyPoolSize ( ) < 1 )
throw JSONRPCError ( - 12 , " Error: Keypool ran out, please call keypoolrefill first " ) ;
// 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 ;
string strAccount ;
if ( params . size ( ) > 0 )
if ( params . size ( ) > 0 )
strAccount = AccountFromValue ( params [ 0 ] ) ;
strAccount = AccountFromValue ( params [ 0 ] ) ;
if ( ! pwalletMain - > IsLocked ( ) )
pwalletMain - > TopUpKeyPool ( ) ;
// Generate a new key that is added to wallet
// Generate a new key that is added to wallet
CBitcoinAddress address ( pwalletMain - > GetOrReuseKeyFromPool ( ) ) ;
std : : vector < unsigned char > newKey ;
if ( ! pwalletMain - > GetKeyFromPool ( newKey , false ) )
throw JSONRPCError ( - 12 , " Error: Keypool ran out, please call keypoolrefill first " ) ;
CBitcoinAddress address ( newKey ) ;
// This could be done in the same main CS as GetKeyFromKeyPool.
pwalletMain - > SetAddressBookName ( address , strAccount ) ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapAddressBook )
pwalletMain - > SetAddressBookName ( address , strAccount ) ;
return address . ToString ( ) ;
return address . ToString ( ) ;
}
}
// requires cs_main, cs_mapWallet, cs_mapAddressBook locks
CBitcoinAddress GetAccountAddress ( string strAccount , bool bForceNew = false )
CBitcoinAddress GetAccountAddress ( string strAccount , bool bForceNew = false )
{
{
CWalletDB walletdb ( pwalletMain - > strWalletFile ) ;
CWalletDB walletdb ( pwalletMain - > strWalletFile ) ;
CAccount account ;
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
// Check if the current key has been used
if ( ! account . vchPubKey . empty ( ) )
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 ;
const CWalletTx & wtx = ( * it ) . second ;
scriptPubKey . SetBitcoinAddress ( account . vchPubKey ) ;
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ;
if ( txout . scriptPubKey = = scriptPubKey )
it ! = pwalletMain - > mapWallet . end ( ) & & ! account . vchPubKey . empty ( ) ;
bKeyUsed = true ;
+ + it )
{
const CWalletTx & wtx = ( * it ) . second ;
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
if ( txout . scriptPubKey = = scriptPubKey )
bKeyUsed = true ;
}
}
}
}
// Generate a new key
// Generate a new key
if ( account . vchPubKey . empty ( ) | | bForceNew | | bKeyUsed )
if ( account . vchPubKey . empty ( ) | | bForceNew | | bKeyUsed )
{
{
if ( pwalletMain - > GetKeyPoolSize ( ) < 1 )
if ( ! pwalletMain - > GetKeyFromPool ( account . vchPubKey , false ) )
{
throw JSONRPCError ( - 12 , " Error: Keypool ran out, please call keypoolrefill first " ) ;
if ( bKeyUsed | | bForceNew )
throw JSONRPCError ( - 12 , " Error: Keypool ran out, please call topupkeypool first " ) ;
pwalletMain - > SetAddressBookName ( CBitcoinAddress ( account . vchPubKey ) , strAccount ) ;
}
walletdb . WriteAccount ( strAccount , account ) ;
else
{
account . vchPubKey = pwalletMain - > GetOrReuseKeyFromPool ( ) ;
pwalletMain - > SetAddressBookName ( CBitcoinAddress ( account . vchPubKey ) , strAccount ) ;
walletdb . WriteAccount ( strAccount , account ) ;
}
}
}
}
return CBitcoinAddress ( account . vchPubKey ) ;
return CBitcoinAddress ( account . vchPubKey ) ;
@ -413,12 +401,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
Value ret ;
Value ret ;
CRITICAL_BLOCK ( cs_main )
ret = GetAccountAddress ( strAccount ) . ToString ( ) ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapWallet )
CRITICAL_BLOCK ( pwalletMain - > cs_mapAddressBook )
{
ret = GetAccountAddress ( strAccount ) . ToString ( ) ;
}
return ret ;
return ret ;
}
}
@ -442,20 +425,15 @@ 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 )
if ( pwalletMain - > mapAddressBook . count ( address ) )
CRITICAL_BLOCK ( pwalletMain - > cs_mapWallet )
CRITICAL_BLOCK ( pwalletMain - > cs_mapAddressBook )
{
{
if ( pwalletMain - > mapAddressBook . count ( address ) )
string strOldAccount = pwalletMain - > mapAddressBook [ address ] ;
{
if ( address = = GetAccountAddress ( strOldAccount ) )
string strOldAccount = pwalletMain - > mapAddressBook [ address ] ;
GetAccountAddress ( strOldAccount , true ) ;
if ( address = = GetAccountAddress ( strOldAccount ) )
GetAccountAddress ( strOldAccount , true ) ;
}
pwalletMain - > SetAddressBookName ( address , strAccount ) ;
}
}
pwalletMain - > SetAddressBookName ( address , strAccount ) ;
return Value : : null ;
return Value : : null ;
}
}
@ -472,12 +450,9 @@ Value getaccount(const Array& params, bool fHelp)
throw JSONRPCError ( - 5 , " Invalid bitcoin address " ) ;
throw JSONRPCError ( - 5 , " Invalid bitcoin address " ) ;
string strAccount ;
string strAccount ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapAddressBook )
map < CBitcoinAddress , string > : : iterator mi = pwalletMain - > mapAddressBook . find ( address ) ;
{
if ( mi ! = pwalletMain - > mapAddressBook . end ( ) & & ! ( * mi ) . second . empty ( ) )
map < CBitcoinAddress , string > : : iterator mi = pwalletMain - > mapAddressBook . find ( address ) ;
strAccount = ( * mi ) . second ;
if ( mi ! = pwalletMain - > mapAddressBook . end ( ) & & ! ( * mi ) . second . empty ( ) )
strAccount = ( * mi ) . second ;
}
return strAccount ;
return strAccount ;
}
}
@ -493,15 +468,12 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
// Find all addresses that have the given account
// Find all addresses that have the given account
Array ret ;
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 ;
const CBitcoinAddress & address = item . first ;
if ( strName = = strAccount )
const string & strName = item . second ;
ret . push_back ( address . ToString ( ) ) ;
if ( strName = = strAccount )
ret . push_back ( address . ToString ( ) ) ;
}
}
}
return ret ;
return ret ;
}
}
@ -548,16 +520,12 @@ 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 ( ) ;
CRITICAL_BLOCK ( cs_main )
if ( pwalletMain - > IsLocked ( ) )
CRITICAL_BLOCK ( pwalletMain - > cs_vMasterKey )
throw JSONRPCError ( - 13 , " Error: Please enter the wallet passphrase with walletpassphrase first. " ) ;
{
if ( pwalletMain - > IsLocked ( ) )
throw JSONRPCError ( - 14 , " Error: The wallet passphrase entered was incorrect. " ) ;
string strError = pwalletMain - > SendMoneyToBitcoinAddress ( address , nAmount , wtx ) ;
string strError = pwalletMain - > SendMoneyToBitcoinAddress ( address , nAmount , wtx ) ;
if ( strError ! = " " )
if ( strError ! = " " )
throw JSONRPCError ( - 4 , strError ) ;
throw JSONRPCError ( - 4 , strError ) ;
}
return wtx . GetHash ( ) . GetHex ( ) ;
return wtx . GetHash ( ) . GetHex ( ) ;
}
}
@ -586,19 +554,16 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
// Tally
// Tally
int64 nAmount = 0 ;
int64 nAmount = 0 ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapWalle t)
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ; it ! = pwalletMain - > mapWallet . end ( ) ; + + i t)
{
{
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ; it ! = pwalletMain - > mapWallet . end ( ) ; + + it )
const CWalletTx & wtx = ( * it ) . second ;
{
if ( wtx . IsCoinBase ( ) | | ! wtx . IsFinal ( ) )
const CWalletTx & wtx = ( * it ) . second ;
continue ;
if ( wtx . IsCoinBase ( ) | | ! wtx . IsFinal ( ) )
continue ;
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
if ( txout . scriptPubKey = = scriptPubKey )
if ( txout . scriptPubKey = = scriptPubKey )
if ( wtx . GetDepthInMainChain ( ) > = nMinDepth )
if ( wtx . GetDepthInMainChain ( ) > = nMinDepth )
nAmount + = txout . nValue ;
nAmount + = txout . nValue ;
}
}
}
return ValueFromAmount ( nAmount ) ;
return ValueFromAmount ( nAmount ) ;
@ -607,15 +572,12 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
void GetAccountAddresses ( string strAccount , set < CBitcoinAddress > & setAddress )
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 ;
const CBitcoinAddress & address = item . first ;
if ( strName = = strAccount )
const string & strName = item . second ;
setAddress . insert ( address ) ;
if ( strName = = strAccount )
setAddress . insert ( address ) ;
}
}
}
}
}
@ -639,21 +601,18 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
// Tally
// Tally
int64 nAmount = 0 ;
int64 nAmount = 0 ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapWalle t)
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ; it ! = pwalletMain - > mapWallet . end ( ) ; + + i t)
{
{
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ; it ! = pwalletMain - > mapWallet . end ( ) ; + + it )
const CWalletTx & wtx = ( * it ) . second ;
{
if ( wtx . IsCoinBase ( ) | | ! wtx . IsFinal ( ) )
const CWalletTx & wtx = ( * it ) . second ;
continue ;
if ( wtx . IsCoinBase ( ) | | ! wtx . IsFinal ( ) )
continue ;
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
{
{
CBitcoinAddress address ;
CBitcoinAddress address ;
if ( ExtractAddress ( txout . scriptPubKey , pwalletMain , address ) & & setAddress . count ( address ) )
if ( ExtractAddress ( txout . scriptPubKey , pwalletMain , address ) & & setAddress . count ( address ) )
if ( wtx . GetDepthInMainChain ( ) > = nMinDepth )
if ( wtx . GetDepthInMainChain ( ) > = nMinDepth )
nAmount + = txout . nValue ;
nAmount + = txout . nValue ;
}
}
}
}
}
@ -664,27 +623,25 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
int64 GetAccountBalance ( CWalletDB & walletdb , const string & strAccount , int nMinDepth )
int64 GetAccountBalance ( CWalletDB & walletdb , const string & strAccount , int nMinDepth )
{
{
int64 nBalance = 0 ;
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 ;
// Tally wallet transactions
wtx . GetAccountAmounts ( strAccount , nGenerated , nReceived , nSent , nFee ) ;
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 )
int64 nGenerated , nReceived , nSent , nFee ;
nBalance + = nReceived ;
wtx . GetAccountAmounts ( strAccount , nGenerated , nReceived , nSent , nFee ) ;
nBalance + = nGenerated - nSent - nFee ;
}
// Tally internal accounting entries
if ( nReceived ! = 0 & & wtx . GetDepthInMainChain ( ) > = nMinDepth )
nBalance + = walletdb . GetAccountCreditDebit ( strAccount ) ;
nBalance + = nReceived ;
nBalance + = nGenerated - nSent - nFee ;
}
}
// Tally internal accounting entries
nBalance + = walletdb . GetAccountCreditDebit ( strAccount ) ;
return nBalance ;
return nBalance ;
}
}
@ -763,33 +720,31 @@ Value movecmd(const Array& params, bool fHelp)
if ( params . size ( ) > 4 )
if ( params . size ( ) > 4 )
strComment = params [ 4 ] . get_str ( ) ;
strComment = params [ 4 ] . get_str ( ) ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapWallet )
CWalletDB walletdb ( pwalletMain - > strWalletFile ) ;
{
walletdb . TxnBegin ( ) ;
CWalletDB walletdb ( pwalletMain - > strWalletFile ) ;
walletdb . TxnBegin ( ) ;
int64 nNow = GetAdjustedTime ( ) ;
int64 nNow = GetAdjustedTime ( ) ;
// Debit
CAccountingEntry debit ;
// Debit
debit . strAccount = strFrom ;
CAccountingEntry debit ;
debit . nCreditDebit = - nAmount ;
debit . strAccount = strFrom ;
debit . nTime = nNow ;
debit . nCreditDebit = - nAmount ;
debit . strOtherAccount = strTo ;
debit . nTime = nNow ;
debit . strComment = strComment ;
debit . strOtherAccount = strTo ;
walletdb . WriteAccountingEntry ( debit ) ;
debit . strComment = strComment ;
walletdb . WriteAccountingEntry ( debit ) ;
// Credit
CAccountingEntry credit ;
// Credit
credit . strAccount = strTo ;
CAccountingEntry credit ;
credit . nCreditDebit = nAmount ;
credit . strAccount = strTo ;
credit . nTime = nNow ;
credit . nCreditDebit = nAmount ;
credit . strOtherAccount = strFrom ;
credit . nTime = nNow ;
credit . strComment = strComment ;
credit . strOtherAccount = strFrom ;
walletdb . WriteAccountingEntry ( credit ) ;
credit . strComment = strComment ;
walletdb . WriteAccountingEntry ( credit ) ;
walletdb . TxnCommit ( ) ;
walletdb . TxnCommit ( ) ;
}
return true ;
return true ;
}
}
@ -822,23 +777,18 @@ 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 )
if ( pwalletMain - > IsLocked ( ) )
CRITICAL_BLOCK ( pwalletMain - > cs_mapWallet )
throw JSONRPCError ( - 13 , " Error: Please enter the wallet passphrase with walletpassphrase first. " ) ;
CRITICAL_BLOCK ( pwalletMain - > cs_vMasterKey )
{
if ( pwalletMain - > IsLocked ( ) )
throw JSONRPCError ( - 14 , " Error: The wallet passphrase entered was incorrect. " ) ;
// Check funds
// Check funds
int64 nBalance = GetAccountBalance ( strAccount , nMinDepth ) ;
int64 nBalance = GetAccountBalance ( strAccount , nMinDepth ) ;
if ( nAmount > nBalance )
if ( nAmount > nBalance )
throw JSONRPCError ( - 6 , " Account has insufficient funds " ) ;
throw JSONRPCError ( - 6 , " Account has insufficient funds " ) ;
// Send
// Send
string strError = pwalletMain - > SendMoneyToBitcoinAddress ( address , nAmount , wtx ) ;
string strError = pwalletMain - > SendMoneyToBitcoinAddress ( address , nAmount , wtx ) ;
if ( strError ! = " " )
if ( strError ! = " " )
throw JSONRPCError ( - 4 , strError ) ;
throw JSONRPCError ( - 4 , strError ) ;
}
return wtx . GetHash ( ) . GetHex ( ) ;
return wtx . GetHash ( ) . GetHex ( ) ;
}
}
@ -889,31 +839,26 @@ 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 )
if ( pwalletMain - > IsLocked ( ) )
CRITICAL_BLOCK ( pwalletMain - > cs_mapWallet )
throw JSONRPCError ( - 13 , " Error: Please enter the wallet passphrase with walletpassphrase first. " ) ;
CRITICAL_BLOCK ( pwalletMain - > cs_vMasterKey )
{
if ( pwalletMain - > IsLocked ( ) )
throw JSONRPCError ( - 14 , " Error: The wallet passphrase entered was incorrect. " ) ;
// Check funds
int64 nBalance = GetAccountBalance ( strAccount , nMinDepth ) ;
if ( totalAmount > nBalance )
throw JSONRPCError ( - 6 , " Account has insufficient funds " ) ;
// Send
// Check funds
CReserveKey keyChange ( pwalletMain ) ;
int64 nBalance = GetAccountBalance ( strAccount , nMinDepth ) ;
int64 nFeeRequired = 0 ;
if ( totalAmount > nBalance )
bool fCreated = pwalletMain - > CreateTransaction ( vecSend , wtx , keyChange , nFeeRequired ) ;
throw JSONRPCError ( - 6 , " Account has insufficient funds " ) ;
if ( ! fCreated )
{
// Send
if ( totalAmount + nFeeRequired > pwalletMain - > GetBalance ( ) )
CReserveKey keyChange ( pwalletMain ) ;
throw JSONRPCError ( - 6 , " Insufficient funds " ) ;
int64 nFeeRequired = 0 ;
throw JSONRPCError ( - 4 , " Transaction creation failed " ) ;
bool fCreated = pwalletMain - > CreateTransaction ( vecSend , wtx , keyChange , nFeeRequired ) ;
}
if ( ! fCreated )
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 ( ) ;
return wtx . GetHash ( ) . GetHex ( ) ;
}
}
@ -944,68 +889,62 @@ Value ListReceived(const Array& params, bool fByAccounts)
// Tally
// Tally
map < CBitcoinAddress , tallyitem > mapTally ;
map < CBitcoinAddress , tallyitem > mapTally ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapWalle t)
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ; it ! = pwalletMain - > mapWallet . end ( ) ; + + i t)
{
{
for ( map < uint256 , CWalletTx > : : iterator it = pwalletMain - > mapWallet . begin ( ) ; it ! = pwalletMain - > mapWallet . end ( ) ; + + it )
const CWalletTx & wtx = ( * it ) . second ;
{
if ( wtx . IsCoinBase ( ) | | ! wtx . IsFinal ( ) )
const CWalletTx & wtx = ( * it ) . second ;
continue ;
if ( wtx . IsCoinBase ( ) | | ! wtx . IsFinal ( ) )
continue ;
int nDepth = wtx . GetDepthInMainChain ( ) ;
int nDepth = wtx . GetDepthInMainChain ( ) ;
if ( nDepth < nMinDepth )
if ( nDepth < nMinDepth )
continue ;
continue ;
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
BOOST_FOREACH ( const CTxOut & txout , wtx . vout )
{
{
CBitcoinAddress address ;
CBitcoinAddress address ;
if ( ! ExtractAddress ( txout . scriptPubKey , pwalletMain , address ) | | ! address . IsValid ( ) )
if ( ! ExtractAddress ( txout . scriptPubKey , pwalletMain , address ) | | ! address . IsValid ( ) )
continue ;
continue ;
tallyitem & item = mapTally [ address ] ;
tallyitem & item = mapTally [ address ] ;
item . nAmount + = txout . nValue ;
item . nAmount + = txout . nValue ;
item . nConf = min ( item . nConf , nDepth ) ;
item . nConf = min ( item . nConf , nDepth ) ;
}
}
}
}
}
// Reply
// Reply
Array ret ;
Array ret ;
map < string , tallyitem > mapAccountTally ;
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 ;
const CBitcoinAddress & address = item . first ;
map < CBitcoinAddress , tallyitem > : : iterator it = mapTally . find ( address ) ;
const string & strAccount = item . second ;
if ( it = = mapTally . end ( ) & & ! fIncludeEmpty )
map < CBitcoinAddress , tallyitem > : : iterator it = mapTally . find ( address ) ;
continue ;
if ( it = = mapTally . end ( ) & & ! fIncludeEmpty )
continue ;
int64 nAmount = 0 ;
int64 nAmount = 0 ;
int nConf = INT_MAX ;
int nConf = INT_MAX ;
if ( it ! = mapTally . end ( ) )
if ( it ! = mapTally . end ( ) )
{
{
nAmount = ( * it ) . second . nAmount ;
nAmount = ( * it ) . second . nAmount ;
nConf = ( * it ) . second . nConf ;
nConf = ( * it ) . second . nConf ;
}
}
if ( fByAccounts )
if ( fByAccounts )
{
{
tallyitem & item = mapAccountTally [ strAccount ] ;
tallyitem & item = mapAccountTally [ strAccount ] ;
item . nAmount + = nAmount ;
item . nAmount + = nAmount ;
item . nConf = min ( item . nConf , nConf ) ;
item . nConf = min ( item . nConf , nConf ) ;
}
}
else
else
{
{
Object obj ;
Object obj ;
obj . push_back ( Pair ( " address " , address . ToString ( ) ) ) ;
obj . push_back ( Pair ( " address " , address . ToString ( ) ) ) ;
obj . push_back ( Pair ( " account " , strAccount ) ) ;
obj . push_back ( Pair ( " account " , strAccount ) ) ;
obj . push_back ( Pair ( " label " , strAccount ) ) ; // deprecated
obj . push_back ( Pair ( " label " , strAccount ) ) ; // deprecated
obj . push_back ( Pair ( " amount " , ValueFromAmount ( nAmount ) ) ) ;
obj . push_back ( Pair ( " amount " , ValueFromAmount ( nAmount ) ) ) ;
obj . push_back ( Pair ( " confirmations " , ( nConf = = INT_MAX ? 0 : nConf ) ) ) ;
obj . push_back ( Pair ( " confirmations " , ( nConf = = INT_MAX ? 0 : nConf ) ) ) ;
ret . push_back ( obj ) ;
ret . push_back ( obj ) ;
}
}
}
}
}
@ -1107,27 +1046,23 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
// Received
// Received
if ( listReceived . size ( ) > 0 & & wtx . GetDepthInMainChain ( ) > = nMinDepth )
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 ;
Object entry ;
if ( pwalletMain - > mapAddressBook . count ( r . first ) )
entry . push_back ( Pair ( " account " , account ) ) ;
account = pwalletMain - > mapAddressBook [ r . first ] ;
entry . push_back ( Pair ( " address " , r . first . ToString ( ) ) ) ;
if ( fAllAccounts | | ( account = = strAccount ) )
entry . push_back ( Pair ( " category " , " receive " ) ) ;
{
entry . push_back ( Pair ( " amount " , ValueFromAmount ( r . second ) ) ) ;
Object entry ;
if ( fLong )
entry . push_back ( Pair ( " account " , account ) ) ;
WalletTxToJSON ( wtx , entry ) ;
entry . push_back ( Pair ( " address " , r . first . ToString ( ) ) ) ;
ret . push_back ( entry ) ;
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 )
void AcentryToJSON ( const CAccountingEntry & acentry , const string & strAccount , Array & ret )
@ -1167,41 +1102,38 @@ Value listtransactions(const Array& params, bool fHelp)
Array ret ;
Array ret ;
CWalletDB walletdb ( pwalletMain - > strWalletFile ) ;
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 ;
// Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
typedef multimap < int64 , TxPair > TxItems ;
typedef pair < CWalletTx * , CAccountingEntry * > TxPair ;
TxItems txByTime ;
typedef multimap < int64 , TxPair > TxItems ;
TxItems txByTime ;
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 )
{
{
CWalletTx * wtx = & ( ( * it ) . second ) ;
CWalletTx * wtx = & ( ( * it ) . second ) ;
txByTime . insert ( make_pair ( wtx - > GetTxTime ( ) , TxPair ( wtx , ( CAccountingEntry * ) 0 ) ) ) ;
txByTime . insert ( make_pair ( wtx - > GetTxTime ( ) , TxPair ( wtx , ( CAccountingEntry * ) 0 ) ) ) ;
}
}
list < CAccountingEntry > acentries ;
list < CAccountingEntry > acentries ;
walletdb . ListAccountCreditDebit ( strAccount , acentries ) ;
walletdb . ListAccountCreditDebit ( strAccount , acentries ) ;
BOOST_FOREACH ( CAccountingEntry & entry , acentries )
BOOST_FOREACH ( CAccountingEntry & entry , acentries )
{
{
txByTime . insert ( make_pair ( entry . nTime , TxPair ( ( CWalletTx * ) 0 , & entry ) ) ) ;
txByTime . insert ( make_pair ( entry . nTime , TxPair ( ( CWalletTx * ) 0 , & entry ) ) ) ;
}
}
// Now: iterate backwards until we have nCount items to return:
// Now: iterate backwards until we have nCount items to return:
TxItems : : reverse_iterator it = txByTime . rbegin ( ) ;
TxItems : : reverse_iterator it = txByTime . rbegin ( ) ;
if ( txByTime . size ( ) > nFrom ) std : : advance ( it , nFrom ) ;
if ( txByTime . size ( ) > nFrom ) std : : advance ( it , nFrom ) ;
for ( ; it ! = txByTime . rend ( ) ; + + it )
for ( ; it ! = txByTime . rend ( ) ; + + it )
{
{
CWalletTx * const pwtx = ( * it ) . second . first ;
CWalletTx * const pwtx = ( * it ) . second . first ;
if ( pwtx ! = 0 )
if ( pwtx ! = 0 )
ListTransactions ( * pwtx , strAccount , 0 , true , ret ) ;
ListTransactions ( * pwtx , strAccount , 0 , true , ret ) ;
CAccountingEntry * const pacentry = ( * it ) . second . second ;
CAccountingEntry * const pacentry = ( * it ) . second . second ;
if ( pacentry ! = 0 )
if ( pacentry ! = 0 )
AcentryToJSON ( * pacentry , strAccount , ret ) ;
AcentryToJSON ( * pacentry , strAccount , ret ) ;
if ( ret . size ( ) > = nCount ) break ;
if ( ret . size ( ) > = nCount ) break ;
}
// ret is now newest to oldest
}
}
// ret is now newest to oldest
// Make sure we return only last nCount items (sends-to-self might give us an extra):
// Make sure we return only last nCount items (sends-to-self might give us an extra):
if ( ret . size ( ) > nCount )
if ( ret . size ( ) > nCount )
@ -1227,34 +1159,30 @@ Value listaccounts(const Array& params, bool fHelp)
nMinDepth = params [ 0 ] . get_int ( ) ;
nMinDepth = params [ 0 ] . get_int ( ) ;
map < string , int64 > mapAccountBalances ;
map < string , int64 > mapAccountBalances ;
CRITICAL_BLOCK ( pwalletMain - > cs_mapWallet )
BOOST_FOREACH ( const PAIRTYPE ( CBitcoinAddress , string ) & entry , pwalletMain - > mapAddressBook ) {
CRITICAL_BLOCK ( pwalletMain - > cs_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 ;
mapAccountBalances [ " " ] + = nGeneratedMature ;
int64 nGeneratedImmature , nGeneratedMature , nFee ;
BOOST_FOREACH ( const PAIRTYPE ( CBitcoinAddress , int64 ) & r , listReceived )
string strSentAccount ;
if ( pwalletMain - > mapAddressBook . count ( r . first ) )
list < pair < CBitcoinAddress , int64 > > listReceived ;
mapAccountBalances [ pwalletMain - > mapAddressBook [ r . first ] ] + = r . second ;
list < pair < CBitcoinAddress , int64 > > listSent ;
else
wtx . GetAmounts ( nGeneratedImmature , nGeneratedMature , listReceived , listSent , nFee , strSentAccount ) ;
mapAccountBalances [ " " ] + = r . second ;
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 ;
}
}
}
}
}
@ -1281,27 +1209,25 @@ Value gettransaction(const Array& params, bool fHelp)
hash . SetHex ( params [ 0 ] . get_str ( ) ) ;
hash . SetHex ( params [ 0 ] . get_str ( ) ) ;
Object entry ;
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 ( ) ;
if ( ! pwalletMain - > mapWallet . count ( hash ) )
int64 nDebit = wtx . GetDebit ( ) ;
throw JSONRPCError ( - 5 , " Invalid or non-wallet transaction id " ) ;
int64 nNet = nCredit - nDebit ;
const CWalletTx & wtx = pwalletMain - > mapWallet [ hash ] ;
int64 nFee = ( wtx . IsFromMe ( ) ? wtx . GetValueOut ( ) - nDebit : 0 ) ;
entry . push_back ( Pair ( " amount " , ValueFromAmount ( nNet - nFee ) ) ) ;
int64 nCredit = wtx . GetCredit ( ) ;
if ( wtx . IsFromMe ( ) )
int64 nDebit = wtx . GetDebit ( ) ;
entry . push_back ( Pair ( " fee " , ValueFromAmount ( nFee ) ) ) ;
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 ;
WalletTxToJSON ( pwalletMain - > mapWallet [ hash ] , entry ) ;
ListTransactions ( pwalletMain - > mapWallet [ hash ] , " * " , 0 , false , details ) ;
entry . push_back ( Pair ( " details " , details ) ) ;
Array details ;
}
ListTransactions ( pwalletMain - > mapWallet [ hash ] , " * " , 0 , false , details ) ;
entry . push_back ( Pair ( " details " , details ) ) ;
return entry ;
return entry ;
}
}
@ -1332,13 +1258,10 @@ Value keypoolrefill(const Array& params, bool fHelp)
" keypoolrefill \n "
" keypoolrefill \n "
" Fills the keypool. " ) ;
" 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 ) )
if ( pwalletMain - > GetKeyPoolSize ( ) < GetArg ( " -keypool " , 100 ) )
throw JSONRPCError ( - 4 , " Error refreshing keypool. " ) ;
throw JSONRPCError ( - 4 , " Error refreshing keypool. " ) ;
@ -1407,24 +1330,21 @@ Value walletpassphrase(const Array& params, bool fHelp)
mlock ( & strWalletPass [ 0 ] , strWalletPass . capacity ( ) ) ;
mlock ( & strWalletPass [ 0 ] , strWalletPass . capacity ( ) ) ;
strWalletPass = params [ 0 ] . get_str ( ) ;
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 ' ) ;
fill ( strWalletPass . begin ( ) , strWalletPass . end ( ) , ' \0 ' ) ;
munlock ( & strWalletPass [ 0 ] , strWalletPass . capacity ( ) ) ;
munlock ( & strWalletPass [ 0 ] , strWalletPass . capacity ( ) ) ;
throw JSONRPCError ( - 14 , " Error: The wallet passphrase entered was incorrect. " ) ;
}
}
else
fill ( strWalletPass . begin ( ) , strWalletPass . end ( ) , ' \0 ' ) ;
throw runtime_error (
munlock ( & strWalletPass [ 0 ] , strWalletPass . capacity ( ) ) ;
" walletpassphrase <passphrase> <timeout> \n "
" Stores the wallet decryption key in memory for <timeout> seconds. " ) ;
}
}
else
throw runtime_error (
" walletpassphrase <passphrase> <timeout> \n "
" Stores the wallet decryption key in memory for <timeout> seconds. " ) ;
CreateThread ( ThreadTopUpKeyPool , NULL ) ;
CreateThread ( ThreadTopUpKeyPool , NULL ) ;
int * pnSleepTime = new int ( params [ 1 ] . get_int ( ) ) ;
int * pnSleepTime = new int ( params [ 1 ] . get_int ( ) ) ;
@ -1553,11 +1473,8 @@ Value validateaddress(const Array& params, bool fHelp)
string currentAddress = address . ToString ( ) ;
string currentAddress = address . ToString ( ) ;
ret . push_back ( Pair ( " address " , currentAddress ) ) ;
ret . push_back ( Pair ( " address " , currentAddress ) ) ;
ret . push_back ( Pair ( " ismine " , ( pwalletMain - > HaveKey ( address ) > 0 ) ) ) ;
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 ;
return ret ;
}
}
@ -2233,7 +2150,10 @@ void ThreadRPCServer2(void* parg)
try
try
{
{
// Execute
// 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
// Send reply
string strReply = JSONRPCReply ( result , Value : : null , id ) ;
string strReply = JSONRPCReply ( result , Value : : null , id ) ;