aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/spend.cpp
diff options
context:
space:
mode:
authorAntoine Poinsot <darosior@protonmail.com>2022-11-25 10:45:55 +0100
committerAntoine Poinsot <darosior@protonmail.com>2023-08-25 12:40:12 +0200
commit10546a569c6c96a5ec1b9708abf9ff5c8644f669 (patch)
tree51942798a796e8d8b2c8c6c0f61d7b9bb0e3c3d7 /src/wallet/spend.cpp
parent9b7ec393b82ca9d7ada77d06e0835df0386a8b85 (diff)
downloadbitcoin-10546a569c6c96a5ec1b9708abf9ff5c8644f669.tar.xz
wallet: accurately account for the size of the witness stack
When estimating the maximum size of an input, we were assuming the number of elements on the witness stack could be encode in a single byte. This is a valid approximation for all the descriptors we support (including P2WSH Miniscript ones), but may not hold anymore once we support Miniscript within Taproot descriptors (since the max standard witness stack size of 100 gets lifted). It's a low-hanging fruit to account for it correctly, so just do it now.
Diffstat (limited to 'src/wallet/spend.cpp')
-rw-r--r--src/wallet/spend.cpp27
1 files changed, 14 insertions, 13 deletions
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 81dd033177..750b6c100b 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -59,19 +59,20 @@ static std::optional<int64_t> MaxInputWeight(const Descriptor& desc, const std::
const CCoinControl* coin_control, const bool tx_is_segwit,
const bool can_grind_r) {
if (const auto sat_weight = desc.MaxSatisfactionWeight(!can_grind_r || UseMaxSig(txin, coin_control))) {
- const bool is_segwit = IsSegwit(desc);
- // Account for the size of the scriptsig and the number of elements on the witness stack. Note
- // that if any input in the transaction is spending a witness program, we need to specify the
- // witness stack size for every input regardless of whether it is segwit itself.
- // NOTE: this also works in case of mixed scriptsig-and-witness such as in p2sh-wrapped segwit v0
- // outputs. In this case the size of the scriptsig length will always be one (since the redeemScript
- // is always a push of the witness program in this case, which is smaller than 253 bytes).
- const int64_t scriptsig_len = is_segwit ? 1 : GetSizeOfCompactSize(*sat_weight / WITNESS_SCALE_FACTOR);
- // FIXME: use the real number of stack elements instead of the "1" placeholder.
- const int64_t witstack_len = is_segwit ? GetSizeOfCompactSize(1) : (tx_is_segwit ? 1 : 0);
- // previous txid + previous vout + sequence + scriptsig len + witstack size + scriptsig or witness
- // NOTE: sat_weight already accounts for the witness discount accordingly.
- return (32 + 4 + 4 + scriptsig_len) * WITNESS_SCALE_FACTOR + witstack_len + *sat_weight;
+ if (const auto elems_count = desc.MaxSatisfactionElems()) {
+ const bool is_segwit = IsSegwit(desc);
+ // Account for the size of the scriptsig and the number of elements on the witness stack. Note
+ // that if any input in the transaction is spending a witness program, we need to specify the
+ // witness stack size for every input regardless of whether it is segwit itself.
+ // NOTE: this also works in case of mixed scriptsig-and-witness such as in p2sh-wrapped segwit v0
+ // outputs. In this case the size of the scriptsig length will always be one (since the redeemScript
+ // is always a push of the witness program in this case, which is smaller than 253 bytes).
+ const int64_t scriptsig_len = is_segwit ? 1 : GetSizeOfCompactSize(*sat_weight / WITNESS_SCALE_FACTOR);
+ const int64_t witstack_len = is_segwit ? GetSizeOfCompactSize(*elems_count) : (tx_is_segwit ? 1 : 0);
+ // previous txid + previous vout + sequence + scriptsig len + witstack size + scriptsig or witness
+ // NOTE: sat_weight already accounts for the witness discount accordingly.
+ return (32 + 4 + 4 + scriptsig_len) * WITNESS_SCALE_FACTOR + witstack_len + *sat_weight;
+ }
}
return {};