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.
751sequence.emplace();752UnserializeFromVector(s, *sequence);753break;754}755case PSBT_IN_REQUIRED_TIME_LOCKTIME:756{757ExpectedKeySize("Input Required Time Based Locktime", key, 1);758if (m_psbt_version < 2) {759throw std::ios_base::failure("Required time based locktime is not allowed in PSBTv0");760}761time_locktime.emplace();762UnserializeFromVector(s, *time_locktime);763if (*time_locktime < LOCKTIME_THRESHOLD) {764throw std::ios_base::failure("Required time based locktime is invalid (less than 500000000)");765}766break;767}768case PSBT_IN_REQUIRED_HEIGHT_LOCKTIME:769{770ExpectedKeySize("Input Required Height Based Locktime", key, 1);771if (m_psbt_version < 2) {772throw std::ios_base::failure("Required height based locktime is not allowed in PSBTv0");773}774height_locktime.emplace();775UnserializeFromVector(s, *height_locktime);776if (*height_locktime >= LOCKTIME_THRESHOLD) {777throw std::ios_base::failure("Required height based locktime is invalid (greater than or equal to 500000000)");778} else if (*height_locktime == 0) {779throw std::ios_base::failure("Required height based locktime is invalid (0)");780}781break;782}783case PSBT_IN_TAP_KEY_SIG:784{785ExpectedKeySize("Input Taproot Key Path Signature", key, 1);786s >> m_tap_key_sig;787if (m_tap_key_sig.size() < 64) {788throw std::ios_base::failure("Input Taproot key path signature is shorter than 64 bytes");789} else if (m_tap_key_sig.size() > 65) {790throw std::ios_base::failure("Input Taproot key path signature is longer than 65 bytes");791}792break;793}794case PSBT_IN_TAP_SCRIPT_SIG:795{796ExpectedKeySize("Input Taproot Script Path Signature", key, 65);797SpanReader s_key{std::span{key}.subspan(1)};798XOnlyPubKey xonly;799uint256 hash;800s_key >> xonly;801s_key >> hash;802std::vector<unsigned char> sig;803s >> sig;804if (sig.size() < 64) {805throw std::ios_base::failure("Input Taproot script path signature is shorter than 64 bytes");806} else if (sig.size() > 65) {807throw std::ios_base::failure("Input Taproot script path signature is longer than 65 bytes");808}809m_tap_script_sigs.emplace(std::make_pair(xonly, hash), sig);810break;811}812case PSBT_IN_TAP_LEAF_SCRIPT:813{814if (key.size() < 34) {815throw std::ios_base::failure("Input Taproot leaf script key is not at least 34 bytes");816} else if ((key.size() - 2) % 32 != 0) {817throw std::ios_base::failure("Input Taproot leaf script key's control block size is not valid");818}819std::vector<unsigned char> script_v;820s >> script_v;821if (script_v.empty()) {822throw std::ios_base::failure("Input Taproot leaf script must be at least 1 byte");823}824uint8_t leaf_ver = script_v.back();825script_v.pop_back();826const auto leaf_script = std::make_pair(script_v, (int)leaf_ver);827m_tap_scripts[leaf_script].insert(std::vector<unsigned char>(key.begin() + 1, key.end()));828break;829}830case PSBT_IN_TAP_BIP32_DERIVATION:831{832ExpectedKeySize("Input Taproot BIP32 Keypath", key, 33);833SpanReader s_key{std::span{key}.subspan(1)};834XOnlyPubKey xonly;835s_key >> xonly;836std::set<uint256> leaf_hashes;837uint64_t value_len = ReadCompactSize(s);838size_t before_hashes = s.size();839s >> leaf_hashes;840size_t after_hashes = s.size();841size_t hashes_len = before_hashes - after_hashes;842if (hashes_len > value_len) {843throw std::ios_base::failure("Input Taproot BIP32 keypath has an invalid length");844}845size_t origin_len = value_len - hashes_len;846m_tap_bip32_paths.emplace(xonly, std::make_pair(leaf_hashes, DeserializeKeyOrigin(s, origin_len)));847break;848}849case PSBT_IN_TAP_INTERNAL_KEY:850{851ExpectedKeySize("Input Taproot Internal Key", key, 1);852UnserializeFromVector(s, m_tap_internal_key);853break;854}855case PSBT_IN_TAP_MERKLE_ROOT:856{857ExpectedKeySize("Input Taproot Merkle Root", key, 1);858UnserializeFromVector(s, m_tap_merkle_root);859break;860}861case PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS:862{863ExpectedKeySize("Input MuSig2 Participants Pubkeys", key, CPubKey::COMPRESSED_SIZE + 1);864DeserializeMuSig2ParticipantPubkeys(s, skey, m_musig2_participants, std::string{"Input"});865break;866}867case PSBT_IN_MUSIG2_PUB_NONCE:868{869if (key.size() != 2 * CPubKey::COMPRESSED_SIZE + 1 && key.size() != 2 * CPubKey::COMPRESSED_SIZE + CSHA256::OUTPUT_SIZE + 1) {870throw std::ios_base::failure("Input musig2 pubnonce key is not expected size of 67 or 99 bytes");871}872CPubKey agg_pub, part_pub;873uint256 leaf_hash;874DeserializeMuSig2ParticipantDataIdentifier(skey, agg_pub, part_pub, leaf_hash);876std::vector<uint8_t> pubnonce;877s >> pubnonce;878if (pubnonce.size() != MUSIG2_PUBNONCE_SIZE) {879throw std::ios_base::failure("Input musig2 pubnonce value is not 66 bytes");880}882m_musig2_pubnonces[std::make_pair(agg_pub, leaf_hash)].emplace(part_pub, pubnonce);883break;884}885case PSBT_IN_MUSIG2_PARTIAL_SIG:886{887if (key.size() != 2 * CPubKey::COMPRESSED_SIZE + 1 && key.size() != 2 * CPubKey::COMPRESSED_SIZE + CSHA256::OUTPUT_SIZE + 1) {888throw std::ios_base::failure("Input musig2 partial sig key is not expected size of 67 or 99 bytes");889}890CPubKey agg_pub, part_pub;891uint256 leaf_hash;892DeserializeMuSig2ParticipantDataIdentifier(skey, agg_pub, part_pub, leaf_hash);894uint256 partial_sig;895UnserializeFromVector(s, partial_sig);897m_musig2_partial_sigs[std::make_pair(agg_pub, leaf_hash)].emplace(part_pub, partial_sig);898break;899}900case PSBT_IN_PROPRIETARY:901{902PSBTProprietary this_prop;903skey >> this_prop.identifier;904this_prop.subtype = ReadCompactSize(skey);905this_prop.key = key;907s >> this_prop.value;908m_proprietary.insert(this_prop);909break;910}911// Unknown stuff912default:913// Read in the value914std::vector<unsigned char> val_bytes;915s >> val_bytes;916unknown.emplace(std::move(key), std::move(val_bytes));917break;918}919}921if (!found_sep) {922throw std::ios_base::failure("Separator is missing at the end of an input map");923}925// Make sure required PSBTv2 fields are present926if (m_psbt_version >= 2) {927if (!found_prev_txid) {928throw std::ios_base::failure("Previous TXID is required in PSBTv2");929}930if (!found_prev_out) {931throw std::ios_base::failure("Previous output's index is required in PSBTv2");932}933}934}935};937/** A structure for PSBTs which contains per output information */938class PSBTOutput939{940private:941uint32_t m_psbt_version;943public:944CScript redeem_script;945CScript witness_script;946std::map<CPubKey, KeyOriginInfo> hd_keypaths;948XOnlyPubKey m_tap_internal_key;949std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> m_tap_tree;950std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> m_tap_bip32_paths;951std::map<CPubKey, std::vector<CPubKey>> m_musig2_participants;953std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;954std::set<PSBTProprietary> m_proprietary;956CAmount amount;957CScript script;959void FillSignatureData(SignatureData& sigdata) const;960void FromSignatureData(const SignatureData& sigdata);961void Merge(const PSBTOutput& output);962uint32_t GetVersion() const { return m_psbt_version; }964explicit PSBTOutput(uint32_t psbt_version, CAmount amount, const CScript& script)965: m_psbt_version(psbt_version),966amount(amount),967script(script)968{969assert(m_psbt_version == 0 || m_psbt_version == 2);970}972// Construct a PSBTOutput when the amount and script are expected to be serialized973template <typename Stream>974explicit PSBTOutput(deserialize_type, Stream& s, uint32_t psbt_version)975: m_psbt_version(psbt_version)976{977assert(m_psbt_version == 2);978Unserialize(s);979}981bool operator==(const PSBTOutput&) const = default;983template <typename Stream>984inline void Serialize(Stream& s) const {985// Write the redeem script986if (!redeem_script.empty()) {987SerializeToVector(s, CompactSizeWriter(PSBT_OUT_REDEEMSCRIPT));988s << redeem_script;989}991// Write the witness script992if (!witness_script.empty()) {993SerializeToVector(s, CompactSizeWriter(PSBT_OUT_WITNESSSCRIPT));994s << witness_script;995}997// Write any hd keypaths998SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_OUT_BIP32_DERIVATION));1000if (m_psbt_version >= 2) {
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.