]> Untitled Git - bdk/commitdiff
test: Check tx feerate with longer signatures
authorDaniela Brozzoni <danielabrozzoni@protonmail.com>
Tue, 2 Aug 2022 09:31:31 +0000 (11:31 +0200)
committerDaniela Brozzoni <danielabrozzoni@protonmail.com>
Tue, 2 Aug 2022 10:08:56 +0000 (12:08 +0200)
This commit also suppresses the `unused_mut` warning
in `assert_fee_rate`, which happens because we call it
without `add_signatures`.

src/wallet/mod.rs

index 6aa8789a0ef88780367ae6f291eb0fb862c56ff3..66d34ba2a202a6b2032d428b947e5b4406984130 100644 (file)
@@ -2011,6 +2011,7 @@ pub(crate) mod test {
     macro_rules! assert_fee_rate {
         ($psbt:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
             let psbt = $psbt.clone();
+            #[allow(unused_mut)]
             let mut tx = $psbt.clone().extract_tx();
             $(
                 $( $add_signature )*
@@ -5088,4 +5089,66 @@ pub(crate) mod test {
             .current_height(maturity_time);
         builder.finish().unwrap();
     }
+
+    #[test]
+    fn test_fee_rate_sign_no_grinding_high_r() {
+        // Our goal is to obtain a transaction with a signature with high-R (71 bytes
+        // instead of 70). We then check that our fee rate and fee calculation is
+        // alright.
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let fee_rate = FeeRate::from_sat_per_vb(1.0);
+        let mut builder = wallet.build_tx();
+        let mut data = vec![0];
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .fee_rate(fee_rate)
+            .add_data(&data);
+        let (mut psbt, details) = builder.finish().unwrap();
+        let (op_return_vout, _) = psbt
+            .unsigned_tx
+            .output
+            .iter()
+            .enumerate()
+            .find(|(_n, i)| i.script_pubkey.is_op_return())
+            .unwrap();
+
+        let mut sig_len: usize = 0;
+        // We try to sign many different times until we find a longer signature (71 bytes)
+        while sig_len < 71 {
+            // Changing the OP_RETURN data will make the signature change (but not the fee, until
+            // data[0] is small enough)
+            data[0] += 1;
+            psbt.unsigned_tx.output[op_return_vout].script_pubkey = Script::new_op_return(&data);
+            // Clearing the previous signature
+            psbt.inputs[0].partial_sigs.clear();
+            // Signing
+            wallet
+                .sign(
+                    &mut psbt,
+                    SignOptions {
+                        remove_partial_sigs: false,
+                        try_finalize: false,
+                        ..Default::default()
+                    },
+                )
+                .unwrap();
+            // We only have one key in the partial_sigs map, this is a trick to retrieve it
+            let key = psbt.inputs[0].partial_sigs.keys().next().unwrap();
+            sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len();
+        }
+        // Actually finalizing the transaction...
+        wallet
+            .sign(
+                &mut psbt,
+                SignOptions {
+                    remove_partial_sigs: false,
+                    ..Default::default()
+                },
+            )
+            .unwrap();
+        // ...and checking that everything is fine
+        assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
+    }
 }