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:
parent
7bd9afa465
commit
3b9f0e3980
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue