@ -1426,6 +1426,17 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
entry . push_back ( Pair ( " address " , addr . ToString ( ) ) ) ;
entry . push_back ( Pair ( " address " , addr . ToString ( ) ) ) ;
}
}
/**
* List transactions based on the given criteria .
*
* @ param pwallet The wallet .
* @ param wtx The wallet transaction .
* @ param strAccount The account , if any , or " * " for all .
* @ param nMinDepth The minimum confirmation depth .
* @ param fLong Whether to include the JSON version of the transaction .
* @ param ret The UniValue into which the result is stored .
* @ param filter The " is mine " filter bool .
*/
void ListTransactions ( CWallet * const pwallet , const CWalletTx & wtx , const std : : string & strAccount , int nMinDepth , bool fLong , UniValue & ret , const isminefilter & filter )
void ListTransactions ( CWallet * const pwallet , const CWalletTx & wtx , const std : : string & strAccount , int nMinDepth , bool fLong , UniValue & ret , const isminefilter & filter )
{
{
CAmount nFee ;
CAmount nFee ;
@ -1742,14 +1753,18 @@ UniValue listsinceblock(const JSONRPCRequest& request)
return NullUniValue ;
return NullUniValue ;
}
}
if ( request . fHelp | | request . params . size ( ) > 3 )
if ( request . fHelp | | request . params . size ( ) > 4 )
throw std : : runtime_error (
throw std : : runtime_error (
" listsinceblock ( \" blockhash \" target_confirmations include_watchonly) \n "
" listsinceblock ( \" blockhash \" target_confirmations include_watchonly include_removed ) \n "
" \n Get all transactions in blocks since block [blockhash], or all transactions if omitted \n "
" \n Get all transactions in blocks since block [blockhash], or all transactions if omitted. \n "
" If \" blockhash \" is no longer a part of the main chain, transactions from the fork point onward are included. \n "
" Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \" removed \" array. \n "
" \n Arguments: \n "
" \n Arguments: \n "
" 1. \" blockhash \" (string, optional) The block hash to list transactions since \n "
" 1. \" blockhash \" (string, optional) The block hash to list transactions since \n "
" 2. target_confirmations: (numeric, optional) The confirmations required, must be 1 or more \n "
" 2. target_confirmations: (numeric, optional, default=1) The confirmations required, must be 1 or more \n "
" 3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress') "
" 3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress') \n "
" 4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \" removed \" array \n "
" (not guaranteed to work on pruned nodes) \n "
" \n Result: \n "
" \n Result: \n "
" { \n "
" { \n "
" \" transactions \" : [ \n "
" \" transactions \" : [ \n "
@ -1774,7 +1789,11 @@ UniValue listsinceblock(const JSONRPCRequest& request)
" \" comment \" : \" ... \" , (string) If a comment is associated with the transaction. \n "
" \" comment \" : \" ... \" , (string) If a comment is associated with the transaction. \n "
" \" label \" : \" label \" (string) A comment for the address/transaction, if any \n "
" \" label \" : \" label \" (string) A comment for the address/transaction, if any \n "
" \" to \" : \" ... \" , (string) If a comment to is associated with the transaction. \n "
" \" to \" : \" ... \" , (string) If a comment to is associated with the transaction. \n "
" ], \n "
" ], \n "
" \" removed \" : [ \n "
" <structure is the same as \" transactions \" above, only present if include_removed=true> \n "
" Note: transactions that were readded in the active chain will appear as-is in this array, and may thus have a positive confirmation count. \n "
" ], \n "
" \" lastblock \" : \" lastblockhash \" (string) The hash of the last block \n "
" \" lastblock \" : \" lastblockhash \" (string) The hash of the last block \n "
" } \n "
" } \n "
" \n Examples: \n "
" \n Examples: \n "
@ -1785,21 +1804,19 @@ UniValue listsinceblock(const JSONRPCRequest& request)
LOCK2 ( cs_main , pwallet - > cs_wallet ) ;
LOCK2 ( cs_main , pwallet - > cs_wallet ) ;
const CBlockIndex * pindex = NULL ;
const CBlockIndex * pindex = NULL ; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
const CBlockIndex * paltindex = NULL ; // Block index of the specified block, even if it's in a deactivated chain.
int target_confirms = 1 ;
int target_confirms = 1 ;
isminefilter filter = ISMINE_SPENDABLE ;
isminefilter filter = ISMINE_SPENDABLE ;
if ( ! request . params [ 0 ] . isNull ( ) )
if ( ! request . params [ 0 ] . isNull ( ) ) {
{
uint256 blockId ;
uint256 blockId ;
blockId . SetHex ( request . params [ 0 ] . get_str ( ) ) ;
blockId . SetHex ( request . params [ 0 ] . get_str ( ) ) ;
BlockMap : : iterator it = mapBlockIndex . find ( blockId ) ;
BlockMap : : iterator it = mapBlockIndex . find ( blockId ) ;
if ( it ! = mapBlockIndex . end ( ) )
if ( it ! = mapBlockIndex . end ( ) ) {
{
paltindex = pindex = it - > second ;
pindex = it - > second ;
if ( chainActive [ pindex - > nHeight ] ! = pindex ) {
if ( chainActive [ pindex - > nHeight ] ! = pindex )
{
// the block being asked for is a part of a deactivated chain;
// the block being asked for is a part of a deactivated chain;
// we don't want to depend on its perceived height in the block
// we don't want to depend on its perceived height in the block
// chain, we want to instead use the last common ancestor
// chain, we want to instead use the last common ancestor
@ -1808,19 +1825,20 @@ UniValue listsinceblock(const JSONRPCRequest& request)
}
}
}
}
if ( ! request . params [ 1 ] . isNull ( ) )
if ( ! request . params [ 1 ] . isNull ( ) ) {
{
target_confirms = request . params [ 1 ] . get_int ( ) ;
target_confirms = request . params [ 1 ] . get_int ( ) ;
if ( target_confirms < 1 )
if ( target_confirms < 1 ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter " ) ;
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid parameter " ) ;
}
}
}
if ( request . params . size ( ) > 2 & & request . params [ 2 ] . get_bool ( ) )
if ( ! request . params [ 2 ] . isNull ( ) & & request . params [ 2 ] . get_bool ( ) ) {
{
filter = filter | ISMINE_WATCH_ONLY ;
filter = filter | ISMINE_WATCH_ONLY ;
}
}
bool include_removed = ( request . params [ 3 ] . isNull ( ) | | request . params [ 3 ] . get_bool ( ) ) ;
int depth = pindex ? ( 1 + chainActive . Height ( ) - pindex - > nHeight ) : - 1 ;
int depth = pindex ? ( 1 + chainActive . Height ( ) - pindex - > nHeight ) : - 1 ;
UniValue transactions ( UniValue : : VARR ) ;
UniValue transactions ( UniValue : : VARR ) ;
@ -1828,8 +1846,27 @@ UniValue listsinceblock(const JSONRPCRequest& request)
for ( const std : : pair < uint256 , CWalletTx > & pairWtx : pwallet - > mapWallet ) {
for ( const std : : pair < uint256 , CWalletTx > & pairWtx : pwallet - > mapWallet ) {
CWalletTx tx = pairWtx . second ;
CWalletTx tx = pairWtx . second ;
if ( depth = = - 1 | | tx . GetDepthInMainChain ( ) < depth )
if ( depth = = - 1 | | tx . GetDepthInMainChain ( ) < depth ) {
ListTransactions ( pwallet , tx , " * " , 0 , true , transactions , filter ) ;
ListTransactions ( pwallet , tx , " * " , 0 , true , transactions , filter ) ;
}
}
// when a reorg'd block is requested, we also list any relevant transactions
// in the blocks of the chain that was detached
UniValue removed ( UniValue : : VARR ) ;
while ( include_removed & & paltindex & & paltindex ! = pindex ) {
CBlock block ;
if ( ! ReadBlockFromDisk ( block , paltindex , Params ( ) . GetConsensus ( ) ) ) {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Can't read block from disk " ) ;
}
for ( const CTransactionRef & tx : block . vtx ) {
if ( pwallet - > mapWallet . count ( tx - > GetHash ( ) ) > 0 ) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
ListTransactions ( pwallet , pwallet - > mapWallet [ tx - > GetHash ( ) ] , " * " , - 100000000 , true , removed , filter ) ;
}
}
paltindex = paltindex - > pprev ;
}
}
CBlockIndex * pblockLast = chainActive [ chainActive . Height ( ) + 1 - target_confirms ] ;
CBlockIndex * pblockLast = chainActive [ chainActive . Height ( ) + 1 - target_confirms ] ;
@ -1837,6 +1874,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
UniValue ret ( UniValue : : VOBJ ) ;
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " transactions " , transactions ) ) ;
ret . push_back ( Pair ( " transactions " , transactions ) ) ;
if ( include_removed ) ret . push_back ( Pair ( " removed " , removed ) ) ;
ret . push_back ( Pair ( " lastblock " , lastblock . GetHex ( ) ) ) ;
ret . push_back ( Pair ( " lastblock " , lastblock . GetHex ( ) ) ) ;
return ret ;
return ret ;
@ -3117,7 +3155,7 @@ static const CRPCCommand commands[] =
{ " wallet " , " listlockunspent " , & listlockunspent , false , { } } ,
{ " wallet " , " listlockunspent " , & listlockunspent , false , { } } ,
{ " wallet " , " listreceivedbyaccount " , & listreceivedbyaccount , false , { " minconf " , " include_empty " , " include_watchonly " } } ,
{ " wallet " , " listreceivedbyaccount " , & listreceivedbyaccount , false , { " minconf " , " include_empty " , " include_watchonly " } } ,
{ " wallet " , " listreceivedbyaddress " , & listreceivedbyaddress , false , { " minconf " , " include_empty " , " include_watchonly " } } ,
{ " wallet " , " listreceivedbyaddress " , & listreceivedbyaddress , false , { " minconf " , " include_empty " , " include_watchonly " } } ,
{ " wallet " , " listsinceblock " , & listsinceblock , false , { " blockhash " , " target_confirmations " , " include_watchonly " } } ,
{ " wallet " , " listsinceblock " , & listsinceblock , false , { " blockhash " , " target_confirmations " , " include_watchonly " , " include_removed " } } ,
{ " wallet " , " listtransactions " , & listtransactions , false , { " account " , " count " , " skip " , " include_watchonly " } } ,
{ " wallet " , " listtransactions " , & listtransactions , false , { " account " , " count " , " skip " , " include_watchonly " } } ,
{ " wallet " , " listunspent " , & listunspent , false , { " minconf " , " maxconf " , " addresses " , " include_unsafe " , " query_options " } } ,
{ " wallet " , " listunspent " , & listunspent , false , { " minconf " , " maxconf " , " addresses " , " include_unsafe " , " query_options " } } ,
{ " wallet " , " listwallets " , & listwallets , true , { } } ,
{ " wallet " , " listwallets " , & listwallets , true , { } } ,