diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 792906c5..5d3af10b 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -1277,6 +1277,58 @@ pub struct InputWeightPrediction { } impl InputWeightPrediction { + /// Input weight prediction corresponding to spending of P2WPKH output with the largest possible + /// DER-encoded signature. + /// + /// If the input in your transaction uses P2WPKH you can use this instead of + /// [`InputWeightPrediction::new`]. + /// + /// This is useful when you **do not** use [signature grinding] and want to ensure you are not + /// under-paying. See [`ground_p2wpkh`](Self::ground_p2wpkh) if you do use signature grinding. + /// + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const P2WPKH_MAX: Self = InputWeightPrediction { script_size: 0, witness_size: 1 + 1 + 73 + 1 + 33 }; + + /// Input weight prediction corresponding to spending of taproot output using the key and + /// default sighash. + /// + /// If the input in your transaction uses Taproot key spend you can use this instead of + /// [`InputWeightPrediction::new`]. + pub const P2TR_KEY_DEFAULT_SIGHASH: Self = InputWeightPrediction { script_size: 0, witness_size: 1 + 1 + 64 }; + + /// Input weight prediction corresponding to spending of taproot output using the key and + /// **non**-default sighash. + /// + /// If the input in your transaction uses Taproot key spend you can use this instead of + /// [`InputWeightPrediction::new`]. + pub const P2TR_KEY_NON_DEFAULT_SIGHASH: Self = InputWeightPrediction { script_size: 0, witness_size: 1 + 1 + 65 }; + + /// Input weight prediction corresponding to spending of P2WPKH output using [signature + /// grinding]. + /// + /// If the input in your transaction uses P2WPKH and you use signature grinding you can use this + /// instead of [`InputWeightPrediction::new`]. See [`P2WPKH_MAX`](Self::P2WPKH_MAX) if you don't + /// use signature grinding. + /// + /// Note: `bytes_to_grind` is usually `1` because of exponential cost of higher values. + /// + /// # Panics + /// + /// The funcion panics in const context and debug builds if `bytes_to_grind` is higher than 62. + /// + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const fn ground_p2wpkh(bytes_to_grind: usize) -> Self { + // Written to trigger const/debug panic for unreasonably high values. + let der_signature_size = 10 + (62 - bytes_to_grind); + let witness_size = 1 // length of element count varint + + 1 // length of element size varint (max signature length is 73B) + + der_signature_size + + 1 // sighash flag + + 1 // length of element size varint + + 33; // length of (always-compressed) public key + InputWeightPrediction { script_size: 0, witness_size } + } + /// Computes the prediction for a single input. pub fn new(input_script_len: usize, witness_element_lengths: T) -> Self where T :IntoIterator, T::Item:Borrow,