Proper Uint256 parser for JSON genesis (#1071)

* Update exception tracinig

* Use lazy JSON parser

why:
  Uint246 type is not directly supported by the JSON serializer

* Json parser update for stringified UInt256 integers

why:
  Now available

* update sub-module branch reference
This commit is contained in:
Jordan Hrycaj 2022-05-06 09:02:28 +01:00 committed by GitHub
parent 7bd9afa465
commit 3b9f0e3980
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 26817 additions and 41 deletions

View File

@ -17,6 +17,8 @@ import
json_serialization/lexer,
"."/[forks, genesis_alloc]
{.push raises: [Defect].}
type
CliqueOptions = object
epoch : Option[int]
@ -135,60 +137,102 @@ const
GoerliNet* = 5.NetworkId
KovanNet* = 42.NetworkId
proc read(rlp: var Rlp, x: var AddressBalance, _: type EthAddress): EthAddress {.inline.} =
proc read(rlp: var Rlp, x: var AddressBalance, _: type EthAddress): EthAddress
{.gcsafe, raises: [Defect,RlpError].} =
let val = rlp.read(UInt256).toByteArrayBE()
result[0 .. ^1] = val.toOpenArray(12, val.high)
proc read(rlp: var Rlp, x: var AddressBalance, _: type GenesisAccount): GenesisAccount {.inline.} =
proc read(rlp: var Rlp, x: var AddressBalance, _: type GenesisAccount): GenesisAccount
{.gcsafe, raises: [Defect,RlpError].} =
GenesisAccount(balance: rlp.read(UInt256))
func decodePrealloc*(data: seq[byte]): GenesisAlloc =
func decodePrealloc*(data: seq[byte]): GenesisAlloc
{.gcsafe, raises: [Defect,RlpError].} =
for tup in rlp.decode(data, seq[AddressBalance]):
result[tup.address] = tup.account
proc readValue(reader: var JsonReader, value: var UInt256) =
# borrowed from `lexer.hexCharValue()` :)
proc fromHex(c: char): int =
case c
of '0'..'9': ord(c) - ord('0')
of 'a'..'f': ord(c) - ord('a') + 10
of 'A'..'F': ord(c) - ord('A') + 10
else: -1
proc readValue(reader: var JsonReader, value: var UInt256)
{.gcsafe, raises: [Defect,CatchableError].} =
## Mixin for `Json.loadFile()`. Note that this driver applies the same
## to `BlockNumber` fields as well as generic `UInt265` fields like the
## account `balance`.
let tok = reader.lexer.tok
if tok == tkInt:
value = reader.lexer.absIntVal.u256
reader.lexer.next()
elif tok == tkString:
# Make sure that "0x11" decodes to 17, "b" and "11" decode to 11.
if reader.lexer.strVal.filterIt(it.isDigit.not).len == 0:
try: value = reader.lexer.strVal.parse(UInt256, radix = 10)
except: reader.raiseUnexpectedValue("int string overflow")
else:
# note that radix is static, so 16 (or 10) cannot be a variable
try: value = reader.lexer.strVal.parse(UInt256, radix = 16)
except: reader.raiseUnexpectedValue("hex string parse error")
reader.lexer.next()
var (accu, ok) = (0.u256, true)
if reader.lexer.lazyTok == tkNumeric:
try:
reader.lexer.customIntValueIt:
accu = accu * 10 + it.u256
ok = reader.lexer.lazyTok == tkExInt # non-negative wanted
except:
ok = false
elif reader.lexer.lazyTok == tkQuoted:
try:
var (sLen, base) = (0, 10)
reader.lexer.customTextValueIt:
if ok:
var num = it.fromHex
if base <= num:
ok = false # cannot be larger than base
elif sLen < 2:
if 0 <= num:
accu = accu * base.u256 + num.u256
elif sLen == 1 and it in {'x', 'X'}:
base = 16 # handle "0x" prefix
else:
ok = false
sLen.inc
elif num < 0:
ok = false # not a hex digit
elif base == 10:
accu = accu * 10 + num.u256
else:
accu = accu * 16 + num.u256
except:
reader.raiseUnexpectedValue("numeric string parse error")
else:
reader.raiseUnexpectedValue("expect int or hex/int string")
if not ok:
reader.raiseUnexpectedValue("Uint256 parse error")
value = accu
reader.lexer.next()
proc readValue(reader: var JsonReader, value: var ChainId) =
proc readValue(reader: var JsonReader, value: var ChainId)
{.gcsafe, raises: [Defect,CatchableError].} =
value = reader.readValue(int).ChainId
proc readValue(reader: var JsonReader, value: var Hash256) =
proc readValue(reader: var JsonReader, value: var Hash256)
{.gcsafe, raises: [Defect,CatchableError].} =
value = Hash256.fromHex(reader.readValue(string))
proc readValue(reader: var JsonReader, value: var BlockNonce) =
proc readValue(reader: var JsonReader, value: var BlockNonce)
{.gcsafe, raises: [Defect,CatchableError].} =
value = fromHex[uint64](reader.readValue(string)).toBlockNonce
proc readValue(reader: var JsonReader, value: var EthTime) =
proc readValue(reader: var JsonReader, value: var EthTime)
{.gcsafe, raises: [Defect,CatchableError].} =
value = fromHex[int64](reader.readValue(string)).fromUnix
proc readValue(reader: var JsonReader, value: var seq[byte]) =
proc readValue(reader: var JsonReader, value: var seq[byte])
{.gcsafe, raises: [Defect,CatchableError].} =
value = hexToSeqByte(reader.readValue(string))
proc readValue(reader: var JsonReader, value: var GasInt) =
proc readValue(reader: var JsonReader, value: var GasInt)
{.gcsafe, raises: [Defect,CatchableError].} =
value = fromHex[GasInt](reader.readValue(string))
proc readValue(reader: var JsonReader, value: var EthAddress) =
proc readValue(reader: var JsonReader, value: var EthAddress)
{.gcsafe, raises: [Defect,CatchableError].} =
value = parseAddress(reader.readValue(string))
proc readValue(reader: var JsonReader, value: var AccountNonce) =
proc readValue(reader: var JsonReader, value: var AccountNonce)
{.gcsafe, raises: [Defect,CatchableError].} =
value = fromHex[uint64](reader.readValue(string))
template to(a: string, b: type EthAddress): EthAddress =
@ -199,9 +243,7 @@ template to(a: string, b: type UInt256): UInt256 =
# json_serialization decode table stuff
UInt256.fromHex(a)
proc loadNetworkParams*(cc: CustomChain, cg: var NetworkParams):
bool {.raises: [Defect].} =
proc loadNetworkParams*(cc: CustomChain, cg: var NetworkParams): bool =
cg.genesis = cc.genesis
cg.config.chainId = cc.config.chainId
cg.config.daoForkSupport = cc.config.daoForkSupport
@ -265,7 +307,7 @@ proc loadNetworkParams*(cc: CustomChain, cg: var NetworkParams):
return true
proc loadNetworkParams*(fileName: string, cg: var NetworkParams):
bool {.raises: [Defect].} =
bool {.raises: [Defect,SerializationError].} =
var cc: CustomChain
try:
cc = Json.loadFile(fileName, CustomChain, allowUnknownFields = true)
@ -275,15 +317,14 @@ proc loadNetworkParams*(fileName: string, cg: var NetworkParams):
except JsonReaderError as e:
error "Invalid network params file format", fileName, msg=e.formatMsg("")
return false
except:
var msg = getCurrentExceptionMsg()
error "Error loading network params file", fileName, msg
except Exception as e:
error "Error loading network params file",
fileName, exception = e.name, msg = e.msg
return false
loadNetworkParams(cc, cg)
proc decodeNetworkParams*(jsonString: string, cg: var NetworkParams):
bool {.raises: [Defect].} =
proc decodeNetworkParams*(jsonString: string, cg: var NetworkParams): bool =
var cc: CustomChain
try:
@ -298,7 +339,8 @@ proc decodeNetworkParams*(jsonString: string, cg: var NetworkParams):
loadNetworkParams(cc, cg)
proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool =
proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool
{.gcsafe, raises: [Defect,CatchableError].} =
try:
ga = Json.decode(data, GenesisAlloc, allowUnknownFields = true)
except JsonReaderError as e:
@ -414,7 +456,8 @@ proc chainConfigForNetwork(id: NetworkId): ChainConfig =
else:
ChainConfig()
proc genesisBlockForNetwork(id: NetworkId): Genesis =
proc genesisBlockForNetwork(id: NetworkId): Genesis
{.gcsafe, raises: [Defect,CatchableError].} =
result = case id
of MainNet:
Genesis(
@ -453,6 +496,7 @@ proc genesisBlockForNetwork(id: NetworkId): Genesis =
else:
Genesis()
proc networkParams*(id: NetworkId): NetworkParams =
proc networkParams*(id: NetworkId): NetworkParams
{.gcsafe, raises: [Defect,CatchableError].} =
result.genesis = genesisBlockForNetwork(id)
result.config = chainConfigForNetwork(id)

File diff suppressed because it is too large Load Diff

View File

@ -76,9 +76,22 @@ proc customGenesisTest() =
check h.blockHash == genesisHash
check cg.config.poaEngine == false
test "Mainnet shadow fork 1":
var cg: NetworkParams
check loadNetworkParams("mainshadow1.json".findFilePath, cg)
let h = cg.toGenesisHeader
let stateRoot = "d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544".toDigest
let genesisHash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3".toDigest
let ttd = "46_089_003_871_917_200_000_000".parse(Uint256)
check h.stateRoot == stateRoot
check h.blockHash == genesisHash
check cg.config.terminalTotalDifficulty.get == ttd
check cg.config.poaEngine == false
proc genesisMain*() =
genesisTest()
customGenesisTest()
when isMainModule:
genesisMain()
genesisTest()
customGenesisTest()

@ -1 +1 @@
Subproject commit c5f0e2465e8375dfc7aa0f56ccef67cb680bc6b0
Subproject commit 3509706517f3562cbcbe9d94988eccdd80474ab8

@ -1 +1 @@
Subproject commit fcd0eadadde0ee000a63df8ab21dc4e9f015a790
Subproject commit 9631fbd1c81c8b25ff8740df440ca7ba87fa6131