From 2324c9ce75fb0c357efc89cd6bdc68785e72dec6 Mon Sep 17 00:00:00 2001 From: steven Date: Sat, 14 Dec 2024 18:45:33 -0600 Subject: [PATCH 1/6] chore: integrate rust-secp256k1 --- Cargo.lock | 25 ++++++++++++++++++++++--- crates/precompile/Cargo.toml | 4 ++++ crates/precompile/src/secp256k1.rs | 13 ++++++++----- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebecebcbe1..27a4af0be8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addchain" @@ -3124,7 +3124,8 @@ dependencies = [ "revm-specification", "ripemd", "rstest 0.22.0", - "secp256k1", + "secp256k1 0.22.2", + "secp256k1 0.29.1", "serde", "serde_derive", "serde_json", @@ -3533,6 +3534,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "295642060261c80709ac034f52fca8e5a9fa2c7d341ded5cdb164b7c33768b2a" +dependencies = [ + "secp256k1-sys 0.5.2", +] + [[package]] name = "secp256k1" version = "0.29.1" @@ -3540,7 +3550,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "rand", - "secp256k1-sys", + "secp256k1-sys 0.10.0", +] + +[[package]] +name = "secp256k1-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "152e20a0fd0519390fc43ab404663af8a0b794273d2a91d60ad4a39f13ffe110" +dependencies = [ + "cc", ] [[package]] diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index e2445b2a03..d1d0661e77 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -31,6 +31,10 @@ specification.workspace = true once_cell = { version = "1.19", default-features = false, features = ["alloc"] } # ecRecover +rust_secp256k1 = { version = "0.22", package = "secp256k1", default-features = false, features = [ + "alloc", + "recovery", +]} k256 = { version = "0.13.3", default-features = false, features = ["ecdsa"] } secp256k1 = { version = ">=0.28, <=0.29", default-features = false, features = [ "alloc", diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index e300f87b4d..37018bdebe 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -45,20 +45,23 @@ mod secp256k1 { #[allow(clippy::module_inception)] mod secp256k1 { use primitives::{alloy_primitives::B512, keccak256, B256}; - use secp256k1::{ + use rust_secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, - Message, SECP256K1, + Message, Secp256k1, }; // Silence the unused crate dependency warning. use k256 as _; + use secp256k1 as _; + + pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let engine = Secp256k1::new(); - pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; - let msg = Message::from_digest(msg.0); - let public = SECP256K1.recover_ecdsa(&msg, &sig)?; + let msg = Message::from_slice(msg.as_ref())?; + let public = engine.recover_ecdsa(&msg, &sig)?; let mut hash = keccak256(&public.serialize_uncompressed()[1..]); hash[..12].fill(0); From 265b3bdbbe818b0000cd63b382522a61f160dc2b Mon Sep 17 00:00:00 2001 From: steven Date: Sun, 15 Dec 2024 21:48:18 -0600 Subject: [PATCH 2/6] parity version --- Cargo.lock | 87 +++++++++++++++------- crates/precompile/Cargo.toml | 7 +- crates/precompile/src/secp256k1.rs | 112 +++++++++++++++-------------- 3 files changed, 125 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 27a4af0be8..c3ffecbb38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,7 +432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f99acddb34000d104961897dbb0240298e8b775a7efffb9fda2a1a3efedd65b3" dependencies = [ "alloy-json-rpc", - "base64", + "base64 0.22.1", "futures-util", "futures-utils-wasm", "serde", @@ -651,6 +651,12 @@ dependencies = [ "rand", ] +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + [[package]] name = "arrayvec" version = "0.7.4" @@ -744,6 +750,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.22.1" @@ -2135,6 +2147,51 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2891,7 +2948,7 @@ version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -3116,6 +3173,7 @@ dependencies = [ "eyre", "k256", "kzg-rs", + "libsecp256k1", "once_cell", "p256", "rand", @@ -3124,8 +3182,7 @@ dependencies = [ "revm-specification", "ripemd", "rstest 0.22.0", - "secp256k1 0.22.2", - "secp256k1 0.29.1", + "secp256k1", "serde", "serde_derive", "serde_json", @@ -3416,7 +3473,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] @@ -3534,15 +3591,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "secp256k1" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295642060261c80709ac034f52fca8e5a9fa2c7d341ded5cdb164b7c33768b2a" -dependencies = [ - "secp256k1-sys 0.5.2", -] - [[package]] name = "secp256k1" version = "0.29.1" @@ -3550,16 +3598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "rand", - "secp256k1-sys 0.10.0", -] - -[[package]] -name = "secp256k1-sys" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "152e20a0fd0519390fc43ab404663af8a0b794273d2a91d60ad4a39f13ffe110" -dependencies = [ - "cc", + "secp256k1-sys", ] [[package]] diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index d1d0661e77..49ffa72060 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -31,10 +31,7 @@ specification.workspace = true once_cell = { version = "1.19", default-features = false, features = ["alloc"] } # ecRecover -rust_secp256k1 = { version = "0.22", package = "secp256k1", default-features = false, features = [ - "alloc", - "recovery", -]} +libsecp256k1 = { version = "0.7", default-features = false, package = "libsecp256k1", optional = true } k256 = { version = "0.13.3", default-features = false, features = ["ecdsa"] } secp256k1 = { version = ">=0.28, <=0.29", default-features = false, features = [ "alloc", @@ -82,7 +79,7 @@ serde_json = "1.0" serde_derive = "1.0" [features] -default = ["std", "c-kzg", "secp256k1", "portable", "blst"] +default = ["std", "c-kzg", "secp256k1", "portable", "blst", "libsecp256k1"] std = [ "primitives/std", "k256/std", diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 37018bdebe..f31fe7a55e 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -9,63 +9,71 @@ pub const ECRECOVER: PrecompileWithAddress = pub use self::secp256k1::ecrecover; -#[cfg(not(feature = "secp256k1"))] #[allow(clippy::module_inception)] mod secp256k1 { - use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; use primitives::{alloy_primitives::B512, keccak256, B256}; - pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { - // parse signature - let mut sig = Signature::from_slice(sig.as_slice())?; - - // normalize signature and flip recovery id if needed. - if let Some(sig_normalized) = sig.normalize_s() { - sig = sig_normalized; - recid ^= 1; + cfg_if::cfg_if! { + if #[cfg(feature = "secp256k1")] { + use secp256k1::{ + ecdsa::{RecoverableSignature, RecoveryId}, + Message, SECP256K1, + }; + + // Silence the unused crate dependency warning. + use k256 as _; + + pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); + let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; + + let msg = Message::from_digest(msg.0); + let public = SECP256K1.recover_ecdsa(&msg, &sig)?; + + let mut hash = keccak256(&public.serialize_uncompressed()[1..]); + hash[..12].fill(0); + Ok(hash) + } + } else if #[cfg(feature = "libsecp256k1")] { + pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let recid = libsecp256k1::RecoveryId::parse(recid)?; + let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; + + let msg = libsecp256k1::Message::parse(msg.as_ref()); + let public = libsecp256k1::recover(&msg, &sig, &recid)?; + + let mut hash = keccak256(&public.serialize_uncompressed()[1..]); + hash[..12].fill(0); + Ok(hash) + } + } else { + use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; + + pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { + // parse signature + let mut sig = Signature::from_slice(sig.as_slice())?; + + // normalize signature and flip recovery id if needed. + if let Some(sig_normalized) = sig.normalize_s() { + sig = sig_normalized; + recid ^= 1; + } + let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); + + // recover key + let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; + // hash it + let mut hash = keccak256( + &recovered_key + .to_encoded_point(/* compress = */ false) + .as_bytes()[1..], + ); + + // truncate to 20 bytes + hash[..12].fill(0); + Ok(hash) + } } - let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); - - // recover key - let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; - // hash it - let mut hash = keccak256( - &recovered_key - .to_encoded_point(/* compress = */ false) - .as_bytes()[1..], - ); - - // truncate to 20 bytes - hash[..12].fill(0); - Ok(hash) - } -} - -#[cfg(feature = "secp256k1")] -#[allow(clippy::module_inception)] -mod secp256k1 { - use primitives::{alloy_primitives::B512, keccak256, B256}; - use rust_secp256k1::{ - ecdsa::{RecoverableSignature, RecoveryId}, - Message, Secp256k1, - }; - - // Silence the unused crate dependency warning. - use k256 as _; - use secp256k1 as _; - - pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { - let engine = Secp256k1::new(); - - let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); - let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; - - let msg = Message::from_slice(msg.as_ref())?; - let public = engine.recover_ecdsa(&msg, &sig)?; - - let mut hash = keccak256(&public.serialize_uncompressed()[1..]); - hash[..12].fill(0); - Ok(hash) } } From 6027fc3795c30ff945be7960862d1c7a3cb2d461 Mon Sep 17 00:00:00 2001 From: steven Date: Sun, 15 Dec 2024 21:50:24 -0600 Subject: [PATCH 3/6] fmt --- crates/precompile/src/secp256k1.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index f31fe7a55e..3ab50ccf41 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -22,7 +22,7 @@ mod secp256k1 { // Silence the unused crate dependency warning. use k256 as _; - + pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; From 5f3311b49367b0042b7d45fec63c111fbdf10a89 Mon Sep 17 00:00:00 2001 From: steven Date: Mon, 16 Dec 2024 08:04:48 -0600 Subject: [PATCH 4/6] dep --- crates/precompile/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 49ffa72060..19146e2c23 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -79,7 +79,7 @@ serde_json = "1.0" serde_derive = "1.0" [features] -default = ["std", "c-kzg", "secp256k1", "portable", "blst", "libsecp256k1"] +default = ["std", "c-kzg", "secp256k1", "portable", "blst"] std = [ "primitives/std", "k256/std", From ec268acf7129670c7481f6fa73b88cd8538b6459 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 31 Dec 2024 16:23:15 +0100 Subject: [PATCH 5/6] restructure,cleanup and order of activation --- Cargo.lock | 41 ++++- crates/precompile/Cargo.toml | 6 +- crates/precompile/src/secp256k1.rs | 151 +++++++++--------- .../src/secp256k1/bitcoin_secp256k1.rs | 20 +++ crates/precompile/src/secp256k1/k256.rs | 27 ++++ .../src/secp256k1/parity_libsecp256k1.rs | 15 ++ 6 files changed, 181 insertions(+), 79 deletions(-) create mode 100644 crates/precompile/src/secp256k1/bitcoin_secp256k1.rs create mode 100644 crates/precompile/src/secp256k1/k256.rs create mode 100644 crates/precompile/src/secp256k1/parity_libsecp256k1.rs diff --git a/Cargo.lock b/Cargo.lock index c3ffecbb38..4af5364c08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,7 +132,7 @@ dependencies = [ "derive_more 1.0.0", "once_cell", "serde", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -814,6 +814,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -1227,7 +1236,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", "crypto-common", "subtle", @@ -2090,7 +2099,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2", + "sha2 0.10.8", "signature", ] @@ -2121,7 +2130,7 @@ checksum = "0850eb19206463a61bede4f7b7e6b21731807137619044b1f3c287ebcfe2b3b0" dependencies = [ "ff", "hex", - "sha2", + "sha2 0.10.8", "sp1_bls12_381", "spin", ] @@ -2161,6 +2170,7 @@ dependencies = [ "libsecp256k1-gen-genmult", "rand", "serde", + "sha2 0.9.9", ] [[package]] @@ -2422,6 +2432,12 @@ version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "open-fastrlp" version = "0.1.4" @@ -2500,7 +2516,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -3186,7 +3202,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "sha2", + "sha2 0.10.8", "substrate-bn", ] @@ -3702,6 +3718,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.8" diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 19146e2c23..6b3f77cad5 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -31,7 +31,6 @@ specification.workspace = true once_cell = { version = "1.19", default-features = false, features = ["alloc"] } # ecRecover -libsecp256k1 = { version = "0.7", default-features = false, package = "libsecp256k1", optional = true } k256 = { version = "0.13.3", default-features = false, features = ["ecdsa"] } secp256k1 = { version = ">=0.28, <=0.29", default-features = false, features = [ "alloc", @@ -39,6 +38,9 @@ secp256k1 = { version = ">=0.28, <=0.29", default-features = false, features = [ "rand", "global-context", ], optional = true } +libsecp256k1 = { version = "0.7", default-features = false, package = "libsecp256k1", features = [ + "static-context", +], optional = true } # SHA2-256 and RIPEMD-160 sha2 = { version = "0.10", default-features = false } @@ -88,6 +90,7 @@ std = [ "sha2/std", "c-kzg?/std", "secp256k1?/std", + "libsecp256k1?/std", ] hashbrown = ["primitives/hashbrown"] asm-keccak = ["primitives/asm-keccak"] @@ -108,6 +111,7 @@ portable = ["c-kzg"] # The problem that `secp256k1` has is it fails to build for `wasm` target on Windows and Mac as it is c lib. # In Linux it passes. If you don't require to build wasm on win/mac, it is safe to use it and it is enabled by default. secp256k1 = ["dep:secp256k1"] +libsecp256k1 = ["dep:libsecp256k1"] # Enables the BLS12-381 precompiles. blst = ["dep:blst"] diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 3ab50ccf41..c05dd7fda5 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -7,75 +7,74 @@ use primitives::{alloy_primitives::B512, Bytes, B256}; pub const ECRECOVER: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_address(1), ec_recover_run); -pub use self::secp256k1::ecrecover; - -#[allow(clippy::module_inception)] -mod secp256k1 { - use primitives::{alloy_primitives::B512, keccak256, B256}; - - cfg_if::cfg_if! { - if #[cfg(feature = "secp256k1")] { - use secp256k1::{ - ecdsa::{RecoverableSignature, RecoveryId}, - Message, SECP256K1, - }; - - // Silence the unused crate dependency warning. - use k256 as _; - - pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { - let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); - let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; - - let msg = Message::from_digest(msg.0); - let public = SECP256K1.recover_ecdsa(&msg, &sig)?; - - let mut hash = keccak256(&public.serialize_uncompressed()[1..]); - hash[..12].fill(0); - Ok(hash) - } - } else if #[cfg(feature = "libsecp256k1")] { - pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { - let recid = libsecp256k1::RecoveryId::parse(recid)?; - let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; - - let msg = libsecp256k1::Message::parse(msg.as_ref()); - let public = libsecp256k1::recover(&msg, &sig, &recid)?; - - let mut hash = keccak256(&public.serialize_uncompressed()[1..]); - hash[..12].fill(0); - Ok(hash) - } - } else { - use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; - - pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { - // parse signature - let mut sig = Signature::from_slice(sig.as_slice())?; - - // normalize signature and flip recovery id if needed. - if let Some(sig_normalized) = sig.normalize_s() { - sig = sig_normalized; - recid ^= 1; - } - let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); - - // recover key - let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; - // hash it - let mut hash = keccak256( - &recovered_key - .to_encoded_point(/* compress = */ false) - .as_bytes()[1..], - ); - - // truncate to 20 bytes - hash[..12].fill(0); - Ok(hash) - } - } - } -} +pub mod k256; + +#[cfg(feature = "secp256k1")] +pub mod bitcoin_secp256k1; + +#[cfg(feature = "libsecp256k1")] +pub mod parity_libsecp256k1; + +// #[allow(clippy::module_inception)] +// mod secp256k1 { +// use primitives::{alloy_primitives::B512, keccak256, B256}; + +// #[cfg(feature = "secp256k1")] +// { +// use secp256k1::{ +// ecdsa::{RecoverableSignature, RecoveryId}, +// Message, SECP256K1, +// }; + +// // Silence the unused crate dependency warning. +// use k256 as _; + +// pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { +// let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); +// let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; + +// let msg = Message::from_digest(msg.0); +// let public = SECP256K1.recover_ecdsa(&msg, &sig)?; + +// let mut hash = keccak256(&public.serialize_uncompressed()[1..]); +// hash[..12].fill(0); +// Ok(hash) +// } +// } +// #[cfg(feature = "libsecp256k1")] +// { + +// } +// #[cfg(feature = "k256")] +// { +// use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; + +// pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { +// // parse signature +// let mut sig = Signature::from_slice(sig.as_slice())?; + +// // normalize signature and flip recovery id if needed. +// if let Some(sig_normalized) = sig.normalize_s() { +// sig = sig_normalized; +// recid ^= 1; +// } +// let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); + +// // recover key +// let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; +// // hash it +// let mut hash = keccak256( +// &recovered_key +// .to_encoded_point(/* compress = */ false) +// .as_bytes()[1..], +// ); + +// // truncate to 20 bytes +// hash[..12].fill(0); +// Ok(hash) +// } +// } +// } pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { const ECRECOVER_BASE: u64 = 3_000; @@ -95,8 +94,16 @@ pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { let recid = input[63] - 27; let sig = <&B512>::try_from(&input[64..128]).unwrap(); - let out = secp256k1::ecrecover(sig, recid, msg) - .map(|o| o.to_vec().into()) - .unwrap_or_default(); + cfg_if::cfg_if! { + if #[cfg(feature = "secp256k1")] { + let res = bitcoin_secp256k1::ecrecover(sig, recid, msg); + } else if #[cfg(feature = "libsecp256k1")] { + let res = parity_libsecp256k1::ecrecover(sig, recid, msg); + } else { + let res = k256::ecrecover(sig, recid, msg); + } + }; + + let out = res.map(|o| o.to_vec().into()).unwrap_or_default(); Ok(PrecompileOutput::new(ECRECOVER_BASE, out)) } diff --git a/crates/precompile/src/secp256k1/bitcoin_secp256k1.rs b/crates/precompile/src/secp256k1/bitcoin_secp256k1.rs new file mode 100644 index 0000000000..7444dd61f1 --- /dev/null +++ b/crates/precompile/src/secp256k1/bitcoin_secp256k1.rs @@ -0,0 +1,20 @@ +use primitives::{alloy_primitives::B512, keccak256, B256}; +use secp256k1::{ + ecdsa::{RecoverableSignature, RecoveryId}, + Message, SECP256K1, +}; + +// Silence the unused crate dependency warning. +use k256 as _; + +pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); + let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; + + let msg = Message::from_digest(msg.0); + let public = SECP256K1.recover_ecdsa(&msg, &sig)?; + + let mut hash = keccak256(&public.serialize_uncompressed()[1..]); + hash[..12].fill(0); + Ok(hash) +} diff --git a/crates/precompile/src/secp256k1/k256.rs b/crates/precompile/src/secp256k1/k256.rs new file mode 100644 index 0000000000..6e16952c06 --- /dev/null +++ b/crates/precompile/src/secp256k1/k256.rs @@ -0,0 +1,27 @@ +use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; +use primitives::{alloy_primitives::B512, keccak256, B256}; + +pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { + // parse signature + let mut sig = Signature::from_slice(sig.as_slice())?; + + // normalize signature and flip recovery id if needed. + if let Some(sig_normalized) = sig.normalize_s() { + sig = sig_normalized; + recid ^= 1; + } + let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); + + // recover key + let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; + // hash it + let mut hash = keccak256( + &recovered_key + .to_encoded_point(/* compress = */ false) + .as_bytes()[1..], + ); + + // truncate to 20 bytes + hash[..12].fill(0); + Ok(hash) +} diff --git a/crates/precompile/src/secp256k1/parity_libsecp256k1.rs b/crates/precompile/src/secp256k1/parity_libsecp256k1.rs new file mode 100644 index 0000000000..b9ea28de0f --- /dev/null +++ b/crates/precompile/src/secp256k1/parity_libsecp256k1.rs @@ -0,0 +1,15 @@ +use libsecp256k1::{recover, Error, Message, RecoveryId, Signature}; +use primitives::{alloy_primitives::B512, keccak256, B256}; + +pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { + let recid = RecoveryId::parse(recid)?; + let sig = Signature::parse_standard(sig)?; + let msg = Message::parse(msg.as_ref()); + + // uses static context. + let public = recover(&msg, &sig, &recid)?; + + let mut hash = keccak256(&public.serialize()[1..]); + hash[..12].fill(0); + Ok(hash) +} From c95c51a06ae74fc57eb5b032695ccd75823330f5 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 31 Dec 2024 16:28:16 +0100 Subject: [PATCH 6/6] rm comments --- crates/precompile/src/secp256k1.rs | 61 ------------------- .../src/secp256k1/parity_libsecp256k1.rs | 2 +- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index c05dd7fda5..da1df1edff 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -15,67 +15,6 @@ pub mod bitcoin_secp256k1; #[cfg(feature = "libsecp256k1")] pub mod parity_libsecp256k1; -// #[allow(clippy::module_inception)] -// mod secp256k1 { -// use primitives::{alloy_primitives::B512, keccak256, B256}; - -// #[cfg(feature = "secp256k1")] -// { -// use secp256k1::{ -// ecdsa::{RecoverableSignature, RecoveryId}, -// Message, SECP256K1, -// }; - -// // Silence the unused crate dependency warning. -// use k256 as _; - -// pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { -// let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid"); -// let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?; - -// let msg = Message::from_digest(msg.0); -// let public = SECP256K1.recover_ecdsa(&msg, &sig)?; - -// let mut hash = keccak256(&public.serialize_uncompressed()[1..]); -// hash[..12].fill(0); -// Ok(hash) -// } -// } -// #[cfg(feature = "libsecp256k1")] -// { - -// } -// #[cfg(feature = "k256")] -// { -// use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; - -// pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { -// // parse signature -// let mut sig = Signature::from_slice(sig.as_slice())?; - -// // normalize signature and flip recovery id if needed. -// if let Some(sig_normalized) = sig.normalize_s() { -// sig = sig_normalized; -// recid ^= 1; -// } -// let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); - -// // recover key -// let recovered_key = VerifyingKey::recover_from_prehash(&msg[..], &sig, recid)?; -// // hash it -// let mut hash = keccak256( -// &recovered_key -// .to_encoded_point(/* compress = */ false) -// .as_bytes()[1..], -// ); - -// // truncate to 20 bytes -// hash[..12].fill(0); -// Ok(hash) -// } -// } -// } - pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { const ECRECOVER_BASE: u64 = 3_000; diff --git a/crates/precompile/src/secp256k1/parity_libsecp256k1.rs b/crates/precompile/src/secp256k1/parity_libsecp256k1.rs index b9ea28de0f..5994bd8467 100644 --- a/crates/precompile/src/secp256k1/parity_libsecp256k1.rs +++ b/crates/precompile/src/secp256k1/parity_libsecp256k1.rs @@ -12,4 +12,4 @@ pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result { let mut hash = keccak256(&public.serialize()[1..]); hash[..12].fill(0); Ok(hash) -} +} \ No newline at end of file