From 5baedc33519661af9d19efcefd23dca8998d2547 Mon Sep 17 00:00:00 2001 From: furszy Date: Fri, 5 Aug 2022 12:51:44 -0300 Subject: wallet: remove fetch pre-selected-inputs responsibility from SelectCoins so if there is an error in any of the pre-set coins, we can fail right away without computing the wallet available coins set (calling `AvailableCoins`) which is a slow operation as it goes through the entire wallet's txes map. ---------------------- And to make the Coin Selection flow cleared, have decoupled SelectCoins in two functions: 1) AutomaticCoinSelection. 2) SelectCoins. 1) AutomaticCoinSelection: Receives a set of coins and selects the best subset of them to cover the target amount. 2) SelectCoins In charge of select all the user manually selected coins first ("pre-set inputs"), and if coin_control 'm_allow_other_inputs=true', call 'AutomaticCoinSelection' to select a subset of coins owned by the wallet to cover for the target - preset_inputs.total_amount remaining value. --- test/functional/rpc_fundrawtransaction.py | 6 ++++-- test/functional/rpc_psbt.py | 2 +- test/functional/wallet_send.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'test/functional') diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py index 79ff25efd9..54b42667bb 100755 --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -406,7 +406,9 @@ class RawTransactionsTest(BitcoinTestFramework): def test_invalid_input(self): self.log.info("Test fundrawtxn with an invalid vin") - inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin! + txid = "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1" + vout = 0 + inputs = [ {'txid' : txid, 'vout' : vout} ] #invalid vin! outputs = { self.nodes[0].getnewaddress() : 1.0} rawtx = self.nodes[2].createrawtransaction(inputs, outputs) assert_raises_rpc_error(-4, "Unable to find UTXO for external input", self.nodes[2].fundrawtransaction, rawtx) @@ -1011,7 +1013,7 @@ class RawTransactionsTest(BitcoinTestFramework): # An external input without solving data should result in an error raw_tx = wallet.createrawtransaction([ext_utxo], {self.nodes[0].getnewaddress(): ext_utxo["amount"] / 2}) - assert_raises_rpc_error(-4, "Insufficient funds", wallet.fundrawtransaction, raw_tx) + assert_raises_rpc_error(-4, "Not solvable pre-selected input COutPoint(%s, %s)" % (ext_utxo["txid"][0:10], ext_utxo["vout"]), wallet.fundrawtransaction, raw_tx) # Error conditions assert_raises_rpc_error(-5, "'not a pubkey' is not hex", wallet.fundrawtransaction, raw_tx, {"solving_data": {"pubkeys":["not a pubkey"]}}) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 3b78a7d095..b79b8f5187 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -657,7 +657,7 @@ class PSBTTest(BitcoinTestFramework): ext_utxo = self.nodes[0].listunspent(addresses=[addr])[0] # An external input without solving data should result in an error - assert_raises_rpc_error(-4, "Insufficient funds", wallet.walletcreatefundedpsbt, [ext_utxo], {self.nodes[0].getnewaddress(): 15}) + assert_raises_rpc_error(-4, "Not solvable pre-selected input COutPoint(%s, %s)" % (ext_utxo["txid"][0:10], ext_utxo["vout"]), wallet.walletcreatefundedpsbt, [ext_utxo], {self.nodes[0].getnewaddress(): 15}) # But funding should work when the solving data is provided psbt = wallet.walletcreatefundedpsbt([ext_utxo], {self.nodes[0].getnewaddress(): 15}, 0, {"add_inputs": True, "solving_data": {"pubkeys": [addr_info['pubkey']], "scripts": [addr_info["embedded"]["scriptPubKey"], addr_info["embedded"]["embedded"]["scriptPubKey"]]}}) diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py index 07baa0595e..fb759c153d 100755 --- a/test/functional/wallet_send.py +++ b/test/functional/wallet_send.py @@ -508,7 +508,7 @@ class WalletSendTest(BitcoinTestFramework): ext_utxo = ext_fund.listunspent(addresses=[addr])[0] # An external input without solving data should result in an error - self.test_send(from_wallet=ext_wallet, to_wallet=self.nodes[0], amount=15, inputs=[ext_utxo], add_inputs=True, psbt=True, include_watching=True, expect_error=(-4, "Insufficient funds")) + self.test_send(from_wallet=ext_wallet, to_wallet=self.nodes[0], amount=15, inputs=[ext_utxo], add_inputs=True, psbt=True, include_watching=True, expect_error=(-4, "Not solvable pre-selected input COutPoint(%s, %s)" % (ext_utxo["txid"][0:10], ext_utxo["vout"]))) # But funding should work when the solving data is provided res = self.test_send(from_wallet=ext_wallet, to_wallet=self.nodes[0], amount=15, inputs=[ext_utxo], add_inputs=True, psbt=True, include_watching=True, solving_data={"pubkeys": [addr_info['pubkey']], "scripts": [addr_info["embedded"]["scriptPubKey"], addr_info["embedded"]["embedded"]["scriptPubKey"]]}) -- cgit v1.2.3