98 lines
3.1 KiB
Nim
98 lines
3.1 KiB
Nim
# Nimbus
|
|
# Copyright (c) 2022-2023 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
# at your option.
|
|
# This file may not be copied, modified, or distributed except according to
|
|
# those terms.
|
|
|
|
{.push gcsafe, raises: [].}
|
|
|
|
import
|
|
chronicles,
|
|
eth/rlp,
|
|
../db/[core_db, storage_types]
|
|
|
|
type
|
|
# transitionStatus describes the status of eth1/2 transition. This switch
|
|
# between modes is a one-way action which is triggered by corresponding
|
|
# consensus-layer message.
|
|
TransitionStatus = object
|
|
# The flag is set when the first NewHead message received
|
|
leftPoW : bool
|
|
|
|
# The flag is set when the first FinalisedBlock message received
|
|
enteredPoS: bool
|
|
|
|
# Merger is an internal help structure used to track the eth1/2
|
|
# transition status. It's a common structure can be used in both full node
|
|
# and light client.
|
|
MergeTracker* = object
|
|
db : CoreDbRef
|
|
status: TransitionStatus
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Private helpers
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc writeStatus(db: CoreDbRef, status: TransitionStatus) =
|
|
db.kvt.put(transitionStatusKey().toOpenArray(), rlp.encode(status))
|
|
|
|
proc readStatus(db: CoreDbRef): TransitionStatus =
|
|
var bytes = db.kvt.get(transitionStatusKey().toOpenArray())
|
|
if bytes.len > 0:
|
|
try:
|
|
result = rlp.decode(bytes, typeof result)
|
|
except CatchableError:
|
|
error "Failed to decode POS transition status"
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Constructors
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc init*(_: type MergeTracker, db: CoreDbRef): MergeTracker =
|
|
MergeTracker(
|
|
db: db,
|
|
status: db.readStatus()
|
|
)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, setters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc reachTTD*(m: var MergeTracker) =
|
|
## ReachTTD is called whenever the first NewHead message received
|
|
## from the consensus-layer.
|
|
if m.status.leftPoW:
|
|
return
|
|
|
|
m.status = TransitionStatus(leftPoW: true)
|
|
m.db.writeStatus(m.status)
|
|
|
|
info "Left PoW stage"
|
|
|
|
proc finalizePoS*(m: var MergeTracker) =
|
|
## FinalizePoS is called whenever the first FinalisedBlock message received
|
|
## from the consensus-layer.
|
|
|
|
if m.status.enteredPoS:
|
|
return
|
|
|
|
m.status = TransitionStatus(leftPoW: true, enteredPoS: true)
|
|
m.db.writeStatus(m.status)
|
|
|
|
info "Entered PoS stage"
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions, getters
|
|
# ------------------------------------------------------------------------------
|
|
|
|
func ttdReached*(m: MergeTracker): bool =
|
|
## TTDReached reports whether the chain has left the PoW stage.
|
|
m.status.leftPoW
|
|
|
|
func posFinalized*(m: MergeTracker): bool =
|
|
## PoSFinalized reports whether the chain has entered the PoS stage.
|
|
m.status.enteredPoS
|