2020-07-02 15:14:11 +00:00
|
|
|
import
|
2020-07-07 23:02:14 +00:00
|
|
|
tables, strutils, os,
|
2020-07-03 19:29:23 +00:00
|
|
|
stew/byteutils, stew/shims/macros, nimcrypto/hash,
|
|
|
|
eth/common/[eth_types, eth_types_json_serialization],
|
2020-07-07 23:02:14 +00:00
|
|
|
spec/presets
|
2020-07-02 15:14:11 +00:00
|
|
|
|
|
|
|
# ATTENTION! This file will produce a large C file, because we are inlining
|
|
|
|
# genesis states as C literals in the generated code (and blobs in the final
|
|
|
|
# binary). It makes sense to keep the file small and separated from the rest
|
|
|
|
# of the module in order go gain maximum efficiency in incremental compilation.
|
|
|
|
#
|
|
|
|
# TODO:
|
|
|
|
# We can compress the embedded states with snappy before embedding them here.
|
|
|
|
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
|
|
|
|
export
|
2020-07-07 23:02:14 +00:00
|
|
|
eth_types_json_serialization, RuntimePreset
|
2020-07-02 15:14:11 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
Eth1Address* = eth_types.EthAddress
|
|
|
|
Eth1BlockHash* = eth_types.Hash256
|
|
|
|
|
|
|
|
Eth1Network* = enum
|
|
|
|
mainnet
|
|
|
|
rinkeby
|
|
|
|
goerli
|
|
|
|
|
|
|
|
Eth2Network* = enum
|
|
|
|
customEth2Network
|
|
|
|
altona
|
|
|
|
|
2020-07-03 19:29:23 +00:00
|
|
|
PresetIncompatible* = object of CatchableError
|
|
|
|
|
2020-07-02 15:14:11 +00:00
|
|
|
Eth2NetworkMetadata* = object
|
|
|
|
eth1Network*: Eth1Network
|
2020-07-03 19:29:23 +00:00
|
|
|
runtimePreset*: RuntimePreset
|
2020-07-02 15:14:11 +00:00
|
|
|
|
|
|
|
# Parsing `enr.Records` is still not possible at compile-time
|
|
|
|
bootstrapNodes*: seq[string]
|
|
|
|
|
|
|
|
depositContractAddress*: Eth1Address
|
|
|
|
depositContractDeployedAt*: Eth1BlockHash
|
|
|
|
|
|
|
|
# Please note that we are using `string` here because SSZ.decode
|
|
|
|
# is not currently usable at compile time and we want to load the
|
|
|
|
# network metadata into a constant.
|
|
|
|
#
|
|
|
|
# We could have also used `seq[byte]`, but this results in a lot
|
|
|
|
# more generated code that slows down compilation. The impact on
|
|
|
|
# compilation times of embedding the genesis as a string is roughly
|
|
|
|
# 0.1s on my machine (you can test this by choosing an invalid name
|
|
|
|
# for the genesis file below).
|
|
|
|
#
|
|
|
|
# `genesisData` will have `len == 0` for networks with a still
|
|
|
|
# unknown genesis state.
|
|
|
|
genesisData*: string
|
|
|
|
|
2020-07-07 23:02:14 +00:00
|
|
|
const presetValueLoaders = genExpr(nnkBracket):
|
2020-07-03 19:29:23 +00:00
|
|
|
for constName in PresetValue:
|
|
|
|
let
|
|
|
|
constNameIdent = ident $constName
|
|
|
|
constType = ident getType(constName)
|
|
|
|
|
|
|
|
yield quote do:
|
2020-07-07 23:02:14 +00:00
|
|
|
(
|
|
|
|
proc (preset: var RuntimePreset, presetValue: string): bool
|
|
|
|
{.gcsafe, noSideEffect, raises: [Defect].} =
|
|
|
|
try:
|
|
|
|
when PresetValue.`constNameIdent` in runtimeValues:
|
|
|
|
preset.`constNameIdent` = parse(`constType`, presetValue)
|
|
|
|
true
|
|
|
|
elif PresetValue.`constNameIdent` in ignoredValues:
|
|
|
|
true
|
|
|
|
else:
|
|
|
|
`constType`(`constNameIdent`) == parse(`constType`, presetValue)
|
|
|
|
except CatchableError as err:
|
|
|
|
false
|
|
|
|
)
|
|
|
|
|
|
|
|
proc extractRuntimePreset*(configPath: string, configData: PresetFile): RuntimePreset
|
|
|
|
{.raises: [PresetIncompatible, Defect].} =
|
|
|
|
result = RuntimePreset()
|
|
|
|
|
|
|
|
for name, value in configData.values:
|
|
|
|
if name notin runtimeValues:
|
|
|
|
if not presetValueLoaders[name.int](result, value):
|
|
|
|
let errMsg = "The preset '" & configPath & "'is not compatible with " &
|
|
|
|
"the current build due to an incompatible value " &
|
|
|
|
$name & " = " & value.string
|
|
|
|
raise newException(PresetIncompatible, errMsg)
|
2020-07-03 19:29:23 +00:00
|
|
|
|
2020-07-02 15:14:11 +00:00
|
|
|
proc loadEth2NetworkMetadata*(path: string): Eth2NetworkMetadata
|
|
|
|
{.raises: [CatchableError, Defect].} =
|
|
|
|
let
|
|
|
|
genesisPath = path / "genesis.ssz"
|
2020-07-07 23:02:14 +00:00
|
|
|
configPath = path / "config.yaml"
|
|
|
|
runtimePreset = extractRuntimePreset(configPath, readPresetFile(configPath))
|
2020-07-02 15:14:11 +00:00
|
|
|
|
|
|
|
Eth2NetworkMetadata(
|
|
|
|
eth1Network: goerli,
|
2020-07-03 19:29:23 +00:00
|
|
|
runtimePreset: runtimePreset,
|
2020-07-02 15:14:11 +00:00
|
|
|
bootstrapNodes: readFile(path / "bootstrap_nodes.txt").split("\n"),
|
|
|
|
depositContractAddress: Eth1Address.fromHex readFile(path / "deposit_contract.txt").strip,
|
|
|
|
depositContractDeployedAt: Eth1BlockHash.fromHex readFile(path / "deposit_contract_block.txt").strip,
|
|
|
|
genesisData: if fileExists(genesisPath): readFile(genesisPath) else: "")
|
|
|
|
|
2020-07-07 23:02:14 +00:00
|
|
|
when const_preset == "mainnet":
|
|
|
|
const
|
|
|
|
mainnetMetadata* = Eth2NetworkMetadata(
|
|
|
|
eth1Network: mainnet,
|
|
|
|
runtimePreset: mainnetRuntimePreset,
|
|
|
|
# TODO The values below are just placeholders for now
|
|
|
|
bootstrapNodes: @[],
|
|
|
|
depositContractAddress: Eth1Address.fromHex "0x1234567890123456789012345678901234567890",
|
|
|
|
depositContractDeployedAt: Eth1BlockHash.fromHex "0x73056f16a59bf70abad5b4365438e8a7d646aa0d7f56d22c3d9e4c6000d8e176",
|
|
|
|
genesisData: "")
|
|
|
|
|
|
|
|
altonaMetadata* = loadEth2NetworkMetadata(
|
|
|
|
currentSourcePath.parentDir / ".." / "vendor" / "eth2-testnets" / "shared" / "altona")
|
2020-07-02 15:14:11 +00:00
|
|
|
|