Skip to content

Commit

Permalink
- rename super_sign
Browse files Browse the repository at this point in the history
- add methods to feature-traits
  • Loading branch information
grandima committed Oct 31, 2024
1 parent ea15d09 commit a353cf6
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 249 deletions.
5 changes: 4 additions & 1 deletion crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ mod signed;
pub use signed::{BigIntConversionError, ParseSignedError, Sign, Signed};

mod signature;
pub use signature::{normalize_v, to_eip155_v, Parity, PrimitiveSignature, EcdsaSignature, Signature, SignatureError};
pub use signature::{
normalize_v, to_eip155_v, ArbitrarySuperSig, EcdsaSignature, K256SuperSig, Parity,
PrimitiveSignature, RlpSuperSig, SerdeSuperSig, Signature, SignatureError,
};

pub mod utils;
pub use utils::{eip191_hash_message, keccak256, Keccak256};
Expand Down
261 changes: 133 additions & 128 deletions crates/primitives/src/signature/ecdsa_sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

use crate::{
hex,
signature::{sig::Signature, Parity, SignatureError},
signature::{
sig::Signature,
super_sig::{ArbitrarySuperSig, K256SuperSig, RlpSuperSig, SerdeSuperSig},
Parity, SignatureError,
},
uint, U256,
};
use alloc::vec::Vec;
use core::str::FromStr;
use crate::signature::super_signature::{ArbitrarySuperSig, K256SuperSig, RlpSuperSig, SerdeSuperSig};

/// The order of the secp256k1 curve
const SECP256K1N_ORDER: U256 =
Expand All @@ -21,63 +24,20 @@ pub struct EcdsaSignature {
s: U256,
}

#[cfg(test)]
impl EcdsaSignature {
/// Returns the recovery ID.
#[cfg(feature = "k256")]
#[inline]
const fn recid(&self) -> k256::ecdsa::RecoveryId {
self.v.recid()
}

#[cfg(feature = "k256")]
#[doc(hidden)]
#[deprecated(note = "use `Signature::recid` instead")]
pub const fn recovery_id(&self) -> k256::ecdsa::RecoveryId {
self.recid()
}

#[doc(hidden)]
fn test_signature() -> Self {
Self::from_scalars_and_parity(
b256!("840cfc572845f5786e702984c2a582528cad4b49b2a10b9db1be7fca90058565"),
b256!("25e7109ceb98168d95b09b18bbf6b685130e0562f233877d492b94eee0c5b6d1"),
false,
)
.unwrap()
.unwrap()
}
}

impl RlpSuperSig for EcdsaSignature {}

impl K256SuperSig for EcdsaSignature {}

impl SerdeSuperSig for EcdsaSignature {}

impl ArbitrarySuperSig for EcdsaSignature {}

