mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-10 12:26:02 +00:00
61bbf40014
* 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
154 lines
4.5 KiB
Nim
154 lines
4.5 KiB
Nim
# Nimbus
|
|
# Copyright (c) 2018-2024 Status Research & Development GmbH
|
|
# 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.
|
|
|
|
import
|
|
std/json,
|
|
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
|
|
|
|
const
|
|
debugMode = false
|
|
|
|
type
|
|
BlockDesc = object
|
|
blk: EthBlock
|
|
badBlock: bool
|
|
|
|
TestEnv = object
|
|
blocks: seq[BlockDesc]
|
|
genesisHeader: BlockHeader
|
|
lastBlockHash: Hash256
|
|
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 = Hash256(data: hexToByteArray[32](node["lastblockhash"].getStr))
|
|
result.network = node["network"].getStr
|
|
result.pre = node["pre"]
|
|
|
|
proc rootExists(db: CoreDbRef; root: Hash256): bool =
|
|
let state = db.ctx.getAccounts().state(updateOk=true).valueOr:
|
|
return false
|
|
state == root
|
|
|
|
proc executeCase(node: JsonNode): bool =
|
|
let
|
|
env = parseEnv(node)
|
|
memDB = newCoreDbRef DefaultDbMemory
|
|
stateDB = LedgerRef.init(memDB, EMPTY_ROOT_HASH)
|
|
config = getChainConfig(env.network)
|
|
com = CommonRef.new(memDB, config)
|
|
|
|
setupStateDB(env.pre, stateDB)
|
|
stateDB.persist()
|
|
|
|
if not com.db.persistHeader(env.genesisHeader,
|
|
com.consensus == ConsensusType.POS):
|
|
debugEcho "Failed to put genesis header into database"
|
|
return false
|
|
|
|
if com.db.getCanonicalHead().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
|
|
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()
|
|
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)
|
|
else:
|
|
suite "new block chain json tests":
|
|
jsonTest(newFolder, "newBlockchainTests", executeFile, skipNewBCTests)
|
|
|
|
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)
|
|
|
|
executeFile("tests/fixtures/eth_tests/BlockchainTests/ValidBlocks/bcTotalDifficultyTest/sideChainWithMoreTransactions.json")
|
|
else:
|
|
blockchainJsonMain()
|