# beacon_chain # Copyright (c) 2018-2024 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. {.push raises: [].} import std/[strutils, parseutils, tables, typetraits], chronos/timer, stew/[byteutils], stint, web3/primitives as web3types, ./datatypes/constants export constants export stint, web3types.toHex, web3types.`==` const # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.6/specs/phase0/beacon-chain.md#withdrawal-prefixes BLS_WITHDRAWAL_PREFIX*: byte = 0 ETH1_ADDRESS_WITHDRAWAL_PREFIX*: byte = 1 # Constants from `validator.md` not covered by config/presets in the spec TARGET_AGGREGATORS_PER_COMMITTEE*: uint64 = 16 # Not used anywhere; only for network preset checking EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: uint64 = 256 TTFB_TIMEOUT* = 5'u64 MESSAGE_DOMAIN_INVALID_SNAPPY*: array[4, byte] = [0x00, 0x00, 0x00, 0x00] MESSAGE_DOMAIN_VALID_SNAPPY*: array[4, byte] = [0x01, 0x00, 0x00, 0x00] type Version* = distinct array[4, byte] Eth1Address* = web3types.Address RuntimeConfig* = object ## https://github.com/ethereum/consensus-specs/tree/v1.4.0-beta.4/configs PRESET_BASE*: string CONFIG_NAME*: string # Transition TERMINAL_TOTAL_DIFFICULTY*: UInt256 TERMINAL_BLOCK_HASH*: Hash32 TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH*: Epoch # Not actively used, but part of the spec # Genesis MIN_GENESIS_ACTIVE_VALIDATOR_COUNT*: uint64 MIN_GENESIS_TIME*: uint64 GENESIS_FORK_VERSION*: Version GENESIS_DELAY*: uint64 # Forking ALTAIR_FORK_VERSION*: Version ALTAIR_FORK_EPOCH*: Epoch BELLATRIX_FORK_VERSION*: Version BELLATRIX_FORK_EPOCH*: Epoch CAPELLA_FORK_VERSION*: Version CAPELLA_FORK_EPOCH*: Epoch DENEB_FORK_VERSION*: Version DENEB_FORK_EPOCH*: Epoch ELECTRA_FORK_VERSION*: Version ELECTRA_FORK_EPOCH*: Epoch # Time parameters # TODO SECONDS_PER_SLOT*: uint64 SECONDS_PER_ETH1_BLOCK*: uint64 MIN_VALIDATOR_WITHDRAWABILITY_DELAY*: uint64 SHARD_COMMITTEE_PERIOD*: uint64 ETH1_FOLLOW_DISTANCE*: uint64 # Validator cycle INACTIVITY_SCORE_BIAS*: uint64 INACTIVITY_SCORE_RECOVERY_RATE*: uint64 EJECTION_BALANCE*: uint64 MIN_PER_EPOCH_CHURN_LIMIT*: uint64 CHURN_LIMIT_QUOTIENT*: uint64 MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT*: uint64 MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA*: uint64 MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT*: uint64 # Fork choice # TODO PROPOSER_SCORE_BOOST*: uint64 # TODO REORG_HEAD_WEIGHT_THRESHOLD*: uint64 # TODO REORG_PARENT_WEIGHT_THRESHOLD*: uint64 # TODO REORG_MAX_EPOCHS_SINCE_FINALIZATION*: uint64 # Deposit contract DEPOSIT_CHAIN_ID*: uint64 DEPOSIT_NETWORK_ID*: uint64 DEPOSIT_CONTRACT_ADDRESS*: Eth1Address # Networking # TODO GOSSIP_MAX_SIZE*: uint64 # TODO MAX_REQUEST_BLOCKS*: uint64 # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION*: uint64 MIN_EPOCHS_FOR_BLOCK_REQUESTS*: uint64 # TODO MAX_CHUNK_SIZE*: uint64 # TODO TTFB_TIMEOUT*: uint64 # TODO RESP_TIMEOUT*: uint64 # TODO ATTESTATION_PROPAGATION_SLOT_RANGE*: uint64 # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY*: uint64 # TODO MESSAGE_DOMAIN_INVALID_SNAPPY*: array[4, byte] # TODO MESSAGE_DOMAIN_VALID_SNAPPY*: array[4, byte] # TODO SUBNETS_PER_NODE*: uint64 # TODO ATTESTATION_SUBNET_COUNT*: uint64 # TODO ATTESTATION_SUBNET_EXTRA_BITS*: uint64 # TODO ATTESTATION_SUBNET_PREFIX_BITS*: uint64 # Deneb # TODO MAX_REQUEST_BLOCKS_DENEB*: uint64 # TODO MAX_REQUEST_BLOB_SIDECARS*: uint64 MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS*: uint64 # TODO BLOB_SIDECAR_SUBNET_COUNT*: uint64 PresetFile* = object values*: Table[string, string] missingValues*: seq[string] PresetFileError* = object of CatchableError PresetIncompatibleError* = object of CatchableError const const_preset* {.strdefine.} = "mainnet" # No-longer used values from legacy config files ignoredValues = [ "TRANSITION_TOTAL_DIFFICULTY", # Name that appears in some altair alphas, obsolete, remove when no more testnets "MIN_ANCHOR_POW_BLOCK_DIFFICULTY", # Name that appears in some altair alphas, obsolete, remove when no more testnets "RANDOM_SUBNETS_PER_VALIDATOR", # Removed in consensus-specs v1.4.0 ] when const_preset == "mainnet": import ./presets/mainnet export mainnet # TODO Move this to RuntimeConfig const SECONDS_PER_SLOT* {.intdefine.}: uint64 = 12 # The default run-time config specifies the default configuration values # that will be used if a particular run-time config is missing specific # confugration values (which will be then taken from this config object). # It mostly matches the mainnet config with the exception of few properties # such as `CONFIG_NAME`, `TERMINAL_TOTAL_DIFFICULTY`, `*_FORK_EPOCH`, etc # which must be effectively overriden in all network (including mainnet). const defaultRuntimeConfig* = RuntimeConfig( # Mainnet config # Extends the mainnet preset PRESET_BASE: "mainnet", # Free-form short name of the network that this configuration applies to - known # canonical network names include: # * 'mainnet' - there can be only one # * 'sepolia' - testnet # * 'holesky' - testnet # Must match the regex: [a-z0-9\-] CONFIG_NAME: "", # Transition # --------------------------------------------------------------- # TBD, 2**256-2**10 is a placeholder TERMINAL_TOTAL_DIFFICULTY: u256"115792089237316195423570985008687907853269984665640564039457584007913129638912", # By default, don't use these params TERMINAL_BLOCK_HASH: Hash32.fromHex( "0x0000000000000000000000000000000000000000000000000000000000000000"), # Genesis # --------------------------------------------------------------- # `2**14` (= 16,384) MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384, # Dec 1, 2020, 12pm UTC MIN_GENESIS_TIME: 1606824000, # Mainnet initial fork version, recommend altering for testnets GENESIS_FORK_VERSION: Version [byte 0x00, 0x00, 0x00, 0x00], # 604800 seconds (7 days) GENESIS_DELAY: 604800, # 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: Version [byte 0x01, 0x00, 0x00, 0x00], ALTAIR_FORK_EPOCH: FAR_FUTURE_EPOCH, # Bellatrix BELLATRIX_FORK_VERSION: Version [byte 0x02, 0x00, 0x00, 0x00], BELLATRIX_FORK_EPOCH: FAR_FUTURE_EPOCH, # Capella CAPELLA_FORK_VERSION: Version [byte 0x03, 0x00, 0x00, 0x00], CAPELLA_FORK_EPOCH: FAR_FUTURE_EPOCH, # Deneb DENEB_FORK_VERSION: Version [byte 0x04, 0x00, 0x00, 0x00], DENEB_FORK_EPOCH: FAR_FUTURE_EPOCH, # Electra ELECTRA_FORK_VERSION: Version [byte 0x05, 0x00, 0x00, 0x00], ELECTRA_FORK_EPOCH: FAR_FUTURE_EPOCH, # Time parameters # --------------------------------------------------------------- # 12 seconds # TODO SECONDS_PER_SLOT: 12, # 14 (estimate from Eth1 mainnet) SECONDS_PER_ETH1_BLOCK: 14, # 2**8 (= 256) epochs ~27 hours MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256, # 2**8 (= 256) epochs ~27 hours SHARD_COMMITTEE_PERIOD: 256, # 2**11 (= 2,048) Eth1 blocks ~8 hours ETH1_FOLLOW_DISTANCE: 2048, # 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'u64, # 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4, # 2**16 (= 65,536) CHURN_LIMIT_QUOTIENT: 65536, # [New in Deneb:EIP7514] 2**3 (= 8) MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8, # [New in Electra:EIP7251] 2**7 * 10**9 (= 128,000,000,000) MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000'u64, # [New in Electra:EIP7251] 2**8 * 10**9 (= 256,000,000,000) MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000'u64, # Deposit contract # --------------------------------------------------------------- # Ethereum PoW Mainnet DEPOSIT_CHAIN_ID: 1, DEPOSIT_NETWORK_ID: 1, DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address), # Networking # --------------------------------------------------------------- # `10 * 2**20` (= 10485760, 10 MiB) # TODO GOSSIP_MAX_SIZE: 10485760, # `2**10` (= 1024) # TODO MAX_REQUEST_BLOCKS: 1024, # `2**8` (= 256) # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, # `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024, # `10 * 2**20` (=10485760, 10 MiB) # TODO MAX_CHUNK_SIZE: 10485760, # 5s # TODO TTFB_TIMEOUT: 5, # 10s # TODO RESP_TIMEOUT: 10, # TODO ATTESTATION_PROPAGATION_SLOT_RANGE: 32, # 500ms # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, # TODO MESSAGE_DOMAIN_INVALID_SNAPPY: [byte 0x00, 0x00, 0x00, 0x00], # TODO MESSAGE_DOMAIN_VALID_SNAPPY: [byte 0x01, 0x00, 0x00, 0x00], # 2 subnets per node # TODO SUBNETS_PER_NODE: 2, # 2**8 (= 64) # TODO ATTESTATION_SUBNET_COUNT: 64, # TODO ATTESTATION_SUBNET_EXTRA_BITS: 0, # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS # TODO ATTESTATION_SUBNET_PREFIX_BITS: 6, # Deneb # `2**7` (=128) # TODO MAX_REQUEST_BLOCKS_DENEB: 128, # MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK # TODO MAX_REQUEST_BLOB_SIDECARS: 768, # `2**12` (= 4096 epochs, ~18 days) MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 4096, # `6` # TODO BLOB_SIDECAR_SUBNET_COUNT: 6, ) elif const_preset == "gnosis": import ./presets/gnosis export gnosis # TODO Move this to RuntimeConfig const SECONDS_PER_SLOT* {.intdefine.}: uint64 = 5 # The default run-time config specifies the default configuration values # that will be used if a particular run-time config is missing specific # confugration values (which will be then taken from this config object). # It mostly matches the gnosis config with the exception of few properties # such as `CONFIG_NAME`, `TERMINAL_TOTAL_DIFFICULTY`, `*_FORK_EPOCH`, etc # which must be effectively overriden in all network (including mainnet). const defaultRuntimeConfig* = RuntimeConfig( # Mainnet config # Extends the mainnet preset PRESET_BASE: "gnosis", # Free-form short name of the network that this configuration applies to - known # canonical network names include: # * 'mainnet' - there can be only one # * 'sepolia' - testnet # * 'holesky' - testnet # Must match the regex: [a-z0-9\-] CONFIG_NAME: "", # Transition # --------------------------------------------------------------- # TBD, 2**256-2**10 is a placeholder TERMINAL_TOTAL_DIFFICULTY: u256"115792089237316195423570985008687907853269984665640564039457584007913129638912", # By default, don't use these params TERMINAL_BLOCK_HASH: BlockHash.fromHex( "0x0000000000000000000000000000000000000000000000000000000000000000"), # Genesis # --------------------------------------------------------------- # `2**14` (= 16,384) MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 4096, # Dec 1, 2020, 12pm UTC MIN_GENESIS_TIME: 1638968400, # Mainnet initial fork version, recommend altering for testnets GENESIS_FORK_VERSION: Version [byte 0x00, 0x00, 0x00, 0x64], # 604800 seconds (7 days) GENESIS_DELAY: 604800, # 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: Version [byte 0x01, 0x00, 0x00, 0x64], ALTAIR_FORK_EPOCH: FAR_FUTURE_EPOCH, # Bellatrix BELLATRIX_FORK_VERSION: Version [byte 0x02, 0x00, 0x00, 0x64], BELLATRIX_FORK_EPOCH: FAR_FUTURE_EPOCH, # Capella CAPELLA_FORK_VERSION: Version [byte 0x03, 0x00, 0x00, 0x64], CAPELLA_FORK_EPOCH: FAR_FUTURE_EPOCH, # Deneb DENEB_FORK_VERSION: Version [byte 0x04, 0x00, 0x00, 0x64], DENEB_FORK_EPOCH: FAR_FUTURE_EPOCH, # Electra ELECTRA_FORK_VERSION: Version [byte 0x05, 0x00, 0x00, 0x64], ELECTRA_FORK_EPOCH: FAR_FUTURE_EPOCH, # Time parameters # --------------------------------------------------------------- # 12 seconds # TODO SECONDS_PER_SLOT: 12, # 14 (estimate from Eth1 mainnet) SECONDS_PER_ETH1_BLOCK: 5, # 2**8 (= 256) epochs ~27 hours MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256, # 2**8 (= 256) epochs ~27 hours SHARD_COMMITTEE_PERIOD: 256, # 2**11 (= 2,048) Eth1 blocks ~8 hours ETH1_FOLLOW_DISTANCE: 2048, # 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'u64, # 2**2 (= 4) MIN_PER_EPOCH_CHURN_LIMIT: 4, # 2**16 (= 65,536) CHURN_LIMIT_QUOTIENT: 4096, # [New in Deneb:EIP7514] 2**3 (= 8) MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 8, # [New in Electra:EIP7251] 2**7 * 10**9 (= 128,000,000,000) (copied from EF mainnet) MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 128000000000'u64, # [New in Electra:EIP7251] 2**8 * 10**9 (= 256,000,000,000) (copied from EF mainnet) MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 256000000000'u64, # Deposit contract # --------------------------------------------------------------- # Gnosis PoW Mainnet DEPOSIT_CHAIN_ID: 100, DEPOSIT_NETWORK_ID: 100, DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address), # Networking # --------------------------------------------------------------- # `10 * 2**20` (= 10485760, 10 MiB) # TODO GOSSIP_MAX_SIZE: 10485760, # `2**10` (= 1024) # TODO MAX_REQUEST_BLOCKS: 1024, # `2**8` (= 256) # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, # `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024, # `10 * 2**20` (=10485760, 10 MiB) # TODO MAX_CHUNK_SIZE: 10485760, # 5s # TODO TTFB_TIMEOUT: 5, # 10s # TODO RESP_TIMEOUT: 10, # TODO ATTESTATION_PROPAGATION_SLOT_RANGE: 32, # 500ms # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, # TODO MESSAGE_DOMAIN_INVALID_SNAPPY: [byte 0x00, 0x00, 0x00, 0x00], # TODO MESSAGE_DOMAIN_VALID_SNAPPY: [byte 0x01, 0x00, 0x00, 0x00], # 2 subnets per node # TODO SUBNETS_PER_NODE: 2, # 2**8 (= 64) # TODO ATTESTATION_SUBNET_COUNT: 64, # TODO ATTESTATION_SUBNET_EXTRA_BITS: 0, # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS # TODO ATTESTATION_SUBNET_PREFIX_BITS: 6, # Deneb # `2**7` (=128) # TODO MAX_REQUEST_BLOCKS_DENEB: 128, # MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK # TODO MAX_REQUEST_BLOB_SIDECARS: 768, # `2**12` (= 4096 epochs, ~18 days) MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 16384, # `6` # TODO BLOB_SIDECAR_SUBNET_COUNT: 6, ) elif const_preset == "minimal": import ./presets/minimal export minimal const SECONDS_PER_SLOT* {.intdefine.}: uint64 = 6 # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/configs/minimal.yaml const defaultRuntimeConfig* = RuntimeConfig( # Minimal config # Extends the minimal preset PRESET_BASE: "minimal", # Free-form short name of the network that this configuration applies to - known # canonical network names include: # * 'mainnet' - there can be only one # * 'sepolia' - testnet # * 'holesky' - testnet # Must match the regex: [a-z0-9\-] CONFIG_NAME: "minimal", # Transition # --------------------------------------------------------------- # 2**256-2**10 for testing minimal network TERMINAL_TOTAL_DIFFICULTY: u256"115792089237316195423570985008687907853269984665640564039457584007913129638912", # By default, don't use these params TERMINAL_BLOCK_HASH: BlockHash.fromHex( "0x0000000000000000000000000000000000000000000000000000000000000000"), # Genesis # --------------------------------------------------------------- # [customized] MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 64, # Jan 3, 2020 MIN_GENESIS_TIME: 1578009600, # Highest byte set to 0x01 to avoid collisions with mainnet versioning GENESIS_FORK_VERSION: Version [byte 0x00, 0x00, 0x00, 0x01], # [customized] Faster to spin up testnets, but does not give validator reasonable warning time for genesis GENESIS_DELAY: 300, # Forking # --------------------------------------------------------------- # Values provided for illustrative purposes. # Individual tests/testnets may set different values. # Altair ALTAIR_FORK_VERSION: Version [byte 0x01, 0x00, 0x00, 0x01], ALTAIR_FORK_EPOCH: Epoch(uint64.high), # Bellatrix BELLATRIX_FORK_VERSION: Version [byte 0x02, 0x00, 0x00, 0x01], BELLATRIX_FORK_EPOCH: Epoch(uint64.high), # Capella CAPELLA_FORK_VERSION: Version [byte 0x03, 0x00, 0x00, 0x01], CAPELLA_FORK_EPOCH: Epoch(uint64.high), # Deneb DENEB_FORK_VERSION: Version [byte 0x04, 0x00, 0x00, 0x01], DENEB_FORK_EPOCH: Epoch(uint64.high), # Electra ELECTRA_FORK_VERSION: Version [byte 0x05, 0x00, 0x00, 0x01], ELECTRA_FORK_EPOCH: Epoch(uint64.high), # Time parameters # --------------------------------------------------------------- # [customized] Faster for testing purposes # TODO SECONDS_PER_SLOT: 6, # 14 (estimate from Eth1 mainnet) SECONDS_PER_ETH1_BLOCK: 14, # 2**8 (= 256) epochs MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256, # [customized] higher frequency of committee turnover and faster time to acceptable voluntary exit SHARD_COMMITTEE_PERIOD: 64, # [customized] process deposits more quickly, but insecure ETH1_FOLLOW_DISTANCE: 16, # 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'u64, # [customized] more easily demonstrate the difference between this value and the activation churn limit MIN_PER_EPOCH_CHURN_LIMIT: 2, # [customized] scale queue churn at much lower validator counts for testing CHURN_LIMIT_QUOTIENT: 32, # [New in Deneb:EIP7514] [customized] MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 4, # [New in Electra:EIP7251] 2**6 * 10**9 (= 64,000,000,000) MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: 64000000000'u64, # [New in Electra:EIP7251] 2**7 * 10**9 (= 128,000,000,000) MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: 128000000000'u64, # Deposit contract # --------------------------------------------------------------- # Ethereum Goerli testnet DEPOSIT_CHAIN_ID: 5, DEPOSIT_NETWORK_ID: 5, # Configured on a per testnet basis DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address), # Networking # --------------------------------------------------------------- # `10 * 2**20` (= 10485760, 10 MiB) # TODO GOSSIP_MAX_SIZE: 10485760, # `2**10` (= 1024) # TODO MAX_REQUEST_BLOCKS: 1024, # `2**8` (= 256) # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, # [customized] `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 272) MIN_EPOCHS_FOR_BLOCK_REQUESTS: 272, # `10 * 2**20` (=10485760, 10 MiB) # TODO MAX_CHUNK_SIZE: 10485760, # 5s # TODO TTFB_TIMEOUT: 5, # 10s # TODO RESP_TIMEOUT: 10, # TODO ATTESTATION_PROPAGATION_SLOT_RANGE: 32, # 500ms # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, # TODO MESSAGE_DOMAIN_INVALID_SNAPPY: [byte 0x00, 0x00, 0x00, 0x00], # TODO MESSAGE_DOMAIN_VALID_SNAPPY: [byte 0x01, 0x00, 0x00, 0x00], # 2 subnets per node # TODO SUBNETS_PER_NODE: 2, # 2**8 (= 64) # TODO ATTESTATION_SUBNET_COUNT: 64, # TODO ATTESTATION_SUBNET_EXTRA_BITS: 0, # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS # TODO ATTESTATION_SUBNET_PREFIX_BITS: 6, # Deneb # `2**7` (=128) # TODO MAX_REQUEST_BLOCKS_DENEB: 128, # MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK # TODO MAX_REQUEST_BLOB_SIDECARS: 768, # `2**12` (= 4096 epochs, ~18 days) MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 4096, # `6` # TODO BLOB_SIDECAR_SUBNET_COUNT: 6, ) else: {.error: "Only mainnet, gnosis, and minimal presets supported".} # macro createConstantsFromPreset*(path: static string): untyped = # result = newStmtList() # let preset = try: readPresetFile(path) # except CatchableError as err: # error err.msg # TODO: This should be marked as noreturn # return # for name, value in preset.values: # let # typ = getType(name) # value = if typ in ["int64", "uint64", "byte"]: typ & "(" & value & ")" # else: "parse(" & typ & ", \"" & value & "\")" # try: # result.add parseStmt("const $1* {.intdefine.} = $2" % [$name, value]) # except ValueError: # doAssert false, "All values in the presets are printable" # if preset.missingValues.card > 0: # warning "Missing constants in preset: " & $preset.missingValues # createConstantsFromPreset const_preset const SLOTS_PER_SYNC_COMMITTEE_PERIOD* = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/p2p-interface.md#configuration func safeMinEpochsForBlockRequests*(cfg: RuntimeConfig): uint64 = cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY + cfg.CHURN_LIMIT_QUOTIENT div 2 func parse(T: type uint64, input: string): T {.raises: [ValueError].} = var res: BiggestUInt if input.len > 2 and input[0] == '0' and input[1] == 'x': if parseHex(input, res) != input.len: raise newException(ValueError, "The constant value should be a valid hex integer") else: if parseBiggestUInt(input, res) != input.len: raise newException(ValueError, "The constant value should be a valid unsigned integer") uint64(res) template parse(T: type byte, input: string): T = byte parse(uint64, input) func parse(T: type array[4, byte], input: string): T {.raises: [ValueError].} = hexToByteArray(input, 4) func parse(T: type Version, input: string): T {.raises: [ValueError].} = Version hexToByteArray(input, 4) template parse(T: type Slot, input: string): T = Slot parse(uint64, input) template parse(T: type Epoch, input: string): T = Epoch parse(uint64, input) template parse(T: type string, input: string): T = input.strip(chars = {'"', '\''}) template parse(T: type Eth1Address, input: string): T = Eth1Address.fromHex(input) template parse(T: type Hash32, input: string): T = Hash32.fromHex(input) template parse(T: type UInt256, input: string): T = parse(input, UInt256, 10) func parse(T: type DomainType, input: string): T {.raises: [ValueError].} = DomainType hexToByteArray(input, 4) proc readRuntimeConfig*( fileContent: string, path: string): (RuntimeConfig, seq[string]) {. raises: [PresetFileError, PresetIncompatibleError].} = var lineNum = 0 cfg = defaultRuntimeConfig template lineinfo: string = try: "$1($2) " % [path, $lineNum] except ValueError: path template fail(msg) = raise newException(PresetFileError, lineinfo() & msg) var names: seq[string] for name, field in cfg.fieldPairs(): names.add name var values: Table[string, string] for line in splitLines(fileContent): inc lineNum if line.len == 0 or line[0] == '#': continue # remove any trailing comments let line = line.split("#")[0] let lineParts = line.split(":") if lineParts.len != 2: fail "Invalid syntax: A preset file should include only assignments in the form 'ConstName: Value'" if lineParts[0] in ignoredValues: continue values[lineParts[0]] = lineParts[1].strip # Certain config keys are baked into the binary at compile-time # and cannot be overridden via config. template checkCompatibility( constValue: untyped, name: string, operator: untyped = `==`): untyped = if values.hasKey(name): const opDesc = astToStr(operator) try: let value = parse(typeof(constValue), values[name]) when constValue is distinct: if not operator(distinctBase(value), distinctBase(constValue)): raise (ref PresetFileError)(msg: "Cannot override config" & " (required: " & name & opDesc & $distinctBase(constValue) & " - config: " & name & "=" & values[name] & ")") else: if not operator(value, constValue): raise (ref PresetFileError)(msg: "Cannot override config" & " (required: " & name & opDesc & $constValue & " - config: " & name & "=" & values[name] & ")") values.del name except ValueError: raise (ref PresetFileError)(msg: "Unable to parse " & name) template checkCompatibility( constValue: untyped, operator: untyped = `==`): untyped = block: const name = astToStr(constValue) checkCompatibility(constValue, name, operator) checkCompatibility SECONDS_PER_SLOT checkCompatibility BLS_WITHDRAWAL_PREFIX checkCompatibility MAX_COMMITTEES_PER_SLOT checkCompatibility TARGET_COMMITTEE_SIZE checkCompatibility MAX_VALIDATORS_PER_COMMITTEE checkCompatibility SHUFFLE_ROUND_COUNT checkCompatibility HYSTERESIS_QUOTIENT checkCompatibility HYSTERESIS_DOWNWARD_MULTIPLIER checkCompatibility HYSTERESIS_UPWARD_MULTIPLIER checkCompatibility MIN_DEPOSIT_AMOUNT checkCompatibility MAX_EFFECTIVE_BALANCE checkCompatibility EFFECTIVE_BALANCE_INCREMENT checkCompatibility MIN_ATTESTATION_INCLUSION_DELAY checkCompatibility SLOTS_PER_EPOCH checkCompatibility MIN_SEED_LOOKAHEAD checkCompatibility MAX_SEED_LOOKAHEAD checkCompatibility EPOCHS_PER_ETH1_VOTING_PERIOD checkCompatibility SLOTS_PER_HISTORICAL_ROOT checkCompatibility MIN_EPOCHS_TO_INACTIVITY_PENALTY checkCompatibility EPOCHS_PER_HISTORICAL_VECTOR checkCompatibility EPOCHS_PER_SLASHINGS_VECTOR checkCompatibility HISTORICAL_ROOTS_LIMIT checkCompatibility VALIDATOR_REGISTRY_LIMIT checkCompatibility BASE_REWARD_FACTOR checkCompatibility WHISTLEBLOWER_REWARD_QUOTIENT checkCompatibility PROPOSER_REWARD_QUOTIENT checkCompatibility INACTIVITY_PENALTY_QUOTIENT checkCompatibility MIN_SLASHING_PENALTY_QUOTIENT checkCompatibility PROPORTIONAL_SLASHING_MULTIPLIER checkCompatibility MAX_PROPOSER_SLASHINGS checkCompatibility MAX_ATTESTER_SLASHINGS checkCompatibility MAX_ATTESTATIONS checkCompatibility MAX_DEPOSITS checkCompatibility MAX_VOLUNTARY_EXITS checkCompatibility TARGET_AGGREGATORS_PER_COMMITTEE checkCompatibility EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION checkCompatibility DOMAIN_BEACON_PROPOSER checkCompatibility DOMAIN_BEACON_ATTESTER checkCompatibility DOMAIN_RANDAO checkCompatibility DOMAIN_DEPOSIT checkCompatibility DOMAIN_VOLUNTARY_EXIT checkCompatibility DOMAIN_SELECTION_PROOF checkCompatibility DOMAIN_AGGREGATE_AND_PROOF checkCompatibility DOMAIN_SYNC_COMMITTEE checkCompatibility DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF checkCompatibility DOMAIN_CONTRIBUTION_AND_PROOF checkCompatibility GOSSIP_MAX_SIZE checkCompatibility MAX_REQUEST_BLOCKS checkCompatibility EPOCHS_PER_SUBNET_SUBSCRIPTION checkCompatibility MAX_CHUNK_SIZE checkCompatibility TTFB_TIMEOUT checkCompatibility RESP_TIMEOUT checkCompatibility ATTESTATION_PROPAGATION_SLOT_RANGE checkCompatibility MAXIMUM_GOSSIP_CLOCK_DISPARITY.milliseconds.uint64, "MAXIMUM_GOSSIP_CLOCK_DISPARITY" checkCompatibility MESSAGE_DOMAIN_INVALID_SNAPPY checkCompatibility MESSAGE_DOMAIN_VALID_SNAPPY checkCompatibility SUBNETS_PER_NODE checkCompatibility ATTESTATION_SUBNET_COUNT checkCompatibility ATTESTATION_SUBNET_EXTRA_BITS checkCompatibility ATTESTATION_SUBNET_PREFIX_BITS checkCompatibility MAX_REQUEST_BLOCKS_DENEB checkCompatibility MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK, "MAX_REQUEST_BLOB_SIDECARS" checkCompatibility BLOB_SIDECAR_SUBNET_COUNT # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/fork-choice.md#configuration # Isn't being used as a preset in the usual way: at any time, there's one correct value checkCompatibility PROPOSER_SCORE_BOOST checkCompatibility REORG_HEAD_WEIGHT_THRESHOLD checkCompatibility REORG_PARENT_WEIGHT_THRESHOLD checkCompatibility REORG_MAX_EPOCHS_SINCE_FINALIZATION for name, field in cfg.fieldPairs(): if name in values: try: field = parse(typeof(field), values[name]) values.del name except ValueError: raise (ref PresetFileError)(msg: "Unable to parse " & name) if cfg.PRESET_BASE != const_preset: raise (ref PresetIncompatibleError)( msg: "Config not compatible with binary, compile with -d:const_preset=" & cfg.PRESET_BASE) # Requires initialized `cfg` checkCompatibility cfg.safeMinEpochsForBlockRequests(), "MIN_EPOCHS_FOR_BLOCK_REQUESTS", `>=` var unknowns: seq[string] for name in values.keys: unknowns.add name (cfg, unknowns) proc readRuntimeConfig*( path: string): (RuntimeConfig, seq[string]) {. raises: [IOError, PresetFileError, PresetIncompatibleError].} = readRuntimeConfig(readFile(path), path) template name*(cfg: RuntimeConfig): string = if cfg.CONFIG_NAME.len() > 0: cfg.CONFIG_NAME else: const_preset func defaultLightClientDataMaxPeriods*(cfg: RuntimeConfig): uint64 = const epochsPerPeriod = EPOCHS_PER_SYNC_COMMITTEE_PERIOD let maxEpochs = cfg.MIN_EPOCHS_FOR_BLOCK_REQUESTS (maxEpochs + epochsPerPeriod - 1) div epochsPerPeriod