refactor: phase out ether genesis in primitives (#2311)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Aditya Pandey
2023-06-16 20:10:02 +05:30
committed by GitHub
parent b90d0b4106
commit 3ace10d835
7 changed files with 1040 additions and 72 deletions

View File

@ -3,17 +3,13 @@ use crate::{
forkid::ForkFilterKey,
header::Head,
proofs::genesis_state_root,
BlockNumber, Chain, ForkFilter, ForkHash, ForkId, Genesis, GenesisAccount, Hardfork, Header,
SealedHeader, H160, H256, U256,
BlockNumber, Chain, ForkFilter, ForkHash, ForkId, Genesis, Hardfork, Header, SealedHeader,
H256, U256,
};
use ethers_core::utils::Genesis as EthersGenesis;
use hex_literal::hex;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
use std::{collections::BTreeMap, sync::Arc};
/// The Ethereum mainnet spec
pub static MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
@ -316,25 +312,8 @@ impl ChainSpec {
}
}
impl From<EthersGenesis> for ChainSpec {
fn from(genesis: EthersGenesis) -> Self {
let alloc = genesis
.alloc
.iter()
.map(|(addr, account)| (addr.0.into(), account.clone().into()))
.collect::<HashMap<H160, GenesisAccount>>();
let genesis_block = Genesis {
nonce: genesis.nonce.as_u64(),
timestamp: genesis.timestamp.as_u64(),
gas_limit: genesis.gas_limit.as_u64(),
difficulty: genesis.difficulty.into(),
mix_hash: genesis.mix_hash.0.into(),
coinbase: genesis.coinbase.0.into(),
extra_data: genesis.extra_data.0.into(),
alloc,
};
impl From<Genesis> for ChainSpec {
fn from(genesis: Genesis) -> Self {
// Block-based hardforks
let hardfork_opts = vec![
(Hardfork::Homestead, genesis.config.homestead_block),
@ -361,7 +340,7 @@ impl From<EthersGenesis> for ChainSpec {
hardforks.insert(
Hardfork::Paris,
ForkCondition::TTD {
total_difficulty: ttd.into(),
total_difficulty: ttd,
fork_block: genesis.config.merge_netsplit_block,
},
);
@ -379,7 +358,7 @@ impl From<EthersGenesis> for ChainSpec {
Self {
chain: genesis.config.chain_id.into(),
genesis: genesis_block,
genesis,
genesis_hash: None,
fork_timestamps: ForkTimestamps::from_hardforks(&hardforks),
hardforks,
@ -417,21 +396,26 @@ impl ForkTimestamps {
#[serde(untagged)]
pub enum AllGenesisFormats {
/// The geth genesis format
Geth(EthersGenesis),
Geth(Genesis),
/// The reth genesis format
Reth(ChainSpec),
}
impl From<EthersGenesis> for AllGenesisFormats {
fn from(genesis: EthersGenesis) -> Self {
impl From<Genesis> for AllGenesisFormats {
fn from(genesis: Genesis) -> Self {
Self::Geth(genesis)
}
}
impl From<ChainSpec> for AllGenesisFormats {
fn from(genesis: ChainSpec) -> Self {
Self::Reth(genesis)
}
}
impl From<Arc<ChainSpec>> for AllGenesisFormats {
fn from(mut genesis: Arc<ChainSpec>) -> Self {
let cloned_genesis = Arc::make_mut(&mut genesis).clone();
Self::Reth(cloned_genesis)
fn from(genesis: Arc<ChainSpec>) -> Self {
Arc::try_unwrap(genesis).unwrap_or_else(|arc| (*arc).clone()).into()
}
}
@ -1195,7 +1179,7 @@ mod tests {
}
"#;
let genesis: ethers_core::utils::Genesis = serde_json::from_str(geth_genesis).unwrap();
let genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
let chainspec = ChainSpec::from(genesis);
// assert a bunch of hardforks that should be set
@ -1334,6 +1318,8 @@ mod tests {
}
}
"#;
let _genesis = serde_json::from_str::<Genesis>(hive_json).unwrap();
let genesis = serde_json::from_str::<AllGenesisFormats>(hive_json).unwrap();
let chainspec: ChainSpec = genesis.into();
assert_eq!(chainspec.genesis_hash, None);

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ use serde::{
};
use std::{fmt, str::FromStr};
/// Wrapper around primitive U256 type to handle edge cases of json parser
/// Wrapper around primitive U256 type that also supports deserializing numbers
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct JsonU256(pub U256);
@ -90,6 +90,15 @@ where
Ok(num.into())
}
/// Supports parsing `U256` numbers as strings via [JsonU256]
pub fn deserialize_json_u256_opt<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
where
D: Deserializer<'de>,
{
let num = Option::<JsonU256>::deserialize(deserializer)?;
Ok(num.map(Into::into))
}
#[cfg(test)]
mod test {
use super::JsonU256;

View File

@ -1,9 +1,9 @@
//! Various serde utilities
mod storage_key;
mod storage;
use serde::Serializer;
pub use storage_key::*;
pub use storage::*;
mod jsonu256;
use crate::H256;

View File

@ -1,6 +1,6 @@
use crate::{H256, U256};
use serde::{Deserialize, Serialize};
use std::fmt::Write;
use crate::{Bytes, H256, U256};
use serde::{Deserialize, Deserializer, Serialize};
use std::{collections::HashMap, fmt::Write};
/// A storage key type that can be serialized to and from a hex string up to 32 bytes. Used for
/// `eth_getStorageAt` and `eth_getProof` RPCs.
@ -53,3 +53,50 @@ impl From<JsonStorageKey> for String {
hex
}
}
/// Converts a Bytes value into a H256, accepting inputs that are less than 32 bytes long. These
/// inputs will be left padded with zeros.
pub fn from_bytes_to_h256<'de, D>(bytes: Bytes) -> Result<H256, D::Error>
where
D: Deserializer<'de>,
{
if bytes.0.len() > 32 {
return Err(serde::de::Error::custom("input too long to be a H256"))
}
// left pad with zeros to 32 bytes
let mut padded = [0u8; 32];
padded[32 - bytes.0.len()..].copy_from_slice(&bytes.0);
// then convert to H256 without a panic
Ok(H256::from_slice(&padded))
}
/// Deserializes the input into an Option<HashMap<H256, H256>>, using [from_bytes_to_h256] which
/// allows cropped values:
///
/// ```json
/// {
/// "0x0000000000000000000000000000000000000000000000000000000000000001": "0x22"
/// }
/// ```
pub fn deserialize_storage_map<'de, D>(
deserializer: D,
) -> Result<Option<HashMap<H256, H256>>, D::Error>
where
D: Deserializer<'de>,
{
let map = Option::<HashMap<Bytes, Bytes>>::deserialize(deserializer)?;
match map {
Some(mut map) => {
let mut res_map = HashMap::with_capacity(map.len());
for (k, v) in map.drain() {
let k_deserialized = from_bytes_to_h256::<'de, D>(k)?;
let v_deserialized = from_bytes_to_h256::<'de, D>(v)?;
res_map.insert(k_deserialized, v_deserialized);
}
Ok(Some(res_map))
}
None => Ok(None),
}
}