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.
751# Try to tweak the nonce752block_2 = self.build_next_block()753add_witness_commitment(block_2, nonce=28)754block_2.solve()756# The commitment should have changed!757assert_not_equal(block_2.vtx[0].vout[-1], block.vtx[0].vout[-1])759# This should also be valid.760test_witness_block(self.nodes[0], self.test_node, block_2, accepted=True)762# Now test commitments with actual transactions763tx = CTransaction()764tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))766# Let's construct a witness script767witness_script = CScript([OP_TRUE])768script_pubkey = script_to_p2wsh_script(witness_script)769tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))771# tx2 will spend tx1, and send back to a regular anyone-can-spend address772tx2 = CTransaction()773tx2.vin.append(CTxIn(COutPoint(tx.txid_int, 0), b""))774tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, witness_script))775tx2.wit.vtxinwit.append(CTxInWitness())776tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_script]778block_3 = self.build_next_block()779self.update_witness_block_with_transactions(block_3, [tx, tx2], nonce=1)780# Add an extra OP_RETURN output that matches the witness commitment template,781# even though it has extra data after the incorrect commitment.782# This block should fail.783block_3.vtx[0].vout.append(CTxOut(0, CScript([OP_RETURN, WITNESS_COMMITMENT_HEADER + ser_uint256(2), 10])))784block_3.hashMerkleRoot = block_3.calc_merkle_root()785block_3.solve()787test_witness_block(self.nodes[0], self.test_node, block_3, accepted=False, reason='bad-witness-merkle-match')789# Add a different commitment with different nonce, but in the790# right location, and with some funds burned(!).791# This should succeed (nValue shouldn't affect finding the792# witness commitment).793add_witness_commitment(block_3, nonce=0)794block_3.vtx[0].vout[0].nValue -= 1795block_3.vtx[0].vout[-1].nValue += 1796block_3.hashMerkleRoot = block_3.calc_merkle_root()797assert_equal(len(block_3.vtx[0].vout), 4) # 3 OP_returns798block_3.solve()799test_witness_block(self.nodes[0], self.test_node, block_3, accepted=True)801# Finally test that a block with no witness transactions can802# omit the commitment.803block_4 = self.build_next_block()804tx3 = CTransaction()805tx3.vin.append(CTxIn(COutPoint(tx2.txid_int, 0), b""))806tx3.vout.append(CTxOut(tx.vout[0].nValue - 1000, witness_script))807block_4.vtx.append(tx3)808block_4.hashMerkleRoot = block_4.calc_merkle_root()809block_4.solve()810test_witness_block(self.nodes[0], self.test_node, block_4, with_witness=False, accepted=True)812# Update available utxo's for use in later test.813self.utxo.pop(0)814self.utxo.append(UTXO(tx3.txid_int, 0, tx3.vout[0].nValue))816@subtest817def test_block_malleability(self):819# Make sure that a block that has too big a virtual size820# because of a too-large coinbase witness is not permanently821# marked bad.822block = self.build_next_block()823add_witness_commitment(block)824block.solve()826block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a' * 5000000)827assert block.get_weight() > MAX_BLOCK_WEIGHT829# We can't send over the p2p network, because this is too big to relay830assert_equal('bad-witness-nonce-size', self.nodes[0].submitblock(block.serialize().hex()))832assert_not_equal(self.nodes[0].getbestblockhash(), block.hash_hex)834block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.pop()835assert block.get_weight() < MAX_BLOCK_WEIGHT836assert_equal(None, self.nodes[0].submitblock(block.serialize().hex()))838assert_equal(self.nodes[0].getbestblockhash(), block.hash_hex)840# Build a relayable-but-invalid block841relayable_block = self.build_next_block()842add_witness_commitment(relayable_block)843relayable_block.solve()845# Append extra witness data to the coinbase input that triggers the846# same validation rejection but keeps the block under the weight limit847# so it can be sent via P2P.848relayable_block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a' * 100_000)850# Ensure it's relayable by weight851assert_greater_than_or_equal(MAX_BLOCK_WEIGHT, relayable_block.get_weight())853# Send over P2P and expect rejection for the same reason854test_witness_block(self.nodes[0], self.test_node, relayable_block,855accepted=False, reason='bad-witness-nonce-size')857# Node should still be on the previous tip858assert_not_equal(self.nodes[0].getbestblockhash(), relayable_block.hash_hex)860# Now fix the block by removing the extra witness data861relayable_block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.pop()863# Confirm the block is still relayable by weight864assert relayable_block.get_weight() <= MAX_BLOCK_WEIGHT866# Send the corrected block and expect acceptance867test_witness_block(self.nodes[0], self.test_node, relayable_block, accepted=True)868assert_equal(self.nodes[0].getbestblockhash(), relayable_block.hash_hex)870# Now make sure that malleating the witness reserved value doesn't871# result in a block permanently marked bad.872block = self.build_next_block()873add_witness_commitment(block)874block.solve()876# Change the nonce -- should not cause the block to be permanently877# failed878block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(1)]879test_witness_block(self.nodes[0], self.test_node, block, accepted=False, reason='bad-witness-merkle-match')881# Changing the witness reserved value doesn't change the block hash882block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(0)]883test_witness_block(self.nodes[0], self.test_node, block, accepted=True)885@subtest886def test_witness_block_size(self):887# TODO: Test that non-witness carrying blocks can't exceed 1MB888# Skipping this test for now; this is covered in feature_block.py890# Test that witness-bearing blocks are limited at ceil(base + wit/4) <= 1MB.891block = self.build_next_block()893assert len(self.utxo) > 0895# Create a P2WSH transaction.896# The witness script will be a bunch of OP_2DROP's, followed by OP_TRUE.897# This should give us plenty of room to tweak the spending tx's898# virtual size.899NUM_DROPS = 200 # 201 max ops per script!900NUM_OUTPUTS = 50902witness_script = CScript([OP_2DROP] * NUM_DROPS + [OP_TRUE])903script_pubkey = script_to_p2wsh_script(witness_script)905prevout = COutPoint(self.utxo[0].sha256, self.utxo[0].n)906value = self.utxo[0].nValue908parent_tx = CTransaction()909parent_tx.vin.append(CTxIn(prevout, b""))910child_value = int(value / NUM_OUTPUTS)911for _ in range(NUM_OUTPUTS):912parent_tx.vout.append(CTxOut(child_value, script_pubkey))913parent_tx.vout[0].nValue -= 50000914assert parent_tx.vout[0].nValue > 0916child_tx = CTransaction()917for i in range(NUM_OUTPUTS):918child_tx.vin.append(CTxIn(COutPoint(parent_tx.txid_int, i), b""))919child_tx.vout = [CTxOut(value - 100000, CScript([OP_TRUE]))]920for _ in range(NUM_OUTPUTS):921child_tx.wit.vtxinwit.append(CTxInWitness())922child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a' * 195] * (2 * NUM_DROPS) + [witness_script]923self.update_witness_block_with_transactions(block, [parent_tx, child_tx])925additional_bytes = MAX_BLOCK_WEIGHT - block.get_weight()926i = 0927while additional_bytes > 0:928# Add some more bytes to each input until we hit MAX_BLOCK_WEIGHT+1929extra_bytes = min(additional_bytes + 1, 55)930block.vtx[-1].wit.vtxinwit[int(i / (2 * NUM_DROPS))].scriptWitness.stack[i % (2 * NUM_DROPS)] = b'a' * (195 + extra_bytes)931additional_bytes -= extra_bytes932i += 1934block.vtx[0].vout.pop() # Remove old commitment935add_witness_commitment(block)936block.solve()937assert_equal(block.get_weight(), MAX_BLOCK_WEIGHT + 1)938# Make sure that our test case would exceed the old max-network-message939# limit940assert len(block.serialize()) > 2 * 1024 * 1024942test_witness_block(self.nodes[0], self.test_node, block, accepted=False, reason='bad-blk-weight')944# Now resize the second transaction to make the block fit.945cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0])946block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a' * (cur_length - 1)947block.vtx[0].vout.pop()948add_witness_commitment(block)949block.solve()950assert_equal(block.get_weight(), MAX_BLOCK_WEIGHT)952test_witness_block(self.nodes[0], self.test_node, block, accepted=True)954# Update available utxo's955self.utxo.pop(0)956self.utxo.append(UTXO(block.vtx[-1].txid_int, 0, block.vtx[-1].vout[0].nValue))958@subtest959def test_submit_block(self):960"""Test that submitblock adds the nonce automatically when possible."""961block = self.build_next_block()963# Try using a custom nonce and then don't supply it.964# This shouldn't possibly work.965add_witness_commitment(block, nonce=1)966block.vtx[0].wit = CTxWitness() # drop the nonce967block.solve()968assert_equal('bad-witness-merkle-match', self.nodes[0].submitblock(block.serialize().hex()))969assert_not_equal(self.nodes[0].getbestblockhash(), block.hash_hex)971# Now redo commitment with the standard nonce, but let bitcoind fill it in.972add_witness_commitment(block, nonce=0)973block.vtx[0].wit = CTxWitness()974block.solve()975assert_equal(None, self.nodes[0].submitblock(block.serialize().hex()))976assert_equal(self.nodes[0].getbestblockhash(), block.hash_hex)978# This time, add a tx with non-empty witness, but don't supply979# the commitment.980block_2 = self.build_next_block()982add_witness_commitment(block_2)984block_2.solve()986# Drop commitment and nonce -- submitblock should not fill in.987block_2.vtx[0].vout.pop()988block_2.vtx[0].wit = CTxWitness()990assert_equal('bad-txnmrklroot', self.nodes[0].submitblock(block_2.serialize().hex()))991# Tip should not advance!992assert_not_equal(self.nodes[0].getbestblockhash(), block_2.hash_hex)994@subtest995def test_extra_witness_data(self):996"""Test extra witness data in a transaction."""998block = self.build_next_block()1000witness_script = CScript([OP_DROP, OP_TRUE])
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.