diff --git a/Cargo.lock b/Cargo.lock index d19b7c5a5..5fbbc8bb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -601,6 +601,27 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bindgen" +version = "0.64.0" +source = "git+https://github.com/rust-lang/rust-bindgen?rev=0de11f0a521611ac8738b7b01d19dddaf3899e66#0de11f0a521611ac8738b7b01d19dddaf3899e66" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2 1.0.66", + "quote 1.0.32", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.27", + "which", +] + [[package]] name = "bindgen" version = "0.65.1" @@ -909,6 +930,19 @@ dependencies = [ "serde", ] +[[package]] +name = "c-kzg" +version = "0.1.0" +source = "git+https://github.com/ethereum/c-kzg-4844#13cec820c08f45318f82ed4e0da0300042758b92" +dependencies = [ + "bindgen 0.64.0 (git+https://github.com/rust-lang/rust-bindgen?rev=0de11f0a521611ac8738b7b01d19dddaf3899e66)", + "cc", + "glob", + "hex", + "libc", + "serde", +] + [[package]] name = "camino" version = "1.1.6" @@ -3703,7 +3737,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b18cbf29f8ff3542ba22bdce9ac610fcb75d74bb4e2b306b2a2762242025b4f" dependencies = [ - "bindgen 0.64.0", + "bindgen 0.64.0 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.8", "libc", ] @@ -5767,6 +5801,7 @@ dependencies = [ "arbitrary", "assert_matches", "bytes", + "c-kzg", "crc", "criterion", "crunchy", @@ -5893,6 +5928,7 @@ dependencies = [ "arrayvec", "auto_impl", "bytes", + "c-kzg", "criterion", "ethereum-types", "ethnum", @@ -8219,6 +8255,17 @@ dependencies = [ "rustls-webpki", ] +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "widestring" version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index 602c36e32..4d083e629 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,6 +143,8 @@ jsonrpsee-types = { version = "0.19" } ## crypto secp256k1 = { version = "0.27.0", default-features = false, features = ["global-context", "rand-std", "recovery"] } +# for eip-4844 +c-kzg = { git = "https://github.com/ethereum/c-kzg-4844" } ### misc-testing proptest = "1.0" diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 0931d4fe4..e73b59d88 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -22,7 +22,7 @@ crunchy = { version = "0.2.2", default-features = false, features = ["limit_256" ruint = { version = "1.9.0", features = ["primitive-types", "rlp"] } # Bloom - fixed-hash = { version = "0.8", default-features = false, features = ["rustc-hex"] } +fixed-hash = { version = "0.8", default-features = false, features = ["rustc-hex"] } # crypto secp256k1 = { workspace = true, default-features = false, features = [ @@ -31,6 +31,9 @@ secp256k1 = { workspace = true, default-features = false, features = [ "recovery", ] } +# for eip-4844 +c-kzg = { workspace = true } + # used for forkid crc = "3" diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 82c0929e1..02946310f 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -142,6 +142,11 @@ pub mod utils { pub use ethers_core::types::serde_helpers; } +/// EIP-4844 + KZG helpers +pub mod kzg { + pub use c_kzg::*; +} + /// Helpers for working with serde pub mod serde_helper; diff --git a/crates/rlp/Cargo.toml b/crates/rlp/Cargo.toml index 653543b51..98c25c7e3 100644 --- a/crates/rlp/Cargo.toml +++ b/crates/rlp/Cargo.toml @@ -18,6 +18,9 @@ ethereum-types = { version = "0.14", features = ["codec"], optional = true } revm-primitives = { workspace = true, features = ["serde"] } reth-rlp-derive = { path = "./rlp-derive", optional = true } +# for eip-4844 +c-kzg = { workspace = true, optional = true } + [dev-dependencies] reth-rlp = { workspace = true, features = [ "derive", @@ -31,9 +34,11 @@ criterion = "0.5.0" pprof = { version = "0.12", features = ["flamegraph", "frame-pointer", "criterion"] } [features] +default = ["kzg"] alloc = [] derive = ["reth-rlp-derive"] std = ["alloc"] +kzg = ["c-kzg"] [[bench]] name = "bench" diff --git a/crates/rlp/src/encode.rs b/crates/rlp/src/encode.rs index 759165a08..6d669fd66 100644 --- a/crates/rlp/src/encode.rs +++ b/crates/rlp/src/encode.rs @@ -413,6 +413,77 @@ pub fn encode_fixed_size, const LEN: usize>(v: &E) -> Arra out } +#[cfg(feature = "kzg")] +mod kzg_support { + extern crate c_kzg; + + use super::BufMut; + use crate::{Decodable, DecodeError, Encodable}; + use c_kzg::{Blob, Bytes48, KzgCommitment, KzgProof, BYTES_PER_BLOB, BYTES_PER_COMMITMENT}; + use core::ops::Deref; + + impl Encodable for Blob { + fn encode(&self, out: &mut dyn BufMut) { + // Deref is implemented to get the underlying bytes + self.deref().encode(out); + } + + fn length(&self) -> usize { + self.deref().length() + } + } + + impl Decodable for Blob { + fn decode(buf: &mut &[u8]) -> Result { + let bytes: [u8; BYTES_PER_BLOB] = Decodable::decode(buf)?; + Ok(Blob::from(bytes)) + } + } + + impl Encodable for Bytes48 { + fn encode(&self, out: &mut dyn BufMut) { + self.deref().encode(out); + } + + fn length(&self) -> usize { + self.deref().length() + } + } + + impl Decodable for Bytes48 { + fn decode(buf: &mut &[u8]) -> Result { + let bytes: [u8; BYTES_PER_COMMITMENT] = Decodable::decode(buf)?; + Ok(Bytes48::from(bytes)) + } + } + + /// Only [Encodable] is implemented for [KzgCommitment] because this is a validated type - it + /// should be decoded using [Decodable] into a [Bytes48] type, validated, _then_ converted + /// into a [KzgCommitment]. + impl Encodable for KzgCommitment { + fn encode(&self, out: &mut dyn BufMut) { + self.deref().encode(out); + } + + fn length(&self) -> usize { + self.deref().length() + } + } + + /// Only [Encodable] is implemented for [KzgProof] because this is a validated type - it should + /// be decoded using [Decodable] into a [Bytes48] type, validated, _then_ converted into a + /// [KzgProof]. + impl Encodable for KzgProof { + fn encode(&self, out: &mut dyn BufMut) { + self.deref().encode(out); + } + + fn length(&self) -> usize { + self.deref().length() + } + } +} + #[cfg(test)] mod tests { extern crate alloc; diff --git a/deny.toml b/deny.toml index c76bbe889..3c59af057 100644 --- a/deny.toml +++ b/deny.toml @@ -84,6 +84,13 @@ name = "rustls-webpki" expression = "LicenseRef-rustls-webpki" license-files = [{ path = "LICENSE", hash = 0x001c7e6c }] +[[licenses.clarify]] +name = "c-kzg" +expression = "Apache-2.0" +# The crate is in `bindings/rust` so we have to go up two directories for the +# license +license-files = [{ path = "../../LICENSE", hash = 0x13cec820 }] + # This section is considered when running `cargo deny check sources`. # More documentation about the 'sources' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html