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.
251if (GetVersion() < 2) {252// This is a v0 psbt, do the v0 AddOutput253outputs.push_back(psbtout);254return true;255}257// No global tx, must be PSBTv2258// Check outputs are modifiable259if (!m_tx_modifiable.has_value() || !m_tx_modifiable->test(1)) {260return false;261}262outputs.push_back(psbtout);264return true;265}267bool PSBTInput::GetUTXO(CTxOut& utxo) const268{269if (non_witness_utxo) {270if (prev_out >= non_witness_utxo->vout.size()) {271return false;272}273if (non_witness_utxo->GetHash() != prev_txid) {274return false;275}276utxo = non_witness_utxo->vout[prev_out];277} else if (!witness_utxo.IsNull()) {278utxo = witness_utxo;279} else {280return false;281}282return true;283}285COutPoint PSBTInput::GetOutPoint() const286{287return COutPoint(prev_txid, prev_out);288}290void PSBTInput::FillSignatureData(SignatureData& sigdata) const291{292if (!final_script_sig.empty()) {293sigdata.scriptSig = final_script_sig;294sigdata.complete = true;295}296if (!final_script_witness.IsNull()) {297sigdata.scriptWitness = final_script_witness;298sigdata.complete = true;299}300if (sigdata.complete) {301return;302}304sigdata.signatures.insert(partial_sigs.begin(), partial_sigs.end());305if (!redeem_script.empty()) {306sigdata.redeem_script = redeem_script;307}308if (!witness_script.empty()) {309sigdata.witness_script = witness_script;310}311for (const auto& key_pair : hd_keypaths) {312sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);313}314if (!m_tap_key_sig.empty()) {315sigdata.taproot_key_path_sig = m_tap_key_sig;316}317for (const auto& [pubkey_leaf, sig] : m_tap_script_sigs) {318sigdata.taproot_script_sigs.emplace(pubkey_leaf, sig);319}320if (!m_tap_internal_key.IsNull()) {321sigdata.tr_spenddata.internal_key = m_tap_internal_key;322}323if (!m_tap_merkle_root.IsNull()) {324sigdata.tr_spenddata.merkle_root = m_tap_merkle_root;325}326for (const auto& [leaf_script, control_block] : m_tap_scripts) {327sigdata.tr_spenddata.scripts.emplace(leaf_script, control_block);328}329for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {330sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);331sigdata.tap_pubkeys.emplace(Hash160(pubkey), pubkey);332}333for (const auto& [hash, preimage] : ripemd160_preimages) {334sigdata.ripemd160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);335}336for (const auto& [hash, preimage] : sha256_preimages) {337sigdata.sha256_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);338}339for (const auto& [hash, preimage] : hash160_preimages) {340sigdata.hash160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);341}342for (const auto& [hash, preimage] : hash256_preimages) {343sigdata.hash256_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);344}345sigdata.musig2_pubkeys.insert(m_musig2_participants.begin(), m_musig2_participants.end());346for (const auto& [agg_key_lh, pubnonces] : m_musig2_pubnonces) {347sigdata.musig2_pubnonces[agg_key_lh].insert(pubnonces.begin(), pubnonces.end());348}349for (const auto& [agg_key_lh, psigs] : m_musig2_partial_sigs) {350sigdata.musig2_partial_sigs[agg_key_lh].insert(psigs.begin(), psigs.end());351}352}354void PSBTInput::FromSignatureData(const SignatureData& sigdata)355{356if (sigdata.complete) {357partial_sigs.clear();358hd_keypaths.clear();359redeem_script.clear();360witness_script.clear();362if (!sigdata.scriptSig.empty()) {363final_script_sig = sigdata.scriptSig;364}365if (!sigdata.scriptWitness.IsNull()) {366final_script_witness = sigdata.scriptWitness;367}368return;369}371partial_sigs.insert(sigdata.signatures.begin(), sigdata.signatures.end());372if (redeem_script.empty() && !sigdata.redeem_script.empty()) {373redeem_script = sigdata.redeem_script;374}375if (witness_script.empty() && !sigdata.witness_script.empty()) {376witness_script = sigdata.witness_script;377}378for (const auto& entry : sigdata.misc_pubkeys) {379hd_keypaths.emplace(entry.second);380}381if (!sigdata.taproot_key_path_sig.empty()) {382m_tap_key_sig = sigdata.taproot_key_path_sig;383}384for (const auto& [pubkey_leaf, sig] : sigdata.taproot_script_sigs) {385m_tap_script_sigs.emplace(pubkey_leaf, sig);386}387if (!sigdata.tr_spenddata.internal_key.IsNull()) {388m_tap_internal_key = sigdata.tr_spenddata.internal_key;389}390if (!sigdata.tr_spenddata.merkle_root.IsNull()) {391m_tap_merkle_root = sigdata.tr_spenddata.merkle_root;392}393for (const auto& [leaf_script, control_block] : sigdata.tr_spenddata.scripts) {394m_tap_scripts.emplace(leaf_script, control_block);395}396for (const auto& [pubkey, leaf_origin] : sigdata.taproot_misc_pubkeys) {397m_tap_bip32_paths.emplace(pubkey, leaf_origin);398}399m_musig2_participants.insert(sigdata.musig2_pubkeys.begin(), sigdata.musig2_pubkeys.end());400for (const auto& [agg_key_lh, pubnonces] : sigdata.musig2_pubnonces) {401m_musig2_pubnonces[agg_key_lh].insert(pubnonces.begin(), pubnonces.end());402}403for (const auto& [agg_key_lh, psigs] : sigdata.musig2_partial_sigs) {404m_musig2_partial_sigs[agg_key_lh].insert(psigs.begin(), psigs.end());405}406for (const auto& [hash, preimage] : sigdata.ripemd160_preimages) {407ripemd160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);408}409for (const auto& [hash, preimage] : sigdata.sha256_preimages) {410sha256_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);411}412for (const auto& [hash, preimage] : sigdata.hash160_preimages) {413hash160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);414}415for (const auto& [hash, preimage] : sigdata.hash256_preimages) {416hash256_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);417}418}420void PSBTInput::Merge(const PSBTInput& input)421{422if (!non_witness_utxo && input.non_witness_utxo) non_witness_utxo = input.non_witness_utxo;423if (witness_utxo.IsNull() && !input.witness_utxo.IsNull()) {424witness_utxo = input.witness_utxo;425}427partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end());428ripemd160_preimages.insert(input.ripemd160_preimages.begin(), input.ripemd160_preimages.end());429sha256_preimages.insert(input.sha256_preimages.begin(), input.sha256_preimages.end());430hash160_preimages.insert(input.hash160_preimages.begin(), input.hash160_preimages.end());431hash256_preimages.insert(input.hash256_preimages.begin(), input.hash256_preimages.end());432hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());433m_proprietary.insert(input.m_proprietary.begin(), input.m_proprietary.end());434unknown.insert(input.unknown.begin(), input.unknown.end());435m_tap_script_sigs.insert(input.m_tap_script_sigs.begin(), input.m_tap_script_sigs.end());436// Merge by control block, the serialized key (BIP 371), to avoid duplicate keys. Keep the437// leaf script already present; BIP 174 lets the Combiner pick arbitrarily on conflict.438std::set<std::vector<unsigned char>> seen_control_blocks;439for (const auto& [_, control_blocks] : m_tap_scripts) {440seen_control_blocks.insert(control_blocks.begin(), control_blocks.end());441}442for (const auto& [leaf, control_blocks] : input.m_tap_scripts) {443for (const auto& control_block : control_blocks) {444if (seen_control_blocks.insert(control_block).second) m_tap_scripts[leaf].insert(control_block);445}446}447m_tap_bip32_paths.insert(input.m_tap_bip32_paths.begin(), input.m_tap_bip32_paths.end());449if (redeem_script.empty() && !input.redeem_script.empty()) redeem_script = input.redeem_script;450if (witness_script.empty() && !input.witness_script.empty()) witness_script = input.witness_script;451if (final_script_sig.empty() && !input.final_script_sig.empty()) final_script_sig = input.final_script_sig;452if (final_script_witness.IsNull() && !input.final_script_witness.IsNull()) final_script_witness = input.final_script_witness;453if (m_tap_key_sig.empty() && !input.m_tap_key_sig.empty()) m_tap_key_sig = input.m_tap_key_sig;454if (m_tap_internal_key.IsNull() && !input.m_tap_internal_key.IsNull()) m_tap_internal_key = input.m_tap_internal_key;455if (m_tap_merkle_root.IsNull() && !input.m_tap_merkle_root.IsNull()) m_tap_merkle_root = input.m_tap_merkle_root;456m_musig2_participants.insert(input.m_musig2_participants.begin(), input.m_musig2_participants.end());457for (const auto& [agg_key_lh, pubnonces] : input.m_musig2_pubnonces) {458m_musig2_pubnonces[agg_key_lh].insert(pubnonces.begin(), pubnonces.end());459}460for (const auto& [agg_key_lh, psigs] : input.m_musig2_partial_sigs) {461m_musig2_partial_sigs[agg_key_lh].insert(psigs.begin(), psigs.end());462}463if (sighash_type == std::nullopt && input.sighash_type != std::nullopt) sighash_type = input.sighash_type;464if (sequence == std::nullopt && input.sequence != std::nullopt) sequence = input.sequence;465if (time_locktime == std::nullopt && input.time_locktime != std::nullopt) time_locktime = input.time_locktime;466if (height_locktime == std::nullopt && input.height_locktime != std::nullopt) height_locktime = input.height_locktime;467}469bool PSBTInput::HasSignatures() const470{471return !final_script_sig.empty()472|| !final_script_witness.IsNull()473|| !partial_sigs.empty()474|| !m_tap_key_sig.empty()475|| !m_tap_script_sigs.empty()476|| !m_musig2_partial_sigs.empty();477}479void PSBTOutput::FillSignatureData(SignatureData& sigdata) const480{481if (!redeem_script.empty()) {482sigdata.redeem_script = redeem_script;483}484if (!witness_script.empty()) {485sigdata.witness_script = witness_script;486}487for (const auto& key_pair : hd_keypaths) {488sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);489}490if (!m_tap_tree.empty() && m_tap_internal_key.IsFullyValid()) {491TaprootBuilder builder;492for (const auto& [depth, leaf_ver, script] : m_tap_tree) {493builder.Add((int)depth, script, (int)leaf_ver, /*track=*/true);494}495assert(builder.IsComplete());496builder.Finalize(m_tap_internal_key);497TaprootSpendData spenddata = builder.GetSpendData();499sigdata.tr_spenddata.internal_key = m_tap_internal_key;500sigdata.tr_spenddata.Merge(spenddata);
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.