diff --git a/Cargo.lock b/Cargo.lock index 2f8c89b2d..4a9aecd48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,7 +400,7 @@ dependencies = [ "chrono", "elliptic-curve", "ethabi", - "fastrlp", + "fastrlp 0.1.3", "generic-array", "hex", "k256", @@ -438,6 +438,17 @@ dependencies = [ "fastrlp-derive", ] +[[package]] +name = "fastrlp" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9244dd9f0a2b54815814926640439146f469837ec4141e33354b6b258a0493" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "fastrlp-derive" version = "0.1.2" @@ -1434,6 +1445,7 @@ version = "0.1.0" dependencies = [ "bytes", "ethers-core", + "fastrlp 0.2.0", ] [[package]] @@ -1461,7 +1473,7 @@ dependencies = [ name = "reth-rpc-types" version = "0.1.0" dependencies = [ - "fastrlp", + "fastrlp 0.1.3", "reth-primitives", "serde", "serde_json", diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 3a4307661..3157934d1 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -8,5 +8,6 @@ readme = "README.md" description = "Commonly used types in reth." [dependencies] +fastrlp = { version = "0.2.0" } ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false } bytes = "1.2" \ No newline at end of file diff --git a/crates/primitives/src/chain.rs b/crates/primitives/src/chain.rs new file mode 100644 index 000000000..3dfe8175a --- /dev/null +++ b/crates/primitives/src/chain.rs @@ -0,0 +1,138 @@ +use crate::U256; +use ethers_core::types::{ParseChainError, U64}; +use fastrlp::{Decodable, Encodable}; +use std::{fmt, str::FromStr}; + +/// Either a named or chain id or the actual id value +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Chain { + /// Contains a known chain + Named(ethers_core::types::Chain), + /// Contains the id of a chain + Id(u64), +} + +impl Chain { + /// The id of the chain + pub fn id(&self) -> u64 { + match self { + Chain::Named(chain) => *chain as u64, + Chain::Id(id) => *id, + } + } + + /// Helper function for checking if a chainid corresponds to a legacy chainid + /// without eip1559 + pub fn is_legacy(&self) -> bool { + match self { + Chain::Named(c) => c.is_legacy(), + Chain::Id(_) => false, + } + } +} + +impl fmt::Display for Chain { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Chain::Named(chain) => chain.fmt(f), + Chain::Id(id) => { + if let Ok(chain) = ethers_core::types::Chain::try_from(*id) { + chain.fmt(f) + } else { + id.fmt(f) + } + } + } + } +} + +impl From for Chain { + fn from(id: ethers_core::types::Chain) -> Self { + Chain::Named(id) + } +} + +impl From for Chain { + fn from(id: u64) -> Self { + ethers_core::types::Chain::try_from(id).map(Chain::Named).unwrap_or_else(|_| Chain::Id(id)) + } +} + +impl From for Chain { + fn from(id: U256) -> Self { + id.as_u64().into() + } +} + +impl From for u64 { + fn from(c: Chain) -> Self { + match c { + Chain::Named(c) => c as u64, + Chain::Id(id) => id, + } + } +} + +impl From for U64 { + fn from(c: Chain) -> Self { + u64::from(c).into() + } +} + +impl From for U256 { + fn from(c: Chain) -> Self { + u64::from(c).into() + } +} + +impl TryFrom for ethers_core::types::Chain { + type Error = ParseChainError; + + fn try_from(chain: Chain) -> Result { + match chain { + Chain::Named(chain) => Ok(chain), + Chain::Id(id) => id.try_into(), + } + } +} + +impl FromStr for Chain { + type Err = String; + + fn from_str(s: &str) -> Result { + if let Ok(chain) = ethers_core::types::Chain::from_str(s) { + Ok(Chain::Named(chain)) + } else { + s.parse::() + .map(Chain::Id) + .map_err(|_| format!("Expected known chain or integer, found: {s}")) + } + } +} + +impl Encodable for Chain { + fn length(&self) -> usize { + match self { + Self::Named(chain) => u64::from(*chain).length(), + Self::Id(id) => id.length(), + } + } + fn encode(&self, out: &mut dyn fastrlp::BufMut) { + match self { + Self::Named(chain) => u64::from(*chain).encode(out), + Self::Id(id) => id.encode(out), + } + } +} + +impl Decodable for Chain { + fn decode(buf: &mut &[u8]) -> Result { + Ok(u64::decode(buf)?.into()) + } +} + +impl Default for Chain { + fn default() -> Self { + ethers_core::types::Chain::Mainnet.into() + } +} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index e6d3a8c3a..c767103ea 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -8,6 +8,7 @@ //! Commonly used types in reth. mod block; +mod chain; mod header; mod log; mod receipt;