Utilize Json flavor for Chain config parser (#1993)
This commit is contained in:
parent
94eda1f3e6
commit
edba847d42
|
@ -14,7 +14,6 @@ import
|
|||
eth/[common, rlp, p2p], stint, stew/[byteutils],
|
||||
json_serialization, chronicles,
|
||||
json_serialization/std/options as jsoptions,
|
||||
json_serialization/std/tables as jstable,
|
||||
json_serialization/lexer,
|
||||
"."/[genesis_alloc, hardforks]
|
||||
|
||||
|
@ -40,9 +39,10 @@ type
|
|||
parentBeaconBlockRoot*: Option[Hash256] # EIP-4788
|
||||
|
||||
GenesisAlloc* = Table[EthAddress, GenesisAccount]
|
||||
GenesisStorage* = Table[UInt256, UInt256]
|
||||
GenesisAccount* = object
|
||||
code* : seq[byte]
|
||||
storage*: Table[UInt256, UInt256]
|
||||
storage*: GenesisStorage
|
||||
balance*: UInt256
|
||||
nonce* : AccountNonce
|
||||
|
||||
|
@ -58,10 +58,26 @@ const
|
|||
SepoliaNet* = 11155111.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
|
||||
# ------------------------------------------------------------------------------
|
||||
proc writeValue(writer: var JsonWriter, value: Option[EthTime])
|
||||
proc writeValue(writer: var JsonWriter[JGenesis], value: Option[EthTime])
|
||||
{.gcsafe, raises: [IOError].} =
|
||||
mixin writeValue
|
||||
|
||||
|
@ -139,9 +155,15 @@ proc fromHex(c: char): int =
|
|||
of 'A'..'F': ord(c) - ord('A') + 10
|
||||
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].} =
|
||||
## 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
|
||||
## account `balance`.
|
||||
var (accu, ok) = (0.u256, true)
|
||||
|
@ -182,35 +204,31 @@ proc readValue(reader: var JsonReader, value: var UInt256)
|
|||
reader.raiseUnexpectedValue("Uint256 parse error")
|
||||
value = accu
|
||||
|
||||
proc readValue(reader: var JsonReader, value: var ChainId)
|
||||
proc readValue(reader: var JsonReader[JGenesis], value: var ChainId)
|
||||
{.gcsafe, raises: [SerializationError, IOError].} =
|
||||
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].} =
|
||||
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].} =
|
||||
try:
|
||||
wrapError:
|
||||
value = fromHex[uint64](reader.readValue(string)).toBlockNonce
|
||||
except ValueError as ex:
|
||||
reader.raiseUnexpectedValue(ex.msg)
|
||||
|
||||
# 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].} =
|
||||
try:
|
||||
wrapError:
|
||||
let data = reader.readValue(string)
|
||||
if data.len > 2 and data[1] == 'x':
|
||||
value = fromHex[int64](data).EthTime
|
||||
else:
|
||||
value = parseInt(data).EthTime
|
||||
except ValueError as ex:
|
||||
reader.raiseUnexpectedValue(ex.msg)
|
||||
|
||||
# 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].} =
|
||||
if reader.tokKind == JsonValueKind.Null:
|
||||
reset value
|
||||
|
@ -221,41 +239,37 @@ proc readValue(reader: var JsonReader, value: var Option[EthTime])
|
|||
let val = EthTime reader.parseInt(uint64)
|
||||
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].} =
|
||||
try:
|
||||
wrapError:
|
||||
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].} =
|
||||
try:
|
||||
wrapError:
|
||||
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].} =
|
||||
try:
|
||||
wrapError:
|
||||
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].} =
|
||||
try:
|
||||
wrapError:
|
||||
value = fromHex[uint64](reader.readValue(string))
|
||||
except ValueError as ex:
|
||||
reader.raiseUnexpectedValue(ex.msg)
|
||||
|
||||
template to(a: string, b: type EthAddress): EthAddress =
|
||||
# json_serialization decode table stuff
|
||||
parseAddress(a)
|
||||
proc readValue(reader: var JsonReader[JGenesis], value: var GenesisStorage)
|
||||
{.gcsafe, raises: [SerializationError, IOError].} =
|
||||
wrapError:
|
||||
for key in reader.readObjectFields:
|
||||
value[UInt256.fromHex(key)] = reader.readValue(UInt256)
|
||||
|
||||
template to(a: string, b: type UInt256): UInt256 =
|
||||
# json_serialization decode table stuff
|
||||
UInt256.fromHex(a)
|
||||
proc readValue(reader: var JsonReader[JGenesis], value: var GenesisAlloc)
|
||||
{.gcsafe, raises: [SerializationError, IOError].} =
|
||||
wrapError:
|
||||
for key in reader.readObjectFields:
|
||||
value[parseAddress(key)] = reader.readValue(GenesisAccount)
|
||||
|
||||
macro fillArrayOfBlockNumberBasedForkOptionals(conf, tmp: typed): untyped =
|
||||
result = newStmtList()
|
||||
|
@ -347,7 +361,7 @@ proc validateChainConfig*(conf: ChainConfig): bool =
|
|||
proc parseGenesis*(data: string): Genesis
|
||||
{.gcsafe.} =
|
||||
try:
|
||||
result = Json.decode(data, Genesis, allowUnknownFields = true)
|
||||
result = JGenesis.decode(data, Genesis, allowUnknownFields = true)
|
||||
except JsonReaderError as e:
|
||||
error "Invalid genesis config file format", msg=e.formatMsg("")
|
||||
return nil
|
||||
|
@ -359,7 +373,7 @@ proc parseGenesis*(data: string): Genesis
|
|||
proc parseGenesisFile*(fileName: string): Genesis
|
||||
{.gcsafe.} =
|
||||
try:
|
||||
result = Json.loadFile(fileName, Genesis, allowUnknownFields = true)
|
||||
result = JGenesis.loadFile(fileName, Genesis, allowUnknownFields = true)
|
||||
except IOError as e:
|
||||
error "Genesis I/O error", fileName, msg=e.msg
|
||||
return nil
|
||||
|
@ -389,7 +403,7 @@ proc validateNetworkParams(params: var NetworkParams, input: string, inputIsFile
|
|||
proc loadNetworkParams*(fileName: string, params: var NetworkParams):
|
||||
bool =
|
||||
try:
|
||||
params = Json.loadFile(fileName, NetworkParams, allowUnknownFields = true)
|
||||
params = JGenesis.loadFile(fileName, NetworkParams, allowUnknownFields = true)
|
||||
except IOError as e:
|
||||
error "Network params I/O error", fileName, msg=e.msg
|
||||
return false
|
||||
|
@ -405,7 +419,7 @@ proc loadNetworkParams*(fileName: string, params: var NetworkParams):
|
|||
|
||||
proc decodeNetworkParams*(jsonString: string, params: var NetworkParams): bool =
|
||||
try:
|
||||
params = Json.decode(jsonString, NetworkParams, allowUnknownFields = true)
|
||||
params = JGenesis.decode(jsonString, NetworkParams, allowUnknownFields = true)
|
||||
except JsonReaderError as e:
|
||||
error "Invalid network params format", msg=e.formatMsg("")
|
||||
return false
|
||||
|
@ -419,7 +433,7 @@ proc decodeNetworkParams*(jsonString: string, params: var NetworkParams): bool =
|
|||
proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool
|
||||
{.gcsafe, raises: [CatchableError].} =
|
||||
try:
|
||||
ga = Json.decode(data, GenesisAlloc, allowUnknownFields = true)
|
||||
ga = JGenesis.decode(data, GenesisAlloc, allowUnknownFields = true)
|
||||
except JsonReaderError as e:
|
||||
error "Invalid genesis config file format", msg=e.formatMsg("")
|
||||
return false
|
||||
|
|
Loading…
Reference in New Issue