nimbus-eth1/tests/test_blockchain_json.nim

157 lines
4.6 KiB
Nim
Raw Normal View History

2019-09-03 15:06:43 +00:00
# Nimbus
# Copyright (c) 2018-2024 Status Research & Development GmbH
2019-09-03 15:06:43 +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.
2019-09-03 15:06:43 +00:00
import
std/json,
2022-12-02 04:39:12 +00:00
unittest2,
stew/byteutils,
./test_helpers,
./test_allowed_to_fail,
../nimbus/db/ledger,
../nimbus/core/chain/forked_chain,
../tools/common/helpers as chp,
../tools/evmstate/helpers,
../nimbus/common/common,
../nimbus/core/eip4844
2019-09-03 15:06:43 +00:00
const
debugMode = false
2019-09-03 15:06:43 +00:00
type
BlockDesc = object
blk: EthBlock
badBlock: bool
2019-09-03 15:06:43 +00:00
TestEnv = object
blocks: seq[BlockDesc]
genesisHeader: Header
lastBlockHash: Hash32
network: string
pre: JsonNode
proc parseBlocks(node: JsonNode): seq[BlockDesc] =
for x in node:
try:
let blockRLP = hexToSeqByte(x["rlp"].getStr)
let blk = rlp.decode(blockRLP, EthBlock)
result.add BlockDesc(
blk: blk,
badBlock: "expectException" in x,
)
except RlpError:
# invalid rlp will not participate in block validation
# e.g. invalid rlp received from network
discard
proc parseEnv(node: JsonNode): TestEnv =
result.blocks = parseBlocks(node["blocks"])
let genesisRLP = hexToSeqByte(node["genesisRLP"].getStr)
result.genesisHeader = rlp.decode(genesisRLP, EthBlock).header
result.lastBlockHash = Hash32(hexToByteArray[32](node["lastblockhash"].getStr))
result.network = node["network"].getStr
result.pre = node["pre"]
proc rootExists(db: CoreDbRef; root: Hash32): bool =
let state = db.ctx.getAccounts().getStateRoot().valueOr:
return false
Update storage tree admin (#2419) * Tighten `CoreDb` API for accounts why: Apart from cruft, the way to fetch the accounts state root via a `CoreDbColRef` record was unnecessarily complicated. * Extend `CoreDb` API for accounts to cover storage tries why: In future, this will make the notion of column objects obsolete. Storage trees will then be indexed by the account address rather than the vertex ID equivalent like a `CoreDbColRef`. * Apply new/extended accounts API to ledger and tests details: This makes the `distinct_ledger` module obsolete * Remove column object constructors why: They were needed as an abstraction of MPT sub-trees including storage trees. Now, storage trees are handled by the account (e.g. via address) they belong to and all other trees can be identified by a constant well known vertex ID. So there is no need for column objects anymore. Still there are some left-over column object methods wnich will be removed next. * Remove `serialise()` and `PayloadRef` from default Aristo API why: Not needed. `PayloadRef` was used for unstructured/unknown payload formats (account or blob) and `serialise()` was used for decodng `PayloadRef`. Now it is known in advance what the payload looks like. * Added query function `hasStorageData()` whether a storage area exists why: Useful for supporting `slotStateEmpty()` of the `CoreDb` API * In the `Ledger` replace `storage.stateEmpty()` by `slotStateEmpty()` * On Aristo, hide the storage root/vertex ID in the `PayloadRef` why: The storage vertex ID is fully controlled by Aristo while the `AristoAccount` object is controlled by the application. With the storage root part of the `AristoAccount` object, there was a useless administrative burden to keep that storage root field up to date. * Remove cruft, update comments etc. * Update changed MPT access paradigms why: Fixes verified proxy tests * Fluffy cosmetics
2024-06-27 09:01:26 +00:00
state == root
proc executeCase(node: JsonNode): bool =
let
env = parseEnv(node)
memDB = newCoreDbRef DefaultDbMemory
stateDB = LedgerRef.init(memDB)
config = getChainConfig(env.network)
com = CommonRef.new(memDB, config)
setupStateDB(env.pre, stateDB)
stateDB.persist()
com.db.persistHeader(env.genesisHeader,
com.proofOfStake(env.genesisHeader)).isOkOr:
debugEcho "Failed to put genesis header into database: ", error
return false
let chead = com.db.getCanonicalHead().expect("canonicalHead exists")
if chead.blockHash != env.genesisHeader.blockHash:
debugEcho "Genesis block hash in database is different with expected genesis block hash"
return false
var c = newForkedChain(com, env.genesisHeader)
var lastStateRoot = env.genesisHeader.stateRoot
for blk in env.blocks:
let res = c.importBlock(blk.blk)
if res.isOk:
if env.lastBlockHash == blk.blk.header.blockHash:
lastStateRoot = blk.blk.header.stateRoot
if blk.badBlock:
debugEcho "A bug? bad block imported"
return false
2019-09-07 10:50:34 +00:00
else:
if not blk.badBlock:
debugEcho "A bug? good block rejected: ", res.error
return false
c.forkChoice(env.lastBlockHash, env.lastBlockHash).isOkOr:
debugEcho error
return false
let head = com.db.getCanonicalHead().expect("canonicalHead exists")
let headHash = head.blockHash
if headHash != env.lastBlockHash:
debugEcho "lastestBlockHash mismatch, get: ", headHash,
" expect: ", env.lastBlockHash
return false
if not memDB.rootExists(lastStateRoot):
debugEcho "Last stateRoot not exists"
return false
true
proc executeFile(node: JsonNode, testStatusIMPL: var TestStatus) =
for name, bctCase in node:
when debugMode:
debugEcho "TEST NAME: ", name
check executeCase(bctCase)
proc blockchainJsonMain*() =
const
legacyFolder = "eth_tests/LegacyTests/Constantinople/BlockchainTests"
newFolder = "eth_tests/BlockchainTests"
loadKzgTrustedSetup().isOkOr:
echo "FATAL: ", error
quit(QuitFailure)
if false:
suite "block chain json tests":
jsonTest(legacyFolder, "BlockchainTests", executeFile, skipBCTests)
2019-09-07 09:47:06 +00:00
else:
suite "new block chain json tests":
jsonTest(newFolder, "newBlockchainTests", executeFile, skipNewBCTests)
2019-09-07 09:47:06 +00:00
when isMainModule:
when debugMode:
proc executeFile(name: string) =
loadKzgTrustedSetup().isOkOr:
echo "FATAL: ", error
quit(QuitFailure)
var testStatusIMPL: TestStatus
let node = json.parseFile(name)
executeFile(node, testStatusIMPL)
if testStatusIMPL == FAILED:
quit(QuitFailure)
executeFile("tests/fixtures/eth_tests/BlockchainTests/GeneralStateTests/stTransactionTest/ValueOverflowParis.json")
2019-09-07 09:47:06 +00:00
else:
blockchainJsonMain()