Merge bitcoindevkit/bdk#779: Add signature grinding for ECDSA signatures
68dd6d20311b28f5c8e8c9657dce8cddae4f7aa3 Add signature grinding for ECDSA signatures (Vladimir Fomene) Pull request description: ### Description This PR adds a new field called `allow_grinding` in the Signer's `SignOptions` struct that is used to determine whether or not to grind an ECDSA signature during the signing process. ### Changelog notice Breaking change: the BDK Signer now produces low-R signatures by default, saving one byte. If you want to preserve the original behavior, set `allow_grinding` in the `SignOptions` to `false`. ### Notes to the reviewers This PR resolves issue #695 #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [ ] I've added tests for the new feature * [x] I've added docs for the new feature #### Bugfixes: * [ ] This pull request breaks the existing API * [ ] I've added tests to reproduce the issue which are now passing * [x] I'm linking the issue being fixed by this PR ACKs for top commit: danielabrozzoni: ACK 68dd6d20311b28f5c8e8c9657dce8cddae4f7aa3 rajarshimaitra: ACK 68dd6d20311b28f5c8e8c9657dce8cddae4f7aa3 Tree-SHA512: 6472338c611b4b32986cf66fcd313ef84f17f5b0ae9e7991ea7da47142641ab812f8b325d4d18314e1a58abe462683101160e62e2363a048fdab3f18aee4d699
This commit is contained in:
commit
1c76084db8
@ -5524,6 +5524,7 @@ pub(crate) mod test {
|
|||||||
SignOptions {
|
SignOptions {
|
||||||
remove_partial_sigs: false,
|
remove_partial_sigs: false,
|
||||||
try_finalize: false,
|
try_finalize: false,
|
||||||
|
allow_grinding: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -5538,6 +5539,7 @@ pub(crate) mod test {
|
|||||||
&mut psbt,
|
&mut psbt,
|
||||||
SignOptions {
|
SignOptions {
|
||||||
remove_partial_sigs: false,
|
remove_partial_sigs: false,
|
||||||
|
allow_grinding: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -5546,6 +5548,39 @@ pub(crate) mod test {
|
|||||||
assert_fee_rate!(psbt, details.fee.unwrap_or(0), fee_rate);
|
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")]
|
#[cfg(feature = "test-hardware-signer")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_signer() {
|
fn test_create_signer() {
|
||||||
|
@ -472,6 +472,7 @@ impl InputSigner for SignerWrapper<PrivateKey> {
|
|||||||
hash,
|
hash,
|
||||||
hash_ty,
|
hash_ty,
|
||||||
secp,
|
secp,
|
||||||
|
sign_options.allow_grinding,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -485,9 +486,14 @@ fn sign_psbt_ecdsa(
|
|||||||
hash: bitcoin::Sighash,
|
hash: bitcoin::Sighash,
|
||||||
hash_ty: EcdsaSighashType,
|
hash_ty: EcdsaSighashType,
|
||||||
secp: &SecpCtx,
|
secp: &SecpCtx,
|
||||||
|
allow_grinding: bool,
|
||||||
) {
|
) {
|
||||||
let msg = &Message::from_slice(&hash.into_inner()[..]).unwrap();
|
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)
|
secp.verify_ecdsa(msg, &sig, &pubkey.inner)
|
||||||
.expect("invalid or corrupted ecdsa signature");
|
.expect("invalid or corrupted ecdsa signature");
|
||||||
|
|
||||||
@ -718,6 +724,11 @@ pub struct SignOptions {
|
|||||||
///
|
///
|
||||||
/// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
|
/// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
|
||||||
pub sign_with_tap_internal_key: bool,
|
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.
|
/// Customize which taproot script-path leaves the signer should sign.
|
||||||
@ -751,6 +762,7 @@ impl Default for SignOptions {
|
|||||||
try_finalize: true,
|
try_finalize: true,
|
||||||
tap_leaves_options: TapLeavesOptions::default(),
|
tap_leaves_options: TapLeavesOptions::default(),
|
||||||
sign_with_tap_internal_key: true,
|
sign_with_tap_internal_key: true,
|
||||||
|
allow_grinding: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user