1
1
mirror of https://github.com/bitcoin/bitcoin.git synced 2024-05-17 23:56:39 +00:00

Implement decodepsbt for Taproot fields

This commit is contained in:
Andrew Chow 2021-07-19 16:54:16 -04:00
parent ac7747585f
commit 7dccdd3157

View File

@ -790,6 +790,43 @@ static RPCHelpMan decodepsbt()
{ {
{RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."}, {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::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_scripts", /*optional=*/ true, "",
{
{RPCResult::Type::OBJ, "", "",
{
{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::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::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::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields", {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::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
@ -831,7 +868,30 @@ static RPCHelpMan decodepsbt()
{RPCResult::Type::STR, "path", "The path"}, {RPCResult::Type::STR, "path", "The path"},
}}, }},
}}, }},
{RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown global fields", {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::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::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::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",
{ {
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
}}, }},
@ -1045,6 +1105,72 @@ static RPCHelpMan decodepsbt()
in.pushKV("hash256_preimages", hash256_preimages); in.pushKV("hash256_preimages", hash256_preimages);
} }
// Taproot key path signature
if (!input.m_tap_key_sig.empty()) {
in.pushKV("taproot_key_path_sig", HexStr(input.m_tap_key_sig));
}
// Taproot script path signatures
if (!input.m_tap_script_sigs.empty()) {
UniValue script_sigs(UniValue::VARR);
for (const auto& [pubkey_leaf, sig] : input.m_tap_script_sigs) {
const auto& [xonly, leaf_hash] = pubkey_leaf;
UniValue sigobj(UniValue::VOBJ);
sigobj.pushKV("pubkey", HexStr(xonly));
sigobj.pushKV("leaf_hash", HexStr(leaf_hash));
sigobj.pushKV("sig", HexStr(sig));
script_sigs.push_back(sigobj);
}
in.pushKV("taproot_script_path_sigs", script_sigs);
}
// Taproot leaf scripts
if (!input.m_tap_scripts.empty()) {
UniValue tap_scripts(UniValue::VARR);
for (const auto& [leaf, control_blocks] : input.m_tap_scripts) {
const auto& [script, leaf_ver] = leaf;
UniValue script_info(UniValue::VOBJ);
script_info.pushKV("script", HexStr(script));
script_info.pushKV("leaf_ver", leaf_ver);
UniValue control_blocks_univ(UniValue::VARR);
for (const auto& control_block : control_blocks) {
control_blocks_univ.push_back(HexStr(control_block));
}
script_info.pushKV("control_blocks", control_blocks_univ);
tap_scripts.push_back(script_info);
}
in.pushKV("taproot_scripts", tap_scripts);
}
// Taproot bip32 keypaths
if (!input.m_tap_bip32_paths.empty()) {
UniValue keypaths(UniValue::VARR);
for (const auto& [xonly, leaf_origin] : input.m_tap_bip32_paths) {
const auto& [leaf_hashes, origin] = leaf_origin;
UniValue path_obj(UniValue::VOBJ);
path_obj.pushKV("pubkey", HexStr(xonly));
path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint)));
path_obj.pushKV("path", WriteHDKeypath(origin.path));
UniValue leaf_hashes_arr(UniValue::VARR);
for (const auto& leaf_hash : leaf_hashes) {
leaf_hashes_arr.push_back(HexStr(leaf_hash));
}
path_obj.pushKV("leaf_hashes", leaf_hashes_arr);
keypaths.push_back(path_obj);
}
in.pushKV("taproot_bip32_derivs", keypaths);
}
// Taproot internal key
if (!input.m_tap_internal_key.IsNull()) {
in.pushKV("taproot_internal_key", HexStr(input.m_tap_internal_key));
}
// Write taproot merkle root
if (!input.m_tap_merkle_root.IsNull()) {
in.pushKV("taproot_merkle_root", HexStr(input.m_tap_merkle_root));
}
// Proprietary // Proprietary
if (!input.m_proprietary.empty()) { if (!input.m_proprietary.empty()) {
UniValue proprietary(UniValue::VARR); UniValue proprietary(UniValue::VARR);
@ -1103,6 +1229,47 @@ static RPCHelpMan decodepsbt()
out.pushKV("bip32_derivs", keypaths); out.pushKV("bip32_derivs", keypaths);
} }
// Taproot internal key
if (!output.m_tap_internal_key.IsNull()) {
out.pushKV("taproot_internal_key", HexStr(output.m_tap_internal_key));
}
// Taproot tree
if (output.m_tap_tree.has_value()) {
UniValue tree(UniValue::VARR);
const auto& tuples = output.m_tap_tree->GetTreeTuples();
for (const auto& tuple : tuples) {
uint8_t depth = std::get<0>(tuple);
uint8_t leaf_ver = std::get<1>(tuple);
CScript script = std::get<2>(tuple);
UniValue elem(UniValue::VOBJ);
elem.pushKV("depth", (int)depth);
elem.pushKV("leaf_ver", (int)leaf_ver);
elem.pushKV("script", HexStr(script));
tree.push_back(elem);
}
out.pushKV("taproot_tree", tree);
}
// Taproot bip32 keypaths
if (!output.m_tap_bip32_paths.empty()) {
UniValue keypaths(UniValue::VARR);
for (const auto& [xonly, leaf_origin] : output.m_tap_bip32_paths) {
const auto& [leaf_hashes, origin] = leaf_origin;
UniValue path_obj(UniValue::VOBJ);
path_obj.pushKV("pubkey", HexStr(xonly));
path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint)));
path_obj.pushKV("path", WriteHDKeypath(origin.path));
UniValue leaf_hashes_arr(UniValue::VARR);
for (const auto& leaf_hash : leaf_hashes) {
leaf_hashes_arr.push_back(HexStr(leaf_hash));
}
path_obj.pushKV("leaf_hashes", leaf_hashes_arr);
keypaths.push_back(path_obj);
}
out.pushKV("taproot_bip32_derivs", keypaths);
}
// Proprietary // Proprietary
if (!output.m_proprietary.empty()) { if (!output.m_proprietary.empty()) {
UniValue proprietary(UniValue::VARR); UniValue proprietary(UniValue::VARR);