-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement new RPC getislocks and add hex field to RPC getbestchainlock #6455
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -300,6 +300,7 @@ static RPCHelpMan getrawtransactionmulti() { | |||||||||||||||||||
{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, | ||||||||||||||||||||
"If false, return a string, otherwise return a json object"}, | ||||||||||||||||||||
}, | ||||||||||||||||||||
// TODO: replace RPCResults to proper annotation | ||||||||||||||||||||
RPCResults{}, | ||||||||||||||||||||
RPCExamples{ | ||||||||||||||||||||
HelpExampleCli("getrawtransactionmulti", | ||||||||||||||||||||
|
@@ -366,6 +367,86 @@ static RPCHelpMan getrawtransactionmulti() { | |||||||||||||||||||
}; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
static RPCHelpMan getislocks() | ||||||||||||||||||||
{ | ||||||||||||||||||||
return RPCHelpMan{"getislocks", | ||||||||||||||||||||
"\nReturns the raw InstantSend lock data for each txids. Returns Null if there is no known IS yet.", | ||||||||||||||||||||
{ | ||||||||||||||||||||
{"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::STR_HEX, "txid", "The transaction id"}, | ||||||||||||||||||||
{RPCResult::Type::ARR, "inputs", "The inputs", | ||||||||||||||||||||
{ | ||||||||||||||||||||
{RPCResult::Type::OBJ, "", "", | ||||||||||||||||||||
{ | ||||||||||||||||||||
{RPCResult::Type::STR_HEX, "txid", "The transaction id"}, | ||||||||||||||||||||
{RPCResult::Type::NUM, "vout", "The output number"}, | ||||||||||||||||||||
}, | ||||||||||||||||||||
}, | ||||||||||||||||||||
}}, | ||||||||||||||||||||
{RPCResult::Type::STR_HEX, "cycleHash", "The Cycle Hash"}, | ||||||||||||||||||||
{RPCResult::Type::STR_HEX, "signature", "The InstantSend's BLS signature"}, | ||||||||||||||||||||
{RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"}, | ||||||||||||||||||||
}}, | ||||||||||||||||||||
RPCResult{"if no InstantSend Lock is known for specified txid", | ||||||||||||||||||||
RPCResult::Type::STR, "data", "Just 'None' string" | ||||||||||||||||||||
}, | ||||||||||||||||||||
}}, | ||||||||||||||||||||
RPCExamples{ | ||||||||||||||||||||
HelpExampleCli("getislocks", "'[\"txid\",...]'") | ||||||||||||||||||||
+ HelpExampleRpc("getislocks", "'[\"txid\",...]'") | ||||||||||||||||||||
}, | ||||||||||||||||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue | ||||||||||||||||||||
{ | ||||||||||||||||||||
const NodeContext& node = EnsureAnyNodeContext(request.context); | ||||||||||||||||||||
|
||||||||||||||||||||
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"); | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
const LLMQContext& llmq_ctx = EnsureLLMQContext(node); | ||||||||||||||||||||
for (const auto idx : irange::range(txids.size())) { | ||||||||||||||||||||
const uint256 txid(ParseHashV(txids[idx], "txid")); | ||||||||||||||||||||
|
||||||||||||||||||||
if (const llmq::CInstantSendLockPtr islock = llmq_ctx.isman->GetInstantSendLockByTxid(txid); islock != nullptr) { | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like to see a type here 🤷 but I have no strong opinion to remove it
Comment on lines
+419
to
+421
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for invalid transaction IDs. The function should validate transaction IDs before attempting to retrieve InstantSend locks. const uint256 txid(ParseHashV(txids[idx], "txid"));
+ if (txid.IsNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid txid at index %d", idx));
+ }
if (const llmq::CInstantSendLockPtr islock = llmq_ctx.isman->GetInstantSendLockByTxid(txid); islock != nullptr) { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||
UniValue objIS(UniValue::VOBJ); | ||||||||||||||||||||
objIS.pushKV("txid", islock->txid.ToString()); | ||||||||||||||||||||
UniValue inputs(UniValue::VARR); | ||||||||||||||||||||
for (const auto out : islock->inputs) { | ||||||||||||||||||||
UniValue outpoint(UniValue::VOBJ); | ||||||||||||||||||||
outpoint.pushKV("txid", out.hash.ToString()); | ||||||||||||||||||||
outpoint.pushKV("vout", static_cast<int64_t>(out.n)); | ||||||||||||||||||||
inputs.push_back(outpoint); | ||||||||||||||||||||
} | ||||||||||||||||||||
objIS.pushKV("inputs", inputs); | ||||||||||||||||||||
objIS.pushKV("cycleHash", islock->cycleHash.ToString()); | ||||||||||||||||||||
objIS.pushKV("signature", islock->sig.ToString()); | ||||||||||||||||||||
{ | ||||||||||||||||||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | ||||||||||||||||||||
ssTx << *islock; | ||||||||||||||||||||
objIS.pushKV("hex", HexStr(ssTx)); | ||||||||||||||||||||
} | ||||||||||||||||||||
result_arr.push_back(objIS); | ||||||||||||||||||||
} else { | ||||||||||||||||||||
result_arr.push_back("None"); | ||||||||||||||||||||
} | ||||||||||||||||||||
} | ||||||||||||||||||||
return result_arr; | ||||||||||||||||||||
|
||||||||||||||||||||
}, | ||||||||||||||||||||
}; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
static RPCHelpMan gettxchainlocks() | ||||||||||||||||||||
{ | ||||||||||||||||||||
return RPCHelpMan{ | ||||||||||||||||||||
|
@@ -2088,6 +2169,7 @@ static const CRPCCommand commands[] = | |||||||||||||||||||
{ "rawtransactions", &getassetunlockstatuses, }, | ||||||||||||||||||||
{ "rawtransactions", &getrawtransaction, }, | ||||||||||||||||||||
{ "rawtransactions", &getrawtransactionmulti, }, | ||||||||||||||||||||
{ "rawtransactions", &getislocks, }, | ||||||||||||||||||||
{ "rawtransactions", &gettxchainlocks, }, | ||||||||||||||||||||
{ "rawtransactions", &createrawtransaction, }, | ||||||||||||||||||||
{ "rawtransactions", &decoderawtransaction, }, | ||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add null check for llmq_ctx.isman.
The code directly accesses
llmq_ctx.isman
without checking if it's null.📝 Committable suggestion