990 lines
35 KiB
Nim
990 lines
35 KiB
Nim
# beacon_chain
|
|
# Copyright (c) 2023 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.
|
|
|
|
{.push raises: [].}
|
|
|
|
import
|
|
./datatypes/[phase0, altair, bellatrix, capella, deneb],
|
|
./eth2_merkleization
|
|
|
|
type
|
|
LightClientDataFork* {.pure.} = enum # Append only, used in DB data!
|
|
None = 0, # only use non-0 in DB to detect accidentally uninitialized data
|
|
Altair = 1,
|
|
Capella = 2,
|
|
Deneb = 3
|
|
|
|
ForkyLightClientHeader* =
|
|
altair.LightClientHeader |
|
|
capella.LightClientHeader |
|
|
deneb.LightClientHeader
|
|
|
|
ForkyLightClientBootstrap* =
|
|
altair.LightClientBootstrap |
|
|
capella.LightClientBootstrap |
|
|
deneb.LightClientBootstrap
|
|
|
|
ForkyLightClientUpdate* =
|
|
altair.LightClientUpdate |
|
|
capella.LightClientUpdate |
|
|
deneb.LightClientUpdate
|
|
|
|
ForkyLightClientFinalityUpdate* =
|
|
altair.LightClientFinalityUpdate |
|
|
capella.LightClientFinalityUpdate |
|
|
deneb.LightClientFinalityUpdate
|
|
|
|
ForkyLightClientOptimisticUpdate* =
|
|
altair.LightClientOptimisticUpdate |
|
|
capella.LightClientOptimisticUpdate |
|
|
deneb.LightClientOptimisticUpdate
|
|
|
|
SomeForkyLightClientUpdateWithSyncCommittee* =
|
|
ForkyLightClientUpdate
|
|
|
|
SomeForkyLightClientUpdateWithFinality* =
|
|
ForkyLightClientUpdate |
|
|
ForkyLightClientFinalityUpdate
|
|
|
|
SomeForkyLightClientUpdate* =
|
|
ForkyLightClientUpdate |
|
|
ForkyLightClientFinalityUpdate |
|
|
ForkyLightClientOptimisticUpdate
|
|
|
|
SomeForkyLightClientObject* =
|
|
ForkyLightClientBootstrap |
|
|
SomeForkyLightClientUpdate
|
|
|
|
ForkyLightClientStore* =
|
|
altair.LightClientStore |
|
|
capella.LightClientStore |
|
|
deneb.LightClientStore
|
|
|
|
ForkedLightClientHeader* = object
|
|
case kind*: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData*: altair.LightClientHeader
|
|
of LightClientDataFork.Capella:
|
|
capellaData*: capella.LightClientHeader
|
|
of LightClientDataFork.Deneb:
|
|
denebData*: deneb.LightClientHeader
|
|
|
|
ForkedLightClientBootstrap* = object
|
|
case kind*: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData*: altair.LightClientBootstrap
|
|
of LightClientDataFork.Capella:
|
|
capellaData*: capella.LightClientBootstrap
|
|
of LightClientDataFork.Deneb:
|
|
denebData*: deneb.LightClientBootstrap
|
|
|
|
ForkedLightClientUpdate* = object
|
|
case kind*: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData*: altair.LightClientUpdate
|
|
of LightClientDataFork.Capella:
|
|
capellaData*: capella.LightClientUpdate
|
|
of LightClientDataFork.Deneb:
|
|
denebData*: deneb.LightClientUpdate
|
|
|
|
ForkedLightClientFinalityUpdate* = object
|
|
case kind*: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData*: altair.LightClientFinalityUpdate
|
|
of LightClientDataFork.Capella:
|
|
capellaData*: capella.LightClientFinalityUpdate
|
|
of LightClientDataFork.Deneb:
|
|
denebData*: deneb.LightClientFinalityUpdate
|
|
|
|
ForkedLightClientOptimisticUpdate* = object
|
|
case kind*: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData*: altair.LightClientOptimisticUpdate
|
|
of LightClientDataFork.Capella:
|
|
capellaData*: capella.LightClientOptimisticUpdate
|
|
of LightClientDataFork.Deneb:
|
|
denebData*: deneb.LightClientOptimisticUpdate
|
|
|
|
SomeForkedLightClientUpdateWithSyncCommittee* =
|
|
ForkedLightClientUpdate
|
|
|
|
SomeForkedLightClientUpdateWithFinality* =
|
|
ForkedLightClientUpdate |
|
|
ForkedLightClientFinalityUpdate
|
|
|
|
SomeForkedLightClientUpdate* =
|
|
ForkedLightClientUpdate |
|
|
ForkedLightClientFinalityUpdate |
|
|
ForkedLightClientOptimisticUpdate
|
|
|
|
SomeForkedLightClientObject* =
|
|
ForkedLightClientBootstrap |
|
|
SomeForkedLightClientUpdate
|
|
|
|
ForkedLightClientStore* = object
|
|
case kind*: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData*: altair.LightClientStore
|
|
of LightClientDataFork.Capella:
|
|
capellaData*: capella.LightClientStore
|
|
of LightClientDataFork.Deneb:
|
|
denebData*: deneb.LightClientStore
|
|
|
|
func lcDataForkAtEpoch*(
|
|
cfg: RuntimeConfig, epoch: Epoch): LightClientDataFork =
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
if epoch >= cfg.DENEB_FORK_EPOCH:
|
|
LightClientDataFork.Deneb
|
|
elif epoch >= cfg.CAPELLA_FORK_EPOCH:
|
|
LightClientDataFork.Capella
|
|
elif epoch >= cfg.ALTAIR_FORK_EPOCH:
|
|
LightClientDataFork.Altair
|
|
else:
|
|
LightClientDataFork.None
|
|
|
|
template kind*(
|
|
x: typedesc[ # `SomeLightClientObject` doesn't work here (Nim 1.6)
|
|
altair.LightClientHeader |
|
|
altair.LightClientBootstrap |
|
|
altair.LightClientUpdate |
|
|
altair.LightClientFinalityUpdate |
|
|
altair.LightClientOptimisticUpdate |
|
|
altair.LightClientStore]): LightClientDataFork =
|
|
LightClientDataFork.Altair
|
|
|
|
template kind*(
|
|
x: typedesc[ # `SomeLightClientObject` doesn't work here (Nim 1.6)
|
|
capella.LightClientHeader |
|
|
capella.LightClientBootstrap |
|
|
capella.LightClientUpdate |
|
|
capella.LightClientFinalityUpdate |
|
|
capella.LightClientOptimisticUpdate |
|
|
capella.LightClientStore]): LightClientDataFork =
|
|
LightClientDataFork.Capella
|
|
|
|
template kind*(
|
|
x: typedesc[ # `SomeLightClientObject` doesn't work here (Nim 1.6)
|
|
deneb.LightClientHeader |
|
|
deneb.LightClientBootstrap |
|
|
deneb.LightClientUpdate |
|
|
deneb.LightClientFinalityUpdate |
|
|
deneb.LightClientOptimisticUpdate |
|
|
deneb.LightClientStore]): LightClientDataFork =
|
|
LightClientDataFork.Deneb
|
|
|
|
template LightClientHeader*(kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
typedesc[deneb.LightClientHeader]
|
|
elif kind == LightClientDataFork.Capella:
|
|
typedesc[capella.LightClientHeader]
|
|
elif kind == LightClientDataFork.Altair:
|
|
typedesc[altair.LightClientHeader]
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
template LightClientBootstrap*(kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
typedesc[deneb.LightClientBootstrap]
|
|
elif kind == LightClientDataFork.Capella:
|
|
typedesc[capella.LightClientBootstrap]
|
|
elif kind == LightClientDataFork.Altair:
|
|
typedesc[altair.LightClientBootstrap]
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
template LightClientUpdate*(kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
typedesc[deneb.LightClientUpdate]
|
|
elif kind == LightClientDataFork.Capella:
|
|
typedesc[capella.LightClientUpdate]
|
|
elif kind == LightClientDataFork.Altair:
|
|
typedesc[altair.LightClientUpdate]
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
template LightClientFinalityUpdate*(kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
typedesc[deneb.LightClientFinalityUpdate]
|
|
elif kind == LightClientDataFork.Capella:
|
|
typedesc[capella.LightClientFinalityUpdate]
|
|
elif kind == LightClientDataFork.Altair:
|
|
typedesc[altair.LightClientFinalityUpdate]
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
template LightClientOptimisticUpdate*(kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
typedesc[deneb.LightClientOptimisticUpdate]
|
|
elif kind == LightClientDataFork.Capella:
|
|
typedesc[capella.LightClientOptimisticUpdate]
|
|
elif kind == LightClientDataFork.Altair:
|
|
typedesc[altair.LightClientOptimisticUpdate]
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
template LightClientStore*(kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
typedesc[deneb.LightClientStore]
|
|
elif kind == LightClientDataFork.Capella:
|
|
typedesc[capella.LightClientStore]
|
|
elif kind == LightClientDataFork.Altair:
|
|
typedesc[altair.LightClientStore]
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
template Forky*(
|
|
x: typedesc[ForkedLightClientHeader],
|
|
kind: static LightClientDataFork): auto =
|
|
kind.LightClientHeader
|
|
|
|
template Forky*(
|
|
x: typedesc[ForkedLightClientBootstrap],
|
|
kind: static LightClientDataFork): auto =
|
|
kind.LightClientBootstrap
|
|
|
|
template Forky*(
|
|
x: typedesc[ForkedLightClientUpdate],
|
|
kind: static LightClientDataFork): auto =
|
|
kind.LightClientUpdate
|
|
|
|
template Forky*(
|
|
x: typedesc[ForkedLightClientFinalityUpdate],
|
|
kind: static LightClientDataFork): auto =
|
|
kind.LightClientFinalityUpdate
|
|
|
|
template Forky*(
|
|
x: typedesc[ForkedLightClientOptimisticUpdate],
|
|
kind: static LightClientDataFork): auto =
|
|
kind.LightClientOptimisticUpdate
|
|
|
|
template Forky*(
|
|
x: typedesc[ForkedLightClientStore],
|
|
kind: static LightClientDataFork): auto =
|
|
kind.LightClientStore
|
|
|
|
template Forked*(x: typedesc[ForkyLightClientHeader]): auto =
|
|
typedesc[ForkedLightClientHeader]
|
|
|
|
template Forked*(x: typedesc[ForkyLightClientBootstrap]): auto =
|
|
typedesc[ForkedLightClientBootstrap]
|
|
|
|
template Forked*(x: typedesc[ForkyLightClientUpdate]): auto =
|
|
typedesc[ForkedLightClientUpdate]
|
|
|
|
template Forked*(x: typedesc[ForkyLightClientFinalityUpdate]): auto =
|
|
typedesc[ForkedLightClientFinalityUpdate]
|
|
|
|
template Forked*(x: typedesc[ForkyLightClientOptimisticUpdate]): auto =
|
|
typedesc[ForkedLightClientOptimisticUpdate]
|
|
|
|
template Forked*(x: typedesc[ForkyLightClientStore]): auto =
|
|
typedesc[ForkedLightClientStore]
|
|
|
|
template withAll*(
|
|
x: typedesc[LightClientDataFork], body: untyped): untyped =
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
block:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
body
|
|
block:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
body
|
|
block:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
body
|
|
block:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withLcDataFork*(
|
|
x: LightClientDataFork, body: untyped): untyped =
|
|
case x
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyHeader*(
|
|
x: ForkedLightClientHeader, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyHeader: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyHeader: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyHeader: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyBootstrap*(
|
|
x: ForkedLightClientBootstrap, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyBootstrap: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyBootstrap: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyBootstrap: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyUpdate*(
|
|
x: ForkedLightClientUpdate, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyUpdate: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyUpdate: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyUpdate: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyFinalityUpdate*(
|
|
x: ForkedLightClientFinalityUpdate, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyFinalityUpdate: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyFinalityUpdate: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyFinalityUpdate: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyOptimisticUpdate*(
|
|
x: ForkedLightClientOptimisticUpdate, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyOptimisticUpdate: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyOptimisticUpdate: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyOptimisticUpdate: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyObject*(
|
|
x: SomeForkedLightClientObject, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyObject: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyObject: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyObject: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
template withForkyStore*(
|
|
x: ForkedLightClientStore, body: untyped): untyped =
|
|
case x.kind
|
|
of LightClientDataFork.Deneb:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Deneb
|
|
template forkyStore: untyped {.inject, used.} = x.denebData
|
|
body
|
|
of LightClientDataFork.Capella:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Capella
|
|
template forkyStore: untyped {.inject, used.} = x.capellaData
|
|
body
|
|
of LightClientDataFork.Altair:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.Altair
|
|
template forkyStore: untyped {.inject, used.} = x.altairData
|
|
body
|
|
of LightClientDataFork.None:
|
|
const lcDataFork {.inject, used.} = LightClientDataFork.None
|
|
body
|
|
|
|
func toFull*(
|
|
update: SomeForkyLightClientUpdate): auto =
|
|
type ResultType = typeof(update).kind.LightClientUpdate
|
|
when update is ForkyLightClientUpdate:
|
|
update
|
|
elif update is SomeForkyLightClientUpdateWithFinality:
|
|
ResultType(
|
|
attested_header: update.attested_header,
|
|
finalized_header: update.finalized_header,
|
|
finality_branch: update.finality_branch,
|
|
sync_aggregate: update.sync_aggregate,
|
|
signature_slot: update.signature_slot)
|
|
else:
|
|
ResultType(
|
|
attested_header: update.attested_header,
|
|
sync_aggregate: update.sync_aggregate,
|
|
signature_slot: update.signature_slot)
|
|
|
|
func toFull*(
|
|
update: SomeForkedLightClientUpdate): ForkedLightClientUpdate =
|
|
when update is ForkyLightClientUpdate:
|
|
update
|
|
else:
|
|
withForkyObject(update):
|
|
when lcDataFork > LightClientDataFork.None:
|
|
var res = ForkedLightClientUpdate(kind: lcDataFork)
|
|
template forkyRes: untyped = res.forky(lcDataFork)
|
|
forkyRes = forkyObject.toFull()
|
|
res
|
|
else:
|
|
default(ForkedLightClientUpdate)
|
|
|
|
func toFinality*(
|
|
update: SomeForkyLightClientUpdate): auto =
|
|
type ResultType = typeof(update).kind.LightClientFinalityUpdate
|
|
when update is ForkyLightClientFinalityUpdate:
|
|
update
|
|
elif update is SomeForkyLightClientUpdateWithFinality:
|
|
ResultType(
|
|
attested_header: update.attested_header,
|
|
finalized_header: update.finalized_header,
|
|
finality_branch: update.finality_branch,
|
|
sync_aggregate: update.sync_aggregate,
|
|
signature_slot: update.signature_slot)
|
|
else:
|
|
ResultType(
|
|
attested_header: update.attested_header,
|
|
sync_aggregate: update.sync_aggregate,
|
|
signature_slot: update.signature_slot)
|
|
|
|
func toFinality*(
|
|
update: SomeForkedLightClientUpdate): ForkedLightClientFinalityUpdate =
|
|
when update is ForkyLightClientFinalityUpdate:
|
|
update
|
|
else:
|
|
withForkyObject(update):
|
|
when lcDataFork > LightClientDataFork.None:
|
|
var res = ForkedLightClientFinalityUpdate(kind: lcDataFork)
|
|
template forkyRes: untyped = res.forky(lcDataFork)
|
|
forkyRes = forkyObject.toFinality()
|
|
res
|
|
else:
|
|
default(ForkedLightClientFinalityUpdate)
|
|
|
|
func toOptimistic*(
|
|
update: SomeForkyLightClientUpdate): auto =
|
|
type ResultType = typeof(update).kind.LightClientOptimisticUpdate
|
|
when update is ForkyLightClientOptimisticUpdate:
|
|
update
|
|
else:
|
|
ResultType(
|
|
attested_header: update.attested_header,
|
|
sync_aggregate: update.sync_aggregate,
|
|
signature_slot: update.signature_slot)
|
|
|
|
func toOptimistic*(
|
|
update: SomeForkedLightClientUpdate): ForkedLightClientOptimisticUpdate =
|
|
when update is ForkyLightClientOptimisticUpdate:
|
|
update
|
|
else:
|
|
withForkyObject(update):
|
|
when lcDataFork > LightClientDataFork.None:
|
|
var res = ForkedLightClientOptimisticUpdate(kind: lcDataFork)
|
|
template forkyRes: untyped = res.forky(lcDataFork)
|
|
forkyRes = forkyObject.toOptimistic()
|
|
res
|
|
else:
|
|
default(ForkedLightClientOptimisticUpdate)
|
|
|
|
func matches*[A, B: SomeForkyLightClientUpdate](a: A, b: B): bool =
|
|
static: doAssert typeof(A).kind == typeof(B).kind
|
|
if a.attested_header != b.attested_header:
|
|
return false
|
|
when a is SomeForkyLightClientUpdateWithSyncCommittee and
|
|
b is SomeForkyLightClientUpdateWithSyncCommittee:
|
|
if a.next_sync_committee != b.next_sync_committee:
|
|
return false
|
|
if a.next_sync_committee_branch != b.next_sync_committee_branch:
|
|
return false
|
|
when a is SomeForkyLightClientUpdateWithFinality and
|
|
b is SomeForkyLightClientUpdateWithFinality:
|
|
if a.finalized_header != b.finalized_header:
|
|
return false
|
|
if a.finality_branch != b.finality_branch:
|
|
return false
|
|
if a.sync_aggregate != b.sync_aggregate:
|
|
return false
|
|
if a.signature_slot != b.signature_slot:
|
|
return false
|
|
true
|
|
|
|
func matches*[A, B: SomeForkedLightClientUpdate](a: A, b: B): bool =
|
|
if a.kind != b.kind:
|
|
return false
|
|
withForkyObject(a):
|
|
when lcDataFork > LightClientDataFork.None:
|
|
forkyObject.matches(b.forky(lcDataFork))
|
|
else:
|
|
true
|
|
|
|
template forky*(
|
|
x:
|
|
ForkedLightClientHeader |
|
|
SomeForkedLightClientObject |
|
|
ForkedLightClientStore,
|
|
kind: static LightClientDataFork): untyped =
|
|
when kind == LightClientDataFork.Deneb:
|
|
x.denebData
|
|
elif kind == LightClientDataFork.Capella:
|
|
x.capellaData
|
|
elif kind == LightClientDataFork.Altair:
|
|
x.altairData
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
func migrateToDataFork*(
|
|
x: var ForkedLightClientHeader,
|
|
newKind: static LightClientDataFork) =
|
|
if newKind == x.kind:
|
|
# Already at correct kind
|
|
discard
|
|
elif newKind < x.kind:
|
|
# Downgrade not supported, re-initialize
|
|
x = ForkedLightClientHeader(kind: newKind)
|
|
else:
|
|
# Upgrade to Altair
|
|
when newKind >= LightClientDataFork.Altair:
|
|
if x.kind == LightClientDataFork.None:
|
|
x = ForkedLightClientHeader(
|
|
kind: LightClientDataFork.Altair)
|
|
|
|
# Upgrade to Capella
|
|
when newKind >= LightClientDataFork.Capella:
|
|
if x.kind == LightClientDataFork.Altair:
|
|
x = ForkedLightClientHeader(
|
|
kind: LightClientDataFork.Capella,
|
|
capellaData: upgrade_lc_header_to_capella(
|
|
x.forky(LightClientDataFork.Altair)))
|
|
|
|
# Upgrade to Deneb
|
|
when newKind >= LightClientDataFork.Deneb:
|
|
if x.kind == LightClientDataFork.Capella:
|
|
x = ForkedLightClientHeader(
|
|
kind: LightClientDataFork.Deneb,
|
|
denebData: upgrade_lc_header_to_deneb(
|
|
x.forky(LightClientDataFork.Capella)))
|
|
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
doAssert x.kind == newKind
|
|
|
|
func migrateToDataFork*(
|
|
x: var ForkedLightClientBootstrap,
|
|
newKind: static LightClientDataFork) =
|
|
if newKind == x.kind:
|
|
# Already at correct kind
|
|
discard
|
|
elif newKind < x.kind:
|
|
# Downgrade not supported, re-initialize
|
|
x = ForkedLightClientBootstrap(kind: newKind)
|
|
else:
|
|
# Upgrade to Altair
|
|
when newKind >= LightClientDataFork.Altair:
|
|
if x.kind == LightClientDataFork.None:
|
|
x = ForkedLightClientBootstrap(
|
|
kind: LightClientDataFork.Altair)
|
|
|
|
# Upgrade to Capella
|
|
when newKind >= LightClientDataFork.Capella:
|
|
if x.kind == LightClientDataFork.Altair:
|
|
x = ForkedLightClientBootstrap(
|
|
kind: LightClientDataFork.Capella,
|
|
capellaData: upgrade_lc_bootstrap_to_capella(
|
|
x.forky(LightClientDataFork.Altair)))
|
|
|
|
# Upgrade to Deneb
|
|
when newKind >= LightClientDataFork.Deneb:
|
|
if x.kind == LightClientDataFork.Capella:
|
|
x = ForkedLightClientBootstrap(
|
|
kind: LightClientDataFork.Deneb,
|
|
denebData: upgrade_lc_bootstrap_to_deneb(
|
|
x.forky(LightClientDataFork.Capella)))
|
|
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
doAssert x.kind == newKind
|
|
|
|
func migrateToDataFork*(
|
|
x: var ForkedLightClientUpdate,
|
|
newKind: static LightClientDataFork) =
|
|
if newKind == x.kind:
|
|
# Already at correct kind
|
|
discard
|
|
elif newKind < x.kind:
|
|
# Downgrade not supported, re-initialize
|
|
x = ForkedLightClientUpdate(kind: newKind)
|
|
else:
|
|
# Upgrade to Altair
|
|
when newKind >= LightClientDataFork.Altair:
|
|
if x.kind == LightClientDataFork.None:
|
|
x = ForkedLightClientUpdate(
|
|
kind: LightClientDataFork.Altair)
|
|
|
|
# Upgrade to Capella
|
|
when newKind >= LightClientDataFork.Capella:
|
|
if x.kind == LightClientDataFork.Altair:
|
|
x = ForkedLightClientUpdate(
|
|
kind: LightClientDataFork.Capella,
|
|
capellaData: upgrade_lc_update_to_capella(
|
|
x.forky(LightClientDataFork.Altair)))
|
|
|
|
# Upgrade to Deneb
|
|
when newKind >= LightClientDataFork.Deneb:
|
|
if x.kind == LightClientDataFork.Capella:
|
|
x = ForkedLightClientUpdate(
|
|
kind: LightClientDataFork.Deneb,
|
|
denebData: upgrade_lc_update_to_deneb(
|
|
x.forky(LightClientDataFork.Capella)))
|
|
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
doAssert x.kind == newKind
|
|
|
|
func migrateToDataFork*(
|
|
x: var ForkedLightClientFinalityUpdate,
|
|
newKind: static LightClientDataFork) =
|
|
if newKind == x.kind:
|
|
# Already at correct kind
|
|
discard
|
|
elif newKind < x.kind:
|
|
# Downgrade not supported, re-initialize
|
|
x = ForkedLightClientFinalityUpdate(kind: newKind)
|
|
else:
|
|
# Upgrade to Altair
|
|
when newKind >= LightClientDataFork.Altair:
|
|
if x.kind == LightClientDataFork.None:
|
|
x = ForkedLightClientFinalityUpdate(
|
|
kind: LightClientDataFork.Altair)
|
|
|
|
# Upgrade to Capella
|
|
when newKind >= LightClientDataFork.Capella:
|
|
if x.kind == LightClientDataFork.Altair:
|
|
x = ForkedLightClientFinalityUpdate(
|
|
kind: LightClientDataFork.Capella,
|
|
capellaData: upgrade_lc_finality_update_to_capella(
|
|
x.forky(LightClientDataFork.Altair)))
|
|
|
|
# Upgrade to Deneb
|
|
when newKind >= LightClientDataFork.Deneb:
|
|
if x.kind == LightClientDataFork.Capella:
|
|
x = ForkedLightClientFinalityUpdate(
|
|
kind: LightClientDataFork.Deneb,
|
|
denebData: upgrade_lc_finality_update_to_deneb(
|
|
x.forky(LightClientDataFork.Capella)))
|
|
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
doAssert x.kind == newKind
|
|
|
|
func migrateToDataFork*(
|
|
x: var ForkedLightClientOptimisticUpdate,
|
|
newKind: static LightClientDataFork) =
|
|
if newKind == x.kind:
|
|
# Already at correct kind
|
|
discard
|
|
elif newKind < x.kind:
|
|
# Downgrade not supported, re-initialize
|
|
x = ForkedLightClientOptimisticUpdate(kind: newKind)
|
|
else:
|
|
# Upgrade to Altair
|
|
when newKind >= LightClientDataFork.Altair:
|
|
if x.kind == LightClientDataFork.None:
|
|
x = ForkedLightClientOptimisticUpdate(
|
|
kind: LightClientDataFork.Altair)
|
|
|
|
# Upgrade to Capella
|
|
when newKind >= LightClientDataFork.Capella:
|
|
if x.kind == LightClientDataFork.Altair:
|
|
x = ForkedLightClientOptimisticUpdate(
|
|
kind: LightClientDataFork.Capella,
|
|
capellaData: upgrade_lc_optimistic_update_to_capella(
|
|
x.forky(LightClientDataFork.Altair)))
|
|
|
|
# Upgrade to Deneb
|
|
when newKind >= LightClientDataFork.Deneb:
|
|
if x.kind == LightClientDataFork.Capella:
|
|
x = ForkedLightClientOptimisticUpdate(
|
|
kind: LightClientDataFork.Deneb,
|
|
denebData: upgrade_lc_optimistic_update_to_deneb(
|
|
x.forky(LightClientDataFork.Capella)))
|
|
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
doAssert x.kind == newKind
|
|
|
|
func migrateToDataFork*(
|
|
x: var ForkedLightClientStore,
|
|
newKind: static LightClientDataFork) =
|
|
if newKind == x.kind:
|
|
# Already at correct kind
|
|
discard
|
|
elif newKind < x.kind:
|
|
# Downgrade not supported, re-initialize
|
|
x = ForkedLightClientStore(kind: newKind)
|
|
else:
|
|
# Upgrade to Altair
|
|
when newKind >= LightClientDataFork.Altair:
|
|
if x.kind == LightClientDataFork.None:
|
|
x = ForkedLightClientStore(
|
|
kind: LightClientDataFork.Altair)
|
|
|
|
# Upgrade to Capella
|
|
when newKind >= LightClientDataFork.Capella:
|
|
if x.kind == LightClientDataFork.Altair:
|
|
x = ForkedLightClientStore(
|
|
kind: LightClientDataFork.Capella,
|
|
capellaData: upgrade_lc_store_to_capella(
|
|
x.forky(LightClientDataFork.Altair)))
|
|
|
|
# Upgrade to Deneb
|
|
when newKind >= LightClientDataFork.Deneb:
|
|
if x.kind == LightClientDataFork.Capella:
|
|
x = ForkedLightClientStore(
|
|
kind: LightClientDataFork.Deneb,
|
|
denebData: upgrade_lc_store_to_deneb(
|
|
x.forky(LightClientDataFork.Capella)))
|
|
|
|
static: doAssert LightClientDataFork.high == LightClientDataFork.Deneb
|
|
doAssert x.kind == newKind
|
|
|
|
func migratingToDataFork*[
|
|
T:
|
|
ForkedLightClientHeader |
|
|
SomeForkedLightClientObject |
|
|
ForkedLightClientStore](
|
|
x: T, newKind: static LightClientDataFork): T =
|
|
var upgradedObject = x
|
|
upgradedObject.migrateToDataFork(newKind)
|
|
upgradedObject
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/light-client/full-node.md#block_to_light_client_header
|
|
func toAltairLightClientHeader(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
phase0.SignedBeaconBlock | phase0.TrustedSignedBeaconBlock |
|
|
altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
|
bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock
|
|
): altair.LightClientHeader =
|
|
altair.LightClientHeader(
|
|
beacon: blck.message.toBeaconBlockHeader())
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/capella/light-client/full-node.md#modified-block_to_light_client_header
|
|
func toCapellaLightClientHeader(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
phase0.SignedBeaconBlock | phase0.TrustedSignedBeaconBlock |
|
|
altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
|
bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock
|
|
): capella.LightClientHeader =
|
|
# Note that during fork transitions, `finalized_header` may still
|
|
# point to earlier forks. While Bellatrix blocks also contain an
|
|
# `ExecutionPayload` (minus `withdrawals_root`), it was not included
|
|
# in the corresponding light client data. To ensure compatibility
|
|
# with legacy data going through `upgrade_lc_header_to_capella`,
|
|
# leave out execution data.
|
|
capella.LightClientHeader(
|
|
beacon: blck.message.toBeaconBlockHeader())
|
|
|
|
func toCapellaLightClientHeader(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
capella.SignedBeaconBlock | capella.TrustedSignedBeaconBlock
|
|
): capella.LightClientHeader =
|
|
template payload: untyped = blck.message.body.execution_payload
|
|
capella.LightClientHeader(
|
|
beacon: blck.message.toBeaconBlockHeader(),
|
|
execution: capella.ExecutionPayloadHeader(
|
|
parent_hash: payload.parent_hash,
|
|
fee_recipient: payload.fee_recipient,
|
|
state_root: payload.state_root,
|
|
receipts_root: payload.receipts_root,
|
|
logs_bloom: payload.logs_bloom,
|
|
prev_randao: payload.prev_randao,
|
|
block_number: payload.block_number,
|
|
gas_limit: payload.gas_limit,
|
|
gas_used: payload.gas_used,
|
|
timestamp: payload.timestamp,
|
|
extra_data: payload.extra_data,
|
|
base_fee_per_gas: payload.base_fee_per_gas,
|
|
block_hash: payload.block_hash,
|
|
transactions_root: hash_tree_root(payload.transactions),
|
|
withdrawals_root: hash_tree_root(payload.withdrawals)),
|
|
execution_branch: blck.message.body.build_proof(
|
|
capella.EXECUTION_PAYLOAD_INDEX).get)
|
|
|
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.0/specs/deneb/light-client/full-node.md#modified-block_to_light_client_header
|
|
func toDenebLightClientHeader(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
phase0.SignedBeaconBlock | phase0.TrustedSignedBeaconBlock |
|
|
altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
|
bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock
|
|
): deneb.LightClientHeader =
|
|
# Note that during fork transitions, `finalized_header` may still
|
|
# point to earlier forks. While Bellatrix blocks also contain an
|
|
# `ExecutionPayload` (minus `withdrawals_root`), it was not included
|
|
# in the corresponding light client data. To ensure compatibility
|
|
# with legacy data going through `upgrade_lc_header_to_capella`,
|
|
# leave out execution data.
|
|
deneb.LightClientHeader(
|
|
beacon: blck.message.toBeaconBlockHeader())
|
|
|
|
func toDenebLightClientHeader(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
capella.SignedBeaconBlock | capella.TrustedSignedBeaconBlock
|
|
): deneb.LightClientHeader =
|
|
template payload: untyped = blck.message.body.execution_payload
|
|
deneb.LightClientHeader(
|
|
beacon: blck.message.toBeaconBlockHeader(),
|
|
execution: deneb.ExecutionPayloadHeader(
|
|
parent_hash: payload.parent_hash,
|
|
fee_recipient: payload.fee_recipient,
|
|
state_root: payload.state_root,
|
|
receipts_root: payload.receipts_root,
|
|
logs_bloom: payload.logs_bloom,
|
|
prev_randao: payload.prev_randao,
|
|
block_number: payload.block_number,
|
|
gas_limit: payload.gas_limit,
|
|
gas_used: payload.gas_used,
|
|
timestamp: payload.timestamp,
|
|
extra_data: payload.extra_data,
|
|
base_fee_per_gas: payload.base_fee_per_gas,
|
|
block_hash: payload.block_hash,
|
|
transactions_root: hash_tree_root(payload.transactions),
|
|
withdrawals_root: hash_tree_root(payload.withdrawals)),
|
|
execution_branch: blck.message.body.build_proof(
|
|
capella.EXECUTION_PAYLOAD_INDEX).get)
|
|
|
|
func toDenebLightClientHeader(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
deneb.SignedBeaconBlock | deneb.TrustedSignedBeaconBlock
|
|
): deneb.LightClientHeader =
|
|
template payload: untyped = blck.message.body.execution_payload
|
|
deneb.LightClientHeader(
|
|
beacon: blck.message.toBeaconBlockHeader(),
|
|
execution: deneb.ExecutionPayloadHeader(
|
|
parent_hash: payload.parent_hash,
|
|
fee_recipient: payload.fee_recipient,
|
|
state_root: payload.state_root,
|
|
receipts_root: payload.receipts_root,
|
|
logs_bloom: payload.logs_bloom,
|
|
prev_randao: payload.prev_randao,
|
|
block_number: payload.block_number,
|
|
gas_limit: payload.gas_limit,
|
|
gas_used: payload.gas_used,
|
|
timestamp: payload.timestamp,
|
|
extra_data: payload.extra_data,
|
|
base_fee_per_gas: payload.base_fee_per_gas,
|
|
block_hash: payload.block_hash,
|
|
transactions_root: hash_tree_root(payload.transactions),
|
|
withdrawals_root: hash_tree_root(payload.withdrawals),
|
|
excess_blob_gas: payload.excess_blob_gas),
|
|
execution_branch: blck.message.body.build_proof(
|
|
capella.EXECUTION_PAYLOAD_INDEX).get)
|
|
|
|
func toLightClientHeader*(
|
|
blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6)
|
|
phase0.SignedBeaconBlock | phase0.TrustedSignedBeaconBlock |
|
|
altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
|
bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock |
|
|
capella.SignedBeaconBlock | capella.TrustedSignedBeaconBlock |
|
|
deneb.SignedBeaconBlock | deneb.TrustedSignedBeaconBlock,
|
|
kind: static LightClientDataFork): auto =
|
|
when kind == LightClientDataFork.Deneb:
|
|
blck.toDenebLightClientHeader()
|
|
elif kind == LightClientDataFork.Capella:
|
|
blck.toCapellaLightClientHeader()
|
|
elif kind == LightClientDataFork.Altair:
|
|
blck.toAltairLightClientHeader()
|
|
else:
|
|
static: raiseAssert "Unreachable"
|
|
|
|
import chronicles
|
|
|
|
func shortLog*[
|
|
T:
|
|
ForkedLightClientHeader |
|
|
SomeForkedLightClientObject |
|
|
ForkedLightClientStore](
|
|
x: T): auto =
|
|
type ResultType = object
|
|
case kind: LightClientDataFork
|
|
of LightClientDataFork.None:
|
|
discard
|
|
of LightClientDataFork.Altair:
|
|
altairData: typeof(x.altairData.shortLog())
|
|
of LightClientDataFork.Capella:
|
|
capellaData: typeof(x.capellaData.shortLog())
|
|
of LightClientDataFork.Deneb:
|
|
denebData: typeof(x.denebData.shortLog())
|
|
|
|
let xKind = x.kind # Nim 1.6.12: Using `kind: x.kind` inside case is broken
|
|
case xKind
|
|
of LightClientDataFork.Deneb:
|
|
ResultType(kind: xKind, denebData: x.denebData.shortLog())
|
|
of LightClientDataFork.Capella:
|
|
ResultType(kind: xKind, capellaData: x.capellaData.shortLog())
|
|
of LightClientDataFork.Altair:
|
|
ResultType(kind: xKind, altairData: x.altairData.shortLog())
|
|
of LightClientDataFork.None:
|
|
ResultType(kind: xKind)
|
|
|
|
chronicles.formatIt ForkedLightClientHeader: it.shortLog
|
|
chronicles.formatIt SomeForkedLightClientObject: it.shortLog
|
|
chronicles.formatIt ForkedLightClientStore: it.shortLog
|