rpc: fix initialization-order-fiasco by lazy-init of decodepsbt_inputs
What changed, and why it matters
This commit fixes a subtle startup bug in Bitcoin Core's RPC help system. Some help text for commands like 'decodepsbt' and 'getblock' was being built before all global constants were ready, which could cause crashes or garbled output when the program starts. The fix delays building that help text until it is actually needed. It is a reliability fix, not a remote attack vector.
Treat as a low-severity hardening/reliability fix. Reviewers should verify that all other RPCResult objects constructed with TxDoc or CURRENCY_UNIT across the codebase use the same lazy-init pattern, and run startup tests on builds with non-deterministic translation-unit ordering.
Security signals we found
Static initialization order fiasco (SIOF) in RPC help metadata construction
Cross-translation-unit dependency on CURRENCY_UNIT global constant
Lazy initialization via function-local static used as fix pattern
Potential crash or undefined behavior during process startup
Evidence from the diff
The patch converts three file-scope const RPCResult objects—decodepsbt_inputs, decodepsbt_outputs, and getblock_vin—into functions that lazily initialize and return static const references. Previously these objects were constructed at dynamic initialization time, and decodepsbt_inputs called TxDoc(), which in turn used CURRENCY_UNIT from a different translation unit. Because C++ does not guarantee initialization order across translation units, CURRENCY_UNIT could be read before it was initialized (initialization-order fiasco). The lazy-init pattern removes the cross-TLU dependency at startup and defers construction until first use, when all globals are guaranteed to be initialized.
Changed components
src/rpc/rawtransaction.cpp (decodepsbt RPC help metadata)src/rpc/blockchain.cpp (getblock RPC help metadata)RPCResult help-text generationInspect captured patch +221 / −209
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d898cd42..8d588b9e 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -734,29 +734,33 @@ static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex& bloc
return blockUndo;
}
-const RPCResult getblock_vin{
- RPCResult::Type::ARR, "vin", "",
- {
- {RPCResult::Type::OBJ, "", "",
+const RPCResult& GetBlockVin()
+{
+ static const RPCResult getblock_vin{
+ RPCResult::Type::ARR, "vin", "",
{
- {RPCResult::Type::ELISION, "", "The same output as verbosity = 2"},
- {RPCResult::Type::OBJ, "prevout", "(Only if undo information is available)",
+ {RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::BOOL, "generated", "Coinbase or not"},
- {RPCResult::Type::NUM, "height", "The height of the prevout"},
- {RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
- {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {RPCResult::Type::ELISION, "", "The same output as verbosity = 2"},
+ {RPCResult::Type::OBJ, "prevout", "(Only if undo information is available)",
{
- {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
- {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
- {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
- {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
- {RPCResult::Type::STR, "type", "The type (one of: " + GetAllOutputTypes() + ")"},
+ {RPCResult::Type::BOOL, "generated", "Coinbase or not"},
+ {RPCResult::Type::NUM, "height", "The height of the prevout"},
+ {RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
+ {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::STR, "type", "The type (one of: " + GetAllOutputTypes() + ")"},
+ }},
}},
}},
- }},
- }
-};
+ }
+ };
+ return getblock_vin;
+}
static RPCMethod getblock()
{
@@ -828,7 +832,7 @@ static RPCMethod getblock()
{
{RPCResult::Type::OBJ, "", "",
{
- getblock_vin,
+ GetBlockVin(),
}},
}},
}},
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 2a1a4d1a..cae9bb6b 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -775,240 +775,248 @@ static RPCMethod signrawtransactionwithkey()
};
}
-const RPCResult decodepsbt_inputs{
- RPCResult::Type::ARR, "inputs", "",
- {
- {RPCResult::Type::OBJ, "", "",
+const RPCResult& DecodePSBTInputs()
+{
+ static const RPCResult decodepsbt_inputs{
+ RPCResult::Type::ARR, "inputs", "",
{
- {RPCResult::Type::OBJ, "non_witness_utxo", /*optional=*/true, "Decoded network transaction for non-witness UTXOs",
- TxDoc({.elision_description="The layout is the same as the output of decoderawtransaction."})
- },
- {RPCResult::Type::OBJ, "witness_utxo", /*optional=*/true, "Transaction output for witness UTXOs",
+ {RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
- {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {RPCResult::Type::OBJ, "non_witness_utxo", /*optional=*/true, "Decoded network transaction for non-witness UTXOs",
+ TxDoc({.elision_description="The layout is the same as the output of decoderawtransaction."})
+ },
+ {RPCResult::Type::OBJ, "witness_utxo", /*optional=*/true, "Transaction output for witness UTXOs",
+ {
+ {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
+ {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "partial_signatures", /*optional=*/true, "",
{
- {RPCResult::Type::STR, "asm", "Disassembly of the output script"},
- {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
- {RPCResult::Type::STR_HEX, "hex", "The raw output script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
+ }},
+ {RPCResult::Type::STR, "sighash", /*optional=*/true, "The sighash type to be used"},
+ {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
{RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
}},
- }},
- {RPCResult::Type::OBJ_DYN, "partial_signatures", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
- }},
- {RPCResult::Type::STR, "sighash", /*optional=*/true, "The sighash type to be used"},
- {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
- {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
- {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
{
- {RPCResult::Type::STR, "pubkey", "The public key with the derivation path as the value."},
- {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
- {RPCResult::Type::STR, "path", "The path"},
+ {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
}},
- }},
- {RPCResult::Type::OBJ, "final_scriptSig", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "Disassembly of the final signature script"},
- {RPCResult::Type::STR_HEX, "hex", "The raw final signature script bytes, hex-encoded"},
- }},
- {RPCResult::Type::ARR, "final_scriptwitness", /*optional=*/true, "",
- {
- {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
- }},
- {RPCResult::Type::OBJ_DYN, "ripemd160_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "sha256_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "hash160_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "hash256_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::STR_HEX, "taproot_key_path_sig", /*optional=*/ true, "hex-encoded signature for the Taproot key path spend"},
- {RPCResult::Type::ARR, "taproot_script_path_sigs", /*optional=*/ true, "",
- {
- {RPCResult::Type::OBJ, "signature", /*optional=*/ true, "The signature for the pubkey and leaf hash combination",
+ {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The public key with the derivation path as the value."},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ }},
+ }},
+ {RPCResult::Type::OBJ, "final_scriptSig", /*optional=*/true, "",
{
- {RPCResult::Type::STR, "pubkey", "The x-only pubkey for this signature"},
- {RPCResult::Type::STR, "leaf_hash", "The leaf hash for this signature"},
- {RPCResult::Type::STR, "sig", "The signature itself"},
+ {RPCResult::Type::STR, "asm", "Disassembly of the final signature script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw final signature script bytes, hex-encoded"},
}},
- }},
- {RPCResult::Type::ARR, "taproot_scripts", /*optional=*/ true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "final_scriptwitness", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
+ }},
+ {RPCResult::Type::OBJ_DYN, "ripemd160_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "sha256_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "hash160_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "hash256_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::STR_HEX, "taproot_key_path_sig", /*optional=*/ true, "hex-encoded signature for the Taproot key path spend"},
+ {RPCResult::Type::ARR, "taproot_script_path_sigs", /*optional=*/ true, "",
{
- {RPCResult::Type::STR_HEX, "script", "A leaf script"},
- {RPCResult::Type::NUM, "leaf_ver", "The version number for the leaf script"},
- {RPCResult::Type::ARR, "control_blocks", "The control blocks for this script",
+ {RPCResult::Type::OBJ, "signature", /*optional=*/ true, "The signature for the pubkey and leaf hash combination",
{
- {RPCResult::Type::STR_HEX, "control_block", "A hex-encoded control block for this script"},
+ {RPCResult::Type::STR, "pubkey", "The x-only pubkey for this signature"},
+ {RPCResult::Type::STR, "leaf_hash", "The leaf hash for this signature"},
+ {RPCResult::Type::STR, "sig", "The signature itself"},
}},
}},
- }},
- {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "taproot_scripts", /*optional=*/ true, "",
{
- {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
- {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
- {RPCResult::Type::STR, "path", "The path"},
- {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
+ {RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
+ {RPCResult::Type::STR_HEX, "script", "A leaf script"},
+ {RPCResult::Type::NUM, "leaf_ver", "The version number for the leaf script"},
+ {RPCResult::Type::ARR, "control_blocks", "The control blocks for this script",
+ {
+ {RPCResult::Type::STR_HEX, "control_block", "A hex-encoded control block for this script"},
+ }},
}},
}},
- }},
- {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
- {RPCResult::Type::STR_HEX, "taproot_merkle_root", /*optional=*/ true, "The hex-encoded Taproot merkle root"},
- {RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
{
- {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},
- {RPCResult::Type::ARR, "participant_pubkeys", "",
+ {RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},
+ {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
+ }},
}},
}},
- }},
- {RPCResult::Type::ARR, "musig2_pubnonces", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
+ {RPCResult::Type::STR_HEX, "taproot_merkle_root", /*optional=*/ true, "The hex-encoded Taproot merkle root"},
+ {RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",
{
- {RPCResult::Type::STR_HEX, "participant_pubkey", "The compressed public key of the participant that created this pubnonce."},
- {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which this pubnonce is for."},
- {RPCResult::Type::STR_HEX, "leaf_hash", /*optional=*/true, "The hash of the leaf script that contains the aggregate pubkey being signed for. Omitted when signing for the internal key."},
- {RPCResult::Type::STR_HEX, "pubnonce", "The public nonce itself."},
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},
+ {RPCResult::Type::ARR, "participant_pubkeys", "",
+ {
+ {RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},
+ }},
+ }},
}},
- }},
- {RPCResult::Type::ARR, "musig2_partial_sigs", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "musig2_pubnonces", /*optional=*/true, "",
{
- {RPCResult::Type::STR_HEX, "participant_pubkey", "The compressed public key of the participant that created this partial signature."},
- {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which this partial signature is for."},
- {RPCResult::Type::STR_HEX, "leaf_hash", /*optional=*/true, "The hash of the leaf script that contains the aggregate pubkey being signed for. Omitted when signing for the internal key."},
- {RPCResult::Type::STR_HEX, "partial_sig", "The partial signature itself."},
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "participant_pubkey", "The compressed public key of the participant that created this pubnonce."},
+ {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which this pubnonce is for."},
+ {RPCResult::Type::STR_HEX, "leaf_hash", /*optional=*/true, "The hash of the leaf script that contains the aggregate pubkey being signed for. Omitted when signing for the internal key."},
+ {RPCResult::Type::STR_HEX, "pubnonce", "The public nonce itself."},
+ }},
}},
- }},
- {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields",
- {
- {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
- }},
- {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The input proprietary map",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "musig2_partial_sigs", /*optional=*/true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "participant_pubkey", "The compressed public key of the participant that created this partial signature."},
+ {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which this partial signature is for."},
+ {RPCResult::Type::STR_HEX, "leaf_hash", /*optional=*/true, "The hash of the leaf script that contains the aggregate pubkey being signed for. Omitted when signing for the internal key."},
+ {RPCResult::Type::STR_HEX, "partial_sig", "The partial signature itself."},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields",
+ {
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The input proprietary map",
{
- {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
- {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
- {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
- {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
+ {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
+ {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
+ {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
+ }},
}},
}},
- }},
- }
-};
+ }
+ };
+ return decodepsbt_inputs;
+}
-const RPCResult decodepsbt_outputs{
- RPCResult::Type::ARR, "outputs", "",
- {
- {RPCResult::Type::OBJ, "", "",
+const RPCResult& DecodePSBTOutputs()
+{
+ static const RPCResult decodepsbt_outputs{
+ RPCResult::Type::ARR, "outputs", "",
{
- {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
- {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
+ {RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
- {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
{
- {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
- {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
- {RPCResult::Type::STR, "path", "The path"},
+ {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
}},
- }},
- {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
- {RPCResult::Type::ARR, "taproot_tree", /*optional=*/ true, "The tuples that make up the Taproot tree, in depth first search order",
- {
- {RPCResult::Type::OBJ, "tuple", /*optional=*/ true, "A single leaf script in the taproot tree",
+ {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
{
- {RPCResult::Type::NUM, "depth", "The depth of this element in the tree"},
- {RPCResult::Type::NUM, "leaf_ver", "The version of this leaf"},
- {RPCResult::Type::STR, "script", "The hex-encoded script itself"},
+ {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
}},
- }},
- {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
{
- {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
- {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
- {RPCResult::Type::STR, "path", "The path"},
- {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
+ {RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
+ {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
}},
}},
- }},
- {RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
+ {RPCResult::Type::ARR, "taproot_tree", /*optional=*/ true, "The tuples that make up the Taproot tree, in depth first search order",
{
- {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},
- {RPCResult::Type::ARR, "participant_pubkeys", "",
+ {RPCResult::Type::OBJ, "tuple", /*optional=*/ true, "A single leaf script in the taproot tree",
{
- {RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},
+ {RPCResult::Type::NUM, "depth", "The depth of this element in the tree"},
+ {RPCResult::Type::NUM, "leaf_ver", "The version of this leaf"},
+ {RPCResult::Type::STR, "script", "The hex-encoded script itself"},
}},
}},
- }},
- {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",
- {
- {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
- }},
- {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The output proprietary map",
- {
- {RPCResult::Type::OBJ, "", "",
+ {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},
+ {RPCResult::Type::ARR, "participant_pubkeys", "",
+ {
+ {RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},
+ }},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",
{
- {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
- {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
- {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
- {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The output proprietary map",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
+ {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
+ {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
+ {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
+ }},
}},
}},
- }},
- }
-};
+ }
+ };
+ return decodepsbt_outputs;
+}
static RPCMethod decodepsbt()
{
@@ -1048,8 +1056,8 @@ static RPCMethod decodepsbt()
{
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
}},
- decodepsbt_inputs,
- decodepsbt_outputs,
+ DecodePSBTInputs(),
+ DecodePSBTOutputs(),
{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."},
}
},
Why this scored 25/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.