impl Signature for EcdsaSignature {
/// Instantiate a new signature from `r`, `s`, and `v` values.
fn new(r: U256, s: U256, v: Parity) -> Self {
Self { r, s, v }
}

/// Returns the `r` component of this signature.
#[inline]
fn r(&self) -> U256 {
self.r
}

/// Returns the `s` component of this signature.
#[inline]
fn s(&self) -> U256 {
self.s
}

/// Returns the recovery ID as a `u8`.
#[inline]
fn v(&self) -> Parity {
self.v
}
impl RlpSuperSig for EcdsaSignature {
#[cfg(feature = "rlp")]
fn decode_rlp_vrs(buf: &mut &[u8]) -> Result<Self, alloy_rlp::Error> {
use alloy_rlp::Decodable;
Expand All @@ -90,34 +50,40 @@ impl Signature for EcdsaSignature {
.map_err(|_| alloy_rlp::Error::Custom("attempted to decode invalid field element"))
}

/// Returns the byte-array representation of this signature.
///
/// The first 32 bytes are the `r` value, the second 32 bytes the `s` value
/// and the final byte is the `v` value in 'Electrum' notation.
#[inline]
fn as_bytes(&self) -> [u8; 65] {
let mut sig = [0u8; 65];
sig[..32].copy_from_slice(&self.r.to_be_bytes::<32>());
sig[32..64].copy_from_slice(&self.s.to_be_bytes::<32>());
sig[64] = self.v.y_parity_byte_non_eip155().unwrap_or(self.v.y_parity_byte());
sig
/// Length of RLP RS field encoding
#[cfg(feature = "rlp")]
fn rlp_rs_len(&self) -> usize {
alloy_rlp::Encodable::length(&self.r) + alloy_rlp::Encodable::length(&self.s)
}

/// Normalizes the signature into "low S" form as described in
/// [BIP 0062: Dealing with Malleability][1].
///
/// [1]: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki
#[inline]
fn normalize_s(&self) -> Option<Self> {
let s = self.s();
#[cfg(feature = "rlp")]
/// Length of RLP V field encoding
fn rlp_vrs_len(&self) -> usize {
self.rlp_rs_len() + alloy_rlp::Encodable::length(&self.v)
}

if s > SECP256K1N_ORDER >> 1 {
Some(Self { v: self.v.inverted(), r: self.r, s: SECP256K1N_ORDER - s })
} else {
None
}
/// Write R and S to an RLP buffer in progress.
#[cfg(feature = "rlp")]
fn write_rlp_rs(&self, out: &mut dyn alloy_rlp::BufMut) {
alloy_rlp::Encodable::encode(&self.r, out);
alloy_rlp::Encodable::encode(&self.s, out);
}

/// Write the V to an RLP buffer without using EIP-155.
#[cfg(feature = "rlp")]
fn write_rlp_v(&self, out: &mut dyn alloy_rlp::BufMut) {
alloy_rlp::Encodable::encode(&self.v, out);
}

/// Write the VRS to the output. The V will always be 27 or 28.
#[cfg(feature = "rlp")]
fn write_rlp_vrs(&self, out: &mut dyn alloy_rlp::BufMut) {
self.write_rlp_v(out);
self.write_rlp_rs(out);
}
}

impl K256SuperSig for EcdsaSignature {
/// Recovers an [`Address`] from this signature and the given message by first prefixing and
/// hashing the message according to [EIP-191](crate::eip191_hash_message).
///
Expand Down Expand Up @@ -174,6 +140,102 @@ impl Signature for EcdsaSignature {
.map_err(Into::into)
}

/// Returns the inner ECDSA signature.
#[cfg(feature = "k256")]
#[inline]
fn into_inner(self) -> k256::ecdsa::Signature {
self.try_into().expect("signature conversion failed")
}

/// Returns the inner ECDSA signature.
#[cfg(feature = "k256")]
#[inline]
fn to_k256(&self) -> Result<k256::ecdsa::Signature, k256::ecdsa::Error> {
k256::ecdsa::Signature::from_scalars(self.r.to_be_bytes(), self.s.to_be_bytes())
}

/// Instantiate from a signature and recovery id
#[cfg(feature = "k256")]
fn from_signature_and_parity<T: TryInto<Parity, Error = E>, E: Into<SignatureError>>(
sig: k256::ecdsa::Signature,
parity: T,
) -> Result<Self, SignatureError> {
let r = U256::from_be_slice(sig.r().to_bytes().as_ref());
let s = U256::from_be_slice(sig.s().to_bytes().as_ref());
Ok(Self { v: parity.try_into().map_err(Into::into)?, r, s })
}

/// Returns the recovery ID.
#[cfg(feature = "k256")]
#[inline]
fn recid(&self) -> k256::ecdsa::RecoveryId {
self.v.recid()
}

/// Deprecated - use `Signature::recid` instead
#[cfg(feature = "k256")]
#[doc(hidden)]
fn recovery_id(&self) -> k256::ecdsa::RecoveryId {
self.recid()
}
}

impl SerdeSuperSig for EcdsaSignature {}

impl ArbitrarySuperSig for EcdsaSignature {}

impl Signature for EcdsaSignature {
/// Instantiate a new signature from `r`, `s`, and `v` values.
fn new(r: U256, s: U256, v: Parity) -> Self {
Self { r, s, v }
}

/// Returns the `r` component of this signature.
#[inline]
fn r(&self) -> U256 {
self.r
}

/// Returns the `s` component of this signature.
#[inline]
fn s(&self) -> U256 {
self.s
}

/// Returns the recovery ID as a `u8`.
#[inline]
fn v(&self) -> Parity {
self.v
}

/// Returns the byte-array representation of this signature.
///
/// The first 32 bytes are the `r` value, the second 32 bytes the `s` value
/// and the final byte is the `v` value in 'Electrum' notation.
#[inline]
fn as_bytes(&self) -> [u8; 65] {
let mut sig = [0u8; 65];
sig[..32].copy_from_slice(&self.r.to_be_bytes::<32>());
sig[32..64].copy_from_slice(&self.s.to_be_bytes::<32>());
sig[64] = self.v.y_parity_byte_non_eip155().unwrap_or(self.v.y_parity_byte());
sig
}

/// Normalizes the signature into "low S" form as described in
/// [BIP 0062: Dealing with Malleability][1].
///
/// [1]: https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki
#[inline]
fn normalize_s(&self) -> Option<Self> {
let s = self.s();

if s > SECP256K1N_ORDER >> 1 {
Some(Self { v: self.v.inverted(), r: self.r, s: SECP256K1N_ORDER - s })
} else {
None
}
}

/// Modifies the recovery ID by applying [EIP-155] to a `v` value.
///
/// [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
Expand Down Expand Up @@ -232,63 +294,6 @@ impl Signature for EcdsaSignature {
) -> Result<Self, SignatureError> {
Ok(Self { v: parity.try_into().map_err(Into::into)?, r, s })
}

/// Length of RLP RS field encoding
#[cfg(feature = "rlp")]
fn rlp_rs_len(&self) -> usize {
alloy_rlp::Encodable::length(&self.r) + alloy_rlp::Encodable::length(&self.s)
}

#[cfg(feature = "rlp")]
/// Length of RLP V field encoding
fn rlp_vrs_len(&self) -> usize {
self.rlp_rs_len() + alloy_rlp::Encodable::length(&self.v)
}

/// Write R and S to an RLP buffer in progress.
#[cfg(feature = "rlp")]
fn write_rlp_rs(&self, out: &mut dyn alloy_rlp::BufMut) {
alloy_rlp::Encodable::encode(&self.r, out);
alloy_rlp::Encodable::encode(&self.s, out);
}

/// Write the V to an RLP buffer without using EIP-155.
#[cfg(feature = "rlp")]
fn write_rlp_v(&self, out: &mut dyn alloy_rlp::BufMut) {
alloy_rlp::Encodable::encode(&self.v, out);
}

/// Write the VRS to the output. The V will always be 27 or 28.
#[cfg(feature = "rlp")]
fn write_rlp_vrs(&self, out: &mut dyn alloy_rlp::BufMut) {
self.write_rlp_v(out);
self.write_rlp_rs(out);
}

/// Returns the inner ECDSA signature.
#[cfg(feature = "k256")]
#[inline]
fn into_inner(self) -> k256::ecdsa::Signature {
self.try_into().expect("signature conversion failed")
}

/// Returns the inner ECDSA signature.
#[cfg(feature = "k256")]
#[inline]
fn to_k256(&self) -> Result<k256::ecdsa::Signature, k256::ecdsa::Error> {
k256::ecdsa::Signature::from_scalars(self.r.to_be_bytes(), self.s.to_be_bytes())
}

/// Instantiate from a signature and recovery id
#[cfg(feature = "k256")]
fn from_signature_and_parity<T: TryInto<Parity, Error = E>, E: Into<SignatureError>>(
sig: k256::ecdsa::Signature,
parity: T,
) -> Result<Self, SignatureError> {
let r = U256::from_be_slice(sig.r().to_bytes().as_ref());
let s = U256::from_be_slice(sig.s().to_bytes().as_ref());
Ok(Self { v: parity.try_into().map_err(Into::into)?, r, s })
}
}

impl TryFrom<&[u8]> for EcdsaSignature {
Expand Down
5 changes: 3 additions & 2 deletions crates/primitives/src/signature/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ pub use ecdsa_sig::EcdsaSignature;

mod utils;

mod sig;
mod super_signature;
mod super_sig;
pub use super_sig::{ArbitrarySuperSig, K256SuperSig, RlpSuperSig, SerdeSuperSig};

mod sig;
pub use sig::Signature;

pub use utils::{normalize_v, to_eip155_v};
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/signature/primitive_sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl TryFrom<PrimitiveSignature> for k256::ecdsa::Signature {
#[cfg(feature = "rlp")]
impl PrimitiveSignature {
/// Decode an RLP-encoded VRS signature. Accepts `decode_parity` closure which allows to
/// customize parity decoding and possibly extract additional data from it (e.g chain_id for
/// customize parity decoding and possibly extract additional data from it (e.g. chain_id for
/// legacy signature).
pub fn decode_rlp_vrs(
buf: &mut &[u8],
Expand Down
Loading

0 comments on commit a353cf6

Please sign in to comment.