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.
751ss += txTo.vin[inIdx].nSequence.to_bytes(4, "little")752ss += hashOutputs753ss += txTo.nLockTime.to_bytes(4, "little")754ss += hashtype.to_bytes(4, "little")755return ss757def SegwitV0SignatureHash(*args, **kwargs):758return hash256(SegwitV0SignatureMsg(*args, **kwargs))760class TestFrameworkScript(unittest.TestCase):761def test_bn2vch(self):762self.assertEqual(bn2vch(0), bytes([]))763self.assertEqual(bn2vch(1), bytes([0x01]))764self.assertEqual(bn2vch(-1), bytes([0x81]))765self.assertEqual(bn2vch(0x7F), bytes([0x7F]))766self.assertEqual(bn2vch(-0x7F), bytes([0xFF]))767self.assertEqual(bn2vch(0x80), bytes([0x80, 0x00]))768self.assertEqual(bn2vch(-0x80), bytes([0x80, 0x80]))769self.assertEqual(bn2vch(0xFF), bytes([0xFF, 0x00]))770self.assertEqual(bn2vch(-0xFF), bytes([0xFF, 0x80]))771self.assertEqual(bn2vch(0x100), bytes([0x00, 0x01]))772self.assertEqual(bn2vch(-0x100), bytes([0x00, 0x81]))773self.assertEqual(bn2vch(0x7FFF), bytes([0xFF, 0x7F]))774self.assertEqual(bn2vch(-0x8000), bytes([0x00, 0x80, 0x80]))775self.assertEqual(bn2vch(-0x7FFFFF), bytes([0xFF, 0xFF, 0xFF]))776self.assertEqual(bn2vch(0x80000000), bytes([0x00, 0x00, 0x00, 0x80, 0x00]))777self.assertEqual(bn2vch(-0x80000000), bytes([0x00, 0x00, 0x00, 0x80, 0x80]))778self.assertEqual(bn2vch(0xFFFFFFFF), bytes([0xFF, 0xFF, 0xFF, 0xFF, 0x00]))779self.assertEqual(bn2vch(123456789), bytes([0x15, 0xCD, 0x5B, 0x07]))780self.assertEqual(bn2vch(-54321), bytes([0x31, 0xD4, 0x80]))782def test_cscriptnum_encoding(self):783# round-trip negative and multi-byte CScriptNums784values = [0, 1, -1, -2, 127, 128, -255, 256, (1 << 15) - 1, -(1 << 16), (1 << 24) - 1, (1 << 31), 1 - (1 << 32), 1 << 40, 1500, -1500]785for value in values:786self.assertEqual(CScriptNum.decode(CScriptNum.encode(CScriptNum(value))), value)788def test_legacy_sigopcount(self):789# test repeated single sig ops790for n_ops in range(1, 100, 10):791for singlesig_op in (OP_CHECKSIG, OP_CHECKSIGVERIFY):792singlesigs_script = CScript([singlesig_op]*n_ops)793self.assertEqual(singlesigs_script.GetSigOpCount(fAccurate=False), n_ops)794self.assertEqual(singlesigs_script.GetSigOpCount(fAccurate=True), n_ops)795# test multisig op (including accurate counting, i.e. BIP16)796for n in range(1, 16+1):797for multisig_op in (OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY):798multisig_script = CScript([CScriptOp.encode_op_n(n), multisig_op])799self.assertEqual(multisig_script.GetSigOpCount(fAccurate=False), 20)800self.assertEqual(multisig_script.GetSigOpCount(fAccurate=True), n)802def BIP341_sha_prevouts(txTo):803return sha256(b"".join(i.prevout.serialize() for i in txTo.vin))805def BIP341_sha_amounts(spent_utxos):806return sha256(b"".join(u.nValue.to_bytes(8, "little", signed=True) for u in spent_utxos))808def BIP341_sha_scriptpubkeys(spent_utxos):809return sha256(b"".join(ser_string(u.scriptPubKey) for u in spent_utxos))811def BIP341_sha_sequences(txTo):812return sha256(b"".join(i.nSequence.to_bytes(4, "little") for i in txTo.vin))814def BIP341_sha_outputs(txTo):815return sha256(b"".join(o.serialize() for o in txTo.vout))817def TaprootSignatureMsg(txTo, spent_utxos, hash_type, input_index=0, *, scriptpath=False, leaf_script=None, codeseparator_pos=-1, annex=None, leaf_ver=LEAF_VERSION_TAPSCRIPT):818assert_equal(len(txTo.vin), len(spent_utxos))819assert input_index < len(txTo.vin)820out_type = SIGHASH_ALL if hash_type == 0 else hash_type & 3821in_type = hash_type & SIGHASH_ANYONECANPAY822spk = spent_utxos[input_index].scriptPubKey823ss = bytes([0, hash_type]) # epoch, hash_type824ss += txTo.version.to_bytes(4, "little")825ss += txTo.nLockTime.to_bytes(4, "little")826if in_type != SIGHASH_ANYONECANPAY:827ss += BIP341_sha_prevouts(txTo)828ss += BIP341_sha_amounts(spent_utxos)829ss += BIP341_sha_scriptpubkeys(spent_utxos)830ss += BIP341_sha_sequences(txTo)831if out_type == SIGHASH_ALL:832ss += BIP341_sha_outputs(txTo)833spend_type = 0834if annex is not None:835spend_type |= 1836if scriptpath:837spend_type |= 2838ss += bytes([spend_type])839if in_type == SIGHASH_ANYONECANPAY:840ss += txTo.vin[input_index].prevout.serialize()841ss += spent_utxos[input_index].nValue.to_bytes(8, "little", signed=True)842ss += ser_string(spk)843ss += txTo.vin[input_index].nSequence.to_bytes(4, "little")844else:845ss += input_index.to_bytes(4, "little")846if (spend_type & 1):847ss += sha256(ser_string(annex))848if out_type == SIGHASH_SINGLE:849if input_index < len(txTo.vout):850ss += sha256(txTo.vout[input_index].serialize())851else:852ss += bytes(0 for _ in range(32))853if scriptpath:854ss += TaggedHash("TapLeaf", bytes([leaf_ver]) + ser_string(leaf_script))855ss += bytes([0])856ss += codeseparator_pos.to_bytes(4, "little", signed=False)857assert_equal(len(ss), 175 - (in_type == SIGHASH_ANYONECANPAY) * 49 - (out_type != SIGHASH_ALL and out_type != SIGHASH_SINGLE) * 32 + (annex is not None) * 32 + scriptpath * 37)858return ss860def TaprootSignatureHash(*args, **kwargs):861return TaggedHash("TapSighash", TaprootSignatureMsg(*args, **kwargs))863def taproot_tree_helper(scripts):864if len(scripts) == 0:865return ([], bytes())866if len(scripts) == 1:867# One entry: treat as a leaf868script = scripts[0]869assert not callable(script)870if isinstance(script, list):871return taproot_tree_helper(script)872assert isinstance(script, tuple)873version = LEAF_VERSION_TAPSCRIPT874name = script[0]875code = script[1]876if len(script) == 3:877version = script[2]878assert_equal(version & 1, 0)879assert isinstance(code, bytes)880h = TaggedHash("TapLeaf", bytes([version]) + ser_string(code))881if name is None:882return ([], h)883return ([(name, version, code, bytes(), h)], h)884elif len(scripts) == 2 and callable(scripts[1]):885# Two entries, and the right one is a function886left, left_h = taproot_tree_helper(scripts[0:1])887right_h = scripts[1](left_h)888left = [(name, version, script, control + right_h, leaf) for name, version, script, control, leaf in left]889right = []890else:891# Two or more entries: descend into each side892split_pos = len(scripts) // 2893left, left_h = taproot_tree_helper(scripts[0:split_pos])894right, right_h = taproot_tree_helper(scripts[split_pos:])895left = [(name, version, script, control + right_h, leaf) for name, version, script, control, leaf in left]896right = [(name, version, script, control + left_h, leaf) for name, version, script, control, leaf in right]897if right_h < left_h:898right_h, left_h = left_h, right_h899h = TaggedHash("TapBranch", left_h + right_h)900return (left + right, h)902# A TaprootInfo object has the following fields:903# - scriptPubKey: the scriptPubKey (witness v1 CScript)904# - internal_pubkey: the internal pubkey (32 bytes)905# - negflag: whether the pubkey in the scriptPubKey was negated from internal_pubkey+tweak*G (bool).906# - tweak: the tweak (32 bytes)907# - leaves: a dict of name -> TaprootLeafInfo objects for all known leaves908# - merkle_root: the script tree's Merkle root, or bytes() if no leaves are present909TaprootInfo = namedtuple("TaprootInfo", "scriptPubKey,internal_pubkey,negflag,tweak,leaves,merkle_root,output_pubkey")911# A TaprootLeafInfo object has the following fields:912# - script: the leaf script (CScript or bytes)913# - version: the leaf version (0xc0 for BIP342 tapscript)914# - merklebranch: the merkle branch to use for this leaf (32*N bytes)915TaprootLeafInfo = namedtuple("TaprootLeafInfo", "script,version,merklebranch,leaf_hash")917def taproot_construct(pubkey, scripts=None, treat_internal_as_infinity=False):918"""Construct a tree of Taproot spending conditions920pubkey: a 32-byte xonly pubkey for the internal pubkey (bytes)921scripts: a list of items; each item is either:922- a (name, CScript or bytes, leaf version) tuple923- a (name, CScript or bytes) tuple (defaulting to leaf version 0xc0)924- another list of items (with the same structure)925- a list of two items; the first of which is an item itself, and the926second is a function. The function takes as input the Merkle root of the927first item, and produces a (fictitious) partner to hash with.929Returns: a TaprootInfo object930"""931if scripts is None:932scripts = []934ret, h = taproot_tree_helper(scripts)935tweak = TaggedHash("TapTweak", pubkey + h)936if treat_internal_as_infinity:937tweaked, negated = compute_xonly_pubkey(tweak)938else:939tweaked, negated = tweak_add_pubkey(pubkey, tweak)940leaves = dict((name, TaprootLeafInfo(script, version, merklebranch, leaf)) for name, version, script, merklebranch, leaf in ret)941return TaprootInfo(CScript([OP_1, tweaked]), pubkey, negated + 0, tweak, leaves, h, tweaked)943def is_op_success(o):944return o == 0x50 or o == 0x62 or o == 0x89 or o == 0x8a or o == 0x8d or o == 0x8e or (o >= 0x7e and o <= 0x81) or (o >= 0x83 and o <= 0x86) or (o >= 0x95 and o <= 0x99) or (o >= 0xbb and o <= 0xfe)
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.