From 25cef45858ce92a5937771009daada51eb333c40 Mon Sep 17 00:00:00 2001 From: Odysseas Gabrielides Date: Sun, 24 Dec 2023 19:58:14 +0200 Subject: [PATCH] feat(rpc): `gettxchainlocks` should return `mempool=false` when tx not in mempool (#5742) ## Issue being fixed or feature implemented Platform (in the scope of Withdrawals) need to be aware if a tx isn't in mempool when requesting status of a tx using RPC `gettxchainlocks`. cc @markin-io ## What was done? - mempool is passed to `GetTransaction` and saving the result for checking latter. - If the returned tx_ref is nullptr, then the RPC returns null for the corresponding tx in the array. Example: `tx1` is mined and chainlocked, `tx2` is in mempool and `tx3` doesn't exist. The result now is: `[ { "height": 830, "chainlock": false, "mempool": true }, { "height": -1, "chainlock": false, "mempool": true }, { "height": -1, "chainlock": false, "mempool": false } ]` ## How Has This Been Tested? ## Breaking Changes ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ --------- Co-authored-by: Konstantin Akimov Co-authored-by: UdjinM6 --- doc/release-notes-5742.md | 4 ++++ src/rpc/rawtransaction.cpp | 14 ++++++++++++-- test/functional/rpc_verifychainlock.py | 15 +++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 doc/release-notes-5742.md diff --git a/doc/release-notes-5742.md b/doc/release-notes-5742.md new file mode 100644 index 0000000000000..6fa741c29323c --- /dev/null +++ b/doc/release-notes-5742.md @@ -0,0 +1,4 @@ +RPC changes +----------- + +RPC `gettxchainlocks` will also return the status `mempool` indicating wether the transaction is in the mempool or not. diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 649a4b582338c..8f06aac2b69b3 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -269,7 +269,7 @@ static UniValue gettxchainlocks(const JSONRPCRequest& request) { RPCHelpMan{ "gettxchainlocks", - "\nReturns the block height each transaction was mined at and whether it is chainlocked or not.\n", + "\nReturns the block height at which each transaction was mined, and indicates whether it is in the mempool, chainlocked, or neither.\n", { {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction ids (no more than 100)", { @@ -284,6 +284,7 @@ static UniValue gettxchainlocks(const JSONRPCRequest& request) { {RPCResult::Type::NUM, "height", "The block height"}, {RPCResult::Type::BOOL, "chainlock", "Chainlock status for the block containing the transaction"}, + {RPCResult::Type::BOOL, "mempool", "Mempool status for the transaction"}, }}, } }, @@ -320,7 +321,15 @@ static UniValue gettxchainlocks(const JSONRPCRequest& request) int height{-1}; bool chainLock{false}; - GetTransaction(nullptr, nullptr, txid, Params().GetConsensus(), hash_block); + const auto tx_ref = GetTransaction(nullptr, node.mempool.get(), txid, Params().GetConsensus(), hash_block); + + if (tx_ref == nullptr) { + result.pushKV("height", -1); + result.pushKV("chainlock", false); + result.pushKV("mempool", false); + result_arr.push_back(result); + continue; + } if (!hash_block.IsNull()) { LOCK(cs_main); @@ -334,6 +343,7 @@ static UniValue gettxchainlocks(const JSONRPCRequest& request) } result.pushKV("height", height); result.pushKV("chainlock", chainLock); + result.pushKV("mempool", height == -1); result_arr.push_back(result); } return result_arr; diff --git a/test/functional/rpc_verifychainlock.py b/test/functional/rpc_verifychainlock.py index a11aba3adc171..31df77c467e69 100755 --- a/test/functional/rpc_verifychainlock.py +++ b/test/functional/rpc_verifychainlock.py @@ -22,6 +22,9 @@ def set_test_params(self): self.set_dash_test_params(5, 3, [["-whitelist=127.0.0.1"], [], [], [], []], fast_dip3_enforcement=True) self.set_dash_llmq_test_params(3, 2) + def cl_helper(self, height, chainlock, mempool): + return {'height': height, 'chainlock': chainlock, 'mempool': mempool} + def run_test(self): node0 = self.nodes[0] node1 = self.nodes[1] @@ -63,12 +66,12 @@ def run_test(self): height1 = node1.getblockcount() tx0 = node0.getblock(node0.getbestblockhash())['tx'][0] tx1 = node1.getblock(node1.getbestblockhash())['tx'][0] - locks0 = node0.gettxchainlocks([tx0, tx1]) - locks1 = node1.gettxchainlocks([tx0, tx1]) - unknown_cl_helper = {'height': -1, 'chainlock': False} - assert_equal(locks0, [{'height': height, 'chainlock': True}, unknown_cl_helper]) - assert_equal(locks1, [unknown_cl_helper, {'height': height1, 'chainlock': False}]) - + tx2 = node0.sendtoaddress(node0.getnewaddress(), 1) + locks0 = node0.gettxchainlocks([tx0, tx1, tx2]) + locks1 = node1.gettxchainlocks([tx0, tx1, tx2]) + unknown_cl_helper = self.cl_helper(-1, False, False) + assert_equal(locks0, [self.cl_helper(height, True, False), unknown_cl_helper, self.cl_helper(-1, False, True)]) + assert_equal(locks1, [unknown_cl_helper, self.cl_helper(height1, False, False), unknown_cl_helper]) if __name__ == '__main__': RPCVerifyChainLockTest().main()