Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: reuse alloy genesis in bindings #139

Merged
merged 2 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/genesis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ alloy-rpc-types.workspace = true
serde.workspace = true

[dev-dependencies]
serde_json.workspace = true
serde_json.workspace = true
1 change: 1 addition & 0 deletions crates/genesis/dumpgenesis/holesky.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crates/genesis/dumpgenesis/mainnet.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crates/genesis/dumpgenesis/sepolia.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"config":{"chainId":11155111,"homesteadBlock":0,"daoForkSupport":true,"eip150Block":0,"eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"berlinBlock":0,"londonBlock":0,"mergeNetsplitBlock":1735371,"shanghaiTime":1677557088,"terminalTotalDifficulty":17000000000000000,"terminalTotalDifficultyPassed":true,"ethash":{}},"nonce":"0x0","timestamp":"0x6159af19","extraData":"0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521","gasLimit":"0x1c9c380","difficulty":"0x20000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","alloc":{"0000006916a87b82333f4245046623b23794c65c":{"balance":"0x84595161401484a000000"},"10f5d45854e038071485ac9e402308cf80d2d2fe":{"balance":"0x52b7d2dcc80cd2e4000000"},"799d329e5f583419167cd722962485926e338f4a":{"balance":"0xde0b6b3a7640000"},"7cf5b79bfe291a67ab02b393e456ccc4c266f753":{"balance":"0xd3c21bcecceda1000000"},"8b7f0977bb4f0fbe7076fa22bc24aca043583f5e":{"balance":"0xd3c21bcecceda1000000"},"a2a6d93439144ffe4d27c9e088dcd8b783946263":{"balance":"0xd3c21bcecceda1000000"},"aaec86394441f915bce3e6ab399977e9906f3b69":{"balance":"0xd3c21bcecceda1000000"},"b21c33de1fab3fa15499c62b59fe0cc3250020d1":{"balance":"0x52b7d2dcc80cd2e4000000"},"bc11295936aa79d594139de1b2e12629414f3bdb":{"balance":"0xd3c21bcecceda1000000"},"beef32ca5b9a198d27b4e02f4c70439fe60356cf":{"balance":"0xd3c21bcecceda1000000"},"d7d76c58b3a519e9fa6cc4d22dc017259bc49f1e":{"balance":"0x52b7d2dcc80cd2e4000000"},"d7eddb78ed295b3c9629240e8924fb8d8874ddd8":{"balance":"0xd3c21bcecceda1000000"},"d9a5179f091d85051d3c982785efd1455cec8699":{"balance":"0xd3c21bcecceda1000000"},"e2e2659028143784d557bcec6ff3a0721048880a":{"balance":"0xd3c21bcecceda1000000"},"f47cae1cf79ca6758bfc787dbd21e6bdbe7112b8":{"balance":"0xd3c21bcecceda1000000"}},"number":"0x0","gasUsed":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","baseFeePerGas":null,"excessBlobGas":null,"blobGasUsed":null}
171 changes: 152 additions & 19 deletions crates/genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,61 @@ pub struct Genesis {
}

