mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-26 15:48:13 -05:00
chore: move all secp256k1 helpers to primitives-traits (#13363)
This commit is contained in:
@@ -13,15 +13,47 @@ pub const SECP256K1N_HALF: U256 = U256::from_be_bytes([
|
||||
]);
|
||||
|
||||
/// Secp256k1 utility functions.
|
||||
#[cfg(feature = "secp256k1")]
|
||||
pub mod secp256k1 {
|
||||
pub use super::impl_secp256k1::*;
|
||||
}
|
||||
use super::*;
|
||||
use revm_primitives::{Address, B256};
|
||||
|
||||
/// Secp256k1 utility functions.
|
||||
#[cfg(not(feature = "secp256k1"))]
|
||||
pub mod secp256k1 {
|
||||
pub use super::impl_k256::*;
|
||||
#[cfg(not(feature = "secp256k1"))]
|
||||
use super::impl_k256 as imp;
|
||||
#[cfg(feature = "secp256k1")]
|
||||
use super::impl_secp256k1 as imp;
|
||||
|
||||
pub use imp::{public_key_to_address, sign_message};
|
||||
|
||||
/// Recover signer from message hash, _without ensuring that the signature has a low `s`
|
||||
/// value_.
|
||||
///
|
||||
/// Using this for signature validation will succeed, even if the signature is malleable or not
|
||||
/// compliant with EIP-2. This is provided for compatibility with old signatures which have
|
||||
/// large `s` values.
|
||||
pub fn recover_signer_unchecked(signature: &Signature, hash: B256) -> Option<Address> {
|
||||
let mut sig: [u8; 65] = [0; 65];
|
||||
|
||||
sig[0..32].copy_from_slice(&signature.r().to_be_bytes::<32>());
|
||||
sig[32..64].copy_from_slice(&signature.s().to_be_bytes::<32>());
|
||||
sig[64] = signature.v() as u8;
|
||||
|
||||
// NOTE: we are removing error from underlying crypto library as it will restrain primitive
|
||||
// errors and we care only if recovery is passing or not.
|
||||
imp::recover_signer_unchecked(&sig, &hash.0).ok()
|
||||
}
|
||||
|
||||
/// Recover signer address from message hash. This ensures that the signature S value is
|
||||
/// greater than `secp256k1n / 2`, as specified in
|
||||
/// [EIP-2](https://eips.ethereum.org/EIPS/eip-2).
|
||||
///
|
||||
/// If the S value is too large, then this will return `None`
|
||||
pub fn recover_signer(signature: &Signature, hash: B256) -> Option<Address> {
|
||||
if signature.s() > SECP256K1N_HALF {
|
||||
return None
|
||||
}
|
||||
|
||||
recover_signer_unchecked(signature, hash)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "secp256k1")]
|
||||
@@ -41,7 +73,10 @@ mod impl_secp256k1 {
|
||||
///
|
||||
/// This does not ensure that the `s` value in the signature is low, and _just_ wraps the
|
||||
/// underlying secp256k1 library.
|
||||
pub fn recover_signer_unchecked(sig: &[u8; 65], msg: &[u8; 32]) -> Result<Address, Error> {
|
||||
pub(crate) fn recover_signer_unchecked(
|
||||
sig: &[u8; 65],
|
||||
msg: &[u8; 32],
|
||||
) -> Result<Address, Error> {
|
||||
let sig =
|
||||
RecoverableSignature::from_compact(&sig[0..64], RecoveryId::from_i32(sig[64] as i32)?)?;
|
||||
|
||||
@@ -87,7 +122,10 @@ mod impl_k256 {
|
||||
///
|
||||
/// This does not ensure that the `s` value in the signature is low, and _just_ wraps the
|
||||
/// underlying secp256k1 library.
|
||||
pub fn recover_signer_unchecked(sig: &[u8; 65], msg: &[u8; 32]) -> Result<Address, Error> {
|
||||
pub(crate) fn recover_signer_unchecked(
|
||||
sig: &[u8; 65],
|
||||
msg: &[u8; 32],
|
||||
) -> Result<Address, Error> {
|
||||
let mut signature = k256::ecdsa::Signature::from_slice(&sig[0..64])?;
|
||||
let mut recid = sig[64];
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::transaction::util::secp256k1;
|
||||
use alloy_consensus::transaction::from_eip155_value;
|
||||
use alloy_primitives::{Address, PrimitiveSignature as Signature, B256, U256};
|
||||
use alloy_primitives::{PrimitiveSignature as Signature, U256};
|
||||
use alloy_rlp::Decodable;
|
||||
use reth_primitives_traits::crypto::SECP256K1N_HALF;
|
||||
|
||||
pub use reth_primitives_traits::crypto::secp256k1::{recover_signer, recover_signer_unchecked};
|
||||
|
||||
pub(crate) fn decode_with_eip155_chain_id(
|
||||
buf: &mut &[u8],
|
||||
@@ -26,43 +26,10 @@ pub(crate) fn decode_with_eip155_chain_id(
|
||||
Ok((Signature::new(r, s, parity), chain_id))
|
||||
}
|
||||
|
||||
/// Recover signer from message hash, _without ensuring that the signature has a low `s`
|
||||
/// value_.
|
||||
///
|
||||
/// Using this for signature validation will succeed, even if the signature is malleable or not
|
||||
/// compliant with EIP-2. This is provided for compatibility with old signatures which have
|
||||
/// large `s` values.
|
||||
pub fn recover_signer_unchecked(signature: &Signature, hash: B256) -> Option<Address> {
|
||||
let mut sig: [u8; 65] = [0; 65];
|
||||
|
||||
sig[0..32].copy_from_slice(&signature.r().to_be_bytes::<32>());
|
||||
sig[32..64].copy_from_slice(&signature.s().to_be_bytes::<32>());
|
||||
sig[64] = signature.v() as u8;
|
||||
|
||||
// NOTE: we are removing error from underlying crypto library as it will restrain primitive
|
||||
// errors and we care only if recovery is passing or not.
|
||||
secp256k1::recover_signer_unchecked(&sig, &hash.0).ok()
|
||||
}
|
||||
|
||||
/// Recover signer address from message hash. This ensures that the signature S value is
|
||||
/// greater than `secp256k1n / 2`, as specified in
|
||||
/// [EIP-2](https://eips.ethereum.org/EIPS/eip-2).
|
||||
///
|
||||
/// If the S value is too large, then this will return `None`
|
||||
pub fn recover_signer(signature: &Signature, hash: B256) -> Option<Address> {
|
||||
if signature.s() > SECP256K1N_HALF {
|
||||
return None
|
||||
}
|
||||
|
||||
recover_signer_unchecked(signature, hash)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::transaction::signature::{
|
||||
recover_signer, recover_signer_unchecked, SECP256K1N_HALF,
|
||||
};
|
||||
use alloy_eips::eip2718::Decodable2718;
|
||||
use crate::transaction::signature::{recover_signer, recover_signer_unchecked};
|
||||
use alloy_eips::{eip2718::Decodable2718, eip7702::constants::SECP256K1N_HALF};
|
||||
use alloy_primitives::{hex, Address, PrimitiveSignature as Signature, B256, U256};
|
||||
use reth_primitives_traits::SignedTransaction;
|
||||
use std::str::FromStr;
|
||||
|
||||
Reference in New Issue
Block a user