wallet: notify when preset + automatic inputs exceed max weight #30309

pull furszy wants to merge 1 commits into bitcoin:master from furszy:2024_wallet_max_weight changing 3 files +74 −0
  1. furszy commented at 5:34 pm on June 19, 2024: member

    Found it while finishing my review on #29523. This does not interfere with it.

    Basically, we are erroring out early when the automatic coin selection process exceeds the maximum weight, but we are not doing so when the user-preselected inputs combined with the wallet-selected inputs exceed the maximum weight. This change avoids signing all inputs before erroring out and introduces test coverage for fundrawtransaction.

  2. DrahtBot commented at 5:34 pm on June 19, 2024: contributor

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

    Code Coverage

    For detailed information about the code coverage, see the test coverage report.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK tdb3, rkrux, ismaelsadeeq, achow101

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

  3. DrahtBot added the label Wallet on Jun 19, 2024
  4. in test/functional/wallet_fundrawtransaction.py:1343 in 3f50276265 outdated
    1338+        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",
    1339+                                wallet.fundrawtransaction, hexstring=rawtx)
    1340+
    1341+        # 3) Pre-select some inputs and let the wallet fill-up the remaining amount
    1342+        inputs = input_weights[0:1000]
    1343+        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",
    


    tdb3 commented at 10:38 pm on June 20, 2024:
    Tested that this would fail if the return util::Error... line was commented out in source/wallet/spend.cpp. It did (as expected).

    tdb3 commented at 1:03 am on June 22, 2024:
    Re-ran this test (comment out return util::Error...) for 72b226882fe2348a9a66aee1d8d21b4e2d275e68. Failed as expected.
  5. tdb3 approved
  6. tdb3 commented at 10:39 pm on June 20, 2024: contributor
    ACK 3f5027626593c7af546d3b53fc658c87bb815348 Helpful addition to help cover edge cases. Anything that should be added to unit tests?
  7. in src/wallet/spend.cpp:805 in 3f50276265 outdated
    798@@ -799,6 +799,13 @@ util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& av
    799         op_selection_result->RecalculateWaste(coin_selection_params.min_viable_change,
    800                                                 coin_selection_params.m_cost_of_change,
    801                                                 coin_selection_params.m_change_fee);
    802+
    803+        // Verify we haven't exceeded the maximum allowed weight
    804+        int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
    805+        if (op_selection_result->GetWeight() >= max_inputs_weight) {
    


    rkrux commented at 2:22 pm on June 21, 2024:

    The comment above MAX_STANDARD_WEIGHT says it’s the maximum weight we are willing to mine: https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.h#L27

    Should the condition here not be strictly greater than?


    furszy commented at 8:48 pm on June 21, 2024:
    yes, thx
  8. furszy commented at 3:19 pm on June 21, 2024: member

    Anything that should be added to unit tests?

    The behavior change is tested on a functional test. No need to duplicate the same test twice. Functional tests are portable across releases due to our API stability requirement. Unit tests are harder to maintain due to internal code changes. Thus when possible, functional tests are preferred.

  9. in test/functional/wallet_fundrawtransaction.py:1328 in 3f50276265 outdated
    1323+        for _ in range(1472):
    1324+            outputs.append({wallet.getnewaddress(address_type="legacy"): 0.1})
    1325+        txid = self.nodes[0].send(outputs=outputs)["txid"]
    1326+        self.generate(self.nodes[0], 1)
    1327+
    1328+        # 272 WU per input (273 when high-s); picking 1471 inputs will exceed the max standard tx weight.
    


    rkrux commented at 3:24 pm on June 21, 2024:
    From (273 when high-s), I assume this considers a signed input but the docs of createrawtransaction and fundrawtransaction say that these commands don’t generate a signed transaction. So this max weight check on picking 1472 inputs of 273 WU each internally seems to be dependent only on the weight parameter passed to fundrawtransaction RPC, which is dependent on the user input. Is there not any other internal worst-case scenario treatment of the inputs weights that might not be dependent on user input?

    furszy commented at 9:00 pm on June 21, 2024:
    yeah, good eye. send() and walletprocesspsbt() will also fail. Will add coverage for one of them.

    rkrux commented at 6:46 am on June 24, 2024:
    Thanks for adding a functional test for send() as well.
  10. in src/wallet/spend.cpp:804 in 3f50276265 outdated
    798@@ -799,6 +799,13 @@ util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& av
    799         op_selection_result->RecalculateWaste(coin_selection_params.min_viable_change,
    800                                                 coin_selection_params.m_cost_of_change,
    801                                                 coin_selection_params.m_change_fee);
    802+
    803+        // Verify we haven't exceeded the maximum allowed weight
    804+        int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
    


    rkrux commented at 3:25 pm on June 21, 2024:
    I assume the MAX_STANDARD_TX_WEIGHT will be replaced by max_tx_weight (if present) during or after 29523 PR is merged?

    furszy commented at 9:14 pm on June 21, 2024:

    I assume the MAX_STANDARD_TX_WEIGHT will be replaced by max_tx_weight (if present) during or after 29523 PR is merged?

    Yes.

  11. rkrux approved
  12. rkrux commented at 3:27 pm on June 21, 2024: none

    tACK 3f50276

    make, make check, test/functional are successful.

    Thanks @furszy for this improvement, and keeping the PR short and to the point, easy to review! Asked few questions for my understanding.

  13. ismaelsadeeq commented at 4:27 pm on June 21, 2024: member
    Approach ACK
  14. wallet: notify when preset + automatic inputs exceed max weight
    This also avoids signing all inputs prior to erroring out.
    72b226882f
  15. furszy force-pushed on Jun 21, 2024
  16. in test/functional/wallet_send.py:608 in 72b226882f
    603+        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",
    604+                                wallet.send, outputs=[{wallet.getnewaddress(): 0.1 * 1471}])
    605+
    606+        # 3) Pre-select some inputs and let the wallet fill-up the remaining amount
    607+        inputs = inputs[0:1000]
    608+        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",
    


    tdb3 commented at 1:05 am on June 22, 2024:
    Saw that the same expected failure occurs here when commenting out return util::Error... for 72b226882fe2348a9a66aee1d8d21b4e2d275e68.
  17. tdb3 approved
  18. tdb3 commented at 1:16 am on June 22, 2024: contributor
    re ACK for 72b226882fe2348a9a66aee1d8d21b4e2d275e68 Re-ran tests locally (exercising induced failures and received failures as expected). test_weight_limits() implementations are almost identical between wallet_fundrawtransaction and wallet_spend. While this feels a bit redundant, these are separate functional tests so an alternative (like combining) wouldn’t really make sense to do.
  19. DrahtBot requested review from ismaelsadeeq on Jun 22, 2024
  20. DrahtBot requested review from rkrux on Jun 22, 2024
  21. in test/functional/wallet_send.py:592 in 72b226882f
    587+        wallet = self.nodes[1].get_wallet_rpc("test_weight_limits")
    588+
    589+        # Generate future inputs; 272 WU per input (273 when high-s).
    590+        # Picking 1471 inputs will exceed the max standard tx weight.
    591+        outputs = []
    592+        for _ in range(1472):
    


    rkrux commented at 6:47 am on June 24, 2024:
    Any specific reason to generate 1472 outputs when 1471 are picked?

    furszy commented at 1:20 pm on June 24, 2024:

    Any specific reason to generate 1472 outputs when 1471 are picked?

    All are picked actually. The extra output covers the fee.


    rkrux commented at 5:13 pm on June 24, 2024:
    Oh yeah, makes sense. TY.
  22. rkrux approved
  23. rkrux commented at 7:06 am on June 24, 2024: none

    tACK 72b2268

    Reran make and all functional tests. Thanks @furszy for addressing my comments quickly!

    Basically, we are erroring out early when the automatic coin selection process exceeds the maximum weight

    I ended up going through the coin selection algorithms and found all of them honouring the max weight criteria in case of automatic coin selection in coinselection:

  24. rkrux commented at 10:20 am on June 24, 2024: none

    tACK 72b2268

    Reran make and all functional tests. Thanks @furszy for addressing my comments quickly!

    Basically, we are erroring out early when the automatic coin selection process exceeds the maximum weight

    I ended up going through the coin selection algorithms and found all of them honouring the max weight criteria in case of automatic coin selection in coinselection:

    Oh interesting, as per this commit: https://github.com/bitcoin/bitcoin/pull/29523/commits/79f3affa3954ebedcdcb28101723f5ce3fe05880, this max_weight means the maximum allowed weight of the selected UTXOs in the transaction, not of the whole transaction, which I now believe transitively translates to the whole transaction weight criteria as well.

  25. ismaelsadeeq commented at 10:49 am on June 25, 2024: member
    utACK 72b226882fe2348a9a66aee1d8d21b4e2d275e68
  26. achow101 commented at 4:01 pm on June 26, 2024: member
    ACK 72b226882fe2348a9a66aee1d8d21b4e2d275e68
  27. achow101 merged this on Jun 26, 2024
  28. achow101 closed this on Jun 26, 2024

  29. furszy deleted the branch on Jun 26, 2024

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-30 15:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me