impl Genesis {
/// Creates a chain config for Clique using the given chain id.
/// and funds the given address with max coins.
///
/// Enables all hard forks up to London at genesis.
pub fn clique_genesis(chain_id: u64, signer_addr: Address) -> Genesis {
// set up a clique config with an instant sealing period and short (8 block) epoch
let clique_config = CliqueConfig { period: Some(0), epoch: Some(8) };

let config = ChainConfig {
chain_id,
eip155_block: Some(0),
eip150_block: Some(0),
eip158_block: Some(0),

homestead_block: Some(0),
byzantium_block: Some(0),
constantinople_block: Some(0),
petersburg_block: Some(0),
istanbul_block: Some(0),
muir_glacier_block: Some(0),
berlin_block: Some(0),
london_block: Some(0),
clique: Some(clique_config),
..Default::default()
};

// fund account
let mut alloc = HashMap::new();
alloc.insert(
signer_addr,
GenesisAccount { balance: U256::MAX, nonce: None, code: None, storage: None },
);

// put signer address in the extra data, padded by the required amount of zeros
// Clique issue: https://github.com/ethereum/EIPs/issues/225
// Clique EIP: https://eips.ethereum.org/EIPS/eip-225
//
// The first 32 bytes are vanity data, so we will populate it with zeros
// This is followed by the signer address, which is 20 bytes
// There are 65 bytes of zeros after the signer address, which is usually populated with the
// proposer signature. Because the genesis does not have a proposer signature, it will be
// populated with zeros.
let extra_data_bytes = [&[0u8; 32][..], signer_addr.as_slice(), &[0u8; 65][..]].concat();
let extra_data = Bytes::from(extra_data_bytes);

Genesis {
config,
alloc,
difficulty: U256::from(1),
gas_limit: 5_000_000,
extra_data,
..Default::default()
}
}

/// Set the nonce.
pub const fn with_nonce(mut self, nonce: u64) -> Self {
self.nonce = nonce;
Expand Down Expand Up @@ -209,78 +264,129 @@ pub struct ChainConfig {
pub chain_id: u64,

/// The homestead switch block (None = no fork, 0 = already homestead).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub homestead_block: Option<u64>,

/// The DAO fork switch block (None = no fork).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub dao_fork_block: Option<u64>,

/// Whether or not the node supports the DAO hard-fork.
pub dao_fork_support: bool,

/// The [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) hard fork block (None = no fork).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub eip150_block: Option<u64>,

/// The [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md) hard fork hash.
#[serde(skip_serializing_if = "Option::is_none")]
pub eip150_hash: Option<B256>,

/// The [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) hard fork block.
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub eip155_block: Option<u64>,

/// The [EIP-158](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-158.md) hard fork block.
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub eip158_block: Option<u64>,

/// The Byzantium hard fork block (None = no fork, 0 = already on byzantium).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub byzantium_block: Option<u64>,

/// The Constantinople hard fork block (None = no fork, 0 = already on constantinople).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub constantinople_block: Option<u64>,

/// The Petersburg hard fork block (None = no fork, 0 = already on petersburg).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub petersburg_block: Option<u64>,

/// The Istanbul hard fork block (None = no fork, 0 = already on istanbul).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub istanbul_block: Option<u64>,

/// The Muir Glacier hard fork block (None = no fork, 0 = already on muir glacier).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub muir_glacier_block: Option<u64>,

/// The Berlin hard fork block (None = no fork, 0 = already on berlin).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub berlin_block: Option<u64>,

/// The London hard fork block (None = no fork, 0 = already on london).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub london_block: Option<u64>,

/// The Arrow Glacier hard fork block (None = no fork, 0 = already on arrow glacier).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub arrow_glacier_block: Option<u64>,

/// The Gray Glacier hard fork block (None = no fork, 0 = already on gray glacier).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub gray_glacier_block: Option<u64>,

/// Virtual fork after the merge to use as a network splitter.
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub merge_netsplit_block: Option<u64>,

/// Shanghai switch time (None = no fork, 0 = already on shanghai).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub shanghai_time: Option<u64>,

/// Cancun switch time (None = no fork, 0 = already on cancun).
#[serde(skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "u64_hex_or_decimal_opt::deserialize"
)]
pub cancun_time: Option<u64>,

/// Total difficulty reached that triggers the merge consensus upgrade.
Expand Down Expand Up @@ -408,11 +514,11 @@ pub struct EthashConfig {}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Copy)]
pub struct CliqueConfig {
/// Number of seconds between blocks to enforce.
#[serde(default, skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub period: Option<u64>,

/// Epoch length to reset votes and checkpoints.
#[serde(default, skip_serializing_if = "Option::is_none", with = "u64_hex_or_decimal_opt")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub epoch: Option<u64>,
}

Expand Down Expand Up @@ -1145,4 +1251,31 @@ mod tests {
{deserialized_genesis:#?} does not match expected {expected_genesis:#?}"
);
}

#[test]
fn parse_dump_genesis_mainnet() {
let mainnet = include_str!("../dumpgenesis/mainnet.json");
let gen = serde_json::from_str::<Genesis>(mainnet).unwrap();
let s = serde_json::to_string_pretty(&gen).unwrap();
let gen2 = serde_json::from_str::<Genesis>(&s).unwrap();
assert_eq!(gen, gen2);
}

#[test]
fn parse_dump_genesis_sepolia() {
let sepolia = include_str!("../dumpgenesis/sepolia.json");
let gen = serde_json::from_str::<Genesis>(sepolia).unwrap();
let s = serde_json::to_string_pretty(&gen).unwrap();
let gen2 = serde_json::from_str::<Genesis>(&s).unwrap();
assert_eq!(gen, gen2);
}

#[test]
fn parse_dump_genesis_holesky() {
let holesky = include_str!("../dumpgenesis/holesky.json");
let gen = serde_json::from_str::<Genesis>(holesky).unwrap();
let s = serde_json::to_string_pretty(&gen).unwrap();
let gen2 = serde_json::from_str::<Genesis>(&s).unwrap();
assert_eq!(gen, gen2);
}
}
2 changes: 1 addition & 1 deletion crates/node-bindings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ exclude.workspace = true

[dependencies]
alloy-primitives = { workspace = true, features = ["k256", "serde"] }
alloy-genesis.workspace = true
k256.workspace = true
serde_json.workspace = true
serde.workspace = true
tempfile.workspace = true

[dev-dependencies]
Expand Down
Loading