diff --git a/mm2src/coins/utxo_signer/src/with_key_pair.rs b/mm2src/coins/utxo_signer/src/with_key_pair.rs index 8d67e23f9c..b62fa695f2 100644 --- a/mm2src/coins/utxo_signer/src/with_key_pair.rs +++ b/mm2src/coins/utxo_signer/src/with_key_pair.rs @@ -244,7 +244,7 @@ pub fn signature_hash_to_sign( } fn sign_message(message: &H256, key_pair: &KeyPair) -> UtxoSignWithKeyPairResult { - let signature = key_pair.private().sign(message)?; + let signature = key_pair.private().sign_low_r(message)?; Ok(Bytes::from(signature.to_vec())) } diff --git a/mm2src/mm2_bitcoin/keys/src/keypair.rs b/mm2src/mm2_bitcoin/keys/src/keypair.rs index 0e29150f60..4c3abdb8f4 100644 --- a/mm2src/mm2_bitcoin/keys/src/keypair.rs +++ b/mm2src/mm2_bitcoin/keys/src/keypair.rs @@ -124,7 +124,7 @@ mod tests { fn check_sign(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool { let message = dhash256(raw_message); let kp = KeyPair::from_private(secret.into()).unwrap(); - kp.private().sign(&message).unwrap() == signature.into() + kp.private().sign_low_r(&message).unwrap() == signature.into() } fn check_verify(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool { diff --git a/mm2src/mm2_bitcoin/keys/src/private.rs b/mm2src/mm2_bitcoin/keys/src/private.rs index aeb60a7711..ce4e64a908 100644 --- a/mm2src/mm2_bitcoin/keys/src/private.rs +++ b/mm2src/mm2_bitcoin/keys/src/private.rs @@ -27,7 +27,16 @@ impl Private { pub fn sign(&self, message: &Message) -> Result { let secret = SecretKey::from_slice(&*self.secret)?; let message = SecpMessage::from_slice(&**message)?; - // use low R signing from bitcoin which reduces signature malleability + let signature = SECP_SIGN.sign(&message, &secret); + let data = signature.serialize_der(); + Ok(data.as_ref().to_vec().into()) + } + + /// Sign a message with a low R value, this reduces signature malleability for Bitcoin transactions + /// and makes fee estimation more reliable. + pub fn sign_low_r(&self, message: &Message) -> Result { + let secret = SecretKey::from_slice(&*self.secret)?; + let message = SecpMessage::from_slice(&**message)?; let signature = SECP_SIGN.sign_low_r(&message, &secret); let data = signature.serialize_der(); Ok(data.as_ref().to_vec().into()) diff --git a/mm2src/mm2_bitcoin/script/src/sign.rs b/mm2src/mm2_bitcoin/script/src/sign.rs index a560b22077..a70e423eea 100644 --- a/mm2src/mm2_bitcoin/script/src/sign.rs +++ b/mm2src/mm2_bitcoin/script/src/sign.rs @@ -262,7 +262,7 @@ impl TransactionInputSigner { ) -> TransactionInput { let hash = self.signature_hash(input_index, input_amount, script_pubkey, sigversion, sighash); - let mut signature: Vec = keypair.private().sign(&hash).unwrap().into(); + let mut signature: Vec = keypair.private().sign_low_r(&hash).unwrap().into(); signature.push(sighash as u8); let script_sig = Builder::default() .push_data(&signature)