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.
251void DeserializeMuSig2ParticipantDataIdentifier(Stream& skey, CPubKey& agg_pub, CPubKey& part_pub, uint256& leaf_hash)252{253leaf_hash.SetNull();255std::array<unsigned char, CPubKey::COMPRESSED_SIZE> part_pubkey_bytes;256std::array<unsigned char, CPubKey::COMPRESSED_SIZE> agg_pubkey_bytes;258skey >> std::as_writable_bytes(std::span{part_pubkey_bytes}) >> std::as_writable_bytes(std::span{agg_pubkey_bytes});259agg_pub.Set(agg_pubkey_bytes.begin(), agg_pubkey_bytes.end());260if (!agg_pub.IsFullyValid()) {261throw std::ios_base::failure("musig2 aggregate pubkey is invalid");262}264part_pub.Set(part_pubkey_bytes.begin(), part_pubkey_bytes.end());265if (!part_pub.IsFullyValid()) {266throw std::ios_base::failure("musig2 participant pubkey is invalid");267}269if (!skey.empty()) {270skey >> leaf_hash;271}272}274static inline void ExpectedKeySize(const std::string& key_name, const std::vector<unsigned char>& key, uint64_t expected_size) {275if (key.size() != expected_size) {276throw std::ios_base::failure(tfm::format("Size of key was not %d for the type %s", expected_size, key_name));277}278}280/** A structure for PSBTs which contain per-input information */281class PSBTInput282{283private:284uint32_t m_psbt_version;286public:287CTransactionRef non_witness_utxo;288CTxOut witness_utxo;289CScript redeem_script;290CScript witness_script;291CScript final_script_sig;292CScriptWitness final_script_witness;293std::map<CPubKey, KeyOriginInfo> hd_keypaths;294std::map<CKeyID, SigPair> partial_sigs;295std::map<uint160, std::vector<unsigned char>> ripemd160_preimages;296std::map<uint256, std::vector<unsigned char>> sha256_preimages;297std::map<uint160, std::vector<unsigned char>> hash160_preimages;298std::map<uint256, std::vector<unsigned char>> hash256_preimages;300Txid prev_txid;301uint32_t prev_out;302std::optional<uint32_t> sequence;303std::optional<uint32_t> time_locktime;304std::optional<uint32_t> height_locktime;306// Taproot fields307std::vector<unsigned char> m_tap_key_sig;308std::map<std::pair<XOnlyPubKey, uint256>, std::vector<unsigned char>> m_tap_script_sigs;309std::map<std::pair<std::vector<unsigned char>, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> m_tap_scripts;310std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> m_tap_bip32_paths;311XOnlyPubKey m_tap_internal_key;312uint256 m_tap_merkle_root;314// MuSig2 fields315std::map<CPubKey, std::vector<CPubKey>> m_musig2_participants;316// Key is the aggregate pubkey and the script leaf hash, value is a map of participant pubkey to pubnonce317std::map<std::pair<CPubKey, uint256>, std::map<CPubKey, std::vector<uint8_t>>> m_musig2_pubnonces;318// Key is the aggregate pubkey and the script leaf hash, value is a map of participant pubkey to partial_sig319std::map<std::pair<CPubKey, uint256>, std::map<CPubKey, uint256>> m_musig2_partial_sigs;321std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;322std::set<PSBTProprietary> m_proprietary;323std::optional<int> sighash_type;325void FillSignatureData(SignatureData& sigdata) const;326void FromSignatureData(const SignatureData& sigdata);327void Merge(const PSBTInput& input);328uint32_t GetVersion() const { return m_psbt_version; }329COutPoint GetOutPoint() const;330/**331* Retrieves the UTXO for this input332*333* @param[out] utxo The UTXO of this input334* @return Whether the UTXO could be retrieved335*/336bool GetUTXO(CTxOut& utxo) const;337bool HasSignatures() const;339explicit PSBTInput(uint32_t psbt_version, const Txid& prev_txid, uint32_t prev_out, std::optional<uint32_t> sequence = std::nullopt)340: m_psbt_version(psbt_version),341prev_txid(prev_txid),342prev_out(prev_out),343sequence(sequence)344{345assert(m_psbt_version == 0 || m_psbt_version == 2);346}348// Construct a PSBTInput when the previous txid and output index are expected to be serialized349template <typename Stream>350explicit PSBTInput(deserialize_type, Stream& s, uint32_t psbt_version)351: m_psbt_version(psbt_version)352{353assert(m_psbt_version == 2);354Unserialize(s);355}357bool operator==(const PSBTInput&) const = default;359template <typename Stream>360inline void Serialize(Stream& s) const {361// Write the utxo362if (non_witness_utxo) {363SerializeToVector(s, CompactSizeWriter(PSBT_IN_NON_WITNESS_UTXO));364SerializeToVector(s, TX_NO_WITNESS(non_witness_utxo));365}366if (!witness_utxo.IsNull()) {367SerializeToVector(s, CompactSizeWriter(PSBT_IN_WITNESS_UTXO));368SerializeToVector(s, witness_utxo);369}371if (final_script_sig.empty() && final_script_witness.IsNull()) {372// Write any partial signatures373for (const auto& sig_pair : partial_sigs) {374SerializeToVector(s, CompactSizeWriter(PSBT_IN_PARTIAL_SIG), std::span{sig_pair.second.first});375s << sig_pair.second.second;376}378// Write the sighash type379if (sighash_type != std::nullopt) {380SerializeToVector(s, CompactSizeWriter(PSBT_IN_SIGHASH));381SerializeToVector(s, *sighash_type);382}384// Write the redeem script385if (!redeem_script.empty()) {386SerializeToVector(s, CompactSizeWriter(PSBT_IN_REDEEMSCRIPT));387s << redeem_script;388}390// Write the witness script391if (!witness_script.empty()) {392SerializeToVector(s, CompactSizeWriter(PSBT_IN_WITNESSSCRIPT));393s << witness_script;394}396// Write any hd keypaths397SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_IN_BIP32_DERIVATION));399// Write any ripemd160 preimage400for (const auto& [hash, preimage] : ripemd160_preimages) {401SerializeToVector(s, CompactSizeWriter(PSBT_IN_RIPEMD160), std::span{hash});402s << preimage;403}405// Write any sha256 preimage406for (const auto& [hash, preimage] : sha256_preimages) {407SerializeToVector(s, CompactSizeWriter(PSBT_IN_SHA256), std::span{hash});408s << preimage;409}411// Write any hash160 preimage412for (const auto& [hash, preimage] : hash160_preimages) {413SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH160), std::span{hash});414s << preimage;415}417// Write any hash256 preimage418for (const auto& [hash, preimage] : hash256_preimages) {419SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH256), std::span{hash});420s << preimage;421}423// Write taproot key sig424if (!m_tap_key_sig.empty()) {425SerializeToVector(s, PSBT_IN_TAP_KEY_SIG);426s << m_tap_key_sig;427}429// Write taproot script sigs430for (const auto& [pubkey_leaf, sig] : m_tap_script_sigs) {431const auto& [xonly, leaf_hash] = pubkey_leaf;432SerializeToVector(s, PSBT_IN_TAP_SCRIPT_SIG, xonly, leaf_hash);433s << sig;434}436// Write taproot leaf scripts437for (const auto& [leaf, control_blocks] : m_tap_scripts) {438const auto& [script, leaf_ver] = leaf;439for (const auto& control_block : control_blocks) {440SerializeToVector(s, PSBT_IN_TAP_LEAF_SCRIPT, std::span{control_block});441std::vector<unsigned char> value_v(script.begin(), script.end());442value_v.push_back((uint8_t)leaf_ver);443s << value_v;444}445}447// Write taproot bip32 keypaths448for (const auto& [xonly, leaf_origin] : m_tap_bip32_paths) {449const auto& [leaf_hashes, origin] = leaf_origin;450SerializeToVector(s, PSBT_IN_TAP_BIP32_DERIVATION, xonly);451std::vector<unsigned char> value;452VectorWriter s_value{value, 0};453s_value << leaf_hashes;454SerializeKeyOrigin(s_value, origin);455s << value;456}458// Write taproot internal key459if (!m_tap_internal_key.IsNull()) {460SerializeToVector(s, PSBT_IN_TAP_INTERNAL_KEY);461s << ToByteVector(m_tap_internal_key);462}464// Write taproot merkle root465if (!m_tap_merkle_root.IsNull()) {466SerializeToVector(s, PSBT_IN_TAP_MERKLE_ROOT);467SerializeToVector(s, m_tap_merkle_root);468}470// Write MuSig2 Participants471for (const auto& [agg_pubkey, part_pubs] : m_musig2_participants) {472SerializeToVector(s, CompactSizeWriter(PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS), std::span{agg_pubkey});473std::vector<unsigned char> value;474VectorWriter s_value{value, 0};475for (auto& pk : part_pubs) {476s_value << std::span{pk};477}478s << value;479}481// Write MuSig2 pubnonces482for (const auto& [agg_pubkey_leaf_hash, pubnonces] : m_musig2_pubnonces) {483const auto& [agg_pubkey, leaf_hash] = agg_pubkey_leaf_hash;484for (const auto& [part_pubkey, pubnonce] : pubnonces) {485if (leaf_hash.IsNull()) {486SerializeToVector(s, CompactSizeWriter(PSBT_IN_MUSIG2_PUB_NONCE), std::span{part_pubkey}, std::span{agg_pubkey});487} else {488SerializeToVector(s, CompactSizeWriter(PSBT_IN_MUSIG2_PUB_NONCE), std::span{part_pubkey}, std::span{agg_pubkey}, leaf_hash);489}490s << pubnonce;491}492}494// Write MuSig2 partial signatures495for (const auto& [agg_pubkey_leaf_hash, psigs] : m_musig2_partial_sigs) {496const auto& [agg_pubkey, leaf_hash] = agg_pubkey_leaf_hash;497for (const auto& [pubkey, psig] : psigs) {498if (leaf_hash.IsNull()) {499SerializeToVector(s, CompactSizeWriter(PSBT_IN_MUSIG2_PARTIAL_SIG), std::span{pubkey}, std::span{agg_pubkey});500} else {
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.