nimbus-eth1/stateless/test_witness_verification.nim

103 lines
3.6 KiB
Nim

# Nimbus
# Copyright (c) 2023-2024 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
import
std/os,
unittest2,
stew/results,
eth/[common, trie/trie_defs],
../../nimbus/db/[ledger, core_db],
../../nimbus/common/chain_config,
./[witness_from_tree, multi_keys, witness_types, witness_verification]
proc getGenesisAlloc(filePath: string): GenesisAlloc =
var cn: NetworkParams
if not loadNetworkParams(filePath, cn):
quit(1)
cn.genesis.alloc
proc setupStateDB(
genAccounts: GenesisAlloc,
stateDB: LedgerRef): (Hash256, MultikeysRef) =
var keys = newSeqOfCap[AccountKey](genAccounts.len)
for address, genAccount in genAccounts:
var storageKeys = newSeqOfCap[StorageSlot](genAccount.storage.len)
for slotKey, slotValue in genAccount.storage:
storageKeys.add(slotKey.toBytesBE)
stateDB.setStorage(address, slotKey, slotValue)
stateDB.setNonce(address, genAccount.nonce)
stateDB.setCode(address, genAccount.code)
stateDB.setBalance(address, genAccount.balance)
let sKeys = if storageKeys.len != 0: newMultiKeys(storageKeys) else: MultikeysRef(nil)
let codeTouched = genAccount.code.len > 0
keys.add(AccountKey(address: address, codeTouched: codeTouched, storageKeys: sKeys))
stateDB.persist()
(stateDB.rootHash, newMultiKeys(keys))
proc buildWitness(
genAccounts: GenesisAlloc): (KeccakHash, BlockWitness) {.raises: [CatchableError].} =
let
coreDb = newCoreDbRef(LegacyDbMemory)
accountsCache = AccountsCache.init(coreDb, emptyRlpHash, true)
(rootHash, multiKeys) = setupStateDB(genAccounts, accountsCache)
var wb = initWitnessBuilder(coreDb, rootHash, {wfNoFlag})
(rootHash, wb.buildWitness(multiKeys))
proc checkWitnessDataMatchesAccounts(
genAccounts: GenesisAlloc,
witnessData: TableRef[EthAddress, AccountData]) {.raises: [CatchableError].} =
for address, genAccount in genAccounts:
let accountData = witnessData[address]
check genAccount.code == accountData.code
check genAccount.storage == accountData.storage
check genAccount.balance == accountData.account.balance
check genAccount.nonce == accountData.account.nonce
proc witnessVerificationMain*() =
suite "Witness verification json tests":
let genesisFiles = ["berlin2000.json", "chainid1.json", "chainid7.json", "merge.json", "devnet4.json", "devnet5.json", "holesky.json"]
test "Block witness verification with valid state root":
for file in genesisFiles:
let
accounts = getGenesisAlloc("tests" / "customgenesis" / file)
(stateRoot, witness) = buildWitness(accounts)
verifyResult = verifyWitness(stateRoot, witness, {wfNoFlag})
check verifyResult.isOk()
checkWitnessDataMatchesAccounts(accounts, verifyResult.get())
test "Block witness verification with invalid state root":
let badStateRoot = toDigest("2cb1b80b285d09e0570fdbbb808e1d14e4ac53e36dcd95dbc268deec2915b3e7")
for file in genesisFiles:
let
accounts = getGenesisAlloc("tests" / "customgenesis" / file)
(_, witness) = buildWitness(accounts)
verifyResult = verifyWitness(badStateRoot, witness, {wfNoFlag})
check verifyResult.isErr()
check verifyResult.error() == "witness stateRoot doesn't match trustedStateRoot"
when isMainModule:
witnessVerificationMain()