Wallet: Add max_tx_weight to transaction funding options (take 2) #29523

pull ismaelsadeeq wants to merge 4 commits into bitcoin:master from ismaelsadeeq:02-2024-add-max-weight-to-tx-funding changing 10 files +178 −76
  1. ismaelsadeeq commented at 9:38 am on March 1, 2024: member

    This PR taken over from #29264

    The PR added an option max_tx_weight to transaction funding RPC’s that ensures the resulting transaction weight does not exceed the specified max_tx_weight limit.

    If max_tx_weight is not given MAX_STANDARD_TX_WEIGHT is used as the max threshold.

    This PR addressed outstanding review comments in #29264

    For more context and rationale behind this PR see https://delvingbitcoin.org/t/lightning-transactions-with-v3-and-ephemeral-anchors/418/11?u=instagibbs

  2. DrahtBot commented at 9:38 am on March 1, 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 furszy, rkrux, achow101
    Concept ACK murchandamus
    Stale ACK Eunovo

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

    Conflicts

    No conflicts as of last run.

  3. DrahtBot added the label Wallet on Mar 1, 2024
  4. ismaelsadeeq marked this as a draft on Mar 1, 2024
  5. ismaelsadeeq commented at 10:27 am on March 1, 2024: member
    Some C.I jobs are failing, putting in draft while I try to address that.
  6. DrahtBot added the label CI failed on Mar 1, 2024
  7. ismaelsadeeq force-pushed on Mar 8, 2024
  8. DrahtBot removed the label CI failed on Mar 8, 2024
  9. ismaelsadeeq marked this as ready for review on Mar 9, 2024
  10. glozow requested review from murchandamus on Mar 18, 2024
  11. glozow requested review from furszy on Mar 18, 2024
  12. in src/wallet/spend.cpp:704 in 05373e6325 outdated
    700@@ -701,7 +701,7 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
    701         } else append_error(bnb_result);
    702     }
    703 
    704-    // As Knapsack and SRD can create change, also deduce change weight.
    705+    // Deduce change weight because remaining Coin Selection algorithms can create change output.
    


    murchandamus commented at 1:11 pm on March 18, 2024:

    In “[doc]: update reason for deducing change output weight” (05373e632500670ff8bd65ed6621a039849886ad):

    to deduct means to subtract, to deduce means to draw a logical conclusion

    0    // Deduct change weight because remaining Coin Selection algorithms can create change output.
    

    Also in the commit message for that PR:

    CoinGrinder will always produce a change output.

    0-`CoinGrinder` also might produce change output, listing all the
    1+`CoinGrinder` will also produce a change output, listing all the
    

    ismaelsadeeq commented at 12:37 pm on March 19, 2024:
    Fixed thank you!
  13. in src/wallet/coinselection.cpp:87 in eaf40cea9d outdated
    83@@ -84,19 +84,19 @@ struct {
    84  *        bound of the range.
    85  * @param const CAmount& cost_of_change This is the cost of creating and spending a change output.
    86  *        This plus selection_target is the upper bound of the range.
    87- * @param int max_selection_weight The maximum allowed weight for a selection result to be valid.
    88+ * @param int64_t max_selection_weight The maximum allowed weight for a selection result to be valid.
    


    murchandamus commented at 1:29 pm on March 18, 2024:

    In “[wallet]: change max_selection_weight to int64_t” (eaf40cea9d31b43b4eb112e561fbadc1911e5732):

    This commit surprises me. I guess being explicit is better than being implicit, so I would understand using int32_t instead of int, but I don’t understand the motivation to switch to an int64_t. int in Bitcoin Core is always a signed 32-bit integer, because Bitcoin Core only supports platforms where int is exactly 32 bits. Therefore, the maximum value for int is 231, i.e. a bit more than 2 billion. Since the blockweight is limited to 4 million bytes, it’s unclear to me why we would need more than 32 bits for max_selection_weight. What am I missing here?


    ismaelsadeeq commented at 3:08 pm on March 18, 2024:
    Thanks @murchandamus for the link and your review comment, I will look into this and respond as soon as I can.

    ismaelsadeeq commented at 12:43 pm on March 19, 2024:

    You are right int is enough, I switched back to the status quo.

    Thanks.

  14. in src/wallet/coinselection.h:179 in 854acd72e9 outdated
    173@@ -174,10 +174,15 @@ struct CoinSelectionParams {
    174      * 1) Received from other wallets, 2) replacing other txs, 3) that have been replaced.
    175      */
    176     bool m_include_unsafe_inputs = false;
    177+    /**
    178+     * The maximally sized transaction we are willing to make.
    179+     */
    


    murchandamus commented at 1:53 pm on March 18, 2024:

    In “[wallet, rpc]: add max_tx_weight to tx funding options” (854acd72e99dc9f0924c5f0b5b7a657b39538911):

    Weight, not size:

    0     /** The maximum weight for this transaction */
    

    ismaelsadeeq commented at 12:38 pm on March 19, 2024:
    Fixed
  15. in src/wallet/coinselection.h:180 in 854acd72e9 outdated
    178+     * The maximally sized transaction we are willing to make.
    179+     */
    180+    std::optional<int64_t> m_max_tx_weight{std::nullopt};
    181 
    182-    CoinSelectionParams(FastRandomContext& rng_fast, size_t change_output_size, size_t change_spend_size,
    183+    CoinSelectionParams(FastRandomContext& rng_fast, int change_output_size, size_t change_spend_size,
    


    murchandamus commented at 1:59 pm on March 18, 2024:

    In “[wallet, rpc]: add max_tx_weight to tx funding options” (854acd72e99dc9f0924c5f0b5b7a657b39538911):

    I’m a bit surprised by this sudden type change in a commit whose commit message doesn’t mention it. While I agree in principal that size_t is an inappropriate type for variables storing vsize or weight, could you please explain your motivation to change the types, and especially in this context? If you are retyping unrelated variables, I think that should perhaps be a separate commit. If you are changing the types of change_output_size and tx_noinputs_size, why not also change_spend_size? Perhaps if we are getting big into the business of changing the types of various transaction size, vsize and weight variables, we should perhaps consider introducing explicit types for weight, size, and vsize to prevent people accidentally mistaking them for the same type. On the other hand, that feels like the sort of change that will never propagate to the entire codebase, so I’m not sure it’s a good idea to even start.


    ismaelsadeeq commented at 3:07 pm on March 18, 2024:

    Thanks for your review @murchandamus

    Perhaps if we are getting big into the business of changing the types of various transaction size, vsize and weight variables, we should perhaps consider introducing explicit types for weight, size, and vsize to prevent people accidentally mistaking them for the same type.

    I agree with this suggestion and have same concern previously here #29242 (review) should make the code cleaner

    Sorry for not explaining the rationale behind this in the commit messages, I will try and explain why I did the change below

    On master we have

    0    int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
    1    
    2
    3   .......
    4    max_inputs_weight -= (coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR);
    

    After this PR maximum transaction weight can be configured by users, so we now subtract from user provided maximum weight or use the default if not given.

    0int max_selection_weight = coin_selection_params.m_max_tx_weight.value_or(MAX_STANDARD_TX
    1_WEIGHT) - coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR;
    

    m_max_tx_weight is int, tx_noinputs_size and change_output_size are both size_t. given that Bitcoin Core only supports platforms where int is exactly 32 bits For signed integers (int), it ranges from -2^(31) to (2^(31)) - 1. For unsigned integers (unsigned int), it ranges from 0 to (2^(32)) - 1.

    The issue arises when after compiling with “ASan + LSan + UBSan + integer, without dependencies, USDT” and running the functional test.

    From 854acd72e9 we allow passing 0 weight and test for that in the functional test, results of subtracting coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR from 0 causes max_selection_weight to have some positive value instead of negative. hence the test fails see https://cirrus-ci.com/task/6341256662482944, This is reproducible locally.

    Thats why I changed change_output_size, and tx_noinputs_sizefrom size_t to int64_t and also use same datatype for m_max_tx_weight which works fine.

    0int64_t max_selection_weight = coin_selection_params.m_max_tx_weight.value_or(MAX_STANDARD_TX
    1_WEIGHT) - static_cast<int64_t>(coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
    

    But since Bitcoin Core only supports platforms where int is exactly 32 bits I think using int for change_output_size, and tx_noinputs_size should work fine?


    ismaelsadeeq commented at 6:00 pm on March 18, 2024:

    From https://github.com/bitcoin/bitcoin/commit/854acd72e99dc9f0924c5f0b5b7a657b39538911 we allow passing 0 weight and test for that in the functional test.

    After thinking about this more, it does not make sense to allow passing passing 0 maximum transaction weight, should instead be between minimum transaction weight possible and MAX_STANDARD_TX_WEIGHT. I will update to this.


    ismaelsadeeq commented at 12:50 pm on March 19, 2024:
    I switched back to status quo, and prevent users from passing max_tx_weight below MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR

    murchandamus commented at 4:06 pm on March 20, 2024:

    But since Bitcoin Core only supports platforms where int is exactly 32 bits I think using int for change_output_size, and tx_noinputs_size should work fine?

    […]

    I switched back to status quo, and prevent users from passing max_tx_weight below MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR

    I think we may have crossed some wires here. Thanks for the explanation, that was very helpful. I still agree that size_t is the wrong type for change_output_size and tx_noinputs_size. I would support you taking the opportunity because m_max_tx_weight is int to also change those two to int, perhaps even take change_spend_size along for that. I just think that it might be better to make it a separate commit and that it should be explained in the commit message.


    ismaelsadeeq commented at 11:45 am on March 22, 2024:
    I Added a commit that changed them to int :)
  16. in src/wallet/rpc/spend.cpp:1377 in 8e256fe679 outdated
    1373@@ -1374,6 +1374,7 @@ RPCHelpMan sendall()
    1374             RPCResult::Type::OBJ, "", "",
    1375                 {
    1376                     {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
    1377+                    {RPCResult::Type::NUM, "weight", "The resulting transaction weight in bytes"},
    


    murchandamus commented at 2:14 pm on March 18, 2024:

    In “[rpc]: update sendall RPC to return the resulting tx weight” (8e256fe679236710549820ec48ac7c0793fcfd96):

    “bytes” is not a unit of weight. I would expect that this is returning the weight in weight units or the vsize in vbytes.


    ismaelsadeeq commented at 12:38 pm on March 19, 2024:
    changed to “The resulting transaction weight in weight units”
  17. murchandamus commented at 2:15 pm on March 18, 2024: contributor
    Concept ACK
  18. ismaelsadeeq force-pushed on Mar 19, 2024
  19. ismaelsadeeq force-pushed on Mar 21, 2024
  20. in src/wallet/spend.cpp:1053 in 1ae0261524 outdated
    1049@@ -1050,7 +1050,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
    1050     if (change_spend_size == -1) {
    1051         coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;
    1052     } else {
    1053-        coin_selection_params.change_spend_size = (size_t)change_spend_size;
    1054+        coin_selection_params.change_spend_size = (int)change_spend_size;
    


    furszy commented at 11:54 am on March 22, 2024:
    change_spend_size is already an int.

    ismaelsadeeq commented at 12:01 pm on March 22, 2024:
    Yes indeed updated, thanks!
  21. ismaelsadeeq force-pushed on Mar 22, 2024
  22. in test/functional/rpc_psbt.py:194 in 0b6835c946 outdated
    187@@ -187,6 +188,16 @@ def run_test(self):
    188         # Create and fund a raw tx for sending 10 BTC
    189         psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt']
    190 
    191+        self.log.info("Test that max_tx_weight option is sanity checked and fails when expected")
    192+        dest_arg = [{self.nodes[0].getnewaddress(): 1}]
    193+        min_tx_weight = MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR
    194+        assert_raises_rpc_error(-8, f"Invalid parameter, max tx weight must be between {min_tx_weight} and 400000", self.nodes[0].walletcreatefundedpsbt, [], dest_arg, 0, {"max_tx_weight": -1})
    


    Eunovo commented at 10:27 am on March 28, 2024:
    I can see that the “400000” here is the MAX_STANDARD_TX_WEIGHT but I think it’s better to define the MAX_STANDARD_TX_WEIGHT constant and use it here. This makes it obvious to anyone reading what “400000” is.

    ismaelsadeeq commented at 12:26 pm on March 28, 2024:
    Yes can also be used in future tests, thinking about defining it in test_framework/blocktools.py

    ismaelsadeeq commented at 10:51 am on April 4, 2024:
    Fixed thanks
  23. in src/wallet/rpc/spend.cpp:794 in 0b6835c946 outdated
    795@@ -787,6 +796,8 @@ RPCHelpMan fundrawtransaction()
    796                                     },
    797                                 },
    798                              },
    799+                            {"max_tx_weight", RPCArg::Type::NUM, RPCArg::Default{MAX_STANDARD_TX_WEIGHT}, "The maximum acceptable transaction weight.\n"
    


    Eunovo commented at 10:41 am on March 28, 2024:
    Nit: might be good to define this in one place since you use it multiple times.

    ismaelsadeeq commented at 12:29 pm on March 28, 2024:
    What should be defined? The help text ? not sure if this is a good idea though so leaving this as is!
  24. ismaelsadeeq force-pushed on Apr 4, 2024
  25. furszy commented at 12:42 pm on April 4, 2024: member
    Any chance to turn the first commit into an scripted-diff?
  26. Eunovo commented at 3:10 pm on April 4, 2024: none
  27. DrahtBot requested review from murchandamus on Apr 4, 2024
  28. ismaelsadeeq force-pushed on Apr 5, 2024
  29. ismaelsadeeq commented at 4:02 pm on April 5, 2024: member

    Any chance to turn the first commit into an scripted-diff?

    The commit message was misleading It’s not just renaming max_weight, it also updates the input parameter docstring to match the new name, some comment updates, and also the fuzz test renames has more info like low_max_selection_weight and high_max_selection_weight.

    I’ve updated the commit message of the first commit https://github.com/bitcoin/bitcoin/pull/29523/commits/270639324a6637e0025e1458221ab488a8a09554

  30. DrahtBot added the label CI failed on Apr 24, 2024
  31. DrahtBot commented at 11:55 pm on April 24, 2024: contributor

    🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the documentation.

    Possibly this is due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    Leave a comment here, if you need help tracking down a confusing failure.

    Debug: https://github.com/bitcoin/bitcoin/runs/23495200918

  32. ismaelsadeeq force-pushed on May 3, 2024
  33. ismaelsadeeq force-pushed on May 3, 2024
  34. ismaelsadeeq commented at 9:46 am on May 3, 2024: member
    Rebased and force pushed from 3d76c37106a4f80fd2ac410696b1049c3aa321c5 to b24b7a9a6a1a10024c639e9d4ee27aa4d0ce653e to fix C.I failure compare diff
  35. DrahtBot removed the label CI failed on May 3, 2024
  36. achow101 referenced this in commit f9486de6a9 on May 3, 2024
  37. DrahtBot added the label Needs rebase on Jun 5, 2024
  38. ismaelsadeeq force-pushed on Jun 10, 2024
  39. ismaelsadeeq commented at 10:32 am on June 10, 2024: member
    Rebased to fix conflict after #28366 was merged. b24b7a9a6..845d16c1b
  40. DrahtBot removed the label Needs rebase on Jun 10, 2024
  41. in src/wallet/spend.cpp:697 in d9ec6e7f28 outdated
    691@@ -692,7 +692,9 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
    692     };
    693 
    694     // Maximum allowed weight for selected coins.
    695-    int max_selection_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
    696+    int max_transaction_weight = coin_selection_params.m_max_tx_weight.value_or(MAX_STANDARD_TX_WEIGHT);
    697+    int tx_weight_no_input = coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR;
    698+    int max_selection_weight = std::max((max_transaction_weight - tx_weight_no_input), 0);
    


    furszy commented at 10:15 pm on June 19, 2024:

    In d9ec6e7f28f0:

    Instead of setting it to 0, could error out early if max_selection_weight <= 0 (a test for this would be nice).


    ismaelsadeeq commented at 4:24 pm on June 21, 2024:
    Thanks fixed.

    ismaelsadeeq commented at 4:24 pm on June 21, 2024:
    Also added a test for this
  42. in src/wallet/spend.cpp:708 in d9ec6e7f28 outdated
    703@@ -702,7 +704,8 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
    704     }
    705 
    706     // Deduct change weight because remaining Coin Selection algorithms can create change output
    707-    max_selection_weight -= (coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR);
    708+    int change_outputs_weight = coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR;
    709+    max_selection_weight = std::max((max_selection_weight - change_outputs_weight), 0);
    


    furszy commented at 10:17 pm on June 19, 2024:
    Same as above, would be nice to error out early if max_selection_weight <= 0. No need to run the selection algorithms under such circumstance.

    ismaelsadeeq commented at 4:24 pm on June 21, 2024:
    Fixed, and also add a test case for it.
  43. in test/functional/test_framework/blocktools.py:51 in d9ec6e7f28 outdated
    47@@ -48,6 +48,7 @@
    48 
    49 MAX_BLOCK_SIGOPS = 20000
    50 MAX_BLOCK_SIGOPS_WEIGHT = MAX_BLOCK_SIGOPS * WITNESS_SCALE_FACTOR
    51+MAX_STANDARD_TX_WEIGHT = 400000
    


    furszy commented at 10:20 pm on June 19, 2024:
    nit: could replace this line with this constant.

    ismaelsadeeq commented at 4:27 pm on June 21, 2024:
    leaving this as is, as I suspect there might be other places that needs to be replaced also. this and others can come in a separate PR ?
  44. furszy commented at 10:21 pm on June 19, 2024: member
    few small comments
  45. ismaelsadeeq commented at 8:12 am on June 20, 2024: member
    thanks for your review @furszy will force push to address this comments shortly.
  46. ismaelsadeeq force-pushed on Jun 21, 2024
  47. ismaelsadeeq force-pushed on Jun 21, 2024
  48. in src/wallet/coinselection.cpp:87 in 79f3affa39 outdated
    83@@ -84,14 +84,14 @@ struct {
    84  *        bound of the range.
    85  * @param const CAmount& cost_of_change This is the cost of creating and spending a change output.
    86  *        This plus selection_target is the upper bound of the range.
    87- * @param int max_weight The maximum weight available for the input set.
    88+ * @param int max_selection_weight The maximum allowed weight for a selection result to be valid.
    


    rkrux commented at 10:27 am on June 24, 2024:

    As per the following 2 statements in ChooseSelectionResult:

    The no_input and change_output weights are accounted for, but where is the weight of the destination output accounted for?


    rkrux commented at 11:21 am on June 24, 2024:
    Took me a while to figure but as I see they are accounted for within coin_selection_params.tx_noinputs_size here: https://github.com/bitcoin/bitcoin/blob/master/src/wallet/spend.cpp#L1100
  49. in src/wallet/coinselection.h:142 in 80355372d5 outdated
    138@@ -139,9 +139,9 @@ struct CoinSelectionParams {
    139     /** Randomness to use in the context of coin selection. */
    140     FastRandomContext& rng_fast;
    141     /** Size of a change output in bytes, determined by the output type. */
    142-    size_t change_output_size = 0;
    143+    int change_output_size = 0;
    


    rkrux commented at 11:26 am on June 24, 2024:

    This change ensures consistency in transaction size and weight calculation within the wallet and prevents conversion overflow when calculating max_selection_weight.

    Are the inconsistencies because size_t is platform dependent and int is not (at least for the purposes of core because of this: https://github.com/bitcoin/bitcoin/blob/v26.0/src/compat/assumptions.h#L44)? I still need to digest this comment: #29523 (review)


    ismaelsadeeq commented at 10:10 am on June 25, 2024:

    It’s simply just to ensure consistency in transaction size and weight calculation within the wallet and prevents conversion overflow when calculating max_selection_weight as it happened here https://cirrus-ci.com/task/6341256662482944


    I think it definitely will be worth it to define a datatype for size in the entire codebase. But I am limiting this change to affect only the wallet size variables change_output_size, change_spend_size and tx_noinputs_size, because they relate to this PR.

  50. in test/functional/rpc_psbt.py:234 in 723a8da8e5 outdated
    229+        assert_raises_rpc_error(-4, "The inputs size exceeds the maximum weight", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": (large_tx_vsize_with_change + 1) * WITNESS_SCALE_FACTOR})
    230+
    231+        max_tx_weight_sufficient = 1000 # 1k vbytes is enough
    232+        psbt = self.nodes[0].walletcreatefundedpsbt(outputs=dest_arg,locktime=0, options={"max_tx_weight": max_tx_weight_sufficient})["psbt"]
    233+        weight = self.nodes[0].decodepsbt(psbt)["tx"]["weight"]
    234+        # ensure the transactions weight is below the transaction weight.
    


    rkrux commented at 12:18 pm on June 24, 2024:

    Nit: In case the file is changed.

    0# ensure the transaction's weight is below the specified max_tx_weight.
    

    ismaelsadeeq commented at 10:13 am on June 25, 2024:
    Fixed.
  51. in test/functional/rpc_psbt.py:211 in 723a8da8e5 outdated
    206+        output_count = 1
    207+        tx_weight_without_inputs = (base_tx_vsize + output_count + p2wpkh_output_vsize) * WITNESS_SCALE_FACTOR
    208+        # min_tx_weight is greater than transaction weight without inputs
    209+        assert_greater_than(min_tx_weight, tx_weight_without_inputs)
    210+
    211+        # In other to test for when the passed max weight is less than the transaction weight without inputs
    


    rkrux commented at 12:20 pm on June 24, 2024:
    Was the intention to write “In order to …”?

    ismaelsadeeq commented at 10:13 am on June 25, 2024:
    Yes updated
  52. rkrux approved
  53. rkrux commented at 12:36 pm on June 24, 2024: none

    Concept ACK a120fc7, but I would look at 723a8da commit a bit more again; make, test/functional are successful though.

    Following transaction funding RPCs are affected with the addition of max_tx_weight option:

    1. fundrawtransaction
    2. walletcreatefundedpsbt
    3. send
  54. ismaelsadeeq force-pushed on Jun 25, 2024
  55. achow101 referenced this in commit 1d00601b9b on Jun 26, 2024
  56. in src/wallet/spend.cpp:720 in 6fe8d287e2 outdated
    715@@ -706,7 +716,11 @@ util::Result<SelectionResult> ChooseSelectionResult(interfaces::Chain& chain, co
    716     }
    717 
    718     // Deduct change weight because remaining Coin Selection algorithms can create change output
    719-    max_selection_weight -= (coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR);
    720+    int change_outputs_weight = coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR;
    721+    max_selection_weight = max_selection_weight - change_outputs_weight;
    


    furszy commented at 8:35 pm on June 26, 2024:

    tiny nit:

    0    max_selection_weight -= change_outputs_weight;
    

    ismaelsadeeq commented at 2:21 pm on June 27, 2024:
    fixed
  57. in src/wallet/spend.cpp:1109 in 6fe8d287e2 outdated
    1105@@ -1091,13 +1106,16 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
    1106     // Static vsize overhead + outputs vsize. 4 version, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
    1107     coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count
    1108 
    1109+    LogInfo("input count size %s \n", GetSizeOfCompactSize(vecSend.size()));
    


    furszy commented at 8:37 pm on June 26, 2024:
    guess that this was used for testing purposes and you forgot to remove it?

    ismaelsadeeq commented at 2:21 pm on June 27, 2024:
    Yes, removed
  58. in src/wallet/spend.cpp:1118 in 6fe8d287e2 outdated
    1113     {
    1114         CTxOut txout(recipient.nAmount, GetScriptForDestination(recipient.dest));
    1115 
    1116         // Include the fee cost for outputs.
    1117         coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout);
    1118+        LogInfo("Output size %s \n", static_cast<int>(::GetSerializeSize(txout)));
    


    furszy commented at 8:38 pm on June 26, 2024:
    Same as above, guess that this was used for testing purposes and you forgot to remove it?

    ismaelsadeeq commented at 2:21 pm on June 27, 2024:
    removed
  59. in test/functional/rpc_psbt.py:225 in 6fe8d287e2 outdated
    220+
    221+        # Test for max_tx_weight just enough to include inputs but not change output
    222+        assert_raises_rpc_error(-4, "Maximum transaction weight is too low, can not accommodate change output", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": (large_tx_vsize_without_inputs + 1) * WITNESS_SCALE_FACTOR})
    223+        # Test that it has to accommodate a change output
    224+        large_tx_vsize_with_change = large_tx_vsize_without_inputs + p2wpkh_output_vsize
    225+        assert_raises_rpc_error(-4, "Maximum transaction weight is too low, can not accommodate change output", self.nodes[0].walletcreatefundedpsbt, [], dest_arg_large, 0, {"max_tx_weight": (large_tx_vsize_with_change) * WITNESS_SCALE_FACTOR})
    


    furszy commented at 8:42 pm on June 26, 2024:
    Isn’t the purpose of this test case to include the change output and fail after wise? (not with the “can not accommodate change output” error message)

    ismaelsadeeq commented at 2:31 pm on June 27, 2024:
    Yes, good catch. Updated
  60. in test/functional/rpc_psbt.py:988 in 6fe8d287e2 outdated
    1032@@ -985,6 +1033,5 @@ def test_psbt_input_keys(psbt_input, keys):
    1033         self.log.info("Test descriptorprocesspsbt raises if an invalid sighashtype is passed")
    1034         assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt, [descriptor], sighashtype="all")
    1035 
    1036-
    


    furszy commented at 8:43 pm on June 26, 2024:
    PEP 8: E305 expected 2 blank lines after class or function definition, found 1. Let’s not remove this line.

    ismaelsadeeq commented at 2:22 pm on June 27, 2024:
    added the line back, thanks
  61. in src/wallet/rpc/spend.cpp:1569 in b3ac1179ff outdated
    1564@@ -1564,8 +1565,9 @@ RPCHelpMan sendall()
    1565                     pwallet->LockCoin(txin.prevout);
    1566                 }
    1567             }
    1568-
    1569-            return FinishTransaction(pwallet, options, rawTx);
    1570+            auto result = FinishTransaction(pwallet, options, rawTx);
    1571+            result.pushKV("weight", tx_size.weight);
    


    furszy commented at 8:51 pm on June 26, 2024:

    Not sure about using tx_size, we would be returning an estimation of the final size of tx. Not the real/current tx weight.

    What about getting the current tx weight by serializing the CMutableTransaction object that appears inside FinishTransaction and explain in the RPC return value description that the returned weight will not be the final one if the transaction is not complete.


    rkrux commented at 8:06 am on June 27, 2024:
    Interesting, I agree with this point. Returning the exact size of the transaction would make the RPC definition more robust.

    rkrux commented at 8:09 am on June 27, 2024:
    This commit (along with this^ suggestion) b3ac117 can be a separate PR as well, doesn’t seem necessary for this PR to be merged if I didn’t miss anything.

    ismaelsadeeq commented at 2:23 pm on June 27, 2024:
    Yes it’s not needed. I removed this commit This can come as a separate PR, the size output can also be added to the other funding RPC’s?
  62. furszy commented at 8:53 pm on June 26, 2024: member
    Code reviewed b3ac1179ff90f, getting closer. Left few topics.
  63. [refactor]: update coin selection algorithms input parameter `max_weight` name
    - This commit renames the coin selection algorithms input parameter `max_weight`
      to `max_selection_weight` for clarity.
    
      The parameter represent the maximum weight of the UTXOs the coin selection algorithm
      should select, not the transaction maximum weight.
    
    - The commit updates the parameter docstring to provide correct description.
    
    - Also updates coin selection unit and fuzzing test variables to match the new name.
    7f61d31a5c
  64. [doc]: update reason for deducting change output weight
    `CoinGrinder` will also produce change output, listing all the
    Coin selection algorithms that produces change output is not maintainable,
    just infer that remaining algorithms all might produce change.
    baab0d2d43
  65. [wallet]: update the data type of `change_output_size`, `change_spend_size` and `tx_noinputs_size` to `int`
    - This change ensures consistency in transaction size and weight calculation
      within the wallet and prevents conversion overflow when calculating
      `max_selection_weight`.
    b6fc5043c1
  66. ismaelsadeeq force-pushed on Jun 27, 2024
  67. [wallet, rpc]: add `max_tx_weight` to tx funding options
    This allows a transaction's weight to be bound under a certain
    weight if possible and desired. This can be beneficial for future
    RBF attempts, or whenever a more restricted spend topology is
    desired.
    
    Co-authored-by: Greg Sanders <gsanders87@gmail.com>
    734076c6de
  68. ismaelsadeeq force-pushed on Jun 27, 2024
  69. ismaelsadeeq commented at 2:39 pm on June 27, 2024: member

    Thanks for the reviews @furszy @rkrux

    Force-pushed from b3ac1179ff90fe261af4e6dc9c7af64e1518b435 to d8febf6d9ea018cf8e980ee036fb5ccd8ea8887a Compare diff b3ac1179ff..734076c6d


    Changes:

    • Rebased after PR 30309 and updated the maximum transaction weight check to use the user passed value when given or default MAX_STANDARD_TX_WEIGHT.
    • Removed miscellaneous logs.
    • Added back the removed line in the rpc_psbt.py functional test according PEP guidelines.
    • Removed the last commit that returned the estimated size in the send RPC based on the review here.
  70. in src/wallet/spend.cpp:1016 in 734076c6de
    1010@@ -1002,7 +1011,11 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
    1011     CoinSelectionParams coin_selection_params{rng_fast}; // Parameters for coin selection, init with dummy
    1012     coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;
    1013     coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs;
    1014-
    1015+    coin_selection_params.m_max_tx_weight = coin_control.m_max_tx_weight.value_or(MAX_STANDARD_TX_WEIGHT);
    1016+    int minimum_tx_weight = MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR;
    1017+    if (coin_selection_params.m_max_tx_weight.value() < minimum_tx_weight || coin_selection_params.m_max_tx_weight.value() > MAX_STANDARD_TX_WEIGHT) {
    


    furszy commented at 4:20 pm on June 27, 2024:

    In 734076c6de178:

    nano nit: shorter

    0    if (*coin_selection_params.m_max_tx_weight < minimum_tx_weight || *coin_selection_params.m_max_tx_weight > MAX_STANDARD_TX_WEIGHT) {
    
  71. furszy commented at 4:22 pm on June 27, 2024: member
    utACK 734076c6de1781f957c8bc3bf7ed6951920cfcf6
  72. DrahtBot requested review from Eunovo on Jun 27, 2024
  73. DrahtBot requested review from rkrux on Jun 27, 2024
  74. rkrux approved
  75. rkrux commented at 11:17 am on July 7, 2024: none

    reACK 734076c

    Ran make and functional tests, all successful. @ismaelsadeeq This diff comparison b3ac117..734076c contains a lot of unrelated changes though.

  76. ismaelsadeeq commented at 11:28 am on July 7, 2024: member

    @ismaelsadeeq This diff comparison b3ac117..734076c contains a lot of unrelated changes though.

    Yes that’s because of the recent rebase.

  77. achow101 commented at 10:19 pm on July 17, 2024: member
    ACK 734076c6de1781f957c8bc3bf7ed6951920cfcf6
  78. achow101 merged this on Jul 17, 2024
  79. achow101 closed this on Jul 17, 2024

  80. ismaelsadeeq deleted the branch on Jul 17, 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-03 15:12 UTC

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