mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
feat: new rpc `gettxchainlocks' to get transaction statuses by batch (#5578)
## Issue being fixed or feature implemented Requested by @QuantumExplorer for platform needs ## What was done? New rpc `gettransactionsarelocked` that returns list of txes. it does less heavy calculations and transfer less data by gRPC. ## How Has This Been Tested? ``` $ src/dash-cli gettransactionsarelocked '["e469de7994b9c1da8efd262fee8843efd7bdcab80c700dc1059c98b28f7c5c1b", "0d9fdf00c9568ff9103742b64e6b8287794633072f8824fa2c475f59e71dbace","0d3f48eebead54d640a7fc5692ddfcba619d8b49347d9a7c04586057c02dec9f"]' [ { "height": 907801, "chainlock": true }, { "height": 101, "chainlock": true }, { "height": -1, "chainlock": false } ] ``` Limiter tested by this call: ``` src/dash-cli gettransactionsarelocked '["", "","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]' | wc ``` ## Breaking Changes N/A ## 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 --------- Co-authored-by: pasta <pasta@dashboost.org> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
parent
400d171d04
commit
633cc3260f
@ -107,6 +107,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "gettransaction", 1, "include_watchonly" },
|
||||
{ "gettransaction", 2, "verbose" },
|
||||
{ "getrawtransaction", 1, "verbose" },
|
||||
{ "gettxchainlocks", 0, "txids" },
|
||||
{ "createrawtransaction", 0, "inputs" },
|
||||
{ "createrawtransaction", 1, "outputs" },
|
||||
{ "createrawtransaction", 2, "locktime" },
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <util/string.h>
|
||||
#include <validation.h>
|
||||
#include <validationinterface.h>
|
||||
#include <util/irange.h>
|
||||
|
||||
#include <evo/specialtx.h>
|
||||
|
||||
@ -261,6 +262,80 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
|
||||
return result;
|
||||
}
|
||||
|
||||
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",
|
||||
{
|
||||
{"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "The transaction ids (no more than 100)",
|
||||
{
|
||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"},
|
||||
},
|
||||
},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::ARR, "", "Response is an array with the same size as the input txids",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "height", "The block height"},
|
||||
{RPCResult::Type::BOOL, "chainlock", "Chainlock status for the block containing the transaction"},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("gettxchainlocks", "'[\"mytxid\",...]'")
|
||||
+ HelpExampleRpc("gettxchainlocks", "[\"mytxid\",...]")
|
||||
},
|
||||
}.Check(request);
|
||||
|
||||
const NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
const LLMQContext& llmq_ctx = EnsureLLMQContext(node);
|
||||
const ChainstateManager& chainman = EnsureChainman(node);
|
||||
const CChainState& active_chainstate = chainman.ActiveChainstate();
|
||||
|
||||
UniValue result_arr(UniValue::VARR);
|
||||
UniValue txids = request.params[0].get_array();
|
||||
if (txids.size() > 100) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Up to 100 txids only");
|
||||
}
|
||||
|
||||
if (g_txindex) {
|
||||
g_txindex->BlockUntilSyncedToCurrentChain();
|
||||
}
|
||||
|
||||
for (const auto idx : irange::range(txids.size())) {
|
||||
UniValue result(UniValue::VOBJ);
|
||||
const uint256 txid(ParseHashV(txids[idx], "txid"));
|
||||
if (txid == Params().GenesisBlock().hashMerkleRoot) {
|
||||
// Special exception for the genesis block coinbase transaction
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved");
|
||||
}
|
||||
|
||||
uint256 hash_block;
|
||||
int height{-1};
|
||||
bool chainLock{false};
|
||||
|
||||
GetTransaction(nullptr, nullptr, txid, Params().GetConsensus(), hash_block);
|
||||
|
||||
if (!hash_block.IsNull()) {
|
||||
LOCK(cs_main);
|
||||
const CBlockIndex* pindex = active_chainstate.m_blockman.LookupBlockIndex(hash_block);
|
||||
if (pindex && active_chainstate.m_chain.Contains(pindex)) {
|
||||
height = pindex->nHeight;
|
||||
}
|
||||
}
|
||||
if (height != -1) {
|
||||
chainLock = llmq_ctx.clhandler->HasChainLock(height, hash_block);
|
||||
}
|
||||
result.pushKV("height", height);
|
||||
result.pushKV("chainlock", chainLock);
|
||||
result_arr.push_back(result);
|
||||
}
|
||||
return result_arr;
|
||||
}
|
||||
|
||||
static UniValue gettxoutproof(const JSONRPCRequest& request)
|
||||
{
|
||||
RPCHelpMan{"gettxoutproof",
|
||||
@ -1683,6 +1758,7 @@ static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) argNames
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
|
||||
{ "rawtransactions", "gettxchainlocks", &gettxchainlocks, {"txids"} },
|
||||
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime"} },
|
||||
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} },
|
||||
{ "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
|
||||
|
@ -115,6 +115,10 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
|
||||
BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), std::runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), std::runtime_error);
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("gettxchainlocks"), std::runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("gettxchainlocks not_array"), std::runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("gettxchainlocks [] extra"), std::runtime_error);
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("createrawtransaction"), std::runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), std::runtime_error);
|
||||
|
@ -4,12 +4,14 @@
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from test_framework.test_framework import DashTestFramework
|
||||
from test_framework.util import assert_raises_rpc_error
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error
|
||||
|
||||
'''
|
||||
rpc_verifychainlock.py
|
||||
|
||||
Test verifychainlock rpc
|
||||
Test the following RPC:
|
||||
- gettxchainlocks
|
||||
- verifychainlock
|
||||
|
||||
'''
|
||||
|
||||
@ -57,6 +59,16 @@ class RPCVerifyChainLockTest(DashTestFramework):
|
||||
assert node0.verifychainlock(block_hash, chainlock_signature, height)
|
||||
assert node1.verifychainlock(block_hash, chainlock_signature, height)
|
||||
|
||||
node1.generate(1)
|
||||
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}])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
RPCVerifyChainLockTest().main()
|
||||
|
Loading…
Reference in New Issue
Block a user