Update the beacon and state network content key prefixes (#1950)

This commit is contained in:
Kim De Mey 2023-12-19 19:59:38 +01:00 committed by GitHub
parent ffa8ad2246
commit dded8643d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 19 deletions

View File

@ -1,4 +1,4 @@
# Nimbus - Portal Network # Fluffy - Portal Network
# Copyright (c) 2022-2023 Status Research & Development GmbH # Copyright (c) 2022-2023 Status Research & Development GmbH
# Licensed and distributed under either of # Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
@ -30,10 +30,12 @@ const
type type
ContentType* = enum ContentType* = enum
lightClientBootstrap = 0x00 # Note: See same note as for state_content.nim
lightClientUpdate = 0x01 unused = 0x00
lightClientFinalityUpdate = 0x02 lightClientBootstrap = 0x10
lightClientOptimisticUpdate = 0x03 lightClientUpdate = 0x11
lightClientFinalityUpdate = 0x12
lightClientOptimisticUpdate = 0x13
# TODO: Consider how we will gossip bootstraps? # TODO: Consider how we will gossip bootstraps?
# In consensus light client operation a node trusts only one bootstrap hash, # In consensus light client operation a node trusts only one bootstrap hash,
@ -59,6 +61,8 @@ type
ContentKey* = object ContentKey* = object
case contentType*: ContentType case contentType*: ContentType
of unused:
discard
of lightClientBootstrap: of lightClientBootstrap:
lightClientBootstrapKey*: LightClientBootstrapKey lightClientBootstrapKey*: LightClientBootstrapKey
of lightClientUpdate: of lightClientUpdate:
@ -84,8 +88,17 @@ func forkDigestAtEpoch*(
forkDigests.atEpoch(epoch, cfg) forkDigests.atEpoch(epoch, cfg)
func encode*(contentKey: ContentKey): ByteList = func encode*(contentKey: ContentKey): ByteList =
doAssert(contentKey.contentType != unused)
ByteList.init(SSZ.encode(contentKey)) ByteList.init(SSZ.encode(contentKey))
proc readSszBytes*(
data: openArray[byte], val: var ContentKey) {.raises: [SszError].} =
mixin readSszValue
if data.len() > 0 and data[0] == ord(unused):
raise newException(MalformedSszError, "SSZ selector unused value")
readSszValue(data, val)
func decode*(contentKey: ByteList): Opt[ContentKey] = func decode*(contentKey: ByteList): Opt[ContentKey] =
try: try:
Opt.some(SSZ.decode(contentKey.asSeq(), ContentKey)) Opt.some(SSZ.decode(contentKey.asSeq(), ContentKey))

View File

@ -253,6 +253,8 @@ proc createGetHandler*(db: BeaconDb): DbGetHandler =
return Opt.none(seq[byte]) return Opt.none(seq[byte])
case contentKey.contentType: case contentKey.contentType:
of unused:
raiseAssert "Should not be used and fail at decoding"
of lightClientBootstrap: of lightClientBootstrap:
db.get(contentId) db.get(contentId)
of lightClientUpdate: of lightClientUpdate:
@ -309,6 +311,8 @@ proc createStoreHandler*(db: BeaconDb): DbStoreHandler =
return return
case contentKey.contentType: case contentKey.contentType:
of unused:
raiseAssert "Should not be used and fail at decoding"
of lightClientBootstrap: of lightClientBootstrap:
db.put(contentId, content) db.put(contentId, content)
of lightClientUpdate: of lightClientUpdate:

View File

@ -192,6 +192,8 @@ proc validateContent(
return err("Error decoding content key") return err("Error decoding content key")
case key.contentType: case key.contentType:
of unused:
raiseAssert "Should not be used and fail at decoding"
of lightClientBootstrap: of lightClientBootstrap:
let decodingResult = decodeLightClientBootstrapForked( let decodingResult = decodeLightClientBootstrapForked(
n.forkDigests, content) n.forkDigests, content)

View File

@ -1,4 +1,4 @@
# Nimbus # Fluffy
# Copyright (c) 2021-2023 Status Research & Development GmbH # Copyright (c) 2021-2023 Status Research & Development GmbH
# Licensed and distributed under either of # Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
@ -23,11 +23,19 @@ type
Address* = array[20, byte] Address* = array[20, byte]
ContentType* = enum ContentType* = enum
accountTrieNode = 0x00 # Note: Need to add this unused value as a case object with an enum without
contractStorageTrieNode = 0x01 # a 0 valueis not allowed: "low(contentType) must be 0 for discriminant".
accountTrieProof = 0x02 # For prefix values that are in the enum gap, the deserialization will fail
contractStorageTrieProof = 0x03 # at runtime as is wanted.
contractBytecode = 0x04 # In the future it might be possible that this will fail at compile time for
# the SSZ Union type, but currently it is allowed in the implementation, and
# the SSZ spec is not explicit about disallowing this.
unused = 0x00
accountTrieNode = 0x20
contractStorageTrieNode = 0x21
accountTrieProof = 0x22
contractStorageTrieProof = 0x23
contractBytecode = 0x24
AccountTrieNodeKey* = object AccountTrieNodeKey* = object
path*: ByteList path*: ByteList
@ -55,6 +63,8 @@ type
ContentKey* = object ContentKey* = object
case contentType*: ContentType case contentType*: ContentType
of unused:
discard
of accountTrieNode: of accountTrieNode:
accountTrieNodeKey*: AccountTrieNodeKey accountTrieNodeKey*: AccountTrieNodeKey
of contractStorageTrieNode: of contractStorageTrieNode:
@ -67,8 +77,18 @@ type
contractBytecodeKey*: ContractBytecodeKey contractBytecodeKey*: ContractBytecodeKey
func encode*(contentKey: ContentKey): ByteList = func encode*(contentKey: ContentKey): ByteList =
doAssert(contentKey.contentType != unused)
ByteList.init(SSZ.encode(contentKey)) ByteList.init(SSZ.encode(contentKey))
proc readSszBytes*(
data: openArray[byte], val: var ContentKey
) {.raises: [SszError].} =
mixin readSszValue
if data.len() > 0 and data[0] == ord(unused):
raise newException(MalformedSszError, "SSZ selector is unused value")
readSszValue(data, val)
func decode*(contentKey: ByteList): Opt[ContentKey] = func decode*(contentKey: ByteList): Opt[ContentKey] =
try: try:
Opt.some(SSZ.decode(contentKey.asSeq(), ContentKey)) Opt.some(SSZ.decode(contentKey.asSeq(), ContentKey))
@ -84,6 +104,8 @@ template computeContentId*(digestCtxType: type, body: untyped): ContentId =
func toContentId*(contentKey: ContentKey): ContentId = func toContentId*(contentKey: ContentKey): ContentId =
case contentKey.contentType: case contentKey.contentType:
of unused:
raiseAssert "Should not be used and fail at decoding"
of accountTrieNode: # sha256(path | node_hash) of accountTrieNode: # sha256(path | node_hash)
let key = contentKey.accountTrieNodeKey let key = contentKey.accountTrieNodeKey
computeContentId sha256: computeContentId sha256:

View File

@ -281,3 +281,28 @@ suite "Beacon Content Encodings":
decodeLightClientBootstrapForked(forkDigests, @[]).isErr() decodeLightClientBootstrapForked(forkDigests, @[]).isErr()
decodeLightClientBootstrapForked(forkDigests, encodedTooEarlyFork).isErr() decodeLightClientBootstrapForked(forkDigests, encodedTooEarlyFork).isErr()
decodeLightClientBootstrapForked(forkDigests, encodedUnknownFork).isErr() decodeLightClientBootstrapForked(forkDigests, encodedUnknownFork).isErr()
suite "Beacon ContentKey Encodings ":
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 0x14])
let decoded = decode(encoded)
check decoded.isNone()
test "Invalid key - empty input":
let encoded = ByteList.init(@[])
let decoded = decode(encoded)
check decoded.isNone()

View File

@ -1,5 +1,5 @@
# Nimbus # Fluffy
# Copyright (c) 2021-2022 Status Research & Development GmbH # Copyright (c) 2021-2023 Status Research & Development GmbH
# Licensed and distributed under either of # Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * 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). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
@ -31,7 +31,7 @@ suite "State ContentKey Encodings":
# Output # Output
contentKeyHex = contentKeyHex =
"0044000000b8be7903aee73b8f6a59cd44a1f52c62148e1f376c0dfa1f5f773a98666efc2bd1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d01020001" "2044000000b8be7903aee73b8f6a59cd44a1f52c62148e1f376c0dfa1f5f773a98666efc2bd1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d01020001"
contentId = contentId =
"41237096982860596884042712109427867048220765019203857308279863638242761605893" "41237096982860596884042712109427867048220765019203857308279863638242761605893"
# or # or
@ -67,7 +67,7 @@ suite "State ContentKey Encodings":
# Output # Output
contentKeyHex = contentKeyHex =
"01829bd824b016326a401d083b33d092293333a830580000003e190b68719aecbcb28ed2271014dd25f2aa633184988eb414189ce0899cade5d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d01000f0e0c00" "21829bd824b016326a401d083b33d092293333a830580000003e190b68719aecbcb28ed2271014dd25f2aa633184988eb414189ce0899cade5d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d01000f0e0c00"
contentId = contentId =
"43529358882110548041037387588279806363134301284609868141745095118932570363585" "43529358882110548041037387588279806363134301284609868141745095118932570363585"
# or # or
@ -100,7 +100,7 @@ suite "State ContentKey Encodings":
# Output # Output
const const
contentKeyHex = contentKeyHex =
"02829bd824b016326a401d083b33d092293333a830d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d" "22829bd824b016326a401d083b33d092293333a830d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d"
contentId = contentId =
"45301550050471302973396879294932122279426162994178563319590607565171451545101" "45301550050471302973396879294932122279426162994178563319590607565171451545101"
# or # or
@ -135,7 +135,7 @@ suite "State ContentKey Encodings":
# Output # Output
contentKeyHex = contentKeyHex =
"03829bd824b016326a401d083b33d092293333a830c8a6030000000000000000000000000000000000000000000000000000000000d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d" "23829bd824b016326a401d083b33d092293333a830c8a6030000000000000000000000000000000000000000000000000000000000d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d"
contentId = contentId =
"80413803151602881485894828440259195604313253842905231566803078625935967002376" "80413803151602881485894828440259195604313253842905231566803078625935967002376"
# or # or
@ -172,7 +172,7 @@ suite "State ContentKey Encodings":
# Output # Output
const const
contentKeyHex = contentKeyHex =
"04829bd824b016326a401d083b33d092293333a830d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d" "24829bd824b016326a401d083b33d092293333a830d1c390624d3bd4e409a61a858e5dcc5517729a9170d014a6c96530d64dd8621d"
contentId = contentId =
"9243655320250466575533858917172702581481192615849913473767356296630272634800" "9243655320250466575533858917172702581481192615849913473767356296630272634800"
# or # or
@ -199,3 +199,27 @@ suite "State ContentKey Encodings":
toContentId(contentKey) == parse(contentId, StUint[256], 10) toContentId(contentKey) == parse(contentId, StUint[256], 10)
# In stint this does BE hex string # In stint this does BE hex string
toContentId(contentKey).toHex() == contentIdHexBE toContentId(contentKey).toHex() == contentIdHexBE
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()

@ -1 +1 @@
Subproject commit ae43c56eabd021406b8afb41f124d63e3cf5adf9 Subproject commit eb9edb34eb3ea599a5b14407615cef0e7e48e8b9