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.
251@cleanup252def spend_inputs_with_different_versions_default_version(self):253self.log.info("Test spending a pre-selected v3 input with the default version of transaction")255outputs = {self.alice.getnewaddress() : 2.0}256self.send_tx(self.charlie, [], outputs, 3)258# alice spends her output259alice_unspent = self.alice.listunspent(minconf=0)[0]260outputs = {self.alice.getnewaddress() : alice_unspent['amount'] - Decimal(0.00000120)}261alice_tx = self.alice.createrawtransaction(inputs=[alice_unspent], outputs=outputs) # don't set the version here263assert_raises_rpc_error(264-4,265"Can't spend unconfirmed version 3 pre-selected input with a version 2 tx",266self.alice.fundrawtransaction,267alice_tx268)270@cleanup271def v3_tx_evicted_from_mempool_by_sibling(self):272self.log.info("Test v3 transaction evicted because of conflicting sibling")274# unconfirmed v3 tx to alice & bob275outputs = {self.alice.getnewaddress() : 2.0, self.bob.getnewaddress() : 2.0}276self.send_tx(self.charlie, [], outputs, 3)278# alice spends her output with a v3 transaction279alice_unspent = self.alice.listunspent(minconf=0)[0]280alice_fee = Decimal(0.00000120)281outputs = {self.alice.getnewaddress() : alice_unspent['amount'] - alice_fee}282alice_txid = self.send_tx(self.alice, [alice_unspent], outputs, 3)284# bob tries to spend money285bob_unspent = self.bob.listunspent(minconf=0)[0]286outputs = {self.bob.getnewaddress() : bob_unspent['amount'] - Decimal(0.00010120)}287bob_txid = self.send_tx(self.bob, [bob_unspent], outputs, 3)289assert_equal(self.alice.gettransaction(alice_txid)['mempoolconflicts'], [bob_txid])291self.log.info("Test that re-submitting Alice's transaction with a higher fee removes bob's tx as a mempool conflict")292fee_delta = Decimal(0.00030120)293outputs = {self.alice.getnewaddress() : alice_unspent['amount'] - fee_delta}294alice_txid = self.send_tx(self.alice, [alice_unspent], outputs, 3)295assert_equal(self.alice.gettransaction(alice_txid)['mempoolconflicts'], [])297@cleanup298def v3_conflict_removed_from_mempool(self):299self.log.info("Test a v3 conflict being removed")300# send a v2 output to alice and confirm it301txid = self.charlie.sendall([self.alice.getnewaddress()])["txid"]302assert_equal(self.charlie.gettransaction(txid, verbose=True)["decoded"]["version"], 2)303self.generate(self.nodes[0], 1)304# create a v3 tx to alice and bob305outputs = {self.alice.getnewaddress() : 2.0, self.bob.getnewaddress() : 2.0}306self.send_tx(self.charlie, [], outputs, 3)308alice_v2_unspent = self.alice.listunspent(minconf=1)[0]309alice_unspent = self.alice.listunspent(minconf=0, maxconf=0)[0]311# alice spends both of her outputs312outputs = {self.charlie.getnewaddress() : alice_v2_unspent['amount'] + alice_unspent['amount'] - Decimal(0.00005120)}313self.send_tx(self.alice, [alice_v2_unspent, alice_unspent], outputs, 3)314# bob can't create a transaction315outputs = {self.bob.getnewaddress() : 1.999}316bob_tx = self.bob.createrawtransaction(inputs=[], outputs=outputs, version=3)318assert_raises_rpc_error(319-4,320"Insufficient funds",321self.bob.fundrawtransaction,322bob_tx, {'include_unsafe': True}323)324# alice fee-bumps her tx so it only spends the v2 utxo325outputs = {self.charlie.getnewaddress() : alice_v2_unspent['amount'] - Decimal(0.00015120)}326self.send_tx(self.alice, [alice_v2_unspent], outputs, 2)327# bob can now create a transaction328outputs = {self.bob.getnewaddress() : 1.999}329self.send_tx(self.bob, [], outputs, 3)331@cleanup332def mempool_conflicts_removed_when_v3_conflict_removed(self):333self.log.info("Test that we remove v3 txs from mempool_conflicts correctly")334# send a v2 output to alice and confirm it335txid = self.charlie.sendall([self.alice.getnewaddress()])["txid"]336assert_equal(self.charlie.gettransaction(txid, verbose=True)["decoded"]["version"], 2)337self.generate(self.nodes[0], 1)338# create a v3 tx to alice and bob339outputs = {self.alice.getnewaddress() : 2.0, self.bob.getnewaddress() : 2.0}340self.send_tx(self.charlie, [], outputs, 3)342alice_v2_unspent = self.alice.listunspent(minconf=1)[0]343alice_unspent = self.alice.listunspent(minconf=0, maxconf=0)[0]344# bob spends his utxo345inputs=[]346outputs = {self.bob.getnewaddress() : 1.999}347bob_txid = self.send_tx(self.bob, inputs, outputs, 3)348# alice spends both of her utxos, replacing bob's tx349outputs = {self.charlie.getnewaddress() : alice_v2_unspent['amount'] + alice_unspent['amount'] - Decimal(0.00005120)}350alice_txid = self.send_tx(self.alice, [alice_v2_unspent, alice_unspent], outputs, 3)351# bob's tx now has a mempool conflict352assert_equal(self.bob.gettransaction(bob_txid)['mempoolconflicts'], [alice_txid])353# alice fee-bumps her tx so it only spends the v2 utxo354outputs = {self.charlie.getnewaddress() : alice_v2_unspent['amount'] - Decimal(0.00015120)}355self.send_tx(self.alice, [alice_v2_unspent], outputs, 2)356# bob's tx now has non conflicts and can be rebroadcast357bob_tx = self.bob.gettransaction(bob_txid)358assert_equal(bob_tx['mempoolconflicts'], [])359self.bob.sendrawtransaction(bob_tx['hex'])361@cleanup362def max_tx_weight(self):363self.log.info("Test max v3 transaction weight.")365tx = CTransaction()366tx.version = 3 # make this a truc tx367# increase tx weight almost to the max truc size368self.bulk_tx(tx, 5, TRUC_MAX_VSIZE - 100)370assert_raises_rpc_error(371-4,372"The inputs size exceeds the maximum weight. Please try sending a smaller amount or manually consolidating your wallet's UTXOs",373self.charlie.fundrawtransaction,374tx.serialize_with_witness().hex(),375{'include_unsafe' : True}376)378tx.version = 2379self.charlie.fundrawtransaction(tx.serialize_with_witness().hex())381@cleanup382def max_tx_child_weight(self):383self.log.info("Test max v3 transaction child weight.")385outputs = {self.alice.getnewaddress() : 10}386self.send_tx(self.charlie, [], outputs, 3)388tx = CTransaction()389tx.version = 3391self.bulk_tx(tx, 5, TRUC_CHILD_MAX_VSIZE - 100)393assert_raises_rpc_error(394-4,395"The inputs size exceeds the maximum weight. Please try sending a smaller amount or manually consolidating your wallet's UTXOs",396self.alice.fundrawtransaction,397tx.serialize_with_witness().hex(),398{'include_unsafe' : True}399)401self.generate(self.nodes[0], 1)402self.alice.fundrawtransaction(tx.serialize_with_witness().hex())404@cleanup405def user_input_weight_not_overwritten(self):406self.log.info("Test that the user-input tx weight is not overwritten by the truc maximum")408tx = CTransaction()409tx.version = 3411self.bulk_tx(tx, 5, int(TRUC_MAX_VSIZE/2))413assert_raises_rpc_error(414-4,415"Maximum transaction weight is less than transaction weight without inputs",416self.charlie.fundrawtransaction,417tx.serialize_with_witness().hex(),418{'include_unsafe' : True, 'max_tx_weight' : int(TRUC_MAX_VSIZE/2)}419)421@cleanup422def user_input_weight_not_overwritten_v3_child(self):423self.log.info("Test that the user-input tx weight is not overwritten by the truc child maximum")425outputs = {self.alice.getnewaddress() : 10}426self.send_tx(self.charlie, [], outputs, 3)428tx = CTransaction()429tx.version = 3431self.bulk_tx(tx, 5, int(TRUC_CHILD_MAX_VSIZE/2))433assert_raises_rpc_error(434-4,435"Maximum transaction weight is less than transaction weight without inputs",436self.alice.fundrawtransaction,437tx.serialize_with_witness().hex(),438{'include_unsafe' : True, 'max_tx_weight' : int(TRUC_CHILD_MAX_VSIZE/2)}439)441self.generate(self.nodes[0], 1)442self.alice.fundrawtransaction(tx.serialize_with_witness().hex())444@cleanup445def createpsbt_v3(self):446self.log.info("Test setting version to 3 with createpsbt")448outputs = {self.alice.getnewaddress() : 10}449psbt = self.charlie.createpsbt(inputs=[], outputs=outputs, version=3)450assert_equal(self.charlie.decodepsbt(psbt)["tx_version"], 3)452@cleanup453def send_v3(self):454self.log.info("Test setting version to 3 with send")456outputs = {self.alice.getnewaddress() : 10}457tx_hex = self.charlie.send(outputs=outputs, add_to_wallet=False, version=3)["hex"]458assert_equal(self.charlie.decoderawtransaction(tx_hex)["version"], 3)460@cleanup461def sendall_v3(self):462self.log.info("Test setting version to 3 with sendall")464tx_hex = self.charlie.sendall(recipients=[self.alice.getnewaddress()], version=3, add_to_wallet=False)["hex"]465assert_equal(self.charlie.decoderawtransaction(tx_hex)["version"], 3)467@cleanup468def sendall_with_unconfirmed_v3(self):469self.log.info("Test setting version to 3 with sendall + unconfirmed inputs")471outputs = {self.alice.getnewaddress(): 2.00001 for _ in range(4)}473self.send_tx(self.charlie, [], outputs, 2)474self.generate(self.nodes[0], 1)476unspents = self.alice.listunspent()478# confirmed v2 utxos479outputs = {self.alice.getnewaddress() : 2.0}480confirmed_v2 = self.send_tx(self.alice, [unspents[0]], outputs, 2)482# confirmed v3 utxos483outputs = {self.alice.getnewaddress() : 2.0}484confirmed_v3 = self.send_tx(self.alice, [unspents[1]], outputs, 3)486self.generate(self.nodes[0], 1)488# unconfirmed v2 utxos489outputs = {self.alice.getnewaddress() : 2.0}490unconfirmed_v2 = self.send_tx(self.alice, [unspents[2]], outputs, 2)492# unconfirmed v3 utxos493outputs = {self.alice.getnewaddress() : 2.0}494unconfirmed_v3 = self.send_tx(self.alice, [unspents[3]], outputs, 3)496# Test that the only unconfirmed inputs this v3 tx spends are v3497tx_hex = self.alice.sendall([self.bob.getnewaddress()], version=3, add_to_wallet=False, minconf=0)["hex"]499decoded_tx = self.alice.decoderawtransaction(tx_hex)500decoded_vin_txids = [txin["txid"] for txin in decoded_tx["vin"]]
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.