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.
1501# So, the selection process, to cover the amount, will pick up the 'final_tx1' output as well, which is an output of the tx that this1502# new tx is replacing!. So, once we send it to the mempool, it will return a "bad-txns-spends-conflicting-tx"1503# because the input will no longer exist once the first tx gets replaced by this new one).1504funded_invalid = wallet.fundrawtransaction(raw_tx2, {'add_inputs': True, 'maxconf': 0, 'fee_rate': 10})['hex']1505final_invalid = wallet.signrawtransactionwithwallet(funded_invalid)['hex']1506assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, final_invalid)1508self.log.info("Craft a replacement adding inputs with highest depth possible")1509funded_tx2 = wallet.fundrawtransaction(raw_tx2, {'add_inputs': True, 'minconf': 2, 'fee_rate': 10})['hex']1510tx2_inputs = self.nodes[0].decoderawtransaction(funded_tx2)['vin']1511assert_greater_than_or_equal(len(tx2_inputs), 2)1512for vin in tx2_inputs:1513if vin['txid'] != unconfirmed_txid:1514assert_greater_than_or_equal(self.nodes[0].gettxout(vin['txid'], vin['vout'])['confirmations'], 2)1516final_tx2 = wallet.signrawtransactionwithwallet(funded_tx2)['hex']1517txid2 = self.nodes[0].sendrawtransaction(final_tx2)1519mempool = self.nodes[0].getrawmempool()1520assert txid1 not in mempool1521assert txid2 in mempool1523wallet.unloadwallet()1525def test_watchonly_cannot_grind_r(self):1526self.log.info("Test that a watchonly wallet will estimate higher fees for a tx than the wallet with private keys")1527self.nodes[0].createwallet("grind")1528wallet = self.nodes[0].get_wallet_rpc("grind")1529default_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)1531self.nodes[0].createwallet(wallet_name="grind_watchonly", disable_private_keys=True)1532watchonly = self.nodes[0].get_wallet_rpc("grind_watchonly")1533assert_equal(watchonly.importdescriptors(wallet.listdescriptors()["descriptors"])[0]["success"], True)1535# Send to legacy address type so that we will have an ecdsa signature with a measurable effect on the feerate1536default_wallet.sendtoaddress(wallet.getnewaddress(address_type="legacy"), 10)1537self.generate(self.nodes[0], 1)1539assert_equal(wallet.listunspent(), watchonly.listunspent())1541ret_addr = default_wallet.getnewaddress()1542tx = wallet.createrawtransaction([], [{ret_addr: 5}])1543funded = wallet.fundrawtransaction(hexstring=tx, fee_rate=10)1545watchonly_funded = watchonly.fundrawtransaction(hexstring=tx, fee_rate=10)1546assert_greater_than(watchonly_funded["fee"], funded["fee"])1548def test_cannot_cover_fees(self):1549self.log.info("Test error message when transaction amount exceeds available balance when fees are included")1550default_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)1552self.nodes[1].createwallet("cannot_cover_fees")1553wallet = self.nodes[1].get_wallet_rpc("cannot_cover_fees")1555# Set up wallet with 2 utxos: 0.3 BTC and 0.15 BTC1556default_wallet.sendtoaddress(wallet.getnewaddress(), 0.3)1557txid2 = default_wallet.sendtoaddress(wallet.getnewaddress(), 0.15)1558self.generate(self.nodes[0], 1)1559vout2 = next(utxo["vout"] for utxo in wallet.listunspent() if utxo["txid"] == txid2)1560amount_with_fee_err_msg = "The total exceeds your balance when the {} transaction fee is included."1562self.log.info("Test without preselected inputs")1563self.log.info("Attempt to send 0.45 BTC without SFFO")1564rawtx = wallet.createrawtransaction(inputs=[], outputs=[{default_wallet.getnewaddress(): 0.45}])1565assert_raises_rpc_error(-4, amount_with_fee_err_msg.format("0.00000042"), wallet.fundrawtransaction, rawtx, options={"fee_rate":1})1567self.log.info("Send 0.45 BTC with SFFO")1568wallet.fundrawtransaction(rawtx, options={"subtractFeeFromOutputs":[0]})1570self.log.info("Attempt to send 0.45 BTC by restricting coin selection with minconf=6")1571assert_raises_rpc_error(-4, "Insufficient funds", wallet.fundrawtransaction, rawtx, options={"minconf":6})1573self.log.info("Test with preselected inputs")1574self.log.info("Attempt to send 0.45 BTC preselecting 0.15 BTC utxo")1575rawtx = wallet.createrawtransaction(inputs=[{"txid": txid2, "vout": vout2}], outputs=[{default_wallet.getnewaddress(): 0.45}])1576assert_raises_rpc_error(-4, amount_with_fee_err_msg.format("0.00000042"), wallet.fundrawtransaction, rawtx, options={"fee_rate":1})1578self.log.info("Send 0.45 BTC preselecting 0.15 BTC utxo with SFFO")1579wallet.fundrawtransaction(hexstring=rawtx, options={"subtractFeeFromOutputs":[0]})1581self.log.info("Attempt to send 0.15 BTC using only the 0.15 BTC preselected utxo")1582rawtx = wallet.createrawtransaction(inputs=[{"txid": txid2, "vout": vout2}], outputs=[{default_wallet.getnewaddress(): 0.15}])1583assert_raises_rpc_error(-4, ERR_NOT_ENOUGH_PRESET_INPUTS, wallet.fundrawtransaction, rawtx, options={"fee_rate":1, "add_inputs":False})1584self.log.info("Send 0.15 BTC using only the 0.15 BTC preselected utxo with SFFO")1585wallet.fundrawtransaction(hexstring=rawtx, options={"subtractFeeFromOutputs":[0], "add_inputs":False})1588if __name__ == '__main__':1589RawTransactionsTest(__file__).main()
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.