From cc434cbf583ec8d1b0f3aa504417231fdc81f33a Mon Sep 17 00:00:00 2001 From: kouloumos Date: Tue, 6 Sep 2022 20:52:41 +0300 Subject: [PATCH] wallet: fix sendall creates tx that fails tx-size check The `sendall` RPC doesn't use `CreateTransactionInternal`as the rest of the wallet RPCs and it never checks against the tx-size mempool limit. Add a check for tx-size as well as test coverage for that case. --- src/wallet/rpc/spend.cpp | 5 +++++ test/functional/wallet_sendall.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp index 68e392790a0..e38b13624c2 100644 --- a/src/wallet/rpc/spend.cpp +++ b/src/wallet/rpc/spend.cpp @@ -1414,6 +1414,11 @@ RPCHelpMan sendall() } } + // If this transaction is too large, e.g. because the wallet has many UTXOs, it will be rejected by the node's mempool. + if (tx_size.weight > MAX_STANDARD_TX_WEIGHT) { + throw JSONRPCError(RPC_WALLET_ERROR, "Transaction too large."); + } + CAmount output_amounts_claimed{0}; for (const CTxOut& out : rawTx.vout) { output_amounts_claimed += out.nValue; diff --git a/test/functional/wallet_sendall.py b/test/functional/wallet_sendall.py index f24329f7b34..db4f32fe161 100755 --- a/test/functional/wallet_sendall.py +++ b/test/functional/wallet_sendall.py @@ -276,6 +276,20 @@ class SendallTest(BitcoinTestFramework): recipients=[self.remainder_target], fee_rate=100000) + # This tests needs to be the last one otherwise @cleanup will fail with "Transaction too large" error + def sendall_fails_with_transaction_too_large(self): + self.log.info("Test that sendall fails if resulting transaction is too large") + # create many inputs + outputs = {self.wallet.getnewaddress(): 0.000025 for _ in range(1600)} + self.def_wallet.sendmany(amounts=outputs) + self.generate(self.nodes[0], 1) + + assert_raises_rpc_error( + -4, + "Transaction too large.", + self.wallet.sendall, + recipients=[self.remainder_target]) + def run_test(self): self.nodes[0].createwallet("activewallet") self.wallet = self.nodes[0].get_wallet_rpc("activewallet") @@ -327,5 +341,8 @@ class SendallTest(BitcoinTestFramework): # Sendall fails when providing a fee that is too high self.sendall_fails_on_high_fee() + # Sendall fails when many inputs result to too large transaction + self.sendall_fails_with_transaction_too_large() + if __name__ == '__main__': SendallTest().main()