mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 21:34:33 +00:00
reduce code duplication in multiple test runners
This commit is contained in:
parent
735d780424
commit
a232c7eb1d
@ -20,7 +20,8 @@ import
|
|||||||
../nimbus/utils/utils,
|
../nimbus/utils/utils,
|
||||||
../nimbus/core/[executor, validate, pow/header],
|
../nimbus/core/[executor, validate, pow/header],
|
||||||
../stateless/[tree_from_witness, witness_types],
|
../stateless/[tree_from_witness, witness_types],
|
||||||
../tools/common/helpers,
|
../tools/common/helpers as chp,
|
||||||
|
../tools/evmstate/helpers,
|
||||||
../nimbus/common/common
|
../nimbus/common/common
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -344,7 +345,7 @@ proc testFixture(node: JsonNode, testStatusIMPL: var TestStatus, debugMode = fal
|
|||||||
# - mine block
|
# - mine block
|
||||||
# 3 - diff resulting state with expected state
|
# 3 - diff resulting state with expected state
|
||||||
# 4 - check that all previous blocks were valid
|
# 4 - check that all previous blocks were valid
|
||||||
let specifyIndex = test_config.getConfiguration().index
|
let specifyIndex = test_config.getConfiguration().index.get(0)
|
||||||
var fixtureIndex = 0
|
var fixtureIndex = 0
|
||||||
var fixtureTested = false
|
var fixtureTested = false
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import
|
import
|
||||||
std/[parseopt, strutils, tables],
|
std/[parseopt, strutils, options],
|
||||||
../nimbus/common/evmforks,
|
../nimbus/common/evmforks
|
||||||
./test_helpers
|
|
||||||
|
|
||||||
type
|
type
|
||||||
ConfigStatus* = enum
|
ConfigStatus* = enum
|
||||||
@ -15,8 +14,8 @@ type
|
|||||||
|
|
||||||
Configuration = ref object
|
Configuration = ref object
|
||||||
testSubject*: string
|
testSubject*: string
|
||||||
fork*: EVMFork
|
fork*: string
|
||||||
index*: int
|
index*: Option[int]
|
||||||
trace*: bool
|
trace*: bool
|
||||||
legacy*: bool
|
legacy*: bool
|
||||||
pruning*: bool
|
pruning*: bool
|
||||||
@ -25,8 +24,6 @@ var testConfig {.threadvar.}: Configuration
|
|||||||
|
|
||||||
proc initConfiguration(): Configuration =
|
proc initConfiguration(): Configuration =
|
||||||
result = new Configuration
|
result = new Configuration
|
||||||
result.fork = FkFrontier
|
|
||||||
result.index = 0
|
|
||||||
result.trace = true
|
result.trace = true
|
||||||
result.pruning = true
|
result.pruning = true
|
||||||
|
|
||||||
@ -47,8 +44,8 @@ proc processArguments*(msg: var string): ConfigStatus =
|
|||||||
config.testSubject = key
|
config.testSubject = key
|
||||||
of cmdLongOption, cmdShortOption:
|
of cmdLongOption, cmdShortOption:
|
||||||
case key.toLowerAscii()
|
case key.toLowerAscii()
|
||||||
of "fork": config.fork = nameToFork[strip(value)]
|
of "fork": config.fork = value
|
||||||
of "index": config.index = parseInt(value)
|
of "index": config.index = some(parseInt(value))
|
||||||
of "trace": config.trace = parseBool(value)
|
of "trace": config.trace = parseBool(value)
|
||||||
of "legacy": config.legacy = parseBool(value)
|
of "legacy": config.legacy = parseBool(value)
|
||||||
of "pruning": config.pruning = parseBool(value)
|
of "pruning": config.pruning = parseBool(value)
|
||||||
|
@ -14,6 +14,8 @@ import
|
|||||||
../nimbus/db/accounts_cache,
|
../nimbus/db/accounts_cache,
|
||||||
../nimbus/common/common,
|
../nimbus/common/common,
|
||||||
../nimbus/utils/utils,
|
../nimbus/utils/utils,
|
||||||
|
../tools/common/helpers as chp,
|
||||||
|
../tools/evmstate/helpers,
|
||||||
chronicles,
|
chronicles,
|
||||||
eth/rlp,
|
eth/rlp,
|
||||||
eth/trie/trie_defs,
|
eth/trie/trie_defs,
|
||||||
@ -26,9 +28,9 @@ type
|
|||||||
header: BlockHeader
|
header: BlockHeader
|
||||||
pre: JsonNode
|
pre: JsonNode
|
||||||
tx: Transaction
|
tx: Transaction
|
||||||
expectedHash: string
|
expectedHash: Hash256
|
||||||
expectedLogs: string
|
expectedLogs: Hash256
|
||||||
fork: EVMFork
|
chainConfig: ChainConfig
|
||||||
debugMode: bool
|
debugMode: bool
|
||||||
trace: bool
|
trace: bool
|
||||||
index: int
|
index: int
|
||||||
@ -83,18 +85,9 @@ proc dumpDebugData(tester: Tester, vmState: BaseVMState, sender: EthAddress, gas
|
|||||||
let status = if success: "_success" else: "_failed"
|
let status = if success: "_success" else: "_failed"
|
||||||
writeFile("debug_" & tester.name & "_" & $tester.index & status & ".json", debugData.pretty())
|
writeFile("debug_" & tester.name & "_" & $tester.index & status & ".json", debugData.pretty())
|
||||||
|
|
||||||
# using only one networkParams will reduce execution
|
|
||||||
# time ~90% instead of create it for every test
|
|
||||||
let params = chainConfigForNetwork(MainNet)
|
|
||||||
|
|
||||||
proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
||||||
if tester.fork == FkParis:
|
|
||||||
params.terminalTotalDifficulty = some(0.u256)
|
|
||||||
else:
|
|
||||||
params.terminalTotalDifficulty = none(BlockNumber)
|
|
||||||
|
|
||||||
let
|
let
|
||||||
com = CommonRef.new(newMemoryDB(), params, getConfiguration().pruning)
|
com = CommonRef.new(newMemoryDB(), tester.chainConfig, getConfiguration().pruning)
|
||||||
parent = BlockHeader(stateRoot: emptyRlpHash)
|
parent = BlockHeader(stateRoot: emptyRlpHash)
|
||||||
|
|
||||||
let vmState = BaseVMState.new(
|
let vmState = BaseVMState.new(
|
||||||
@ -106,6 +99,7 @@ proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
|||||||
|
|
||||||
var gasUsed: GasInt
|
var gasUsed: GasInt
|
||||||
let sender = tester.tx.getSender()
|
let sender = tester.tx.getSender()
|
||||||
|
let fork = com.toEVMFork(tester.header.blockNumber)
|
||||||
|
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
setupStateDB(tester.pre, db)
|
setupStateDB(tester.pre, db)
|
||||||
@ -116,18 +110,17 @@ proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
|||||||
db.persist()
|
db.persist()
|
||||||
|
|
||||||
defer:
|
defer:
|
||||||
let obtainedHash = "0x" & `$`(vmState.readOnlyStateDB.rootHash).toLowerAscii
|
let obtainedHash = vmState.readOnlyStateDB.rootHash
|
||||||
check obtainedHash == tester.expectedHash
|
check obtainedHash == tester.expectedHash
|
||||||
let logEntries = vmState.getAndClearLogEntries()
|
let logEntries = vmState.getAndClearLogEntries()
|
||||||
let actualLogsHash = hashLogEntries(logEntries)
|
let actualLogsHash = hashLogEntries(logEntries)
|
||||||
let expectedLogsHash = toLowerAscii(tester.expectedLogs)
|
check(tester.expectedLogs == actualLogsHash)
|
||||||
check(expectedLogsHash == actualLogsHash)
|
|
||||||
if tester.debugMode:
|
if tester.debugMode:
|
||||||
let success = expectedLogsHash == actualLogsHash and obtainedHash == tester.expectedHash
|
let success = tester.expectedLogs == actualLogsHash and obtainedHash == tester.expectedHash
|
||||||
tester.dumpDebugData(vmState, sender, gasUsed, success)
|
tester.dumpDebugData(vmState, sender, gasUsed, success)
|
||||||
|
|
||||||
let rc = vmState.processTransaction(
|
let rc = vmState.processTransaction(
|
||||||
tester.tx, sender, tester.header, tester.fork)
|
tester.tx, sender, tester.header, fork)
|
||||||
if rc.isOk:
|
if rc.isOk:
|
||||||
gasUsed = rc.value
|
gasUsed = rc.value
|
||||||
|
|
||||||
@ -144,7 +137,7 @@ proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
|||||||
if miner in vmState.selfDestructs:
|
if miner in vmState.selfDestructs:
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
db.addBalance(miner, 0.u256)
|
db.addBalance(miner, 0.u256)
|
||||||
if tester.fork >= FkSpurious:
|
if fork >= FkSpurious:
|
||||||
if db.isEmptyAccount(miner):
|
if db.isEmptyAccount(miner):
|
||||||
db.deleteAccount(miner)
|
db.deleteAccount(miner)
|
||||||
|
|
||||||
@ -155,7 +148,7 @@ proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
|
|||||||
db.persist()
|
db.persist()
|
||||||
|
|
||||||
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus,
|
proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus,
|
||||||
trace = false, debugMode = false, supportedForks: set[EVMFork] = supportedForks) =
|
trace = false, debugMode = false) =
|
||||||
var tester: Tester
|
var tester: Tester
|
||||||
var fixture: JsonNode
|
var fixture: JsonNode
|
||||||
for label, child in fixtures:
|
for label, child in fixtures:
|
||||||
@ -163,57 +156,53 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus,
|
|||||||
tester.name = label
|
tester.name = label
|
||||||
break
|
break
|
||||||
|
|
||||||
let fenv = fixture["env"]
|
tester.pre = fixture["pre"]
|
||||||
tester.header = BlockHeader(
|
tester.header = parseHeader(fixture["env"])
|
||||||
coinbase : fenv["currentCoinbase"].getStr.ethAddressFromHex,
|
|
||||||
difficulty : fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
|
|
||||||
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
|
|
||||||
gasLimit : fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
|
|
||||||
timestamp : fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
|
|
||||||
stateRoot : emptyRlpHash
|
|
||||||
)
|
|
||||||
|
|
||||||
if "currentBaseFee" in fenv:
|
|
||||||
tester.header.baseFee = fromHex(UInt256, fenv{"currentBaseFee"}.getStr)
|
|
||||||
|
|
||||||
if "currentRandom" in fenv:
|
|
||||||
tester.header.prevRandao.data = hexToByteArray[32](fenv{"currentRandom"}.getStr)
|
|
||||||
|
|
||||||
let specifyIndex = getConfiguration().index
|
|
||||||
tester.trace = trace
|
tester.trace = trace
|
||||||
tester.debugMode = debugMode
|
tester.debugMode = debugMode
|
||||||
let ftrans = fixture["transaction"]
|
|
||||||
var testedInFork = false
|
|
||||||
var numIndex = -1
|
|
||||||
for fork in supportedForks:
|
|
||||||
if fixture["post"].hasKey(forkNames[fork]):
|
|
||||||
numIndex = fixture["post"][forkNames[fork]].len
|
|
||||||
for expectation in fixture["post"][forkNames[fork]]:
|
|
||||||
inc tester.index
|
|
||||||
if specifyIndex > 0 and tester.index != specifyIndex:
|
|
||||||
continue
|
|
||||||
testedInFork = true
|
|
||||||
tester.expectedHash = expectation["hash"].getStr
|
|
||||||
tester.expectedLogs = expectation["logs"].getStr
|
|
||||||
let
|
|
||||||
indexes = expectation["indexes"]
|
|
||||||
dataIndex = indexes["data"].getInt
|
|
||||||
gasIndex = indexes["gas"].getInt
|
|
||||||
valueIndex = indexes["value"].getInt
|
|
||||||
tester.tx = ftrans.getFixtureTransaction(dataIndex, gasIndex, valueIndex)
|
|
||||||
tester.pre = fixture["pre"]
|
|
||||||
tester.fork = fork
|
|
||||||
testFixtureIndexes(tester, testStatusIMPL)
|
|
||||||
|
|
||||||
if not testedInFork:
|
let
|
||||||
echo "test subject '", tester.name, "' not tested in any forks/subtests"
|
post = fixture["post"]
|
||||||
if specifyIndex <= 0 or specifyIndex > numIndex:
|
txData = fixture["transaction"]
|
||||||
echo "Maximum subtest available: ", numIndex
|
conf = getConfiguration()
|
||||||
|
|
||||||
|
template prepareFork(forkName: string) =
|
||||||
|
try:
|
||||||
|
tester.chainConfig = getChainConfig(forkName)
|
||||||
|
except ValueError as ex:
|
||||||
|
debugEcho ex.msg
|
||||||
|
return
|
||||||
|
|
||||||
|
template runSubTest(subTest: JsonNode) =
|
||||||
|
tester.expectedHash = Hash256.fromJson(subTest["hash"])
|
||||||
|
tester.expectedLogs = Hash256.fromJson(subTest["logs"])
|
||||||
|
tester.tx = parseTx(txData, subTest["indexes"])
|
||||||
|
tester.testFixtureIndexes(testStatusIMPL)
|
||||||
|
|
||||||
|
if conf.fork.len > 0:
|
||||||
|
if not post.hasKey(conf.fork):
|
||||||
|
debugEcho "selected fork not available: " & conf.fork
|
||||||
|
return
|
||||||
|
|
||||||
|
let forkData = post[conf.fork]
|
||||||
|
prepareFork(conf.fork)
|
||||||
|
if conf.index.isNone:
|
||||||
|
for subTest in forkData:
|
||||||
|
runSubTest(subTest)
|
||||||
else:
|
else:
|
||||||
echo "available forks in this test:"
|
let index = conf.index.get()
|
||||||
for fork in test_helpers.supportedForks:
|
if index > forkData.len or index < 0:
|
||||||
if fixture["post"].hasKey(forkNames[fork]):
|
debugEcho "selected index out of range(0-$1), requested $2" %
|
||||||
echo fork
|
[$forkData.len, $index]
|
||||||
|
return
|
||||||
|
|
||||||
|
let subTest = forkData[index]
|
||||||
|
runSubTest(subTest)
|
||||||
|
else:
|
||||||
|
for forkName, forkData in post:
|
||||||
|
prepareFork(forkName)
|
||||||
|
for subTest in forkData:
|
||||||
|
runSubTest(subTest)
|
||||||
|
|
||||||
proc generalStateJsonMain*(debugMode = false) =
|
proc generalStateJsonMain*(debugMode = false) =
|
||||||
const
|
const
|
||||||
@ -239,9 +228,7 @@ proc generalStateJsonMain*(debugMode = false) =
|
|||||||
let path = "tests" / "fixtures" / folder
|
let path = "tests" / "fixtures" / folder
|
||||||
let n = json.parseFile(path / config.testSubject)
|
let n = json.parseFile(path / config.testSubject)
|
||||||
var testStatusIMPL: TestStatus
|
var testStatusIMPL: TestStatus
|
||||||
var forks: set[EVMFork] = {}
|
testFixture(n, testStatusIMPL, config.trace, true)
|
||||||
forks.incl config.fork
|
|
||||||
testFixture(n, testStatusIMPL, config.trace, true, forks)
|
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var message: string
|
var message: string
|
||||||
|
@ -34,19 +34,6 @@ const
|
|||||||
FkParis: "Merge"
|
FkParis: "Merge"
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
supportedForks* = {
|
|
||||||
FkFrontier,
|
|
||||||
FkHomestead,
|
|
||||||
FkTangerine,
|
|
||||||
FkSpurious,
|
|
||||||
FkByzantium,
|
|
||||||
FkConstantinople,
|
|
||||||
FkPetersburg,
|
|
||||||
FkIstanbul,
|
|
||||||
FkBerlin,
|
|
||||||
FkLondon,
|
|
||||||
FkParis}
|
|
||||||
|
|
||||||
nameToFork* = revmap(forkNames)
|
nameToFork* = revmap(forkNames)
|
||||||
|
|
||||||
func skipNothing*(folder: string, name: string): bool = false
|
func skipNothing*(folder: string, name: string): bool = false
|
||||||
@ -121,20 +108,6 @@ func getHexadecimalInt*(j: JsonNode): int64 =
|
|||||||
data = fromHex(StUint[64], j.getStr)
|
data = fromHex(StUint[64], j.getStr)
|
||||||
result = cast[int64](data)
|
result = cast[int64](data)
|
||||||
|
|
||||||
proc setupStateDB*(wantedState: JsonNode, stateDB: AccountsCache) =
|
|
||||||
for ac, accountData in wantedState:
|
|
||||||
let account = ethAddressFromHex(ac)
|
|
||||||
for slot, value in accountData{"storage"}:
|
|
||||||
stateDB.setStorage(account, fromHex(UInt256, slot), fromHex(UInt256, value.getStr))
|
|
||||||
|
|
||||||
let nonce = accountData{"nonce"}.getHexadecimalInt.AccountNonce
|
|
||||||
let code = accountData{"code"}.getStr.safeHexToSeqByte
|
|
||||||
let balance = UInt256.fromHex accountData{"balance"}.getStr
|
|
||||||
|
|
||||||
stateDB.setNonce(account, nonce)
|
|
||||||
stateDB.setCode(account, code)
|
|
||||||
stateDB.setBalance(account, balance)
|
|
||||||
|
|
||||||
proc verifyStateDB*(wantedState: JsonNode, stateDB: ReadOnlyStateDB) =
|
proc verifyStateDB*(wantedState: JsonNode, stateDB: ReadOnlyStateDB) =
|
||||||
for ac, accountData in wantedState:
|
for ac, accountData in wantedState:
|
||||||
let account = ethAddressFromHex(ac)
|
let account = ethAddressFromHex(ac)
|
||||||
@ -165,93 +138,8 @@ proc verifyStateDB*(wantedState: JsonNode, stateDB: ReadOnlyStateDB) =
|
|||||||
if wantedNonce != actualNonce:
|
if wantedNonce != actualNonce:
|
||||||
raise newException(ValidationError, &"{ac} nonceDiff {wantedNonce.toHex} != {actualNonce.toHex}")
|
raise newException(ValidationError, &"{ac} nonceDiff {wantedNonce.toHex} != {actualNonce.toHex}")
|
||||||
|
|
||||||
proc parseAccessList(n: JsonNode): AccessList =
|
proc hashLogEntries*(logs: seq[Log]): Hash256 =
|
||||||
if n.kind == JNull:
|
keccakHash(rlp.encode(logs))
|
||||||
return
|
|
||||||
|
|
||||||
for x in n:
|
|
||||||
var ap = AccessPair(
|
|
||||||
address: parseAddress(x["address"].getStr)
|
|
||||||
)
|
|
||||||
let sks = x["storageKeys"]
|
|
||||||
for sk in sks:
|
|
||||||
ap.storageKeys.add hexToByteArray[32](sk.getStr())
|
|
||||||
result.add ap
|
|
||||||
|
|
||||||
proc getFixtureTransaction*(j: JsonNode, dataIndex, gasIndex, valueIndex: int): Transaction =
|
|
||||||
let dynamicFeeTx = "gasPrice" notin j
|
|
||||||
let nonce = j["nonce"].getHexadecimalInt.AccountNonce
|
|
||||||
let gasLimit = j["gasLimit"][gasIndex].getHexadecimalInt
|
|
||||||
|
|
||||||
var toAddr: Option[EthAddress]
|
|
||||||
# Fixture transactions with `"to": ""` are contract creations.
|
|
||||||
#
|
|
||||||
# Fixture transactions with `"to": "0x..."` or `"to": "..."` where `...` are
|
|
||||||
# 40 hex digits are call/transfer transactions. Even if the digits are all
|
|
||||||
# zeros, because the all-zeros address is a legitimate account.
|
|
||||||
#
|
|
||||||
# There are no other formats. The number of digits if present is always 40,
|
|
||||||
# "0x" prefix is used in some but not all fixtures, and upper case hex digits
|
|
||||||
# occur in a few.
|
|
||||||
let rawTo = j["to"].getStr
|
|
||||||
if rawTo != "":
|
|
||||||
toAddr = some(rawTo.parseAddress)
|
|
||||||
|
|
||||||
let hexStr = j["value"][valueIndex].getStr
|
|
||||||
# stTransactionTest/ValueOverflow.json
|
|
||||||
# prevent parsing exception and subtitute it with max uint256
|
|
||||||
let value = if ':' in hexStr: high(UInt256) else: fromHex(UInt256, hexStr)
|
|
||||||
let payload = j["data"][dataIndex].getStr.safeHexToSeqByte
|
|
||||||
|
|
||||||
var secretKey = j["secretKey"].getStr
|
|
||||||
removePrefix(secretKey, "0x")
|
|
||||||
let privateKey = PrivateKey.fromHex(secretKey).tryGet()
|
|
||||||
|
|
||||||
if dynamicFeeTx:
|
|
||||||
let accList = j["accessLists"][dataIndex]
|
|
||||||
var tx = Transaction(
|
|
||||||
txType: TxEip1559,
|
|
||||||
nonce: nonce,
|
|
||||||
maxFee: j["maxFeePerGas"].getHexadecimalInt,
|
|
||||||
maxPriorityFee: j["maxPriorityFeePerGas"].getHexadecimalInt,
|
|
||||||
gasLimit: gasLimit,
|
|
||||||
to: toAddr,
|
|
||||||
value: value,
|
|
||||||
payload: payload,
|
|
||||||
accessList: parseAccessList(accList),
|
|
||||||
chainId: ChainId(1)
|
|
||||||
)
|
|
||||||
return signTransaction(tx, privateKey, ChainId(1), false)
|
|
||||||
|
|
||||||
let gasPrice = j["gasPrice"].getHexadecimalInt
|
|
||||||
if j.hasKey("accessLists"):
|
|
||||||
let accList = j["accessLists"][dataIndex]
|
|
||||||
var tx = Transaction(
|
|
||||||
txType: TxEip2930,
|
|
||||||
nonce: nonce,
|
|
||||||
gasPrice: gasPrice,
|
|
||||||
gasLimit: gasLimit,
|
|
||||||
to: toAddr,
|
|
||||||
value: value,
|
|
||||||
payload: payload,
|
|
||||||
accessList: parseAccessList(accList),
|
|
||||||
chainId: ChainId(1)
|
|
||||||
)
|
|
||||||
signTransaction(tx, privateKey, ChainId(1), false)
|
|
||||||
else:
|
|
||||||
var tx = Transaction(
|
|
||||||
txType: TxLegacy,
|
|
||||||
nonce: nonce,
|
|
||||||
gasPrice: gasPrice,
|
|
||||||
gasLimit: gasLimit,
|
|
||||||
to: toAddr,
|
|
||||||
value: value,
|
|
||||||
payload: payload
|
|
||||||
)
|
|
||||||
signTransaction(tx, privateKey, ChainId(1), false)
|
|
||||||
|
|
||||||
proc hashLogEntries*(logs: seq[Log]): string =
|
|
||||||
toLowerAscii("0x" & $keccakHash(rlp.encode(logs)))
|
|
||||||
|
|
||||||
proc setupEthNode*(
|
proc setupEthNode*(
|
||||||
conf: NimbusConf, ctx: EthContext,
|
conf: NimbusConf, ctx: EthContext,
|
||||||
|
@ -20,6 +20,7 @@ import
|
|||||||
../../nimbus/transaction,
|
../../nimbus/transaction,
|
||||||
../../nimbus/core/executor,
|
../../nimbus/core/executor,
|
||||||
../../nimbus/common/common,
|
../../nimbus/common/common,
|
||||||
|
../common/helpers as chp,
|
||||||
"."/[config, helpers]
|
"."/[config, helpers]
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -29,7 +30,7 @@ type
|
|||||||
tx: Transaction
|
tx: Transaction
|
||||||
expectedHash: Hash256
|
expectedHash: Hash256
|
||||||
expectedLogs: Hash256
|
expectedLogs: Hash256
|
||||||
fork: EVMFork
|
chainConfig: ChainConfig
|
||||||
index: int
|
index: int
|
||||||
tracerFlags: set[TracerFlags]
|
tracerFlags: set[TracerFlags]
|
||||||
error: string
|
error: string
|
||||||
@ -64,13 +65,6 @@ proc extractNameAndFixture(ctx: var StateContext, n: JsonNode): JsonNode =
|
|||||||
return
|
return
|
||||||
doAssert(false, "unreachable")
|
doAssert(false, "unreachable")
|
||||||
|
|
||||||
proc parseTx(txData, index: JsonNode): Transaction =
|
|
||||||
let
|
|
||||||
dataIndex = index["data"].getInt
|
|
||||||
gasIndex = index["gas"].getInt
|
|
||||||
valIndex = index["value"].getInt
|
|
||||||
parseTx(txData, dataIndex, gasIndex, valIndex)
|
|
||||||
|
|
||||||
proc toBytes(x: string): seq[byte] =
|
proc toBytes(x: string): seq[byte] =
|
||||||
result = newSeq[byte](x.len)
|
result = newSeq[byte](x.len)
|
||||||
for i in 0..<x.len: result[i] = x[i].byte
|
for i in 0..<x.len: result[i] = x[i].byte
|
||||||
@ -190,7 +184,6 @@ proc writeTraceToStderr(vmState: BaseVMState, pretty: bool) =
|
|||||||
if pretty:
|
if pretty:
|
||||||
stderr.writeLine(trace.pretty)
|
stderr.writeLine(trace.pretty)
|
||||||
else:
|
else:
|
||||||
var gasUsed = 0
|
|
||||||
let logs = trace["structLogs"]
|
let logs = trace["structLogs"]
|
||||||
trace.delete("structLogs")
|
trace.delete("structLogs")
|
||||||
for x in logs:
|
for x in logs:
|
||||||
@ -204,14 +197,9 @@ proc writeTraceToStderr(vmState: BaseVMState, pretty: bool) =
|
|||||||
|
|
||||||
proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateResult =
|
proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateResult =
|
||||||
let
|
let
|
||||||
params = chainConfigForNetwork(MainNet)
|
com = CommonRef.new(newMemoryDB(), ctx.chainConfig, pruneTrie = false)
|
||||||
|
|
||||||
if ctx.fork == FkParis:
|
|
||||||
params.terminalTotalDifficulty = some(0.u256)
|
|
||||||
|
|
||||||
let
|
|
||||||
com = CommonRef.new(newMemoryDB(), params, pruneTrie = false)
|
|
||||||
parent = BlockHeader(stateRoot: emptyRlpHash)
|
parent = BlockHeader(stateRoot: emptyRlpHash)
|
||||||
|
fork = com.toEVMFork(ctx.header.blockNumber)
|
||||||
|
|
||||||
let vmState = TestVMState()
|
let vmState = TestVMState()
|
||||||
vmState.init(
|
vmState.init(
|
||||||
@ -233,7 +221,7 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR
|
|||||||
name : ctx.name,
|
name : ctx.name,
|
||||||
pass : ctx.error.len == 0,
|
pass : ctx.error.len == 0,
|
||||||
root : vmState.stateDB.rootHash,
|
root : vmState.stateDB.rootHash,
|
||||||
fork : toString(ctx.fork),
|
fork : $fork,
|
||||||
error: ctx.error
|
error: ctx.error
|
||||||
)
|
)
|
||||||
if conf.dumpEnabled:
|
if conf.dumpEnabled:
|
||||||
@ -242,7 +230,7 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR
|
|||||||
writeTraceToStderr(vmState, conf.pretty)
|
writeTraceToStderr(vmState, conf.pretty)
|
||||||
|
|
||||||
let rc = vmState.processTransaction(
|
let rc = vmState.processTransaction(
|
||||||
ctx.tx, sender, ctx.header, ctx.fork)
|
ctx.tx, sender, ctx.header, fork)
|
||||||
if rc.isOk:
|
if rc.isOk:
|
||||||
gasUsed = rc.value
|
gasUsed = rc.value
|
||||||
|
|
||||||
@ -250,7 +238,7 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR
|
|||||||
if miner in vmState.selfDestructs:
|
if miner in vmState.selfDestructs:
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
db.addBalance(miner, 0.u256)
|
db.addBalance(miner, 0.u256)
|
||||||
if ctx.fork >= FkSpurious:
|
if fork >= FkSpurious:
|
||||||
if db.isEmptyAccount(miner):
|
if db.isEmptyAccount(miner):
|
||||||
db.deleteAccount(miner)
|
db.deleteAccount(miner)
|
||||||
db.persist(clearCache = false)
|
db.persist(clearCache = false)
|
||||||
@ -289,9 +277,11 @@ proc prepareAndRun(ctx: var StateContext, conf: StateConf): bool =
|
|||||||
hasError = false
|
hasError = false
|
||||||
|
|
||||||
template prepareFork(forkName: string) =
|
template prepareFork(forkName: string) =
|
||||||
let fork = parseFork(forkName)
|
try:
|
||||||
doAssert(fork.isSome, "unsupported fork: " & forkName)
|
ctx.chainConfig = getChainConfig(forkName)
|
||||||
ctx.fork = fork.get()
|
except ValueError as ex:
|
||||||
|
debugEcho ex.msg
|
||||||
|
return false
|
||||||
ctx.index = index
|
ctx.index = index
|
||||||
inc index
|
inc index
|
||||||
|
|
||||||
@ -332,14 +322,15 @@ proc prepareAndRun(ctx: var StateContext, conf: StateConf): bool =
|
|||||||
not hasError
|
not hasError
|
||||||
|
|
||||||
when defined(chronicles_runtime_filtering):
|
when defined(chronicles_runtime_filtering):
|
||||||
proc toLogLevel(v: int): LogLevel =
|
type Lev = chronicles.LogLevel
|
||||||
|
proc toLogLevel(v: int): Lev =
|
||||||
case v
|
case v
|
||||||
of 1: LogLevel.ERROR
|
of 1: Lev.ERROR
|
||||||
of 2: LogLevel.WARN
|
of 2: Lev.WARN
|
||||||
of 3: LogLevel.INFO
|
of 3: Lev.INFO
|
||||||
of 4: LogLevel.DEBUG
|
of 4: Lev.DEBUG
|
||||||
of 5: LogLevel.TRACE
|
of 5: Lev.TRACE
|
||||||
else: LogLevel.NONE
|
else: Lev.NONE
|
||||||
|
|
||||||
proc setVerbosity(v: int) =
|
proc setVerbosity(v: int) =
|
||||||
let level = v.toLogLevel
|
let level = v.toLogLevel
|
||||||
|
@ -131,6 +131,13 @@ proc parseTx*(n: JsonNode, dataIndex, gasIndex, valueIndex: int): Transaction =
|
|||||||
let secretKey = required(PrivateKey, "secretKey")
|
let secretKey = required(PrivateKey, "secretKey")
|
||||||
signTransaction(tx, secretKey, tx.chainId, false)
|
signTransaction(tx, secretKey, tx.chainId, false)
|
||||||
|
|
||||||
|
proc parseTx*(txData, index: JsonNode): Transaction =
|
||||||
|
let
|
||||||
|
dataIndex = index["data"].getInt
|
||||||
|
gasIndex = index["gas"].getInt
|
||||||
|
valIndex = index["value"].getInt
|
||||||
|
parseTx(txData, dataIndex, gasIndex, valIndex)
|
||||||
|
|
||||||
proc setupStateDB*(wantedState: JsonNode, stateDB: AccountsCache) =
|
proc setupStateDB*(wantedState: JsonNode, stateDB: AccountsCache) =
|
||||||
for ac, accountData in wantedState:
|
for ac, accountData in wantedState:
|
||||||
let account = hexToByteArray[20](ac)
|
let account = hexToByteArray[20](ac)
|
||||||
@ -140,36 +147,3 @@ proc setupStateDB*(wantedState: JsonNode, stateDB: AccountsCache) =
|
|||||||
stateDB.setNonce(account, fromJson(AccountNonce, accountData["nonce"]))
|
stateDB.setNonce(account, fromJson(AccountNonce, accountData["nonce"]))
|
||||||
stateDB.setCode(account, fromJson(Blob, accountData["code"]))
|
stateDB.setCode(account, fromJson(Blob, accountData["code"]))
|
||||||
stateDB.setBalance(account, fromJson(UInt256, accountData["balance"]))
|
stateDB.setBalance(account, fromJson(UInt256, accountData["balance"]))
|
||||||
|
|
||||||
proc parseFork*(x: string): Option[EVMFork] =
|
|
||||||
case x
|
|
||||||
of "Frontier" : some(FkFrontier)
|
|
||||||
of "Homestead" : some(FkHomestead)
|
|
||||||
of "EIP150" : some(FkTangerine)
|
|
||||||
of "EIP158" : some(FkSpurious)
|
|
||||||
of "Byzantium" : some(FkByzantium)
|
|
||||||
of "Constantinople" : some(FkConstantinople)
|
|
||||||
of "ConstantinopleFix": some(FkPetersburg)
|
|
||||||
of "Istanbul" : some(FkIstanbul)
|
|
||||||
of "Berlin" : some(FkBerlin)
|
|
||||||
of "London" : some(FkLondon)
|
|
||||||
of "Merge" : some(FkParis)
|
|
||||||
of "Shanghai" : some(FkShanghai)
|
|
||||||
of "Cancun" : some(FkCancun)
|
|
||||||
else: none(EVMFork)
|
|
||||||
|
|
||||||
proc toString*(x: EVMFork): string =
|
|
||||||
case x
|
|
||||||
of FkFrontier : "Frontier"
|
|
||||||
of FkHomestead : "Homestead"
|
|
||||||
of FkTangerine : "EIP150"
|
|
||||||
of FkSpurious : "EIP158"
|
|
||||||
of FkByzantium : "Byzantium"
|
|
||||||
of FkConstantinople: "Constantinople"
|
|
||||||
of FkPetersburg : "ConstantinopleFix"
|
|
||||||
of FkIstanbul : "Istanbul"
|
|
||||||
of FkBerlin : "Berlin"
|
|
||||||
of FkLondon : "London"
|
|
||||||
of FkParis : "Merge"
|
|
||||||
of FkShanghai : "Shanghai"
|
|
||||||
of FkCancun : "Cancun"
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user