This PR fixes a bug in the MaxSatisfactionWeight calculation for Taproot descriptors. Previously, the implementation contained a FIXME comment and only calculated keypath spend weight, leading to significant underestimations for script path spending.
What Changed:
1. TaprootDescriptor::MaxSatisfactionWeight - Replaced the placeholder implementation with proper script path weight calculation:
- Now iterates through all subdescriptors to find the heaviest script path
- Uses
MaxSatSize()instead ofMaxSatisfactionWeight()for subdescriptors (Taproot SegWit v1 has a 1:1 ratio between witness bytes and weight units, unlike the 4:1 ratio in legacy SegWit v0) - Accounts for satisfaction size, script size, and control block size
- Returns the maximum of keypath (66 weight units) and all script paths
2. PKDescriptor::MaxSatSize - Corrected Schnorr signature size from 65 to 64 bytes (SIGHASH_DEFAULT is omitted in Schnorr signatures)
3. MultiADescriptor::MaxSatSize - Corrected Schnorr signature size from 65 to 64 bytes
4. Added comprehensive unit tests - New test case descriptor_tr_max_satisfaction_weight with:
- Test for
tr(key, pk(key))verifying script path weight (134) exceeds keypath weight (66) - Test for
tr(key, sortedmulti_a(2, K1, K2))verifying complex script path calculation (235 weight units) - Detailed comments explaining the weight calculations for each component
Why:
Accurate weight estimation for Taproot descriptors is critical for:
- Fee calculation - Underestimated weights lead to insufficient fees and transaction rejection
- Transaction size estimation - Affects PSBT construction and validation
- Wallet coin selection - Incorrect weights cause suboptimal UTXO selection
The tests demonstrate the bug (old code would return 66 for both cases) and prove the fix produces correct weight estimates.