mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +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", 1, "include_watchonly" },
|
||||||
{ "gettransaction", 2, "verbose" },
|
{ "gettransaction", 2, "verbose" },
|
||||||
{ "getrawtransaction", 1, "verbose" },
|
{ "getrawtransaction", 1, "verbose" },
|
||||||
|
{ "gettxchainlocks", 0, "txids" },
|
||||||
{ "createrawtransaction", 0, "inputs" },
|
{ "createrawtransaction", 0, "inputs" },
|
||||||
{ "createrawtransaction", 1, "outputs" },
|
{ "createrawtransaction", 1, "outputs" },
|
||||||
{ "createrawtransaction", 2, "locktime" },
|
{ "createrawtransaction", 2, "locktime" },
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <util/string.h>
|
#include <util/string.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
#include <validationinterface.h>
|
||||||
|
#include <util/irange.h>
|
||||||
|
|
||||||
#include <evo/specialtx.h>
|
#include <evo/specialtx.h>
|
||||||
|
|
||||||
@ -261,6 +262,80 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
|
|||||||
return result;
|
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)
|
static UniValue gettxoutproof(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
RPCHelpMan{"gettxoutproof",
|
RPCHelpMan{"gettxoutproof",
|
||||||
@ -1683,6 +1758,7 @@ static const CRPCCommand commands[] =
|
|||||||
{ // category name actor (function) argNames
|
{ // category name actor (function) argNames
|
||||||
// --------------------- ------------------------ ----------------------- ----------
|
// --------------------- ------------------------ ----------------------- ----------
|
||||||
{ "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
|
{ "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
|
||||||
|
{ "rawtransactions", "gettxchainlocks", &gettxchainlocks, {"txids"} },
|
||||||
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime"} },
|
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime"} },
|
||||||
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} },
|
{ "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} },
|
||||||
{ "rawtransactions", "decodescript", &decodescript, {"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 not_hex"), std::runtime_error);
|
||||||
BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), 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"), std::runtime_error);
|
||||||
BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error);
|
BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error);
|
||||||
BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), 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.
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
from test_framework.test_framework import DashTestFramework
|
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
|
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 node0.verifychainlock(block_hash, chainlock_signature, height)
|
||||||
assert node1.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__':
|
if __name__ == '__main__':
|
||||||
RPCVerifyChainLockTest().main()
|
RPCVerifyChainLockTest().main()
|
||||||
|
Loading…
Reference in New Issue
Block a user