Skip to content

Conversation

@kouloumos
Copy link
Contributor

Fixes #26011

The sendall RPC doesn't use CreateTransactionInternal as the rest of
the 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

// Limit size
if ((sign && GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT) ||
(!sign && tx_sizes.weight > MAX_STANDARD_TX_WEIGHT))
{
return util::Error{_("Transaction too large")};
}

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.

@DrahtBot DrahtBot added the Wallet label Sep 6, 2022
Copy link
Contributor

@ishaanam ishaanam left a 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

@kouloumos
Copy link
Contributor Author

  • whether the feerate exceeds the default maximum feerate set by the user

There is already this check against the fee_rate passed by the user. I can't find any other relevant check at CreateTransactionInternal. Could you give more details on that?

  • whether the tx will pass the mempool's chain limits

My understanding is that this is not a problem because this RPC only uses confirmed UTXOs.

@ishaanam
Copy link
Contributor

I can't find any other relevant check at CreateTransactionInternal. Could you give more details on that?

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.

@achow101
Copy link
Member

ACK 8d822033bcdf6888b900d5a65ff21f3d8b9d30d5

@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 14, 2022

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

No conflicts as of last run.

Copy link
Member

@glozow glozow left a 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.

Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Contributor Author

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.

@kouloumos kouloumos force-pushed the wallet-fix-sendall-tx-size branch from 8d82203 to 2b4fc04 Compare September 14, 2022 18:45
@kouloumos
Copy link
Contributor Author

which checks that the total fee is not greater than the maximum fee (set using -maxtxfee).

Good catch, I see that this change is now #26084.

Force pushed only to add more context to the added check.

@achow101
Copy link
Member

ACK 2b4fc04916e3ed43fcf7297ef6d7c9d71148c844

Copy link
Contributor

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.

Suggested change
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Transaction too large.");
throw JSONRPCError(RPC_WALLET_ERROR, "Transaction too large.");

Copy link
Contributor Author

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

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

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

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.
Copy link
Contributor

@w0xlt w0xlt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 2b4fc04

@kouloumos kouloumos force-pushed the wallet-fix-sendall-tx-size branch from 2b4fc04 to cc434cb Compare September 15, 2022 10:40
Copy link
Contributor

@w0xlt w0xlt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reACK cc434cb

@kouloumos
Copy link
Contributor Author

Thank you all for the reviews!

A rebase was needed after the merge of #26084.
Also force pushed to change the error code from RPC_WALLET_INSUFFICIENT_FUNDS to RPC_WALLET_ERROR based on @ishaanam's comment.

@glozow
Copy link
Member

glozow commented Sep 15, 2022

re ACK cc434cb via range-diff. Changes were addressing #26024 (comment) and #26024 (comment).

@achow101
Copy link
Member

ACK cc434cb

@achow101 achow101 merged commit a56876e into bitcoin:master Sep 15, 2022
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 15, 2022
…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
@murchandamus
Copy link
Contributor

post-merge ACK cc434cb

Thanks for catching this.

@bitcoin bitcoin locked and limited conversation to collaborators Sep 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sendall creates tx that fails tx-size mempool check

8 participants