nimbus-eth1/tests/test_difficulty.nim

128 lines
3.8 KiB
Nim
Raw Normal View History

2023-11-01 03:32:09 +00:00
# Nimbus
# Copyright (c) 2019-2024 Status Research & Development GmbH
2023-11-01 03:32:09 +00:00
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
2022-12-02 04:39:12 +00:00
import
std/[strutils, tables, os, json],
2022-12-02 04:39:12 +00:00
unittest2,
stew/byteutils,
../nimbus/core/pow/difficulty,
../nimbus/constants,
../nimbus/common/common,
2023-05-22 08:12:50 +00:00
./test_helpers
2019-08-23 15:54:25 +00:00
type
Tester = object
parentTimestamp: int64
parentDifficulty: UInt256
parentUncles: Hash32
2019-08-23 15:54:25 +00:00
currentTimestamp: int64
currentBlockNumber: uint64
currentDifficulty: UInt256
2019-08-23 15:54:25 +00:00
Tests = Table[string, Tester]
2023-05-22 08:12:50 +00:00
const
inputPath = "tests" / "fixtures" / "eth_tests" / "DifficultyTests"
2019-08-23 15:54:25 +00:00
proc hexOrInt64(data: JsonNode, key: string, hex: static[bool]): int64 =
when hex:
getHexadecimalInt data[key]
else:
int64(parseInt data[key].getStr)
proc hexOrInt256(data: JsonNode, key: string, hex: static[bool]): UInt256 =
2019-08-23 15:54:25 +00:00
when hex:
UInt256.fromHex data[key].getStr
else:
parse(data[key].getStr, UInt256)
2019-08-23 15:54:25 +00:00
proc parseHash(data: string): Hash32 =
2023-05-22 08:12:50 +00:00
case data
of "0x00": result = EMPTY_UNCLE_HASH
of "0x01": result.data[0] = 1.byte
else:
doAssert(false, "invalid uncle hash")
2019-08-23 15:54:25 +00:00
proc parseTests(testData: JsonNode): Tests =
2023-05-22 08:12:50 +00:00
const hex = true
result = Table[string, Tester]()
2019-08-23 15:54:25 +00:00
var t: Tester
2023-05-22 08:12:50 +00:00
for title, data in testData:
2019-08-23 15:54:25 +00:00
t.parentTimestamp = hexOrInt64(data, "parentTimestamp", hex)
t.parentDifficulty = hexOrInt256(data, "parentDifficulty", hex)
2020-02-20 03:43:47 +00:00
let pu = data.fields.getOrDefault("parentUncles")
if pu.isNil:
t.parentUncles = EMPTY_UNCLE_HASH
else:
2023-05-22 08:12:50 +00:00
t.parentUncles = parseHash(pu.getStr)
2019-08-23 15:54:25 +00:00
t.currentTimestamp = hexOrInt64(data, "currentTimestamp", hex)
t.currentBlockNumber = uint64 hexOrInt64(data, "currentBlockNumber", hex)
2019-08-23 15:54:25 +00:00
t.currentDifficulty = hexOrInt256(data, "currentDifficulty", hex)
result[title] = t
proc calculator(revision: string, timestamp: EthTime, header: Header): DifficultyInt =
2023-05-22 08:12:50 +00:00
case revision
of "Homestead": result = calcDifficultyHomestead(timestamp, header)
of "GrayGlacier": result = calcDifficultyGrayGlacier(timestamp, header)
of "Frontier": result = calcDifficultyFrontier(timestamp, header)
of "Berlin": result = calcDifficultyMuirGlacier(timestamp, header)
of "Constantinople": result = calcDifficultyConstantinople(timestamp, header)
of "Byzantium": result = calcDifficultyByzantium(timestamp, header)
of "ArrowGlacier": result = calcDifficultyArrowGlacier(timestamp, header)
else:
doAssert(false, "unknown revision: " & revision)
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
var fixture: JsonNode
for _, child in fixtures:
fixture = child
break
for revision, child in fixture:
if revision == "_info":
continue
let tests = parseTests(child)
for title, t in tests:
let p = Header(
2023-05-22 08:12:50 +00:00
difficulty : t.parentDifficulty,
timestamp : EthTime(t.parentTimestamp),
number : t.currentBlockNumber - 1,
2023-05-22 08:12:50 +00:00
ommersHash : t.parentUncles
)
let timestamp = EthTime(t.currentTimestamp)
2019-08-23 15:54:25 +00:00
2023-05-22 08:12:50 +00:00
let diff = calculator(revision, timestamp, p)
2019-08-23 15:54:25 +00:00
check diff == t.currentDifficulty
2023-05-22 08:12:50 +00:00
template runTest() =
var filenames: seq[string] = @[]
for filename in walkDirRec(inputPath):
if not filename.endsWith(".json"):
continue
filenames.add filename
2020-04-12 10:33:17 +00:00
2023-05-22 08:12:50 +00:00
doAssert(filenames.len > 0)
2020-04-12 11:09:18 +00:00
2023-05-22 08:12:50 +00:00
for fname in filenames:
let filename = fname
test fname.substr(inputPath.len + 1):
2023-05-22 08:12:50 +00:00
let fixtures = parseJson(readFile(filename))
testFixture(fixtures, testStatusIMPL)
proc difficultyMain*() =
2019-09-21 05:45:23 +00:00
suite "DifficultyTest":
2023-05-22 08:12:50 +00:00
runTest()
when isMainModule:
difficultyMain()