Skip to content
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

wallet: Error with "Transaction too large" if the funded tx will end up being too large after signing #20536

Merged
merged 3 commits into from Mar 8, 2021

Conversation

achow101
Copy link
Member

Currently the Transaction too large is calculated on the transaction that is returned from CreateTransaction. This does not make sense for when CreateTransaction is being used for fundrawtransaction as no signing occurs so the final returned transaction is missing signatures. Thus users may successfully fund a transaction but fail to broadcast it after it has been fully signed.

So instead we should figure out whether the transaction we are funding will be too large after it is signed. We can do this by having CalculateMaximumSignedTxSize also return the transaction weight and then comparing that weight against the maximum weight.

Our max weight check in CreateTransaction only worked if the transaction
was fully signed. However if we are funding a transaction, it is
possible that the tx weight will be too large for a standard tx. In that
case, we should also fail. So we use the tx weight returned by
CalculateMaximumSignedTxSize and check against the limit for those
transactions.
@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 30, 2020

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@decryp2kanon
Copy link
Contributor

Concept ACK

@laanwj
Copy link
Member

laanwj commented Dec 17, 2020

Concept ACK, thanks for adding a test.

@@ -3068,7 +3068,8 @@ bool CWallet::CreateTransactionInternal(
tx = MakeTransactionRef(std::move(txNew));

// Limit size
if (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT)
if ((sign && GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT) ||
(!sign && tx_sizes.second > MAX_STANDARD_TX_WEIGHT))
Copy link
Member

Choose a reason for hiding this comment

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

do we need both the checks because this could end up being -1?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have both checks here because the estimate is an overestimate, so I would prefer to use the accurate weight when possible, i.e. when the transaction is signed.

If BnB is used, the test will fail because the transaction is too large.
@instagibbs
Copy link
Member

Seems strictly better, simple, plus test coverage.

ACK 48a0319

Copy link
Contributor

@meshcollider meshcollider left a comment

Choose a reason for hiding this comment

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

utACK 48a0319

Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

utACK with nits 48a0319

@@ -1594,14 +1594,15 @@ bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScri
return true;
}

int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
// Returns pair of vsize and weight
std::pair<int64_t, int64_t> CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig)
Copy link
Contributor

Choose a reason for hiding this comment

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

I have noticed that this codebase often uses unnamed fields in a specific order rather than named fields. Wouldn't it be advantageous to define transfer objects that have named fields to be more explicit in what is retrieved from response objects?

Copy link
Member Author

Choose a reason for hiding this comment

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

For something like this, I feel like it is overkill to introduce a struct or class for these, especially since it is used in only one place.

@@ -1610,13 +1611,16 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
}

// txouts needs to be in the order of tx.vin
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig)
std::pair<int64_t, int64_t> CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd find it more intuitive if this were two separate methods to get vsize and weight rather than the unnamed pair of values.

Copy link
Member Author

Choose a reason for hiding this comment

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

I did these as a single function because it's the same calculation.

@meshcollider meshcollider merged commit a8b0892 into bitcoin:master Mar 8, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 8, 2021
…e funded tx will end up being too large after signing

48a0319 Add a test that selects too large if BnB is used (Andrew Chow)
3e69939 Fail if maximum weight is too large (Andrew Chow)
51e2cd3 Have CalculateMaximumSignedTxSize also compute tx weight (Andrew Chow)

Pull request description:

  Currently the `Transaction too large` is calculated on the transaction that is returned from `CreateTransaction`. This does not make sense for when `CreateTransaction` is being used for `fundrawtransaction` as no signing occurs so the final returned transaction is missing signatures. Thus users may successfully fund a transaction but fail to broadcast it after it has been fully signed.

  So instead we should figure out whether the transaction we are funding will be too large after it is signed. We can do this by having `CalculateMaximumSignedTxSize` also return the transaction weight and then comparing that weight against the maximum weight.

ACKs for top commit:
  instagibbs:
    ACK bitcoin@48a0319
  meshcollider:
    utACK 48a0319
  Xekyo:
    utACK with nits 48a0319

Tree-SHA512: 1700c60b07f67e2d5c591c5ccd131ac9f1861fab3def961c3c9c4b3281ec1063fe8e4f0f7f1038cac72692340856406bcee8fb45c8104d2ad34357a0ec878ac7
maflcko pushed a commit that referenced this pull request Mar 16, 2021
…on_too_large

d09120b test: give fundraw more time for test_transaction_too_large (Jon Atack)

Pull request description:

  to hopefully fix timeouts from a new test added in 48a0319 of #20536 merged March 8, 2021

  seen locally when running via the test runner

  ```
  File "/home/jon/projects/bitcoin/bitcoin/test/functional/rpc_fundrawtransaction.py", line 927, in test_transaction_too_large
  raise JSONRPCException({
      test_framework.authproxy.JSONRPCException: 'generatetoaddress' RPC took longer than 30.000000 seconds. Consider using larger timeout for calls that take longer to return. (-344)
  ```
  and in the CI like https://bitcoinbuilds.org/index.php?ansilog=28537952-2c92-46f2-9871-8918e5ba2738.log#l2398
  ```
  File "/home/ubuntu/src/test/functional/rpc_fundrawtransaction.py", line 927, in test_transaction_too_large
  test_framework.authproxy.JSONRPCException: 'generatetoaddress' RPC took longer than 240.000000 seconds. Consider using larger timeout for calls that take longer to return. (-344)
  ```

Top commit has no ACKs.

Tree-SHA512: f11c923439014fe12420f986c640fd301a26282eb41516957d73b9c751087cbae3d0e316f9ccb49bcb424f488540266f70d3f97948633e77c62bd7935df90452
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
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.

None yet

7 participants