Remove SSZ Union usage in BlockHeaderWithProof type

Remove SSZ Union in BlockHeaderWithProof type by making the proof
an SSZ encoded ByteList. The right type for the proof can be
selected at the decoding step by first looking into the header
for the timestamp and selecting the right type based on the
hardfork the block is in.
This commit is contained in:
kdeme 2025-01-23 23:42:37 +01:00
parent 67b8dd7fdc
commit 242b9e033d
No known key found for this signature in database
GPG Key ID: 4E8DD21420AF43F5
5 changed files with 27 additions and 40 deletions

View File

@ -26,25 +26,15 @@ const
MAX_WITHDRAWALS_COUNT = MAX_WITHDRAWALS_PER_PAYLOAD
MAX_EPHEMERAL_HEADER_PAYLOAD = 256
MAX_HEADER_PROOF_LENGTH* = 1024
type
## BlockHeader types
HistoricalHashesAccumulatorProof* = array[15, Digest]
BlockHeaderProofType* = enum
none = 0x00 # An SSZ Union None
historicalHashesAccumulatorProof = 0x01
BlockHeaderProof* = object
case proofType*: BlockHeaderProofType
of none:
discard
of historicalHashesAccumulatorProof:
historicalHashesAccumulatorProof*: HistoricalHashesAccumulatorProof
BlockHeaderWithProof* = object
header*: ByteList[MAX_HEADER_LENGTH] # RLP data
proof*: BlockHeaderProof
proof*: ByteList[MAX_HEADER_PROOF_LENGTH]
## Ephemeral BlockHeader list
EphemeralBlockHeaderList* =
@ -73,11 +63,3 @@ type
## Receipts types
ReceiptByteList* = ByteList[MAX_RECEIPT_LENGTH] # RLP data
PortalReceipts* = List[ReceiptByteList, MAX_TRANSACTION_COUNT]
func init*(T: type BlockHeaderProof, proof: HistoricalHashesAccumulatorProof): T =
BlockHeaderProof(
proofType: historicalHashesAccumulatorProof, historicalHashesAccumulatorProof: proof
)
func init*(T: type BlockHeaderProof): T =
BlockHeaderProof(proofType: none)

View File

@ -50,20 +50,23 @@ func validateHeaderBytes*(
ok(header)
func verifyBlockHeaderProof*(
a: FinishedHistoricalHashesAccumulator, header: Header, proof: BlockHeaderProof
a: FinishedHistoricalHashesAccumulator,
header: Header,
proof: ByteList[MAX_HEADER_PROOF_LENGTH],
): Result[void, string] =
case proof.proofType
of BlockHeaderProofType.historicalHashesAccumulatorProof:
a.verifyAccumulatorProof(header, proof.historicalHashesAccumulatorProof)
of BlockHeaderProofType.none:
if header.isPreMerge():
err("Pre merge header requires HistoricalHashesAccumulatorProof")
else:
# TODO:
# Add verification post merge based on historical_roots & historical_summaries
# Lets for now no longer accept other headers without a proof and the most
# recent ones are now a different type.
err("Post merge header proofs not yet activated")
let timestamp = Moment.init(header.timestamp.int64, Second)
if isShanghai(chainConfig, timestamp):
# TODO: Add verification post merge based on historical_summaries
err("Shanghai block verification not implemented")
elif isPoSBlock(chainConfig, header.number):
# TODO: Add verification post merge based on historical_roots
err("PoS block verification not implemented")
else:
let accumulatorProof = decodeSsz(proof.asSeq(), HistoricalHashesAccumulatorProof).valueOr:
return err("Failed decoding accumulator proof: " & error)
a.verifyAccumulatorProof(header, accumulatorProof)
func validateCanonicalHeaderBytes*(
bytes: openArray[byte], id: uint64 | Hash32, a: FinishedHistoricalHashesAccumulator

View File

@ -1,5 +1,5 @@
# Nimbus
# Copyright (c) 2022-2024 Status Research & Development GmbH
# Copyright (c) 2022-2025 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).
@ -198,7 +198,7 @@ func buildHeaderWithProof*(
ok(
BlockHeaderWithProof(
header: ByteList[2048].init(rlp.encode(header)),
proof: BlockHeaderProof.init(proof),
header: ByteList[MAX_HEADER_LENGTH].init(rlp.encode(header)),
proof: ByteList[MAX_HEADER_PROOF_LENGTH].init(SSZ.encode(proof)),
)
)

View File

@ -1,5 +1,5 @@
# Nimbus - Portal Network
# Copyright (c) 2021-2024 Status Research & Development GmbH
# Copyright (c) 2021-2025 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).
@ -63,7 +63,8 @@ proc store*(hn: HistoryNode, blockHash: Hash32, blockHeader: Header) =
let
headerRlp = rlp.encode(blockHeader)
blockHeaderWithProof = BlockHeaderWithProof(
header: ByteList[2048].init(headerRlp), proof: BlockHeaderProof.init()
header: ByteList[MAX_HEADER_LENGTH].init(headerRlp),
proof: ByteList[MAX_HEADER_PROOF_LENGTH].init(@[]),
)
contentKeyBytes = blockHeaderContentKey(blockHash).encode()
contentId = history_content.toContentId(contentKeyBytes)

View File

@ -1,5 +1,5 @@
# Fluffy
# Copyright (c) 2021-2024 Status Research & Development GmbH
# Copyright (c) 2021-2025 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).
@ -154,7 +154,8 @@ proc mockStateRootLookup*(
blockHeader = Header(stateRoot: stateRoot)
headerRlp = rlp.encode(blockHeader)
blockHeaderWithProof = BlockHeaderWithProof(
header: ByteList[2048].init(headerRlp), proof: BlockHeaderProof.init()
header: ByteList[MAX_HEADER_LENGTH].init(headerRlp),
proof: ByteList[MAX_HEADER_PROOF_LENGTH].init(@[]),
)
contentKeyBytes = blockHeaderContentKey(blockNumOrHash).encode()
contentId = history_content.toContentId(contentKeyBytes)