Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1001{RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",1002{1003{RPCResult::Type::STR, "asm", "Disassembly of the witness script"},1004{RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},1005{RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},1006}},1007{RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",1008{1009{RPCResult::Type::OBJ, "", "",1010{1011{RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},1012{RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},1013{RPCResult::Type::STR, "path", "The path"},1014}},1015}},1016{RPCResult::Type::NUM, "amount", /* optional=*/ true, "The amount (nValue) for this output"},1017{RPCResult::Type::OBJ, "script", /* optional=*/ true, "The output script (scriptPubKey) for this output",1018ElideGroup(ScriptPubKeyDoc(), "The layout is the same as the output of scriptPubKeys in decoderawtransaction."),1019},1020{RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},1021{RPCResult::Type::ARR, "taproot_tree", /*optional=*/ true, "The tuples that make up the Taproot tree, in depth first search order",1022{1023{RPCResult::Type::OBJ, "tuple", /*optional=*/ true, "A single leaf script in the taproot tree",1024{1025{RPCResult::Type::NUM, "depth", "The depth of this element in the tree"},1026{RPCResult::Type::NUM, "leaf_ver", "The version of this leaf"},1027{RPCResult::Type::STR, "script", "The hex-encoded script itself"},1028}},1029}},1030{RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",1031{1032{RPCResult::Type::OBJ, "", "",1033{1034{RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},1035{RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},1036{RPCResult::Type::STR, "path", "The path"},1037{RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",1038{1039{RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},1040}},1041}},1042}},1043{RPCResult::Type::ARR, "musig2_participant_pubkeys", /*optional=*/true, "",1044{1045{RPCResult::Type::OBJ, "", "",1046{1047{RPCResult::Type::STR_HEX, "aggregate_pubkey", "The compressed aggregate public key for which the participants create."},1048{RPCResult::Type::ARR, "participant_pubkeys", "",1049{1050{RPCResult::Type::STR_HEX, "pubkey", "The compressed public keys that are aggregated for aggregate_pubkey."},1051}},1052}},1053}},1054{RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",1055{1056{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},1057}},1058{RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The output proprietary map",1059{1060{RPCResult::Type::OBJ, "", "",1061{1062{RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},1063{RPCResult::Type::NUM, "subtype", "The number for the subtype"},1064{RPCResult::Type::STR_HEX, "key", "The hex for the key"},1065{RPCResult::Type::STR_HEX, "value", "The hex for the value"},1066}},1067}},1068}},1069}1070};1071return decodepsbt_outputs;1072}1074static RPCMethod decodepsbt()1075{1076return RPCMethod{1077"decodepsbt",1078"Return a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.",1079{1080{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"},1081},1082RPCResult{1083RPCResult::Type::OBJ, "", "",1084{1085{RPCResult::Type::OBJ, "tx", /*optional=*/true, "The decoded network-serialized unsigned transaction.",1086TxDoc({.elision_mode = ElisionMode::WithSummary, .elision_summary = "The layout is the same as the output of decoderawtransaction."})1087},1088{RPCResult::Type::ARR, "global_xpubs", "",1089{1090{RPCResult::Type::OBJ, "", "",1091{1092{RPCResult::Type::STR, "xpub", "The extended public key this path corresponds to"},1093{RPCResult::Type::STR_HEX, "master_fingerprint", "The fingerprint of the master key"},1094{RPCResult::Type::STR, "path", "The path"},1095}},1096}},1097{RPCResult::Type::NUM, "tx_version", /* optional */ true, "The version number of the unsigned transaction. Not to be confused with PSBT version"},1098{RPCResult::Type::NUM, "fallback_locktime", /* optional */ true, "The locktime to fallback to if no inputs specify a required locktime."},1099{RPCResult::Type::NUM, "input_count", /* optional */ true, "The number of inputs in this psbt"},1100{RPCResult::Type::NUM, "output_count", /* optional */ true, "The number of outputs in this psbt."},1101{RPCResult::Type::BOOL, "inputs_modifiable", /* optional */ true, "Whether inputs can be modified"},1102{RPCResult::Type::BOOL, "outputs_modifiable", /* optional */ true, "Whether outputs can be modified"},1103{RPCResult::Type::BOOL, "has_sighash_single", /* optional */ true, "Whether this PSBT has SIGHASH_SINGLE inputs"},1104{RPCResult::Type::NUM, "psbt_version", /* optional */ true, "The PSBT version number. Not to be confused with the unsigned transaction version"},1105{RPCResult::Type::ARR, "proprietary", "The global proprietary map",1106{1107{RPCResult::Type::OBJ, "", "",1108{1109{RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},1110{RPCResult::Type::NUM, "subtype", "The number for the subtype"},1111{RPCResult::Type::STR_HEX, "key", "The hex for the key"},1112{RPCResult::Type::STR_HEX, "value", "The hex for the value"},1113}},1114}},1115{RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields",1116{1117{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},1118}},1119DecodePSBTInputs(),1120DecodePSBTOutputs(),1121{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."},1122}1123},1124RPCExamples{1125HelpExampleCli("decodepsbt", "\"psbt\"")1126},1127[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue1128{1129// Unserialize the transactions1130util::Result<PartiallySignedTransaction> psbt_res = DecodeBase64PSBT(request.params[0].get_str());1131if (!psbt_res) {1132throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed %s", util::ErrorString(psbt_res).original));1133}1134PartiallySignedTransaction psbtx = *psbt_res;1136UniValue result(UniValue::VOBJ);1138if (psbtx.GetVersion() < 2) {1139// Add the decoded tx1140UniValue tx_univ(UniValue::VOBJ);1141TxToUniv(CTransaction(*CHECK_NONFATAL(psbtx.GetUnsignedTx())), /*block_hash=*/uint256(), /*entry=*/tx_univ, /*include_hex=*/false);1142result.pushKV("tx", std::move(tx_univ));1143}1145// Add the global xpubs1146UniValue global_xpubs(UniValue::VARR);1147for (std::pair<KeyOriginInfo, std::set<CExtPubKey>> xpub_pair : psbtx.m_xpubs) {1148for (auto& xpub : xpub_pair.second) {1149std::vector<unsigned char> ser_xpub;1150ser_xpub.assign(BIP32_EXTKEY_WITH_VERSION_SIZE, 0);1151xpub.EncodeWithVersion(ser_xpub.data());1153UniValue keypath(UniValue::VOBJ);1154keypath.pushKV("xpub", EncodeBase58Check(ser_xpub));1155keypath.pushKV("master_fingerprint", HexStr(xpub_pair.first.fingerprint));1156keypath.pushKV("path", WriteHDKeypath(xpub_pair.first.path));1157global_xpubs.push_back(std::move(keypath));1158}1159}1160result.pushKV("global_xpubs", std::move(global_xpubs));1162// Add PSBTv2 stuff1163if (psbtx.GetVersion() >= 2) {1164result.pushKV("tx_version", psbtx.tx_version);1165if (psbtx.fallback_locktime.has_value()) {1166result.pushKV("fallback_locktime", static_cast<uint64_t>(*psbtx.fallback_locktime));1167}1168result.pushKV("input_count", (uint64_t)psbtx.inputs.size());1169result.pushKV("output_count", (uint64_t)psbtx.outputs.size());1170if (psbtx.m_tx_modifiable.has_value()) {1171result.pushKV("inputs_modifiable", psbtx.m_tx_modifiable->test(0));1172result.pushKV("outputs_modifiable", psbtx.m_tx_modifiable->test(1));1173result.pushKV("has_sighash_single", psbtx.m_tx_modifiable->test(2));1174}1175}1177// PSBT version1178result.pushKV("psbt_version", psbtx.GetVersion());1180// Proprietary1181UniValue proprietary(UniValue::VARR);1182for (const auto& entry : psbtx.m_proprietary) {1183UniValue this_prop(UniValue::VOBJ);1184this_prop.pushKV("identifier", HexStr(entry.identifier));1185this_prop.pushKV("subtype", entry.subtype);1186this_prop.pushKV("key", HexStr(entry.key));1187this_prop.pushKV("value", HexStr(entry.value));1188proprietary.push_back(std::move(this_prop));1189}1190result.pushKV("proprietary", std::move(proprietary));1192// Unknown data1193UniValue unknowns(UniValue::VOBJ);1194for (auto [key, value] : psbtx.unknown) {1195unknowns.pushKVEnd(HexStr(key), HexStr(value));1196}1197result.pushKV("unknown", std::move(unknowns));1199// inputs1200CAmount total_in = 0;1201bool have_all_utxos = true;1202UniValue inputs(UniValue::VARR);1203for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {1204const PSBTInput& input = psbtx.inputs[i];1205UniValue in(UniValue::VOBJ);1206// UTXOs1207bool have_a_utxo = false;1208CTxOut txout;1209if (!input.witness_utxo.IsNull()) {1210txout = input.witness_utxo;1212UniValue o(UniValue::VOBJ);1213ScriptToUniv(txout.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);1215UniValue out(UniValue::VOBJ);1216out.pushKV("amount", ValueFromAmount(txout.nValue));1217out.pushKV("scriptPubKey", std::move(o));1219in.pushKV("witness_utxo", std::move(out));1221have_a_utxo = true;1222}1223if (input.non_witness_utxo) {1224txout = input.non_witness_utxo->vout[input.prev_out];1226UniValue non_wit(UniValue::VOBJ);1227TxToUniv(*input.non_witness_utxo, /*block_hash=*/uint256(), /*entry=*/non_wit, /*include_hex=*/false);1228in.pushKV("non_witness_utxo", std::move(non_wit));1230have_a_utxo = true;1231}1232if (have_a_utxo) {1233if (MoneyRange(txout.nValue) && MoneyRange(total_in + txout.nValue)) {1234total_in += txout.nValue;1235} else {1236// Hack to just not show fee later1237have_all_utxos = false;1238}1239} else {1240have_all_utxos = false;1241}1243// Partial sigs1244if (!input.partial_sigs.empty()) {1245UniValue partial_sigs(UniValue::VOBJ);1246for (const auto& sig : input.partial_sigs) {1247partial_sigs.pushKV(HexStr(sig.second.first), HexStr(sig.second.second));1248}1249in.pushKV("partial_signatures", std::move(partial_sigs));1250}