state network test vectors update (#2003)
* state network test vectors update * nibbles codec * moving test vectors into portal-spec-tests * fix copyright year in all_fluffy_tests
This commit is contained in:
parent
f1e9ca8526
commit
9c53c73173
|
@ -18,6 +18,14 @@ import
|
|||
|
||||
export ssz_serialization, common_types, hash, results
|
||||
|
||||
const
|
||||
MAX_PACKED_NIBBLES_LEN = 32
|
||||
MAX_UNPACKED_NIBBLES_LEN = 64
|
||||
|
||||
MAX_TRIE_NODE_LEN = 1024
|
||||
MAX_TRIE_PROOF_LEN = 65
|
||||
MAX_BYTECODE_LEN = 32768
|
||||
|
||||
type
|
||||
NodeHash* = KeccakHash
|
||||
CodeHash* = KeccakHash
|
||||
|
@ -39,19 +47,12 @@ type
|
|||
NibblePair* = byte
|
||||
Nibbles* = object
|
||||
isOddLength*: bool
|
||||
packedNibbles*: List[NibblePair, 32]
|
||||
packedNibbles*: List[NibblePair, MAX_PACKED_NIBBLES_LEN]
|
||||
|
||||
WitnessNode* = List[byte, 1024]
|
||||
Witness* = List[WitnessNode, 1024]
|
||||
TrieNode* = List[byte, MAX_TRIE_NODE_LEN]
|
||||
TrieProof* = List[TrieNode, MAX_TRIE_PROOF_LEN]
|
||||
|
||||
StateWitness* = object
|
||||
key*: Nibbles
|
||||
proof*: Witness
|
||||
|
||||
StorageWitness* = object
|
||||
key*: Nibbles
|
||||
proof*: Witness
|
||||
stateWitness*: StateWitness
|
||||
Bytecode* = List[byte, MAX_BYTECODE_LEN]
|
||||
|
||||
AccountTrieNodeKey* = object
|
||||
path*: Nibbles
|
||||
|
@ -78,26 +79,27 @@ type
|
|||
contractCodeKey*: ContractCodeKey
|
||||
|
||||
AccountTrieNodeOffer* = object
|
||||
proof*: StateWitness
|
||||
proof*: TrieProof
|
||||
blockHash*: BlockHash
|
||||
|
||||
AccountTrieNodeRetrieval* = object
|
||||
node*: WitnessNode
|
||||
node*: TrieNode
|
||||
|
||||
ContractTrieNodeOffer* = object
|
||||
proof*: StorageWitness
|
||||
storageProof*: TrieProof
|
||||
accountProof*: TrieProof
|
||||
blockHash*: BlockHash
|
||||
|
||||
ContractTrieNodeRetrieval* = object
|
||||
node*: WitnessNode
|
||||
node*: TrieNode
|
||||
|
||||
ContractCodeOffer* = object
|
||||
code*: ByteList
|
||||
accountProof*: StateWitness
|
||||
code*: Bytecode
|
||||
accountProof*: TrieProof
|
||||
blockHash*: BlockHash
|
||||
|
||||
ContractCodeRetrieval* = object
|
||||
code*: ByteList
|
||||
code*: Bytecode
|
||||
|
||||
func encode*(contentKey: ContentKey): ByteList =
|
||||
doAssert(contentKey.contentType != unused)
|
||||
|
@ -125,3 +127,44 @@ func toContentId*(contentKey: ByteList): ContentId =
|
|||
|
||||
func toContentId*(contentKey: ContentKey): ContentId =
|
||||
toContentId(encode(contentKey))
|
||||
|
||||
func packNibbles*(nibbles: seq[byte]): Nibbles =
|
||||
doAssert(nibbles.len() <= MAX_UNPACKED_NIBBLES_LEN, "Can't pack more than 64 nibbles")
|
||||
|
||||
let
|
||||
isOddLength = (nibbles.len() %% 2 == 1)
|
||||
outputLength = (nibbles.len() + 1) div 2
|
||||
|
||||
var
|
||||
output = newSeq[NibblePair]()
|
||||
highNibble = not isOddLength
|
||||
currentByte: byte = 0
|
||||
|
||||
for nibble in nibbles:
|
||||
if highNibble:
|
||||
currentByte = nibble shl 4
|
||||
else:
|
||||
output.add(NibblePair(currentByte or nibble))
|
||||
currentByte = 0
|
||||
highNibble = not highNibble
|
||||
|
||||
Nibbles(isOddLength: isOddLength, packedNibbles: Nibbles.packedNibbles.init(output))
|
||||
|
||||
func unpackNibbles*(nibbles: Nibbles): seq[byte] =
|
||||
doAssert(nibbles.packedNibbles.len() <= MAX_PACKED_NIBBLES_LEN, "Can't unpack more than 32 nibbles")
|
||||
|
||||
var output = newSeq[byte]()
|
||||
|
||||
for pair in nibbles.packedNibbles:
|
||||
let
|
||||
first = (pair and 0xF0) shr 4
|
||||
second = pair and 0x0F
|
||||
|
||||
output.add(first)
|
||||
output.add(second)
|
||||
|
||||
if nibbles.isOddLength:
|
||||
output.delete(0)
|
||||
|
||||
output
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Nimbus
|
||||
# Copyright (c) 2021-2023 Status Research & Development GmbH
|
||||
# Copyright (c) 2021-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)
|
||||
|
@ -9,7 +9,8 @@
|
|||
|
||||
import
|
||||
./test_portal_wire_protocol,
|
||||
./state_network_tests/test_state_content,
|
||||
./state_network_tests/test_state_content_keys,
|
||||
./state_network_tests/test_state_content_values,
|
||||
./test_state_proof_verification,
|
||||
./test_accumulator,
|
||||
./test_history_network,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# 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
|
||||
../../network/state/state_content
|
||||
|
||||
type JsonBlockInfo* = object
|
||||
number*: uint64
|
||||
block_hash*: string
|
||||
state_root*: string
|
||||
|
||||
type JsonAccount* = object
|
||||
nonce*: string
|
||||
balance*: string
|
||||
storage_hash*: string
|
||||
code_hash*: string
|
||||
|
||||
type JsonBlock* = object
|
||||
`block`*: JsonBlockInfo
|
||||
address*: string
|
||||
account*: JsonAccount
|
||||
storage_slot*: string
|
||||
storage_value*: string
|
||||
account_proof*: seq[string]
|
||||
storage_proof*: seq[string]
|
||||
bytecode*: string
|
||||
|
||||
type JsonAccountTrieNode* = object
|
||||
content_key*: string
|
||||
content_id*: string
|
||||
content_value_offer*: string
|
||||
content_value_retrieval*: string
|
||||
|
||||
type JsonContractStorageTtrieNode* = object
|
||||
content_key*: string
|
||||
content_id*: string
|
||||
content_value_offer*: string
|
||||
content_value_retrieval*: string
|
||||
|
||||
type JsonContractBytecode* = object
|
||||
content_key*: string
|
||||
content_id*: string
|
||||
content_value_offer*: string
|
||||
content_value_retrieval*: string
|
|
@ -1,239 +0,0 @@
|
|||
# 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
|
||||
testutils/unittests,
|
||||
stew/[byteutils, io2],
|
||||
eth/keys,
|
||||
../../network/state/state_content
|
||||
|
||||
suite "State Content Keys":
|
||||
const evenNibles = "0005000000123456789abc"
|
||||
test "Encode/decode even nibbles":
|
||||
const
|
||||
packedNibbles = Nibbles.packedNibbles.init(@[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC])
|
||||
isOddLength = false
|
||||
|
||||
let
|
||||
nibbles = Nibbles(packedNibbles: packedNibbles, isOddLength: isOddLength)
|
||||
encoded = SSZ.encode(nibbles)
|
||||
check encoded.toHex() == evenNibles
|
||||
# echo ">>>", encoded.toHex()
|
||||
|
||||
const oddNibbles = "0105000000123456789abc0d"
|
||||
test "Encode/decode odd nibbles":
|
||||
const
|
||||
packedNibbles = Nibbles.packedNibbles.init(@[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0x0D])
|
||||
isOddLength = true
|
||||
|
||||
let
|
||||
nibbles = Nibbles(packedNibbles: packedNibbles, isOddLength: isOddLength)
|
||||
encoded = SSZ.encode(nibbles)
|
||||
check encoded.toHex() == oddNibbles
|
||||
# echo ">>>", encoded.toHex()
|
||||
|
||||
const accountTrieNodeKeyEncoded = "2024000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700005000000123456789abc"
|
||||
test "Encode/decode AccountTrieNodeKey":
|
||||
const
|
||||
packedNibbles = Nibbles.packedNibbles.init(@[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC])
|
||||
isOddLength = false
|
||||
nodeHash = NodeHash.fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
||||
|
||||
let
|
||||
nibbles = Nibbles(packedNibbles: packedNibbles, isOddLength: isOddLength)
|
||||
accountTrieNodeKey = AccountTrieNodeKey(path: nibbles, nodeHash: nodeHash)
|
||||
contentKey = ContentKey(contentType: accountTrieNode, accountTrieNodeKey: accountTrieNodeKey)
|
||||
encoded = contentKey.encode()
|
||||
# echo ">>>", $encoded
|
||||
check $encoded == accountTrieNodeKeyEncoded
|
||||
|
||||
let decoded = encoded.decode().valueOr:
|
||||
raiseAssert "Cannot decode AccountTrieNodeKey"
|
||||
check:
|
||||
decoded.contentType == accountTrieNode
|
||||
decoded.accountTrieNodeKey == AccountTrieNodeKey(path: nibbles, nodeHash: nodeHash)
|
||||
|
||||
const contractTrieNodeKeyEncoded = "21000d836201318ec6899a6754069038278074328038000000c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4700005000000123456789abc"
|
||||
test "Encode/decode ContractTrieNodeKey":
|
||||
const
|
||||
address = Address.fromHex("000d836201318ec6899a67540690382780743280")
|
||||
packedNibbles = Nibbles.packedNibbles.init(@[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC])
|
||||
isOddLength = false
|
||||
nodeHash = NodeHash.fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
||||
|
||||
let
|
||||
nibbles = Nibbles(packedNibbles: (packedNibbles), isOddLength: isOddLength)
|
||||
contractTrieNodeKey = ContractTrieNodeKey(address: address, path: nibbles, nodeHash: nodeHash)
|
||||
contentKey = ContentKey(contentType: contractTrieNode, contractTrieNodeKey: contractTrieNodeKey)
|
||||
encoded = contentKey.encode()
|
||||
# echo ">>>", $encoded
|
||||
check $encoded == contractTrieNodeKeyEncoded
|
||||
|
||||
let decoded = encoded.decode().valueOr:
|
||||
raiseAssert "Cannot decode ContractTrieNodeKey"
|
||||
check:
|
||||
decoded.contentType == contractTrieNode
|
||||
decoded.contractTrieNodeKey == ContractTrieNodeKey(address: address, path: nibbles, nodeHash: nodeHash)
|
||||
|
||||
const contractCodeKeyEncoded = "22000d836201318ec6899a67540690382780743280c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
|
||||
test "Encode/decode ContractCodeKey":
|
||||
const
|
||||
address = Address.fromHex("000d836201318ec6899a67540690382780743280")
|
||||
codeHash = CodeHash.fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
|
||||
|
||||
let
|
||||
contractCodeKey = ContractCodeKey(address: address, codeHash: codeHash)
|
||||
contentKey = ContentKey(contentType: contractCode, contractCodeKey: contractCodeKey)
|
||||
encoded = contentKey.encode()
|
||||
# echo ">>>", $encoded
|
||||
check $encoded == contractCodeKeyEncoded
|
||||
|
||||
let decoded = encoded.decode().valueOr:
|
||||
raiseAssert "Cannot decode ContractCodeKey"
|
||||
check:
|
||||
decoded.contentType == contractCode
|
||||
decoded.contractCodeKey.address == address
|
||||
decoded.contractCodeKey.codeHash == codeHash
|
||||
|
||||
test "Invalid prefix - 0 value":
|
||||
let encoded = ByteList.init(@[byte 0x00])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
test "Invalid prefix - before valid range":
|
||||
let encoded = ByteList.init(@[byte 0x01])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
test "Invalid prefix - after valid range":
|
||||
let encoded = ByteList.init(@[byte 0x25])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
test "Invalid key - empty input":
|
||||
let encoded = ByteList.init(@[])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
suite "State Content Values":
|
||||
const accountTrieNodeOfferEncoded = "24000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa308000000130000000005000000123456789abc04000000010203040506"
|
||||
test "Encode/decode AccountTrieNodeOffer":
|
||||
let
|
||||
blockHash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
|
||||
packedNibbles = @[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]
|
||||
isOddLength = false
|
||||
key = Nibbles(packedNibbles: Nibbles.packedNibbles.init(packedNibbles), isOddLength: isOddLength)
|
||||
witnessNode = WitnessNode(@[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
|
||||
proof = Witness(@[witnessNode])
|
||||
|
||||
accountTrieNodeOffer = AccountTrieNodeOffer(blockHash: BlockHash.fromHex(blockHash), proof: StateWitness(key: key, proof: proof))
|
||||
encoded = SSZ.encode(accountTrieNodeOffer)
|
||||
# echo ">>>", encoded.toHex()
|
||||
check encoded.toHex() == accountTrieNodeOfferEncoded
|
||||
|
||||
let decoded = SSZ.decode(encoded, AccountTrieNodeOffer)
|
||||
check:
|
||||
decoded.blockHash == BlockHash.fromHex(blockHash)
|
||||
decoded.proof == StateWitness(key: key, proof: proof)
|
||||
|
||||
const accountTrieNodeRetrievalEncoded = "04000000010203040506"
|
||||
test "Encode/decode AccountTrieNodeRetrieval":
|
||||
let
|
||||
witnessNode = WitnessNode(@[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
|
||||
|
||||
accountTrieNodeRetrieval = AccountTrieNodeRetrieval(node: witnessNode)
|
||||
encoded = SSZ.encode(accountTrieNodeRetrieval)
|
||||
# echo ">>>", encoded.toHex()
|
||||
check encoded.toHex() == accountTrieNodeRetrievalEncoded
|
||||
|
||||
let decoded = SSZ.decode(encoded, AccountTrieNodeRetrieval)
|
||||
check decoded.node == witnessNode
|
||||
|
||||
const contractTrieNodeOfferEncoded = "24000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa30c00000017000000220000000005000000123456789abc040000000102030405060708000000150000000005000000123456789abcdef104000000010203040506070809"
|
||||
test "Encode/decode ContractTrieNodeOffer":
|
||||
let
|
||||
blockHash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
|
||||
contractWitnessKeyPackedNibbles = @[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]
|
||||
contractWitnessProof = Witness(@[WitnessNode(@[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07])])
|
||||
stateWitnessKeyPackedNibbles = @[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF1]
|
||||
stateWitnessProof = Witness(@[WitnessNode(@[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09])])
|
||||
|
||||
contractTrieNodeOffer = ContractTrieNodeOffer(
|
||||
blockHash: BlockHash.fromHex(blockHash),
|
||||
proof: StorageWitness(
|
||||
key: Nibbles(packedNibbles: Nibbles.packedNibbles.init(contractWitnessKeyPackedNibbles), isOddLength: false),
|
||||
proof: contractWitnessProof,
|
||||
stateWitness: StateWitness(
|
||||
key: Nibbles(packedNibbles: Nibbles.packedNibbles.init(stateWitnessKeyPackedNibbles), isOddLength: false),
|
||||
proof: stateWitnessProof
|
||||
)))
|
||||
encoded = SSZ.encode(contractTrieNodeOffer)
|
||||
# echo ">>>", encoded.toHex()
|
||||
check encoded.toHex() == contractTrieNodeOfferEncoded
|
||||
|
||||
let decoded = SSZ.decode(encoded, ContractTrieNodeOffer)
|
||||
check:
|
||||
decoded.blockHash == BlockHash.fromHex(blockHash)
|
||||
decoded.proof == StorageWitness(
|
||||
key: Nibbles(packedNibbles: Nibbles.packedNibbles.init(contractWitnessKeyPackedNibbles), isOddLength: false),
|
||||
proof: contractWitnessProof,
|
||||
stateWitness: StateWitness(
|
||||
key: Nibbles(packedNibbles: Nibbles.packedNibbles.init(stateWitnessKeyPackedNibbles), isOddLength: false),
|
||||
proof: stateWitnessProof
|
||||
))
|
||||
|
||||
const contractTrieNodeRetrievalEncoded = "04000000010203040506"
|
||||
test "Encode/decode ContractTrieNodeRetrieval":
|
||||
let
|
||||
witnessNode = WitnessNode(@[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
|
||||
|
||||
contractTrieNodeRetrieval = ContractTrieNodeRetrieval(node: witnessNode)
|
||||
encoded = SSZ.encode(contractTrieNodeRetrieval)
|
||||
# echo ">>>", encoded.toHex()
|
||||
check encoded.toHex() == contractTrieNodeRetrievalEncoded
|
||||
|
||||
let decoded = SSZ.decode(encoded, ContractTrieNodeRetrieval)
|
||||
check decoded.node == witnessNode
|
||||
|
||||
const contractCodeOfferEncoded = "2800000036000000d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3010203040506070809a0a1a2a3a408000000130000000005000000123456789abc04000000010203040506"
|
||||
test "Encode/decode ContractCodeOffer":
|
||||
let
|
||||
code = @[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4]
|
||||
blockHash = "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
|
||||
accountProofKey = Nibbles(packedNibbles: Nibbles.packedNibbles.init(@[NibblePair 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]), isOddLength: false)
|
||||
accountProofWitness = Witness(@[WitnessNode(@[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06])])
|
||||
|
||||
contractCodeOffer = ContractCodeOffer(
|
||||
code: ByteList.init(code),
|
||||
blockHash: BlockHash.fromHex(blockHash),
|
||||
accountProof: StateWitness(key: accountProofKey, proof: accountProofWitness))
|
||||
encoded = SSZ.encode(contractCodeOffer)
|
||||
# echo ">>>", encoded.toHex()
|
||||
check encoded.toHex() == contractCodeOfferEncoded
|
||||
|
||||
let decoded = SSZ.decode(encoded, ContractCodeOffer)
|
||||
check:
|
||||
decoded.code == ByteList.init(code)
|
||||
decoded.blockHash == BlockHash.fromHex(blockHash)
|
||||
decoded.accountProof == StateWitness(key: accountProofKey, proof: accountProofWitness)
|
||||
|
||||
const contractCodeRetrievalEncoded = "04000000010203040506070809a0a1a2a3a4"
|
||||
test "Encode/decode ContractCodeRetrieval":
|
||||
let
|
||||
code = @[byte 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4]
|
||||
|
||||
contractCodeRetrieval = ContractCodeRetrieval(code: ByteList.init(code))
|
||||
encoded = SSZ.encode(contractCodeRetrieval)
|
||||
# echo ">>>", encoded.toHex()
|
||||
check encoded.toHex() == contractCodeRetrievalEncoded
|
||||
|
||||
let decoded = SSZ.decode(encoded, ContractCodeRetrieval)
|
||||
check decoded.code == ByteList.init(code)
|
|
@ -0,0 +1,123 @@
|
|||
# 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
|
||||
testutils/unittests,
|
||||
stew/[byteutils, io2],
|
||||
eth/keys,
|
||||
../../network/state/state_content
|
||||
|
||||
|
||||
suite "State Content Keys":
|
||||
const evenNibles = "00050000008679e8ed"
|
||||
test "Encode/decode even nibbles":
|
||||
const
|
||||
nibbles: seq[byte] = @[8, 6, 7, 9, 14, 8, 14, 13]
|
||||
packedNibbles = packNibbles(nibbles)
|
||||
unpackedNibbles = unpackNibbles(packedNibbles)
|
||||
|
||||
let
|
||||
encoded = SSZ.encode(packedNibbles)
|
||||
|
||||
check encoded.toHex() == evenNibles
|
||||
check unpackedNibbles == nibbles
|
||||
|
||||
const oddNibbles = "0105000000018679e8ed"
|
||||
test "Encode/decode odd nibbles":
|
||||
const
|
||||
nibbles: seq[byte] = @[1, 8, 6, 7, 9, 14, 8, 14, 13]
|
||||
packedNibbles = packNibbles(nibbles)
|
||||
unpackedNibbles = unpackNibbles(packedNibbles)
|
||||
|
||||
let
|
||||
encoded = SSZ.encode(packedNibbles)
|
||||
|
||||
check encoded.toHex() == oddNibbles
|
||||
check unpackedNibbles == nibbles
|
||||
|
||||
const accountTrieNodeKeyEncoded = "20240000006225fcc63b22b80301d9f2582014e450e91f9b329b7cc87ad16894722fff529600050000008679e8ed"
|
||||
test "Encode/decode AccountTrieNodeKey":
|
||||
const
|
||||
nibbles: seq[byte] = @[8, 6, 7, 9, 14, 8, 14, 13]
|
||||
packedNibbles = packNibbles(nibbles)
|
||||
nodeHash = NodeHash.fromHex("6225fcc63b22b80301d9f2582014e450e91f9b329b7cc87ad16894722fff5296")
|
||||
|
||||
let
|
||||
accountTrieNodeKey = AccountTrieNodeKey(path: packedNibbles, nodeHash: nodeHash)
|
||||
contentKey = ContentKey(contentType: accountTrieNode, accountTrieNodeKey: accountTrieNodeKey)
|
||||
encoded = contentKey.encode()
|
||||
check $encoded == accountTrieNodeKeyEncoded
|
||||
|
||||
let decoded = encoded.decode().valueOr:
|
||||
raiseAssert "Cannot decode AccountTrieNodeKey"
|
||||
check:
|
||||
decoded.contentType == accountTrieNode
|
||||
decoded.accountTrieNodeKey == AccountTrieNodeKey(path: packedNibbles, nodeHash: nodeHash)
|
||||
|
||||
const contractTrieNodeKeyEncoded = "21c02aaa39b223fe8d0a0e5c4f27ead9083c756cc238000000eb43d68008d216e753fef198cf51077f5a89f406d9c244119d1643f0f2b190110005000000405787"
|
||||
test "Encode/decode ContractTrieNodeKey":
|
||||
const
|
||||
nibbles: seq[byte] = @[4, 0, 5, 7, 8, 7]
|
||||
packedNibbles = packNibbles(nibbles)
|
||||
address = Address.fromHex("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
|
||||
isOddLength = false
|
||||
nodeHash = NodeHash.fromHex("eb43d68008d216e753fef198cf51077f5a89f406d9c244119d1643f0f2b19011")
|
||||
|
||||
let
|
||||
contractTrieNodeKey = ContractTrieNodeKey(address: address, path: packedNibbles, nodeHash: nodeHash)
|
||||
contentKey = ContentKey(contentType: contractTrieNode, contractTrieNodeKey: contractTrieNodeKey)
|
||||
encoded = contentKey.encode()
|
||||
check $encoded == contractTrieNodeKeyEncoded
|
||||
|
||||
let decoded = encoded.decode().valueOr:
|
||||
raiseAssert "Cannot decode ContractTrieNodeKey"
|
||||
check:
|
||||
decoded.contentType == contractTrieNode
|
||||
decoded.contractTrieNodeKey == ContractTrieNodeKey(address: address, path: packedNibbles, nodeHash: nodeHash)
|
||||
|
||||
const contractCodeKeyEncoded = "22c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2d0a06b12ac47863b5c7be4185c2deaad1c61557033f56c7d4ea74429cbb25e23"
|
||||
test "Encode/decode ContractCodeKey":
|
||||
const
|
||||
address = Address.fromHex("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
|
||||
codeHash = CodeHash.fromHex("d0a06b12ac47863b5c7be4185c2deaad1c61557033f56c7d4ea74429cbb25e23")
|
||||
|
||||
let
|
||||
contractCodeKey = ContractCodeKey(address: address, codeHash: codeHash)
|
||||
contentKey = ContentKey(contentType: contractCode, contractCodeKey: contractCodeKey)
|
||||
encoded = contentKey.encode()
|
||||
check $encoded == contractCodeKeyEncoded
|
||||
|
||||
let decoded = encoded.decode().valueOr:
|
||||
raiseAssert "Cannot decode ContractCodeKey"
|
||||
check:
|
||||
decoded.contentType == contractCode
|
||||
decoded.contractCodeKey.address == address
|
||||
decoded.contractCodeKey.codeHash == codeHash
|
||||
|
||||
test "Invalid prefix - 0 value":
|
||||
let encoded = ByteList.init(@[byte 0x00])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
test "Invalid prefix - before valid range":
|
||||
let encoded = ByteList.init(@[byte 0x01])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
test "Invalid prefix - after valid range":
|
||||
let encoded = ByteList.init(@[byte 0x25])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
||||
|
||||
test "Invalid key - empty input":
|
||||
let encoded = ByteList.init(@[])
|
||||
let decoded = decode(encoded)
|
||||
|
||||
check decoded.isNone()
|
|
@ -0,0 +1,130 @@
|
|||
# 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/[sugar, sequtils],
|
||||
testutils/unittests,
|
||||
stew/[byteutils, io2],
|
||||
eth/keys,
|
||||
./helpers,
|
||||
../../network/state/state_content,
|
||||
../../eth_data/history_data_json_store
|
||||
|
||||
const testVectorDir = "./vendor/portal-spec-tests/tests/mainnet/state/"
|
||||
|
||||
suite "State Content Values":
|
||||
test "Encode/decode AccountTrieNodeOffer":
|
||||
let
|
||||
blockContent = readJsonType(testVectorDir & "block.json", JsonBlock).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
accountTrieNode = readJsonType(testVectorDir & "account_trie_node.json", JsonAccountTrieNode).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
blockHash = BlockHash.fromHex(blockContent.`block`.block_hash)
|
||||
proof = TrieProof.init(blockContent.account_proof.map((hex) => TrieNode.init(hex.hexToSeqByte())))
|
||||
accountTrieNodeOffer = AccountTrieNodeOffer(blockHash: blockHash, proof: proof)
|
||||
|
||||
encoded = SSZ.encode(accountTrieNodeOffer)
|
||||
expected = accountTrieNode.content_value_offer.hexToSeqByte()
|
||||
decoded = SSZ.decode(encoded, AccountTrieNodeOffer)
|
||||
|
||||
check encoded == expected
|
||||
check decoded == accountTrieNodeOffer
|
||||
|
||||
test "Encode/decode AccountTrieNodeRetrieval":
|
||||
let
|
||||
blockContent = readJsonType(testVectorDir & "block.json", JsonBlock).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
accountTrieNode = readJsonType(testVectorDir & "account_trie_node.json", JsonAccountTrieNode).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
|
||||
node = TrieNode.init(blockContent.account_proof[^1].hexToSeqByte())
|
||||
accountTrieNodeRetrieval = AccountTrieNodeRetrieval(node: node)
|
||||
|
||||
encoded = SSZ.encode(accountTrieNodeRetrieval)
|
||||
expected = accountTrieNode.content_value_retrieval.hexToSeqByte()
|
||||
decoded = SSZ.decode(encoded, AccountTrieNodeRetrieval)
|
||||
|
||||
check encoded == expected
|
||||
check decoded == accountTrieNodeRetrieval
|
||||
|
||||
test "Encode/decode ContractTrieNodeOffer":
|
||||
let
|
||||
blockContent = readJsonType(testVectorDir & "block.json", JsonBlock).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
contractStorageTrieNode = readJsonType(testVectorDir & "contract_storage_trie_node.json", JsonContractStorageTtrieNode).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
|
||||
blockHash = BlockHash.fromHex(blockContent.`block`.block_hash)
|
||||
storageProof = TrieProof.init(blockContent.storage_proof.map((hex) => TrieNode.init(hex.hexToSeqByte())))
|
||||
accountProof = TrieProof.init(blockContent.account_proof.map((hex) => TrieNode.init(hex.hexToSeqByte())))
|
||||
contractTrieNodeOffer = ContractTrieNodeOffer(
|
||||
blockHash: blockHash,
|
||||
storage_proof: storageProof,
|
||||
account_proof: accountProof)
|
||||
|
||||
encoded = SSZ.encode(contractTrieNodeOffer)
|
||||
expected = contractStorageTrieNode.content_value_offer.hexToSeqByte()
|
||||
decoded = SSZ.decode(encoded, ContractTrieNodeOffer)
|
||||
|
||||
check encoded == expected
|
||||
check decoded == contractTrieNodeOffer
|
||||
|
||||
test "Encode/decode ContractTrieNodeRetrieval":
|
||||
let
|
||||
blockContent = readJsonType(testVectorDir & "block.json", JsonBlock).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
contractStorageTrieNode = readJsonType(testVectorDir & "contract_storage_trie_node.json", JsonContractStorageTtrieNode).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
|
||||
node = TrieNode.init(blockContent.storage_proof[^1].hexToSeqByte())
|
||||
contractTrieNodeRetrieval = ContractTrieNodeRetrieval(node: node)
|
||||
|
||||
encoded = SSZ.encode(contractTrieNodeRetrieval)
|
||||
expected = contractStorageTrieNode.content_value_retrieval.hexToSeqByte()
|
||||
decoded = SSZ.decode(encoded, ContractTrieNodeRetrieval)
|
||||
|
||||
check encoded == expected
|
||||
check decoded == contractTrieNodeRetrieval
|
||||
|
||||
test "Encode/decode ContractCodeOffer":
|
||||
let
|
||||
blockContent = readJsonType(testVectorDir & "block.json", JsonBlock).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
contractBytecode = readJsonType(testVectorDir & "contract_bytecode.json", JsonContractBytecode).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
|
||||
code = Bytecode.init(blockContent.bytecode.hexToSeqByte())
|
||||
blockHash = BlockHash.fromHex(blockContent.`block`.block_hash)
|
||||
accountProof = TrieProof.init(blockContent.account_proof.map((hex) => TrieNode.init(hex.hexToSeqByte())))
|
||||
contractCodeOffer = ContractCodeOffer(
|
||||
code: code,
|
||||
blockHash: blockHash,
|
||||
accountProof: accountProof)
|
||||
|
||||
encoded = SSZ.encode(contractCodeOffer)
|
||||
expected = contractBytecode.content_value_offer.hexToSeqByte()
|
||||
decoded = SSZ.decode(encoded, ContractCodeOffer)
|
||||
|
||||
check encoded == expected
|
||||
check decoded == contractCodeOffer
|
||||
|
||||
test "Encode/decode ContractCodeRetrieval":
|
||||
let
|
||||
blockContent = readJsonType(testVectorDir & "block.json", JsonBlock).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
contractBytecode = readJsonType(testVectorDir & "contract_bytecode.json", JsonContractBytecode).valueOr:
|
||||
raiseAssert "Cannot read test vector: " & error
|
||||
|
||||
code = Bytecode.init(blockContent.bytecode.hexToSeqByte())
|
||||
contractCodeRetrieval = ContractCodeRetrieval(code: code)
|
||||
|
||||
encoded = SSZ.encode(contractCodeRetrieval)
|
||||
expected = contractBytecode.content_value_retrieval.hexToSeqByte()
|
||||
decoded = SSZ.decode(encoded, ContractCodeRetrieval)
|
||||
|
||||
check encoded == expected
|
||||
check decoded == contractCodeRetrieval
|
|
@ -1 +1 @@
|
|||
Subproject commit c3f11b8713c3e12be7f517d75cbdbafb9753d1ff
|
||||
Subproject commit e3928b0487ab92ed8323e631728ee3475629757d
|
Loading…
Reference in New Issue