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.
1501random.shuffle(unspents)1502unspents.sort(key=lambda x: int(x["amount"] * 100000000), reverse=True)1503if len(unspents) > 50:1504unspents = unspents[:50]1505random.shuffle(unspents)1506balance = 01507for unspent in unspents:1508balance += int(unspent["amount"] * 100000000)1509txid = int(unspent["txid"], 16)1510fund_tx.vin.append(CTxIn(COutPoint(txid, int(unspent["vout"])), CScript()))1511# Add outputs1512cur_progress = done / len(spenders)1513next_progress = (done + count_this_tx) / len(spenders)1514change_goal = (1.0 - 0.6 * next_progress) / (1.0 - 0.6 * cur_progress) * balance1515self.log.debug("Create %i UTXOs in a transaction spending %i inputs worth %.8f (sending ~%.8f to change)" % (count_this_tx, len(unspents), balance * 0.00000001, change_goal * 0.00000001))1516for i in range(count_this_tx):1517avg = (balance - change_goal) / (count_this_tx - i)1518amount = int(random.randrange(int(avg*0.85 + 0.5), int(avg*1.15 + 0.5)) + 0.5)1519balance -= amount1520fund_tx.vout.append(CTxOut(amount, spenders[done + i].script))1521# Add change1522fund_tx.vout.append(CTxOut(balance - 10000, random.choice(host_spks)))1523# Ask the node to sign1524fund_tx = tx_from_hex(self.nodesigner.signrawtransaction(fund_tx.serialize().hex(), unspents)["hex"])1525# Construct UTXOData entries1526for i in range(count_this_tx):1527utxodata = UTXOData(outpoint=COutPoint(fund_tx.txid_int, i), output=fund_tx.vout[i], spender=spenders[done])1528if utxodata.spender.need_vin_vout_mismatch:1529mismatching_utxos.append(utxodata)1530else:1531normal_utxos.append(utxodata)1532done += 11533# Mine into a block1534self.block_submit(node, [fund_tx], "Funding tx", None, random.choice(host_pubkeys), 10000, MAX_BLOCK_SIGOPS_WEIGHT, True, True)1536# Consume groups of choice(input_coins) from utxos in a tx, testing the spenders.1537self.log.info("- Running %i spending tests" % done)1538random.shuffle(normal_utxos)1539random.shuffle(mismatching_utxos)1540assert_equal(done, len(normal_utxos) + len(mismatching_utxos))1542left = done1543while left:1544# Construct CTransaction with random version, nLocktime1545tx = CTransaction()1546tx.version = random.choice(TX_STANDARD_VERSIONS + [0, TX_MAX_STANDARD_VERSION + 1, random.getrandbits(32)])1547min_sequence = (tx.version != 1 and tx.version != 0) * 0x80000000 # The minimum sequence number to disable relative locktime1548if random.choice([True, False]):1549tx.nLockTime = random.randrange(LOCKTIME_THRESHOLD, self.lastblocktime - 7200) # all absolute locktimes in the past1550else:1551tx.nLockTime = random.randrange(self.lastblockheight + 1) # all block heights in the past1553# Decide how many UTXOs to test with.1554acceptable = [n for n in input_counts if n <= left and (left - n > max(input_counts) or (left - n) in [0] + input_counts)]1555num_inputs = random.choice(acceptable)1557# If we have UTXOs that require mismatching inputs/outputs left, include exactly one of those1558# unless there is only one normal UTXO left (as tests with mismatching UTXOs require at least one1559# normal UTXO to go in the first position), and we don't want to run out of normal UTXOs.1560input_utxos = []1561while len(mismatching_utxos) and (len(input_utxos) == 0 or len(normal_utxos) == 1):1562input_utxos.append(mismatching_utxos.pop())1563left -= 11565# Top up until we hit num_inputs (but include at least one normal UTXO always).1566for _ in range(max(1, num_inputs - len(input_utxos))):1567input_utxos.append(normal_utxos.pop())1568left -= 11570# The first input cannot require a mismatching output (as there is at least one output).1571while True:1572random.shuffle(input_utxos)1573if not input_utxos[0].spender.need_vin_vout_mismatch:1574break1575first_mismatch_input = None1576for i in range(len(input_utxos)):1577if input_utxos[i].spender.need_vin_vout_mismatch:1578first_mismatch_input = i1579assert first_mismatch_input is None or first_mismatch_input > 01581# Decide fee, and add CTxIns to tx.1582amount = sum(utxo.output.nValue for utxo in input_utxos)1583fee = min(random.randrange(MIN_FEE * 2, MIN_FEE * 4), amount - DUST_LIMIT) # 10000-20000 sat fee1584in_value = amount - fee1585tx.vin = [CTxIn(outpoint=utxo.outpoint, nSequence=random.randint(min_sequence, 0xffffffff)) for utxo in input_utxos]1586tx.wit.vtxinwit = [CTxInWitness() for _ in range(len(input_utxos))]1587sigops_weight = sum(utxo.spender.sigops_weight for utxo in input_utxos)1588self.log.debug("Test: %s" % (", ".join(utxo.spender.comment for utxo in input_utxos)))1590# Add 1 to 4 random outputs (but constrained by inputs that require mismatching outputs)1591num_outputs = random.choice(range(1, 1 + min(4, 4 if first_mismatch_input is None else first_mismatch_input)))1592assert in_value >= 0 and fee - num_outputs * DUST_LIMIT >= MIN_FEE1593for i in range(num_outputs):1594tx.vout.append(CTxOut())1595if in_value <= DUST_LIMIT:1596tx.vout[-1].nValue = DUST_LIMIT1597elif i < num_outputs - 1:1598tx.vout[-1].nValue = in_value1599else:1600tx.vout[-1].nValue = random.randint(DUST_LIMIT, in_value)1601in_value -= tx.vout[-1].nValue1602tx.vout[-1].scriptPubKey = random.choice(host_spks)1603sigops_weight += CScript(tx.vout[-1].scriptPubKey).GetSigOpCount(False) * WITNESS_SCALE_FACTOR1604fee += in_value1605assert fee >= 01607# Select coinbase pubkey1608cb_pubkey = random.choice(host_pubkeys)1609sigops_weight += 1 * WITNESS_SCALE_FACTOR1611# Precompute one satisfying and one failing scriptSig/witness for each input.1612input_data = []1613for i in range(len(input_utxos)):1614fn = input_utxos[i].spender.sat_function1615fail = None1616success = fn(tx, i, [utxo.output for utxo in input_utxos], True)1617if not input_utxos[i].spender.no_fail:1618fail = fn(tx, i, [utxo.output for utxo in input_utxos], False)1619input_data.append((fail, success))1620if self.options.dump_tests:1621dump_json_test(tx, input_utxos, i, success, fail)1623# Sign each input incorrectly once on each complete signing pass, except the very last.1624for fail_input in list(range(len(input_utxos))) + [None]:1625# Skip trying to fail at spending something that can't be made to fail.1626if fail_input is not None and input_utxos[fail_input].spender.no_fail:1627continue1628# Expected message with each input failure, may be None(which is ignored)1629expected_fail_msg = None if fail_input is None else input_utxos[fail_input].spender.err_msg1630# Fill inputs/witnesses1631for i in range(len(input_utxos)):1632tx.vin[i].scriptSig = input_data[i][i != fail_input][0]1633tx.wit.vtxinwit[i].scriptWitness.stack = input_data[i][i != fail_input][1]1634# Submit to mempool to check standardness1635is_standard_tx = (1636fail_input is None # Must be valid to be standard1637and (all(utxo.spender.is_standard for utxo in input_utxos)) # All inputs must be standard1638and tx.version in TX_STANDARD_VERSIONS # The tx version must be standard1639and not (tx.version == 3 and tx.get_vsize() > TRUC_MAX_VSIZE) # Topological standardness rules must be followed1640)1641msg = ','.join(utxo.spender.comment + ("*" if n == fail_input else "") for n, utxo in enumerate(input_utxos))1642if is_standard_tx:1643node.sendrawtransaction(tx.serialize().hex(), 0)1644assert node.getmempoolentry(tx.txid_hex) is not None, "Failed to accept into mempool: " + msg1645else:1646assert_raises_rpc_error(-26, None, node.sendrawtransaction, tx.serialize().hex(), 0)1647# Submit in a block1648self.block_submit(node, [tx], msg, witness=True, accept=fail_input is None, cb_pubkey=cb_pubkey, fees=fee, sigops_weight=sigops_weight, err_msg=expected_fail_msg)1650if (len(spenders) - left) // 200 > (len(spenders) - left - len(input_utxos)) // 200:1651self.log.info(" - %i tests done" % (len(spenders) - left))1653assert_equal(left, 0)1654assert_equal(len(normal_utxos), 0)1655assert_equal(len(mismatching_utxos), 0)1656self.log.info(" - Done")1658def gen_test_vectors(self):1659"""Run a scenario that corresponds (and optionally produces) to BIP341 test vectors."""1661self.log.info("Unit test scenario...")1663# Deterministically mine coins to OP_TRUE in block 11664assert_equal(self.nodes[0].getblockcount(), 0)1665coinbase = CTransaction()1666coinbase.version = 11667coinbase.vin = [CTxIn(COutPoint(0, 0xffffffff), CScript([OP_1, OP_1]), SEQUENCE_FINAL)]1668coinbase.vout = [CTxOut(5000000000, CScript([OP_1]))]1669coinbase.nLockTime = 01670assert_equal(coinbase.txid_hex, "f60c73405d499a956d3162e3483c395526ef78286458a4cb17b125aa92e49b20")1671# Mine it1672block = create_block(hashprev=int(self.nodes[0].getbestblockhash(), 16), coinbase=coinbase)1673block.solve()1674self.nodes[0].submitblock(block.serialize().hex())1675assert_equal(self.nodes[0].getblockcount(), 1)1676self.generatetoaddress(self.nodes[0], COINBASE_MATURITY, self.nodesigner.getnewaddress()[2])1678SEED = 3171679VALID_LEAF_VERS = list(range(0xc0, 0x100, 2)) + [0x66, 0x7e, 0x80, 0x84, 0x96, 0x98, 0xba, 0xbc, 0xbe]1680# Generate private keys1681prvs = [hashlib.sha256(SEED.to_bytes(2, 'big') + bytes([i])).digest() for i in range(100)]1682# Generate corresponding public x-only pubkeys1683pubs = [compute_xonly_pubkey(prv)[0] for prv in prvs]1684# Generate taproot objects1685inner_keys = [pubs[i] for i in range(7)]1687script_lists = [1688None,1689[("0", CScript([pubs[50], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT)],1690[("0", CScript([pubs[51], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT)],1691[("0", CScript([pubs[52], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT), ("1", CScript([b"BIP341"]), VALID_LEAF_VERS[pubs[99][0] % 41])],1692[("0", CScript([pubs[53], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT), ("1", CScript([b"Taproot"]), VALID_LEAF_VERS[pubs[99][1] % 41])],1693[("0", CScript([pubs[54], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT),1694[("1", CScript([pubs[55], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT), ("2", CScript([pubs[56], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT)]1695],1696[("0", CScript([pubs[57], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT),1697[("1", CScript([pubs[58], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT), ("2", CScript([pubs[59], OP_CHECKSIG]), LEAF_VERSION_TAPSCRIPT)]1698],1699]1700taps = [taproot_construct(inner_keys[i], script_lists[i]) for i in range(len(inner_keys))]1702# Require negated taps[0]1703assert taps[0].negflag1704# Require one negated and one non-negated in taps 1 and 2.1705assert_not_equal(taps[1].negflag, taps[2].negflag)1706# Require one negated and one non-negated in taps 3 and 4.1707assert_not_equal(taps[3].negflag, taps[4].negflag)1708# Require one negated and one non-negated in taps 5 and 6.1709assert_not_equal(taps[5].negflag, taps[6].negflag)1711cblks = [{leaf: get({**DEFAULT_CONTEXT, 'tap': taps[i], 'leaf': leaf}, 'controlblock') for leaf in taps[i].leaves} for i in range(7)]1712# Require one swapped and one unswapped in taps 3 and 4.1713assert_not_equal((cblks[3]['0'][33:65] < cblks[3]['1'][33:65]), (cblks[4]['0'][33:65] < cblks[4]['1'][33:65]))1714# Require one swapped and one unswapped in taps 5 and 6, both at the top and child level.1715assert_not_equal((cblks[5]['0'][33:65] < cblks[5]['1'][65:]), (cblks[6]['0'][33:65] < cblks[6]['1'][65:]))1716assert_not_equal((cblks[5]['1'][33:65] < cblks[5]['2'][33:65]), (cblks[6]['1'][33:65] < cblks[6]['2'][33:65]))1717# Require within taps 5 (and thus also 6) that one level is swapped and the other is not.1718assert_not_equal((cblks[5]['0'][33:65] < cblks[5]['1'][65:]), (cblks[5]['1'][33:65] < cblks[5]['2'][33:65]))1720# Compute a deterministic set of scriptPubKeys1721tap_spks = []1722old_spks = []1723spend_info = {}1724# First, taproot scriptPubKeys, for the tap objects constructed above1725for i, tap in enumerate(taps):1726tap_spks.append(tap.scriptPubKey)1727d = {'key': prvs[i], 'tap': tap, 'mode': 'taproot'}1728spend_info[tap.scriptPubKey] = d1729# Then, a number of deterministically generated (keys 0x1,0x2,0x3) with 2x P2PKH, 1x P2WPKH spks.1730for i in range(1, 4):1731prv = ECKey()1732prv.set(i.to_bytes(32, 'big'), True)1733pub = prv.get_pubkey().get_bytes()1734d = {"key": prv}1735d["scriptcode"] = key_to_p2pkh_script(pub)1736d["inputs"] = [getter("sign"), pub]1737if i < 3:1738# P2PKH1739d['spk'] = key_to_p2pkh_script(pub)1740d['mode'] = 'legacy'1741else:1742# P2WPKH1743d['spk'] = key_to_p2wpkh_script(pub)1744d['mode'] = 'witv0'1745old_spks.append(d['spk'])1746spend_info[d['spk']] = d1748# Construct a deterministic chain of transactions creating UTXOs to the test's spk's (so that they1749# come from distinct txids).1750txn = []
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.