diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c57b8b1e7..87d309dc42 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -181,19 +181,19 @@ jobs: - name: Build Lighthouse for x86_64-apple-darwin portable if: matrix.arch == 'x86_64-apple-darwin-portable' - run: cargo install --path lighthouse --force --locked --features portable + run: cargo install --path lighthouse --force --locked --features portable,gnosis - name: Build Lighthouse for x86_64-apple-darwin modern if: matrix.arch == 'x86_64-apple-darwin' - run: cargo install --path lighthouse --force --locked --features modern + run: cargo install --path lighthouse --force --locked --features modern,gnosis - name: Build Lighthouse for Windows portable if: matrix.arch == 'x86_64-windows-portable' - run: cargo install --path lighthouse --force --locked --features portable + run: cargo install --path lighthouse --force --locked --features portable,gnosis - name: Build Lighthouse for Windows modern if: matrix.arch == 'x86_64-windows' - run: cargo install --path lighthouse --force --locked --features modern + run: cargo install --path lighthouse --force --locked --features modern,gnosis - name: Configure GPG and create artifacts if: startsWith(matrix.arch, 'x86_64-windows') != true diff --git a/Makefile b/Makefile index a4b880b806..c372b9ef8b 100644 --- a/Makefile +++ b/Makefile @@ -50,13 +50,13 @@ endif # optimized CPU functions that may not be available on some systems. This # results in a more portable binary with ~20% slower BLS verification. build-x86_64: - cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features modern + cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features modern,gnosis build-x86_64-portable: - cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features portable + cross build --release --manifest-path lighthouse/Cargo.toml --target x86_64-unknown-linux-gnu --features portable,gnosis build-aarch64: - cross build --release --manifest-path lighthouse/Cargo.toml --target aarch64-unknown-linux-gnu + cross build --release --manifest-path lighthouse/Cargo.toml --target aarch64-unknown-linux-gnu --features gnosis build-aarch64-portable: - cross build --release --manifest-path lighthouse/Cargo.toml --target aarch64-unknown-linux-gnu --features portable + cross build --release --manifest-path lighthouse/Cargo.toml --target aarch64-unknown-linux-gnu --features portable,gnosis # Create a `.tar.gz` containing a binary for a specific target. define tarball_release_binary diff --git a/boot_node/src/lib.rs b/boot_node/src/lib.rs index 2afc063808..6b933013fc 100644 --- a/boot_node/src/lib.rs +++ b/boot_node/src/lib.rs @@ -63,6 +63,9 @@ pub fn run( EthSpecId::Mainnet => { main::(lh_matches, bn_matches, eth2_network_config, log) } + EthSpecId::Gnosis => { + main::(lh_matches, bn_matches, eth2_network_config, log) + } } { slog::crit!(slog_scope::logger(), "{}", e); } diff --git a/common/eth2_config/src/lib.rs b/common/eth2_config/src/lib.rs index b45ad9d1e2..fafa15ef8d 100644 --- a/common/eth2_config/src/lib.rs +++ b/common/eth2_config/src/lib.rs @@ -53,6 +53,13 @@ impl Eth2Config { spec: ChainSpec::minimal(), } } + + pub fn gnosis() -> Self { + Self { + eth_spec_id: EthSpecId::Gnosis, + spec: ChainSpec::gnosis(), + } + } } /// A directory that can be built by downloading files via HTTP. @@ -229,5 +236,6 @@ macro_rules! define_hardcoded_nets { define_hardcoded_nets!( (mainnet, "mainnet", GENESIS_STATE_IS_KNOWN), (pyrmont, "pyrmont", GENESIS_STATE_IS_KNOWN), - (prater, "prater", GENESIS_STATE_IS_KNOWN) + (prater, "prater", GENESIS_STATE_IS_KNOWN), + (gnosis, "gnosis", GENESIS_STATE_IS_KNOWN) ); diff --git a/common/eth2_network_config/built_in_network_configs/gnosis/boot_enr.yaml b/common/eth2_network_config/built_in_network_configs/gnosis/boot_enr.yaml new file mode 100644 index 0000000000..4b232d8b32 --- /dev/null +++ b/common/eth2_network_config/built_in_network_configs/gnosis/boot_enr.yaml @@ -0,0 +1,5 @@ +# Gnosis Chain Team +- enr:-IS4QGmLwm7gFd0L0CEisllrb1op3v-wAGSc7_pwSMGgN3bOS9Fz7m1dWbwuuPHKqeETz9MbhjVuoWk0ohkyRv98kVoBgmlkgnY0gmlwhGjtlgaJc2VjcDI1NmsxoQLMdh0It9fJbuiLydZ9fpF6MRzgNle0vODaDiMqhbC7WIN1ZHCCIyg +- enr:-IS4QFUVG3dvLPCUEI7ycRvFm0Ieg_ITa5tALmJ9LI7dJ6ieT3J4fF9xLRjOoB4ApV-Rjp7HeLKzyTWG1xRdbFBNZPQBgmlkgnY0gmlwhErP5weJc2VjcDI1NmsxoQOBbaJBvx0-w_pyZUhQl9A510Ho2T0grE0K8JevzES99IN1ZHCCIyg +- enr:-Ku4QOQk8V-Hu2gxFzRXmLYIO4AvWDZhoMFwTf3n3DYm_mbsWv0ZitoqiN6JZUUj6Li6e1Jk1w2zFSVHKPMUP1g5tsgBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD5Jd3FAAAAZP__________gmlkgnY0gmlwhC1PTpmJc2VjcDI1NmsxoQL1Ynt5PoA0UOcHa1Rfn98rmnRlLzNuWTePPP4m4qHVroN1ZHCCKvg +- enr:-Ku4QFaTwgoms-EiiRIfHUH3FXprWUFgjHg4UuWvilqoUQtDbmTszVIxUEOwQUmA2qkiP-T9wXjc_rVUuh9cU7WgwbgBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD5Jd3FAAAAZP__________gmlkgnY0gmlwhC0hBmCJc2VjcDI1NmsxoQOpsg1XCrXmCwZKcSTcycLwldoKUMHPUpMEVGeg_EEhuYN1ZHCCKvg diff --git a/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml b/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml new file mode 100644 index 0000000000..c34ebed7d5 --- /dev/null +++ b/common/eth2_network_config/built_in_network_configs/gnosis/config.yaml @@ -0,0 +1,85 @@ +# Gnosis Beacon Chain config + +# Extends the gnosis preset +PRESET_BASE: 'gnosis' + +# Transition +# --------------------------------------------------------------- +# TBD, 2**256-2**10 is a placeholder +TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129638912 +# By default, don't use these params +TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000 +TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615 + +# Genesis +# --------------------------------------------------------------- +# `2**12` (= 4,096) +MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 4096 +# Dec 8, 2021, 13:00 UTC +MIN_GENESIS_TIME: 1638968400 +# Gnosis Beacon Chain initial fork version +GENESIS_FORK_VERSION: 0x00000064 +# 6000 seconds (100 minutes) +GENESIS_DELAY: 6000 + + +# Forking +# --------------------------------------------------------------- +# Some forks are disabled for now: +# - These may be re-assigned to another fork-version later +# - Temporarily set to max uint64 value: 2**64 - 1 + +# Altair +ALTAIR_FORK_VERSION: 0x01000064 +ALTAIR_FORK_EPOCH: 512 +# Merge +BELLATRIX_FORK_VERSION: 0x02000064 +BELLATRIX_FORK_EPOCH: 18446744073709551615 +# Sharding +SHARDING_FORK_VERSION: 0x03000064 +SHARDING_FORK_EPOCH: 18446744073709551615 + +# TBD, 2**32 is a placeholder. Merge transition approach is in active R&D. +TRANSITION_TOTAL_DIFFICULTY: 4294967296 + + +# Time parameters +# --------------------------------------------------------------- +# 5 seconds +SECONDS_PER_SLOT: 5 +# 6 (estimate from Gnosis Chain) +SECONDS_PER_ETH1_BLOCK: 6 +# 2**8 (= 256) epochs ~8 hours +MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256 +# 2**8 (= 256) epochs ~8 hours +SHARD_COMMITTEE_PERIOD: 256 +# 2**10 (= 1024) ~1.4 hour +ETH1_FOLLOW_DISTANCE: 1024 + + +# Validator cycle +# --------------------------------------------------------------- +# 2**2 (= 4) +INACTIVITY_SCORE_BIAS: 4 +# 2**4 (= 16) +INACTIVITY_SCORE_RECOVERY_RATE: 16 +# 2**4 * 10**9 (= 16,000,000,000) Gwei +EJECTION_BALANCE: 16000000000 +# 2**2 (= 4) +MIN_PER_EPOCH_CHURN_LIMIT: 4 +# 2**12 (= 4096) +CHURN_LIMIT_QUOTIENT: 4096 + + +# Fork choice +# --------------------------------------------------------------- +# TODO: enable once proposer boosting is desired on mainnet +# 70% +# PROPOSER_SCORE_BOOST: 70 + +# Deposit contract +# --------------------------------------------------------------- +# Gnosis Chain +DEPOSIT_CHAIN_ID: 100 +DEPOSIT_NETWORK_ID: 100 +DEPOSIT_CONTRACT_ADDRESS: 0x0B98057eA310F4d31F2a452B414647007d1645d9 diff --git a/common/eth2_network_config/built_in_network_configs/gnosis/deploy_block.txt b/common/eth2_network_config/built_in_network_configs/gnosis/deploy_block.txt new file mode 100644 index 0000000000..0071371e28 --- /dev/null +++ b/common/eth2_network_config/built_in_network_configs/gnosis/deploy_block.txt @@ -0,0 +1 @@ +19469077 diff --git a/common/eth2_network_config/built_in_network_configs/gnosis/genesis.ssz.zip b/common/eth2_network_config/built_in_network_configs/gnosis/genesis.ssz.zip new file mode 100644 index 0000000000..3bfb326a24 Binary files /dev/null and b/common/eth2_network_config/built_in_network_configs/gnosis/genesis.ssz.zip differ diff --git a/common/eth2_network_config/src/lib.rs b/common/eth2_network_config/src/lib.rs index 4085d392a6..044548bd61 100644 --- a/common/eth2_network_config/src/lib.rs +++ b/common/eth2_network_config/src/lib.rs @@ -226,7 +226,7 @@ mod tests { use super::*; use ssz::Encode; use tempfile::Builder as TempBuilder; - use types::{Config, Eth1Data, Hash256, MainnetEthSpec}; + use types::{Config, Eth1Data, GnosisEthSpec, Hash256, MainnetEthSpec, GNOSIS}; type E = MainnetEthSpec; @@ -263,7 +263,11 @@ mod tests { .unwrap_or_else(|_| panic!("{:?}", net.name)); // Ensure we can parse the YAML config to a chain spec. - config.chain_spec::().unwrap(); + if net.name == GNOSIS { + config.chain_spec::().unwrap(); + } else { + config.chain_spec::().unwrap(); + } assert_eq!( config.genesis_state_bytes.is_some(), diff --git a/consensus/types/presets/gnosis/altair.yaml b/consensus/types/presets/gnosis/altair.yaml new file mode 100644 index 0000000000..ff6bd98a00 --- /dev/null +++ b/consensus/types/presets/gnosis/altair.yaml @@ -0,0 +1,24 @@ +# Gnosis Beacon Chain preset - Altair + +# Updated penalty values +# --------------------------------------------------------------- +# 3 * 2**24 (= 50,331,648) +INACTIVITY_PENALTY_QUOTIENT_ALTAIR: 50331648 +# 2**6 (= 64) +MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: 64 +# 2 +PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: 2 + + +# Sync committee +# --------------------------------------------------------------- +# 2**9 (= 512) +SYNC_COMMITTEE_SIZE: 512 +# 2**8 (= 256) +EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 512 + + +# Sync protocol +# --------------------------------------------------------------- +# 1 +MIN_SYNC_COMMITTEE_PARTICIPANTS: 1 diff --git a/consensus/types/presets/gnosis/bellatrix.yaml b/consensus/types/presets/gnosis/bellatrix.yaml new file mode 100644 index 0000000000..e938af4792 --- /dev/null +++ b/consensus/types/presets/gnosis/bellatrix.yaml @@ -0,0 +1,21 @@ +# Gnosis Beacon Chain preset - Bellatrix + +# Updated penalty values +# --------------------------------------------------------------- +# 2**24 (= 16,777,216) +INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: 16777216 +# 2**5 (= 32) +MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: 32 +# 3 +PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: 3 + +# Execution +# --------------------------------------------------------------- +# 2**30 (= 1,073,741,824) +MAX_BYTES_PER_TRANSACTION: 1073741824 +# 2**20 (= 1,048,576) +MAX_TRANSACTIONS_PER_PAYLOAD: 1048576 +# 2**8 (= 256) +BYTES_PER_LOGS_BLOOM: 256 +# 2**5 (= 32) +MAX_EXTRA_DATA_BYTES: 32 diff --git a/consensus/types/presets/gnosis/phase0.yaml b/consensus/types/presets/gnosis/phase0.yaml new file mode 100644 index 0000000000..87c73e6fb7 --- /dev/null +++ b/consensus/types/presets/gnosis/phase0.yaml @@ -0,0 +1,94 @@ +# Gnosis Beacon Chain preset - Phase0 + +# Misc +# --------------------------------------------------------------- +# 2**6 (= 64) +MAX_COMMITTEES_PER_SLOT: 64 +# 2**7 (= 128) +TARGET_COMMITTEE_SIZE: 128 +# 2**11 (= 2,048) +MAX_VALIDATORS_PER_COMMITTEE: 2048 +# See issue 563 +SHUFFLE_ROUND_COUNT: 90 +# 4 +HYSTERESIS_QUOTIENT: 4 +# 1 (minus 0.25) +HYSTERESIS_DOWNWARD_MULTIPLIER: 1 +# 5 (plus 1.25) +HYSTERESIS_UPWARD_MULTIPLIER: 5 + + +# Fork Choice +# --------------------------------------------------------------- +# 2**3 (= 8) +SAFE_SLOTS_TO_UPDATE_JUSTIFIED: 8 + + +# Gwei values +# --------------------------------------------------------------- +# 2**0 * 10**9 (= 1,000,000,000) Gwei +MIN_DEPOSIT_AMOUNT: 1000000000 +# 2**5 * 10**9 (= 32,000,000,000) Gwei +MAX_EFFECTIVE_BALANCE: 32000000000 +# 2**0 * 10**9 (= 1,000,000,000) Gwei +EFFECTIVE_BALANCE_INCREMENT: 1000000000 + + +# Time parameters +# --------------------------------------------------------------- +# 2**0 (= 1) slots 5 seconds +MIN_ATTESTATION_INCLUSION_DELAY: 1 +# 2**4 (= 16) slots 1.87 minutes +SLOTS_PER_EPOCH: 16 +# 2**0 (= 1) epochs 1.87 minutes +MIN_SEED_LOOKAHEAD: 1 +# 2**2 (= 4) epochs 7.47 minutes +MAX_SEED_LOOKAHEAD: 4 +# 2**6 (= 64) epochs ~2 hours +EPOCHS_PER_ETH1_VOTING_PERIOD: 64 +# 2**13 (= 8,192) slots ~15.9 hours +SLOTS_PER_HISTORICAL_ROOT: 8192 +# 2**2 (= 4) epochs 7.47 minutes +MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4 + + +# State list lengths +# --------------------------------------------------------------- +# 2**16 (= 65,536) epochs ~85 days +EPOCHS_PER_HISTORICAL_VECTOR: 65536 +# 2**13 (= 8,192) epochs ~10.6 days +EPOCHS_PER_SLASHINGS_VECTOR: 8192 +# 2**24 (= 16,777,216) historical roots, ~15,243 years +HISTORICAL_ROOTS_LIMIT: 16777216 +# 2**40 (= 1,099,511,627,776) validator spots +VALIDATOR_REGISTRY_LIMIT: 1099511627776 + + +# Reward and penalty quotients +# --------------------------------------------------------------- +# 2**6 (= 64) +BASE_REWARD_FACTOR: 25 +# 2**9 (= 512) +WHISTLEBLOWER_REWARD_QUOTIENT: 512 +# 2**3 (= 8) +PROPOSER_REWARD_QUOTIENT: 8 +# 2**26 (= 67,108,864) +INACTIVITY_PENALTY_QUOTIENT: 67108864 +# 2**7 (= 128) (lower safety margin at Phase 0 genesis) +MIN_SLASHING_PENALTY_QUOTIENT: 128 +# 1 (lower safety margin at Phase 0 genesis) +PROPORTIONAL_SLASHING_MULTIPLIER: 1 + + +# Max operations per block +# --------------------------------------------------------------- +# 2**4 (= 16) +MAX_PROPOSER_SLASHINGS: 16 +# 2**1 (= 2) +MAX_ATTESTER_SLASHINGS: 2 +# 2**7 (= 128) +MAX_ATTESTATIONS: 128 +# 2**4 (= 16) +MAX_DEPOSITS: 16 +# 2**4 (= 16) +MAX_VOLUNTARY_EXITS: 16 diff --git a/consensus/types/src/chain_spec.rs b/consensus/types/src/chain_spec.rs index f191eb8671..8f58003572 100644 --- a/consensus/types/src/chain_spec.rs +++ b/consensus/types/src/chain_spec.rs @@ -596,6 +596,161 @@ impl ChainSpec { ..ChainSpec::mainnet() } } + + /// Returns a `ChainSpec` compatible with the Gnosis Beacon Chain specification. + pub fn gnosis() -> Self { + Self { + /* + * Constants + */ + genesis_slot: Slot::new(0), + far_future_epoch: Epoch::new(u64::MAX), + base_rewards_per_epoch: 4, + deposit_contract_tree_depth: 32, + + /* + * Misc + */ + max_committees_per_slot: 64, + target_committee_size: 128, + min_per_epoch_churn_limit: 4, + churn_limit_quotient: 4_096, + shuffle_round_count: 90, + min_genesis_active_validator_count: 4_096, + min_genesis_time: 1638968400, // Dec 8, 2020 + hysteresis_quotient: 4, + hysteresis_downward_multiplier: 1, + hysteresis_upward_multiplier: 5, + + /* + * Gwei values + */ + min_deposit_amount: option_wrapper(|| { + u64::checked_pow(2, 0)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), + max_effective_balance: option_wrapper(|| { + u64::checked_pow(2, 5)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), + ejection_balance: option_wrapper(|| { + u64::checked_pow(2, 4)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), + effective_balance_increment: option_wrapper(|| { + u64::checked_pow(2, 0)?.checked_mul(u64::checked_pow(10, 9)?) + }) + .expect("calculation does not overflow"), + + /* + * Initial Values + */ + genesis_fork_version: [0x00, 0x00, 0x00, 0x64], + bls_withdrawal_prefix_byte: 0, + + /* + * Time parameters + */ + genesis_delay: 6000, // 100 minutes + seconds_per_slot: 5, + min_attestation_inclusion_delay: 1, + min_seed_lookahead: Epoch::new(1), + max_seed_lookahead: Epoch::new(4), + min_epochs_to_inactivity_penalty: 4, + min_validator_withdrawability_delay: Epoch::new(256), + shard_committee_period: 256, + + /* + * Reward and penalty quotients + */ + base_reward_factor: 25, + whistleblower_reward_quotient: 512, + proposer_reward_quotient: 8, + inactivity_penalty_quotient: u64::checked_pow(2, 26).expect("pow does not overflow"), + min_slashing_penalty_quotient: 128, + proportional_slashing_multiplier: 1, + + /* + * Signature domains + */ + domain_beacon_proposer: 0, + domain_beacon_attester: 1, + domain_randao: 2, + domain_deposit: 3, + domain_voluntary_exit: 4, + domain_selection_proof: 5, + domain_aggregate_and_proof: 6, + + /* + * Fork choice + */ + safe_slots_to_update_justified: 8, + proposer_score_boost: None, + + /* + * Eth1 + */ + eth1_follow_distance: 1024, + seconds_per_eth1_block: 6, + deposit_chain_id: 100, + deposit_network_id: 100, + deposit_contract_address: "0B98057eA310F4d31F2a452B414647007d1645d9" + .parse() + .expect("chain spec deposit contract address"), + + /* + * Altair hard fork params + */ + inactivity_penalty_quotient_altair: option_wrapper(|| { + u64::checked_pow(2, 24)?.checked_mul(3) + }) + .expect("calculation does not overflow"), + min_slashing_penalty_quotient_altair: u64::checked_pow(2, 6) + .expect("pow does not overflow"), + proportional_slashing_multiplier_altair: 2, + inactivity_score_bias: 4, + inactivity_score_recovery_rate: 16, + min_sync_committee_participants: 1, + epochs_per_sync_committee_period: Epoch::new(512), + domain_sync_committee: 7, + domain_sync_committee_selection_proof: 8, + domain_contribution_and_proof: 9, + altair_fork_version: [0x01, 0x00, 0x00, 0x64], + altair_fork_epoch: Some(Epoch::new(256)), + + /* + * Merge hard fork params + */ + inactivity_penalty_quotient_bellatrix: u64::checked_pow(2, 24) + .expect("pow does not overflow"), + min_slashing_penalty_quotient_bellatrix: u64::checked_pow(2, 5) + .expect("pow does not overflow"), + proportional_slashing_multiplier_bellatrix: 3, + bellatrix_fork_version: [0x02, 0x00, 0x00, 0x64], + bellatrix_fork_epoch: None, + terminal_total_difficulty: Uint256::MAX + .checked_sub(Uint256::from(2u64.pow(10))) + .expect("subtraction does not overflow") + // Add 1 since the spec declares `2**256 - 2**10` and we use + // `Uint256::MAX` which is `2*256- 1`. + .checked_add(Uint256::one()) + .expect("addition does not overflow"), + terminal_block_hash: Hash256::zero(), + terminal_block_hash_activation_epoch: Epoch::new(u64::MAX), + + /* + * Network specific + */ + boot_nodes: vec![], + network_id: 100, // Gnosis Chain network id + attestation_propagation_slot_range: 32, + attestation_subnet_count: 64, + random_subnets_per_validator: 1, + maximum_gossip_clock_disparity_millis: 500, + target_aggregators_per_committee: 16, + epochs_per_random_subnet_subscription: 256, + } + } } impl Default for ChainSpec { @@ -746,6 +901,7 @@ impl Config { match self.preset_base.as_str() { "minimal" => Some(EthSpecId::Minimal), "mainnet" => Some(EthSpecId::Mainnet), + "gnosis" => Some(EthSpecId::Gnosis), _ => None, } } diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index ae0cafe1ff..e616976026 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -3,17 +3,17 @@ use crate::*; use safe_arith::SafeArith; use serde_derive::{Deserialize, Serialize}; use ssz_types::typenum::{ - Unsigned, U0, U1024, U1073741824, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, - U4096, U512, U64, U65536, U8, U8192, + bit::B0, UInt, Unsigned, U0, U1024, U1048576, U1073741824, U1099511627776, U128, U16, + U16777216, U2, U2048, U256, U32, U4, U4096, U512, U625, U64, U65536, U8, U8192, }; use std::fmt::{self, Debug}; use std::str::FromStr; -use ssz_types::typenum::{bit::B0, UInt, U1048576, U256, U625}; pub type U5000 = UInt, B0>, B0>; // 625 * 8 = 5000 const MAINNET: &str = "mainnet"; const MINIMAL: &str = "minimal"; +pub const GNOSIS: &str = "gnosis"; /// Used to identify one of the `EthSpec` instances defined here. #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -21,6 +21,7 @@ const MINIMAL: &str = "minimal"; pub enum EthSpecId { Mainnet, Minimal, + Gnosis, } impl FromStr for EthSpecId { @@ -30,6 +31,7 @@ impl FromStr for EthSpecId { match s { MAINNET => Ok(EthSpecId::Mainnet), MINIMAL => Ok(EthSpecId::Minimal), + GNOSIS => Ok(EthSpecId::Gnosis), _ => Err(format!("Unknown eth spec: {}", s)), } } @@ -40,6 +42,7 @@ impl fmt::Display for EthSpecId { let s = match self { EthSpecId::Mainnet => MAINNET, EthSpecId::Minimal => MINIMAL, + EthSpecId::Gnosis => GNOSIS, }; write!(f, "{}", s) } @@ -317,3 +320,46 @@ impl EthSpec for MinimalEthSpec { EthSpecId::Minimal } } + +/// Gnosis Beacon Chain specifications. +#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))] +#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)] +pub struct GnosisEthSpec; + +impl EthSpec for GnosisEthSpec { + type JustificationBitsLength = U4; + type SubnetBitfieldLength = U64; + type MaxValidatorsPerCommittee = U2048; + type GenesisEpoch = U0; + type SlotsPerEpoch = U16; + type EpochsPerEth1VotingPeriod = U64; + type SlotsPerHistoricalRoot = U8192; + type EpochsPerHistoricalVector = U65536; + type EpochsPerSlashingsVector = U8192; + type HistoricalRootsLimit = U16777216; + type ValidatorRegistryLimit = U1099511627776; + type MaxProposerSlashings = U16; + type MaxAttesterSlashings = U2; + type MaxAttestations = U128; + type MaxDeposits = U16; + type MaxVoluntaryExits = U16; + type SyncCommitteeSize = U512; + type SyncCommitteeSubnetCount = U4; + type MaxBytesPerTransaction = U1073741824; // 1,073,741,824 + type MaxTransactionsPerPayload = U1048576; // 1,048,576 + type BytesPerLogsBloom = U256; + type GasLimitDenominator = U1024; + type MinGasLimit = U5000; + type MaxExtraDataBytes = U32; + type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count + type MaxPendingAttestations = U2048; // 128 max attestations * 16 slots per epoch + type SlotsPerEth1VotingPeriod = U1024; // 64 epochs * 16 slots per epoch + + fn default_spec() -> ChainSpec { + ChainSpec::gnosis() + } + + fn spec_name() -> EthSpecId { + EthSpecId::Gnosis + } +} diff --git a/consensus/types/src/preset.rs b/consensus/types/src/preset.rs index ccda1a06a0..8ee38e46a6 100644 --- a/consensus/types/src/preset.rs +++ b/consensus/types/src/preset.rs @@ -187,7 +187,7 @@ impl BellatrixPreset { #[cfg(test)] mod test { use super::*; - use crate::{MainnetEthSpec, MinimalEthSpec}; + use crate::{GnosisEthSpec, MainnetEthSpec, MinimalEthSpec}; use serde::de::DeserializeOwned; use std::env; use std::fs::File; @@ -226,6 +226,11 @@ mod test { preset_test::(); } + #[test] + fn gnosis_presets_consistent() { + preset_test::(); + } + #[test] fn minimal_presets_consistent() { preset_test::(); diff --git a/lcli/src/main.rs b/lcli/src/main.rs index a494cd3822..9af4b25548 100644 --- a/lcli/src/main.rs +++ b/lcli/src/main.rs @@ -38,7 +38,7 @@ fn main() { .value_name("STRING") .takes_value(true) .required(true) - .possible_values(&["minimal", "mainnet"]) + .possible_values(&["minimal", "mainnet", "gnosis"]) .default_value("mainnet") .global(true), ) @@ -665,6 +665,7 @@ fn main() { .and_then(|eth_spec_id| match eth_spec_id { EthSpecId::Minimal => run(EnvironmentBuilder::minimal(), &matches), EthSpecId::Mainnet => run(EnvironmentBuilder::mainnet(), &matches), + EthSpecId::Gnosis => run(EnvironmentBuilder::gnosis(), &matches), }); match result { diff --git a/lighthouse/Cargo.toml b/lighthouse/Cargo.toml index 130322e0e9..2429b6606d 100644 --- a/lighthouse/Cargo.toml +++ b/lighthouse/Cargo.toml @@ -16,6 +16,8 @@ modern = ["bls/supranational-force-adx"] milagro = ["bls/milagro"] # Support minimal spec (used for testing only). spec-minimal = [] +# Support Gnosis spec and Gnosis Beacon Chain. +gnosis = [] [dependencies] beacon_node = { "path" = "../beacon_node" } diff --git a/lighthouse/environment/src/lib.rs b/lighthouse/environment/src/lib.rs index e536d3c95b..448c84b54d 100644 --- a/lighthouse/environment/src/lib.rs +++ b/lighthouse/environment/src/lib.rs @@ -21,7 +21,7 @@ use std::path::PathBuf; use std::sync::Arc; use task_executor::{ShutdownReason, TaskExecutor}; use tokio::runtime::{Builder as RuntimeBuilder, Runtime}; -use types::{EthSpec, MainnetEthSpec, MinimalEthSpec}; +use types::{EthSpec, GnosisEthSpec, MainnetEthSpec, MinimalEthSpec}; #[cfg(target_family = "unix")] use { @@ -87,6 +87,19 @@ impl EnvironmentBuilder { } } +impl EnvironmentBuilder { + /// Creates a new builder using the `gnosis` eth2 specification. + pub fn gnosis() -> Self { + Self { + runtime: None, + log: None, + eth_spec_instance: GnosisEthSpec, + eth2_config: Eth2Config::gnosis(), + eth2_network_config: None, + } + } +} + impl EnvironmentBuilder { /// Specifies that a multi-threaded tokio runtime should be used. Ideal for production uses. /// diff --git a/lighthouse/src/main.rs b/lighthouse/src/main.rs index 693b3de821..51c1075cdb 100644 --- a/lighthouse/src/main.rs +++ b/lighthouse/src/main.rs @@ -52,11 +52,12 @@ fn main() { "{}\n\ BLS library: {}\n\ SHA256 hardware acceleration: {}\n\ - Specs: mainnet (true), minimal ({})", + Specs: mainnet (true), minimal ({}), gnosis ({})", VERSION.replace("Lighthouse/", ""), bls_library_name(), have_sha_extensions(), cfg!(feature = "spec-minimal"), + cfg!(feature = "gnosis"), ).as_str() ) .arg( @@ -302,9 +303,11 @@ fn main() { match eth_spec_id { EthSpecId::Mainnet => run(EnvironmentBuilder::mainnet(), &matches, eth2_network_config), + #[cfg(feature = "gnosis")] + EthSpecId::Gnosis => run(EnvironmentBuilder::gnosis(), &matches, eth2_network_config), #[cfg(feature = "spec-minimal")] EthSpecId::Minimal => run(EnvironmentBuilder::minimal(), &matches, eth2_network_config), - #[cfg(not(feature = "spec-minimal"))] + #[cfg(not(all(feature = "spec-minimal", feature = "gnosis")))] other => { eprintln!( "Eth spec `{}` is not supported by this build of Lighthouse",