nimbus-eth2/beacon_chain/spec/presets.nim

236 lines
6.7 KiB
Nim

import
macros, strutils, parseutils, tables,
stew/endians2
{.push raises: [Defect].}
export
toBytesBE
type
Slot* = distinct uint64
Epoch* = distinct uint64
Version* = distinct array[4, byte]
PresetValue* {.pure.} = enum
BASE_REWARD_FACTOR
BLS_WITHDRAWAL_PREFIX
CHURN_LIMIT_QUOTIENT
DEPOSIT_CONTRACT_ADDRESS
DOMAIN_AGGREGATE_AND_PROOF
DOMAIN_BEACON_ATTESTER
DOMAIN_BEACON_PROPOSER
DOMAIN_DEPOSIT
DOMAIN_RANDAO
DOMAIN_SELECTION_PROOF
DOMAIN_VOLUNTARY_EXIT
EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE
EFFECTIVE_BALANCE_INCREMENT
EJECTION_BALANCE
EPOCHS_PER_ETH1_VOTING_PERIOD
EPOCHS_PER_HISTORICAL_VECTOR
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION
EPOCHS_PER_SLASHINGS_VECTOR
ETH1_FOLLOW_DISTANCE
GENESIS_FORK_VERSION
GENESIS_DELAY
HISTORICAL_ROOTS_LIMIT
HYSTERESIS_DOWNWARD_MULTIPLIER
HYSTERESIS_QUOTIENT
HYSTERESIS_UPWARD_MULTIPLIER
INACTIVITY_PENALTY_QUOTIENT
MAX_ATTESTATIONS
MAX_ATTESTER_SLASHINGS
MAX_COMMITTEES_PER_SLOT
MAX_DEPOSITS
MAX_EFFECTIVE_BALANCE
MAX_EPOCHS_PER_CROSSLINK
MAX_PROPOSER_SLASHINGS
MAX_SEED_LOOKAHEAD
MAX_VALIDATORS_PER_COMMITTEE
MAX_VOLUNTARY_EXITS
MIN_ATTESTATION_INCLUSION_DELAY
MIN_DEPOSIT_AMOUNT
MIN_EPOCHS_TO_INACTIVITY_PENALTY
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
MIN_GENESIS_TIME
MIN_PER_EPOCH_CHURN_LIMIT
MIN_SEED_LOOKAHEAD
MIN_SLASHING_PENALTY_QUOTIENT
MIN_VALIDATOR_WITHDRAWABILITY_DELAY
PROPOSER_REWARD_QUOTIENT
RANDOM_SUBNETS_PER_VALIDATOR
SAFE_SLOTS_TO_UPDATE_JUSTIFIED
SECONDS_PER_ETH1_BLOCK
SECONDS_PER_SLOT
SHARD_COMMITTEE_PERIOD
SHUFFLE_ROUND_COUNT
SLOTS_PER_EPOCH
SLOTS_PER_HISTORICAL_ROOT
TARGET_AGGREGATORS_PER_COMMITTEE
TARGET_COMMITTEE_SIZE
VALIDATOR_REGISTRY_LIMIT
WHISTLEBLOWER_REWARD_QUOTIENT
RuntimePreset* = object
GENESIS_FORK_VERSION*: Version
GENESIS_DELAY*: uint64
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT*: uint64
MIN_GENESIS_TIME*: uint64
PresetFile* = object
values*: Table[PresetValue, TaintedString]
missingValues*: set[PresetValue]
PresetFileError* = object of CatchableError
const
const_preset* {.strdefine.} = "mainnet"
runtimeValues* = {
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT,
MIN_GENESIS_TIME,
GENESIS_FORK_VERSION,
GENESIS_DELAY,
}
# These constants cannot really be overriden in a preset.
# If we encounter them, we'll just ignore the preset value.
ignoredValues* = {
# The deposit contract address is loaded through a dedicated
# metadata file. It would break the property we are exploiting
# right now that all preset values can be parsed as uint64
DEPOSIT_CONTRACT_ADDRESS,
# These are defined as an enum in datatypes.nim:
DOMAIN_BEACON_PROPOSER,
DOMAIN_BEACON_ATTESTER,
DOMAIN_RANDAO,
DOMAIN_DEPOSIT,
DOMAIN_VOLUNTARY_EXIT,
DOMAIN_SELECTION_PROOF,
DOMAIN_AGGREGATE_AND_PROOF,
}
presetValueTypes* = {
BLS_WITHDRAWAL_PREFIX: "byte",
GENESIS_FORK_VERSION: "Version",
}.toTable
func parse*(T: type uint64, input: string): T
{.raises: [ValueError, Defect].} =
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")
result = uint64(res)
template parse*(T: type byte, input: string): T =
byte parse(uint64, input)
template parse*(T: type int, input: string): T =
# TODO: remove this
int parse(uint64, input)
proc parse*(T: type Version, input: string): T
{.raises: [ValueError, Defect].} =
Version toBytesBE(uint32 parse(uint64, input))
template parse*(T: type Slot, input: string): T =
Slot parse(uint64, input)
template getType*(presetValue: PresetValue): string =
presetValueTypes.getOrDefault(presetValue, "uint64")
template toUInt64*(v: Version): uint64 =
fromBytesBE(uint64, array[4, byte](v))
template entireSet(T: type enum): untyped =
{low(T) .. high(T)}
proc readPresetFile*(path: string): PresetFile
{.raises: [IOError, PresetFileError, Defect].} =
var
lineNum = 0
presetValues = ignoredValues
template lineinfo: string =
try: "$1($2) " % [path, $lineNum]
except ValueError: path
template fail(msg) =
raise newException(PresetFileError, lineinfo() & msg)
for line in splitLines(readFile(path)):
inc lineNum
if line.len == 0 or line[0] == '#': continue
var lineParts = line.split(":")
if lineParts.len != 2:
fail "Invalid syntax: A preset file should include only assignments in the form 'ConstName: Value'"
let value = try: parseEnum[PresetValue](lineParts[0])
except ValueError: fail "Unrecognized constant in a preset: " & lineParts[0]
if value in ignoredValues: continue
presetValues.incl value
result.values.add value, lineParts[1].strip
result.missingValues = PresetValue.entireSet - presetValues
const
mainnetRuntimePreset* = RuntimePreset(
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384,
MIN_GENESIS_TIME: 1578009600,
GENESIS_FORK_VERSION: Version [byte 0, 0, 0, 0],
GENESIS_DELAY: 172800)
minimalRuntimePreset* = RuntimePreset(
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 64,
MIN_GENESIS_TIME: 1578009600,
GENESIS_FORK_VERSION: Version [byte 0, 0, 0, 1],
GENESIS_DELAY: 300)
when const_preset == "mainnet":
template defaultRuntimePreset*: auto = mainnetRuntimePreset
import ./presets/v0_12_1/mainnet
export mainnet
elif const_preset == "minimal":
template defaultRuntimePreset*: auto = minimalRuntimePreset
import ./presets/v0_12_1/minimal
export minimal
else:
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:
var value = string value
if presetValueTypes.hasKey(name):
let typ = presetValueTypes[name]
value = typ & "(" & value & ")"
result.add parseStmt("const $1* {.intdefine.} = $2" % [$name, value])
if preset.missingValues.card > 0:
warning "Missing constants in preset: " & $preset.missingValues
createConstantsFromPreset const_preset
const defaultRuntimePreset* = RuntimePreset(
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: MIN_GENESIS_ACTIVE_VALIDATOR_COUNT,
MIN_GENESIS_TIME: MIN_GENESIS_TIME,
GENESIS_FORK_VERSION: GENESIS_FORK_VERSION,
GENESIS_DELAY: GENESIS_DELAY)