From 2b254693f55751ec300812d79426b08148f125a4 Mon Sep 17 00:00:00 2001 From: Bhargav Annem Date: Wed, 10 Jul 2024 06:02:36 -0500 Subject: [PATCH] feat: use `kzg-rs` for kzg point evaluation (#1558) * feat: use `kzg-rs` * fix: use `c-kzg` by default in std env * refactor: feature gate by `c-kzg` * fix: use published crate * fix: `kzg-rs` import * feat: use `cfg_if` for `kzg-rs` imports * feat: use `kzg-rs` * fix: `kzg-rs` import * chore: add `kzg-rs` feature to revm-interpreter * fix: check kzg-rs enable in revm/precompile * fix: kzg-rs include once_cell and derive_more in primitives, update feature tags * Update crates/primitives/src/lib.rs * Update crates/precompile/src/lib.rs * Update crates/primitives/Cargo.toml * Update crates/revm/Cargo.toml * Update crates/precompile/Cargo.toml * Update crates/primitives/src/lib.rs --------- Co-authored-by: rakita --- Cargo.lock | 59 +++++++++++++++++++ crates/interpreter/Cargo.toml | 2 + crates/precompile/Cargo.toml | 8 +++ crates/precompile/src/kzg_point_evaluation.rs | 8 ++- crates/precompile/src/lib.rs | 7 ++- crates/primitives/Cargo.toml | 12 +++- crates/primitives/src/env.rs | 2 +- crates/primitives/src/kzg.rs | 9 ++- crates/primitives/src/kzg/env_settings.rs | 56 ++++++++++-------- .../src/kzg/trusted_setup_points.rs | 8 ++- crates/primitives/src/lib.rs | 8 ++- crates/revm/Cargo.toml | 2 + 12 files changed, 146 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f572ed13e0..7d3d99c1b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -720,6 +720,19 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bls12_381" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" +dependencies = [ + "ff", + "group", + "pairing", + "rand_core", + "subtle", +] + [[package]] name = "blst" version = "0.3.12" @@ -1408,6 +1421,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ + "bitvec", "rand_core", "subtle", ] @@ -2242,6 +2256,21 @@ dependencies = [ "sha3-asm", ] +[[package]] +name = "kzg-rs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9920cd4460ce3cbca19c62f3bb9a9611562478a4dc9d2c556f4a7d049c5b6b" +dependencies = [ + "bls12_381", + "glob", + "hex", + "once_cell", + "serde", + "serde_derive", + "serde_yaml", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2574,6 +2603,15 @@ dependencies = [ "sha2", ] +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group", +] + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -3154,6 +3192,7 @@ dependencies = [ "criterion", "eyre", "k256", + "kzg-rs", "once_cell", "p256", "rand", @@ -3184,6 +3223,7 @@ dependencies = [ "enumn", "hashbrown", "hex", + "kzg-rs", "once_cell", "serde", ] @@ -3687,6 +3727,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4358,6 +4411,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.7.1" diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 022e0e8a74..da07fefad2 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -81,3 +81,5 @@ optional_eip3607 = ["revm-primitives/optional_eip3607"] optional_gas_refund = ["revm-primitives/optional_gas_refund"] optional_no_base_fee = ["revm-primitives/optional_no_base_fee"] optional_beneficiary_reward = ["revm-primitives/optional_beneficiary_reward"] + +kzg-rs = ["revm-primitives/kzg-rs"] diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index a242a36e5d..18495b0d75 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -47,6 +47,11 @@ bn = { package = "substrate-bn", version = "0.6", default-features = false } # KZG point evaluation precompile c-kzg = { version = "1.0.2", default-features = false, optional = true } +# Optionally use `kzg-rs` for a pure Rust implementation of KZG point evaluation. +kzg-rs = { version = "0.1", default-features = false, features = [ + 'cache', +], optional = true } + # BLS12-381 precompiles blst = { version = "0.3.12", optional = true } @@ -98,6 +103,9 @@ secp256r1 = ["dep:p256"] # Enables the KZG point evaluation precompile. c-kzg = ["dep:c-kzg", "revm-primitives/c-kzg"] +# `kzg-rs` is not audited but useful for `no_std` environment, use it with causing and default to `c-kzg` if possible. +kzg-rs = ["dep:kzg-rs", "revm-primitives/kzg-rs"] + portable = ["revm-primitives/portable", "c-kzg?/portable"] # Use `secp256k1` as a faster alternative to `k256`. diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index 22192ce56d..6f295219a6 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -1,5 +1,11 @@ use crate::{Address, Error, Precompile, PrecompileResult, PrecompileWithAddress}; -use c_kzg::{Bytes32, Bytes48, KzgProof, KzgSettings}; +cfg_if::cfg_if! { + if #[cfg(feature = "c-kzg")] { + use c_kzg::{Bytes32, Bytes48, KzgProof, KzgSettings}; + } else if #[cfg(feature = "kzg-rs")] { + use kzg_rs::{Bytes32, Bytes48, KzgProof, KzgSettings}; + } +} use revm_primitives::{hex_literal::hex, Bytes, Env, PrecompileOutput}; use sha2::{Digest, Sha256}; diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index fbd8e69cbc..662dca6a21 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -15,7 +15,7 @@ pub mod bn128; pub mod fatal_precompile; pub mod hash; pub mod identity; -#[cfg(feature = "c-kzg")] +#[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg_point_evaluation; pub mod modexp; pub mod secp256k1; @@ -25,6 +25,9 @@ pub mod utilities; pub use fatal_precompile::fatal_precompile; +#[cfg(all(feature = "c-kzg", feature = "kzg-rs"))] +// silence kzg-rs lint as c-kzg will be used as default if both are enabled. +use kzg_rs as _; pub use primitives::{ precompile::{PrecompileError as Error, *}, Address, Bytes, HashMap, HashSet, Log, B256, @@ -142,7 +145,7 @@ impl Precompiles { // EIP-4844: Shard Blob Transactions cfg_if! { - if #[cfg(feature = "c-kzg")] { + if #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] { let precompile = kzg_point_evaluation::POINT_EVALUATION.clone(); } else { // TODO move constants to separate file. diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index a7f19132cc..3a6f03c394 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -22,7 +22,7 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] -alloy-eips = { version = "0.1", default-features = false, features = ["k256"]} +alloy-eips = { version = "0.1", default-features = false, features = ["k256"] } alloy-primitives = { version = "0.7.2", default-features = false, features = [ "rlp", ] } @@ -35,6 +35,11 @@ bitflags = { version = "2.6.0", default-features = false } c-kzg = { version = "1.0.2", default-features = false, optional = true } once_cell = { version = "1.19", default-features = false, optional = true } +# Optionally use `kzg-rs` for a pure Rust implementation of KZG. +kzg-rs = { version = "0.1", default-features = false, features = [ + 'cache', +], optional = true } + # utility enumn = "0.1" derive_more = { version = "0.99", optional = true } @@ -70,12 +75,13 @@ serde = [ "bitvec/serde", "bitflags/serde", "c-kzg?/serde", + "kzg-rs?/serde", ] arbitrary = [ "std", "alloy-eips/arbitrary", "alloy-primitives/arbitrary", - "bitflags/arbitrary" + "bitflags/arbitrary", ] asm-keccak = ["alloy-primitives/asm-keccak"] portable = ["c-kzg?/portable"] @@ -105,3 +111,5 @@ rand = ["alloy-primitives/rand"] # See comments in `revm-precompile` c-kzg = ["dep:c-kzg", "dep:once_cell", "dep:derive_more"] +# `kzg-rs` is not audited but useful for `no_std` environment, use it with causing and default to `c-kzg` if possible. +kzg-rs = ["dep:kzg-rs", "dep:once_cell", "dep:derive_more"] diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 1ec9c717f8..45cfb119c5 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -275,7 +275,7 @@ pub struct CfgEnv { /// Chain ID is introduced EIP-155 pub chain_id: u64, /// KZG Settings for point evaluation precompile. By default, this is loaded from the ethereum mainnet trusted setup. - #[cfg(feature = "c-kzg")] + #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] #[cfg_attr(feature = "serde", serde(skip))] pub kzg_settings: crate::kzg::EnvKzgSettings, /// Bytecode that is created with CREATE/CREATE2 is by default analysed and jumptable is created. diff --git a/crates/primitives/src/kzg.rs b/crates/primitives/src/kzg.rs index 8d37463f0c..e3fc8cf586 100644 --- a/crates/primitives/src/kzg.rs +++ b/crates/primitives/src/kzg.rs @@ -1,7 +1,14 @@ mod env_settings; mod trusted_setup_points; -pub use c_kzg::KzgSettings; +cfg_if::cfg_if! { + if #[cfg(feature = "c-kzg")] { + pub use c_kzg::KzgSettings; + } else if #[cfg(feature = "kzg-rs")] { + pub use kzg_rs::KzgSettings; + } +} + pub use env_settings::EnvKzgSettings; pub use trusted_setup_points::{ parse_kzg_trusted_setup, G1Points, G2Points, KzgErrors, BYTES_PER_G1_POINT, BYTES_PER_G2_POINT, diff --git a/crates/primitives/src/kzg/env_settings.rs b/crates/primitives/src/kzg/env_settings.rs index d9b5f24350..8e48ca98aa 100644 --- a/crates/primitives/src/kzg/env_settings.rs +++ b/crates/primitives/src/kzg/env_settings.rs @@ -5,33 +5,39 @@ use super::{ use once_cell::race::OnceBox; use std::{boxed::Box, sync::Arc}; -/// KZG Settings that allow us to specify a custom trusted setup. -/// or use hardcoded default settings. -#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] -pub enum EnvKzgSettings { - /// Default mainnet trusted setup - #[default] - Default, - /// Custom trusted setup. - Custom(Arc), -} +cfg_if::cfg_if! { + if #[cfg(feature = "c-kzg")] { + /// KZG Settings that allow us to specify a custom trusted setup. + /// or use hardcoded default settings. + #[derive(Debug, Clone, Default, PartialEq, Eq )] + pub enum EnvKzgSettings { + /// Default mainnet trusted setup + #[default] + Default, + /// Custom trusted setup. + Custom(Arc), + } -impl EnvKzgSettings { - /// Return set KZG settings. - /// - /// In will initialize the default settings if it is not already loaded. - pub fn get(&self) -> &KzgSettings { - match self { - Self::Default => { - static DEFAULT: OnceBox = OnceBox::new(); - DEFAULT.get_or_init(|| { - let settings = - KzgSettings::load_trusted_setup(G1_POINTS.as_ref(), G2_POINTS.as_ref()) - .expect("failed to load default trusted setup"); - Box::new(settings) - }) + impl EnvKzgSettings { + /// Return set KZG settings. + /// + /// In will initialize the default settings if it is not already loaded. + pub fn get(&self) -> &KzgSettings { + match self { + Self::Default => { + static DEFAULT: OnceBox = OnceBox::new(); + DEFAULT.get_or_init(|| { + let settings = + KzgSettings::load_trusted_setup(G1_POINTS.as_ref(), G2_POINTS.as_ref()) + .expect("failed to load default trusted setup"); + Box::new(settings) + }) + } + Self::Custom(settings) => settings, + } } - Self::Custom(settings) => settings, } + } else if #[cfg(feature = "kzg-rs")] { + pub use kzg_rs::EnvKzgSettings; } } diff --git a/crates/primitives/src/kzg/trusted_setup_points.rs b/crates/primitives/src/kzg/trusted_setup_points.rs index dc90b64bed..c89c4e642e 100644 --- a/crates/primitives/src/kzg/trusted_setup_points.rs +++ b/crates/primitives/src/kzg/trusted_setup_points.rs @@ -2,7 +2,13 @@ use core::fmt; use derive_more::{AsMut, AsRef, Deref, DerefMut}; use std::boxed::Box; -pub use c_kzg::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; +cfg_if::cfg_if! { + if #[cfg(feature = "c-kzg")] { + pub use c_kzg::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; + } else if #[cfg(feature = "kzg-rs")] { + pub use kzg_rs::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}; + } +} /// Number of G1 Points. pub const NUM_G1_POINTS: usize = 4096; diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 78e939d5f7..e29efe9b12 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -12,7 +12,7 @@ mod constants; pub mod db; pub mod env; -#[cfg(feature = "c-kzg")] +#[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg; pub mod precompile; pub mod result; @@ -38,10 +38,14 @@ cfg_if::cfg_if! { } } -#[cfg(feature = "c-kzg")] +#[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub use kzg::{EnvKzgSettings, KzgSettings}; pub use precompile::*; pub use result::*; pub use specification::*; pub use state::*; pub use utilities::*; + +#[cfg(all(feature = "c-kzg", feature = "kzg-rs"))] +// silence kzg-rs lint as c-kzg will be used as default if both are enabled. +use kzg_rs as _; diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 14614d4410..f5013c4b7b 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -126,6 +126,8 @@ optional_beneficiary_reward = ["revm-interpreter/optional_beneficiary_reward"] # See comments in `revm-precompile` secp256k1 = ["revm-precompile/secp256k1"] c-kzg = ["revm-precompile/c-kzg"] +# `kzg-rs` is not audited but useful for `no_std` environment, use it with causing and default to `c-kzg` if possible. +kzg-rs = ["revm-precompile/kzg-rs"] blst = ["revm-precompile/blst"] [[example]]