mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
wallet: notify when preset + automatic inputs exceed max weight
This also avoids signing all inputs prior to erroring out.
This commit is contained in:
parent
2d21060af8
commit
72b226882f
@ -799,6 +799,13 @@ util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& av
|
||||
op_selection_result->RecalculateWaste(coin_selection_params.min_viable_change,
|
||||
coin_selection_params.m_cost_of_change,
|
||||
coin_selection_params.m_change_fee);
|
||||
|
||||
// Verify we haven't exceeded the maximum allowed weight
|
||||
int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
|
||||
if (op_selection_result->GetWeight() > max_inputs_weight) {
|
||||
return util::Error{_("The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. "
|
||||
"Please try sending a smaller amount or manually consolidating your wallet's UTXOs")};
|
||||
}
|
||||
}
|
||||
return op_selection_result;
|
||||
}
|
||||
|
@ -114,6 +114,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.test_add_inputs_default_value()
|
||||
self.test_preset_inputs_selection()
|
||||
self.test_weight_calculation()
|
||||
self.test_weight_limits()
|
||||
self.test_change_position()
|
||||
self.test_simple()
|
||||
self.test_simple_two_coins()
|
||||
@ -1312,6 +1313,38 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
self.nodes[2].unloadwallet("test_weight_calculation")
|
||||
|
||||
def test_weight_limits(self):
|
||||
self.log.info("Test weight limits")
|
||||
|
||||
self.nodes[2].createwallet("test_weight_limits")
|
||||
wallet = self.nodes[2].get_wallet_rpc("test_weight_limits")
|
||||
|
||||
outputs = []
|
||||
for _ in range(1472):
|
||||
outputs.append({wallet.getnewaddress(address_type="legacy"): 0.1})
|
||||
txid = self.nodes[0].send(outputs=outputs)["txid"]
|
||||
self.generate(self.nodes[0], 1)
|
||||
|
||||
# 272 WU per input (273 when high-s); picking 1471 inputs will exceed the max standard tx weight.
|
||||
rawtx = wallet.createrawtransaction([], [{wallet.getnewaddress(): 0.1 * 1471}])
|
||||
|
||||
# 1) Try to fund transaction only using the preset inputs
|
||||
input_weights = []
|
||||
for i in range(1471):
|
||||
input_weights.append({"txid": txid, "vout": i, "weight": 273})
|
||||
assert_raises_rpc_error(-4, "Transaction too large", wallet.fundrawtransaction, hexstring=rawtx, input_weights=input_weights)
|
||||
|
||||
# 2) Let the wallet fund the transaction
|
||||
assert_raises_rpc_error(-4, "The inputs size exceeds the maximum weight. Please try sending a smaller amount or manually consolidating your wallet's UTXOs",
|
||||
wallet.fundrawtransaction, hexstring=rawtx)
|
||||
|
||||
# 3) Pre-select some inputs and let the wallet fill-up the remaining amount
|
||||
inputs = input_weights[0:1000]
|
||||
assert_raises_rpc_error(-4, "The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. Please try sending a smaller amount or manually consolidating your wallet's UTXOs",
|
||||
wallet.fundrawtransaction, hexstring=rawtx, input_weights=inputs)
|
||||
|
||||
self.nodes[2].unloadwallet("test_weight_limits")
|
||||
|
||||
def test_include_unsafe(self):
|
||||
self.log.info("Test fundrawtxn with unsafe inputs")
|
||||
|
||||
|
@ -577,5 +577,39 @@ class WalletSendTest(BitcoinTestFramework):
|
||||
# but rounded to nearest integer, it should be the same as the target fee rate
|
||||
assert_equal(round(actual_fee_rate_sat_vb), target_fee_rate_sat_vb)
|
||||
|
||||
# Check tx creation size limits
|
||||
self.test_weight_limits()
|
||||
|
||||
def test_weight_limits(self):
|
||||
self.log.info("Test weight limits")
|
||||
|
||||
self.nodes[1].createwallet("test_weight_limits")
|
||||
wallet = self.nodes[1].get_wallet_rpc("test_weight_limits")
|
||||
|
||||
# Generate future inputs; 272 WU per input (273 when high-s).
|
||||
# Picking 1471 inputs will exceed the max standard tx weight.
|
||||
outputs = []
|
||||
for _ in range(1472):
|
||||
outputs.append({wallet.getnewaddress(address_type="legacy"): 0.1})
|
||||
self.nodes[0].send(outputs=outputs)
|
||||
self.generate(self.nodes[0], 1)
|
||||
|
||||
# 1) Try to fund transaction only using the preset inputs
|
||||
inputs = wallet.listunspent()
|
||||
assert_raises_rpc_error(-4, "Transaction too large",
|
||||
wallet.send, outputs=[{wallet.getnewaddress(): 0.1 * 1471}], options={"inputs": inputs, "add_inputs": False})
|
||||
|
||||
# 2) Let the wallet fund the transaction
|
||||
assert_raises_rpc_error(-4, "The inputs size exceeds the maximum weight. Please try sending a smaller amount or manually consolidating your wallet's UTXOs",
|
||||
wallet.send, outputs=[{wallet.getnewaddress(): 0.1 * 1471}])
|
||||
|
||||
# 3) Pre-select some inputs and let the wallet fill-up the remaining amount
|
||||
inputs = inputs[0:1000]
|
||||
assert_raises_rpc_error(-4, "The combination of the pre-selected inputs and the wallet automatic inputs selection exceeds the transaction maximum weight. Please try sending a smaller amount or manually consolidating your wallet's UTXOs",
|
||||
wallet.send, outputs=[{wallet.getnewaddress(): 0.1 * 1471}], options={"inputs": inputs, "add_inputs": True})
|
||||
|
||||
self.nodes[1].unloadwallet("test_weight_limits")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletSendTest().main()
|
||||
|
Loading…
Reference in New Issue
Block a user