SignOptions {
remove_partial_sigs: false,
try_finalize: false,
+ allow_grinding: false,
..Default::default()
},
)
&mut psbt,
SignOptions {
remove_partial_sigs: false,
+ allow_grinding: false,
..Default::default()
},
)
assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
}
+ #[test]
+ fn test_fee_rate_sign_grinding_low_r() {
+ // Our goal is to obtain a transaction with a signature with low-R (70 bytes)
+ // by setting the `allow_grinding` signing option as true.
+ // We then check that our fee rate and fee calculation is alright and that our
+ // signature is 70 bytes.
+ 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();
+ builder
+ .drain_to(addr.script_pubkey())
+ .drain_wallet()
+ .fee_rate(fee_rate);
+ let (mut psbt, details) = builder.finish().unwrap();
+
+ wallet
+ .sign(
+ &mut psbt,
+ SignOptions {
+ remove_partial_sigs: false,
+ allow_grinding: true,
+ ..Default::default()
+ },
+ )
+ .unwrap();
+
+ let key = psbt.inputs[0].partial_sigs.keys().next().unwrap();
+ let sig_len = psbt.inputs[0].partial_sigs[key].sig.serialize_der().len();
+ assert_eq!(sig_len, 70);
+ assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
+ }
+
#[cfg(feature = "test-hardware-signer")]
#[test]
fn test_create_signer() {
hash,
hash_ty,
secp,
+ sign_options.allow_grinding,
);
Ok(())
hash: bitcoin::Sighash,
hash_ty: EcdsaSighashType,
secp: &SecpCtx,
+ allow_grinding: bool,
) {
let msg = &Message::from_slice(&hash.into_inner()[..]).unwrap();
- let sig = secp.sign_ecdsa(msg, secret_key);
+ let sig = if allow_grinding {
+ secp.sign_ecdsa_low_r(msg, secret_key)
+ } else {
+ secp.sign_ecdsa(msg, secret_key)
+ };
secp.verify_ecdsa(msg, &sig, &pubkey.inner)
.expect("invalid or corrupted ecdsa signature");
///
/// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
pub sign_with_tap_internal_key: bool,
+
+ /// Whether we should grind ECDSA signature to ensure signing with low r
+ /// or not.
+ /// Defaults to `true`, i.e., we always grind ECDSA signature to sign with low r.
+ pub allow_grinding: bool,
}
/// Customize which taproot script-path leaves the signer should sign.
try_finalize: true,
tap_leaves_options: TapLeavesOptions::default(),
sign_with_tap_internal_key: true,
+ allow_grinding: true,
}
}
}