diff --git a/Cargo.lock b/Cargo.lock index eace0ff2ea..e158940ed3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -671,6 +671,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.6" @@ -863,6 +869,17 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -909,6 +926,12 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + [[package]] name = "byteorder" version = "1.5.0" @@ -1068,6 +1091,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + [[package]] name = "core-foundation" version = "0.9.4" @@ -1863,6 +1892,33 @@ dependencies = [ "crunchy", ] +[[package]] +name = "halo2curves-axiom" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75bb262279138550a603b35a73da944fcde987a321eb550c05276ce7b0a4e692" +dependencies = [ + "blake2b_simd", + "digest 0.10.7", + "ff", + "group", + "hex", + "lazy_static", + "maybe-rayon", + "num-bigint 0.4.6", + "num-traits", + "pairing", + "pasta_curves", + "paste", + "rand", + "rand_core", + "serde", + "serde_arrays", + "sha2", + "static_assertions", + "subtle", +] + [[package]] name = "hash-db" version = "0.15.2" @@ -2526,6 +2582,16 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "memchr" version = "2.7.4" @@ -2616,6 +2682,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "smallvec", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -2799,6 +2880,166 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "openvm" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "bytemuck", + "hex-literal", + "num-bigint-dig", + "num-traits", + "openvm-platform", + "openvm-rv32im-guest", + "serde", +] + +[[package]] +name = "openvm-algebra-complex-macros" +version = "0.1.0" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "openvm-macros-common", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "openvm-algebra-guest" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "halo2curves-axiom", + "num-bigint-dig", + "openvm", + "openvm-algebra-complex-macros", + "openvm-algebra-moduli-setup", + "openvm-platform", + "serde", + "serde-big-array", + "strum_macros", +] + +[[package]] +name = "openvm-algebra-moduli-setup" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "openvm-macros-common", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "openvm-ecc-guest" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "ecdsa", + "elliptic-curve", + "group", + "halo2curves-axiom", + "hex-literal", + "itertools 0.13.0", + "k256", + "lazy_static", + "num-bigint 0.4.6", + "num-bigint-dig", + "num-traits", + "openvm", + "openvm-algebra-guest", + "openvm-algebra-moduli-setup", + "openvm-ecc-sw-setup", + "openvm-platform", + "openvm-rv32im-guest", + "rand", + "serde", + "strum_macros", +] + +[[package]] +name = "openvm-ecc-sw-setup" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "openvm-macros-common", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "openvm-keccak256-guest" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "openvm-platform", + "serde", + "tiny-keccak", +] + +[[package]] +name = "openvm-macros-common" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "syn 2.0.90", +] + +[[package]] +name = "openvm-pairing-guest" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "group", + "hex-literal", + "itertools 0.13.0", + "lazy_static", + "num-bigint 0.4.6", + "num-bigint-dig", + "num-traits", + "openvm", + "openvm-algebra-complex-macros", + "openvm-algebra-guest", + "openvm-algebra-moduli-setup", + "openvm-ecc-guest", + "openvm-ecc-sw-setup", + "openvm-platform", + "openvm-rv32im-guest", + "rand", + "serde", + "strum_macros", +] + +[[package]] +name = "openvm-platform" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "getrandom", + "libm", + "stability", + "strum_macros", +] + +[[package]] +name = "openvm-rv32im-guest" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "openvm-platform", + "strum_macros", +] + +[[package]] +name = "openvm-sha256-guest" +version = "0.1.1-alpha" +source = "git+https://github.com/openvm-org/openvm.git?tag=v0.1.1-alpha#ac2f61988f68621258fc84ea4589a7db8a85a873" +dependencies = [ + "openvm", + "openvm-platform", + "sha2", +] + [[package]] name = "p256" version = "0.13.2" @@ -2869,6 +3110,21 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "lazy_static", + "rand", + "static_assertions", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" @@ -3449,6 +3705,11 @@ dependencies = [ "k256", "kzg-rs", "once_cell", + "openvm", + "openvm-ecc-guest", + "openvm-keccak256-guest", + "openvm-pairing-guest", + "openvm-sha256-guest", "p256", "rand", "revm-primitives", @@ -3964,6 +4225,24 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_arrays" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38636132857f68ec3d5f3eb121166d2af33cb55174c4d5ff645db6165cbef0fd" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.215" @@ -4170,6 +4449,16 @@ dependencies = [ "der", ] +[[package]] +name = "stability" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" +dependencies = [ + "quote", + "syn 2.0.90", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/Cargo.toml b/Cargo.toml index e7db667608..8e5c1dedf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,26 @@ default-members = ["crates/revm"] all-features = true rustdoc-args = ["--cfg", "docsrs"] +[workspace.dependencies] +# openvm +openvm = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-ecc-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-pairing-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-keccak256-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-sha256-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-sdk = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-build = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-pairing-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-rv32im-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-algebra-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-algebra-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-ecc-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-ecc-transpiler = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-pairing-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-circuit = { git = "https://github.com/openvm-org/openvm.git", tag = "v0.1.1-alpha" } +openvm-stark-sdk = { git = "https://github.com/openvm-org/stark-backend.git", tag = "v0.1.3-alpha" } + [profile.release] lto = true codegen-units = 1 diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 10597a946a..381c49040b 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -63,6 +63,13 @@ p256 = { version = "0.13.2", optional = true, default-features = false, features # utils cfg-if = { version = "1.0", default-features = false } +# Optionally use openvm intrinsics +openvm.workspace = true +openvm-ecc-guest = { workspace = true, features = ["k256"] } +openvm-keccak256-guest.workspace = true +openvm-sha256-guest.workspace = true +openvm-pairing-guest = { workspace = true, features = ["bn254"] } + [dev-dependencies] criterion = "0.5" rand = { version = "0.8", features = ["std"] } @@ -73,7 +80,7 @@ serde_json = "1.0" serde_derive = "1.0" [features] -default = ["std", "c-kzg", "secp256k1", "portable", "blst"] +default = ["std", "c-kzg", "portable", "blst"] std = [ "revm-primitives/std", "k256/std", diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index fa0fd121c1..908627aa30 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -2,9 +2,25 @@ use crate::{ utilities::{bool_to_bytes32, right_pad}, Address, Error, Precompile, PrecompileResult, PrecompileWithAddress, }; +#[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") +))] use bn::{AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; use revm_primitives::PrecompileOutput; use std::vec::Vec; +#[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] +use { + openvm_ecc_guest::{ + weierstrass::{IntrinsicCurve, WeierstrassPoint}, + AffinePoint, + }, + openvm_pairing_guest::{ + algebra::IntMod, + bn254::{Bn254, Fp, Fp2, G1Affine, Scalar}, + pairing::PairingCheck, + }, +}; pub mod add { use super::*; @@ -123,16 +139,34 @@ pub const PAIR_ELEMENT_LEN: usize = 64 + 128; /// # Panics /// /// Panics if the input is not at least 32 bytes long. +#[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") +))] #[inline] pub fn read_fq(input: &[u8]) -> Result { Fq::from_slice(&input[..32]).map_err(|_| Error::Bn128FieldPointNotAMember) } +#[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] +#[inline] +pub fn read_fq(input: &[u8]) -> Result { + if input.len() < 32 { + Err(Error::Bn128FieldPointNotAMember) + } else { + Ok(Fp::from_be_bytes(&input[..32])) + } +} + /// Reads the `x` and `y` points from the input slice. /// /// # Panics /// /// Panics if the input is not at least 64 bytes long. +#[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") +))] #[inline] pub fn read_point(input: &[u8]) -> Result { let px = read_fq(&input[0..32])?; @@ -140,7 +174,19 @@ pub fn read_point(input: &[u8]) -> Result { new_g1_point(px, py) } +#[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] +#[inline] +pub fn read_point(input: &[u8]) -> Result { + let px = read_fq(&input[0..32])?; + let py = read_fq(&input[32..64])?; + new_g1_point(px, py) +} + /// Creates a new `G1` point from the given `x` and `y` coordinates. +#[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") +))] pub fn new_g1_point(px: Fq, py: Fq) -> Result { if px == Fq::zero() && py == Fq::zero() { Ok(G1::zero()) @@ -151,6 +197,11 @@ pub fn new_g1_point(px: Fq, py: Fq) -> Result { } } +#[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] +pub fn new_g1_point(px: Fp, py: Fp) -> Result { + G1Affine::from_xy(px, py).ok_or(Error::Bn128AffineGFailedToCreate) +} + pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { return Err(Error::OutOfGas.into()); @@ -162,11 +213,30 @@ pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult let p2 = read_point(&input[64..])?; let mut output = [0u8; 64]; - if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { - sum.x().to_big_endian(&mut output[..32]).unwrap(); - sum.y().to_big_endian(&mut output[32..]).unwrap(); + #[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") + ))] + { + if let Some(sum) = AffineG1::from_jacobian(p1 + p2) { + sum.x().to_big_endian(&mut output[..32]).unwrap(); + sum.y().to_big_endian(&mut output[32..]).unwrap(); + } + Ok(PrecompileOutput::new(gas_cost, output.into())) + } + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + { + let sum = p1 + p2; + // TODO: we should add as_be_bytes to SW point. + // manually reverse to avoid allocation + let x_bytes: &[u8] = sum.x().as_le_bytes(); + let y_bytes: &[u8] = sum.y().as_le_bytes(); + for i in 0..32 { + output[i] = x_bytes[31 - i]; + output[i + 32] = y_bytes[31 - i]; + } + Ok(PrecompileOutput::new(gas_cost, output.into())) } - Ok(PrecompileOutput::new(gas_cost, output.into())) } pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { @@ -178,17 +248,38 @@ pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult let p = read_point(&input[..64])?; - // `Fr::from_slice` can only fail when the length is not 32. - let fr = bn::Fr::from_slice(&input[64..96]).unwrap(); - let mut output = [0u8; 64]; - if let Some(mul) = AffineG1::from_jacobian(p * fr) { - mul.x().to_big_endian(&mut output[..32]).unwrap(); - mul.y().to_big_endian(&mut output[32..]).unwrap(); + #[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") + ))] + { + // `Fr::from_slice` can only fail when the length is not 32. + let fr = bn::Fr::from_slice(&input[64..96]).unwrap(); + + if let Some(mul) = AffineG1::from_jacobian(p * fr) { + mul.x().to_big_endian(&mut output[..32]).unwrap(); + mul.y().to_big_endian(&mut output[32..]).unwrap(); + } + Ok(PrecompileOutput::new(gas_cost, output.into())) + } + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + { + let scalar = Scalar::from_be_bytes(&input[64..96]); + + let res = Bn254::msm(&[scalar], &[p]); + // manually reverse to avoid allocation + let x_bytes: &[u8] = res.x().as_le_bytes(); + let y_bytes: &[u8] = res.y().as_le_bytes(); + for i in 0..32 { + output[i] = x_bytes[31 - i]; + output[i + 32] = y_bytes[31 - i]; + } + Ok(PrecompileOutput::new(gas_cost, output.into())) } - Ok(PrecompileOutput::new(gas_cost, output.into())) } +#[allow(non_snake_case)] pub fn run_pair( input: &[u8], pair_per_point_cost: u64, @@ -209,43 +300,80 @@ pub fn run_pair( } else { let elements = input.len() / PAIR_ELEMENT_LEN; + #[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") + ))] let mut points = Vec::with_capacity(elements); + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + let mut P = Vec::with_capacity(elements); + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + let mut Q = Vec::with_capacity(elements); + // read points for idx in 0..elements { + // At each idx, there is (G1, G2) which is 6 Fp points let read_fq_at = |n: usize| { debug_assert!(n < PAIR_ELEMENT_LEN / 32); let start = idx * PAIR_ELEMENT_LEN + n * 32; // SAFETY: We're reading `6 * 32 == PAIR_ELEMENT_LEN` bytes from `input[idx..]` // per iteration. This is guaranteed to be in-bounds. let slice = unsafe { input.get_unchecked(start..start + 32) }; - Fq::from_slice(slice).map_err(|_| Error::Bn128FieldPointNotAMember) - }; - let ax = read_fq_at(0)?; - let ay = read_fq_at(1)?; - let bay = read_fq_at(2)?; - let bax = read_fq_at(3)?; - let bby = read_fq_at(4)?; - let bbx = read_fq_at(5)?; - - let a = new_g1_point(ax, ay)?; - let b = { - let ba = Fq2::new(bax, bay); - let bb = Fq2::new(bbx, bby); - // TODO: check whether or not we need these zero checks - if ba.is_zero() && bb.is_zero() { - G2::zero() - } else { - G2::from(AffineG2::new(ba, bb).map_err(|_| Error::Bn128AffineGFailedToCreate)?) - } + read_fq(slice) }; - - points.push((a, b)); + // https://eips.ethereum.org/EIPS/eip-197, Fp2 is encoded as (a, b) where a * i + b + let g1_x = read_fq_at(0)?; + let g1_y = read_fq_at(1)?; + let g2_x_c1 = read_fq_at(2)?; + let g2_x_c0 = read_fq_at(3)?; + let g2_y_c1 = read_fq_at(4)?; + let g2_y_c0 = read_fq_at(5)?; + + #[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") + ))] + { + let g1 = new_g1_point(g1_x, g1_y)?; + let g2 = { + let g2_x = Fq2::new(g2_x_c0, g2_x_c1); + let g2_y = Fq2::new(g2_y_c0, g2_y_c1); + // TODO: check whether or not we need these zero checks + if g2_x.is_zero() && g2_y.is_zero() { + G2::zero() + } else { + G2::from( + AffineG2::new(g2_x, g2_y) + .map_err(|_| Error::Bn128AffineGFailedToCreate)?, + ) + } + }; + points.push((g1, g2)); + } + + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + { + let g1 = AffinePoint::new(g1_x, g1_y); + let g2_x = Fp2::new(g2_x_c0, g2_x_c1); + let g2_y = Fp2::new(g2_y_c0, g2_y_c1); + let g2 = AffinePoint::new(g2_x, g2_y); + + P.push(g1); + Q.push(g2); + } } - let mul = bn::pairing_batch(&points); + #[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") + ))] + let success = bn::pairing_batch(&points) == Gt::one(); + + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + let success = Bn254::pairing_check(&P, &Q).is_ok(); - mul == Gt::one() + success }; Ok(PrecompileOutput::new(gas_used, bool_to_bytes32(success))) } diff --git a/crates/precompile/src/hash.rs b/crates/precompile/src/hash.rs index 2be7f4621a..0fb86b7ec2 100644 --- a/crates/precompile/src/hash.rs +++ b/crates/precompile/src/hash.rs @@ -42,7 +42,13 @@ pub fn sha256_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { if cost > gas_limit { Err(Error::OutOfGas.into()) } else { + #[cfg(any( + not(target_os = "zkvm"), + all(target_os = "zkvm", target_vendor = "succinct") + ))] let output = sha2::Sha256::digest(input); + #[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] + let output = openvm_sha256_guest::sha256(input); Ok(PrecompileOutput::new(cost, output.to_vec().into())) } } diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 02b7dc6227..2711baadac 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -8,7 +8,48 @@ pub const ECRECOVER: PrecompileWithAddress = PrecompileWithAddress( pub use self::secp256k1::ecrecover; -#[cfg(not(feature = "secp256k1"))] +#[cfg(all(target_os = "zkvm", not(target_vendor = "succinct")))] +#[allow(clippy::module_inception)] +mod secp256k1 { + use k256::{ + ecdsa::{Error, RecoveryId, Signature}, + Secp256k1, + }; + use openvm_ecc_guest::{algebra::IntMod, ecdsa::VerifyingKey, weierstrass::WeierstrassPoint}; + use openvm_keccak256_guest::keccak256; + use revm_primitives::{alloy_primitives::B512, B256}; + + pub fn ecrecover(sig: &B512, mut recid: u8, msg: &B256) -> Result { + // parse signature + let mut sig = Signature::from_slice(sig.as_slice())?; + if let Some(sig_normalized) = sig.normalize_s() { + sig = sig_normalized; + recid ^= 1; + } + let recid = RecoveryId::from_byte(recid).expect("recovery ID is valid"); + + // annoying: Signature::to_bytes copies from slice + let recovered_key = VerifyingKey::::recover_from_prehash_noverify( + &msg[..], + &sig.to_bytes(), + recid, + ); + let public_key = recovered_key.as_affine(); + let mut encoded = [0u8; 64]; + encoded[..32].copy_from_slice(&public_key.x().to_be_bytes()); + encoded[32..].copy_from_slice(&public_key.y().to_be_bytes()); + // hash it + let mut hash = keccak256(&encoded); + // truncate to 20 bytes + hash[..12].fill(0); + Ok(B256::from(hash)) + } +} + +#[cfg(any( + all(not(feature = "secp256k1"), not(target_os = "zkvm")), + all(target_os = "zkvm", target_vendor = "succinct") +))] #[allow(clippy::module_inception)] mod secp256k1 { use k256::ecdsa::{Error, RecoveryId, Signature, VerifyingKey}; @@ -40,7 +81,7 @@ mod secp256k1 { } } -#[cfg(feature = "secp256k1")] +#[cfg(all(feature = "secp256k1", not(target_os = "zkvm")))] #[allow(clippy::module_inception)] mod secp256k1 { use revm_primitives::{alloy_primitives::B512, keccak256, B256};