From 2471a960b567956c6b54b9831a25cb40f22d1390 Mon Sep 17 00:00:00 2001 From: chanakasameera <70064803+chanakasameera@users.noreply.github.com> Date: Fri, 18 Mar 2022 09:42:26 +0530 Subject: [PATCH] Add txn-no as a pagination token into listaccounthistory rpc (#1110) * Add txn-no as a pegination into listaccounthistory rpc * Added a review comment suggesion * txn is used as a pagination key to search in account history DB * block height and txn are used as keys to search in wallet * txn is used as pagination key to search in wallet * Updated txn logic and tests. * CWalletTx.nIndex is used as txn instead of entry.vout * Update test/functional/rpc_listaccounthistory.py Co-authored-by: surangap Co-authored-by: Anthony Fieroni Co-authored-by: Prasanna Loganathar --- src/masternodes/rpc_accounts.cpp | 15 +++++++++++++-- test/functional/rpc_listaccounthistory.py | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index db96b97358..4081456c24 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -94,7 +94,7 @@ UniValue outputEntryToJSON(COutputEntry const & entry, CBlockIndex const * index } else { obj.pushKV("type", "receive"); } - obj.pushKV("txn", (uint64_t) entry.vout); + obj.pushKV("txn", (uint64_t) pwtx->nIndex); obj.pushKV("txid", pwtx->GetHash().ToString()); TAmounts amounts({{DCT_ID{0},entry.amount}}); obj.pushKV("amounts", AmountsToJSON(amounts)); @@ -964,6 +964,8 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { "Filter by transaction type, supported letter from {CustomTxType}"}, {"limit", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "Maximum number of records to return, 100 by default"}, + {"txn", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, + "Order in block, unlimited by default"}, }, }, }, @@ -991,6 +993,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { std::string tokenFilter; uint32_t limit = 100; auto txType = CustomTxType::None; + uint32_t txn = std::numeric_limits::max(); if (request.params.size() > 1) { UniValue optionsObj = request.params[1].get_obj(); @@ -1002,6 +1005,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { {"token", UniValueType(UniValue::VSTR)}, {"txtype", UniValueType(UniValue::VSTR)}, {"limit", UniValueType(UniValue::VNUM)}, + {"txn", UniValueType(UniValue::VNUM)}, }, true, true); if (!optionsObj["maxBlockHeight"].isNull()) { @@ -1031,6 +1035,10 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { if (limit == 0) { limit = std::numeric_limits::max(); } + + if (!optionsObj["txn"].isNull()) { + txn = (uint32_t) optionsObj["txn"].get_int64(); + } } pwallet->BlockUntilSyncedToCurrentChain(); @@ -1159,7 +1167,7 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { return count != 0 || isMine; }; - AccountHistoryKey startKey{account, maxBlockHeight, std::numeric_limits::max()}; + AccountHistoryKey startKey{account, maxBlockHeight, txn}; if (!noRewards && !account.empty()) { // revert previous tx to restore account balances to maxBlockHeight @@ -1184,6 +1192,9 @@ UniValue listaccounthistory(const JSONRPCRequest& request) { return txs.count(pwtx->GetHash()) || startBlock > index->nHeight || index->nHeight > maxBlockHeight; }, [&](COutputEntry const & entry, CBlockIndex const * index, CWalletTx const * pwtx) { + if (txn != std::numeric_limits::max() && index->nHeight == maxBlockHeight && pwtx->nIndex > txn ) { + return true; + } auto& array = ret.emplace(index->nHeight, UniValue::VARR).first->second; array.push_back(outputEntryToJSON(entry, index, pwtx)); return --count != 0; diff --git a/test/functional/rpc_listaccounthistory.py b/test/functional/rpc_listaccounthistory.py index cc0fa8a211..6b792a6b55 100755 --- a/test/functional/rpc_listaccounthistory.py +++ b/test/functional/rpc_listaccounthistory.py @@ -64,6 +64,7 @@ def run_test(self): found = False for txs in results: assert_equal(txs['owner'], collateral_a) + self.log.info("test 0: block %d, txn is %d", txs['blockHeight'], txs['txn']) if txs['type'] == 'MintToken': found = True assert_equal(found, True) @@ -72,6 +73,27 @@ def run_test(self): for txs in results: assert(hasattr(txs['amounts'], '__len__') and (not isinstance(txs['amounts'], str))) + # list {"maxBlockHeight":103, "txn":1}, should list without blockheight = 103, txn=2. i.e without MintToken + results = self.nodes[0].listaccounthistory(collateral_a, {"maxBlockHeight":103, "txn":1}) + for txs in results: + self.log.info("test 1: block %d, txn is %d", txs['blockHeight'], txs['txn']) + assert_equal(txs['owner'], collateral_a) + assert_equal(txs['blockHeight'] <= 103, True) + if txs['blockHeight'] == 103: + assert_equal(txs['txn'] <= 1 , True) # for block 103 txn:1 applies. + + # list {"maxBlockHeight":103, "txn":0}, should list without blockheight = 103, txn=1,2. i.e without any txs from 103 block + results = self.nodes[0].listaccounthistory(collateral_a, {"maxBlockHeight":103, "txn":0}) + + for txs in results: + self.log.info("test 2: block %d, txn is %d", txs['blockHeight'], txs['txn']) + assert_equal(txs['owner'], collateral_a) + assert_equal(txs['blockHeight'] <= 103, True) + if txs['blockHeight'] == 103: + assert_equal(txs['txn'] <= 0 , True) + else: + assert_equal(txs['txn'] >= 0 , True) # means txn:0 only applicable to block 103 only + # Get node 1 results results = self.nodes[1].listaccounthistory(collateral_a)