From 2e53fd8db342a9143636ee1710299c2e3ad1f02d Mon Sep 17 00:00:00 2001 From: leruaa Date: Fri, 19 Jul 2024 15:42:21 +0200 Subject: [PATCH 1/7] feat: expose Signature --- crates/core/src/lib.rs | 5 - crates/primitives/Cargo.toml | 2 +- crates/primitives/src/lib.rs | 18 +-- crates/primitives/src/signature/builder.rs | 17 ++ crates/primitives/src/signature/mod.rs | 8 +- crates/primitives/src/signature/sig.rs | 179 ++++++++++++--------- 6 files changed, 126 insertions(+), 103 deletions(-) create mode 100644 crates/primitives/src/signature/builder.rs diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 93a3ecc46..255555b2b 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -12,11 +12,6 @@ pub use alloy_primitives as primitives; #[doc(no_inline)] pub use primitives::{hex, uint}; -#[cfg(feature = "unstable-doc")] -#[doc(hidden)] -#[allow(unused_imports)] -pub use primitives::PrivateSignature as _; - #[cfg(feature = "dyn-abi")] #[doc(inline)] pub use alloy_dyn_abi as dyn_abi; diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 3f4bd42d4..d51312721 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -70,7 +70,7 @@ criterion.workspace = true serde_json.workspace = true [features] -default = ["std"] +default = ["std", "k256"] std = [ "bytes/std", "hex/std", diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 6e8c65f30..daa645d0b 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -51,21 +51,13 @@ mod signed; pub use signed::{BigIntConversionError, ParseSignedError, Sign, Signed}; mod signature; -pub use signature::{to_eip155_v, Parity, SignatureError}; - -/// Only available for documentation purposes. -// Without this visible (not `#[doc(hidden)]`) re-export, `rustdoc` will not generate documentation -// for the `Signature` type alias below. -#[cfg(feature = "unstable-doc")] -pub use signature::Signature as PrivateSignature; +pub use signature::{ + to_eip155_v, Parity, RawSignature, Signature, SignatureBuilder, SignatureError, +}; -/// An ECDSA Signature, consisting of V, R, and S. +/// A memoized ECDSA Signature, consisting of V, R, and S. #[cfg(feature = "k256")] -pub type Signature = signature::Signature; - -/// An ECDSA Signature, consisting of V, R, and S. -#[cfg(not(feature = "k256"))] -pub type Signature = signature::Signature<()>; +pub type MemoizedSignature = signature::Signature; pub mod utils; pub use utils::{eip191_hash_message, keccak256, Keccak256}; diff --git a/crates/primitives/src/signature/builder.rs b/crates/primitives/src/signature/builder.rs new file mode 100644 index 000000000..b944429ec --- /dev/null +++ b/crates/primitives/src/signature/builder.rs @@ -0,0 +1,17 @@ +use crate::{Parity, SignatureError, U256}; + +/// Trait used to uniformize signature creation. +pub trait SignatureBuilder: Sized { + /// Instantiate from v, r, s. + fn from_rs_and_parity, E: Into>( + r: U256, + s: U256, + parity: P, + ) -> Result; + + /// Parses a signature from a byte slice, with a v value + fn from_bytes_and_parity, E: Into>( + bytes: &[u8], + parity: P, + ) -> Result; +} diff --git a/crates/primitives/src/signature/mod.rs b/crates/primitives/src/signature/mod.rs index 5dd8e22a6..9ca43c4b6 100644 --- a/crates/primitives/src/signature/mod.rs +++ b/crates/primitives/src/signature/mod.rs @@ -1,3 +1,6 @@ +mod builder; +pub use builder::SignatureBuilder; + mod error; pub use error::SignatureError; @@ -5,10 +8,7 @@ mod parity; pub use parity::Parity; mod sig; -#[cfg(feature = "unstable-doc")] -pub use sig::Signature; -#[cfg(not(feature = "unstable-doc"))] -pub(crate) use sig::Signature; +pub use sig::{RawSignature, Signature}; mod utils; pub use utils::to_eip155_v; diff --git a/crates/primitives/src/signature/sig.rs b/crates/primitives/src/signature/sig.rs index 193d8ae07..8b3b2b5ad 100644 --- a/crates/primitives/src/signature/sig.rs +++ b/crates/primitives/src/signature/sig.rs @@ -6,7 +6,9 @@ use crate::{ U256, }; use alloc::vec::Vec; -use core::str::FromStr; +use core::{fmt::Debug, marker::PhantomData, str::FromStr}; + +use super::builder::SignatureBuilder; /// An Ethereum ECDSA signature. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -19,6 +21,9 @@ pub struct Signature { s: U256, } +/// An raw Ethereum ECDSA signature. +pub type RawSignature = Signature<()>; + #[cfg(feature = "k256")] impl<'a> TryFrom<&'a [u8]> for Signature { type Error = SignatureError; @@ -34,7 +39,7 @@ impl<'a> TryFrom<&'a [u8]> for Signature { } } -impl<'a> TryFrom<&'a [u8]> for Signature<()> { +impl<'a> TryFrom<&'a [u8]> for RawSignature { type Error = SignatureError; fn try_from(bytes: &'a [u8]) -> Result { @@ -55,7 +60,7 @@ impl FromStr for Signature { } } -impl FromStr for Signature<()> { +impl FromStr for RawSignature { type Err = SignatureError; fn from_str(s: &str) -> Result { @@ -64,30 +69,30 @@ impl FromStr for Signature<()> { } } -impl From<&crate::Signature> for [u8; 65] { +impl From<&Signature> for [u8; 65] { #[inline] - fn from(value: &crate::Signature) -> [u8; 65] { + fn from(value: &Signature) -> [u8; 65] { value.as_bytes() } } -impl From for [u8; 65] { +impl From> for [u8; 65] { #[inline] - fn from(value: crate::Signature) -> [u8; 65] { + fn from(value: Signature) -> [u8; 65] { value.as_bytes() } } -impl From<&crate::Signature> for Vec { +impl From<&Signature> for Vec { #[inline] - fn from(value: &crate::Signature) -> Self { + fn from(value: &Signature) -> Self { value.as_bytes().to_vec() } } -impl From for Vec { +impl From> for Vec { #[inline] - fn from(value: crate::Signature) -> Self { + fn from(value: Signature) -> Self { value.as_bytes().to_vec() } } @@ -100,7 +105,10 @@ impl From<(k256::ecdsa::Signature, k256::ecdsa::RecoveryId)> for Signature Signature +where + Self: SignatureBuilder, +{ /// Decode an RLP-encoded VRS signature. pub fn decode_rlp_vrs(buf: &mut &[u8]) -> Result { use alloy_rlp::Decodable; @@ -114,6 +122,26 @@ impl crate::Signature { } } +#[cfg(feature = "k256")] +impl SignatureBuilder for Signature { + fn from_rs_and_parity, E: Into>( + r: U256, + s: U256, + parity: T, + ) -> Result { + Self::from_scalars_and_parity(r.into(), s.into(), parity) + } + + #[inline] + fn from_bytes_and_parity, E: Into>( + bytes: &[u8], + parity: T, + ) -> Result { + let sig = k256::ecdsa::Signature::from_slice(bytes)?; + Self::from_signature_and_parity(sig, parity) + } +} + #[cfg(feature = "k256")] impl Signature { #[doc(hidden)] @@ -136,25 +164,6 @@ impl Signature { Ok(Self { inner: sig, v: parity.try_into().map_err(Into::into)?, r, s }) } - /// Instantiate from v, r, s. - pub fn from_rs_and_parity, E: Into>( - r: U256, - s: U256, - parity: T, - ) -> Result { - Self::from_scalars_and_parity(r.into(), s.into(), parity) - } - - /// Parses a signature from a byte slice, with a v value - #[inline] - pub fn from_bytes_and_parity, E: Into>( - bytes: &[u8], - parity: T, - ) -> Result { - let sig = k256::ecdsa::Signature::from_slice(bytes)?; - Self::from_signature_and_parity(sig, parity) - } - /// Creates a [`Signature`] from the serialized `r` and `s` scalar values, which comprise the /// ECDSA signature, alongside a `v` value, used to determine the recovery ID. /// @@ -249,29 +258,22 @@ impl Signature { } } -impl Signature<()> { - /// Parses a signature from a byte slice, with a v value - /// - /// # Panics - /// - /// If the slice is not at least 64 bytes long. - #[inline] - pub fn from_bytes_and_parity, E: Into>( - bytes: &[u8], +impl SignatureBuilder<()> for RawSignature { + fn from_rs_and_parity, E: Into>( + r: U256, + s: U256, parity: T, ) -> Result { - let r = U256::from_be_slice(&bytes[..32]); - let s = U256::from_be_slice(&bytes[32..64]); - Self::from_rs_and_parity(r, s, parity) + Ok(Self { inner: (), v: parity.try_into().map_err(Into::into)?, r, s }) } - /// Instantiate from v, r, s. - pub fn from_rs_and_parity, E: Into>( - r: U256, - s: U256, + fn from_bytes_and_parity, E: Into>( + bytes: &[u8], parity: T, ) -> Result { - Ok(Self { inner: (), v: parity.try_into().map_err(Into::into)?, r, s }) + let r = U256::from_be_slice(&bytes[..32]); + let s = U256::from_be_slice(&bytes[32..64]); + Self::from_rs_and_parity(r, s, parity) } } @@ -375,7 +377,7 @@ impl Signature { } #[cfg(feature = "rlp")] -impl alloy_rlp::Encodable for crate::Signature { +impl alloy_rlp::Encodable for Signature { fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { alloy_rlp::Header { list: true, payload_length: self.rlp_vrs_len() }.encode(out); self.write_rlp_vrs(out); @@ -388,7 +390,10 @@ impl alloy_rlp::Encodable for crate::Signature { } #[cfg(feature = "rlp")] -impl alloy_rlp::Decodable for crate::Signature { +impl alloy_rlp::Decodable for Signature +where + Self: SignatureBuilder, +{ fn decode(buf: &mut &[u8]) -> Result { let header = alloy_rlp::Header::decode(buf)?; let pre_len = buf.len(); @@ -403,7 +408,7 @@ impl alloy_rlp::Decodable for crate::Signature { } #[cfg(feature = "serde")] -impl serde::Serialize for crate::Signature { +impl serde::Serialize for Signature { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -437,7 +442,10 @@ impl serde::Serialize for crate::Signature { } #[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for crate::Signature { +impl<'de, T> serde::Deserialize<'de> for Signature +where + Self: SignatureBuilder, +{ fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -486,9 +494,12 @@ impl<'de> serde::Deserialize<'de> for crate::Signature { } } - struct MapVisitor; - impl<'de> serde::de::Visitor<'de> for MapVisitor { - type Value = crate::Signature; + struct MapVisitor(PhantomData); + impl<'de, T> serde::de::Visitor<'de> for MapVisitor + where + Signature: SignatureBuilder, + { + type Value = Signature; fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("a JSON signature object containing r, s, and v or yParity") @@ -536,13 +547,16 @@ impl<'de> serde::Deserialize<'de> for crate::Signature { let r = r.ok_or_else(|| serde::de::Error::missing_field("r"))?; let s = s.ok_or_else(|| serde::de::Error::missing_field("s"))?; - crate::Signature::from_rs_and_parity(r, s, v).map_err(serde::de::Error::custom) + Signature::::from_rs_and_parity(r, s, v).map_err(serde::de::Error::custom) } } - struct TupleVisitor; - impl<'de> serde::de::Visitor<'de> for TupleVisitor { - type Value = crate::Signature; + struct TupleVisitor(PhantomData); + impl<'de, T> serde::de::Visitor<'de> for TupleVisitor + where + Signature: SignatureBuilder, + { + type Value = Signature; fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("a tuple containing r, s, and v") @@ -562,20 +576,23 @@ impl<'de> serde::Deserialize<'de> for crate::Signature { .next_element()? .ok_or_else(|| serde::de::Error::invalid_length(2, &self))?; - crate::Signature::from_rs_and_parity(r, s, v).map_err(serde::de::Error::custom) + Signature::::from_rs_and_parity(r, s, v).map_err(serde::de::Error::custom) } } if deserializer.is_human_readable() { - deserializer.deserialize_map(MapVisitor) + deserializer.deserialize_map(MapVisitor(Default::default())) } else { - deserializer.deserialize_tuple(3, TupleVisitor) + deserializer.deserialize_tuple(3, TupleVisitor(Default::default())) } } } #[cfg(feature = "arbitrary")] -impl<'a> arbitrary::Arbitrary<'a> for crate::Signature { +impl<'a, T> arbitrary::Arbitrary<'a> for Signature +where + Self: SignatureBuilder, +{ fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { Self::from_rs_and_parity(u.arbitrary()?, u.arbitrary()?, u.arbitrary::()?) .map_err(|_| arbitrary::Error::IncorrectFormat) @@ -583,7 +600,11 @@ impl<'a> arbitrary::Arbitrary<'a> for crate::Signature { } #[cfg(feature = "arbitrary")] -impl proptest::arbitrary::Arbitrary for crate::Signature { +impl proptest::arbitrary::Arbitrary for Signature +where + T: Debug, + Self: SignatureBuilder, +{ type Parameters = (); type Strategy = proptest::strategy::FilterMap< <(U256, U256, Parity) as proptest::arbitrary::Arbitrary>::Strategy, @@ -631,11 +652,11 @@ mod tests { #[test] fn signature_from_str() { - let s1 = crate::Signature::from_str( + let s1 = RawSignature::from_str( "0xaa231fbe0ed2b5418e6ba7c19bee2522852955ec50996c02a2fe3e71d30ddaf1645baf4823fea7cb4fcc7150842493847cfb6a6d63ab93e8ee928ee3f61f503500" ).expect("could not parse 0x-prefixed signature"); - let s2 = crate::Signature::from_str( + let s2 = RawSignature::from_str( "aa231fbe0ed2b5418e6ba7c19bee2522852955ec50996c02a2fe3e71d30ddaf1645baf4823fea7cb4fcc7150842493847cfb6a6d63ab93e8ee928ee3f61f503500" ).expect("could not parse non-prefixed signature"); @@ -651,10 +672,9 @@ mod tests { "v":"0x1" }"#; - let signature: crate::Signature = - serde_json::from_str(raw_signature_without_y_parity).unwrap(); + let signature: RawSignature = serde_json::from_str(raw_signature_without_y_parity).unwrap(); - let expected = crate::Signature::from_rs_and_parity( + let expected = RawSignature::from_rs_and_parity( U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0") .unwrap(), U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05") @@ -679,10 +699,9 @@ mod tests { ); println!("{raw_signature_with_y_parity}"); - let signature: crate::Signature = - serde_json::from_value(raw_signature_with_y_parity).unwrap(); + let signature: RawSignature = serde_json::from_value(raw_signature_with_y_parity).unwrap(); - let expected = crate::Signature::from_rs_and_parity( + let expected = RawSignature::from_rs_and_parity( U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0") .unwrap(), U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05") @@ -698,7 +717,7 @@ mod tests { #[test] fn serialize_both_parity() { // this test should be removed if the struct moves to an enum based on tx type - let signature = crate::Signature::from_rs_and_parity( + let signature = RawSignature::from_rs_and_parity( U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0") .unwrap(), U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05") @@ -718,7 +737,7 @@ mod tests { #[test] fn serialize_v_only() { // this test should be removed if the struct moves to an enum based on tx type - let signature = crate::Signature::from_rs_and_parity( + let signature = RawSignature::from_rs_and_parity( U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0") .unwrap(), U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05") @@ -736,7 +755,7 @@ mod tests { #[cfg(feature = "serde")] #[test] fn test_bincode_roundtrip() { - let signature = crate::Signature::from_rs_and_parity( + let signature = RawSignature::from_rs_and_parity( U256::from_str("0xc569c92f176a3be1a6352dd5005bfc751dcb32f57623dd2a23693e64bf4447b0") .unwrap(), U256::from_str("0x1a891b566d369e79b7a66eecab1e008831e22daa15f91a0a0cf4f9f28f47ee05") @@ -746,7 +765,7 @@ mod tests { .unwrap(); let bin = bincode::serialize(&signature).unwrap(); - assert_eq!(bincode::deserialize::(&bin).unwrap(), signature); + assert_eq!(bincode::deserialize::(&bin).unwrap(), signature); } #[cfg(feature = "rlp")] @@ -756,12 +775,12 @@ mod tests { let bytes = crate::hex!("f84301a048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a010002cef538bc0c8e21c46080634a93e082408b0ad93f4a7207e63ec5463793d"); // Decode the byte sequence into a Signature instance - let result = Signature::decode(&mut &bytes[..]).unwrap(); + let result = RawSignature::decode(&mut &bytes[..]).unwrap(); // Assert that the decoded Signature matches the expected Signature assert_eq!( result, - Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3664935310002cef538bc0c8e21c46080634a93e082408b0ad93f4a7207e63ec5463793d01").unwrap() + RawSignature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3664935310002cef538bc0c8e21c46080634a93e082408b0ad93f4a7207e63ec5463793d01").unwrap() ); } @@ -769,7 +788,7 @@ mod tests { #[test] fn signature_rlp_encode() { // Given a Signature instance - let sig = Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap(); + let sig = RawSignature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap(); // Initialize an empty buffer let mut buf = vec![]; @@ -788,7 +807,7 @@ mod tests { #[test] fn signature_rlp_length() { // Given a Signature instance - let sig = Signature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap(); + let sig = RawSignature::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c8041b").unwrap(); // Assert that the length of the Signature matches the expected length assert_eq!(sig.length(), 69); From e9531d3343409e57d882f1cad3491f6fe1f3f98b Mon Sep 17 00:00:00 2001 From: leruaa Date: Fri, 19 Jul 2024 15:45:30 +0200 Subject: [PATCH 2/7] fix: ooops --- crates/primitives/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index d51312721..3f4bd42d4 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -70,7 +70,7 @@ criterion.workspace = true serde_json.workspace = true [features] -default = ["std", "k256"] +default = ["std"] std = [ "bytes/std", "hex/std", From dd0b40559ab566208bbf3bffbbdfed6843556c90 Mon Sep 17 00:00:00 2001 From: leruaa Date: Fri, 19 Jul 2024 15:49:50 +0200 Subject: [PATCH 3/7] chore: unstable-doc is useless now --- crates/core/Cargo.toml | 4 +--- crates/primitives/Cargo.toml | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index bbafaa590..1781e6cde 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -59,6 +59,4 @@ arbitrary = [ "alloy-dyn-abi?/arbitrary", ] k256 = ["alloy-primitives/k256"] -eip712 = ["alloy-sol-types?/eip712-serde", "alloy-dyn-abi?/eip712"] - -unstable-doc = ["alloy-primitives/unstable-doc"] +eip712 = ["alloy-sol-types?/eip712-serde", "alloy-dyn-abi?/eip712"] \ No newline at end of file diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 3f4bd42d4..04fdbe645 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -110,8 +110,6 @@ allocative = ["dep:allocative"] # Should not be needed most of the time. hex-compat = ["hex/hex"] -unstable-doc = [] - [[bench]] name = "primitives" path = "benches/primitives.rs" From c7e75357745c2390f7019be34038ebce6a9633fe Mon Sep 17 00:00:00 2001 From: leruaa Date: Sat, 20 Jul 2024 17:01:21 +0000 Subject: [PATCH 4/7] feat: allow to instanciate `RawSignature` --- crates/primitives/src/signature/sig.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/primitives/src/signature/sig.rs b/crates/primitives/src/signature/sig.rs index 8b3b2b5ad..1fa4e469a 100644 --- a/crates/primitives/src/signature/sig.rs +++ b/crates/primitives/src/signature/sig.rs @@ -24,6 +24,13 @@ pub struct Signature { /// An raw Ethereum ECDSA signature. pub type RawSignature = Signature<()>; +impl RawSignature { + /// Creates a new [`RawSignature`]. + pub const fn new(v: Parity, r: U256, s: U256) -> Self { + Self { inner: (), v, r, s } + } +} + #[cfg(feature = "k256")] impl<'a> TryFrom<&'a [u8]> for Signature { type Error = SignatureError; @@ -343,6 +350,11 @@ impl Signature { Self { inner: self.inner, v: parity.into(), r: self.r, s: self.s } } + /// Converts the signature into a [`RawSignature`]. + pub fn into_raw(self) -> RawSignature { + RawSignature::new(self.v, self.r, self.s) + } + /// Length of RLP RS field encoding #[cfg(feature = "rlp")] pub fn rlp_rs_len(&self) -> usize { From 0166e1a35c3ee473272682d1f48c991b3f44714f Mon Sep 17 00:00:00 2001 From: leruaa Date: Sat, 20 Jul 2024 19:13:58 +0000 Subject: [PATCH 5/7] feat: streamline BuildableSignature --- crates/primitives/src/lib.rs | 2 +- .../signature/{builder.rs => buildable.rs} | 2 +- crates/primitives/src/signature/mod.rs | 4 ++-- crates/primitives/src/signature/sig.rs | 20 +++++++++---------- 4 files changed, 14 insertions(+), 14 deletions(-) rename crates/primitives/src/signature/{builder.rs => buildable.rs} (93%) diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index daa645d0b..fcd1b0790 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -52,7 +52,7 @@ pub use signed::{BigIntConversionError, ParseSignedError, Sign, Signed}; mod signature; pub use signature::{ - to_eip155_v, Parity, RawSignature, Signature, SignatureBuilder, SignatureError, + to_eip155_v, BuildableSignature, Parity, RawSignature, Signature, SignatureError, }; /// A memoized ECDSA Signature, consisting of V, R, and S. diff --git a/crates/primitives/src/signature/builder.rs b/crates/primitives/src/signature/buildable.rs similarity index 93% rename from crates/primitives/src/signature/builder.rs rename to crates/primitives/src/signature/buildable.rs index b944429ec..de47c0ef7 100644 --- a/crates/primitives/src/signature/builder.rs +++ b/crates/primitives/src/signature/buildable.rs @@ -1,7 +1,7 @@ use crate::{Parity, SignatureError, U256}; /// Trait used to uniformize signature creation. -pub trait SignatureBuilder: Sized { +pub trait BuildableSignature: Sized { /// Instantiate from v, r, s. fn from_rs_and_parity, E: Into>( r: U256, diff --git a/crates/primitives/src/signature/mod.rs b/crates/primitives/src/signature/mod.rs index 9ca43c4b6..2ec0cc63c 100644 --- a/crates/primitives/src/signature/mod.rs +++ b/crates/primitives/src/signature/mod.rs @@ -1,5 +1,5 @@ -mod builder; -pub use builder::SignatureBuilder; +mod buildable; +pub use buildable::BuildableSignature; mod error; pub use error::SignatureError; diff --git a/crates/primitives/src/signature/sig.rs b/crates/primitives/src/signature/sig.rs index 1fa4e469a..8b3413563 100644 --- a/crates/primitives/src/signature/sig.rs +++ b/crates/primitives/src/signature/sig.rs @@ -8,7 +8,7 @@ use crate::{ use alloc::vec::Vec; use core::{fmt::Debug, marker::PhantomData, str::FromStr}; -use super::builder::SignatureBuilder; +use super::buildable::BuildableSignature; /// An Ethereum ECDSA signature. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -114,7 +114,7 @@ impl From<(k256::ecdsa::Signature, k256::ecdsa::RecoveryId)> for Signature Signature where - Self: SignatureBuilder, + Self: BuildableSignature, { /// Decode an RLP-encoded VRS signature. pub fn decode_rlp_vrs(buf: &mut &[u8]) -> Result { @@ -130,7 +130,7 @@ where } #[cfg(feature = "k256")] -impl SignatureBuilder for Signature { +impl BuildableSignature for Signature { fn from_rs_and_parity, E: Into>( r: U256, s: U256, @@ -265,7 +265,7 @@ impl Signature { } } -impl SignatureBuilder<()> for RawSignature { +impl BuildableSignature for RawSignature { fn from_rs_and_parity, E: Into>( r: U256, s: U256, @@ -404,7 +404,7 @@ impl alloy_rlp::Encodable for Signature { #[cfg(feature = "rlp")] impl alloy_rlp::Decodable for Signature where - Self: SignatureBuilder, + Self: BuildableSignature, { fn decode(buf: &mut &[u8]) -> Result { let header = alloy_rlp::Header::decode(buf)?; @@ -456,7 +456,7 @@ impl serde::Serialize for Signature { #[cfg(feature = "serde")] impl<'de, T> serde::Deserialize<'de> for Signature where - Self: SignatureBuilder, + Self: BuildableSignature, { fn deserialize(deserializer: D) -> Result where @@ -509,7 +509,7 @@ where struct MapVisitor(PhantomData); impl<'de, T> serde::de::Visitor<'de> for MapVisitor where - Signature: SignatureBuilder, + Signature: BuildableSignature, { type Value = Signature; @@ -566,7 +566,7 @@ where struct TupleVisitor(PhantomData); impl<'de, T> serde::de::Visitor<'de> for TupleVisitor where - Signature: SignatureBuilder, + Signature: BuildableSignature, { type Value = Signature; @@ -603,7 +603,7 @@ where #[cfg(feature = "arbitrary")] impl<'a, T> arbitrary::Arbitrary<'a> for Signature where - Self: SignatureBuilder, + Self: BuildableSignature, { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { Self::from_rs_and_parity(u.arbitrary()?, u.arbitrary()?, u.arbitrary::()?) @@ -615,7 +615,7 @@ where impl proptest::arbitrary::Arbitrary for Signature where T: Debug, - Self: SignatureBuilder, + Self: BuildableSignature, { type Parameters = (); type Strategy = proptest::strategy::FilterMap< From 283408d290a2b0cccc26caef76896109f7291985 Mon Sep 17 00:00:00 2001 From: leruaa Date: Tue, 23 Jul 2024 18:33:03 +0000 Subject: [PATCH 6/7] feat: add test_signature() for RawSignature --- crates/primitives/src/signature/sig.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/primitives/src/signature/sig.rs b/crates/primitives/src/signature/sig.rs index 8b3413563..ce8a08843 100644 --- a/crates/primitives/src/signature/sig.rs +++ b/crates/primitives/src/signature/sig.rs @@ -29,6 +29,15 @@ impl RawSignature { pub const fn new(v: Parity, r: U256, s: U256) -> Self { Self { inner: (), v, r, s } } + + #[doc(hidden)] + pub fn test_signature() -> Self { + Self::new( + false.into(), + b256!("840cfc572845f5786e702984c2a582528cad4b49b2a10b9db1be7fca90058565").into(), + b256!("25e7109ceb98168d95b09b18bbf6b685130e0562f233877d492b94eee0c5b6d1").into(), + ) + } } #[cfg(feature = "k256")] From 5d68c822baf36bbd069eea040bb848591c6421f5 Mon Sep 17 00:00:00 2001 From: leruaa Date: Tue, 23 Jul 2024 18:33:51 +0000 Subject: [PATCH 7/7] feat: allow to convert BuildableSignature to RawSignature --- crates/primitives/src/signature/buildable.rs | 5 +++++ crates/primitives/src/signature/sig.rs | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/crates/primitives/src/signature/buildable.rs b/crates/primitives/src/signature/buildable.rs index de47c0ef7..e50f6e57a 100644 --- a/crates/primitives/src/signature/buildable.rs +++ b/crates/primitives/src/signature/buildable.rs @@ -1,5 +1,7 @@ use crate::{Parity, SignatureError, U256}; +use super::RawSignature; + /// Trait used to uniformize signature creation. pub trait BuildableSignature: Sized { /// Instantiate from v, r, s. @@ -14,4 +16,7 @@ pub trait BuildableSignature: Sized { bytes: &[u8], parity: P, ) -> Result; + + /// Converts the signature into a [`RawSignature`]. + fn into_raw(self) -> RawSignature; } diff --git a/crates/primitives/src/signature/sig.rs b/crates/primitives/src/signature/sig.rs index ce8a08843..18b7188dc 100644 --- a/crates/primitives/src/signature/sig.rs +++ b/crates/primitives/src/signature/sig.rs @@ -156,6 +156,10 @@ impl BuildableSignature for Signature { let sig = k256::ecdsa::Signature::from_slice(bytes)?; Self::from_signature_and_parity(sig, parity) } + + fn into_raw(self) -> RawSignature { + RawSignature::new(self.v, self.r, self.s) + } } #[cfg(feature = "k256")] @@ -291,6 +295,10 @@ impl BuildableSignature for RawSignature { let s = U256::from_be_slice(&bytes[32..64]); Self::from_rs_and_parity(r, s, parity) } + + fn into_raw(self) -> RawSignature { + self + } } impl Signature {