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.
501sigdata.tr_builder = builder;502}503for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {504sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);505sigdata.tap_pubkeys.emplace(Hash160(pubkey), pubkey);506}507sigdata.musig2_pubkeys.insert(m_musig2_participants.begin(), m_musig2_participants.end());508}510void PSBTOutput::FromSignatureData(const SignatureData& sigdata)511{512if (redeem_script.empty() && !sigdata.redeem_script.empty()) {513redeem_script = sigdata.redeem_script;514}515if (witness_script.empty() && !sigdata.witness_script.empty()) {516witness_script = sigdata.witness_script;517}518for (const auto& entry : sigdata.misc_pubkeys) {519hd_keypaths.emplace(entry.second);520}521if (!sigdata.tr_spenddata.internal_key.IsNull()) {522m_tap_internal_key = sigdata.tr_spenddata.internal_key;523}524if (sigdata.tr_builder.has_value() && sigdata.tr_builder->HasScripts()) {525m_tap_tree = sigdata.tr_builder->GetTreeTuples();526}527for (const auto& [pubkey, leaf_origin] : sigdata.taproot_misc_pubkeys) {528m_tap_bip32_paths.emplace(pubkey, leaf_origin);529}530m_musig2_participants.insert(sigdata.musig2_pubkeys.begin(), sigdata.musig2_pubkeys.end());531}533void PSBTOutput::Merge(const PSBTOutput& output)534{535hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());536m_proprietary.insert(output.m_proprietary.begin(), output.m_proprietary.end());537unknown.insert(output.unknown.begin(), output.unknown.end());538m_tap_bip32_paths.insert(output.m_tap_bip32_paths.begin(), output.m_tap_bip32_paths.end());540if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;541if (witness_script.empty() && !output.witness_script.empty()) witness_script = output.witness_script;542if (m_tap_internal_key.IsNull() && !output.m_tap_internal_key.IsNull()) m_tap_internal_key = output.m_tap_internal_key;543if (m_tap_tree.empty() && !output.m_tap_tree.empty()) m_tap_tree = output.m_tap_tree;544m_musig2_participants.insert(output.m_musig2_participants.begin(), output.m_musig2_participants.end());545}547bool PSBTInputSigned(const PSBTInput& input)548{549return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();550}552bool PSBTInputSignedAndVerified(const PartiallySignedTransaction& psbt, unsigned int input_index, const PrecomputedTransactionData* txdata)553{554CTxOut utxo;555assert(input_index < psbt.inputs.size());556const PSBTInput& input = psbt.inputs[input_index];558if (input.non_witness_utxo) {559// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.560COutPoint prevout = input.GetOutPoint();561if (prevout.n >= input.non_witness_utxo->vout.size()) {562return false;563}564if (input.non_witness_utxo->GetHash() != prevout.hash) {565return false;566}567utxo = input.non_witness_utxo->vout[prevout.n];568} else if (!input.witness_utxo.IsNull()) {569utxo = input.witness_utxo;570} else {571return false;572}574std::optional<CMutableTransaction> unsigned_tx = psbt.GetUnsignedTx();575if (!unsigned_tx) {576return false;577}578const CMutableTransaction& tx = *unsigned_tx;579if (txdata) {580return VerifyScript(input.final_script_sig, utxo.scriptPubKey, &input.final_script_witness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker{&tx, input_index, utxo.nValue, *txdata, MissingDataBehavior::FAIL});581} else {582return VerifyScript(input.final_script_sig, utxo.scriptPubKey, &input.final_script_witness, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker{&tx, input_index, utxo.nValue, MissingDataBehavior::FAIL});583}584}586size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt) {587size_t count = 0;588for (const auto& input : psbt.inputs) {589if (!PSBTInputSigned(input)) {590count++;591}592}594return count;595}597void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index)598{599std::optional<CMutableTransaction> unsigned_tx = psbt.GetUnsignedTx();600if (!unsigned_tx) {601return;602}603const CTxOut& out = unsigned_tx->vout.at(index);604PSBTOutput& psbt_out = psbt.outputs.at(index);606// Fill a SignatureData with output info607SignatureData sigdata;608psbt_out.FillSignatureData(sigdata);610// Construct a would-be spend of this output, to update sigdata with.611// Note that ProduceSignature is used to fill in metadata (not actual signatures),612// so provider does not need to provide any private keys (it can be a HidingSigningProvider).613CMutableTransaction tx{};614tx.vin.emplace_back();615MutableTransactionSignatureCreator creator(tx, /*input_idx=*/0, out.nValue, {.sighash_type = SIGHASH_ALL});616ProduceSignature(provider, creator, out.scriptPubKey, sigdata);618// Put redeem_script, witness_script, key paths, into PSBTOutput.619psbt_out.FromSignatureData(sigdata);620}622std::optional<PrecomputedTransactionData> PrecomputePSBTData(const PartiallySignedTransaction& psbt)623{624std::optional<CMutableTransaction> unsigned_tx = psbt.GetUnsignedTx();625if (!unsigned_tx) {626return std::nullopt;627}628const CMutableTransaction& tx = *unsigned_tx;629bool have_all_spent_outputs = true;630std::vector<CTxOut> utxos;631for (const PSBTInput& input : psbt.inputs) {632if (!input.GetUTXO(utxos.emplace_back())) have_all_spent_outputs = false;633}634PrecomputedTransactionData txdata;635if (have_all_spent_outputs) {636txdata.Init(tx, std::move(utxos), true);637} else {638txdata.Init(tx, {}, true);639}640return txdata;641}643util::Expected<void, PSBTError> SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, const common::PSBTFillOptions& options, SignatureData* out_sigdata)644{645PSBTInput& input = psbt.inputs.at(index);646std::optional<CMutableTransaction> unsigned_tx = psbt.GetUnsignedTx();647if (!unsigned_tx) {648return util::Unexpected{PSBTError::INVALID_TX};649}650const CMutableTransaction& tx = *unsigned_tx;652if (PSBTInputSignedAndVerified(psbt, index, txdata)) {653return {};654}656// Fill SignatureData with input info657SignatureData sigdata;658input.FillSignatureData(sigdata);660// Get UTXO661bool require_witness_sig = false;662CTxOut utxo;664if (input.non_witness_utxo) {665// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.666COutPoint prevout = input.GetOutPoint();667if (prevout.n >= input.non_witness_utxo->vout.size()) {668return util::Unexpected{PSBTError::MISSING_INPUTS};669}670if (input.non_witness_utxo->GetHash() != prevout.hash) {671return util::Unexpected{PSBTError::MISSING_INPUTS};672}673utxo = input.non_witness_utxo->vout[prevout.n];674} else if (!input.witness_utxo.IsNull()) {675utxo = input.witness_utxo;676// When we're taking our information from a witness UTXO, we can't verify it is actually data from677// the output being spent. This is safe in case a witness signature is produced (which includes this678// information directly in the hash), but not for non-witness signatures. Remember that we require679// a witness signature in this situation.680require_witness_sig = true;681} else {682return util::Unexpected{PSBTError::MISSING_INPUTS};683}685// Get the sighash type686// If both the field and the parameter are provided, they must match687// If only the parameter is provided, use it and add it to the PSBT if it is other than SIGHASH_DEFAULT688// for all input types, and not SIGHASH_ALL for non-taproot input types.689// If neither are provided, use SIGHASH_DEFAULT if it is taproot, and SIGHASH_ALL for everything else.690int sighash{options.sighash_type.value_or(utxo.scriptPubKey.IsPayToTaproot() ? SIGHASH_DEFAULT : SIGHASH_ALL)};692// For user safety, the desired sighash must be provided if the PSBT wants something other than the default set in the previous line.693if (input.sighash_type && input.sighash_type != sighash) {694return util::Unexpected{PSBTError::SIGHASH_MISMATCH};695}696// Set the PSBT sighash field when sighash is not DEFAULT or ALL697// DEFAULT is allowed for non-taproot inputs since DEFAULT may be passed for them (e.g. the psbt being signed also has taproot inputs)698// Note that signing already aliases DEFAULT to ALL for non-taproot inputs.699if (utxo.scriptPubKey.IsPayToTaproot() ? sighash != SIGHASH_DEFAULT :700(sighash != SIGHASH_DEFAULT && sighash != SIGHASH_ALL)) {701input.sighash_type = sighash;702}704// Check all existing signatures use the sighash type705if (sighash == SIGHASH_DEFAULT) {706if (!input.m_tap_key_sig.empty() && input.m_tap_key_sig.size() != 64) {707return util::Unexpected{PSBTError::SIGHASH_MISMATCH};708}709for (const auto& [_, sig] : input.m_tap_script_sigs) {710if (sig.size() != 64) return util::Unexpected{PSBTError::SIGHASH_MISMATCH};711}712} else {713if (!input.m_tap_key_sig.empty() && (input.m_tap_key_sig.size() != 65 || input.m_tap_key_sig.back() != sighash)) {714return util::Unexpected{PSBTError::SIGHASH_MISMATCH};715}716for (const auto& [_, sig] : input.m_tap_script_sigs) {717if (sig.size() != 65 || sig.back() != sighash) return util::Unexpected{PSBTError::SIGHASH_MISMATCH};718}719for (const auto& [_, sig] : input.partial_sigs) {720if (sig.second.back() != sighash) return util::Unexpected{PSBTError::SIGHASH_MISMATCH};721}722}724sigdata.witness = false;725bool sig_complete;726if (txdata == nullptr) {727sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);728} else {729MutableTransactionSignatureCreator creator(tx, index, utxo.nValue, txdata, {.sighash_type = sighash});730sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);731}732// Verify that a witness signature was produced in case one was required.733if (require_witness_sig && !sigdata.witness) return util::Unexpected{PSBTError::INCOMPLETE};735// If we are not finalizing, set sigdata.complete to false to not set the scriptWitness736if (!options.finalize && sigdata.complete) sigdata.complete = false;738input.FromSignatureData(sigdata);740// If we have a witness signature, put a witness UTXO.741if (sigdata.witness) {742input.witness_utxo = utxo;743// We can remove the non_witness_utxo if and only if there are no non-segwit or segwit v0744// inputs in this transaction. Since this requires inspecting the entire transaction, this745// is something for the caller to deal with (i.e. FillPSBT).746}748// Fill in the missing info749if (out_sigdata) {750out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
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.