Skip to content

Commit 7dccdd3

Browse files
committed
Implement decodepsbt for Taproot fields
1 parent ac77475 commit 7dccdd3

File tree

1 file changed

+168
-1
lines changed

1 file changed

+168
-1
lines changed

src/rpc/rawtransaction.cpp

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,43 @@ static RPCHelpMan decodepsbt()
790790
{
791791
{RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
792792
}},
793+
{RPCResult::Type::STR_HEX, "taproot_key_path_sig", /*optional=*/ true, "hex-encoded signature for the Taproot key path spend"},
794+
{RPCResult::Type::ARR, "taproot_script_path_sigs", /*optional=*/ true, "",
795+
{
796+
{RPCResult::Type::OBJ, "signature", /*optional=*/ true, "The signature for the pubkey and leaf hash combination",
797+
{
798+
{RPCResult::Type::STR, "pubkey", "The x-only pubkey for this signature"},
799+
{RPCResult::Type::STR, "leaf_hash", "The leaf hash for this signature"},
800+
{RPCResult::Type::STR, "sig", "The signature itself"},
801+
}},
802+
}},
803+
{RPCResult::Type::ARR, "taproot_scripts", /*optional=*/ true, "",
804+
{
805+
{RPCResult::Type::OBJ, "", "",
806+
{
807+
{RPCResult::Type::STR_HEX, "script", "A leaf script"},
808+
{RPCResult::Type::NUM, "leaf_ver", "The version number for the leaf script"},
809+
{RPCResult::Type::ARR, "control_blocks", "The control blocks for this script",
810+
{
811+
{RPCResult::Type::STR_HEX, "control_block", "A hex-encoded control block for this script"},
812+
}},
813+
}},
814+
}},
815+
{RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
816+
{
817+
{RPCResult::Type::OBJ, "", "",
818+
{
819+
{RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
820+
{RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
821+
{RPCResult::Type::STR, "path", "The path"},
822+
{RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
823+
{
824+
{RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
825+
}},
826+
}},
827+
}},
828+
{RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
829+
{RPCResult::Type::STR_HEX, "taproot_merkle_root", /*optional=*/ true, "The hex-encoded Taproot merkle root"},
793830
{RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields",
794831
{
795832
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
@@ -831,7 +868,30 @@ static RPCHelpMan decodepsbt()
831868
{RPCResult::Type::STR, "path", "The path"},
832869
}},
833870
}},
834-
{RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown global fields",
871+
{RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
872+
{RPCResult::Type::ARR, "taproot_tree", /*optional=*/ true, "The tuples that make up the Taproot tree, in depth first search order",
873+
{
874+
{RPCResult::Type::OBJ, "tuple", /*optional=*/ true, "A single leaf script in the taproot tree",
875+
{
876+
{RPCResult::Type::NUM, "depth", "The depth of this element in the tree"},
877+
{RPCResult::Type::NUM, "leaf_ver", "The version of this leaf"},
878+
{RPCResult::Type::STR, "script", "The hex-encoded script itself"},
879+
}},
880+
}},
881+
{RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
882+
{
883+
{RPCResult::Type::OBJ, "", "",
884+
{
885+
{RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
886+
{RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
887+
{RPCResult::Type::STR, "path", "The path"},
888+
{RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
889+
{
890+
{RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
891+
}},
892+
}},
893+
}},
894+
{RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",
835895
{
836896
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
837897
}},
@@ -1045,6 +1105,72 @@ static RPCHelpMan decodepsbt()
10451105
in.pushKV("hash256_preimages", hash256_preimages);
10461106
}
10471107

1108+
// Taproot key path signature
1109+
if (!input.m_tap_key_sig.empty()) {
1110+
in.pushKV("taproot_key_path_sig", HexStr(input.m_tap_key_sig));
1111+
}
1112+
1113+
// Taproot script path signatures
1114+
if (!input.m_tap_script_sigs.empty()) {
1115+
UniValue script_sigs(UniValue::VARR);
1116+
for (const auto& [pubkey_leaf, sig] : input.m_tap_script_sigs) {
1117+
const auto& [xonly, leaf_hash] = pubkey_leaf;
1118+
UniValue sigobj(UniValue::VOBJ);
1119+
sigobj.pushKV("pubkey", HexStr(xonly));
1120+
sigobj.pushKV("leaf_hash", HexStr(leaf_hash));
1121+
sigobj.pushKV("sig", HexStr(sig));
1122+
script_sigs.push_back(sigobj);
1123+
}
1124+
in.pushKV("taproot_script_path_sigs", script_sigs);
1125+
}
1126+
1127+
// Taproot leaf scripts
1128+
if (!input.m_tap_scripts.empty()) {
1129+
UniValue tap_scripts(UniValue::VARR);
1130+
for (const auto& [leaf, control_blocks] : input.m_tap_scripts) {
1131+
const auto& [script, leaf_ver] = leaf;
1132+
UniValue script_info(UniValue::VOBJ);
1133+
script_info.pushKV("script", HexStr(script));
1134+
script_info.pushKV("leaf_ver", leaf_ver);
1135+
UniValue control_blocks_univ(UniValue::VARR);
1136+
for (const auto& control_block : control_blocks) {
1137+
control_blocks_univ.push_back(HexStr(control_block));
1138+
}
1139+
script_info.pushKV("control_blocks", control_blocks_univ);
1140+
tap_scripts.push_back(script_info);
1141+
}
1142+
in.pushKV("taproot_scripts", tap_scripts);
1143+
}
1144+
1145+
// Taproot bip32 keypaths
1146+
if (!input.m_tap_bip32_paths.empty()) {
1147+
UniValue keypaths(UniValue::VARR);
1148+
for (const auto& [xonly, leaf_origin] : input.m_tap_bip32_paths) {
1149+
const auto& [leaf_hashes, origin] = leaf_origin;
1150+
UniValue path_obj(UniValue::VOBJ);
1151+
path_obj.pushKV("pubkey", HexStr(xonly));
1152+
path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint)));
1153+
path_obj.pushKV("path", WriteHDKeypath(origin.path));
1154+
UniValue leaf_hashes_arr(UniValue::VARR);
1155+
for (const auto& leaf_hash : leaf_hashes) {
1156+
leaf_hashes_arr.push_back(HexStr(leaf_hash));
1157+
}
1158+
path_obj.pushKV("leaf_hashes", leaf_hashes_arr);
1159+
keypaths.push_back(path_obj);
1160+
}
1161+
in.pushKV("taproot_bip32_derivs", keypaths);
1162+
}
1163+
1164+
// Taproot internal key
1165+
if (!input.m_tap_internal_key.IsNull()) {
1166+
in.pushKV("taproot_internal_key", HexStr(input.m_tap_internal_key));
1167+
}
1168+
1169+
// Write taproot merkle root
1170+
if (!input.m_tap_merkle_root.IsNull()) {
1171+
in.pushKV("taproot_merkle_root", HexStr(input.m_tap_merkle_root));
1172+
}
1173+
10481174
// Proprietary
10491175
if (!input.m_proprietary.empty()) {
10501176
UniValue proprietary(UniValue::VARR);
@@ -1103,6 +1229,47 @@ static RPCHelpMan decodepsbt()
11031229
out.pushKV("bip32_derivs", keypaths);
11041230
}
11051231

1232+
// Taproot internal key
1233+
if (!output.m_tap_internal_key.IsNull()) {
1234+
out.pushKV("taproot_internal_key", HexStr(output.m_tap_internal_key));
1235+
}
1236+
1237+
// Taproot tree
1238+
if (output.m_tap_tree.has_value()) {
1239+
UniValue tree(UniValue::VARR);
1240+
const auto& tuples = output.m_tap_tree->GetTreeTuples();
1241+
for (const auto& tuple : tuples) {
1242+
uint8_t depth = std::get<0>(tuple);
1243+
uint8_t leaf_ver = std::get<1>(tuple);
1244+
CScript script = std::get<2>(tuple);
1245+
UniValue elem(UniValue::VOBJ);
1246+
elem.pushKV("depth", (int)depth);
1247+
elem.pushKV("leaf_ver", (int)leaf_ver);
1248+
elem.pushKV("script", HexStr(script));
1249+
tree.push_back(elem);
1250+
}
1251+
out.pushKV("taproot_tree", tree);
1252+
}
1253+
1254+
// Taproot bip32 keypaths
1255+
if (!output.m_tap_bip32_paths.empty()) {
1256+
UniValue keypaths(UniValue::VARR);
1257+
for (const auto& [xonly, leaf_origin] : output.m_tap_bip32_paths) {
1258+
const auto& [leaf_hashes, origin] = leaf_origin;
1259+
UniValue path_obj(UniValue::VOBJ);
1260+
path_obj.pushKV("pubkey", HexStr(xonly));
1261+
path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint)));
1262+
path_obj.pushKV("path", WriteHDKeypath(origin.path));
1263+
UniValue leaf_hashes_arr(UniValue::VARR);
1264+
for (const auto& leaf_hash : leaf_hashes) {
1265+
leaf_hashes_arr.push_back(HexStr(leaf_hash));
1266+
}
1267+
path_obj.pushKV("leaf_hashes", leaf_hashes_arr);
1268+
keypaths.push_back(path_obj);
1269+
}
1270+
out.pushKV("taproot_bip32_derivs", keypaths);
1271+
}
1272+
11061273
// Proprietary
11071274
if (!output.m_proprietary.empty()) {
11081275
UniValue proprietary(UniValue::VARR);

0 commit comments

Comments
 (0)