-
Notifications
You must be signed in to change notification settings - Fork 38.7k
wallet: fix sendall creates tx that fails tx-size check #26024
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ishaanam
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
It may be out of the scope of this PR to fix this, but I wanted to note that it seems like there are a few other checks that CreateTransactionInternal performs that aren't implemented in sendall but that I think would still be relevant. Namely:
- whether the feerate exceeds the default maximum feerate set by the user
- whether the tx will pass the mempool's chain limits
There is already this check against the
My understanding is that this is not a problem because this RPC only uses confirmed UTXOs. |
I meant this check, which checks that the total fee is not greater than the maximum fee (set using -maxtxfee). Earlier I should have said fee instead of feerate. |
|
ACK 8d822033bcdf6888b900d5a65ff21f3d8b9d30d5 |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
glozow
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 8d822033bcdf6888b900d5a65ff21f3d8b9d30d5
Agree we should stop sendall from creating a nonstandard tx. I think a more long term solution would be to still enable sendall to do what it's supposed to do, but create multiple transactions.
test/functional/wallet_sendall.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sendall being able to create multiple transactions would also automatically resolve this problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you see this multiple transactions capability to be helpful on any other scenario except of when the wallet has many UTXOs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. But it seems quite limiting to just not be able to sendall when the wallet gets bigger. I might be wrong but isn't consolidation one of its use cases? And it's a bit ugly to not be able to use cleanup after this test. Anyway I don't want to hold up this PR, so feel free to resolve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was more of a curiosity question. Your argument seems valid, as per the current functional test, you need ~1600 inputs to reach the limit.
8d82203 to
2b4fc04
Compare
Good catch, I see that this change is now #26084. Force pushed only to add more context to the added check. |
|
ACK 2b4fc04916e3ed43fcf7297ef6d7c9d71148c844 |
src/wallet/rpc/spend.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the error code should not indicate that the wallet has insufficient funds.
| throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Transaction too large."); | |
| throw JSONRPCError(RPC_WALLET_ERROR, "Transaction too large."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially tracked what error code the same check was returning from CreateTransactionInternal.
I now see that the 2 paths to call CreateTransaction return a different error code:
RPC_WALLET_INSUFFICIENT_FUNDS < SendMoney < CreateTransaction < CreateTransactionInternal
bitcoin/src/wallet/rpc/spend.cpp
Lines 159 to 162 in 718304d
| auto res = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, coin_control, true); | |
| if (!res) { | |
| throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, util::ErrorString(res).original); | |
| } |
RPC_WALLET_ERROR < FundTransaction < CreateTransaction < CreateTransactionInternal
bitcoin/src/wallet/rpc/spend.cpp
Lines 702 to 704 in 718304d
| if (!FundTransaction(wallet, tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) { | |
| throw JSONRPCError(RPC_WALLET_ERROR, error.original); | |
| } |
I am not sure if I am missing something but it seems that there is ambiguity. Probably because CreateTransactionInternal includes a variety of checks that in the end need to be represented with a single error code.
For example, a failed fee estimation is returned differently based on the RPC
bitcoin/test/functional/wallet_fallbackfee.py
Lines 27 to 29 in 718304d
| assert_raises_rpc_error(-6, "Fee estimation failed", lambda: self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)) | |
| assert_raises_rpc_error(-4, "Fee estimation failed", lambda: self.nodes[0].fundrawtransaction(self.nodes[0].createrawtransaction([], {self.nodes[0].getnewaddress(): 1}))) | |
| assert_raises_rpc_error(-6, "Fee estimation failed", lambda: self.nodes[0].sendmany("", {self.nodes[0].getnewaddress(): 1})) |
Nevertheless, I agree with you that in this case RPC_WALLET_ERROR is more appropriate. I will change it together with the needed rebase.
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.
w0xlt
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 2b4fc04
2b4fc04 to
cc434cb
Compare
w0xlt
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reACK cc434cb
|
re ACK cc434cb via range-diff. Changes were addressing #26024 (comment) and #26024 (comment). |
|
ACK cc434cb |
…e check cc434cb wallet: fix sendall creates tx that fails tx-size check (kouloumos) Pull request description: Fixes bitcoin#26011 The `sendall` RPC doesn't use `CreateTransactionInternal` as the rest of the wallet RPCs. [This has already been discussed in the original PR](bitcoin#24118 (comment)). By not going through that path, it never checks the transaction's weight against the maximum tx weight for transactions we're willing to relay. https://github.com/bitcoin/bitcoin/blob/447f50e4aed9a8b1d80e1891cda85801aeb80b4e/src/wallet/spend.cpp#L1013-L1018 This PR adds a check for tx-size as well as test coverage for that case. _Note: It seems that the test takes a bit of time on slower machines, I'm not sure if dropping it might be for the better._ ACKs for top commit: glozow: re ACK cc434cb via range-diff. Changes were addressing bitcoin#26024 (comment) and bitcoin#26024 (comment). achow101: ACK cc434cb w0xlt: reACK bitcoin@cc434cb Tree-SHA512: 64a1d8f2c737b39f3ccee90689eda1dd9c1b65f11b2c7bc0ec8bfe72f0202ce90ab4033bb0ecfc6080af8c947575059588a00938fe48e7fd553f7fb5ee03b3cc
|
post-merge ACK cc434cb Thanks for catching this. |
Fixes #26011
The
sendallRPC doesn't useCreateTransactionInternalas the rest ofthe wallet RPCs. This has already been discussed in the original PR.
By not going through that path, it never checks the transaction's weight
against the maximum tx weight for transactions we're willing to relay.
bitcoin/src/wallet/spend.cpp
Lines 1013 to 1018 in 447f50e
This PR adds a check for tx-size as well as test coverage for that case.
Note: It seems that the test takes a bit of time on slower machines,
I'm not sure if dropping it might be for the better.