Add retrieval content validation to state network. (#2166)

* Add retrieval content validation to state network.

* Complete state validation tests for retrieval content.

* Improve naming functions and parameters.
This commit is contained in:
web3-developer 2024-05-06 23:13:35 +08:00 committed by GitHub
parent 143f2e99f5
commit 5c4358a969
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 189 additions and 20 deletions

View File

@ -239,7 +239,7 @@ func packNibbles*(nibbles: seq[byte]): Nibbles =
func unpackNibbles*(nibbles: Nibbles): seq[byte] =
doAssert(nibbles.len() <= MAX_PACKED_NIBBLES_LEN, "Packed nibbles length is too long")
var output = newSeqOfCap[byte](nibbles.len * 2)
var output = newSeqOfCap[byte](nibbles.len() * 2)
for i, pair in nibbles:
if i == 0 and pair == 0x00:

View File

@ -14,7 +14,8 @@ import
eth/p2p/discoveryv5/[protocol, enr],
../../database/content_db,
../wire/[portal_protocol, portal_stream, portal_protocol_config],
./state_content
./state_content,
./state_validation
logScope:
topics = "portal_state"
@ -79,34 +80,25 @@ func decodeValue*(
Opt.some(value)
proc validateAccountTrieNode(
n: StateNetwork, key: ContentKey, contentValue: RetrievalContentValue
): bool =
true
proc validateContractTrieNode(
n: StateNetwork, key: ContentKey, contentValue: RetrievalContentValue
): bool =
true
proc validateContractCode(
n: StateNetwork, key: ContentKey, contentValue: RetrievalContentValue
): bool =
true
proc validateContent*(
n: StateNetwork, contentKey: ContentKey, contentValue: RetrievalContentValue
): bool =
doAssert(contentKey.contentType == contentValue.contentType)
case contentKey.contentType
of unused:
warn "Received content with unused content type"
false
of accountTrieNode:
validateAccountTrieNode(n, contentKey, contentValue)
validateFetchedAccountTrieNode(
contentKey.accountTrieNodeKey, contentValue.accountTrieNode
)
of contractTrieNode:
validateContractTrieNode(n, contentKey, contentValue)
validateFetchedContractTrieNode(
contentKey.contractTrieNodeKey, contentValue.contractTrieNode
)
of contractCode:
validateContractCode(n, contentKey, contentValue)
validateFetchedContractCode(contentKey.contractCodeKey, contentValue.contractCode)
proc getContent*(n: StateNetwork, key: ContentKey): Future[Opt[seq[byte]]] {.async.} =
let

View File

@ -0,0 +1,34 @@
# Fluffy
# Copyright (c) 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.
import eth/common, ./state_content
proc validateFetchedAccountTrieNode*(
trustedAccountTrieNodeKey: AccountTrieNodeKey,
accountTrieNode: AccountTrieNodeRetrieval,
): bool =
let expectedHash = trustedAccountTrieNodeKey.nodeHash
let actualHash = keccakHash(accountTrieNode.node.asSeq())
expectedHash == actualHash
proc validateFetchedContractTrieNode*(
trustedContractTrieNodeKey: ContractTrieNodeKey,
contractTrieNode: ContractTrieNodeRetrieval,
): bool =
let expectedHash = trustedContractTrieNodeKey.nodeHash
let actualHash = keccakHash(contractTrieNode.node.asSeq())
expectedHash == actualHash
proc validateFetchedContractCode*(
trustedContractCodeKey: ContractCodeKey, contractCode: ContractCodeRetrieval
): bool =
let expectedHash = trustedContractCodeKey.codeHash
let actualHash = keccakHash(contractCode.code.asSeq())
expectedHash == actualHash

View File

@ -0,0 +1,143 @@
# Fluffy
# 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.
import
std/os,
unittest2,
stew/byteutils,
../../network/state/state_content,
../../network/state/state_validation,
../../eth_data/yaml_utils
const testVectorDir = "./vendor/portal-spec-tests/tests/mainnet/state/validation/"
type YamlTrieNodeRecursiveGossipKV = ref object
content_key: string
content_value_offer: string
content_value_retrieval: string
type YamlTrieNodeKV = object
content_key: string
content_value_offer: string
content_value_retrieval: string
recursive_gossip: YamlTrieNodeRecursiveGossipKV
type YamlTrieNodeKVs = seq[YamlTrieNodeKV]
type YamlContractBytecodeKV = object
content_key: string
content_value_offer: string
content_value_retrieval: string
type YamlContractBytecodeKVs = seq[YamlContractBytecodeKV]
suite "State Validation":
test "Validate valid AccountTrieNodeRetrieval nodes":
const file = testVectorDir / "account_trie_node.yaml"
let testCase = YamlTrieNodeKVs.loadFromYaml(file).valueOr:
raiseAssert "Cannot read test vector: " & error
for testData in testCase:
let contentKey = decode(testData.content_key.hexToSeqByte().ByteList).get()
let contentValueRetrieval = SSZ.decode(
testData.content_value_retrieval.hexToSeqByte(), AccountTrieNodeRetrieval
)
check:
validateFetchedAccountTrieNode(
contentKey.accountTrieNodeKey, contentValueRetrieval
)
test "Validate invalid AccountTrieNodeRetrieval nodes":
const file = testVectorDir / "account_trie_node.yaml"
let testCase = YamlTrieNodeKVs.loadFromYaml(file).valueOr:
raiseAssert "Cannot read test vector: " & error
for testData in testCase:
let contentKey = decode(testData.content_key.hexToSeqByte().ByteList).get()
var contentValueRetrieval = SSZ.decode(
testData.content_value_retrieval.hexToSeqByte(), AccountTrieNodeRetrieval
)
contentValueRetrieval.node[^1] += 1 # Modify node hash
check:
not validateFetchedAccountTrieNode(
contentKey.accountTrieNodeKey, contentValueRetrieval
)
test "Validate valid ContractTrieNodeRetrieval nodes":
const file = testVectorDir / "contract_storage_trie_node.yaml"
let testCase = YamlTrieNodeKVs.loadFromYaml(file).valueOr:
raiseAssert "Cannot read test vector: " & error
for testData in testCase:
let contentKey = decode(testData.content_key.hexToSeqByte().ByteList).get()
let contentValueRetrieval = SSZ.decode(
testData.content_value_retrieval.hexToSeqByte(), ContractTrieNodeRetrieval
)
check:
validateFetchedContractTrieNode(
contentKey.contractTrieNodeKey, contentValueRetrieval
)
test "Validate invalid ContractTrieNodeRetrieval nodes":
const file = testVectorDir / "contract_storage_trie_node.yaml"
let testCase = YamlTrieNodeKVs.loadFromYaml(file).valueOr:
raiseAssert "Cannot read test vector: " & error
for testData in testCase:
let contentKey = decode(testData.content_key.hexToSeqByte().ByteList).get()
var contentValueRetrieval = SSZ.decode(
testData.content_value_retrieval.hexToSeqByte(), ContractTrieNodeRetrieval
)
contentValueRetrieval.node[^1] += 1 # Modify node hash
check:
not validateFetchedContractTrieNode(
contentKey.contractTrieNodeKey, contentValueRetrieval
)
test "Validate valid ContractCodeRetrieval nodes":
const file = testVectorDir / "contract_bytecode.yaml"
let testCase = YamlContractBytecodeKVs.loadFromYaml(file).valueOr:
raiseAssert "Cannot read test vector: " & error
for testData in testCase:
let contentKey = decode(testData.content_key.hexToSeqByte().ByteList).get()
let contentValueRetrieval = SSZ.decode(
testData.content_value_retrieval.hexToSeqByte(), ContractCodeRetrieval
)
check:
validateFetchedContractCode(contentKey.contractCodeKey, contentValueRetrieval)
test "Validate invalid ContractCodeRetrieval nodes":
const file = testVectorDir / "contract_bytecode.yaml"
let testCase = YamlContractBytecodeKVs.loadFromYaml(file).valueOr:
raiseAssert "Cannot read test vector: " & error
for testData in testCase:
let contentKey = decode(testData.content_key.hexToSeqByte().ByteList).get()
var contentValueRetrieval = SSZ.decode(
testData.content_value_retrieval.hexToSeqByte(), ContractCodeRetrieval
)
contentValueRetrieval.code[^1] += 1 # Modify node hash
check:
not validateFetchedContractCode(
contentKey.contractCodeKey, contentValueRetrieval
)