Utilize Json flavor for Chain config parser (#1993)

This commit is contained in:
andri lim 2024-01-28 08:52:20 +07:00 committed by GitHub
parent 94eda1f3e6
commit edba847d42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -14,7 +14,6 @@ import
eth/[common, rlp, p2p], stint, stew/[byteutils], eth/[common, rlp, p2p], stint, stew/[byteutils],
json_serialization, chronicles, json_serialization, chronicles,
json_serialization/std/options as jsoptions, json_serialization/std/options as jsoptions,
json_serialization/std/tables as jstable,
json_serialization/lexer, json_serialization/lexer,
"."/[genesis_alloc, hardforks] "."/[genesis_alloc, hardforks]
@ -40,9 +39,10 @@ type
parentBeaconBlockRoot*: Option[Hash256] # EIP-4788 parentBeaconBlockRoot*: Option[Hash256] # EIP-4788
GenesisAlloc* = Table[EthAddress, GenesisAccount] GenesisAlloc* = Table[EthAddress, GenesisAccount]
GenesisStorage* = Table[UInt256, UInt256]
GenesisAccount* = object GenesisAccount* = object
code* : seq[byte] code* : seq[byte]
storage*: Table[UInt256, UInt256] storage*: GenesisStorage
balance*: UInt256 balance*: UInt256
nonce* : AccountNonce nonce* : AccountNonce
@ -58,10 +58,26 @@ const
SepoliaNet* = 11155111.NetworkId SepoliaNet* = 11155111.NetworkId
HoleskyNet* = 17000.NetworkId HoleskyNet* = 17000.NetworkId
createJsonFlavor JGenesis,
automaticObjectSerialization = false,
requireAllFields = false,
omitOptionalFields = true,
allowUnknownFields = true,
skipNullFields = true
template derefType(T: type): untyped =
typeof(T()[])
NetworkParams.useDefaultReaderIn JGenesis
GenesisAccount.useDefaultReaderIn JGenesis
derefType(Genesis).useDefaultReaderIn JGenesis
derefType(ChainConfig).useDefaultReaderIn JGenesis
CliqueOptions.useDefaultReaderIn JGenesis
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Private helper functions # Private helper functions
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
proc writeValue(writer: var JsonWriter, value: Option[EthTime]) proc writeValue(writer: var JsonWriter[JGenesis], value: Option[EthTime])
{.gcsafe, raises: [IOError].} = {.gcsafe, raises: [IOError].} =
mixin writeValue mixin writeValue
@ -139,9 +155,15 @@ proc fromHex(c: char): int =
of 'A'..'F': ord(c) - ord('A') + 10 of 'A'..'F': ord(c) - ord('A') + 10
else: -1 else: -1
proc readValue(reader: var JsonReader, value: var UInt256) template wrapError(body: untyped) =
try:
body
except ValueError as ex:
raiseUnexpectedValue(reader, ex.msg)
proc readValue(reader: var JsonReader[JGenesis], value: var UInt256)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
## Mixin for `Json.loadFile()`. Note that this driver applies the same ## Mixin for `JGenesis.loadFile()`. Note that this driver applies the same
## to `BlockNumber` fields as well as generic `UInt265` fields like the ## to `BlockNumber` fields as well as generic `UInt265` fields like the
## account `balance`. ## account `balance`.
var (accu, ok) = (0.u256, true) var (accu, ok) = (0.u256, true)
@ -182,35 +204,31 @@ proc readValue(reader: var JsonReader, value: var UInt256)
reader.raiseUnexpectedValue("Uint256 parse error") reader.raiseUnexpectedValue("Uint256 parse error")
value = accu value = accu
proc readValue(reader: var JsonReader, value: var ChainId) proc readValue(reader: var JsonReader[JGenesis], value: var ChainId)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
value = reader.readValue(int).ChainId value = reader.readValue(int).ChainId
proc readValue(reader: var JsonReader, value: var Hash256) proc readValue(reader: var JsonReader[JGenesis], value: var Hash256)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
value = Hash256.fromHex(reader.readValue(string)) value = Hash256.fromHex(reader.readValue(string))
proc readValue(reader: var JsonReader, value: var BlockNonce) proc readValue(reader: var JsonReader[JGenesis], value: var BlockNonce)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
try: wrapError:
value = fromHex[uint64](reader.readValue(string)).toBlockNonce value = fromHex[uint64](reader.readValue(string)).toBlockNonce
except ValueError as ex:
reader.raiseUnexpectedValue(ex.msg)
# genesis timestamp is in hex/dec # genesis timestamp is in hex/dec
proc readValue(reader: var JsonReader, value: var EthTime) proc readValue(reader: var JsonReader[JGenesis], value: var EthTime)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
try: wrapError:
let data = reader.readValue(string) let data = reader.readValue(string)
if data.len > 2 and data[1] == 'x': if data.len > 2 and data[1] == 'x':
value = fromHex[int64](data).EthTime value = fromHex[int64](data).EthTime
else: else:
value = parseInt(data).EthTime value = parseInt(data).EthTime
except ValueError as ex:
reader.raiseUnexpectedValue(ex.msg)
# but shanghaiTime and cancunTime in config is in int literal # but shanghaiTime and cancunTime in config is in int literal
proc readValue(reader: var JsonReader, value: var Option[EthTime]) proc readValue(reader: var JsonReader[JGenesis], value: var Option[EthTime])
{.gcsafe, raises: [IOError, JsonReaderError].} = {.gcsafe, raises: [IOError, JsonReaderError].} =
if reader.tokKind == JsonValueKind.Null: if reader.tokKind == JsonValueKind.Null:
reset value reset value
@ -221,41 +239,37 @@ proc readValue(reader: var JsonReader, value: var Option[EthTime])
let val = EthTime reader.parseInt(uint64) let val = EthTime reader.parseInt(uint64)
value = some val value = some val
proc readValue(reader: var JsonReader, value: var seq[byte]) proc readValue(reader: var JsonReader[JGenesis], value: var seq[byte])
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
try: wrapError:
value = hexToSeqByte(reader.readValue(string)) value = hexToSeqByte(reader.readValue(string))
except ValueError as ex:
reader.raiseUnexpectedValue(ex.msg)
proc readValue(reader: var JsonReader, value: var GasInt) proc readValue(reader: var JsonReader[JGenesis], value: var GasInt)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
try: wrapError:
value = fromHex[GasInt](reader.readValue(string)) value = fromHex[GasInt](reader.readValue(string))
except ValueError as ex:
reader.raiseUnexpectedValue(ex.msg)
proc readValue(reader: var JsonReader, value: var EthAddress) proc readValue(reader: var JsonReader[JGenesis], value: var EthAddress)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
try: wrapError:
value = parseAddress(reader.readValue(string)) value = parseAddress(reader.readValue(string))
except ValueError as ex:
reader.raiseUnexpectedValue(ex.msg)
proc readValue(reader: var JsonReader, value: var AccountNonce) proc readValue(reader: var JsonReader[JGenesis], value: var AccountNonce)
{.gcsafe, raises: [SerializationError, IOError].} = {.gcsafe, raises: [SerializationError, IOError].} =
try: wrapError:
value = fromHex[uint64](reader.readValue(string)) value = fromHex[uint64](reader.readValue(string))
except ValueError as ex:
reader.raiseUnexpectedValue(ex.msg)
template to(a: string, b: type EthAddress): EthAddress = proc readValue(reader: var JsonReader[JGenesis], value: var GenesisStorage)
# json_serialization decode table stuff {.gcsafe, raises: [SerializationError, IOError].} =
parseAddress(a) wrapError:
for key in reader.readObjectFields:
value[UInt256.fromHex(key)] = reader.readValue(UInt256)
template to(a: string, b: type UInt256): UInt256 = proc readValue(reader: var JsonReader[JGenesis], value: var GenesisAlloc)
# json_serialization decode table stuff {.gcsafe, raises: [SerializationError, IOError].} =
UInt256.fromHex(a) wrapError:
for key in reader.readObjectFields:
value[parseAddress(key)] = reader.readValue(GenesisAccount)
macro fillArrayOfBlockNumberBasedForkOptionals(conf, tmp: typed): untyped = macro fillArrayOfBlockNumberBasedForkOptionals(conf, tmp: typed): untyped =
result = newStmtList() result = newStmtList()
@ -347,7 +361,7 @@ proc validateChainConfig*(conf: ChainConfig): bool =
proc parseGenesis*(data: string): Genesis proc parseGenesis*(data: string): Genesis
{.gcsafe.} = {.gcsafe.} =
try: try:
result = Json.decode(data, Genesis, allowUnknownFields = true) result = JGenesis.decode(data, Genesis, allowUnknownFields = true)
except JsonReaderError as e: except JsonReaderError as e:
error "Invalid genesis config file format", msg=e.formatMsg("") error "Invalid genesis config file format", msg=e.formatMsg("")
return nil return nil
@ -359,7 +373,7 @@ proc parseGenesis*(data: string): Genesis
proc parseGenesisFile*(fileName: string): Genesis proc parseGenesisFile*(fileName: string): Genesis
{.gcsafe.} = {.gcsafe.} =
try: try:
result = Json.loadFile(fileName, Genesis, allowUnknownFields = true) result = JGenesis.loadFile(fileName, Genesis, allowUnknownFields = true)
except IOError as e: except IOError as e:
error "Genesis I/O error", fileName, msg=e.msg error "Genesis I/O error", fileName, msg=e.msg
return nil return nil
@ -389,7 +403,7 @@ proc validateNetworkParams(params: var NetworkParams, input: string, inputIsFile
proc loadNetworkParams*(fileName: string, params: var NetworkParams): proc loadNetworkParams*(fileName: string, params: var NetworkParams):
bool = bool =
try: try:
params = Json.loadFile(fileName, NetworkParams, allowUnknownFields = true) params = JGenesis.loadFile(fileName, NetworkParams, allowUnknownFields = true)
except IOError as e: except IOError as e:
error "Network params I/O error", fileName, msg=e.msg error "Network params I/O error", fileName, msg=e.msg
return false return false
@ -405,7 +419,7 @@ proc loadNetworkParams*(fileName: string, params: var NetworkParams):
proc decodeNetworkParams*(jsonString: string, params: var NetworkParams): bool = proc decodeNetworkParams*(jsonString: string, params: var NetworkParams): bool =
try: try:
params = Json.decode(jsonString, NetworkParams, allowUnknownFields = true) params = JGenesis.decode(jsonString, NetworkParams, allowUnknownFields = true)
except JsonReaderError as e: except JsonReaderError as e:
error "Invalid network params format", msg=e.formatMsg("") error "Invalid network params format", msg=e.formatMsg("")
return false return false
@ -419,7 +433,7 @@ proc decodeNetworkParams*(jsonString: string, params: var NetworkParams): bool =
proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool
{.gcsafe, raises: [CatchableError].} = {.gcsafe, raises: [CatchableError].} =
try: try:
ga = Json.decode(data, GenesisAlloc, allowUnknownFields = true) ga = JGenesis.decode(data, GenesisAlloc, allowUnknownFields = true)
except JsonReaderError as e: except JsonReaderError as e:
error "Invalid genesis config file format", msg=e.formatMsg("") error "Invalid genesis config file format", msg=e.formatMsg("")
return false return false