Merge rust-bitcoin/rust-bitcoin#1835: Fix associated constants of `InputWeightPrediction`

6cec19f6d3 Update documentation of `InputWeightPrediction` (Martin Habovstiak)
6fec1789b9 Fix associated constants of `InputWeightPrediction` (Martin Habovstiak)

Pull request description:

  These constants had an error that they had `script_size` set to 0 which
  was incorrect because it's not length of the script but serialized size.
  Rather than just bumping the value this uses the `from_slice` method
  which is less error-prone.

  Closes https://github.com/rust-bitcoin/rust-bitcoin/issues/1834

ACKs for top commit:
  apoelstra:
    ACK 6cec19f6d3
  tcharding:
    ACK 6cec19f6d3

Tree-SHA512: 4e05be2c05795e8c4f9c67374491be71d2bde8233446f22bf458cfeb542d81043f03f90f65e59e769fce8275925dff28fc3dfce48fd62bd20be7fca22b71ca3c
This commit is contained in:
Andrew Poelstra 2023-05-12 12:55:19 +00:00
commit ff08caf17c
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
1 changed files with 6 additions and 44 deletions

View File

@ -1329,7 +1329,8 @@ pub const fn predict_weight_from_slices(
/// Weight prediction of an individual input. /// Weight prediction of an individual input.
/// ///
/// This helper type collects information about an input to be used in [`predict_weight`] function. /// This helper type collects information about an input to be used in [`predict_weight`] function.
/// It can only be created using the [`new`](InputWeightPrediction::new) function. /// It can only be created using the [`new`](InputWeightPrediction::new) function or using other
/// associated constants/methods.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct InputWeightPrediction { pub struct InputWeightPrediction {
script_size: usize, script_size: usize,
@ -1347,24 +1348,21 @@ impl InputWeightPrediction {
/// under-paying. See [`ground_p2wpkh`](Self::ground_p2wpkh) if you do use signature grinding. /// 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 /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding
pub const P2WPKH_MAX: Self = pub const P2WPKH_MAX: Self = InputWeightPrediction::from_slice(0, &[73, 33]);
InputWeightPrediction { script_size: 0, witness_size: 1 + 1 + 73 + 1 + 33 };
/// Input weight prediction corresponding to spending of taproot output using the key and /// Input weight prediction corresponding to spending of taproot output using the key and
/// default sighash. /// default sighash.
/// ///
/// If the input in your transaction uses Taproot key spend you can use this instead of /// If the input in your transaction uses Taproot key spend you can use this instead of
/// [`InputWeightPrediction::new`]. /// [`InputWeightPrediction::new`].
pub const P2TR_KEY_DEFAULT_SIGHASH: Self = pub const P2TR_KEY_DEFAULT_SIGHASH: Self = InputWeightPrediction::from_slice(0, &[64]);
InputWeightPrediction { script_size: 0, witness_size: 1 + 1 + 64 };
/// Input weight prediction corresponding to spending of taproot output using the key and /// Input weight prediction corresponding to spending of taproot output using the key and
/// **non**-default sighash. /// **non**-default sighash.
/// ///
/// If the input in your transaction uses Taproot key spend you can use this instead of /// If the input in your transaction uses Taproot key spend you can use this instead of
/// [`InputWeightPrediction::new`]. /// [`InputWeightPrediction::new`].
pub const P2TR_KEY_NON_DEFAULT_SIGHASH: Self = pub const P2TR_KEY_NON_DEFAULT_SIGHASH: Self = InputWeightPrediction::from_slice(0, &[65]);
InputWeightPrediction { script_size: 0, witness_size: 1 + 1 + 65 };
/// Input weight prediction corresponding to spending of P2WPKH output using [signature /// Input weight prediction corresponding to spending of P2WPKH output using [signature
/// grinding]. /// grinding].
@ -1383,13 +1381,7 @@ impl InputWeightPrediction {
pub const fn ground_p2wpkh(bytes_to_grind: usize) -> Self { pub const fn ground_p2wpkh(bytes_to_grind: usize) -> Self {
// Written to trigger const/debug panic for unreasonably high values. // Written to trigger const/debug panic for unreasonably high values.
let der_signature_size = 10 + (62 - bytes_to_grind); let der_signature_size = 10 + (62 - bytes_to_grind);
let witness_size = 1 // length of element count varint InputWeightPrediction::from_slice(0, &[der_signature_size, 33])
+ 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. /// Computes the prediction for a single input.
@ -1465,36 +1457,6 @@ mod tests {
assert_eq!(raw_tx, &buf[..size]); assert_eq!(raw_tx, &buf[..size]);
} }
#[test]
fn predict_weight_all_witness_size() {
// 109
let p2wpkh = InputWeightPrediction::P2WPKH_MAX;
// 66
let p2tr_default = InputWeightPrediction::P2TR_KEY_DEFAULT_SIGHASH;
// 67
let p2tr_non_default = InputWeightPrediction::P2TR_KEY_NON_DEFAULT_SIGHASH;
// 109 + 66 + 67 = 242
let p = vec![p2wpkh, p2tr_default, p2tr_non_default];
let output_script_lens = vec![1];
let w = predict_weight(p, output_script_lens);
// input_weight = partial_input_weight + input_count * 4 * (32 + 4 + 4)
// input_weight = 242 + 3 * 4 * (32 + 4 + 4)
// input_weight = 722
// output_size = 8 * output_count + output_scripts_size
// output_size = 8 * 1 + 2
// output_size = 10
// weight = non_input_size * 4 + input_weight + input_count - inputs_with_witnesses + 2
// weight = 20 * 4 + 722 + 3 - 3 + 2
// weight = 804
assert_eq!(w, Weight::from_wu(804));
}
#[test] #[test]
fn test_outpoint() { fn test_outpoint() {
assert_eq!(OutPoint::from_str("i don't care"), Err(ParseOutPointError::Format)); assert_eq!(OutPoint::from_str("i don't care"), Err(ParseOutPointError::Format));