More state endpoint tests (#2399)

This commit is contained in:
web3-developer 2024-06-20 00:21:23 +08:00 committed by GitHub
parent 081cb15493
commit 0b8363764d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 172 additions and 14 deletions

View File

@ -40,15 +40,13 @@ proc getNextNodeHash(
let nextNibble = nibbles[nibbleIdx]
doAssert(nextNibble < 16)
let nextHashBytes = trieNodeRlp.listElem(nextNibble.int)
doAssert(not nextHashBytes.isEmpty())
let nextHashBytes = trieNodeRlp.listElem(nextNibble.int).toBytes()
if nextHashBytes.len() == 0:
return Opt.none((Nibbles, NodeHash))
nibbleIdx += 1
return Opt.some(
(
nibbles[0 ..< nibbleIdx].packNibbles(),
KeccakHash.fromBytes(nextHashBytes.toBytes()),
)
(nibbles[0 ..< nibbleIdx].packNibbles(), KeccakHash.fromBytes(nextHashBytes))
)
# leaf or extension node
@ -57,16 +55,13 @@ proc getNextNodeHash(
return Opt.none((Nibbles, NodeHash))
# extension node
let nextHashBytes = trieNodeRlp.listElem(1).toBytes()
if nextHashBytes.len() == 0:
return Opt.none((Nibbles, NodeHash))
nibbleIdx += prefix.unpackNibbles().len()
let nextHashBytes = trieNodeRlp.listElem(1)
doAssert(not nextHashBytes.isEmpty())
Opt.some(
(
nibbles[0 ..< nibbleIdx].packNibbles(),
KeccakHash.fromBytes(nextHashBytes.toBytes()),
)
(nibbles[0 ..< nibbleIdx].packNibbles(), KeccakHash.fromBytes(nextHashBytes))
)
except RlpError as e:
raiseAssert(e.msg)

View File

@ -11,6 +11,7 @@ import
./test_state_content_keys_vectors,
./test_state_content_nibbles,
./test_state_content_values_vectors,
./test_state_endpoints_genesis,
./test_state_endpoints_vectors,
./test_state_gossip_getparent_genesis,
./test_state_gossip_getparent_vectors,

View File

@ -0,0 +1,162 @@
# 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,
testutils/unittests,
chronos,
results,
eth/[common, trie],
../../../nimbus/common/chain_config,
../../network/wire/[portal_protocol, portal_stream],
../../network/state/
[state_content, state_network, state_gossip, state_endpoints, state_utils],
../../database/content_db,
./state_test_helpers
suite "State Endpoints - Genesis JSON Files":
const STATE_NODE1_PORT = 20702
const genesisFiles = [
"berlin2000.json", "calaveras.json", "chainid1.json", "chainid7.json",
"devnet4.json", "devnet5.json", "holesky.json", "mainshadow1.json", "merge.json",
]
asyncTest "Test getBalance, getTransactionCount, getStorageAt and getCode using JSON files":
let
rng = newRng()
stateNode1 = newStateNode(rng, STATE_NODE1_PORT)
for file in genesisFiles:
let
accounts = getGenesisAlloc("fluffy" / "tests" / "custom_genesis" / file)
(accountState, storageStates) = accounts.toState()
stateRoot = accountState.rootHash()
for address, account in accounts:
let
proof = accountState.generateAccountProof(address)
leafNode = proof[^1]
addressHash = keccakHash(address).data
path = removeLeafKeyEndNibbles(Nibbles.init(addressHash, true), leafNode)
key = AccountTrieNodeKey.init(path, keccakHash(leafNode.asSeq()))
offer = AccountTrieNodeOffer(proof: proof)
# store the account leaf node
let contentKey = key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
contentKey, contentKey.toContentId(), offer.toRetrievalValue().encode()
)
# store the account parent nodes / all remaining nodes
var
parent = offer.withKey(key).getParent()
parentContentKey = parent.key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
parentContentKey,
parentContentKey.toContentId(),
parent.offer.toRetrievalValue().encode(),
)
for i in proof.low ..< proof.high - 1:
parent = parent.getParent()
parentContentKey = parent.key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
parentContentKey,
parentContentKey.toContentId(),
parent.offer.toRetrievalValue().encode(),
)
# mock the block hash because we don't have history network running
stateNode1.mockBlockHashToStateRoot(offer.blockHash, stateRoot)
# verify can lookup account values by walking the trie via the state network endpoints
let
balanceRes =
await stateNode1.stateNetwork.getBalance(offer.blockHash, address)
nonceRes =
await stateNode1.stateNetwork.getTransactionCount(offer.blockHash, address)
check:
balanceRes.isOk()
balanceRes.get() == account.balance
nonceRes.isOk()
nonceRes.get() == account.nonce
if account.code.len() > 0:
block:
# store the code
let
key =
ContractCodeKey(address: address, codeHash: keccakHash(account.code))
value = ContractCodeRetrieval(code: Bytecode.init(account.code))
let contentKey = key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
contentKey, contentKey.toContentId(), value.encode()
)
# verify can lookup code by walking the trie via the state network endpoints
let codeRes =
await stateNode1.stateNetwork.getCode(offer.blockHash, address)
check:
codeRes.isOk()
codeRes.get().asSeq() == account.code
# next test the storage for accounts that have code
let storageState = storageStates[address]
for slotKey, slotValue in account.storage:
let
storageProof = storageState.generateStorageProof(slotKey)
leafNode = storageProof[^1]
slotKeyHash = keccakHash(toBytesBE(slotKey)).data
path = removeLeafKeyEndNibbles(
Nibbles.init(keccakHash(toBytesBE(slotKey)).data, true), leafNode
)
key = ContractTrieNodeKey(
address: address, path: path, nodeHash: keccakHash(leafNode.asSeq())
)
offer =
ContractTrieNodeOffer(storageProof: storageProof, accountProof: proof)
# store the contract storage leaf node
let contentKey = key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
contentKey, contentKey.toContentId(), offer.toRetrievalValue().encode()
)
# store the remaining contract storage nodes
var
parent = offer.withKey(key).getParent()
parentContentKey = parent.key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
parentContentKey,
parentContentKey.toContentId(),
parent.offer.toRetrievalValue().encode(),
)
for i in storageProof.low ..< storageProof.high - 1:
parent = parent.getParent()
parentContentKey = parent.key.toContentKey().encode()
stateNode1.portalProtocol.storeContent(
parentContentKey,
parentContentKey.toContentId(),
parent.offer.toRetrievalValue().encode(),
)
# verify can lookup contract values by walking the trie via the state network endpoints
let storageAtRes = await stateNode1.stateNetwork.getStorageAt(
offer.blockHash, address, slotKey
)
check:
storageAtRes.isOk()
storageAtRes.get() == slotValue