diff --git a/Cargo.lock b/Cargo.lock index cf825eaba2ec..692c43dc7477 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,11 +153,23 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f938f00332d63a5b0ac687bd6f46d03884638948921d9f8b50c59563d421ae25" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", "smol_str", ] +[[package]] +name = "alloy-rlp-derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa5bb468bc7c46e0c5074d418f575262ff79451242e5ac1380121ed4e23c4fd" +dependencies = [ + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -1932,12 +1944,12 @@ dependencies = [ name = "ef-tests" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "reth-db", "reth-interfaces", "reth-primitives", "reth-provider", "reth-revm", - "reth-rlp", "reth-stages", "serde", "serde_json", @@ -2373,12 +2385,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "ethnum" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0198b9d0078e0f30dedc7acbb21c974e838fc8fae3ee170128658a98cb2c1c04" - [[package]] name = "event-listener" version = "2.5.3" @@ -5220,6 +5226,7 @@ dependencies = [ name = "reth" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "backon", "clap", "comfy-table", @@ -5262,7 +5269,6 @@ dependencies = [ "reth-prune", "reth-revm", "reth-revm-inspectors", - "reth-rlp", "reth-rpc", "reth-rpc-api", "reth-rpc-builder", @@ -5307,6 +5313,7 @@ dependencies = [ name = "reth-basic-payload-builder" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "futures-core", "futures-util", "reth-metrics", @@ -5314,7 +5321,6 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-revm", - "reth-rlp", "reth-tasks", "reth-transaction-pool", "revm", @@ -5457,6 +5463,7 @@ dependencies = [ name = "reth-discv4" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "discv5", "enr 0.8.1", "generic-array", @@ -5465,8 +5472,6 @@ dependencies = [ "reth-net-common", "reth-net-nat", "reth-primitives", - "reth-rlp", - "reth-rlp-derive", "reth-tracing", "secp256k1", "serde", @@ -5480,6 +5485,7 @@ dependencies = [ name = "reth-dns-discovery" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "async-trait", "data-encoding", "enr 0.8.1", @@ -5487,7 +5493,6 @@ dependencies = [ "parking_lot 0.12.1", "reth-net-common", "reth-primitives", - "reth-rlp", "reth-tracing", "schnellru", "secp256k1", @@ -5504,6 +5509,7 @@ dependencies = [ name = "reth-downloaders" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "assert_matches", "futures", "futures-util", @@ -5514,7 +5520,6 @@ dependencies = [ "reth-interfaces", "reth-metrics", "reth-primitives", - "reth-rlp", "reth-tasks", "reth-tracing", "tempfile", @@ -5530,6 +5535,7 @@ name = "reth-ecies" version = "0.1.0-alpha.6" dependencies = [ "aes 0.8.3", + "alloy-rlp", "block-padding", "byteorder", "cipher 0.4.4", @@ -5544,7 +5550,6 @@ dependencies = [ "rand 0.8.5", "reth-net-common", "reth-primitives", - "reth-rlp", "secp256k1", "sha2 0.10.7", "sha3", @@ -5560,6 +5565,7 @@ dependencies = [ name = "reth-eth-wire" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "arbitrary", "async-trait", "bytes", @@ -5575,7 +5581,6 @@ dependencies = [ "reth-ecies", "reth-metrics", "reth-primitives", - "reth-rlp", "reth-tracing", "secp256k1", "serde", @@ -5716,6 +5721,7 @@ dependencies = [ name = "reth-network" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "aquamarine", "async-trait", "auto_impl", @@ -5744,8 +5750,6 @@ dependencies = [ "reth-network-api", "reth-primitives", "reth-provider", - "reth-rlp", - "reth-rlp-derive", "reth-rpc-types", "reth-tasks", "reth-tracing", @@ -5779,12 +5783,12 @@ dependencies = [ name = "reth-payload-builder" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "futures-util", "reth-interfaces", "reth-metrics", "reth-primitives", "reth-revm-primitives", - "reth-rlp", "reth-rpc-types", "revm-primitives", "sha2 0.10.7", @@ -5798,6 +5802,7 @@ dependencies = [ name = "reth-primitives" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "arbitrary", "assert_matches", "bytes", @@ -5821,8 +5826,6 @@ dependencies = [ "proptest-derive", "rand 0.8.5", "reth-codecs", - "reth-rlp", - "reth-rlp-derive", "revm-primitives", "ruint", "secp256k1", @@ -5848,6 +5851,7 @@ dependencies = [ name = "reth-provider" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "auto_impl", "derive_more", "itertools 0.11.0", @@ -5857,7 +5861,6 @@ dependencies = [ "reth-interfaces", "reth-primitives", "reth-revm-primitives", - "reth-rlp", "reth-trie", "tempfile", "tokio", @@ -5886,6 +5889,7 @@ dependencies = [ name = "reth-revm" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "once_cell", "reth-consensus-common", "reth-interfaces", @@ -5893,7 +5897,6 @@ dependencies = [ "reth-provider", "reth-revm-inspectors", "reth-revm-primitives", - "reth-rlp", "revm", "tracing", ] @@ -5922,38 +5925,11 @@ dependencies = [ "revm", ] -[[package]] -name = "reth-rlp" -version = "0.1.0-alpha.6" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "c-kzg", - "criterion", - "ethereum-types", - "ethnum", - "hex-literal 0.4.1", - "pprof", - "reth-rlp", - "reth-rlp-derive", - "revm-primitives", - "smol_str", -] - -[[package]] -name = "reth-rlp-derive" -version = "0.1.0-alpha.6" -dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.32", - "syn 2.0.28", -] - [[package]] name = "reth-rpc" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "assert_matches", "async-trait", "bytes", @@ -5975,7 +5951,6 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-revm", - "reth-rlp", "reth-rpc-api", "reth-rpc-engine-api", "reth-rpc-types", @@ -6057,6 +6032,7 @@ dependencies = [ name = "reth-rpc-engine-api" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "assert_matches", "async-trait", "jsonrpsee-core", @@ -6066,7 +6042,6 @@ dependencies = [ "reth-payload-builder", "reth-primitives", "reth-provider", - "reth-rlp", "reth-rpc-api", "reth-rpc-types", "reth-tasks", @@ -6079,11 +6054,11 @@ dependencies = [ name = "reth-rpc-types" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "itertools 0.11.0", "jsonrpsee-types", "rand 0.8.5", "reth-primitives", - "reth-rlp", "serde", "serde_json", "similar-asserts", @@ -6094,8 +6069,8 @@ dependencies = [ name = "reth-rpc-types-compat" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "reth-primitives", - "reth-rlp", "reth-rpc-types", ] @@ -6103,6 +6078,7 @@ dependencies = [ name = "reth-stages" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "aquamarine", "assert_matches", "async-trait", @@ -6125,7 +6101,6 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-revm", - "reth-rlp", "reth-trie", "serde", "serde_json", @@ -6162,6 +6137,7 @@ dependencies = [ name = "reth-transaction-pool" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "aquamarine", "assert_matches", "async-trait", @@ -6178,7 +6154,6 @@ dependencies = [ "reth-metrics", "reth-primitives", "reth-provider", - "reth-rlp", "reth-tasks", "serde", "thiserror", @@ -6191,6 +6166,7 @@ dependencies = [ name = "reth-trie" version = "0.1.0-alpha.6" dependencies = [ + "alloy-rlp", "criterion", "derive_more", "hex", @@ -6199,7 +6175,6 @@ dependencies = [ "reth-interfaces", "reth-primitives", "reth-provider", - "reth-rlp", "thiserror", "tokio", "tokio-stream", diff --git a/Cargo.toml b/Cargo.toml index 244240b97686..4879467031ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,8 +25,6 @@ members = [ "crates/revm", "crates/revm/revm-primitives", "crates/revm/revm-inspectors", - "crates/rlp", - "crates/rlp/rlp-derive", "crates/rpc/ipc", "crates/rpc/rpc", "crates/rpc/rpc-api", @@ -62,9 +60,7 @@ rust-version = "1.70" # Remember to update .clippy.toml and README.md license = "MIT OR Apache-2.0" homepage = "https://paradigmxyz.github.io/reth" repository = "https://github.com/paradigmxyz/reth" -exclude = [ - ".github/", -] +exclude = [".github/"] # Like release, but with full debug symbols. Useful for e.g. `perf`. [profile.debug-fast] @@ -90,7 +86,6 @@ reth-primitives = { path = "./crates/primitives" } reth-interfaces = { path = "./crates/interfaces" } reth-provider = { path = "./crates/storage/provider" } reth-db = { path = "./crates/storage/db" } -reth-rlp = { path = "./crates/rlp" } reth-rpc-types = { path = "./crates/rpc/rpc-types" } reth-rpc-builder = { path = "./crates/rpc/rpc-builder" } reth-blockchain-tree = { path = "./crates/blockchain-tree" } @@ -106,6 +101,7 @@ reth-rpc-types-compat = { path = "./crates/rpc/rpc-types-compat"} ## eth +alloy-rlp = { version = "0.3.1", default-features = false } ethers-core = { version = "2.0.8", default-features = false } ethers-providers = { version = "2.0.8", default-features = false } ethers-signers = { version = "2.0.8", default-features = false } @@ -150,4 +146,4 @@ c-kzg = { git = "https://github.com/ethereum/c-kzg-4844" } ### misc-testing proptest = "1.0" -arbitrary = "1.1" \ No newline at end of file +arbitrary = "1.1" diff --git a/bin/reth/Cargo.toml b/bin/reth/Cargo.toml index 6f636cbb5143..7c1d82dbbd32 100644 --- a/bin/reth/Cargo.toml +++ b/bin/reth/Cargo.toml @@ -28,7 +28,6 @@ reth-rpc-builder = { path = "../../crates/rpc/rpc-builder" } reth-rpc = { path = "../../crates/rpc/rpc" } reth-rpc-types = { path = "../../crates/rpc/rpc-types" } reth-rpc-api = { path = "../../crates/rpc/rpc-api" } -reth-rlp.workspace = true reth-network = { path = "../../crates/net/network", features = ["serde"] } reth-network-api.workspace = true reth-downloaders = { path = "../../crates/net/downloaders", features = ["test-utils"] } @@ -42,6 +41,8 @@ reth-metrics.workspace = true reth-prune = { path = "../../crates/prune" } reth-trie = { path = "../../crates/trie" } +alloy-rlp.workspace = true + # crypto secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery"] } diff --git a/bin/reth/src/args/payload_builder_args.rs b/bin/reth/src/args/payload_builder_args.rs index 2f3837db7457..f2d10bf1be57 100644 --- a/bin/reth/src/args/payload_builder_args.rs +++ b/bin/reth/src/args/payload_builder_args.rs @@ -2,6 +2,7 @@ use crate::{ args::utils::parse_duration_from_secs, cli::config::PayloadBuilderConfig, version::default_extradata, }; +use alloy_rlp::Encodable; use clap::{ builder::{RangedU64ValueParser, TypedValueParser}, Arg, Args, Command, diff --git a/bin/reth/src/cli/config.rs b/bin/reth/src/cli/config.rs index a698b3a5d472..940017ca9f34 100644 --- a/bin/reth/src/cli/config.rs +++ b/bin/reth/src/cli/config.rs @@ -1,7 +1,7 @@ //! Config traits for various node components. +use alloy_rlp::Encodable; use reth_revm::primitives::bytes::BytesMut; -use reth_rlp::Encodable; use reth_rpc_builder::EthConfig; use std::{borrow::Cow, time::Duration}; diff --git a/crates/net/discv4/Cargo.toml b/crates/net/discv4/Cargo.toml index 2c5bd92cbe98..d3646b1627ef 100644 --- a/crates/net/discv4/Cargo.toml +++ b/crates/net/discv4/Cargo.toml @@ -13,12 +13,11 @@ Ethereum network discovery [dependencies] # reth reth-primitives.workspace = true -reth-rlp.workspace = true -reth-rlp-derive = { path = "../../rlp/rlp-derive" } reth-net-common = { path = "../common" } reth-net-nat = { path = "../nat" } # ethereum +alloy-rlp = { workspace = true, features = ["derive"] } discv5 = { git = "https://github.com/sigp/discv5" } secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } enr = { version = "0.8.1", default-features = false, features = ["rust-secp256k1"] } diff --git a/crates/net/discv4/src/config.rs b/crates/net/discv4/src/config.rs index 924a7b62371e..452acc0ab741 100644 --- a/crates/net/discv4/src/config.rs +++ b/crates/net/discv4/src/config.rs @@ -3,13 +3,13 @@ //! This basis of this file has been taken from the discv5 codebase: //! +use alloy_rlp::Encodable; use reth_net_common::ban_list::BanList; use reth_net_nat::{NatResolver, ResolveNatInterval}; use reth_primitives::{ bytes::{Bytes, BytesMut}, NodeRecord, }; -use reth_rlp::Encodable; use std::{ collections::{HashMap, HashSet}, time::Duration, diff --git a/crates/net/discv4/src/error.rs b/crates/net/discv4/src/error.rs index 804e084ba589..580f0e23d860 100644 --- a/crates/net/discv4/src/error.rs +++ b/crates/net/discv4/src/error.rs @@ -7,7 +7,7 @@ use tokio::sync::{mpsc::error::SendError, oneshot::error::RecvError}; #[allow(missing_docs)] pub enum DecodePacketError { #[error("Failed to rlp decode: {0:?}")] - Rlp(#[from] reth_rlp::DecodeError), + Rlp(#[from] alloy_rlp::Error), #[error("Received packet len too short.")] PacketTooShort, #[error("Hash of the header not equals to the hash of the data.")] diff --git a/crates/net/discv4/src/lib.rs b/crates/net/discv4/src/lib.rs index f5bff545f754..0e1cc83d3cc3 100644 --- a/crates/net/discv4/src/lib.rs +++ b/crates/net/discv4/src/lib.rs @@ -28,10 +28,12 @@ //! //! - `serde` (default): Enable serde support //! - `test-utils`: Export utilities for testing + use crate::{ error::{DecodePacketError, Discv4Error}, proto::{FindNode, Message, Neighbours, Packet, Ping, Pong}, }; +use alloy_rlp::{RlpDecodable, RlpEncodable}; use discv5::{ kbucket, kbucket::{ @@ -46,7 +48,6 @@ use reth_primitives::{ bytes::{Bytes, BytesMut}, ForkId, PeerId, H256, }; -use reth_rlp::{RlpDecodable, RlpEncodable}; use secp256k1::SecretKey; use std::{ cell::RefCell, @@ -321,7 +322,7 @@ impl Discv4 { /// Sets the pair in the EIP-868 [`Enr`] of the node. /// /// If the key already exists, this will update it. - pub fn set_eip868_rlp(&self, key: Vec, value: impl reth_rlp::Encodable) { + pub fn set_eip868_rlp(&self, key: Vec, value: impl alloy_rlp::Encodable) { let mut buf = BytesMut::new(); value.encode(&mut buf); self.set_eip868_rlp_pair(key, buf.freeze()) @@ -1003,6 +1004,7 @@ impl Discv4Service { let remote_addr = node.udp_addr(); let id = node.id; let ping = Ping { + version: 4, from: self.local_node_record.into(), to: node.into(), expire: self.ping_expiration(), @@ -2003,9 +2005,9 @@ impl From for EnrForkIdEntry { mod tests { use super::*; use crate::test_utils::{create_discv4, create_discv4_with_config, rng_endpoint, rng_record}; + use alloy_rlp::{Decodable, Encodable}; use rand::{thread_rng, Rng}; use reth_primitives::{hex_literal::hex, mainnet_nodes, ForkHash}; - use reth_rlp::{Decodable, Encodable}; use std::{future::poll_fn, net::Ipv4Addr}; #[tokio::test] @@ -2131,6 +2133,7 @@ mod tests { let addr: SocketAddr = (v6, 30303).into(); let ping = Ping { + version: 4, from: rng_endpoint(&mut rng), to: rng_endpoint(&mut rng), expire: service.ping_expiration(), @@ -2163,6 +2166,7 @@ mod tests { let addr: SocketAddr = (v6, 30303).into(); let ping = Ping { + version: 4, from: rng_endpoint(&mut rng), to: rng_endpoint(&mut rng), expire: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() - 1, @@ -2303,6 +2307,7 @@ mod tests { // ping node 2 with wrong to field let mut ping = Ping { + version: 4, from: service_1.local_node_record.into(), to: service_2.local_node_record.into(), expire: service_1.ping_expiration(), diff --git a/crates/net/discv4/src/proto.rs b/crates/net/discv4/src/proto.rs index 88b3bb93644d..bd0ad5f1cf58 100644 --- a/crates/net/discv4/src/proto.rs +++ b/crates/net/discv4/src/proto.rs @@ -1,6 +1,9 @@ #![allow(missing_docs)] use crate::{error::DecodePacketError, EnrForkIdEntry, PeerId, MAX_PACKET_SIZE, MIN_PACKET_SIZE}; +use alloy_rlp::{ + length_of_length, Decodable, Encodable, Error as RlpError, Header, RlpDecodable, RlpEncodable, +}; use enr::{Enr, EnrKey}; use reth_primitives::{ bytes::{Buf, BufMut, Bytes, BytesMut}, @@ -8,8 +11,6 @@ use reth_primitives::{ rpc_utils::rlp, ForkId, NodeRecord, H256, }; -use reth_rlp::{length_of_length, Decodable, DecodeError, Encodable, Header}; -use reth_rlp_derive::{RlpDecodable, RlpEncodable}; use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, SecretKey, SECP256K1, @@ -224,21 +225,19 @@ impl EnrWrapper { } } -impl Encodable for EnrWrapper -where - K: EnrKey, -{ - fn encode(&self, out: &mut dyn BufMut) { - let payload_length = self.0.signature().length() + +impl EnrWrapper { + fn payload_length(&self) -> usize { + self.0.signature().length() + self.0.seq().length() + - self.0.iter().fold(0, |acc, (k, v)| acc + k.as_slice().length() + v.len()); - - let header = Header { list: true, payload_length }; - header.encode(out); + self.0.iter().fold(0, |acc, (k, v)| acc + k.as_slice().length() + v.len()) + } +} +impl Encodable for EnrWrapper { + fn encode(&self, out: &mut dyn BufMut) { + Header { list: true, payload_length: self.payload_length() }.encode(out); self.0.signature().encode(out); self.0.seq().encode(out); - for (k, v) in self.0.iter() { // Keys are byte data k.as_slice().encode(out); @@ -248,32 +247,30 @@ where } fn length(&self) -> usize { - let payload_length = self.0.signature().length() + - self.0.seq().length() + - self.0.iter().fold(0, |acc, (k, v)| acc + k.as_slice().length() + v.len()); + let payload_length = self.payload_length(); payload_length + length_of_length(payload_length) } } impl Decodable for EnrWrapper { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> Result { let enr = as rlp::Decodable>::decode(&rlp::Rlp::new(buf)) .map_err(|e| match e { - rlp::DecoderError::RlpIsTooShort => DecodeError::InputTooShort, - rlp::DecoderError::RlpInvalidLength => DecodeError::Overflow, - rlp::DecoderError::RlpExpectedToBeList => DecodeError::UnexpectedString, - rlp::DecoderError::RlpExpectedToBeData => DecodeError::UnexpectedList, + rlp::DecoderError::RlpIsTooShort => RlpError::InputTooShort, + rlp::DecoderError::RlpInvalidLength => RlpError::Overflow, + rlp::DecoderError::RlpExpectedToBeList => RlpError::UnexpectedString, + rlp::DecoderError::RlpExpectedToBeData => RlpError::UnexpectedList, rlp::DecoderError::RlpDataLenWithZeroPrefix | - rlp::DecoderError::RlpListLenWithZeroPrefix => DecodeError::LeadingZero, - rlp::DecoderError::RlpInvalidIndirection => DecodeError::NonCanonicalSize, + rlp::DecoderError::RlpListLenWithZeroPrefix => RlpError::LeadingZero, + rlp::DecoderError::RlpInvalidIndirection => RlpError::NonCanonicalSize, rlp::DecoderError::RlpIncorrectListLen => { - DecodeError::Custom("incorrect list length when decoding rlp") + RlpError::Custom("incorrect list length when decoding rlp") } - rlp::DecoderError::RlpIsTooBig => DecodeError::Custom("rlp is too big"), + rlp::DecoderError::RlpIsTooBig => RlpError::Custom("rlp is too big"), rlp::DecoderError::RlpInconsistentLengthAndData => { - DecodeError::Custom("inconsistent length and data when decoding rlp") + RlpError::Custom("inconsistent length and data when decoding rlp") } - rlp::DecoderError::Custom(s) => DecodeError::Custom(s), + rlp::DecoderError::Custom(s) => RlpError::Custom(s), }) .map(EnrWrapper::new); if enr.is_ok() { @@ -292,7 +289,7 @@ pub struct EnrRequest { } /// A [ENRResponse packet](https://github.com/ethereum/devp2p/blob/master/discv4.md#enrresponse-packet-0x06). -#[derive(Clone, Debug, Eq, PartialEq, RlpEncodable)] +#[derive(Clone, Debug, Eq, PartialEq, RlpEncodable, RlpDecodable)] pub struct EnrResponse { pub request_hash: H256, pub enr: EnrWrapper, @@ -310,35 +307,11 @@ impl EnrResponse { } } -impl Decodable for EnrResponse { - fn decode(buf: &mut &[u8]) -> Result { - let b = &mut &**buf; - let rlp_head = Header::decode(b)?; - if !rlp_head.list { - return Err(DecodeError::UnexpectedString) - } - // let started_len = b.len(); - let this = Self { - request_hash: reth_rlp::Decodable::decode(b)?, - enr: EnrWrapper::::decode(b)?, - }; - // TODO: `Decodable` can be derived once we have native reth_rlp decoding for ENR: - // Skipping the size check here is fine since the `buf` is the UDP datagram - // let consumed = started_len - b.len(); - // if consumed != rlp_head.payload_length { - // return Err(reth_rlp::DecodeError::ListLengthMismatch { - // expected: rlp_head.payload_length, - // got: consumed, - // }) - // } - *buf = *b; - Ok(this) - } -} - /// A [Ping packet](https://github.com/ethereum/devp2p/blob/master/discv4.md#ping-packet-0x01). -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, RlpEncodable, RlpDecodable)] +// #[rlp(trailing)] pub struct Ping { + pub version: u32, pub from: NodeEndpoint, pub to: NodeEndpoint, pub expire: u64, @@ -346,82 +319,9 @@ pub struct Ping { pub enr_sq: Option, } -impl Encodable for Ping { - fn encode(&self, out: &mut dyn BufMut) { - #[derive(RlpEncodable)] - struct V4PingMessage<'a> { - version: u32, - from: &'a NodeEndpoint, - to: &'a NodeEndpoint, - expire: u64, - } - - #[derive(RlpEncodable)] - struct V4PingMessageEIP868<'a> { - version: u32, - from: &'a NodeEndpoint, - to: &'a NodeEndpoint, - expire: u64, - enr_seq: u64, - } - if let Some(enr_seq) = self.enr_sq { - V4PingMessageEIP868 { - version: 4, // version 4 - from: &self.from, - to: &self.to, - expire: self.expire, - enr_seq, - } - .encode(out); - } else { - V4PingMessage { - version: 4, // version 4 - from: &self.from, - to: &self.to, - expire: self.expire, - } - .encode(out); - } - } -} - -impl Decodable for Ping { - fn decode(buf: &mut &[u8]) -> Result { - let b = &mut &**buf; - let rlp_head = Header::decode(b)?; - if !rlp_head.list { - return Err(DecodeError::UnexpectedString) - } - let started_len = b.len(); - let _version = u32::decode(b)?; - let mut this = Self { - from: Decodable::decode(b)?, - to: Decodable::decode(b)?, - expire: Decodable::decode(b)?, - enr_sq: None, - }; - - // only decode the ENR sequence if there's more data in the datagram to decode else skip - if b.has_remaining() { - this.enr_sq = Some(Decodable::decode(b)?); - } - - let consumed = started_len - b.len(); - if consumed > rlp_head.payload_length { - return Err(DecodeError::ListLengthMismatch { - expected: rlp_head.payload_length, - got: consumed, - }) - } - let rem = rlp_head.payload_length - consumed; - b.advance(rem); - *buf = *b; - Ok(this) - } -} - /// A [Pong packet](https://github.com/ethereum/devp2p/blob/master/discv4.md#pong-packet-0x02). -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, RlpEncodable, RlpDecodable)] +// #[rlp(trailing)] pub struct Pong { pub to: NodeEndpoint, pub echo: H256, @@ -430,67 +330,6 @@ pub struct Pong { pub enr_sq: Option, } -impl Encodable for Pong { - fn encode(&self, out: &mut dyn BufMut) { - #[derive(RlpEncodable)] - struct PongMessageEIP868<'a> { - to: &'a NodeEndpoint, - echo: &'a H256, - expire: u64, - enr_seq: u64, - } - - #[derive(RlpEncodable)] - struct PongMessage<'a> { - to: &'a NodeEndpoint, - echo: &'a H256, - expire: u64, - } - - if let Some(enr_seq) = self.enr_sq { - PongMessageEIP868 { to: &self.to, echo: &self.echo, expire: self.expire, enr_seq } - .encode(out); - } else { - PongMessage { to: &self.to, echo: &self.echo, expire: self.expire }.encode(out); - } - } -} - -impl Decodable for Pong { - fn decode(buf: &mut &[u8]) -> Result { - let b = &mut &**buf; - let rlp_head = Header::decode(b)?; - if !rlp_head.list { - return Err(DecodeError::UnexpectedString) - } - let started_len = b.len(); - let mut this = Self { - to: Decodable::decode(b)?, - echo: Decodable::decode(b)?, - expire: Decodable::decode(b)?, - enr_sq: None, - }; - - // only decode the ENR sequence if there's more data in the datagram to decode else skip - if b.has_remaining() { - this.enr_sq = Some(Decodable::decode(b)?); - } - - let consumed = started_len - b.len(); - if consumed > rlp_head.payload_length { - return Err(DecodeError::ListLengthMismatch { - expected: rlp_head.payload_length, - got: consumed, - }) - } - let rem = rlp_head.payload_length - consumed; - b.advance(rem); - *buf = *b; - - Ok(this) - } -} - #[cfg(test)] mod tests { use super::*; @@ -549,6 +388,7 @@ mod tests { let mut ip = [0u8; 16]; rng.fill_bytes(&mut ip); let msg = Ping { + version: 4, from: rng_endpoint(&mut rng), to: rng_endpoint(&mut rng), expire: 0, @@ -570,6 +410,7 @@ mod tests { let mut ip = [0u8; 16]; rng.fill_bytes(&mut ip); let msg = Ping { + version: 4, from: rng_endpoint(&mut rng), to: rng_endpoint(&mut rng), expire: 0, @@ -717,8 +558,8 @@ mod tests { #[test] fn encode_decode_enr_msg() { use self::EnrWrapper; + use alloy_rlp::Decodable; use enr::secp256k1::SecretKey; - use reth_rlp::Decodable; use std::net::Ipv4Addr; let key = SecretKey::new(&mut rand::rngs::OsRng); @@ -755,8 +596,8 @@ mod tests { #[test] fn encode_known_rlp_enr() { use self::EnrWrapper; + use alloy_rlp::Decodable; use enr::{secp256k1::SecretKey, EnrPublicKey}; - use reth_rlp::Decodable; use std::net::Ipv4Addr; let valid_record = diff --git a/crates/net/discv4/src/test_utils.rs b/crates/net/discv4/src/test_utils.rs index 3c1ce96b8b5b..cc03941c6126 100644 --- a/crates/net/discv4/src/test_utils.rs +++ b/crates/net/discv4/src/test_utils.rs @@ -253,6 +253,7 @@ pub fn rng_ipv4_record(rng: &mut impl RngCore) -> NodeRecord { pub fn rng_message(rng: &mut impl RngCore) -> Message { match rng.gen_range(1..=4) { 1 => Message::Ping(Ping { + version: 4, from: rng_endpoint(rng), to: rng_endpoint(rng), expire: rng.gen(), diff --git a/crates/net/dns/Cargo.toml b/crates/net/dns/Cargo.toml index 14054205de95..85ebb1c870a2 100644 --- a/crates/net/dns/Cargo.toml +++ b/crates/net/dns/Cargo.toml @@ -12,7 +12,8 @@ description = "Support for EIP-1459 Node Discovery via DNS" # reth reth-primitives.workspace = true reth-net-common = { path = "../common" } -reth-rlp.workspace = true + +alloy-rlp.workspace = true # ethereum secp256k1 = { workspace = true, features = ["global-context", "rand-std", "recovery", "serde"] } diff --git a/crates/net/dns/src/lib.rs b/crates/net/dns/src/lib.rs index b101c8b3ed4d..d17f8268a214 100644 --- a/crates/net/dns/src/lib.rs +++ b/crates/net/dns/src/lib.rs @@ -391,7 +391,7 @@ pub enum DnsDiscoveryEvent { /// Converts an [Enr] into a [NodeRecord] fn convert_enr_node_record(enr: &Enr) -> Option { - use reth_rlp::Decodable; + use alloy_rlp::Decodable; let node_record = NodeRecord { address: enr.ip4().map(IpAddr::from).or_else(|| enr.ip6().map(IpAddr::from))?, @@ -411,9 +411,9 @@ fn convert_enr_node_record(enr: &Enr) -> Option mod tests { use super::*; use crate::tree::TreeRootEntry; + use alloy_rlp::Encodable; use enr::{EnrBuilder, EnrKey}; use reth_primitives::{Chain, Hardfork, MAINNET}; - use reth_rlp::Encodable; use secp256k1::rand::thread_rng; use std::{future::poll_fn, net::Ipv4Addr}; use tokio_stream::StreamExt; diff --git a/crates/net/downloaders/Cargo.toml b/crates/net/downloaders/Cargo.toml index 281dbfc6c784..fb38e2181925 100644 --- a/crates/net/downloaders/Cargo.toml +++ b/crates/net/downloaders/Cargo.toml @@ -30,7 +30,7 @@ rayon.workspace = true thiserror.workspace = true # optional deps for the test-utils feature -reth-rlp = { workspace = true, optional = true } +alloy-rlp = { workspace = true, optional = true } tempfile = { version = "3.3", optional = true } itertools = { workspace = true, optional = true } @@ -39,12 +39,12 @@ reth-db = { path = "../../storage/db", features = ["test-utils"] } reth-interfaces = { workspace = true, features = ["test-utils"] } reth-tracing = { path = "../../tracing" } +alloy-rlp.workspace = true assert_matches = "1.5.0" tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } -reth-rlp.workspace = true itertools.workspace = true tempfile = "3.3" [features] -test-utils = ["dep:reth-rlp", "dep:tempfile", "dep:itertools"] +test-utils = ["dep:alloy-rlp", "dep:tempfile", "dep:itertools"] diff --git a/crates/net/downloaders/src/test_utils/file_client.rs b/crates/net/downloaders/src/test_utils/file_client.rs index 64aee95cd9bf..871006275074 100644 --- a/crates/net/downloaders/src/test_utils/file_client.rs +++ b/crates/net/downloaders/src/test_utils/file_client.rs @@ -1,4 +1,5 @@ use super::file_codec::BlockFileCodec; +use alloy_rlp::{Decodable, Header as RlpHeader}; use itertools::Either; use reth_interfaces::{ p2p::{ @@ -14,7 +15,6 @@ use reth_primitives::{ Block, BlockBody, BlockHash, BlockHashOrNumber, BlockNumber, Header, HeadersDirection, PeerId, H256, }; -use reth_rlp::{Decodable, Header as RlpHeader}; use std::{ collections::HashMap, iter::zip, @@ -65,7 +65,7 @@ pub enum FileClientError { /// An error occurred when decoding blocks, headers, or rlp headers from the file. #[error(transparent)] - Rlp(#[from] reth_rlp::DecodeError), + Rlp(#[from] alloy_rlp::Error), } impl FileClient { @@ -255,6 +255,7 @@ mod tests { headers::{reverse_headers::ReverseHeadersDownloaderBuilder, test_utils::child_header}, test_utils::{generate_bodies, generate_bodies_file}, }; + use alloy_rlp::Encodable; use assert_matches::assert_matches; use futures::SinkExt; use futures_util::stream::StreamExt; @@ -267,7 +268,6 @@ mod tests { test_utils::TestConsensus, }; use reth_primitives::SealedHeader; - use reth_rlp::Encodable; use std::{ io::{Read, Seek, SeekFrom, Write}, sync::Arc, diff --git a/crates/net/downloaders/src/test_utils/file_codec.rs b/crates/net/downloaders/src/test_utils/file_codec.rs index 98388be4ad76..443877026b23 100644 --- a/crates/net/downloaders/src/test_utils/file_codec.rs +++ b/crates/net/downloaders/src/test_utils/file_codec.rs @@ -1,17 +1,17 @@ //! Codec for reading raw block bodies from a file. use super::FileClientError; +use alloy_rlp::{Decodable, Encodable}; use reth_primitives::{ bytes::{Buf, BytesMut}, Block, }; -use reth_rlp::{Decodable, Encodable}; use tokio_util::codec::{Decoder, Encoder}; /// Codec for reading raw block bodies from a file. /// /// If using with [`FramedRead`](tokio_util::codec::FramedRead), the user should make sure the /// framed reader has capacity for the entire block file. Otherwise, the decoder will return -/// [`InputTooShort`](reth_rlp::DecodeError::InputTooShort), because RLP headers can only be +/// [`InputTooShort`](alloy_rlp::Error::InputTooShort), because RLP headers can only be /// decoded if the internal buffer is large enough to contain the entire block body. /// /// Without ensuring the framed reader has capacity for the entire file, a block body is likely to diff --git a/crates/net/ecies/Cargo.toml b/crates/net/ecies/Cargo.toml index 9a83e64bc7e3..722dec6b5b11 100644 --- a/crates/net/ecies/Cargo.toml +++ b/crates/net/ecies/Cargo.toml @@ -8,10 +8,10 @@ homepage.workspace = true repository.workspace = true [dependencies] -reth-rlp = { workspace = true, features = ["derive", "ethereum-types", "std"] } reth-primitives.workspace = true reth-net-common = { path = "../common" } +alloy-rlp = { workspace = true, features = ["derive", "std"] } futures.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["full"] } diff --git a/crates/net/ecies/src/algorithm.rs b/crates/net/ecies/src/algorithm.rs index 26f530ab820c..baf04157286b 100644 --- a/crates/net/ecies/src/algorithm.rs +++ b/crates/net/ecies/src/algorithm.rs @@ -6,6 +6,7 @@ use crate::{ ECIESError, }; use aes::{cipher::StreamCipher, Aes128, Aes256}; +use alloy_rlp::{Encodable, Rlp, RlpEncodable, RlpMaxEncodedLen}; use byteorder::{BigEndian, ByteOrder, ReadBytesExt}; use ctr::Ctr64BE; use digest::{crypto_common::KeyIvInit, Digest}; @@ -13,9 +14,8 @@ use educe::Educe; use rand::{thread_rng, Rng}; use reth_primitives::{ bytes::{BufMut, Bytes, BytesMut}, - H128, H256, H512 as PeerId, + H128, H256, H512 as PeerId, H512, }; -use reth_rlp::{Encodable, Rlp, RlpEncodable, RlpMaxEncodedLen}; use secp256k1::{ ecdsa::{RecoverableSignature, RecoveryId}, PublicKey, SecretKey, SECP256K1, @@ -264,7 +264,7 @@ impl ECIES { struct S<'a> { sig_bytes: &'a [u8; 65], id: &'a PeerId, - nonce: &'a H256, + nonce: &'a [u8; 32], protocol_version: u8, } @@ -272,7 +272,7 @@ impl ECIES { S { sig_bytes: &sig_bytes, id: &id, - nonce: &self.nonce, + nonce: &self.nonce.0, protocol_version: PROTOCOL_VERSION as u8, } .encode(&mut out); @@ -316,10 +316,10 @@ impl ECIES { &sigdata[..64], RecoveryId::from_i32(sigdata[64] as i32)?, )?; - let remote_id = data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?; + let remote_id = H512(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?); self.remote_id = Some(remote_id); self.remote_public_key = Some(id2pk(remote_id)?); - self.remote_nonce = Some(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?); + self.remote_nonce = Some(H256(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?)); let x = ecdh_x(&self.remote_public_key.unwrap(), &self.secret_key); self.remote_ephemeral_public_key = Some(SECP256K1.recover_ecdsa( @@ -346,13 +346,13 @@ impl ECIES { #[derive(RlpEncodable, RlpMaxEncodedLen)] struct S { id: PeerId, - nonce: H256, + nonce: [u8; 32], protocol_version: u8, } - reth_rlp::encode_fixed_size(&S { + alloy_rlp::encode_fixed_size(&S { id: pk2id(&self.ephemeral_public_key), - nonce: self.nonce, + nonce: self.nonce.0, protocol_version: PROTOCOL_VERSION as u8, }) } @@ -399,7 +399,7 @@ impl ECIES { let mut data = Rlp::new(data)?; self.remote_ephemeral_public_key = Some(id2pk(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAckData)?)?); - self.remote_nonce = Some(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAckData)?); + self.remote_nonce = Some(H256(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAckData)?)); self.ephemeral_shared_secret = Some(ecdh_x(&self.remote_ephemeral_public_key.unwrap(), &self.ephemeral_secret_key)); diff --git a/crates/net/ecies/src/error.rs b/crates/net/ecies/src/error.rs index f4281ffad974..1a2a738c4b05 100644 --- a/crates/net/ecies/src/error.rs +++ b/crates/net/ecies/src/error.rs @@ -63,7 +63,7 @@ pub enum ECIESErrorImpl { Secp256k1(secp256k1::Error), /// Error when decoding RLP data #[error(transparent)] - RLPDecoding(reth_rlp::DecodeError), + RLPDecoding(alloy_rlp::Error), /// Error when converting to integer #[error(transparent)] FromInt(std::num::TryFromIntError), @@ -111,8 +111,8 @@ impl From for ECIESError { } } -impl From for ECIESError { - fn from(source: reth_rlp::DecodeError) -> Self { +impl From for ECIESError { + fn from(source: alloy_rlp::Error) -> Self { ECIESErrorImpl::RLPDecoding(source).into() } } diff --git a/crates/net/eth-wire/Cargo.toml b/crates/net/eth-wire/Cargo.toml index d3042c94feee..701a9e4ba06b 100644 --- a/crates/net/eth-wire/Cargo.toml +++ b/crates/net/eth-wire/Cargo.toml @@ -9,23 +9,17 @@ homepage.workspace = true repository.workspace = true [dependencies] -bytes.workspace = true -thiserror.workspace = true -serde = { workspace = true, optional = true } - # reth reth-codecs = { path = "../../storage/codecs" } reth-primitives.workspace = true reth-ecies = { path = "../ecies" } -reth-rlp = { workspace = true, features = [ - "alloc", - "derive", - "std", - "ethereum-types", - "smol_str", -] } reth-metrics.workspace = true +alloy-rlp = { workspace = true, features = ["derive", "std", "smol_str"] } +bytes.workspace = true +thiserror.workspace = true +serde = { workspace = true, optional = true } + # used for Chain and builders ethers-core = { workspace = true, default-features = false } diff --git a/crates/net/eth-wire/src/capability.rs b/crates/net/eth-wire/src/capability.rs index 6bdfd85bdce3..7e2aa9b50090 100644 --- a/crates/net/eth-wire/src/capability.rs +++ b/crates/net/eth-wire/src/capability.rs @@ -1,9 +1,9 @@ //! All capability related types use crate::{version::ParseVersionError, EthMessage, EthVersion}; +use alloy_rlp::{Decodable, Encodable, RlpDecodable, RlpEncodable}; use reth_codecs::add_arbitrary_tests; use reth_primitives::bytes::{BufMut, Bytes}; -use reth_rlp::{Decodable, DecodeError, Encodable, RlpDecodable, RlpEncodable}; use smol_str::SmolStr; #[cfg(feature = "serde")] @@ -162,7 +162,7 @@ impl Encodable for Capabilities { } impl Decodable for Capabilities { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { let inner = Vec::::decode(buf)?; Ok(Self { diff --git a/crates/net/eth-wire/src/disconnect.rs b/crates/net/eth-wire/src/disconnect.rs index b72d7bf9a2bf..2d21db345c54 100644 --- a/crates/net/eth-wire/src/disconnect.rs +++ b/crates/net/eth-wire/src/disconnect.rs @@ -1,11 +1,11 @@ //! Disconnect +use alloy_rlp::{Decodable, Encodable, Error as RlpError, Header}; use bytes::Bytes; use futures::{Sink, SinkExt}; use reth_codecs::derive_arbitrary; use reth_ecies::stream::ECIESStream; use reth_primitives::bytes::{Buf, BufMut}; -use reth_rlp::{Decodable, DecodeError, Encodable, Header}; use std::fmt::Display; use thiserror::Error; use tokio::io::AsyncWrite; @@ -106,25 +106,29 @@ impl TryFrom for DisconnectReason { } } -/// The [`Encodable`](reth_rlp::Encodable) implementation for [`DisconnectReason`] encodes the +/// The [`Encodable`](alloy_rlp::Encodable) implementation for [`DisconnectReason`] encodes the /// disconnect reason in a single-element RLP list. impl Encodable for DisconnectReason { + #[inline] fn encode(&self, out: &mut dyn BufMut) { - vec![*self as u8].encode(out); + alloy_rlp::encode_list(&[*self as u8], out) } + + #[inline] fn length(&self) -> usize { - vec![*self as u8].length() + alloy_rlp::list_length(&[*self as u8]) } } -/// The [`Decodable`](reth_rlp::Decodable) implementation for [`DisconnectReason`] supports either +/// The [`Decodable`](alloy_rlp::Decodable) implementation for [`DisconnectReason`] supports either /// a disconnect reason encoded a single byte or a RLP list containing the disconnect reason. impl Decodable for DisconnectReason { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { if buf.is_empty() { - return Err(DecodeError::InputTooShort) - } else if buf.len() > 2 { - return Err(DecodeError::Overflow) + return Err(RlpError::InputTooShort) + } + if buf.len() > 2 { + return Err(RlpError::Overflow) } if buf.len() > 1 { @@ -132,7 +136,7 @@ impl Decodable for DisconnectReason { // buf[0] is the first (and only) element of the list. let header = Header::decode(buf)?; if !header.list { - return Err(DecodeError::UnexpectedString) + return Err(RlpError::UnexpectedString) } } @@ -143,7 +147,7 @@ impl Decodable for DisconnectReason { Ok(DisconnectReason::DisconnectRequested) } else { DisconnectReason::try_from(u8::decode(buf)?) - .map_err(|_| DecodeError::Custom("unknown disconnect reason")) + .map_err(|_| RlpError::Custom("unknown disconnect reason")) } } } @@ -190,8 +194,8 @@ where #[cfg(test)] mod tests { use crate::{p2pstream::P2PMessage, DisconnectReason}; + use alloy_rlp::{Decodable, Encodable}; use reth_primitives::hex; - use reth_rlp::{Decodable, Encodable}; fn all_reasons() -> Vec { vec![ diff --git a/crates/net/eth-wire/src/errors/eth.rs b/crates/net/eth-wire/src/errors/eth.rs index d87fed4ebd48..ae7c7c97d871 100644 --- a/crates/net/eth-wire/src/errors/eth.rs +++ b/crates/net/eth-wire/src/errors/eth.rs @@ -50,8 +50,8 @@ impl From for EthStreamError { } } -impl From for EthStreamError { - fn from(err: reth_rlp::DecodeError) -> Self { +impl From for EthStreamError { + fn from(err: alloy_rlp::Error) -> Self { P2PStreamError::from(err).into() } } diff --git a/crates/net/eth-wire/src/errors/p2p.rs b/crates/net/eth-wire/src/errors/p2p.rs index 3d7a2e7f00ca..f323a47c1cd2 100644 --- a/crates/net/eth-wire/src/errors/p2p.rs +++ b/crates/net/eth-wire/src/errors/p2p.rs @@ -12,7 +12,7 @@ pub enum P2PStreamError { #[error(transparent)] Io(#[from] io::Error), #[error(transparent)] - Rlp(#[from] reth_rlp::DecodeError), + Rlp(#[from] alloy_rlp::Error), #[error(transparent)] Snap(#[from] snap::Error), #[error(transparent)] @@ -73,7 +73,7 @@ pub enum P2PHandshakeError { #[error("Disconnected by peer: {0}")] Disconnected(DisconnectReason), #[error("error decoding a message during handshake: {0}")] - DecodeError(#[from] reth_rlp::DecodeError), + DecodeError(#[from] alloy_rlp::Error), } /// An error that can occur when interacting with a pinger. diff --git a/crates/net/eth-wire/src/ethstream.rs b/crates/net/eth-wire/src/ethstream.rs index ae5d60edf3e9..208d8485be8e 100644 --- a/crates/net/eth-wire/src/ethstream.rs +++ b/crates/net/eth-wire/src/ethstream.rs @@ -4,13 +4,13 @@ use crate::{ types::{EthMessage, ProtocolMessage, Status}, CanDisconnect, DisconnectReason, EthVersion, }; +use alloy_rlp::Encodable; use futures::{ready, Sink, SinkExt, StreamExt}; use pin_project::pin_project; use reth_primitives::{ bytes::{Bytes, BytesMut}, ForkFilter, }; -use reth_rlp::Encodable; use std::{ pin::Pin, task::{Context, Poll}, diff --git a/crates/net/eth-wire/src/hello.rs b/crates/net/eth-wire/src/hello.rs index c14759fd40ba..c44fcc48db70 100644 --- a/crates/net/eth-wire/src/hello.rs +++ b/crates/net/eth-wire/src/hello.rs @@ -1,7 +1,7 @@ use crate::{capability::Capability, EthVersion, ProtocolVersion}; +use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_codecs::derive_arbitrary; use reth_primitives::{constants::RETH_CLIENT_VERSION, PeerId}; -use reth_rlp::{RlpDecodable, RlpEncodable}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -107,8 +107,8 @@ impl HelloMessageBuilder { #[cfg(test)] mod tests { + use alloy_rlp::{Decodable, Encodable, EMPTY_STRING_CODE}; use reth_ecies::util::pk2id; - use reth_rlp::{Decodable, Encodable, EMPTY_STRING_CODE}; use secp256k1::{SecretKey, SECP256K1}; use crate::{ diff --git a/crates/net/eth-wire/src/p2pstream.rs b/crates/net/eth-wire/src/p2pstream.rs index bc1e34a48381..4449200c1883 100644 --- a/crates/net/eth-wire/src/p2pstream.rs +++ b/crates/net/eth-wire/src/p2pstream.rs @@ -6,6 +6,7 @@ use crate::{ pinger::{Pinger, PingerEvent}, DisconnectReason, HelloMessage, }; +use alloy_rlp::{length_of_length, Decodable, Encodable, Error as RlpError, EMPTY_LIST_CODE}; use futures::{Sink, SinkExt, StreamExt}; use pin_project::pin_project; use reth_codecs::derive_arbitrary; @@ -14,7 +15,6 @@ use reth_primitives::{ bytes::{Buf, BufMut, Bytes, BytesMut}, hex, }; -use reth_rlp::{Decodable, DecodeError, Encodable, EMPTY_LIST_CODE}; use std::{ collections::{BTreeSet, HashMap, HashSet, VecDeque}, io, @@ -663,7 +663,8 @@ pub enum P2PMessage { } impl P2PMessage { - /// Gets the [`P2PMessageID`] for the given message. + /// Returns the [`P2PMessageID`] for this message. + #[inline] pub fn message_id(&self) -> P2PMessageID { match self { P2PMessage::Hello(_) => P2PMessageID::Hello, @@ -674,82 +675,63 @@ impl P2PMessage { } } -/// The [`Encodable`](reth_rlp::Encodable) implementation for [`P2PMessage::Ping`] and +/// The [`Encodable`](alloy_rlp::Encodable) implementation for [`P2PMessage::Ping`] and /// [`P2PMessage::Pong`] encodes the message as RLP, and prepends a snappy header to the RLP bytes /// for all variants except the [`P2PMessage::Hello`] variant, because the hello message is never /// compressed in the `p2p` subprotocol. impl Encodable for P2PMessage { + #[inline] fn encode(&self, out: &mut dyn BufMut) { - (self.message_id() as u8).encode(out); + self.message_id().encode(out); match self { P2PMessage::Hello(msg) => msg.encode(out), P2PMessage::Disconnect(msg) => msg.encode(out), - P2PMessage::Ping => { - // Ping payload is _always_ snappy encoded - out.put_u8(0x01); - out.put_u8(0x00); - out.put_u8(EMPTY_LIST_CODE); - } - P2PMessage::Pong => { - // Pong payload is _always_ snappy encoded - out.put_u8(0x01); - out.put_u8(0x00); - out.put_u8(EMPTY_LIST_CODE); - } + // Ping/Pong payload is _always_ snappy encoded + P2PMessage::Ping | P2PMessage::Pong => out.put_slice(&[0x01, 0x00, EMPTY_LIST_CODE]), } } + #[inline] fn length(&self) -> usize { - let payload_len = match self { + let payload_length = match self { P2PMessage::Hello(msg) => msg.length(), P2PMessage::Disconnect(msg) => msg.length(), - // id + snappy encoded payload - P2PMessage::Ping => 3, // len([0x01, 0x00, 0xc0]) = 3 - P2PMessage::Pong => 3, // len([0x01, 0x00, 0xc0]) = 3 + P2PMessage::Ping | P2PMessage::Pong => 3, // len([0x01, 0x00, 0xc0]) = 3 }; - payload_len + 1 // (1 for length of p2p message id) + payload_length + length_of_length(payload_length) } } -/// The [`Decodable`](reth_rlp::Decodable) implementation for [`P2PMessage`] assumes that each of +/// The [`Decodable`](alloy_rlp::Decodable) implementation for [`P2PMessage`] assumes that each of /// the message variants are snappy compressed, except for the [`P2PMessage::Hello`] variant since /// the hello message is never compressed in the `p2p` subprotocol. /// The [`Decodable`] implementation for [`P2PMessage::Ping`] and /// [`P2PMessage::Pong`] expects a snappy encoded payload, see [`Encodable`] implementation. impl Decodable for P2PMessage { - fn decode(buf: &mut &[u8]) -> Result { - /// Removes the snappy prefix from the Ping/Pong buffer - fn advance_snappy_ping_pong_payload(buf: &mut &[u8]) -> Result<(), DecodeError> { - if buf.len() < 3 { - return Err(DecodeError::InputTooShort) - } - if buf[..3] != [0x01, 0x00, EMPTY_LIST_CODE] { - return Err(DecodeError::Custom("expected snappy payload")) - } - buf.advance(3); - Ok(()) - } - - let message_id = u8::decode(&mut &buf[..])?; - let id = P2PMessageID::try_from(message_id) - .or(Err(DecodeError::Custom("unknown p2p message id")))?; - buf.advance(1); - match id { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + match P2PMessageID::decode(buf)? { P2PMessageID::Hello => Ok(P2PMessage::Hello(HelloMessage::decode(buf)?)), P2PMessageID::Disconnect => Ok(P2PMessage::Disconnect(DisconnectReason::decode(buf)?)), - P2PMessageID::Ping => { - advance_snappy_ping_pong_payload(buf)?; - Ok(P2PMessage::Ping) - } - P2PMessageID::Pong => { - advance_snappy_ping_pong_payload(buf)?; - Ok(P2PMessage::Pong) + id @ (P2PMessageID::Ping | P2PMessageID::Pong) => { + if buf.len() < 3 { + return Err(RlpError::InputTooShort) + } + if buf[..3] != [0x01, 0x00, EMPTY_LIST_CODE] { + return Err(RlpError::Custom("expected snappy payload")) + } + buf.advance(3); + match id { + P2PMessageID::Ping => Ok(P2PMessage::Ping), + P2PMessageID::Pong => Ok(P2PMessage::Pong), + _ => unreachable!(), + } } } } } /// Message IDs for `p2p` subprotocol messages. +#[repr(u8)] #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum P2PMessageID { /// Message ID for the [`P2PMessage::Hello`] message. @@ -790,6 +772,26 @@ impl TryFrom for P2PMessageID { } } +impl Encodable for P2PMessageID { + #[inline] + fn encode(&self, out: &mut dyn BufMut) { + (*self as u8).encode(out) + } + + #[inline] + fn length(&self) -> usize { + (*self as u8).length() + } +} + +impl Decodable for P2PMessageID { + #[inline] + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + let id = u8::decode(buf)?; + P2PMessageID::try_from(id).map_err(|_| RlpError::Custom("unknown p2p message id")) + } +} + /// RLPx `p2p` protocol version #[derive_arbitrary(rlp)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] @@ -803,22 +805,23 @@ pub enum ProtocolVersion { } impl Encodable for ProtocolVersion { + #[inline] fn encode(&self, out: &mut dyn BufMut) { (*self as u8).encode(out) } + + #[inline] fn length(&self) -> usize { - // the version should be a single byte (*self as u8).length() } } impl Decodable for ProtocolVersion { - fn decode(buf: &mut &[u8]) -> Result { - let version = u8::decode(buf)?; - match version { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + match u8::decode(buf)? { 4 => Ok(ProtocolVersion::V4), 5 => Ok(ProtocolVersion::V5), - _ => Err(DecodeError::Custom("unknown p2p protocol version")), + _ => Err(RlpError::Custom("unknown p2p protocol version")), } } } diff --git a/crates/net/eth-wire/src/types/blocks.rs b/crates/net/eth-wire/src/types/blocks.rs index 808c8f4a4609..b12bbf889a64 100644 --- a/crates/net/eth-wire/src/types/blocks.rs +++ b/crates/net/eth-wire/src/types/blocks.rs @@ -1,8 +1,8 @@ //! Implements the `GetBlockHeaders`, `GetBlockBodies`, `BlockHeaders`, and `BlockBodies` message //! types. +use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; use reth_codecs::derive_arbitrary; use reth_primitives::{BlockBody, BlockHashOrNumber, Header, HeadersDirection, H256}; -use reth_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -53,7 +53,7 @@ impl From> for BlockHeaders { /// A request for a peer to return block bodies for the given block hashes. #[derive_arbitrary(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct GetBlockBodies( /// The block hashes to request bodies for. @@ -93,12 +93,12 @@ mod test { use crate::types::{ message::RequestPair, BlockBodies, BlockHeaders, GetBlockBodies, GetBlockHeaders, }; + use alloy_rlp::{Decodable, Encodable}; use hex_literal::hex; use reth_primitives::{ BlockHashOrNumber, Header, HeadersDirection, Signature, Transaction, TransactionKind, TransactionSigned, TxLegacy, U256, }; - use reth_rlp::{Decodable, Encodable}; use std::str::FromStr; use super::BlockBody; diff --git a/crates/net/eth-wire/src/types/broadcast.rs b/crates/net/eth-wire/src/types/broadcast.rs index c31ce72445fb..32c5baff16be 100644 --- a/crates/net/eth-wire/src/types/broadcast.rs +++ b/crates/net/eth-wire/src/types/broadcast.rs @@ -1,11 +1,11 @@ //! Types for broadcasting new data. use crate::{EthMessage, EthVersion}; +use alloy_rlp::{ + Decodable, Encodable, RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper, +}; use bytes::Bytes; use reth_codecs::derive_arbitrary; use reth_primitives::{Block, TransactionSigned, H256, U128}; -use reth_rlp::{ - Decodable, Encodable, RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper, -}; use std::sync::Arc; #[cfg(feature = "serde")] @@ -37,7 +37,7 @@ impl NewBlockHashes { /// A block hash _and_ a block number. #[derive_arbitrary(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable, Default)] +#[derive(Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct BlockHashNumber { /// The block hash @@ -207,7 +207,7 @@ impl From for NewPooledTransactionHashes { /// This informs peers of transaction hashes for transactions that have appeared on the network, /// but have not been included in a block. #[derive_arbitrary(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct NewPooledTransactionHashes66( /// Transaction hashes for new transactions that have appeared on the network. @@ -236,8 +236,8 @@ pub struct NewPooledTransactionHashes68 { /// the following way: /// * `[type_0: B_1, type_1: B_1, ...]` /// - /// This would make it seem like the [`Encodable`](reth_rlp::Encodable) and - /// [`Decodable`](reth_rlp::Decodable) implementations should directly use a `Vec` for + /// This would make it seem like the [`Encodable`](alloy_rlp::Encodable) and + /// [`Decodable`](alloy_rlp::Decodable) implementations should directly use a `Vec` for /// encoding and decoding, because it looks like this field should be encoded as a _list_ of /// bytes. /// @@ -248,7 +248,7 @@ pub struct NewPooledTransactionHashes68 { /// **not** a RLP list. /// /// Because of this, we do not directly use the `Vec` when encoding and decoding, and - /// instead use the [`Encodable`](reth_rlp::Encodable) and [`Decodable`](reth_rlp::Decodable) + /// instead use the [`Encodable`](alloy_rlp::Encodable) and [`Decodable`](alloy_rlp::Decodable) /// implementations for `&[u8]` instead, which encodes into a RLP string, and expects an RLP /// string when decoding. pub types: Vec, @@ -258,43 +258,35 @@ pub struct NewPooledTransactionHashes68 { pub hashes: Vec, } +#[derive(RlpEncodable)] +#[allow(unused)] +struct EncodableNewPooledTransactionHashes68<'a> { + types: &'a [u8], + sizes: &'a Vec, + hashes: &'a Vec, +} + impl Encodable for NewPooledTransactionHashes68 { fn encode(&self, out: &mut dyn bytes::BufMut) { - #[derive(RlpEncodable)] - struct EncodableNewPooledTransactionHashes68<'a> { - types: &'a [u8], - sizes: &'a Vec, - hashes: &'a Vec, - } - - let encodable = EncodableNewPooledTransactionHashes68 { + EncodableNewPooledTransactionHashes68 { types: &self.types[..], sizes: &self.sizes, hashes: &self.hashes, - }; - - encodable.encode(out); + } + .encode(out); } fn length(&self) -> usize { - #[derive(RlpEncodable)] - struct EncodableNewPooledTransactionHashes68<'a> { - types: &'a [u8], - sizes: &'a Vec, - hashes: &'a Vec, - } - - let encodable = EncodableNewPooledTransactionHashes68 { + EncodableNewPooledTransactionHashes68 { types: &self.types[..], sizes: &self.sizes, hashes: &self.hashes, - }; - - encodable.length() + } + .length() } } impl Decodable for NewPooledTransactionHashes68 { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { #[derive(RlpDecodable)] struct EncodableNewPooledTransactionHashes68 { types: Bytes, @@ -311,9 +303,9 @@ impl Decodable for NewPooledTransactionHashes68 { mod tests { use std::str::FromStr; + use alloy_rlp::{Decodable, Encodable}; use bytes::BytesMut; use hex_literal::hex; - use reth_rlp::{Decodable, Encodable}; use super::*; diff --git a/crates/net/eth-wire/src/types/message.rs b/crates/net/eth-wire/src/types/message.rs index d37f5033bea8..85e6fb188c53 100644 --- a/crates/net/eth-wire/src/types/message.rs +++ b/crates/net/eth-wire/src/types/message.rs @@ -5,8 +5,8 @@ use super::{ NewPooledTransactionHashes68, NodeData, PooledTransactions, Receipts, Status, Transactions, }; use crate::{errors::EthStreamError, EthVersion, SharedTransactions}; +use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; use reth_primitives::bytes::{Buf, BufMut}; -use reth_rlp::{length_of_length, Decodable, Encodable, Header}; use std::{fmt::Debug, sync::Arc}; #[cfg(feature = "serde")] @@ -325,8 +325,8 @@ impl Encodable for EthMessageID { } impl Decodable for EthMessageID { - fn decode(buf: &mut &[u8]) -> Result { - let id = buf.first().ok_or(reth_rlp::DecodeError::InputTooShort)?; + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + let id = buf.first().ok_or(alloy_rlp::Error::InputTooShort)?; let id = match id { 0x00 => EthMessageID::Status, 0x01 => EthMessageID::NewBlockHashes, @@ -343,7 +343,7 @@ impl Decodable for EthMessageID { 0x0e => EthMessageID::NodeData, 0x0f => EthMessageID::GetReceipts, 0x10 => EthMessageID::Receipts, - _ => return Err(reth_rlp::DecodeError::Custom("Invalid message ID")), + _ => return Err(alloy_rlp::Error::Custom("Invalid message ID")), }; buf.advance(1); Ok(id) @@ -393,7 +393,7 @@ impl Encodable for RequestPair where T: Encodable, { - fn encode(&self, out: &mut dyn reth_rlp::BufMut) { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { let header = Header { list: true, payload_length: self.request_id.length() + self.message.length() }; @@ -416,7 +416,7 @@ impl Decodable for RequestPair where T: Decodable, { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { let _header = Header::decode(buf)?; Ok(Self { request_id: u64::decode(buf)?, message: T::decode(buf)? }) } @@ -428,8 +428,8 @@ mod test { errors::EthStreamError, types::message::RequestPair, EthMessage, EthMessageID, GetNodeData, NodeData, ProtocolMessage, }; + use alloy_rlp::{Decodable, Encodable}; use hex_literal::hex; - use reth_rlp::{Decodable, Encodable}; fn encode(value: T) -> Vec { let mut buf = vec![]; diff --git a/crates/net/eth-wire/src/types/receipts.rs b/crates/net/eth-wire/src/types/receipts.rs index f1bb3bc1209f..7c278b7be38b 100644 --- a/crates/net/eth-wire/src/types/receipts.rs +++ b/crates/net/eth-wire/src/types/receipts.rs @@ -1,14 +1,14 @@ //! Implements the `GetReceipts` and `Receipts` message types. +use alloy_rlp::{RlpDecodableWrapper, RlpEncodableWrapper}; use reth_codecs::derive_arbitrary; use reth_primitives::{ReceiptWithBloom, H256}; -use reth_rlp::{RlpDecodableWrapper, RlpEncodableWrapper}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// A request for transaction receipts from the given block hashes. #[derive_arbitrary(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct GetReceipts( /// The block hashes to request receipts for. @@ -37,9 +37,9 @@ mod test { types::{message::RequestPair, GetReceipts}, Receipts, }; + use alloy_rlp::{Decodable, Encodable}; use hex_literal::hex; use reth_primitives::{Log, Receipt, ReceiptWithBloom, TxType}; - use reth_rlp::{Decodable, Encodable}; #[test] fn roundtrip_eip1559() { diff --git a/crates/net/eth-wire/src/types/state.rs b/crates/net/eth-wire/src/types/state.rs index 699e52568c67..bcd4ea529d2a 100644 --- a/crates/net/eth-wire/src/types/state.rs +++ b/crates/net/eth-wire/src/types/state.rs @@ -1,7 +1,7 @@ //! Implements the `GetNodeData` and `NodeData` message types. +use alloy_rlp::{RlpDecodableWrapper, RlpEncodableWrapper}; use reth_codecs::derive_arbitrary; use reth_primitives::{Bytes, H256}; -use reth_rlp::{RlpDecodableWrapper, RlpEncodableWrapper}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; /// This message was removed in `eth/67`, only clients running `eth/66` or earlier will respond to /// this message. #[derive_arbitrary(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct GetNodeData(pub Vec); @@ -29,7 +29,7 @@ mod test { use hex_literal::hex; use crate::{message::RequestPair, GetNodeData, NodeData}; - use reth_rlp::{Decodable, Encodable}; + use alloy_rlp::{Decodable, Encodable}; #[test] // Test vector from: https://eips.ethereum.org/EIPS/eip-2481 diff --git a/crates/net/eth-wire/src/types/status.rs b/crates/net/eth-wire/src/types/status.rs index a29af1894147..05331fcc86ff 100644 --- a/crates/net/eth-wire/src/types/status.rs +++ b/crates/net/eth-wire/src/types/status.rs @@ -1,10 +1,9 @@ use crate::{EthVersion, StatusBuilder}; - +use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_codecs::derive_arbitrary; use reth_primitives::{ hex, Chain, ChainSpec, ForkId, Genesis, Hardfork, Head, H256, MAINNET, U256, }; -use reth_rlp::{RlpDecodable, RlpEncodable}; use std::fmt::{Debug, Display}; #[cfg(feature = "serde")] @@ -149,13 +148,13 @@ impl Default for Status { #[cfg(test)] mod tests { use crate::types::{EthVersion, Status}; + use alloy_rlp::{Decodable, Encodable}; use ethers_core::types::Chain as NamedChain; use hex_literal::hex; use rand::Rng; use reth_primitives::{ Chain, ChainSpec, ForkCondition, ForkHash, ForkId, Genesis, Hardfork, Head, H256, U256, }; - use reth_rlp::{Decodable, Encodable}; use std::str::FromStr; #[test] diff --git a/crates/net/eth-wire/src/types/transactions.rs b/crates/net/eth-wire/src/types/transactions.rs index 35a8a7649127..8f707d69a962 100644 --- a/crates/net/eth-wire/src/types/transactions.rs +++ b/crates/net/eth-wire/src/types/transactions.rs @@ -1,10 +1,10 @@ //! Implements the `GetPooledTransactions` and `PooledTransactions` message types. +use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; use reth_codecs::{add_arbitrary_tests, derive_arbitrary}; use reth_primitives::{ kzg::{self, Blob, Bytes48, KzgProof, KzgSettings}, TransactionSigned, H256, }; -use reth_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -24,7 +24,7 @@ use reth_primitives::{ /// A list of transaction hashes that the peer would like transaction bodies for. #[derive_arbitrary(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpEncodableWrapper, RlpDecodableWrapper)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct GetPooledTransactions( /// The transaction hashes to request transaction bodies for. @@ -185,11 +185,11 @@ fn generate_blob_transaction(blobs: Vec, transaction: TransactionSigned) - #[cfg(test)] mod test { use crate::{message::RequestPair, GetPooledTransactions, PooledTransactions}; + use alloy_rlp::{Decodable, Encodable}; use hex_literal::hex; use reth_primitives::{ hex, Signature, Transaction, TransactionKind, TransactionSigned, TxEip1559, TxLegacy, U256, }; - use reth_rlp::{Decodable, Encodable}; use std::str::FromStr; #[test] diff --git a/crates/net/eth-wire/tests/fuzz_roundtrip.rs b/crates/net/eth-wire/tests/fuzz_roundtrip.rs index 34117e8e1305..ed9467d293ca 100644 --- a/crates/net/eth-wire/tests/fuzz_roundtrip.rs +++ b/crates/net/eth-wire/tests/fuzz_roundtrip.rs @@ -1,10 +1,10 @@ //! Round-trip encoding fuzzing for the `eth-wire` crate. -use reth_rlp::{Decodable, Encodable}; +use alloy_rlp::{Decodable, Encodable}; use serde::Serialize; use std::fmt::Debug; -/// Creates a fuzz test for a type that should be [`Encodable`](reth_rlp::Encodable) and -/// [`Decodable`](reth_rlp::Decodable). +/// Creates a fuzz test for a type that should be [`Encodable`](alloy_rlp::Encodable) and +/// [`Decodable`](alloy_rlp::Decodable). /// /// The test will create a random instance of the type, encode it, and then decode it. fn roundtrip_encoding(thing: T) @@ -48,6 +48,7 @@ macro_rules! fuzz_type_and_name { #[cfg(any(test, feature = "bench"))] pub mod fuzz_rlp { use crate::roundtrip_encoding; + use alloy_rlp::{RlpDecodableWrapper, RlpEncodableWrapper}; use reth_codecs::derive_arbitrary; use reth_eth_wire::{ BlockBodies, BlockHeaders, DisconnectReason, GetBlockBodies, GetBlockHeaders, GetNodeData, @@ -56,7 +57,6 @@ pub mod fuzz_rlp { PooledTransactions, Receipts, Status, Transactions, }; use reth_primitives::{BlockHashOrNumber, TransactionSigned}; - use reth_rlp::{RlpDecodableWrapper, RlpEncodableWrapper}; use serde::{Deserialize, Serialize}; use test_fuzz::test_fuzz; diff --git a/crates/net/eth-wire/tests/new_block.rs b/crates/net/eth-wire/tests/new_block.rs index 9e011bd8d45b..cc22a46973b1 100644 --- a/crates/net/eth-wire/tests/new_block.rs +++ b/crates/net/eth-wire/tests/new_block.rs @@ -1,7 +1,7 @@ //! Decoding tests for [`NewBlock`] +use alloy_rlp::Decodable; use reth_eth_wire::NewBlock; use reth_primitives::hex; -use reth_rlp::Decodable; use std::{fs, path::PathBuf}; #[test] diff --git a/crates/net/eth-wire/tests/new_pooled_transactions.rs b/crates/net/eth-wire/tests/new_pooled_transactions.rs index 9f767c2573bd..0ed63d60294c 100644 --- a/crates/net/eth-wire/tests/new_pooled_transactions.rs +++ b/crates/net/eth-wire/tests/new_pooled_transactions.rs @@ -1,7 +1,7 @@ //! Decoding tests for [`NewPooledTransactions`] +use alloy_rlp::Decodable; use reth_eth_wire::NewPooledTransactionHashes66; use reth_primitives::hex; -use reth_rlp::Decodable; use std::{fs, path::PathBuf}; #[test] diff --git a/crates/net/network/Cargo.toml b/crates/net/network/Cargo.toml index a4008f5caabd..67a2ef270d96 100644 --- a/crates/net/network/Cargo.toml +++ b/crates/net/network/Cargo.toml @@ -26,8 +26,6 @@ reth-discv4 = { path = "../discv4" } reth-dns-discovery = { path = "../dns" } reth-eth-wire = { path = "../eth-wire" } reth-ecies = { path = "../ecies" } -reth-rlp.workspace = true -reth-rlp-derive = { path = "../../rlp/rlp-derive" } reth-tasks.workspace = true reth-transaction-pool.workspace = true reth-provider.workspace = true @@ -47,6 +45,7 @@ humantime-serde = { version = "1.1", optional = true } serde_json = { workspace = true, optional = true } # misc +alloy-rlp = { workspace = true, features = ["derive"] } auto_impl = "1" aquamarine = "0.3.0" tracing.workspace = true diff --git a/crates/net/network/src/transactions.rs b/crates/net/network/src/transactions.rs index 7345893d1e74..b67883dc0d6e 100644 --- a/crates/net/network/src/transactions.rs +++ b/crates/net/network/src/transactions.rs @@ -7,6 +7,7 @@ use crate::{ metrics::{TransactionsManagerMetrics, NETWORK_POOL_TRANSACTIONS_SCOPE}, NetworkHandle, }; +use alloy_rlp::Encodable; use futures::{stream::FuturesUnordered, Future, FutureExt, StreamExt}; use reth_eth_wire::{ EthVersion, GetPooledTransactions, NewPooledTransactionHashes, NewPooledTransactionHashes66, @@ -22,7 +23,6 @@ use reth_primitives::{ FromRecoveredTransaction, IntoRecoveredTransaction, PeerId, TransactionSigned, TxHash, TxType, H256, }; -use reth_rlp::Encodable; use reth_transaction_pool::{ error::PoolResult, PoolTransaction, PropagateKind, PropagatedTransactions, TransactionPool, ValidPoolTransaction, @@ -789,10 +789,10 @@ pub enum NetworkTransactionEvent { mod tests { use super::*; use crate::{test_utils::Testnet, NetworkConfigBuilder, NetworkManager}; + use alloy_rlp::Decodable; use reth_interfaces::sync::{NetworkSyncUpdater, SyncState}; use reth_network_api::NetworkInfo; use reth_provider::test_utils::NoopProvider; - use reth_rlp::Decodable; use reth_transaction_pool::test_utils::{testing_pool, MockTransaction}; use secp256k1::SecretKey; use std::future::poll_fn; diff --git a/crates/payload/basic/Cargo.toml b/crates/payload/basic/Cargo.toml index 874c9842d830..7f1d468b3c3b 100644 --- a/crates/payload/basic/Cargo.toml +++ b/crates/payload/basic/Cargo.toml @@ -13,13 +13,13 @@ description = "A basic payload builder for reth that uses the txpool API to buil reth-primitives.workspace = true reth-revm = { path = "../../revm" } reth-transaction-pool.workspace = true -reth-rlp.workspace = true reth-provider.workspace = true reth-payload-builder.workspace = true reth-tasks.workspace = true reth-metrics.workspace = true ## ethereum +alloy-rlp.workspace = true revm.workspace = true ## async diff --git a/crates/payload/basic/src/lib.rs b/crates/payload/basic/src/lib.rs index dea187a30b62..61d4f4af8b70 100644 --- a/crates/payload/basic/src/lib.rs +++ b/crates/payload/basic/src/lib.rs @@ -14,6 +14,7 @@ //! reth basic payload job generator use crate::metrics::PayloadBuilderMetrics; +use alloy_rlp::Encodable; use futures_core::ready; use futures_util::FutureExt; use reth_payload_builder::{ @@ -38,7 +39,6 @@ use reth_revm::{ }, into_reth_log, }; -use reth_rlp::Encodable; use reth_tasks::TaskSpawner; use reth_transaction_pool::TransactionPool; use revm::{ diff --git a/crates/payload/builder/Cargo.toml b/crates/payload/builder/Cargo.toml index 664fae7039a2..3b98563c66ba 100644 --- a/crates/payload/builder/Cargo.toml +++ b/crates/payload/builder/Cargo.toml @@ -12,12 +12,12 @@ description = "reth payload builder" ## reth reth-primitives.workspace = true reth-rpc-types.workspace = true -reth-rlp.workspace = true reth-interfaces.workspace = true reth-revm-primitives = { path = "../../revm/revm-primitives" } reth-metrics.workspace = true ## ethereum +alloy-rlp.workspace = true revm-primitives.workspace = true ## async diff --git a/crates/payload/builder/src/payload.rs b/crates/payload/builder/src/payload.rs index c930585a457d..494b192d21c5 100644 --- a/crates/payload/builder/src/payload.rs +++ b/crates/payload/builder/src/payload.rs @@ -1,8 +1,8 @@ //! Contains types required for building a payload. +use alloy_rlp::Encodable; use reth_primitives::{Address, ChainSpec, Header, SealedBlock, Withdrawal, H256, U256}; use reth_revm_primitives::config::revm_spec_by_timestamp_after_merge; -use reth_rlp::Encodable; use reth_rpc_types::engine::{ ExecutionPayload, ExecutionPayloadEnvelope, PayloadAttributes, PayloadId, }; diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 69cf6d3e0f6e..e312d56b0451 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -10,16 +10,15 @@ description = "Commonly used types in reth." [dependencies] # reth -reth-rlp = { workspace = true, features = ["std", "derive", "ethereum-types"] } -reth-rlp-derive = { path = "../rlp/rlp-derive" } reth-codecs = { path = "../storage/codecs" } revm-primitives = { workspace = true, features = ["serde"] } # ethereum +alloy-rlp = { workspace = true, features = ["std", "derive", "arrayvec"] } ethers-core = { workspace = true, default-features = false } tiny-keccak = { version = "2.0", features = ["keccak"] } crunchy = { version = "0.2.2", default-features = false, features = ["limit_256"] } -ruint = { version = "1.9.0", features = ["primitive-types", "rlp"] } +ruint = { version = "1.9.0", features = ["primitive-types", "rlp", "alloy-rlp"] } # Bloom fixed-hash = { version = "0.8", default-features = false, features = ["rustc-hex"] } diff --git a/crates/primitives/benches/recover_ecdsa_crit.rs b/crates/primitives/benches/recover_ecdsa_crit.rs index 7706b68a6736..3f4cc20fa65b 100644 --- a/crates/primitives/benches/recover_ecdsa_crit.rs +++ b/crates/primitives/benches/recover_ecdsa_crit.rs @@ -1,8 +1,8 @@ +use alloy_rlp::Decodable; use criterion::{criterion_group, criterion_main, Criterion}; use hex_literal::hex; use pprof::criterion::{Output, PProfProfiler}; use reth_primitives::TransactionSigned; -use reth_rlp::Decodable; /// Benchmarks the recovery of the public key from the ECDSA message using criterion. pub fn criterion_benchmark(c: &mut Criterion) { diff --git a/crates/primitives/benches/trie_root.rs b/crates/primitives/benches/trie_root.rs index fe0bd2f84234..6f76abed4f90 100644 --- a/crates/primitives/benches/trie_root.rs +++ b/crates/primitives/benches/trie_root.rs @@ -53,12 +53,12 @@ criterion_main!(benches); mod implementations { use super::*; + use alloy_rlp::Encodable; use bytes::BytesMut; use reth_primitives::{ proofs::adjust_index_for_rlp, trie::{HashBuilder, Nibbles}, }; - use reth_rlp::Encodable; use std::vec::IntoIter; pub fn trie_hash_ordered_trie_root(receipts: IntoIter) -> H256 { diff --git a/crates/primitives/src/bits.rs b/crates/primitives/src/bits.rs index 2ffd8f3d47ea..c11c2401260a 100644 --- a/crates/primitives/src/bits.rs +++ b/crates/primitives/src/bits.rs @@ -1,10 +1,10 @@ //! Fixed hash types +use alloy_rlp::{RlpDecodableWrapper, RlpEncodableWrapper, RlpMaxEncodedLen}; use bytes::Buf; use derive_more::{AsRef, Deref}; use fixed_hash::construct_fixed_hash; use impl_serde::impl_fixed_hash_serde; use reth_codecs::{impl_hash_compact, Compact}; -use reth_rlp::{RlpDecodableWrapper, RlpEncodableWrapper, RlpMaxEncodedLen}; /// Implements a fixed hash type (eg. H512) with `serde`, `Arbitrary`, `proptest::Arbitrary` and /// `Compact` support. diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index 0c9866ba28ef..c1ed4e75194d 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -1,9 +1,9 @@ use crate::{ Address, BlockHash, BlockNumber, Header, SealedHeader, TransactionSigned, Withdrawal, H256, U64, }; +use alloy_rlp::{Decodable, Encodable, Error, RlpDecodable, RlpEncodable}; use fixed_hash::rustc_hex::FromHexError; use reth_codecs::derive_arbitrary; -use reth_rlp::{Decodable, DecodeError, Encodable, RlpDecodable, RlpEncodable}; use serde::{ de::{MapAccess, Visitor}, ser::SerializeStruct, @@ -308,16 +308,15 @@ impl Encodable for BlockHashOrNumber { /// Allows for RLP decoding of a block hash or block number impl Decodable for BlockHashOrNumber { - fn decode(buf: &mut &[u8]) -> Result { - let header: u8 = *buf.first().ok_or(DecodeError::InputTooShort)?; + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + let header: u8 = *buf.first().ok_or(Error::InputTooShort)?; // if the byte string is exactly 32 bytes, decode it into a Hash // 0xa0 = 0x80 (start of string) + 0x20 (32, length of string) if header == 0xa0 { // strip the first byte, parsing the rest of the string. // If the rest of the string fails to decode into 32 bytes, we'll bubble up the // decoding error. - let hash = H256::decode(buf)?; - Ok(Self::Hash(hash)) + Ok(Self::Hash(H256(Decodable::decode(buf)?))) } else { // a block number when encoded as bytes ranges from 0 to any number of bytes - we're // going to accept numbers which fit in less than 64 bytes. diff --git a/crates/primitives/src/bloom.rs b/crates/primitives/src/bloom.rs index b973cef334c6..afa25cf1fb81 100644 --- a/crates/primitives/src/bloom.rs +++ b/crates/primitives/src/bloom.rs @@ -3,6 +3,7 @@ //! Adapted from #![allow(missing_docs)] use crate::{impl_fixed_hash_type, keccak256, Log}; +use alloy_rlp::{RlpDecodableWrapper, RlpEncodableWrapper, RlpMaxEncodedLen}; use bytes::Buf; use core::{mem, ops}; use crunchy::unroll; @@ -10,7 +11,6 @@ use derive_more::{AsRef, Deref}; use fixed_hash::*; use impl_serde::impl_fixed_hash_serde; use reth_codecs::{impl_hash_compact, Compact}; -use reth_rlp::{RlpDecodableWrapper, RlpEncodableWrapper, RlpMaxEncodedLen}; /// Length of bloom filter used for Ethereum. pub const BLOOM_BITS: u32 = 3; diff --git a/crates/primitives/src/chain/mod.rs b/crates/primitives/src/chain/mod.rs index 69afd1fe03fc..47706ed2a475 100644 --- a/crates/primitives/src/chain/mod.rs +++ b/crates/primitives/src/chain/mod.rs @@ -2,8 +2,8 @@ use crate::{ net::{goerli_nodes, mainnet_nodes, sepolia_nodes}, NodeRecord, U256, U64, }; +use alloy_rlp::{Decodable, Encodable}; use reth_codecs::add_arbitrary_tests; -use reth_rlp::{Decodable, Encodable}; use serde::{Deserialize, Serialize}; use std::{fmt, str::FromStr}; @@ -173,7 +173,7 @@ impl FromStr for Chain { } impl Encodable for Chain { - fn encode(&self, out: &mut dyn reth_rlp::BufMut) { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { match self { Self::Named(chain) => u64::from(*chain).encode(out), Self::Id(id) => id.encode(out), @@ -188,7 +188,7 @@ impl Encodable for Chain { } impl Decodable for Chain { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { Ok(u64::decode(buf)?.into()) } } diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index f82d93052c22..dad99bd0337e 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -1042,9 +1042,9 @@ mod tests { ForkCondition, ForkHash, ForkId, Genesis, Hardfork, Head, DEV, GOERLI, H256, MAINNET, SEPOLIA, U256, }; + use alloy_rlp::Encodable; use bytes::BytesMut; use ethers_core::types as EtherType; - use reth_rlp::Encodable; fn test_fork_ids(spec: &ChainSpec, cases: &[(Head, ForkId)]) { for (block, expected_id) in cases { let computed_id = spec.fork_id(block); diff --git a/crates/primitives/src/forkid.rs b/crates/primitives/src/forkid.rs index a737e8430fc3..1182b1e773e8 100644 --- a/crates/primitives/src/forkid.rs +++ b/crates/primitives/src/forkid.rs @@ -5,9 +5,9 @@ #![deny(missing_docs)] use crate::{BlockNumber, Head, H256}; +use alloy_rlp::*; use crc::*; use reth_codecs::derive_arbitrary; -use reth_rlp::*; use serde::{Deserialize, Serialize}; use std::{ cmp::Ordering, diff --git a/crates/primitives/src/genesis.rs b/crates/primitives/src/genesis.rs index 0dd2e4eaf384..f3c73dddfc6f 100644 --- a/crates/primitives/src/genesis.rs +++ b/crates/primitives/src/genesis.rs @@ -5,7 +5,7 @@ use crate::{ utils::serde_helpers::{deserialize_stringified_u64, deserialize_stringified_u64_opt}, Account, Address, Bytes, H256, KECCAK_EMPTY, U256, }; -use reth_rlp::{encode_fixed_size, length_of_length, Encodable, Header as RlpHeader}; +use alloy_rlp::{encode_fixed_size, length_of_length, Encodable, Header as RlpHeader}; use revm_primitives::B160; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/crates/primitives/src/header.rs b/crates/primitives/src/header.rs index 8aeab18b84f8..add822c90981 100644 --- a/crates/primitives/src/header.rs +++ b/crates/primitives/src/header.rs @@ -8,8 +8,8 @@ use crate::{ }; use bytes::{Buf, BufMut, BytesMut}; +use alloy_rlp::{length_of_length, Decodable, Encodable, EMPTY_LIST_CODE, EMPTY_STRING_CODE}; use reth_codecs::{add_arbitrary_tests, derive_arbitrary, main_codec, Compact}; -use reth_rlp::{length_of_length, Decodable, Encodable, EMPTY_LIST_CODE, EMPTY_STRING_CODE}; use serde::{Deserialize, Serialize}; use std::{ mem, @@ -240,13 +240,13 @@ impl Header { length += self.receipts_root.length(); length += self.logs_bloom.length(); length += self.difficulty.length(); - length += U256::from(self.number).length(); - length += U256::from(self.gas_limit).length(); - length += U256::from(self.gas_used).length(); + length += self.number.length(); + length += self.gas_limit.length(); + length += self.gas_used.length(); length += self.timestamp.length(); length += self.extra_data.length(); length += self.mix_hash.length(); - length += H64::from_low_u64_be(self.nonce).length(); + length += self.nonce.to_be_bytes().length(); if let Some(base_fee) = self.base_fee_per_gas { length += U256::from(base_fee).length(); @@ -287,7 +287,7 @@ impl Header { impl Encodable for Header { fn encode(&self, out: &mut dyn BufMut) { let list_header = - reth_rlp::Header { list: true, payload_length: self.header_payload_length() }; + alloy_rlp::Header { list: true, payload_length: self.header_payload_length() }; list_header.encode(out); self.parent_hash.encode(out); self.ommers_hash.encode(out); @@ -297,18 +297,18 @@ impl Encodable for Header { self.receipts_root.encode(out); self.logs_bloom.encode(out); self.difficulty.encode(out); - U256::from(self.number).encode(out); - U256::from(self.gas_limit).encode(out); - U256::from(self.gas_used).encode(out); + self.number.encode(out); + self.gas_limit.encode(out); + self.gas_used.encode(out); self.timestamp.encode(out); self.extra_data.encode(out); self.mix_hash.encode(out); - H64::from_low_u64_be(self.nonce).encode(out); + self.nonce.to_be_bytes().encode(out); // Encode base fee. Put empty string if base fee is missing, // but withdrawals root is present. - if let Some(ref base_fee) = self.base_fee_per_gas { - U256::from(*base_fee).encode(out); + if let Some(base_fee) = self.base_fee_per_gas { + U256::from(base_fee).encode(out); } else if self.withdrawals_root.is_some() || self.blob_gas_used.is_some() || self.excess_blob_gas.is_some() @@ -345,27 +345,25 @@ impl Encodable for Header { } fn length(&self) -> usize { - let mut length = 0; - length += self.header_payload_length(); - length += length_of_length(length); - length + let length = self.header_payload_length(); + length + length_of_length(length) } } impl Decodable for Header { - fn decode(buf: &mut &[u8]) -> Result { - let rlp_head = reth_rlp::Header::decode(buf)?; + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + let rlp_head = alloy_rlp::Header::decode(buf)?; if !rlp_head.list { - return Err(reth_rlp::DecodeError::UnexpectedString) + return Err(alloy_rlp::Error::UnexpectedString) } let started_len = buf.len(); let mut this = Self { - parent_hash: Decodable::decode(buf)?, - ommers_hash: Decodable::decode(buf)?, - beneficiary: Decodable::decode(buf)?, - state_root: Decodable::decode(buf)?, - transactions_root: Decodable::decode(buf)?, - receipts_root: Decodable::decode(buf)?, + parent_hash: H256(Decodable::decode(buf)?), + ommers_hash: H256(Decodable::decode(buf)?), + beneficiary: H160(Decodable::decode(buf)?), + state_root: H256(Decodable::decode(buf)?), + transactions_root: H256(Decodable::decode(buf)?), + receipts_root: H256(Decodable::decode(buf)?), logs_bloom: Decodable::decode(buf)?, difficulty: Decodable::decode(buf)?, number: U256::decode(buf)?.to::(), @@ -373,8 +371,8 @@ impl Decodable for Header { gas_used: U256::decode(buf)?.to::(), timestamp: Decodable::decode(buf)?, extra_data: Decodable::decode(buf)?, - mix_hash: Decodable::decode(buf)?, - nonce: H64::decode(buf)?.to_low_u64_be(), + mix_hash: H256(Decodable::decode(buf)?), + nonce: u64::from_be_bytes(Decodable::decode(buf)?), base_fee_per_gas: None, withdrawals_root: None, blob_gas_used: None, @@ -382,28 +380,28 @@ impl Decodable for Header { }; if started_len - buf.len() < rlp_head.payload_length { - if buf.first().map(|b| *b == EMPTY_STRING_CODE).unwrap_or_default() { + if buf.first().map_or(false, |b| *b == EMPTY_STRING_CODE) { buf.advance(1) } else { - this.base_fee_per_gas = Some(U256::decode(buf)?.to::()); + this.base_fee_per_gas = Some(u64::decode(buf)?); } } // Withdrawals root for post-shanghai headers if started_len - buf.len() < rlp_head.payload_length { - if buf.first().map(|b| *b == EMPTY_STRING_CODE).unwrap_or_default() { + if buf.first().map_or(false, |b| *b == EMPTY_STRING_CODE) { buf.advance(1) } else { - this.withdrawals_root = Some(Decodable::decode(buf)?); + this.withdrawals_root = Some(H256(Decodable::decode(buf)?)); } } // Blob gas used and excess blob gas for post-cancun headers if started_len - buf.len() < rlp_head.payload_length { - if buf.first().map(|b| *b == EMPTY_LIST_CODE).unwrap_or_default() { + if buf.first().map_or(false, |b| *b == EMPTY_LIST_CODE) { buf.advance(1) } else { - this.blob_gas_used = Some(U256::decode(buf)?.to::()); + this.blob_gas_used = Some(u64::decode(buf)?); } } @@ -415,12 +413,12 @@ impl Decodable for Header { // post-London, so this is technically not valid. However, a tool like proptest would // generate a block like this. if started_len - buf.len() < rlp_head.payload_length { - this.excess_blob_gas = Some(U256::decode(buf)?.to::()); + this.excess_blob_gas = Some(u64::decode(buf)?); } let consumed = started_len - buf.len(); if consumed != rlp_head.payload_length { - return Err(reth_rlp::DecodeError::ListLengthMismatch { + return Err(alloy_rlp::Error::ListLengthMismatch { expected: rlp_head.payload_length, got: consumed, }) @@ -500,7 +498,7 @@ impl Encodable for SealedHeader { } impl Decodable for SealedHeader { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { let b = &mut &**buf; let started_len = buf.len(); @@ -595,7 +593,7 @@ impl Encodable for HeadersDirection { } impl Decodable for HeadersDirection { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { let value: bool = Decodable::decode(buf)?; Ok(value.into()) } diff --git a/crates/primitives/src/hex_bytes.rs b/crates/primitives/src/hex_bytes.rs index 0e2db39e5545..51d18607cefe 100644 --- a/crates/primitives/src/hex_bytes.rs +++ b/crates/primitives/src/hex_bytes.rs @@ -1,7 +1,7 @@ use crate::serde_helper::hex_bytes; +use alloy_rlp::{Decodable, Encodable}; use bytes::Buf; use reth_codecs::Compact; -use reth_rlp::{Decodable, DecodeError, Encodable}; use serde::{Deserialize, Serialize}; use std::{ borrow::Borrow, @@ -160,7 +160,7 @@ impl Encodable for Bytes { } impl Decodable for Bytes { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { Ok(Self(bytes::Bytes::decode(buf)?)) } } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 02946310f13a..ff90d9b0c2c5 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -19,6 +19,7 @@ //! //! - `arbitrary`: Adds `proptest` and `arbitrary` support for primitive types. //! - `test-utils`: Export utilities for testing + pub mod abi; mod account; pub mod basefee; diff --git a/crates/primitives/src/log.rs b/crates/primitives/src/log.rs index 3b72967b686b..41e71cd06a1e 100644 --- a/crates/primitives/src/log.rs +++ b/crates/primitives/src/log.rs @@ -1,10 +1,10 @@ use crate::{Address, Bytes, H256}; +use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_codecs::{main_codec, Compact}; -use reth_rlp::{RlpDecodable, RlpEncodable}; /// Ethereum Log #[main_codec(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, RlpDecodable, RlpEncodable, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq, RlpEncodable, RlpDecodable)] pub struct Log { /// Contract that emitted this log. pub address: Address, diff --git a/crates/primitives/src/net.rs b/crates/primitives/src/net.rs index 327544713537..770036586fd8 100644 --- a/crates/primitives/src/net.rs +++ b/crates/primitives/src/net.rs @@ -1,6 +1,5 @@ use crate::PeerId; -use reth_rlp::RlpDecodable; -use reth_rlp_derive::RlpEncodable; +use alloy_rlp::{RlpDecodable, RlpEncodable}; use secp256k1::{SecretKey, SECP256K1}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use std::{ @@ -221,9 +220,9 @@ impl FromStr for NodeRecord { #[cfg(test)] mod tests { use super::*; + use alloy_rlp::{Decodable, Encodable}; use bytes::BytesMut; use rand::{thread_rng, Rng, RngCore}; - use reth_rlp::{Decodable, Encodable}; #[test] fn test_mapped_ipv6() { diff --git a/crates/primitives/src/proofs.rs b/crates/primitives/src/proofs.rs index 95fd279d12b5..3ff5a568d527 100644 --- a/crates/primitives/src/proofs.rs +++ b/crates/primitives/src/proofs.rs @@ -4,11 +4,11 @@ use crate::{ Address, Bytes, GenesisAccount, Header, Log, ReceiptWithBloom, ReceiptWithBloomRef, TransactionSigned, Withdrawal, H256, }; +use alloy_rlp::Encodable; use bytes::{BufMut, BytesMut}; use hash_db::Hasher; use hex_literal::hex; use plain_hasher::PlainHasher; -use reth_rlp::Encodable; use std::collections::HashMap; use triehash::sec_trie_root; @@ -112,7 +112,7 @@ where pub fn calculate_log_root(logs: &[Log]) -> H256 { //https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/cmd/evm/internal/t8ntool/execution.go#L255 let mut logs_rlp = Vec::new(); - reth_rlp::encode_list(logs, &mut logs_rlp); + alloy_rlp::encode_list(logs, &mut logs_rlp); keccak256(logs_rlp) } @@ -120,7 +120,7 @@ pub fn calculate_log_root(logs: &[Log]) -> H256 { pub fn calculate_ommers_root(ommers: &[Header]) -> H256 { // RLP Encode let mut ommers_rlp = Vec::new(); - reth_rlp::encode_list(ommers, &mut ommers_rlp); + alloy_rlp::encode_list(ommers, &mut ommers_rlp); keccak256(ommers_rlp) } @@ -147,7 +147,7 @@ mod tests { Address, Block, Bloom, GenesisAccount, Log, Receipt, ReceiptWithBloom, TxType, H160, H256, U256, }; - use reth_rlp::Decodable; + use alloy_rlp::Decodable; use super::{calculate_withdrawals_root, EMPTY_ROOT}; diff --git a/crates/primitives/src/receipt.rs b/crates/primitives/src/receipt.rs index 57cbdcc6d0d5..a1036dd6eae7 100644 --- a/crates/primitives/src/receipt.rs +++ b/crates/primitives/src/receipt.rs @@ -1,11 +1,13 @@ +#![allow(non_snake_case)] + use crate::{ bloom::logs_bloom, compression::{RECEIPT_COMPRESSOR, RECEIPT_DECOMPRESSOR}, Bloom, Log, TxType, }; +use alloy_rlp::{length_of_length, Decodable, Encodable}; use bytes::{Buf, BufMut, BytesMut}; use reth_codecs::{main_codec, Compact, CompactZstd}; -use reth_rlp::{length_of_length, Decodable, Encodable}; use std::cmp::Ordering; /// Receipt containing result of transaction execution. @@ -90,23 +92,23 @@ impl ReceiptWithBloom { } /// Decodes the receipt payload - fn decode_receipt(buf: &mut &[u8], tx_type: TxType) -> Result { + fn decode_receipt(buf: &mut &[u8], tx_type: TxType) -> alloy_rlp::Result { let b = &mut &**buf; - let rlp_head = reth_rlp::Header::decode(b)?; + let rlp_head = alloy_rlp::Header::decode(b)?; if !rlp_head.list { - return Err(reth_rlp::DecodeError::UnexpectedString) + return Err(alloy_rlp::Error::UnexpectedString) } let started_len = b.len(); - let success = reth_rlp::Decodable::decode(b)?; - let cumulative_gas_used = reth_rlp::Decodable::decode(b)?; + let success = alloy_rlp::Decodable::decode(b)?; + let cumulative_gas_used = alloy_rlp::Decodable::decode(b)?; let bloom = Decodable::decode(b)?; - let logs = reth_rlp::Decodable::decode(b)?; + let logs = alloy_rlp::Decodable::decode(b)?; let this = Self { receipt: Receipt { tx_type, success, cumulative_gas_used, logs }, bloom }; let consumed = started_len - b.len(); if consumed != rlp_head.payload_length { - return Err(reth_rlp::DecodeError::ListLengthMismatch { + return Err(alloy_rlp::Error::ListLengthMismatch { expected: rlp_head.payload_length, got: consumed, }) @@ -126,19 +128,19 @@ impl Encodable for ReceiptWithBloom { } impl Decodable for ReceiptWithBloom { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { // a receipt is either encoded as a string (non legacy) or a list (legacy). // We should not consume the buffer if we are decoding a legacy receipt, so let's // check if the first byte is between 0x80 and 0xbf. let rlp_type = *buf .first() - .ok_or(reth_rlp::DecodeError::Custom("cannot decode a receipt from empty bytes"))?; + .ok_or(alloy_rlp::Error::Custom("cannot decode a receipt from empty bytes"))?; - match rlp_type.cmp(&reth_rlp::EMPTY_LIST_CODE) { + match rlp_type.cmp(&alloy_rlp::EMPTY_LIST_CODE) { Ordering::Less => { // strip out the string header - let _header = reth_rlp::Header::decode(buf)?; - let receipt_type = *buf.first().ok_or(reth_rlp::DecodeError::Custom( + let _header = alloy_rlp::Header::decode(buf)?; + let receipt_type = *buf.first().ok_or(alloy_rlp::Error::Custom( "typed receipt cannot be decoded from an empty slice", ))?; if receipt_type == 0x01 { @@ -151,11 +153,11 @@ impl Decodable for ReceiptWithBloom { buf.advance(1); Self::decode_receipt(buf, TxType::EIP4844) } else { - Err(reth_rlp::DecodeError::Custom("invalid receipt type")) + Err(alloy_rlp::Error::Custom("invalid receipt type")) } } Ordering::Equal => { - Err(reth_rlp::DecodeError::Custom("an empty list is not a valid receipt encoding")) + Err(alloy_rlp::Error::Custom("an empty list is not a valid receipt encoding")) } Ordering::Greater => Self::decode_receipt(buf, TxType::Legacy), } @@ -211,8 +213,8 @@ struct ReceiptWithBloomEncoder<'a> { impl<'a> ReceiptWithBloomEncoder<'a> { /// Returns the rlp header for the receipt payload. - fn receipt_rlp_header(&self) -> reth_rlp::Header { - let mut rlp_head = reth_rlp::Header { list: true, payload_length: 0 }; + fn receipt_rlp_header(&self) -> alloy_rlp::Header { + let mut rlp_head = alloy_rlp::Header { list: true, payload_length: 0 }; rlp_head.payload_length += self.receipt.success.length(); rlp_head.payload_length += self.receipt.cumulative_gas_used.length(); @@ -243,7 +245,7 @@ impl<'a> ReceiptWithBloomEncoder<'a> { if with_header { let payload_length = payload.len() + 1; - let header = reth_rlp::Header { list: false, payload_length }; + let header = alloy_rlp::Header { list: false, payload_length }; header.encode(out); } @@ -290,8 +292,8 @@ impl<'a> Encodable for ReceiptWithBloomEncoder<'a> { mod tests { use super::*; use crate::{hex_literal::hex, Address, H256}; + use alloy_rlp::{Decodable, Encodable}; use ethers_core::types::Bytes; - use reth_rlp::{Decodable, Encodable}; use std::str::FromStr; #[test] diff --git a/crates/primitives/src/transaction/access_list.rs b/crates/primitives/src/transaction/access_list.rs index a86b33b69eb8..8897c7e450b1 100644 --- a/crates/primitives/src/transaction/access_list.rs +++ b/crates/primitives/src/transaction/access_list.rs @@ -1,15 +1,14 @@ -use std::mem; - use crate::{Address, H256}; +use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; use reth_codecs::{main_codec, Compact}; -use reth_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; use revm_primitives::U256; use serde::{Deserialize, Serialize}; +use std::mem; /// A list of addresses and storage keys that the transaction plans to access. /// Accesses outside the list are possible, but become more expensive. #[main_codec(rlp)] -#[derive(Clone, Debug, PartialEq, Eq, Hash, Default, RlpDecodable, RlpEncodable)] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, RlpEncodable, RlpDecodable)] #[serde(rename_all = "camelCase")] pub struct AccessListItem { /// Account addresses that would be loaded at the start of execution diff --git a/crates/primitives/src/transaction/eip2930.rs b/crates/primitives/src/transaction/eip2930.rs index ecd6ecb7ec20..bc9c095a5736 100644 --- a/crates/primitives/src/transaction/eip2930.rs +++ b/crates/primitives/src/transaction/eip2930.rs @@ -73,8 +73,8 @@ mod tests { transaction::{signature::Signature, TransactionKind}, Address, Bytes, Transaction, TransactionSigned, U256, }; + use alloy_rlp::{Decodable, Encodable}; use bytes::BytesMut; - use reth_rlp::{Decodable, Encodable}; #[test] fn test_decode_create() { diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index a2d64517fcb7..2b615dd2b563 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -1,25 +1,26 @@ use crate::{ compression::{TRANSACTION_COMPRESSOR, TRANSACTION_DECOMPRESSOR}, - keccak256, Address, Bytes, TxHash, H256, + keccak256, Address, Bytes, TxHash, H160, H256, +}; +use alloy_rlp::{ + length_of_length, Decodable, Encodable, Error as RlpError, Header, EMPTY_LIST_CODE, + EMPTY_STRING_CODE, }; -pub use access_list::{AccessList, AccessListItem, AccessListWithGasUsed}; use bytes::{Buf, BytesMut}; use derive_more::{AsRef, Deref}; -pub use error::InvalidTransactionError; -pub use meta::TransactionMeta; use reth_codecs::{add_arbitrary_tests, derive_arbitrary, Compact}; -use reth_rlp::{ - length_of_length, Decodable, DecodeError, Encodable, Header, EMPTY_LIST_CODE, EMPTY_STRING_CODE, -}; use serde::{Deserialize, Serialize}; -pub use signature::Signature; use std::mem; -pub use tx_type::{TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, LEGACY_TX_TYPE_ID}; +pub use access_list::{AccessList, AccessListItem, AccessListWithGasUsed}; pub use eip1559::TxEip1559; pub use eip2930::TxEip2930; pub use eip4844::TxEip4844; +pub use error::InvalidTransactionError; pub use legacy::TxLegacy; +pub use meta::TransactionMeta; +pub use signature::Signature; +pub use tx_type::{TxType, EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, LEGACY_TX_TYPE_ID}; mod access_list; mod eip1559; @@ -730,7 +731,7 @@ impl Compact for TransactionKind { } impl Encodable for TransactionKind { - fn encode(&self, out: &mut dyn reth_rlp::BufMut) { + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { match self { TransactionKind::Call(to) => to.encode(out), TransactionKind::Create => out.put_u8(EMPTY_STRING_CODE), @@ -745,17 +746,16 @@ impl Encodable for TransactionKind { } impl Decodable for TransactionKind { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> Result { if let Some(&first) = buf.first() { if first == EMPTY_STRING_CODE { buf.advance(1); Ok(TransactionKind::Create) } else { - let addr =
::decode(buf)?; - Ok(TransactionKind::Call(addr)) + Ok(TransactionKind::Call(H160(Decodable::decode(buf)?))) } } else { - Err(DecodeError::InputTooShort) + Err(RlpError::InputTooShort) } } } @@ -1023,7 +1023,7 @@ impl TransactionSigned { /// Decodes legacy transaction from the data buffer. /// /// This expects `rlp(legacy_tx)` - fn decode_rlp_legacy_transaction(data: &mut &[u8]) -> Result { + fn decode_rlp_legacy_transaction(data: &mut &[u8]) -> Result { // keep this around, so we can use it to calculate the hash let original_encoding = *data; @@ -1052,18 +1052,16 @@ impl TransactionSigned { /// Decodes en enveloped EIP-2718 typed transaction. /// /// CAUTION: this expects that `data` is `[id, rlp(tx)]` - fn decode_enveloped_typed_transaction( - data: &mut &[u8], - ) -> Result { + fn decode_enveloped_typed_transaction(data: &mut &[u8]) -> Result { // keep this around so we can use it to calculate the hash let original_encoding = *data; - let tx_type = *data.first().ok_or(DecodeError::InputTooShort)?; + let tx_type = *data.first().ok_or(RlpError::InputTooShort)?; data.advance(1); // decode the list header for the rest of the transaction let header = Header::decode(data)?; if !header.list { - return Err(DecodeError::Custom("typed tx fields must be encoded as a list")) + return Err(RlpError::Custom("typed tx fields must be encoded as a list")) } // length of tx encoding = tx type byte (size = 1) + length of header + payload length @@ -1105,7 +1103,7 @@ impl TransactionSigned { max_fee_per_blob_gas: Decodable::decode(data)?, blob_versioned_hashes: Decodable::decode(data)?, }), - _ => return Err(DecodeError::Custom("unsupported typed transaction type")), + _ => return Err(RlpError::Custom("unsupported typed transaction type")), }; let signature = Signature::decode(data)?; @@ -1121,11 +1119,11 @@ impl TransactionSigned { /// For legacy transactions, the format is encoded as: `rlp(tx)` /// For EIP-2718 typed transaction, the format is encoded as the type of the transaction /// followed by the rlp of the transaction: `type` + `rlp(tx)` - pub fn decode_enveloped(tx: Bytes) -> Result { + pub fn decode_enveloped(tx: Bytes) -> Result { let mut data = tx.as_ref(); if data.is_empty() { - return Err(DecodeError::InputTooShort) + return Err(RlpError::InputTooShort) } // Check if the tx is a list @@ -1159,7 +1157,7 @@ impl Encodable for TransactionSigned { /// /// CAUTION: this expects that the given buf contains rlp impl Decodable for TransactionSigned { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> Result { // decode header let mut original_encoding = *buf; let header = Header::decode(buf)?; @@ -1268,11 +1266,11 @@ impl Encodable for TransactionSignedEcRecovered { } impl Decodable for TransactionSignedEcRecovered { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> Result { let signed_transaction = TransactionSigned::decode(buf)?; let signer = signed_transaction .recover_signer() - .ok_or(DecodeError::Custom("Unable to recover decoded transaction signer."))?; + .ok_or(RlpError::Custom("Unable to recover decoded transaction signer."))?; Ok(TransactionSignedEcRecovered { signer, signed_transaction }) } } @@ -1316,16 +1314,16 @@ mod tests { transaction::{signature::Signature, TransactionKind, TxEip1559, TxLegacy}, Address, Bytes, Transaction, TransactionSigned, TransactionSignedEcRecovered, H256, U256, }; + use alloy_rlp::{Decodable, Encodable}; use bytes::BytesMut; use ethers_core::utils::hex; - use reth_rlp::{Decodable, DecodeError, Encodable}; use std::str::FromStr; #[test] fn test_decode_empty_typed_tx() { let input = [0x80u8]; - let res = TransactionSigned::decode(&mut &input[..]).unwrap_err(); - assert_eq!(DecodeError::InputTooShort, res); + let res = TransactionSigned::decode(&mut &input[..]); + assert_eq!(res.unwrap_err(), alloy_rlp::Error::InputTooShort); } #[test] diff --git a/crates/primitives/src/transaction/signature.rs b/crates/primitives/src/transaction/signature.rs index 6977d8c26182..b8f947a2dae3 100644 --- a/crates/primitives/src/transaction/signature.rs +++ b/crates/primitives/src/transaction/signature.rs @@ -1,7 +1,7 @@ use crate::{transaction::util::secp256k1, Address, H256, U256}; +use alloy_rlp::{Decodable, Encodable, Error as RlpError}; use bytes::Buf; use reth_codecs::{derive_arbitrary, Compact}; -use reth_rlp::{Decodable, DecodeError, Encodable}; use serde::{Deserialize, Serialize}; /// r, s: Values corresponding to the signature of the @@ -50,7 +50,7 @@ impl Signature { /// Encodes the `v` value using the legacy scheme with EIP-155 support depends on chain_id. pub(crate) fn encode_with_eip155_chain_id( &self, - out: &mut dyn reth_rlp::BufMut, + out: &mut dyn alloy_rlp::BufMut, chain_id: Option, ) { self.v(chain_id).encode(out); @@ -73,7 +73,7 @@ impl Signature { /// This will return a chain ID if the `v` value is [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) compatible. pub(crate) fn decode_with_eip155_chain_id( buf: &mut &[u8], - ) -> Result<(Self, Option), DecodeError> { + ) -> alloy_rlp::Result<(Self, Option)> { let v = u64::decode(buf)?; let r = Decodable::decode(buf)?; let s = Decodable::decode(buf)?; @@ -85,7 +85,7 @@ impl Signature { } else { // non-EIP-155 legacy scheme, v = 27 for even y-parity, v = 28 for odd y-parity if v != 27 && v != 28 { - return Err(DecodeError::Custom("invalid Ethereum signature (V is not 27 or 28)")) + return Err(RlpError::Custom("invalid Ethereum signature (V is not 27 or 28)")) } let odd_y_parity = v == 28; Ok((Signature { r, s, odd_y_parity }, None)) @@ -98,14 +98,14 @@ impl Signature { } /// Encode the `odd_y_parity`, `r`, `s` values without a RLP header. - pub(crate) fn encode(&self, out: &mut dyn reth_rlp::BufMut) { + pub(crate) fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { self.odd_y_parity.encode(out); self.r.encode(out); self.s.encode(out); } /// Decodes the `odd_y_parity`, `r`, `s` values without a RLP header. - pub(crate) fn decode(buf: &mut &[u8]) -> Result { + pub(crate) fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { Ok(Signature { odd_y_parity: Decodable::decode(buf)?, r: Decodable::decode(buf)?, diff --git a/crates/primitives/src/trie/hash_builder/mod.rs b/crates/primitives/src/trie/hash_builder/mod.rs index 90c9210e0d4f..2dc8477d7af9 100644 --- a/crates/primitives/src/trie/hash_builder/mod.rs +++ b/crates/primitives/src/trie/hash_builder/mod.rs @@ -439,7 +439,7 @@ mod tests { K: AsRef<[u8]> + Ord, { let hashed = iter - .map(|(k, v)| (keccak256(k.as_ref()), reth_rlp::encode_fixed_size(v).to_vec())) + .map(|(k, v)| (keccak256(k.as_ref()), alloy_rlp::encode_fixed_size(v).to_vec())) // Collect into a btree map to sort the data .collect::>(); @@ -590,7 +590,8 @@ mod tests { // Skip the 0th element given in this example they have a common prefix and will // collapse to a Branch node. use crate::bytes::BytesMut; - use reth_rlp::Encodable; + use alloy_rlp::Encodable; + let leaf1 = LeafNode::new(&Nibbles::unpack(&raw_input[0].0[1..]), input[0].1); let leaf2 = LeafNode::new(&Nibbles::unpack(&raw_input[1].0[1..]), input[1].1); let mut branch: [&dyn Encodable; 17] = [b""; 17]; @@ -599,7 +600,7 @@ mod tests { branch[4] = &leaf1; branch[7] = &leaf2; let mut branch_node_rlp = BytesMut::new(); - reth_rlp::encode_list::(&branch, &mut branch_node_rlp); + alloy_rlp::encode_list::<_, dyn Encodable>(&branch, &mut branch_node_rlp); let branch_node_hash = keccak256(branch_node_rlp); let mut hb2 = HashBuilder::default(); diff --git a/crates/primitives/src/trie/nibbles.rs b/crates/primitives/src/trie/nibbles.rs index 3bbf74a8b762..9a9e7bf3c112 100644 --- a/crates/primitives/src/trie/nibbles.rs +++ b/crates/primitives/src/trie/nibbles.rs @@ -1,7 +1,7 @@ use crate::Bytes; +use alloy_rlp::RlpEncodableWrapper; use derive_more::{Deref, DerefMut, From, Index}; use reth_codecs::{main_codec, Compact}; -use reth_rlp::RlpEncodableWrapper; use serde::{Deserialize, Serialize}; /// The nibbles are the keys for the AccountsTrie and the subkeys for the StorageTrie. diff --git a/crates/primitives/src/trie/nodes/branch.rs b/crates/primitives/src/trie/nodes/branch.rs index 36ee35eb98fd..fe26b83ad795 100644 --- a/crates/primitives/src/trie/nodes/branch.rs +++ b/crates/primitives/src/trie/nodes/branch.rs @@ -1,8 +1,8 @@ use super::{super::TrieMask, rlp_node, CHILD_INDEX_RANGE}; use crate::H256; +use alloy_rlp::{BufMut, EMPTY_STRING_CODE}; use bytes::Buf; use reth_codecs::Compact; -use reth_rlp::{BufMut, EMPTY_STRING_CODE}; use serde::{Deserialize, Serialize}; /// A Branch node is only a pointer to the stack of nodes and is used to @@ -47,7 +47,7 @@ impl<'a> BranchNode<'a> { // Create the RLP header from the mask elements present. let mut i = first_child_idx; let header = CHILD_INDEX_RANGE.fold( - reth_rlp::Header { list: true, payload_length: 1 }, + alloy_rlp::Header { list: true, payload_length: 1 }, |mut header, digit| { if state_mask.is_bit_set(digit) { header.payload_length += self.stack[i].len(); diff --git a/crates/primitives/src/trie/nodes/extension.rs b/crates/primitives/src/trie/nodes/extension.rs index d124084bdea0..2c57b0b2406b 100644 --- a/crates/primitives/src/trie/nodes/extension.rs +++ b/crates/primitives/src/trie/nodes/extension.rs @@ -1,5 +1,5 @@ use super::{super::Nibbles, rlp_node}; -use reth_rlp::{BufMut, Encodable}; +use alloy_rlp::{BufMut, Encodable}; /// An intermediate node that exists solely to compress the trie's paths. It contains a path segment /// (a shared prefix of keys) and a single child pointer. Essentially, an extension node can be @@ -30,7 +30,7 @@ impl<'a> ExtensionNode<'a> { impl Encodable for ExtensionNode<'_> { fn encode(&self, out: &mut dyn BufMut) { - let h = reth_rlp::Header { + let h = alloy_rlp::Header { list: true, payload_length: self.prefix.as_slice().length() + self.node.len(), }; diff --git a/crates/primitives/src/trie/nodes/leaf.rs b/crates/primitives/src/trie/nodes/leaf.rs index 5ccbcfb0c3bb..e118df7e5111 100644 --- a/crates/primitives/src/trie/nodes/leaf.rs +++ b/crates/primitives/src/trie/nodes/leaf.rs @@ -1,5 +1,5 @@ use super::{super::Nibbles, rlp_node}; -use reth_rlp::{BufMut, Encodable}; +use alloy_rlp::{BufMut, Encodable}; /// A leaf node represents the endpoint or terminal node in the trie. In other words, a leaf node is /// where actual values are stored. @@ -33,7 +33,7 @@ impl<'a> LeafNode<'a> { // Handroll because `key` must be encoded as a slice impl Encodable for LeafNode<'_> { fn encode(&self, out: &mut dyn BufMut) { - #[derive(reth_rlp::RlpEncodable)] + #[derive(alloy_rlp::RlpEncodable)] struct S<'a> { encoded_path: &'a [u8], value: &'a [u8], diff --git a/crates/primitives/src/trie/nodes/mod.rs b/crates/primitives/src/trie/nodes/mod.rs index df38b58faadc..2be366779fb4 100644 --- a/crates/primitives/src/trie/nodes/mod.rs +++ b/crates/primitives/src/trie/nodes/mod.rs @@ -1,5 +1,5 @@ use crate::{keccak256, H256}; -use reth_rlp::EMPTY_STRING_CODE; +use alloy_rlp::EMPTY_STRING_CODE; use std::ops::Range; mod branch; diff --git a/crates/primitives/src/withdrawal.rs b/crates/primitives/src/withdrawal.rs index 098110803c47..161b4b881918 100644 --- a/crates/primitives/src/withdrawal.rs +++ b/crates/primitives/src/withdrawal.rs @@ -1,8 +1,7 @@ -use std::mem; - use crate::{constants::GWEI_TO_WEI, serde_helper::u64_hex, Address, U256}; +use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_codecs::{main_codec, Compact}; -use reth_rlp::{RlpDecodable, RlpEncodable}; +use std::mem; /// Withdrawal represents a validator withdrawal from the consensus layer. #[main_codec] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 037a717d41af..bcf4df1e804a 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -24,5 +24,5 @@ revm.workspace = true tracing.workspace = true [dev-dependencies] -reth-rlp.workspace = true +alloy-rlp.workspace = true once_cell = "1.17.0" diff --git a/crates/revm/src/executor.rs b/crates/revm/src/executor.rs index 5ce714521fba..4ff3bcb99d29 100644 --- a/crates/revm/src/executor.rs +++ b/crates/revm/src/executor.rs @@ -646,6 +646,7 @@ pub fn insert_post_block_withdrawals_balance_increments( mod tests { use super::*; use crate::database::State; + use alloy_rlp::Decodable; use once_cell::sync::Lazy; use reth_consensus_common::calc; use reth_primitives::{ @@ -656,7 +657,6 @@ mod tests { post_state::{AccountChanges, Storage, StorageTransition, StorageWipe}, AccountReader, BlockHashReader, StateProvider, StateRootProvider, }; - use reth_rlp::Decodable; use std::{collections::HashMap, str::FromStr}; static DEFAULT_REVM_ACCOUNT: Lazy = Lazy::new(|| RevmAccount { diff --git a/crates/rlp/Cargo.toml b/crates/rlp/Cargo.toml deleted file mode 100644 index 98c25c7e31b6..000000000000 --- a/crates/rlp/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "reth-rlp" -version.workspace = true -edition.workspace = true -rust-version.workspace = true -license = "Apache-2.0" -description = "Fast RLP serialization library" -homepage.workspace = true -repository.workspace = true - -[dependencies] -arrayvec = { version = "0.7", default-features = false } -auto_impl = "1" -bytes.workspace = true -ethnum = { version = "1", default-features = false, optional = true } -smol_str = { version = "0.2", default-features = false, optional = true } -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", - "std", - "ethnum", - "ethereum-types", - "smol_str", -] } -hex-literal = "0.4" -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" -harness = false diff --git a/crates/rlp/LICENCE b/crates/rlp/LICENCE deleted file mode 100644 index 9c8f3ea0871e..000000000000 --- a/crates/rlp/LICENCE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/crates/rlp/README.md b/crates/rlp/README.md deleted file mode 100644 index 0fda03ed21df..000000000000 --- a/crates/rlp/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## RLP encoder/decoder - -Forked from an earlier Apache licenced version of the `fastrlp` crate, before it changed licence to GPL. -NOTE: The Rust fastrlp implementation is itself a port of the [Golang Apache licensed fastrlp](https://github.com/umbracle/fastrlp) \ No newline at end of file diff --git a/crates/rlp/benches/bench.rs b/crates/rlp/benches/bench.rs deleted file mode 100644 index e69695183147..000000000000 --- a/crates/rlp/benches/bench.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! benchmarking for rlp - -use bytes::BytesMut; -use criterion::{criterion_group, criterion_main, Criterion}; -use ethnum::*; -use hex_literal::hex; -use pprof::criterion::{Output, PProfProfiler}; -use reth_rlp::*; - -fn bench_encode(c: &mut Criterion) { - c.bench_function("encode_u64", |b| { - b.iter(|| { - let mut out = BytesMut::new(); - 0x1023_4567_89ab_cdefu64.encode(&mut out); - }) - }); - c.bench_function("encode_u256", |b| { - b.iter(|| { - let mut out = BytesMut::new(); - let uint = U256::from_be_bytes(hex!( - "8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0" - )); - uint.encode(&mut out); - }) - }); - c.bench_function("encode_1000_u64", |b| { - b.iter(|| { - let mut out = BytesMut::new(); - reth_rlp::encode_list((0..1000u64).collect::>().as_slice(), &mut out); - }) - }); -} - -fn bench_decode(c: &mut Criterion) { - c.bench_function("decode_u64", |b| { - b.iter(|| { - let data = [0x88, 0x10, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; - let _ = u64::decode(&mut &data[..]).unwrap(); - }) - }); - c.bench_function("decode_u256", |b| { - b.iter(|| { - let data = [ - 0xa0, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0x09, 0x10, 0x20, 0x30, 0x40, - 0x50, 0x60, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x12, 0xf0, - ]; - let _ = U256::decode(&mut &data[..]).unwrap(); - }) - }); - c.bench_function("decode_1000_u64", |b| { - let input = (0..1000u64).collect::>(); - let mut data = BytesMut::new(); - reth_rlp::encode_list(input.as_slice(), &mut data); - b.iter(|| { - let _ = Vec::::decode(&mut &data[..]).unwrap(); - }); - }); -} - -criterion_group! { - name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = bench_encode, bench_decode -} -criterion_main!(benches); diff --git a/crates/rlp/rlp-derive/Cargo.toml b/crates/rlp/rlp-derive/Cargo.toml deleted file mode 100644 index 72760af83d96..000000000000 --- a/crates/rlp/rlp-derive/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "reth-rlp-derive" -version.workspace = true -license = "Apache-2.0" -edition.workspace = true -rust-version.workspace = true -description = "Procedural macros for reth-rlp" -homepage.workspace = true -repository.workspace = true - -[lib] -proc-macro = true - -[dependencies] -syn = "2" -quote.workspace = true -proc-macro2.workspace = true diff --git a/crates/rlp/rlp-derive/LICENCE b/crates/rlp/rlp-derive/LICENCE deleted file mode 100644 index 9c8f3ea0871e..000000000000 --- a/crates/rlp/rlp-derive/LICENCE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/crates/rlp/rlp-derive/README.md b/crates/rlp/rlp-derive/README.md deleted file mode 100644 index a105019ab65c..000000000000 --- a/crates/rlp/rlp-derive/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## RLP derive crate - -Forked from an earlier Apache licenced version of the `fastrlp-derive` crate, before it changed licence to GPL. -NOTE: The Rust fastrlp implementation is itself a port of the [Golang Apache licensed fastrlp](https://github.com/umbracle/fastrlp) diff --git a/crates/rlp/rlp-derive/src/de.rs b/crates/rlp/rlp-derive/src/de.rs deleted file mode 100644 index aab545fd86d3..000000000000 --- a/crates/rlp/rlp-derive/src/de.rs +++ /dev/null @@ -1,123 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Error, Result}; - -use crate::utils::{attributes_include, field_ident, is_optional, parse_struct, EMPTY_STRING_CODE}; - -pub(crate) fn impl_decodable(ast: &syn::DeriveInput) -> Result { - let body = parse_struct(ast, "RlpDecodable")?; - - let fields = body.fields.iter().enumerate(); - - let supports_trailing_opt = attributes_include(&ast.attrs, "trailing"); - - let mut encountered_opt_item = false; - let mut stmts = Vec::with_capacity(body.fields.len()); - for (i, field) in fields { - let is_opt = is_optional(field); - if is_opt { - if !supports_trailing_opt { - return Err(Error::new_spanned(field, "Optional fields are disabled. Add `#[rlp(trailing)]` attribute to the struct in order to enable")); - } - encountered_opt_item = true; - } else if encountered_opt_item && !attributes_include(&field.attrs, "default") { - return Err(Error::new_spanned( - field, - "All subsequent fields must be either optional or default.", - )) - } - - stmts.push(decodable_field(i, field, is_opt)); - } - - let name = &ast.ident; - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - - let impl_block = quote! { - impl #impl_generics reth_rlp::Decodable for #name #ty_generics #where_clause { - fn decode(mut buf: &mut &[u8]) -> Result { - let b = &mut &**buf; - let rlp_head = reth_rlp::Header::decode(b)?; - - if !rlp_head.list { - return Err(reth_rlp::DecodeError::UnexpectedString); - } - - let started_len = b.len(); - let this = Self { - #(#stmts)* - }; - - let consumed = started_len - b.len(); - if consumed != rlp_head.payload_length { - return Err(reth_rlp::DecodeError::ListLengthMismatch { - expected: rlp_head.payload_length, - got: consumed, - }); - } - - *buf = *b; - - Ok(this) - } - } - }; - - Ok(quote! { - const _: () = { - extern crate reth_rlp; - #impl_block - }; - }) -} - -pub(crate) fn impl_decodable_wrapper(ast: &syn::DeriveInput) -> Result { - let body = parse_struct(ast, "RlpDecodableWrapper")?; - - assert_eq!( - body.fields.iter().count(), - 1, - "#[derive(RlpDecodableWrapper)] is only defined for structs with one field." - ); - - let name = &ast.ident; - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - - let impl_block = quote! { - impl #impl_generics reth_rlp::Decodable for #name #ty_generics #where_clause { - fn decode(buf: &mut &[u8]) -> Result { - Ok(Self(reth_rlp::Decodable::decode(buf)?)) - } - } - }; - - Ok(quote! { - const _: () = { - extern crate reth_rlp; - #impl_block - }; - }) -} - -fn decodable_field(index: usize, field: &syn::Field, is_opt: bool) -> TokenStream { - let ident = field_ident(index, field); - - if attributes_include(&field.attrs, "default") { - quote! { #ident: Default::default(), } - } else if is_opt { - quote! { - #ident: if started_len - b.len() < rlp_head.payload_length { - if b.first().map(|b| *b == #EMPTY_STRING_CODE).unwrap_or_default() { - bytes::Buf::advance(b, 1); - None - } else { - Some(reth_rlp::Decodable::decode(b)?) - } - } else { - None - }, - } - } else { - quote! { #ident: reth_rlp::Decodable::decode(b)?, } - } -} diff --git a/crates/rlp/rlp-derive/src/en.rs b/crates/rlp/rlp-derive/src/en.rs deleted file mode 100644 index dda14741f0b6..000000000000 --- a/crates/rlp/rlp-derive/src/en.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::iter::Peekable; - -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Error, Result}; - -use crate::utils::{attributes_include, field_ident, is_optional, parse_struct, EMPTY_STRING_CODE}; - -pub(crate) fn impl_encodable(ast: &syn::DeriveInput) -> Result { - let body = parse_struct(ast, "RlpEncodable")?; - - let mut fields = body - .fields - .iter() - .enumerate() - .filter(|(_, field)| !attributes_include(&field.attrs, "skip")) - .peekable(); - - let supports_trailing_opt = attributes_include(&ast.attrs, "trailing"); - - let mut encountered_opt_item = false; - let mut length_stmts = Vec::with_capacity(body.fields.len()); - let mut stmts = Vec::with_capacity(body.fields.len()); - - while let Some((i, field)) = fields.next() { - let is_opt = is_optional(field); - if is_opt { - if !supports_trailing_opt { - return Err(Error::new_spanned(field, "Optional fields are disabled. Add `#[rlp(trailing)]` attribute to the struct in order to enable")); - } - encountered_opt_item = true; - } else if encountered_opt_item { - return Err(Error::new_spanned(field, "All subsequent fields must be optional.")) - } - - length_stmts.push(encodable_length(i, field, is_opt, fields.clone())); - stmts.push(encodable_field(i, field, is_opt, fields.clone())); - } - - let name = &ast.ident; - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - - let impl_block = quote! { - trait E { - fn rlp_header(&self) -> reth_rlp::Header; - } - - impl #impl_generics E for #name #ty_generics #where_clause { - fn rlp_header(&self) -> reth_rlp::Header { - let mut rlp_head = reth_rlp::Header { list: true, payload_length: 0 }; - #(#length_stmts)* - rlp_head - } - } - - impl #impl_generics reth_rlp::Encodable for #name #ty_generics #where_clause { - fn length(&self) -> usize { - let rlp_head = E::rlp_header(self); - return reth_rlp::length_of_length(rlp_head.payload_length) + rlp_head.payload_length; - } - fn encode(&self, out: &mut dyn reth_rlp::BufMut) { - E::rlp_header(self).encode(out); - #(#stmts)* - } - } - }; - - Ok(quote! { - const _: () = { - extern crate reth_rlp; - #impl_block - }; - }) -} - -pub(crate) fn impl_encodable_wrapper(ast: &syn::DeriveInput) -> Result { - let body = parse_struct(ast, "RlpEncodableWrapper")?; - - let ident = { - let fields: Vec<_> = body.fields.iter().collect(); - if fields.len() == 1 { - let field = fields.first().expect("fields.len() == 1; qed"); - field_ident(0, field) - } else { - panic!("#[derive(RlpEncodableWrapper)] is only defined for structs with one field.") - } - }; - - let name = &ast.ident; - let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); - - let impl_block = quote! { - impl #impl_generics reth_rlp::Encodable for #name #ty_generics #where_clause { - fn length(&self) -> usize { - self.#ident.length() - } - fn encode(&self, out: &mut dyn reth_rlp::BufMut) { - self.#ident.encode(out) - } - } - }; - - Ok(quote! { - const _: () = { - extern crate reth_rlp; - #impl_block - }; - }) -} - -pub(crate) fn impl_max_encoded_len(ast: &syn::DeriveInput) -> Result { - let body = parse_struct(ast, "RlpMaxEncodedLen")?; - - let stmts: Vec<_> = body - .fields - .iter() - .enumerate() - .filter(|(_, field)| !attributes_include(&field.attrs, "skip")) - .map(|(index, field)| encodable_max_length(index, field)) - .collect(); - let name = &ast.ident; - - let impl_block = quote! { - unsafe impl reth_rlp::MaxEncodedLen<{ reth_rlp::const_add(reth_rlp::length_of_length(#(#stmts)*), #(#stmts)*) }> for #name {} - unsafe impl reth_rlp::MaxEncodedLenAssoc for #name { - const LEN: usize = { reth_rlp::const_add(reth_rlp::length_of_length(#(#stmts)*), { #(#stmts)* }) }; - } - }; - - Ok(quote! { - const _: () = { - extern crate reth_rlp; - #impl_block - }; - }) -} - -fn encodable_length<'a>( - index: usize, - field: &syn::Field, - is_opt: bool, - mut remaining: Peekable>, -) -> TokenStream { - let ident = field_ident(index, field); - - if is_opt { - let default = if remaining.peek().is_some() { - let condition = remaining_opt_fields_some_condition(remaining); - quote! { #condition as usize } - } else { - quote! { 0 } - }; - - quote! { rlp_head.payload_length += &self.#ident.as_ref().map(|val| reth_rlp::Encodable::length(val)).unwrap_or(#default); } - } else { - quote! { rlp_head.payload_length += reth_rlp::Encodable::length(&self.#ident); } - } -} - -fn encodable_max_length(index: usize, field: &syn::Field) -> TokenStream { - let fieldtype = &field.ty; - - if index == 0 { - quote! { <#fieldtype as reth_rlp::MaxEncodedLenAssoc>::LEN } - } else { - quote! { + <#fieldtype as reth_rlp::MaxEncodedLenAssoc>::LEN } - } -} - -fn encodable_field<'a>( - index: usize, - field: &syn::Field, - is_opt: bool, - mut remaining: Peekable>, -) -> TokenStream { - let ident = field_ident(index, field); - - if is_opt { - let if_some_encode = quote! { - if let Some(val) = self.#ident.as_ref() { - reth_rlp::Encodable::encode(val, out) - } - }; - - if remaining.peek().is_some() { - let condition = remaining_opt_fields_some_condition(remaining); - quote! { - #if_some_encode - else if #condition { - out.put_u8(#EMPTY_STRING_CODE); - } - } - } else { - quote! { #if_some_encode } - } - } else { - quote! { reth_rlp::Encodable::encode(&self.#ident, out); } - } -} - -fn remaining_opt_fields_some_condition<'a>( - remaining: impl Iterator, -) -> TokenStream { - let conditions = remaining.map(|(index, field)| { - let ident = field_ident(index, field); - quote! { self.#ident.is_some() } - }); - quote! { #(#conditions) ||* } -} diff --git a/crates/rlp/rlp-derive/src/lib.rs b/crates/rlp/rlp-derive/src/lib.rs deleted file mode 100644 index 02d9bc4449cb..000000000000 --- a/crates/rlp/rlp-derive/src/lib.rs +++ /dev/null @@ -1,83 +0,0 @@ -#![cfg_attr(docsrs, feature(doc_cfg))] -#![doc( - html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", - html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", - issue_tracker_base_url = "https://github.com/paradigmxzy/reth/issues/" -)] -#![warn(missing_docs, unreachable_pub)] -#![deny(unused_must_use, unused_crate_dependencies)] -#![doc(test( - no_crate_inject, - attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) -))] - -//! Derive macro for `#[derive(RlpEncodable, RlpDecodable)]`. -//! -//! For example of usage see `./tests/rlp.rs`. -//! -//! This library also supports up to 1 `#[rlp(default)]` in a struct, -//! which is similar to [`#[serde(default)]`](https://serde.rs/field-attrs.html#default) -//! with the caveat that we use the `Default` value if -//! the field deserialization fails, as we don't serialize field -//! names and there is no way to tell if it is present or not. - -extern crate proc_macro; - -mod de; -mod en; -mod utils; - -use de::*; -use en::*; -use proc_macro::TokenStream; - -/// Derives `Encodable` for the type which encodes the all fields as list: `` -#[proc_macro_derive(RlpEncodable, attributes(rlp))] -pub fn encodable(input: TokenStream) -> TokenStream { - syn::parse(input) - .and_then(|ast| impl_encodable(&ast)) - .unwrap_or_else(|err| err.to_compile_error()) - .into() -} - -/// Derives `Encodable` for the type which encodes the fields as-is, without a header: `` -#[proc_macro_derive(RlpEncodableWrapper, attributes(rlp))] -pub fn encodable_wrapper(input: TokenStream) -> TokenStream { - syn::parse(input) - .and_then(|ast| impl_encodable_wrapper(&ast)) - .unwrap_or_else(|err| err.to_compile_error()) - .into() -} - -/// Derives `MaxEncodedLen` for types of constant size. -#[proc_macro_derive(RlpMaxEncodedLen, attributes(rlp))] -pub fn max_encoded_len(input: TokenStream) -> TokenStream { - syn::parse(input) - .and_then(|ast| impl_max_encoded_len(&ast)) - .unwrap_or_else(|err| err.to_compile_error()) - .into() -} - -/// Derives `Decodable` for the type whose implementation expects an rlp-list input: `` -/// -/// This is the inverse of `RlpEncodable`. -#[proc_macro_derive(RlpDecodable, attributes(rlp))] -pub fn decodable(input: TokenStream) -> TokenStream { - syn::parse(input) - .and_then(|ast| impl_decodable(&ast)) - .unwrap_or_else(|err| err.to_compile_error()) - .into() -} - -/// Derives `Decodable` for the type whose implementation expects only the individual fields -/// encoded: `` -/// -/// This is the inverse of `RlpEncodableWrapper`. -#[proc_macro_derive(RlpDecodableWrapper, attributes(rlp))] -pub fn decodable_wrapper(input: TokenStream) -> TokenStream { - syn::parse(input) - .and_then(|ast| impl_decodable_wrapper(&ast)) - .unwrap_or_else(|err| err.to_compile_error()) - .into() -} diff --git a/crates/rlp/rlp-derive/src/utils.rs b/crates/rlp/rlp-derive/src/utils.rs deleted file mode 100644 index f4d4c87679c8..000000000000 --- a/crates/rlp/rlp-derive/src/utils.rs +++ /dev/null @@ -1,57 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Attribute, DataStruct, Error, Field, Meta, Result, Type, TypePath}; - -pub(crate) const EMPTY_STRING_CODE: u8 = 0x80; - -pub(crate) fn parse_struct<'a>( - ast: &'a syn::DeriveInput, - derive_attr: &str, -) -> Result<&'a DataStruct> { - if let syn::Data::Struct(s) = &ast.data { - Ok(s) - } else { - Err(Error::new_spanned( - ast, - format!("#[derive({derive_attr})] is only defined for structs."), - )) - } -} - -pub(crate) fn attributes_include(attrs: &[Attribute], attr_name: &str) -> bool { - for attr in attrs.iter() { - if attr.path().is_ident("rlp") { - if let Meta::List(meta) = &attr.meta { - let mut is_attr = false; - let _ = meta.parse_nested_meta(|meta| { - is_attr = meta.path.is_ident(attr_name); - Ok(()) - }); - if is_attr { - return true - } - } - } - } - false -} - -pub(crate) fn is_optional(field: &Field) -> bool { - if let Type::Path(TypePath { qself, path }) = &field.ty { - qself.is_none() && - path.leading_colon.is_none() && - path.segments.len() == 1 && - path.segments.first().unwrap().ident == "Option" - } else { - false - } -} - -pub(crate) fn field_ident(index: usize, field: &syn::Field) -> TokenStream { - if let Some(ident) = &field.ident { - quote! { #ident } - } else { - let index = syn::Index::from(index); - quote! { #index } - } -} diff --git a/crates/rlp/src/decode.rs b/crates/rlp/src/decode.rs deleted file mode 100644 index 94d466612bf7..000000000000 --- a/crates/rlp/src/decode.rs +++ /dev/null @@ -1,669 +0,0 @@ -use crate::types::Header; -use bytes::{Buf, Bytes, BytesMut}; - -pub trait Decodable: Sized { - fn decode(buf: &mut &[u8]) -> Result; -} - -#[cfg(feature = "alloc")] -mod alloc_impl { - use super::*; - - impl Decodable for ::alloc::boxed::Box - where - T: Decodable + Sized, - { - fn decode(buf: &mut &[u8]) -> Result { - T::decode(buf).map(::alloc::boxed::Box::new) - } - } - - impl Decodable for ::alloc::sync::Arc - where - T: Decodable + Sized, - { - fn decode(buf: &mut &[u8]) -> Result { - T::decode(buf).map(::alloc::sync::Arc::new) - } - } - - impl Decodable for ::alloc::string::String { - fn decode(from: &mut &[u8]) -> Result { - let h = Header::decode(from)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - let mut to = ::alloc::vec::Vec::with_capacity(h.payload_length); - to.extend_from_slice(&from[..h.payload_length]); - from.advance(h.payload_length); - - Self::from_utf8(to).map_err(|_| DecodeError::Custom("invalid string")) - } - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum DecodeError { - Overflow, - LeadingZero, - InputTooShort, - NonCanonicalSingleByte, - NonCanonicalSize, - UnexpectedLength, - UnexpectedString, - UnexpectedList, - ListLengthMismatch { expected: usize, got: usize }, - Custom(&'static str), -} - -#[cfg(feature = "std")] -impl std::error::Error for DecodeError {} - -impl core::fmt::Display for DecodeError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - DecodeError::Overflow => write!(f, "overflow"), - DecodeError::LeadingZero => write!(f, "leading zero"), - DecodeError::InputTooShort => write!(f, "input too short"), - DecodeError::NonCanonicalSingleByte => write!(f, "non-canonical single byte"), - DecodeError::NonCanonicalSize => write!(f, "non-canonical size"), - DecodeError::UnexpectedLength => write!(f, "unexpected length"), - DecodeError::UnexpectedString => write!(f, "unexpected string"), - DecodeError::UnexpectedList => write!(f, "unexpected list"), - DecodeError::ListLengthMismatch { expected, got } => { - write!(f, "list length mismatch: expected {expected}, got {got}") - } - DecodeError::Custom(err) => write!(f, "{err}"), - } - } -} - -impl Header { - /// Returns the decoded header. - /// - /// Returns an error if the given `buf`'s len is less than the expected payload. - pub fn decode(buf: &mut &[u8]) -> Result { - if !buf.has_remaining() { - return Err(DecodeError::InputTooShort) - } - - let b = buf[0]; - let h: Self = { - if b < 0x80 { - Self { list: false, payload_length: 1 } - } else if b < 0xB8 { - buf.advance(1); - let h = Self { list: false, payload_length: b as usize - 0x80 }; - - if h.payload_length == 1 { - if !buf.has_remaining() { - return Err(DecodeError::InputTooShort) - } - if buf[0] < 0x80 { - return Err(DecodeError::NonCanonicalSingleByte) - } - } - - h - } else if b < 0xC0 { - buf.advance(1); - let len_of_len = b as usize - 0xB7; - if buf.len() < len_of_len { - return Err(DecodeError::InputTooShort) - } - let payload_length = usize::try_from(u64::from_be_bytes( - static_left_pad(&buf[..len_of_len]).ok_or(DecodeError::LeadingZero)?, - )) - .map_err(|_| DecodeError::Custom("Input too big"))?; - buf.advance(len_of_len); - if payload_length < 56 { - return Err(DecodeError::NonCanonicalSize) - } - - Self { list: false, payload_length } - } else if b < 0xF8 { - buf.advance(1); - Self { list: true, payload_length: b as usize - 0xC0 } - } else { - buf.advance(1); - let list = true; - let len_of_len = b as usize - 0xF7; - if buf.len() < len_of_len { - return Err(DecodeError::InputTooShort) - } - let payload_length = usize::try_from(u64::from_be_bytes( - static_left_pad(&buf[..len_of_len]).ok_or(DecodeError::LeadingZero)?, - )) - .map_err(|_| DecodeError::Custom("Input too big"))?; - buf.advance(len_of_len); - if payload_length < 56 { - return Err(DecodeError::NonCanonicalSize) - } - - Self { list, payload_length } - } - }; - - if buf.remaining() < h.payload_length { - return Err(DecodeError::InputTooShort) - } - - Ok(h) - } -} - -fn static_left_pad(data: &[u8]) -> Option<[u8; LEN]> { - if data.len() > LEN { - return None - } - - let mut v = [0; LEN]; - - if data.is_empty() { - return Some(v) - } - - if data[0] == 0 { - return None - } - - v[LEN - data.len()..].copy_from_slice(data); - Some(v) -} - -macro_rules! decode_integer { - ($t:ty) => { - impl Decodable for $t { - fn decode(buf: &mut &[u8]) -> Result { - let h = Header::decode(buf)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - if h.payload_length > (<$t>::BITS as usize / 8) { - return Err(DecodeError::Overflow) - } - if buf.remaining() < h.payload_length { - return Err(DecodeError::InputTooShort) - } - // In the case of 0x80, the Header will be decoded, leaving h.payload_length to be - // zero. - // 0x80 is the canonical encoding of 0, so we return 0 here. - if h.payload_length == 0 { - return Ok(<$t>::from(0u8)) - } - let v = <$t>::from_be_bytes( - static_left_pad(&buf[..h.payload_length]).ok_or(DecodeError::LeadingZero)?, - ); - buf.advance(h.payload_length); - Ok(v) - } - } - }; -} - -decode_integer!(usize); -decode_integer!(u8); -decode_integer!(u16); -decode_integer!(u32); -decode_integer!(u64); -decode_integer!(u128); - -impl Decodable for bool { - fn decode(buf: &mut &[u8]) -> Result { - Ok(match u8::decode(buf)? { - 0 => false, - 1 => true, - _ => return Err(DecodeError::Custom("invalid bool value, must be 0 or 1")), - }) - } -} - -#[cfg(feature = "std")] -impl Decodable for std::net::IpAddr { - fn decode(buf: &mut &[u8]) -> Result { - use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - - let h = Header::decode(buf)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - let o = match h.payload_length { - 4 => { - let mut to = [0_u8; 4]; - to.copy_from_slice(&buf[..4]); - IpAddr::V4(Ipv4Addr::from(to)) - } - 16 => { - let mut to = [0u8; 16]; - to.copy_from_slice(&buf[..16]); - IpAddr::V6(Ipv6Addr::from(to)) - } - _ => return Err(DecodeError::UnexpectedLength), - }; - buf.advance(h.payload_length); - Ok(o) - } -} - -#[cfg(feature = "ethnum")] -decode_integer!(ethnum::U256); - -#[cfg(feature = "ethereum-types")] -mod ethereum_types_support { - use super::*; - use ethereum_types::*; - use revm_primitives::{ruint::aliases::U128 as RU128, B160, B256, U256 as RU256}; - - macro_rules! fixed_hash_impl { - ($t:ty) => { - impl Decodable for $t { - fn decode(buf: &mut &[u8]) -> Result { - Decodable::decode(buf).map(Self) - } - } - }; - } - - fixed_hash_impl!(B160); - fixed_hash_impl!(B256); - - fixed_hash_impl!(H64); - fixed_hash_impl!(H128); - fixed_hash_impl!(H160); - fixed_hash_impl!(H256); - fixed_hash_impl!(H512); - fixed_hash_impl!(H520); - - macro_rules! fixed_uint_impl { - ($t:ty, $n_bytes:tt) => { - impl Decodable for $t { - fn decode(buf: &mut &[u8]) -> Result { - let h = Header::decode(buf)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - if h.payload_length > $n_bytes { - return Err(DecodeError::Overflow) - } - if buf.remaining() < h.payload_length { - return Err(DecodeError::InputTooShort) - } - // In the case of 0x80, the Header will be decoded, leaving h.payload_length to - // be zero. - // 0x80 is the canonical encoding of 0, so we return 0 here. - if h.payload_length == 0 { - return Ok(<$t>::from(0u8)) - } - let n = <$t>::from_big_endian( - &static_left_pad::<$n_bytes>(&buf[..h.payload_length]) - .ok_or(DecodeError::LeadingZero)?, - ); - buf.advance(h.payload_length); - Ok(n) - } - } - }; - } - - macro_rules! fixed_revm_uint_impl { - ($t:ty, $n_bytes:tt) => { - impl Decodable for $t { - fn decode(buf: &mut &[u8]) -> Result { - let h = Header::decode(buf)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - if h.payload_length > $n_bytes { - return Err(DecodeError::Overflow) - } - if buf.remaining() < h.payload_length { - return Err(DecodeError::InputTooShort) - } - // In the case of 0x80, the Header will be decoded, leaving h.payload_length to - // be zero. - // 0x80 is the canonical encoding of 0, so we return 0 here. - if h.payload_length == 0 { - return Ok(<$t>::from(0u8)) - } - let n = <$t>::from_be_bytes( - static_left_pad::<$n_bytes>(&buf[..h.payload_length]) - .ok_or(DecodeError::LeadingZero)?, - ); - buf.advance(h.payload_length); - Ok(n) - } - } - }; - } - - fixed_revm_uint_impl!(RU256, 32); - fixed_revm_uint_impl!(RU128, 16); - - fixed_uint_impl!(U64, 8); - fixed_uint_impl!(U128, 16); - fixed_uint_impl!(U256, 32); - fixed_uint_impl!(U512, 64); -} - -impl Decodable for [u8; N] { - fn decode(from: &mut &[u8]) -> Result { - let h = Header::decode(from)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - if h.payload_length != N { - return Err(DecodeError::UnexpectedLength) - } - - let mut to = [0_u8; N]; - to.copy_from_slice(&from[..N]); - from.advance(N); - - Ok(to) - } -} - -impl Decodable for BytesMut { - fn decode(from: &mut &[u8]) -> Result { - let h = Header::decode(from)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - let mut to = BytesMut::with_capacity(h.payload_length); - to.extend_from_slice(&from[..h.payload_length]); - from.advance(h.payload_length); - - Ok(to) - } -} - -impl Decodable for Bytes { - fn decode(buf: &mut &[u8]) -> Result { - BytesMut::decode(buf).map(BytesMut::freeze) - } -} - -pub struct Rlp<'a> { - payload_view: &'a [u8], -} - -impl<'a> Rlp<'a> { - pub fn new(mut payload: &'a [u8]) -> Result { - let h = Header::decode(&mut payload)?; - if !h.list { - return Err(DecodeError::UnexpectedString) - } - - let payload_view = &payload[..h.payload_length]; - Ok(Self { payload_view }) - } - - pub fn get_next(&mut self) -> Result, DecodeError> { - if self.payload_view.is_empty() { - return Ok(None) - } - - Ok(Some(T::decode(&mut self.payload_view)?)) - } -} - -#[cfg(feature = "alloc")] -impl Decodable for alloc::vec::Vec -where - E: Decodable, -{ - fn decode(buf: &mut &[u8]) -> Result { - let h = Header::decode(buf)?; - if !h.list { - return Err(DecodeError::UnexpectedString) - } - - let payload_view = &mut &buf[..h.payload_length]; - - let mut to = alloc::vec::Vec::new(); - while !payload_view.is_empty() { - to.push(E::decode(payload_view)?); - } - - buf.advance(h.payload_length); - - Ok(to) - } -} - -#[cfg(feature = "smol_str")] -impl Decodable for smol_str::SmolStr { - fn decode(from: &mut &[u8]) -> Result { - let h = Header::decode(from)?; - if h.list { - return Err(DecodeError::UnexpectedList) - } - let data = &from[..h.payload_length]; - let s = match core::str::from_utf8(data) { - Ok(s) => Ok(smol_str::SmolStr::from(s)), - Err(_) => Err(DecodeError::Custom("invalid string")), - }; - from.advance(h.payload_length); - s - } -} - -#[cfg(test)] -mod tests { - extern crate alloc; - - use super::*; - use crate::Encodable; - use alloc::vec; - use core::fmt::Debug; - use ethereum_types::{U128, U256, U512, U64}; - use ethnum::AsU256; - use hex_literal::hex; - - fn check_decode<'a, T, IT>(fixtures: IT) - where - T: Decodable + PartialEq + Debug, - IT: IntoIterator, &'a [u8])>, - { - for (expected, mut input) in fixtures { - assert_eq!(T::decode(&mut input), expected); - if expected.is_ok() { - assert_eq!(input, &[]); - } - } - } - - fn check_decode_list(fixtures: IT) - where - T: Decodable + PartialEq + Debug, - IT: IntoIterator, DecodeError>, &'static [u8])>, - { - for (expected, mut input) in fixtures { - assert_eq!(vec::Vec::::decode(&mut input), expected); - if expected.is_ok() { - assert_eq!(input, &[]); - } - } - } - - #[test] - fn rlp_strings() { - check_decode::(vec![ - (Ok(hex!("00")[..].to_vec().into()), &hex!("00")[..]), - ( - Ok(hex!("6f62636465666768696a6b6c6d")[..].to_vec().into()), - &hex!("8D6F62636465666768696A6B6C6D")[..], - ), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - ]) - } - - #[test] - fn rlp_fixed_length() { - check_decode(vec![ - (Ok(hex!("6f62636465666768696a6b6c6d")), &hex!("8D6F62636465666768696A6B6C6D")[..]), - (Err(DecodeError::UnexpectedLength), &hex!("8C6F62636465666768696A6B6C")[..]), - (Err(DecodeError::UnexpectedLength), &hex!("8E6F62636465666768696A6B6C6D6E")[..]), - ]) - } - - #[test] - fn rlp_u64() { - check_decode(vec![ - (Ok(9_u64), &hex!("09")[..]), - (Ok(0_u64), &hex!("80")[..]), - (Ok(0x0505_u64), &hex!("820505")[..]), - (Ok(0xCE05050505_u64), &hex!("85CE05050505")[..]), - (Err(DecodeError::Overflow), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - (Err(DecodeError::LeadingZero), &hex!("00")[..]), - (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]), - (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]), - (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]), - ( - Err(DecodeError::Overflow), - &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ]) - } - - #[test] - fn rlp_u256() { - check_decode(vec![ - (Ok(9_u8.as_u256()), &hex!("09")[..]), - (Ok(0_u8.as_u256()), &hex!("80")[..]), - (Ok(0x0505_u16.as_u256()), &hex!("820505")[..]), - (Ok(0xCE05050505_u64.as_u256()), &hex!("85CE05050505")[..]), - (Ok(0xFFFFFFFFFFFFFFFFFF7C_u128.as_u256()), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - (Err(DecodeError::LeadingZero), &hex!("00")[..]), - (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]), - (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]), - (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]), - ( - Err(DecodeError::Overflow), - &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ]) - } - - #[cfg(feature = "ethereum-types")] - #[test] - fn rlp_ethereum_types_u64() { - check_decode(vec![ - (Ok(U64::from(9_u8)), &hex!("09")[..]), - (Ok(U64::from(0_u8)), &hex!("80")[..]), - (Ok(U64::from(0x0505_u16)), &hex!("820505")[..]), - (Ok(U64::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]), - (Err(DecodeError::Overflow), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - (Err(DecodeError::LeadingZero), &hex!("00")[..]), - (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]), - (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]), - (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]), - ( - Err(DecodeError::Overflow), - &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ]) - } - - #[cfg(feature = "ethereum-types")] - #[test] - fn rlp_ethereum_types_u128() { - check_decode(vec![ - (Ok(U128::from(9_u8)), &hex!("09")[..]), - (Ok(U128::from(0_u8)), &hex!("80")[..]), - (Ok(U128::from(0x0505_u16)), &hex!("820505")[..]), - (Ok(U128::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]), - (Ok(U128::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - (Err(DecodeError::LeadingZero), &hex!("00")[..]), - (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]), - (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]), - (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]), - ( - Err(DecodeError::Overflow), - &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ]) - } - - #[cfg(feature = "ethereum-types")] - #[test] - fn rlp_ethereum_types_u256() { - check_decode(vec![ - (Ok(U256::from(9_u8)), &hex!("09")[..]), - (Ok(U256::from(0_u8)), &hex!("80")[..]), - (Ok(U256::from(0x0505_u16)), &hex!("820505")[..]), - (Ok(U256::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]), - (Ok(U256::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::InputTooShort), &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..]), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - (Err(DecodeError::LeadingZero), &hex!("00")[..]), - (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]), - (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]), - (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]), - ( - Err(DecodeError::Overflow), - &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ]) - } - - #[cfg(feature = "ethereum-types")] - #[test] - fn rlp_ethereum_types_u512() { - check_decode(vec![ - (Ok(U512::from(9_u8)), &hex!("09")[..]), - (Ok(U512::from(0_u8)), &hex!("80")[..]), - (Ok(U512::from(0x0505_u16)), &hex!("820505")[..]), - (Ok(U512::from(0xCE05050505_u64)), &hex!("85CE05050505")[..]), - ( - Ok(U512::from(0xFFFFFFFFFFFFFFFFFF7C_u128)), - &hex!("8AFFFFFFFFFFFFFFFFFF7C")[..], - ), - ( - Err(DecodeError::InputTooShort), - &hex!("8BFFFFFFFFFFFFFFFFFF7C")[..], - ), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - (Err(DecodeError::LeadingZero), &hex!("00")[..]), - (Err(DecodeError::NonCanonicalSingleByte), &hex!("8105")[..]), - (Err(DecodeError::LeadingZero), &hex!("8200F4")[..]), - (Err(DecodeError::NonCanonicalSize), &hex!("B8020004")[..]), - ( - Ok(U512::from_dec_str("115792089237316195423570985008687907853269984676653278628940326933415738736640").unwrap()), - &hex!("A101000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ( - Err(DecodeError::Overflow), - &hex!("B84101000000000000000000000000000000000000008B000000000000000000000000000000000000000000000000000000000000008B000000000000000000000000")[..], - ), - ]) - } - - #[test] - fn rlp_vectors() { - check_decode_list(vec![ - (Ok(vec![]), &hex!("C0")[..]), - (Ok(vec![0xBBCCB5_u64, 0xFFC0B5_u64]), &hex!("C883BBCCB583FFC0B5")[..]), - ]) - } - - #[cfg(feature = "smol_str")] - #[test] - fn rlp_smol_str() { - use smol_str::SmolStr; - let mut b = BytesMut::new(); - "test smol str".to_string().encode(&mut b); - check_decode::(vec![ - (Ok(SmolStr::new("test smol str")), b.as_ref()), - (Err(DecodeError::UnexpectedList), &hex!("C0")[..]), - ]) - } -} diff --git a/crates/rlp/src/encode.rs b/crates/rlp/src/encode.rs deleted file mode 100644 index 6d669fd667e1..000000000000 --- a/crates/rlp/src/encode.rs +++ /dev/null @@ -1,738 +0,0 @@ -use crate::types::*; -use arrayvec::ArrayVec; -use auto_impl::auto_impl; -use bytes::{BufMut, Bytes, BytesMut}; -use core::borrow::Borrow; - -macro_rules! to_be_bytes_trimmed { - ($be:ident, $x:expr) => {{ - $be = $x.to_be_bytes(); - &$be[($x.leading_zeros() / 8) as usize..] - }}; -} - -impl Header { - /// Encodes the header into the `out` buffer. - pub fn encode(&self, out: &mut dyn BufMut) { - if self.payload_length < 56 { - let code = if self.list { EMPTY_LIST_CODE } else { EMPTY_STRING_CODE }; - out.put_u8(code + self.payload_length as u8); - } else { - let len_be; - let len_be = to_be_bytes_trimmed!(len_be, self.payload_length); - let code = if self.list { 0xF7 } else { 0xB7 }; - out.put_u8(code + len_be.len() as u8); - out.put_slice(len_be); - } - } - - /// Returns the length of the encoded header - pub fn length(&self) -> usize { - let mut out = BytesMut::new(); - self.encode(&mut out); - out.len() - } -} - -pub const fn length_of_length(payload_length: usize) -> usize { - if payload_length < 56 { - 1 - } else { - 1 + 8 - payload_length.leading_zeros() as usize / 8 - } -} - -#[doc(hidden)] -pub const fn const_add(a: usize, b: usize) -> usize { - a + b -} - -#[doc(hidden)] -pub unsafe trait MaxEncodedLen: Encodable {} - -#[doc(hidden)] -pub unsafe trait MaxEncodedLenAssoc: Encodable { - const LEN: usize; -} - -/// Use this to define length of an encoded entity -/// -/// # Safety -/// Invalid value can cause the encoder to crash. -#[macro_export] -macro_rules! impl_max_encoded_len { - ($t:ty, $len:block) => { - unsafe impl MaxEncodedLen<{ $len }> for $t {} - unsafe impl MaxEncodedLenAssoc for $t { - const LEN: usize = $len; - } - }; -} - -#[auto_impl(&)] -#[cfg_attr(feature = "alloc", auto_impl(Box, Arc))] -pub trait Encodable { - /// Appends the rlp encoded object to the specified output buffer. - fn encode(&self, out: &mut dyn BufMut); - - /// Returns the length of the encoded object. - /// - /// NOTE: This includes the length of the rlp [Header]. - fn length(&self) -> usize { - let mut out = BytesMut::new(); - self.encode(&mut out); - out.len() - } -} - -impl<'a> Encodable for &'a [u8] { - fn encode(&self, out: &mut dyn BufMut) { - if self.len() != 1 || self[0] >= EMPTY_STRING_CODE { - Header { list: false, payload_length: self.len() }.encode(out); - } - out.put_slice(self); - } - - fn length(&self) -> usize { - let mut len = self.len(); - if self.len() != 1 || self[0] >= EMPTY_STRING_CODE { - len += length_of_length(self.len()); - } - len - } -} - -impl Encodable for [u8; LEN] { - fn encode(&self, out: &mut dyn BufMut) { - (self as &[u8]).encode(out) - } - - fn length(&self) -> usize { - (self as &[u8]).length() - } -} - -unsafe impl MaxEncodedLenAssoc for [u8; LEN] { - const LEN: usize = LEN + length_of_length(LEN); -} - -macro_rules! encodable_uint { - ($t:ty) => { - #[allow(clippy::cmp_owned)] - impl Encodable for $t { - fn length(&self) -> usize { - if *self < <$t>::from(EMPTY_STRING_CODE) { - 1 - } else { - 1 + (<$t>::BITS as usize / 8) - (self.leading_zeros() as usize / 8) - } - } - - fn encode(&self, out: &mut dyn BufMut) { - if *self == 0 { - out.put_u8(EMPTY_STRING_CODE); - } else if *self < <$t>::from(EMPTY_STRING_CODE) { - out.put_u8(u8::try_from(*self).unwrap()); - } else { - let be; - let be = to_be_bytes_trimmed!(be, *self); - out.put_u8(EMPTY_STRING_CODE + be.len() as u8); - out.put_slice(be); - } - } - } - }; -} - -macro_rules! max_encoded_len_uint { - ($t:ty) => { - impl_max_encoded_len!($t, { - length_of_length(<$t>::MAX.to_be_bytes().len()) + <$t>::MAX.to_be_bytes().len() - }); - }; -} - -encodable_uint!(usize); -max_encoded_len_uint!(usize); - -encodable_uint!(u8); -max_encoded_len_uint!(u8); - -encodable_uint!(u16); -max_encoded_len_uint!(u16); - -encodable_uint!(u32); -max_encoded_len_uint!(u32); - -encodable_uint!(u64); -max_encoded_len_uint!(u64); - -encodable_uint!(u128); -max_encoded_len_uint!(u128); - -impl Encodable for bool { - fn encode(&self, out: &mut dyn BufMut) { - (*self as u8).encode(out) - } - - fn length(&self) -> usize { - (*self as u8).length() - } -} - -impl_max_encoded_len!(bool, { ::LEN }); - -#[cfg(feature = "smol_str")] -impl Encodable for smol_str::SmolStr { - fn encode(&self, out: &mut dyn BufMut) { - self.as_bytes().encode(out); - } - fn length(&self) -> usize { - self.as_bytes().length() - } -} - -#[cfg(feature = "std")] -impl Encodable for std::net::IpAddr { - fn encode(&self, out: &mut dyn BufMut) { - match self { - std::net::IpAddr::V4(ref o) => (&o.octets()[..]).encode(out), - std::net::IpAddr::V6(ref o) => (&o.octets()[..]).encode(out), - } - } -} - -#[cfg(feature = "ethnum")] -mod ethnum_support { - use super::*; - - encodable_uint!(ethnum::U256); - impl_max_encoded_len!(ethnum::U256, { length_of_length(32) + 32 }); -} - -#[cfg(feature = "ethereum-types")] -mod ethereum_types_support { - use super::*; - use ethereum_types::*; - - use revm_primitives::{ruint::aliases::U128 as RU128, B160, B256, U256 as RU256}; - - macro_rules! fixed_hash_impl { - ($t:ty) => { - impl Encodable for $t { - fn length(&self) -> usize { - self.0.length() - } - - fn encode(&self, out: &mut dyn bytes::BufMut) { - self.0.encode(out) - } - } - impl_max_encoded_len!($t, { length_of_length(<$t>::len_bytes()) + <$t>::len_bytes() }); - }; - } - - fixed_hash_impl!(B160); - fixed_hash_impl!(B256); - fixed_hash_impl!(H64); - fixed_hash_impl!(H128); - fixed_hash_impl!(H160); - fixed_hash_impl!(H256); - fixed_hash_impl!(H512); - fixed_hash_impl!(H520); - - macro_rules! fixed_uint_impl { - ($t:ty, $n_bytes:tt) => { - impl Encodable for $t { - fn length(&self) -> usize { - if *self < <$t>::from(EMPTY_STRING_CODE) { - 1 - } else { - 1 + $n_bytes - (self.leading_zeros() as usize / 8) - } - } - - fn encode(&self, out: &mut dyn bytes::BufMut) { - let mut temp_arr = [0u8; $n_bytes]; - self.to_big_endian(&mut temp_arr[..]); - // cut the leading zeros after converting to big endian - let sliced = &temp_arr[(self.leading_zeros() / 8) as usize..]; - sliced.encode(out); - } - } - }; - } - - fixed_uint_impl!(U64, 8); - fixed_uint_impl!(U128, 16); - fixed_uint_impl!(U256, 32); - fixed_uint_impl!(U512, 64); - - macro_rules! fixed_revm_uint_impl { - ($t:ty, $n_bytes:tt) => { - impl Encodable for $t { - fn length(&self) -> usize { - if *self < <$t>::from(EMPTY_STRING_CODE) { - 1 - } else { - 1 + self.byte_len() - } - } - - fn encode(&self, out: &mut dyn bytes::BufMut) { - let be = self.to_be_bytes::<$n_bytes>(); - (&be[self.leading_zeros() / 8..]).encode(out); - } - } - }; - } - - fixed_revm_uint_impl!(RU128, 16); - fixed_revm_uint_impl!(RU256, 32); - impl_max_encoded_len!(RU256, { length_of_length(32) + 32 }); -} - -macro_rules! slice_impl { - ($t:ty) => { - impl $crate::Encodable for $t { - fn length(&self) -> usize { - (&self[..]).length() - } - - fn encode(&self, out: &mut dyn bytes::BufMut) { - (&self[..]).encode(out) - } - } - }; -} - -#[cfg(feature = "alloc")] -mod alloc_support { - use super::*; - - extern crate alloc; - - impl Encodable for ::alloc::vec::Vec - where - T: Encodable, - { - fn encode(&self, out: &mut dyn BufMut) { - encode_list(self, out) - } - - fn length(&self) -> usize { - list_length(self) - } - } - - impl Encodable for ::alloc::string::String { - fn encode(&self, out: &mut dyn BufMut) { - self.as_bytes().encode(out); - } - fn length(&self) -> usize { - self.as_bytes().length() - } - } -} - -impl Encodable for &str { - fn encode(&self, out: &mut dyn BufMut) { - self.as_bytes().encode(out); - } - fn length(&self) -> usize { - self.as_bytes().length() - } -} - -slice_impl!(Bytes); -slice_impl!(BytesMut); - -fn rlp_list_header(v: &[K]) -> Header -where - E: Encodable + ?Sized, - K: Borrow, -{ - let mut h = Header { list: true, payload_length: 0 }; - for x in v { - h.payload_length += x.borrow().length(); - } - h -} - -pub fn list_length(v: &[K]) -> usize -where - E: Encodable, - K: Borrow, -{ - let payload_length = rlp_list_header(v).payload_length; - length_of_length(payload_length) + payload_length -} - -/// RLP encode the list of items. -pub fn encode_list(v: &[K], out: &mut dyn BufMut) -where - E: Encodable + ?Sized, - K: Borrow, -{ - let h = rlp_list_header(v); - h.encode(out); - for x in v { - x.borrow().encode(out); - } -} - -/// RLP encode an iterator over items. -/// -/// NOTE: This function clones the iterator. If the items are expensive to clone, consider -/// using [encode_list] instead. -pub fn encode_iter(i: impl Iterator + Clone, out: &mut dyn BufMut) -where - K: Encodable, -{ - let mut h = Header { list: true, payload_length: 0 }; - for x in i.clone() { - h.payload_length += x.length(); - } - - h.encode(out); - for x in i { - x.encode(out); - } -} - -pub fn encode_fixed_size, const LEN: usize>(v: &E) -> ArrayVec { - let mut out = ArrayVec::from([0_u8; LEN]); - - let mut s = out.as_mut_slice(); - - v.encode(&mut s); - - let final_len = LEN - s.len(); - out.truncate(final_len); - - 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; - - use super::*; - use alloc::vec; - use bytes::BytesMut; - use hex_literal::hex; - - fn encoded(t: T) -> BytesMut { - let mut out = BytesMut::new(); - t.encode(&mut out); - out - } - - fn encoded_list(t: &[T]) -> BytesMut { - let mut out1 = BytesMut::new(); - encode_list(t, &mut out1); - - let v = t.to_vec(); - assert_eq!(out1.len(), v.length()); - - let mut out2 = BytesMut::new(); - v.encode(&mut out2); - assert_eq!(out1, out2); - - out1 - } - - fn encoded_iter<'a, T: Encodable + 'a>(iter: impl Iterator + Clone) -> BytesMut { - let mut out = BytesMut::new(); - encode_iter(iter, &mut out); - out - } - - #[test] - fn rlp_str() { - assert_eq!(encoded("")[..], hex!("80")[..]); - assert_eq!(encoded("{")[..], hex!("7b")[..]); - assert_eq!(encoded("test str")[..], hex!("887465737420737472")[..]); - } - - #[test] - fn rlp_strings() { - assert_eq!(encoded(hex!(""))[..], hex!("80")[..]); - assert_eq!(encoded(hex!("7B"))[..], hex!("7b")[..]); - assert_eq!(encoded(hex!("80"))[..], hex!("8180")[..]); - assert_eq!(encoded(hex!("ABBA"))[..], hex!("82abba")[..]); - } - - fn u8_fixtures() -> impl IntoIterator { - vec![ - (0, &hex!("80")[..]), - (1, &hex!("01")[..]), - (0x7F, &hex!("7F")[..]), - (0x80, &hex!("8180")[..]), - ] - } - - fn c>( - it: impl IntoIterator, - ) -> impl Iterator { - it.into_iter().map(|(k, v)| (k.into(), v)) - } - - fn u16_fixtures() -> impl IntoIterator { - c(u8_fixtures()).chain(vec![(0x400, &hex!("820400")[..])]) - } - - fn u32_fixtures() -> impl IntoIterator { - c(u16_fixtures()) - .chain(vec![(0xFFCCB5, &hex!("83ffccb5")[..]), (0xFFCCB5DD, &hex!("84ffccb5dd")[..])]) - } - - fn u64_fixtures() -> impl IntoIterator { - c(u32_fixtures()).chain(vec![ - (0xFFCCB5DDFF, &hex!("85ffccb5ddff")[..]), - (0xFFCCB5DDFFEE, &hex!("86ffccb5ddffee")[..]), - (0xFFCCB5DDFFEE14, &hex!("87ffccb5ddffee14")[..]), - (0xFFCCB5DDFFEE1483, &hex!("88ffccb5ddffee1483")[..]), - ]) - } - - fn u128_fixtures() -> impl IntoIterator { - c(u64_fixtures()).chain(vec![( - 0x10203E405060708090A0B0C0D0E0F2, - &hex!("8f10203e405060708090a0b0c0d0e0f2")[..], - )]) - } - - #[cfg(feature = "ethnum")] - fn u256_fixtures() -> impl IntoIterator { - c(u128_fixtures()).chain(vec![( - ethnum::U256::from_str_radix( - "0100020003000400050006000700080009000A0B4B000C000D000E01", - 16, - ) - .unwrap(), - &hex!("9c0100020003000400050006000700080009000a0b4b000c000d000e01")[..], - )]) - } - - #[cfg(feature = "ethereum-types")] - fn eth_u64_fixtures() -> impl IntoIterator { - c(u64_fixtures()).chain(vec![ - ( - ethereum_types::U64::from_str_radix("FFCCB5DDFF", 16).unwrap(), - &hex!("85ffccb5ddff")[..], - ), - ( - ethereum_types::U64::from_str_radix("FFCCB5DDFFEE", 16).unwrap(), - &hex!("86ffccb5ddffee")[..], - ), - ( - ethereum_types::U64::from_str_radix("FFCCB5DDFFEE14", 16).unwrap(), - &hex!("87ffccb5ddffee14")[..], - ), - ( - ethereum_types::U64::from_str_radix("FFCCB5DDFFEE1483", 16).unwrap(), - &hex!("88ffccb5ddffee1483")[..], - ), - ]) - } - - #[cfg(feature = "ethereum-types")] - fn eth_u128_fixtures() -> impl IntoIterator { - c(u128_fixtures()).chain(vec![( - ethereum_types::U128::from_str_radix("10203E405060708090A0B0C0D0E0F2", 16).unwrap(), - &hex!("8f10203e405060708090a0b0c0d0e0f2")[..], - )]) - } - - #[cfg(feature = "ethereum-types")] - fn eth_u256_fixtures() -> impl IntoIterator { - c(u128_fixtures()).chain(vec![( - ethereum_types::U256::from_str_radix( - "0100020003000400050006000700080009000A0B4B000C000D000E01", - 16, - ) - .unwrap(), - &hex!("9c0100020003000400050006000700080009000a0b4b000c000d000e01")[..], - )]) - } - - #[cfg(feature = "ethereum-types")] - fn eth_u512_fixtures() -> impl IntoIterator { - c(eth_u256_fixtures()).chain(vec![( - ethereum_types::U512::from_str_radix( - "0100020003000400050006000700080009000A0B4B000C000D000E010100020003000400050006000700080009000A0B4B000C000D000E01", - 16, - ) - .unwrap(), - &hex!("b8380100020003000400050006000700080009000A0B4B000C000D000E010100020003000400050006000700080009000A0B4B000C000D000E01")[..], - )]) - } - - macro_rules! uint_rlp_test { - ($fixtures:expr) => { - for (input, output) in $fixtures { - assert_eq!(encoded(input), output); - } - }; - } - - #[test] - fn rlp_uints() { - uint_rlp_test!(u8_fixtures()); - uint_rlp_test!(u16_fixtures()); - uint_rlp_test!(u32_fixtures()); - uint_rlp_test!(u64_fixtures()); - uint_rlp_test!(u128_fixtures()); - #[cfg(feature = "ethnum")] - uint_rlp_test!(u256_fixtures()); - } - - #[cfg(feature = "ethereum-types")] - #[test] - fn rlp_eth_uints() { - uint_rlp_test!(eth_u64_fixtures()); - uint_rlp_test!(eth_u128_fixtures()); - uint_rlp_test!(eth_u256_fixtures()); - uint_rlp_test!(eth_u512_fixtures()); - } - - #[test] - fn rlp_list() { - assert_eq!(encoded_list::(&[]), &hex!("c0")[..]); - assert_eq!(encoded_list::(&[0x00u8]), &hex!("c180")[..]); - assert_eq!(encoded_list(&[0xFFCCB5_u64, 0xFFC0B5_u64]), &hex!("c883ffccb583ffc0b5")[..]); - } - - #[test] - fn rlp_iter() { - assert_eq!(encoded_iter::([].iter()), &hex!("c0")[..]); - assert_eq!( - encoded_iter([0xFFCCB5_u64, 0xFFC0B5_u64].iter()), - &hex!("c883ffccb583ffc0b5")[..] - ); - } - - #[cfg(feature = "smol_str")] - #[test] - fn rlp_smol_str() { - use smol_str::SmolStr; - assert_eq!(encoded(SmolStr::new(""))[..], hex!("80")[..]); - let mut b = BytesMut::new(); - "test smol str".to_string().encode(&mut b); - assert_eq!(&encoded(SmolStr::new("test smol str"))[..], b.as_ref()); - let mut b = BytesMut::new(); - "abcdefgh".to_string().encode(&mut b); - assert_eq!(&encoded(SmolStr::new("abcdefgh"))[..], b.as_ref()); - } - - #[test] - fn to_be_bytes_trimmed() { - macro_rules! test_to_be_bytes_trimmed { - ($($x:expr => $expected:expr),+ $(,)?) => {$( - let be; - assert_eq!(to_be_bytes_trimmed!(be, $x), $expected); - )+}; - } - - test_to_be_bytes_trimmed! { - 0u8 => [], - 0u16 => [], - 0u32 => [], - 0u64 => [], - 0usize => [], - 0u128 => [], - - 1u8 => [1], - 1u16 => [1], - 1u32 => [1], - 1u64 => [1], - 1usize => [1], - 1u128 => [1], - - u8::MAX => [0xff], - u16::MAX => [0xff, 0xff], - u32::MAX => [0xff, 0xff, 0xff, 0xff], - u64::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], - u128::MAX => [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], - - 1u8 => [1], - 255u8 => [255], - 256u16 => [1, 0], - 65535u16 => [255, 255], - 65536u32 => [1, 0, 0], - 65536u64 => [1, 0, 0], - } - } -} diff --git a/crates/rlp/src/lib.rs b/crates/rlp/src/lib.rs deleted file mode 100644 index c9bf35e5c5b8..000000000000 --- a/crates/rlp/src/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -#![cfg_attr(docsrs, feature(doc_cfg))] -#![doc( - html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png", - html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256", - issue_tracker_base_url = "https://github.com/paradigmxzy/reth/issues/" -)] -#![warn(unreachable_pub)] -#![deny(unused_must_use)] -#![doc(test( - no_crate_inject, - attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) -))] -#![cfg_attr(not(feature = "std"), no_std)] - -//! A fast RLP implementation. -//! -//! ## Feature Flags -//! -//! This crate works on `#[no_std]` targets if `std` is not enabled. -//! -//! - `derive`: Enables derive macros. -//! - `std`: Uses the Rust standard library. - -#[cfg(feature = "alloc")] -extern crate alloc; - -mod decode; -mod encode; -mod types; - -pub use bytes::BufMut; - -pub use decode::{Decodable, DecodeError, Rlp}; -pub use encode::{ - const_add, encode_fixed_size, encode_iter, encode_list, length_of_length, list_length, - Encodable, MaxEncodedLen, MaxEncodedLenAssoc, -}; -pub use types::*; - -#[cfg(feature = "derive")] -pub use reth_rlp_derive::{ - RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper, RlpMaxEncodedLen, -}; diff --git a/crates/rlp/src/types.rs b/crates/rlp/src/types.rs deleted file mode 100644 index 4cbc6f10f636..000000000000 --- a/crates/rlp/src/types.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[derive(Debug, Clone, Default, PartialEq, Eq)] -pub struct Header { - pub list: bool, - pub payload_length: usize, -} - -pub const EMPTY_STRING_CODE: u8 = 0x80; -pub const EMPTY_LIST_CODE: u8 = 0xC0; diff --git a/crates/rlp/tests/rlp.rs b/crates/rlp/tests/rlp.rs deleted file mode 100644 index c7c3e52e4177..000000000000 --- a/crates/rlp/tests/rlp.rs +++ /dev/null @@ -1,135 +0,0 @@ -use bytes::{Bytes, BytesMut}; -use ethnum::U256; -use hex_literal::hex; -use reth_rlp::{DecodeError, *}; - -#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)] -struct Item { - a: Bytes, -} - -#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable, RlpMaxEncodedLen)] -struct Test4Numbers { - a: u8, - b: u64, - c: U256, - #[rlp(skip)] - #[rlp(default)] - s: U256, - d: U256, -} - -#[derive(Debug, PartialEq, RlpEncodableWrapper, RlpDecodableWrapper)] -pub struct W(Test4Numbers); - -#[derive(Debug, PartialEq, RlpEncodable)] -struct Test4NumbersGenerics<'a, D: Encodable> { - a: u8, - b: u64, - c: &'a U256, - d: &'a D, -} - -#[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)] -#[rlp(trailing)] -struct TestOpt { - a: u8, - b: u64, - c: Option, - d: Option, -} - -fn encoded(t: &T) -> BytesMut { - let mut out = BytesMut::new(); - t.encode(&mut out); - out -} - -#[test] -fn test_encode_item() { - let item = Item { a: b"dog".to_vec().into() }; - - let expected = vec![0xc4, 0x83, b'd', b'o', b'g']; - let out = encoded(&item); - assert_eq!(&*out, expected); - - let decoded = Decodable::decode(&mut &*expected).expect("decode failure"); - assert_eq!(item, decoded); - - let item = Test4Numbers { - a: 0x05, - b: 0xdeadbeefbaadcafe, - c: U256::from_be_bytes(hex!( - "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - )), - s: U256::from_be_bytes(hex!( - "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" - )), - d: U256::from_be_bytes(hex!( - "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" - )), - }; - - let expected = hex!("f84c0588deadbeefbaadcafea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").to_vec(); - let out = encoded(&item); - assert_eq!(&*out, expected); - - let out = reth_rlp::encode_fixed_size(&item); - assert_eq!(&*out, expected); - - let decoded: Test4Numbers = Decodable::decode(&mut &*expected).unwrap(); - assert_eq!(decoded.a, item.a); - assert_eq!(decoded.b, item.b); - assert_eq!(decoded.c, item.c); - assert_eq!(decoded.d, item.d); - assert_eq!(decoded.s, U256::ZERO); - - let mut rlp_view = Rlp::new(&expected).unwrap(); - assert_eq!(rlp_view.get_next().unwrap(), Some(item.a)); - assert_eq!(rlp_view.get_next().unwrap(), Some(item.b)); - assert_eq!(rlp_view.get_next().unwrap(), Some(item.c)); - assert_eq!(rlp_view.get_next().unwrap(), Some(item.d)); - assert_eq!(rlp_view.get_next::().unwrap(), None); - - assert_eq!( - encoded(&Test4NumbersGenerics { a: item.a, b: item.b, c: &item.c, d: &item.d }), - expected - ); - - assert_eq!(encoded(&W(item)), expected); - assert_eq!(W::decode(&mut &*expected).unwrap().0, decoded); - assert_eq!(Test4Numbers::LEN, 79); -} - -#[test] -fn invalid_decode_sideeffect() { - let fixture = hex!("f84d0588deadbeefbaadcafea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); - let mut sl: &[u8] = &fixture; - - assert_eq!(Test4Numbers::decode(&mut sl), Err(DecodeError::InputTooShort)); - - assert_eq!(sl.len(), fixture.len()); -} - -#[test] -fn test_opt_fields_roundtrip() { - let expected = hex!("c20102"); - let item = TestOpt { a: 1, b: 2, c: None, d: None }; - assert_eq!(&*encoded(&item), expected); - assert_eq!(TestOpt::decode(&mut &expected[..]).unwrap(), item); - - let expected = hex!("c3010203"); - let item = TestOpt { a: 1, b: 2, c: Some(3), d: None }; - assert_eq!(&*encoded(&item), expected); - assert_eq!(TestOpt::decode(&mut &expected[..]).unwrap(), item); - - let expected = hex!("c401020304"); - let item = TestOpt { a: 1, b: 2, c: Some(3), d: Some(4) }; - assert_eq!(&*encoded(&item), expected); - assert_eq!(TestOpt::decode(&mut &expected[..]).unwrap(), item); - - let expected = hex!("c401028004"); - let item = TestOpt { a: 1, b: 2, c: None, d: Some(4) }; - assert_eq!(&*encoded(&item), expected); - assert_eq!(TestOpt::decode(&mut &expected[..]).unwrap(), item); -} diff --git a/crates/rpc/rpc-engine-api/Cargo.toml b/crates/rpc/rpc-engine-api/Cargo.toml index 8570e610f35b..641b41cc0545 100644 --- a/crates/rpc/rpc-engine-api/Cargo.toml +++ b/crates/rpc/rpc-engine-api/Cargo.toml @@ -30,8 +30,8 @@ jsonrpsee-core.workspace = true tracing.workspace = true [dev-dependencies] -reth-rlp.workspace = true reth-interfaces = { workspace = true, features = ["test-utils"] } reth-provider = { workspace = true, features = ["test-utils"] } reth-payload-builder = { workspace = true, features = ["test-utils"] } +alloy-rlp.workspace = true assert_matches = "1.5.0" diff --git a/crates/rpc/rpc-engine-api/src/lib.rs b/crates/rpc/rpc-engine-api/src/lib.rs index ba36670c5aa3..d2e6c35f50cb 100644 --- a/crates/rpc/rpc-engine-api/src/lib.rs +++ b/crates/rpc/rpc-engine-api/src/lib.rs @@ -30,9 +30,6 @@ pub use message::EngineApiMessageVersion; // re-export server trait for convenience pub use reth_rpc_api::EngineApiServer; +// silence unused import warning #[cfg(test)] -#[allow(unused_imports)] -mod tests { - // silence unused import warning - use reth_rlp as _; -} +use alloy_rlp as _; diff --git a/crates/rpc/rpc-engine-api/tests/it/payload.rs b/crates/rpc/rpc-engine-api/tests/it/payload.rs index bc9f1f4249ae..ee763e1b12dc 100644 --- a/crates/rpc/rpc-engine-api/tests/it/payload.rs +++ b/crates/rpc/rpc-engine-api/tests/it/payload.rs @@ -1,5 +1,6 @@ //! Some payload tests +use alloy_rlp::{Decodable, Error}; use assert_matches::assert_matches; use reth_interfaces::test_utils::generators::{ self, random_block, random_block_range, random_header, @@ -9,7 +10,6 @@ use reth_primitives::{ proofs::{self}, Block, SealedBlock, TransactionSigned, H256, U256, }; -use reth_rlp::{Decodable, DecodeError}; use reth_rpc_types::engine::{ExecutionPayload, ExecutionPayloadBodyV1, PayloadError}; fn transform_block Block>(src: SealedBlock, f: F) -> ExecutionPayload { @@ -87,7 +87,7 @@ fn payload_validation() { }); assert_matches!( TryInto::::try_into(payload_with_invalid_txs), - Err(PayloadError::Decode(DecodeError::InputTooShort)) + Err(PayloadError::Decode(Error::InputTooShort)) ); // Non empty ommers diff --git a/crates/rpc/rpc-types-compat/Cargo.toml b/crates/rpc/rpc-types-compat/Cargo.toml index a7997e34102e..8affb2c6d43f 100644 --- a/crates/rpc/rpc-types-compat/Cargo.toml +++ b/crates/rpc/rpc-types-compat/Cargo.toml @@ -13,4 +13,4 @@ Compatibility layer for reth-primitives and ethereum RPC types [dependencies] reth-primitives.workspace = true reth-rpc-types.workspace = true -reth-rlp.workspace = true +alloy-rlp.workspace = true diff --git a/crates/rpc/rpc-types-compat/src/block.rs b/crates/rpc/rpc-types-compat/src/block.rs index 6551124d9f74..6bebb6c70583 100644 --- a/crates/rpc/rpc-types-compat/src/block.rs +++ b/crates/rpc/rpc-types-compat/src/block.rs @@ -1,8 +1,8 @@ //! Compatibility functions for rpc `Block` type. use crate::transaction::from_recovered_with_block_context; +use alloy_rlp::Encodable; use reth_primitives::{Block as PrimitiveBlock, Header as PrimitiveHeader, H256, U256}; -use reth_rlp::Encodable; use reth_rpc_types::{Block, BlockError, BlockTransactions, BlockTransactionsKind, Header}; /// Converts the given primitive block into a [Block] response with the given diff --git a/crates/rpc/rpc-types/Cargo.toml b/crates/rpc/rpc-types/Cargo.toml index 3cce6c1a8417..ab223298de2c 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -13,15 +13,14 @@ Reth RPC types [dependencies] # reth reth-primitives.workspace = true -reth-rlp.workspace = true -# errors -thiserror.workspace = true # misc +alloy-rlp.workspace = true itertools.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true jsonrpsee-types = { workspace = true, optional = true } +thiserror.workspace = true [features] default = ["jsonrpsee-types"] diff --git a/crates/rpc/rpc-types/src/eth/block.rs b/crates/rpc/rpc-types/src/eth/block.rs index 5588d55611f6..474aa16b16fd 100644 --- a/crates/rpc/rpc-types/src/eth/block.rs +++ b/crates/rpc/rpc-types/src/eth/block.rs @@ -1,5 +1,6 @@ //! Contains types that represent ethereum types in [reth_primitives] when used in RPC use crate::Transaction; +use alloy_rlp::Encodable; use reth_primitives::{ Address, Bloom, Bytes, Header as PrimitiveHeader, SealedHeader, Withdrawal, H256, H64, U256, U64, @@ -56,7 +57,7 @@ pub enum BlockError { InvalidSignature, /// A raw block failed to decode #[error("failed to decode raw block {0}")] - RlpDecodeRawBlock(reth_rlp::DecodeError), + RlpDecodeRawBlock(alloy_rlp::Error), } /// Block representation diff --git a/crates/rpc/rpc-types/src/eth/engine/payload.rs b/crates/rpc/rpc-types/src/eth/engine/payload.rs index d63e0817e183..65ed7b907185 100644 --- a/crates/rpc/rpc-types/src/eth/engine/payload.rs +++ b/crates/rpc/rpc-types/src/eth/engine/payload.rs @@ -1,10 +1,10 @@ +use alloy_rlp::Decodable; use reth_primitives::{ constants::{MAXIMUM_EXTRA_DATA_SIZE, MIN_PROTOCOL_BASE_FEE_U256}, proofs::{self, EMPTY_LIST_HASH}, Address, Block, Bloom, Bytes, Header, SealedBlock, TransactionSigned, UintTryTo, Withdrawal, H256, H64, U256, U64, }; -use reth_rlp::Decodable; use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer}; /// The execution payload body response that allows for `null` values. @@ -232,7 +232,7 @@ pub enum PayloadError { }, /// Encountered decoding error. #[error(transparent)] - Decode(#[from] reth_rlp::DecodeError), + Decode(#[from] alloy_rlp::Error), } impl PayloadError { diff --git a/crates/rpc/rpc-types/src/eth/transaction/typed.rs b/crates/rpc/rpc-types/src/eth/transaction/typed.rs index a87e1f4345c6..8ba14bc357ae 100644 --- a/crates/rpc/rpc-types/src/eth/transaction/typed.rs +++ b/crates/rpc/rpc-types/src/eth/transaction/typed.rs @@ -3,10 +3,10 @@ //! transaction deserialized from the json input of an RPC call. Depending on what fields are set, //! it can be converted into the container type [`TypedTransactionRequest`]. +use alloy_rlp::{BufMut, Decodable, Encodable, Error as RlpError, RlpDecodable, RlpEncodable}; use reth_primitives::{ - AccessList, Address, Bytes, Transaction, TxEip1559, TxEip2930, TxLegacy, U128, U256, + AccessList, Address, Bytes, Transaction, TxEip1559, TxEip2930, TxLegacy, H160, U128, U256, }; -use reth_rlp::{BufMut, Decodable, DecodeError, Encodable, RlpDecodable, RlpEncodable}; use serde::{Deserialize, Serialize}; /// Container type for various Ethereum transaction requests @@ -140,17 +140,16 @@ impl Encodable for TransactionKind { } impl Decodable for TransactionKind { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { if let Some(&first) = buf.first() { if first == 0x80 { *buf = &buf[1..]; Ok(TransactionKind::Create) } else { - let addr =
::decode(buf)?; - Ok(TransactionKind::Call(addr)) + Ok(TransactionKind::Call(H160(Decodable::decode(buf)?))) } } else { - Err(DecodeError::InputTooShort) + Err(RlpError::InputTooShort) } } } diff --git a/crates/rpc/rpc/Cargo.toml b/crates/rpc/rpc/Cargo.toml index 756fefd8a1e3..36bfe35aa592 100644 --- a/crates/rpc/rpc/Cargo.toml +++ b/crates/rpc/rpc/Cargo.toml @@ -14,7 +14,6 @@ Reth RPC implementation reth-interfaces.workspace = true reth-primitives.workspace = true reth-rpc-api = { path = "../rpc-api" } -reth-rlp.workspace = true reth-rpc-types.workspace = true reth-provider = { workspace = true, features = ["test-utils"] } reth-transaction-pool = { workspace = true, features = ["test-utils"] } @@ -27,6 +26,7 @@ reth-consensus-common = { path = "../../consensus/common" } reth-rpc-types-compat.workspace = true # eth +alloy-rlp.workspace = true revm = { workspace = true, features = [ "optional_block_gas_limit", "optional_eip3607", diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index cf7a98b74549..fcab2f71c779 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -10,6 +10,7 @@ use crate::{ result::{internal_rpc_err, ToRpcResult}, EthApiSpec, TracingCallGuard, }; +use alloy_rlp::{Decodable, Encodable}; use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_primitives::{Account, Block, BlockId, BlockNumberOrTag, Bytes, TransactionSigned, H256}; @@ -22,7 +23,6 @@ use reth_revm::{ FourByteInspector, TracingInspector, TracingInspectorConfig, }, }; -use reth_rlp::{Decodable, Encodable}; use reth_rpc_api::DebugApiServer; use reth_rpc_types::{ state::StateOverride, diff --git a/crates/stages/Cargo.toml b/crates/stages/Cargo.toml index 960ca15aa572..cd41e951566c 100644 --- a/crates/stages/Cargo.toml +++ b/crates/stages/Cargo.toml @@ -52,10 +52,10 @@ reth-interfaces = { workspace = true, features = ["test-utils"] } reth-downloaders = { path = "../net/downloaders" } reth-eth-wire = { path = "../net/eth-wire" } # TODO(onbjerg): We only need this for [BlockBody] reth-blockchain-tree = { path = "../blockchain-tree" } -reth-rlp.workspace = true reth-revm = { path = "../revm" } reth-trie = { path = "../trie", features = ["test-utils"] } +alloy-rlp.workspace = true itertools.workspace = true tokio = { workspace = true, features = ["rt", "sync", "macros"] } assert_matches = "1.5.0" diff --git a/crates/stages/src/stages/execution.rs b/crates/stages/src/stages/execution.rs index 2d0332a2ade0..5aaf48686840 100644 --- a/crates/stages/src/stages/execution.rs +++ b/crates/stages/src/stages/execution.rs @@ -469,6 +469,7 @@ impl ExecutionStageThresholds { mod tests { use super::*; use crate::test_utils::TestTransaction; + use alloy_rlp::Decodable; use assert_matches::assert_matches; use reth_db::{models::AccountBeforeTx, test_utils::create_test_rw_db}; use reth_primitives::{ @@ -477,7 +478,6 @@ mod tests { }; use reth_provider::{AccountReader, BlockWriter, ProviderFactory, ReceiptProvider}; use reth_revm::Factory; - use reth_rlp::Decodable; use std::sync::Arc; fn stage() -> ExecutionStage { diff --git a/crates/stages/src/stages/mod.rs b/crates/stages/src/stages/mod.rs index 777041fbcac1..315f1a26c664 100644 --- a/crates/stages/src/stages/mod.rs +++ b/crates/stages/src/stages/mod.rs @@ -45,6 +45,7 @@ mod tests { test_utils::TestTransaction, ExecInput, }; + use alloy_rlp::Decodable; use reth_db::{ cursor::DbCursorRO, mdbx::{cursor::Cursor, RW}, @@ -62,7 +63,6 @@ mod tests { StorageReader, }; use reth_revm::Factory; - use reth_rlp::Decodable; use std::sync::Arc; #[tokio::test] diff --git a/crates/storage/codecs/derive/src/arbitrary.rs b/crates/storage/codecs/derive/src/arbitrary.rs index 82d35c6e624c..0768aa7c70dc 100644 --- a/crates/storage/codecs/derive/src/arbitrary.rs +++ b/crates/storage/codecs/derive/src/arbitrary.rs @@ -30,7 +30,7 @@ pub fn maybe_generate_tests(args: TokenStream, ast: &DeriveInput) -> TokenStream } }); } else if arg.to_string() == "rlp" { - traits.push(quote! { use reth_rlp::{Encodable, Decodable}; }); + traits.push(quote! { use alloy_rlp::{Encodable, Decodable}; }); roundtrips.push(quote! { { let mut buf = vec![]; @@ -64,7 +64,7 @@ pub fn maybe_generate_tests(args: TokenStream, ast: &DeriveInput) -> TokenStream // malformed rlp-header check let mut decode_buf = &mut buf.as_slice(); - let mut header = reth_rlp::Header::decode(decode_buf).expect("failed to decode header"); + let mut header = alloy_rlp::Header::decode(decode_buf).expect("failed to decode header"); header.payload_length+=1; let mut b = Vec::with_capacity(decode_buf.len()); header.encode(&mut b); diff --git a/crates/storage/provider/Cargo.toml b/crates/storage/provider/Cargo.toml index 62ceb6fa182a..bac64f11ccf7 100644 --- a/crates/storage/provider/Cargo.toml +++ b/crates/storage/provider/Cargo.toml @@ -31,15 +31,15 @@ derive_more = "0.99" parking_lot = "0.12" # test-utils -reth-rlp = { workspace = true, optional = true } +alloy-rlp = { workspace = true, optional = true } [dev-dependencies] reth-db = { path = "../db", features = ["test-utils"] } reth-primitives = { workspace = true, features = ["arbitrary", "test-utils"] } -reth-rlp.workspace = true reth-trie = { path = "../../trie", features = ["test-utils"] } +alloy-rlp.workspace = true parking_lot = "0.12" tempfile = "3.3" [features] -test-utils = ["reth-rlp"] +test-utils = ["dep:alloy-rlp"] diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 7df40d45e00c..3b0e289233df 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -1,12 +1,12 @@ //! Dummy blocks and data for tests use crate::{post_state::PostState, DatabaseProviderRW}; +use alloy_rlp::Decodable; use reth_db::{database::Database, models::StoredBlockBodyIndices, tables}; use reth_primitives::{ hex_literal::hex, Account, BlockNumber, Bytes, Header, Log, Receipt, SealedBlock, SealedBlockWithSenders, TxType, Withdrawal, H160, H256, U256, }; -use reth_rlp::Decodable; use std::collections::BTreeMap; /// Assert genesis block diff --git a/crates/transaction-pool/Cargo.toml b/crates/transaction-pool/Cargo.toml index 5cf13b257542..068d8038f5a5 100644 --- a/crates/transaction-pool/Cargo.toml +++ b/crates/transaction-pool/Cargo.toml @@ -21,7 +21,6 @@ normal = [ reth-primitives.workspace = true reth-provider.workspace = true reth-interfaces.workspace = true -reth-rlp.workspace = true reth-metrics.workspace = true reth-tasks.workspace = true @@ -33,6 +32,7 @@ tokio = { workspace = true, default-features = false, features = ["sync"] } tokio-stream.workspace = true # misc +alloy-rlp.workspace = true aquamarine = "0.3.0" thiserror.workspace = true tracing.workspace = true diff --git a/crates/transaction-pool/src/traits.rs b/crates/transaction-pool/src/traits.rs index 7d07a72a8759..0ad9e2d6504d 100644 --- a/crates/transaction-pool/src/traits.rs +++ b/crates/transaction-pool/src/traits.rs @@ -4,12 +4,12 @@ use crate::{ validate::ValidPoolTransaction, AllTransactionsEvents, }; +use alloy_rlp::Encodable; use futures_util::{ready, Stream}; use reth_primitives::{ Address, FromRecoveredTransaction, IntoRecoveredTransaction, PeerId, Transaction, TransactionKind, TransactionSignedEcRecovered, TxHash, EIP1559_TX_TYPE_ID, H256, U256, }; -use reth_rlp::Encodable; use std::{ collections::{HashMap, HashSet}, fmt, diff --git a/crates/trie/Cargo.toml b/crates/trie/Cargo.toml index 3c37d4295e8e..075f78e71a8f 100644 --- a/crates/trie/Cargo.toml +++ b/crates/trie/Cargo.toml @@ -14,16 +14,11 @@ Merkle trie implementation # reth reth-primitives.workspace = true reth-interfaces.workspace = true -reth-rlp.workspace = true reth-db = { path = "../storage/db" } -# tokio +alloy-rlp.workspace = true tokio = { workspace = true, default-features = false, features = ["sync"] } - -# tracing tracing.workspace = true - -# misc hex = "0.4" thiserror.workspace = true derive_more = "0.99" diff --git a/crates/trie/src/account.rs b/crates/trie/src/account.rs index 88307168a03c..29ce5d47ccb5 100644 --- a/crates/trie/src/account.rs +++ b/crates/trie/src/account.rs @@ -1,5 +1,5 @@ +use alloy_rlp::{RlpDecodable, RlpEncodable}; use reth_primitives::{proofs::EMPTY_ROOT, Account, H256, KECCAK_EMPTY, U256}; -use reth_rlp::{RlpDecodable, RlpEncodable}; /// An Ethereum account as represented in the trie. #[derive(Clone, Copy, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] diff --git a/crates/trie/src/test_utils.rs b/crates/trie/src/test_utils.rs index 690514acdfe3..44dbbd8ea0b0 100644 --- a/crates/trie/src/test_utils.rs +++ b/crates/trie/src/test_utils.rs @@ -1,6 +1,6 @@ use crate::account::EthAccount; +use alloy_rlp::{encode_fixed_size, Encodable}; use reth_primitives::{proofs::KeccakHasher, Account, Address, H256, U256}; -use reth_rlp::{encode_fixed_size, Encodable}; /// Re-export of [triehash]. pub use triehash; diff --git a/crates/trie/src/trie.rs b/crates/trie/src/trie.rs index cc443d668009..a3f60e727930 100644 --- a/crates/trie/src/trie.rs +++ b/crates/trie/src/trie.rs @@ -8,6 +8,7 @@ use crate::{ walker::TrieWalker, StateRootError, StorageRootError, }; +use alloy_rlp::Encodable; use reth_db::{tables, transaction::DbTx}; use reth_primitives::{ keccak256, @@ -15,7 +16,6 @@ use reth_primitives::{ trie::{HashBuilder, Nibbles}, Address, BlockNumber, StorageEntry, H256, }; -use reth_rlp::Encodable; use std::{ collections::{HashMap, HashSet}, ops::RangeInclusive, @@ -513,7 +513,7 @@ where } } hash_builder - .add_leaf(storage_key_nibbles, reth_rlp::encode_fixed_size(&value).as_ref()); + .add_leaf(storage_key_nibbles, alloy_rlp::encode_fixed_size(&value).as_ref()); storage = hashed_storage_cursor.next()?; } } @@ -1325,7 +1325,7 @@ mod tests { hex!("3100000000000000000000000000000000000000000000000000000000000000"), ] { hashed_storage.upsert(hashed_address, StorageEntry { key: H256(key), value }).unwrap(); - hb.add_leaf(Nibbles::unpack(key), &reth_rlp::encode_fixed_size(&value)); + hb.add_leaf(Nibbles::unpack(key), &alloy_rlp::encode_fixed_size(&value)); } let root = hb.root(); diff --git a/docs/crates/eth-wire.md b/docs/crates/eth-wire.md index 0c216644fce4..a908e1a92908 100644 --- a/docs/crates/eth-wire.md +++ b/docs/crates/eth-wire.md @@ -65,7 +65,7 @@ These traits are defined as follows: [Crate: crates/common/rlp](https://github.com/paradigmxyz/reth/blob/main/crates/common/rlp) ```rust, ignore pub trait Decodable: Sized { - fn decode(buf: &mut &[u8]) -> Result; + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result; } pub trait Encodable { fn encode(&self, out: &mut dyn BufMut); @@ -73,7 +73,7 @@ pub trait Encodable { } ``` These traits describe how the `Ethmessage` should be serialized/deserialized into raw bytes using the RLP format. -In reth all [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) encode/decode operations are handled by the `common/rlp` and `common/rlp-derive` crates. +In reth all [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) encode/decode operations are handled by the [`alloy-rlp`](https://github.com/alloy-rs/rlp) crate. Note that the `ProtocolMessage` itself implements these traits, so any stream of bytes can be converted into it by calling `ProtocolMessage::decode()` and vice versa with `ProtocolMessage::encode()`. The message type is determined by the first byte of the byte stream. @@ -127,11 +127,11 @@ impl Encodable for TransactionSigned { } impl Decodable for TransactionSigned { - fn decode(buf: &mut &[u8]) -> Result { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { // Implementation omitted for brevity //... } - +} ``` Now that we know how the types work, let's take a look at how these are utilized in the network. diff --git a/docs/repo/layout.md b/docs/repo/layout.md index 8418518fb4d2..519ac27c0420 100644 --- a/docs/repo/layout.md +++ b/docs/repo/layout.md @@ -128,11 +128,9 @@ Crates related to building and validating payloads (blocks). ### Primitives -These crates define primitive types or algorithms such as RLP. +These crates define primitive types or data structures such as the Merkle Patricia Tree. - [`primitives`](../../crates/primitives): Commonly used types in Reth. -- [`rlp`](../../crates/rlp): An implementation of RLP, forked from an earlier Apache-licensed version of [`fastrlp`][fastrlp] -- [`rlp/rlp-derive`](../../crates/rlp/rlp-derive): Forked from an earlier Apache licenced version of the [`fastrlp-derive`][fastrlp-derive] crate, before it changed licence to GPL. - [`trie`](../../crates/trie): An implementation of a Merkle Patricia Trie used for various roots (e.g. the state root) in Ethereum. ### Misc @@ -146,10 +144,9 @@ Small utility crates. - [`tracing`](../../crates/tracing): A small utility crate to install a uniform [`tracing`][tracing] subscriber [fastrlp]: https://crates.io/crates/fastrlp -[fastrlp-derive]: https://crates.io/crates/fastrlp-derive [libmdbx-rs]: https://crates.io/crates/libmdbx [discv4]: https://github.com/ethereum/devp2p/blob/master/discv4.md [jsonrpsee]: https://github.com/paritytech/jsonrpsee/ [tracing]: https://crates.io/crates/tracing [eip-1459]: https://eips.ethereum.org/EIPS/eip-1459 -[engine-spec]: https://github.com/ethereum/execution-apis/tree/main/src/engine \ No newline at end of file +[engine-spec]: https://github.com/ethereum/execution-apis/tree/main/src/engine diff --git a/testing/ef-tests/Cargo.toml b/testing/ef-tests/Cargo.toml index 7145273a9310..54bf521a2af1 100644 --- a/testing/ef-tests/Cargo.toml +++ b/testing/ef-tests/Cargo.toml @@ -16,11 +16,11 @@ reth-primitives.workspace = true reth-db = { path = "../../crates/storage/db", features = ["mdbx", "test-utils"] } reth-provider.workspace = true reth-stages = { path = "../../crates/stages" } -reth-rlp.workspace = true reth-interfaces.workspace = true reth-revm = { path = "../../crates/revm" } +alloy-rlp.workspace = true tokio = "1.28.1" walkdir = "2.3.3" serde = "1.0.163" serde_json.workspace = true -thiserror.workspace = true \ No newline at end of file +thiserror.workspace = true diff --git a/testing/ef-tests/src/cases/blockchain_test.rs b/testing/ef-tests/src/cases/blockchain_test.rs index e2f7fc8ac65d..6103f94f82f1 100644 --- a/testing/ef-tests/src/cases/blockchain_test.rs +++ b/testing/ef-tests/src/cases/blockchain_test.rs @@ -4,10 +4,10 @@ use crate::{ models::{BlockchainTest, ForkSpec, RootOrState}, Case, Error, Suite, }; +use alloy_rlp::Decodable; use reth_db::test_utils::create_test_rw_db; use reth_primitives::{BlockBody, SealedBlock}; use reth_provider::{BlockWriter, ProviderFactory}; -use reth_rlp::Decodable; use reth_stages::{stages::ExecutionStage, ExecInput, Stage}; use std::{collections::BTreeMap, ffi::OsStr, fs, path::Path, sync::Arc}; diff --git a/testing/ef-tests/src/result.rs b/testing/ef-tests/src/result.rs index 5aaf58a9e8bc..3e3821809da7 100644 --- a/testing/ef-tests/src/result.rs +++ b/testing/ef-tests/src/result.rs @@ -43,7 +43,7 @@ pub enum Error { RethError(#[from] reth_interfaces::Error), /// An error occurred while decoding RLP. #[error("An error occurred deserializing RLP")] - RlpDecodeError(#[from] reth_rlp::DecodeError), + RlpDecodeError(#[from] alloy_rlp::Error), } /// The result of running a test.