79 lines
2.4 KiB
Nim
79 lines
2.4 KiB
Nim
|
# Nimbus
|
||
|
# Copyright (c) 2022 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.
|
||
|
|
||
|
# https://github.com/ethereum/portal-network-specs/blob/master/header-gossip-network.md
|
||
|
|
||
|
{.push raises: [Defect].}
|
||
|
|
||
|
import
|
||
|
nimcrypto/[sha2, hash],
|
||
|
ssz_serialization, ssz_serialization/merkleization,
|
||
|
eth/common/eth_types,
|
||
|
../../common/common_types
|
||
|
|
||
|
export merkleization
|
||
|
|
||
|
const
|
||
|
epochSize = 8192 # blocks
|
||
|
maxHistoricalEpochs = 100_000 # Doesn't really need a limit, does it?
|
||
|
|
||
|
type
|
||
|
# Header Gossip Content Keys
|
||
|
# https://github.com/ethereum/portal-network-specs/blob/master/header-gossip-network.md#content-keys
|
||
|
|
||
|
ContentType* = enum
|
||
|
accumulatorSnapshot = 0x00
|
||
|
newBlockHeader = 0x01
|
||
|
|
||
|
AccumulatorSnapshotKey* = object
|
||
|
accumulatorRootHash*: Bytes32
|
||
|
|
||
|
NewBlockHeaderKey* = object
|
||
|
blockHash*: BlockHash
|
||
|
blockNumber*: UInt256
|
||
|
|
||
|
ContentKey* = object
|
||
|
case contentType*: ContentType
|
||
|
of accumulatorSnapshot:
|
||
|
accumulatorSnapshotKey*: AccumulatorSnapshotKey
|
||
|
of newBlockHeader:
|
||
|
newBlockHeaderKey*: NewBlockHeaderKey
|
||
|
|
||
|
# Header Accumulator
|
||
|
# https://github.com/ethereum/portal-network-specs/blob/master/header-gossip-network.md#accumulator-snapshot
|
||
|
|
||
|
HeaderRecord = object
|
||
|
blockHash: BlockHash
|
||
|
totalDifficulty: UInt256
|
||
|
|
||
|
EpochAccumulator = List[HeaderRecord, epochSize]
|
||
|
|
||
|
Accumulator* = object
|
||
|
historicalEpochs*: List[Bytes32, maxHistoricalEpochs]
|
||
|
currentEpoch*: EpochAccumulator
|
||
|
|
||
|
func updateAccumulator*(a: var Accumulator, header: BlockHeader) =
|
||
|
let lastTotalDifficulty =
|
||
|
if a.currentEpoch.len() == 0:
|
||
|
0.stuint(256)
|
||
|
else:
|
||
|
a.currentEpoch[^1].totalDifficulty
|
||
|
|
||
|
if a.currentEpoch.len() == epochSize:
|
||
|
let epochHash = hash_tree_root(a.currentEpoch)
|
||
|
|
||
|
doAssert(a.historicalEpochs.add(epochHash.data))
|
||
|
a.currentEpoch = EpochAccumulator.init(@[])
|
||
|
|
||
|
let headerRecord =
|
||
|
HeaderRecord(
|
||
|
blockHash: header.blockHash(),
|
||
|
totalDifficulty: lastTotalDifficulty + header.difficulty)
|
||
|
|
||
|
let res = a.currentEpoch.add(headerRecord)
|
||
|
doAssert(res, "Can't fail because of currentEpoch length check")
|