mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-12 12:06:47 +00:00
* Cleanup unneeded stateless and block witness code. Keeping MultiKeys which is used in the eth_getProofsByBlockNumber RPC endpoint which is needed for the Fluffy state network bridge. * Rename generateWitness flag to collectWitnessData to better describe what the flag does. We only collect the keys of the touched accounts and storage slots but no block witness generation is supported for now. * Move remaining stateless code into nimbus directory. * Add vmstate parameter to ChainRef to fix test. * Exclude *.in from check copyright year --------- Co-authored-by: jangko <jangko128@gmail.com>
149 lines
5.5 KiB
Nim
149 lines
5.5 KiB
Nim
# Nimbus
|
|
# Copyright (c) 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.
|
|
|
|
# This test is intended to be run manually against a running instance of Nimbus-Eth1
|
|
# so it should not be added to the test runner or to the CI test suite.
|
|
#
|
|
# It uses the exp_getProofsByBlockNumber endpoint to get the list of state updates
|
|
# for each block, it then applies these updates against a local test state and
|
|
# then checks the state root against the expected state root which is pulled from
|
|
# the block header. The local test state is persisted to disk so that the data can
|
|
# be re-used between separate test runs. The default database directory is the
|
|
# current directory but this can be changed by setting the DATABASE_PATH const below.
|
|
#
|
|
# To run the test:
|
|
# 1. Sync Nimbus up to or past the block number/s that you wish to test against.
|
|
# You can use the premix persist tool to do this if Nimbus is not able to sync.
|
|
# 2. Start Nimbus with the http RPC-API enabled with the 'eth' and 'exp' namespaces
|
|
# turned on using this command: build/nimbus --rpc --rpc-api=eth,exp
|
|
# 3. Start the test.
|
|
|
|
import
|
|
unittest2,
|
|
web3/eth_api,
|
|
json_rpc/rpcclient,
|
|
stew/byteutils,
|
|
../nimbus/core/chain,
|
|
../nimbus/common/common,
|
|
../nimbus/rpc,
|
|
../nimbus/db/opts,
|
|
../nimbus/db/core_db,
|
|
../nimbus/db/core_db/persistent,
|
|
../nimbus/db/state_db/base,
|
|
./rpc/experimental_rpc_client
|
|
|
|
const
|
|
RPC_HOST = "127.0.0.1"
|
|
RPC_PORT = Port(8545)
|
|
DATABASE_PATH = "."
|
|
START_BLOCK = 330_000
|
|
END_BLOCK = 1_000_000
|
|
|
|
type
|
|
Hash256 = eth_types.Hash256
|
|
|
|
template ethAddr*(x: Address): EthAddress =
|
|
EthAddress x
|
|
|
|
template toHash256(hash: untyped): Hash256 =
|
|
fromHex(Hash256, hash.toHex())
|
|
|
|
proc updateStateUsingProofsAndCheckStateRoot(
|
|
stateDB: AccountStateDB,
|
|
expectedStateRoot: Hash256,
|
|
proofs: seq[ProofResponse]) =
|
|
|
|
check:
|
|
proofs.len() > 0
|
|
|
|
for proof in proofs:
|
|
let
|
|
address = proof.address.ethAddr()
|
|
balance = proof.balance
|
|
nonce = proof.nonce.uint64
|
|
codeHash = proof.codeHash.toHash256()
|
|
storageHash = proof.storageHash.toHash256()
|
|
slotProofs = proof.storageProof
|
|
|
|
if (balance == 0 and nonce == 0 and codeHash == ZERO_HASH256 and storageHash == ZERO_HASH256):
|
|
# Account doesn't exist:
|
|
# The account was deleted due to a self destruct and the data no longer exists in the state.
|
|
# The RPC API correctly returns zeroed values in this scenario which is the same behavior
|
|
# implemented by geth.
|
|
stateDB.setCode(address, @[])
|
|
stateDB.clearStorage(address)
|
|
stateDB.deleteAccount(address)
|
|
elif (balance == 0 and nonce == 0 and codeHash == EMPTY_CODE_HASH and storageHash == EMPTY_ROOT_HASH):
|
|
# Account exists but is empty:
|
|
# The account was deleted due to a self destruct or the storage was cleared/set to zero
|
|
# and the bytecode is empty.
|
|
# The RPC API correctly returns codeHash == EMPTY_CODE_HASH and storageHash == EMPTY_ROOT_HASH
|
|
# in this scenario which is the same behavior implemented by geth.
|
|
stateDB.setCode(address, @[])
|
|
stateDB.clearStorage(address)
|
|
stateDB.setBalance(address, 0.u256)
|
|
stateDB.setNonce(address, 0)
|
|
else:
|
|
# Account exists and is not empty:
|
|
stateDB.setBalance(address, balance)
|
|
stateDB.setNonce(address, nonce)
|
|
for slotProof in slotProofs:
|
|
stateDB.setStorage(address, slotProof.key, slotProof.value)
|
|
|
|
check stateDB.getBalance(address) == balance
|
|
check stateDB.getNonce(address) == nonce
|
|
|
|
if codeHash == ZERO_HASH256 or codeHash == EMPTY_CODE_HASH:
|
|
check stateDB.getCode(address).len() == 0
|
|
check stateDB.getCodeHash(address) == EMPTY_CODE_HASH
|
|
else:
|
|
check stateDB.getCodeHash(address) == codeHash
|
|
|
|
if storageHash == ZERO_HASH256 or storageHash == EMPTY_ROOT_HASH:
|
|
check stateDB.getStorageRoot(address) == EMPTY_ROOT_HASH
|
|
else:
|
|
check stateDB.getStorageRoot(address) == storageHash
|
|
|
|
check stateDB.rootHash == expectedStateRoot
|
|
|
|
proc rpcGetProofsTrackStateChangesMain*() =
|
|
|
|
suite "rpc getProofs track state changes tests":
|
|
|
|
let client = newRpcHttpClient()
|
|
waitFor client.connect(RPC_HOST, RPC_PORT, secure = false)
|
|
|
|
test "Test tracking the changes introduced in every block":
|
|
|
|
let com = CommonRef.new(newCoreDbRef(
|
|
DefaultDbPersistent, DATABASE_PATH, DbOptions.init()))
|
|
com.initializeEmptyDb()
|
|
|
|
let
|
|
blockHeader = waitFor client.eth_getBlockByNumber(blockId(START_BLOCK), false)
|
|
stateDB = newAccountStateDB(com.db, blockHeader.stateRoot.toHash256())
|
|
|
|
for i in START_BLOCK..END_BLOCK:
|
|
let
|
|
blockNum = blockId(i.uint64)
|
|
blockHeader: BlockObject = waitFor client.eth_getBlockByNumber(blockNum, false)
|
|
proofs = waitFor client.exp_getProofsByBlockNumber(blockNum, true)
|
|
|
|
updateStateUsingProofsAndCheckStateRoot(
|
|
stateDB,
|
|
blockHeader.stateRoot.toHash256(),
|
|
proofs)
|
|
|
|
if i mod 1000 == 0:
|
|
echo "Block number: ", i
|
|
echo "Expected block stateRoot: ", blockHeader.stateRoot
|
|
echo "Actual block stateRoot: ", stateDB.rootHash
|
|
doAssert blockHeader.stateRoot.toHash256() == stateDB.rootHash
|
|
|
|
when isMainModule:
|
|
rpcGetProofsTrackStateChangesMain()
|