initial Electra support skeleton (#5946)

This commit is contained in:
tersec 2024-02-24 13:44:15 +00:00 committed by GitHub
parent feec45ba76
commit d09bf3b587
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 792 additions and 158 deletions

View File

@ -508,7 +508,8 @@ proc new*(T: type BeaconChainDB,
kvStore db.openKvStore("altair_blocks").expectDb(), kvStore db.openKvStore("altair_blocks").expectDb(),
kvStore db.openKvStore("bellatrix_blocks").expectDb(), kvStore db.openKvStore("bellatrix_blocks").expectDb(),
kvStore db.openKvStore("capella_blocks").expectDb(), kvStore db.openKvStore("capella_blocks").expectDb(),
kvStore db.openKvStore("deneb_blocks").expectDb()] kvStore db.openKvStore("deneb_blocks").expectDb(),
kvStore db.openKvStore("electra_blocks").expectDb()]
stateRoots = kvStore db.openKvStore("state_roots", true).expectDb() stateRoots = kvStore db.openKvStore("state_roots", true).expectDb()
@ -517,7 +518,8 @@ proc new*(T: type BeaconChainDB,
kvStore db.openKvStore("altair_state_no_validators").expectDb(), kvStore db.openKvStore("altair_state_no_validators").expectDb(),
kvStore db.openKvStore("bellatrix_state_no_validators").expectDb(), kvStore db.openKvStore("bellatrix_state_no_validators").expectDb(),
kvStore db.openKvStore("capella_state_no_validator_pubkeys").expectDb(), kvStore db.openKvStore("capella_state_no_validator_pubkeys").expectDb(),
kvStore db.openKvStore("deneb_state_no_validator_pubkeys").expectDb()] kvStore db.openKvStore("deneb_state_no_validator_pubkeys").expectDb(),
kvStore db.openKvStore("electra_state_no_validator_pubkeys").expectDb()]
stateDiffs = kvStore db.openKvStore("state_diffs").expectDb() stateDiffs = kvStore db.openKvStore("state_diffs").expectDb()
summaries = kvStore db.openKvStore("beacon_block_summaries", true).expectDb() summaries = kvStore db.openKvStore("beacon_block_summaries", true).expectDb()
@ -789,7 +791,8 @@ proc putBlock*(
proc putBlock*( proc putBlock*(
db: BeaconChainDB, db: BeaconChainDB,
value: bellatrix.TrustedSignedBeaconBlock | value: bellatrix.TrustedSignedBeaconBlock |
capella.TrustedSignedBeaconBlock | deneb.TrustedSignedBeaconBlock) = capella.TrustedSignedBeaconBlock | deneb.TrustedSignedBeaconBlock |
electra.TrustedSignedBeaconBlock) =
db.withManyWrites: db.withManyWrites:
db.blocks[type(value).kind].putSZSSZ(value.root.data, value) db.blocks[type(value).kind].putSZSSZ(value.root.data, value)
db.putBeaconBlockSummary(value.root, value.message.toBeaconBlockSummary()) db.putBeaconBlockSummary(value.root, value.message.toBeaconBlockSummary())
@ -839,6 +842,10 @@ template toBeaconStateNoImmutableValidators(state: deneb.BeaconState):
DenebBeaconStateNoImmutableValidators = DenebBeaconStateNoImmutableValidators =
isomorphicCast[DenebBeaconStateNoImmutableValidators](state) isomorphicCast[DenebBeaconStateNoImmutableValidators](state)
template toBeaconStateNoImmutableValidators(state: electra.BeaconState):
ElectraBeaconStateNoImmutableValidators =
isomorphicCast[ElectraBeaconStateNoImmutableValidators](state)
proc putState*( proc putState*(
db: BeaconChainDB, key: Eth2Digest, db: BeaconChainDB, key: Eth2Digest,
value: phase0.BeaconState | altair.BeaconState) = value: phase0.BeaconState | altair.BeaconState) =
@ -848,7 +855,8 @@ proc putState*(
proc putState*( proc putState*(
db: BeaconChainDB, key: Eth2Digest, db: BeaconChainDB, key: Eth2Digest,
value: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState) = value: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState |
electra.BeaconState) =
db.updateImmutableValidators(value.validators.asSeq()) db.updateImmutableValidators(value.validators.asSeq())
db.statesNoVal[type(value).kind].putSZSSZ( db.statesNoVal[type(value).kind].putSZSSZ(
key.data, toBeaconStateNoImmutableValidators(value)) key.data, toBeaconStateNoImmutableValidators(value))
@ -976,7 +984,7 @@ proc getBlock*(
proc getBlock*[ proc getBlock*[
X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock | X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock |
deneb.TrustedSignedBeaconBlock]( deneb.TrustedSignedBeaconBlock | electra.TrustedSignedBeaconBlock](
db: BeaconChainDB, key: Eth2Digest, db: BeaconChainDB, key: Eth2Digest,
T: type X): Opt[T] = T: type X): Opt[T] =
# We only store blocks that we trust in the database # We only store blocks that we trust in the database
@ -1031,7 +1039,7 @@ proc getBlockSSZ*(
proc getBlockSSZ*[ proc getBlockSSZ*[
X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock | X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock |
deneb.TrustedSignedBeaconBlock]( deneb.TrustedSignedBeaconBlock | electra.TrustedSignedBeaconBlock](
db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], T: type X): bool = db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], T: type X): bool =
let dataPtr = addr data # Short-lived let dataPtr = addr data # Short-lived
var success = true var success = true
@ -1080,7 +1088,7 @@ proc getBlockSZ*(
proc getBlockSZ*[ proc getBlockSZ*[
X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock | X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock |
deneb.TrustedSignedBeaconBlock]( deneb.TrustedSignedBeaconBlock | electra.TrustedSignedBeaconBlock](
db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], T: type X): bool = db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], T: type X): bool =
let dataPtr = addr data # Short-lived let dataPtr = addr data # Short-lived
func decode(data: openArray[byte]) = func decode(data: openArray[byte]) =
@ -1178,7 +1186,8 @@ proc getStateOnlyMutableValidators(
proc getStateOnlyMutableValidators( proc getStateOnlyMutableValidators(
immutableValidators: openArray[ImmutableValidatorData2], immutableValidators: openArray[ImmutableValidatorData2],
store: KvStoreRef, key: openArray[byte], store: KvStoreRef, key: openArray[byte],
output: var (capella.BeaconState | deneb.BeaconState), output: var (capella.BeaconState | deneb.BeaconState |
electra.BeaconState),
rollback: RollbackProc): bool = rollback: RollbackProc): bool =
## Load state into `output` - BeaconState is large so we want to avoid ## Load state into `output` - BeaconState is large so we want to avoid
## re-allocating it if possible ## re-allocating it if possible
@ -1263,7 +1272,8 @@ proc getState*(
proc getState*( proc getState*(
db: BeaconChainDB, key: Eth2Digest, db: BeaconChainDB, key: Eth2Digest,
output: var (altair.BeaconState | bellatrix.BeaconState | output: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState), capella.BeaconState | deneb.BeaconState |
electra.BeaconState),
rollback: RollbackProc): bool = rollback: RollbackProc): bool =
## Load state into `output` - BeaconState is large so we want to avoid ## Load state into `output` - BeaconState is large so we want to avoid
## re-allocating it if possible ## re-allocating it if possible
@ -1483,7 +1493,7 @@ iterator getAncestorSummaries*(db: BeaconChainDB, root: Eth2Digest):
# Backwards compat for reading old databases, or those that for whatever # Backwards compat for reading old databases, or those that for whatever
# reason lost a summary along the way.. # reason lost a summary along the way..
static: doAssert ConsensusFork.high == ConsensusFork.Deneb static: doAssert ConsensusFork.high == ConsensusFork.Electra
while true: while true:
if db.v0.backend.getSnappySSZ( if db.v0.backend.getSnappySSZ(
subkey(BeaconBlockSummary, res.root), res.summary) == GetResult.found: subkey(BeaconBlockSummary, res.root), res.summary) == GetResult.found:
@ -1498,6 +1508,8 @@ iterator getAncestorSummaries*(db: BeaconChainDB, root: Eth2Digest):
res.summary = blck.get().message.toBeaconBlockSummary() res.summary = blck.get().message.toBeaconBlockSummary()
elif (let blck = db.getBlock(res.root, deneb.TrustedSignedBeaconBlock); blck.isSome()): elif (let blck = db.getBlock(res.root, deneb.TrustedSignedBeaconBlock); blck.isSome()):
res.summary = blck.get().message.toBeaconBlockSummary() res.summary = blck.get().message.toBeaconBlockSummary()
elif (let blck = db.getBlock(res.root, electra.TrustedSignedBeaconBlock); blck.isSome()):
res.summary = blck.get().message.toBeaconBlockSummary()
else: else:
break break

View File

@ -77,6 +77,8 @@ proc initLightClient*(
case node.dag.cfg.consensusForkAtEpoch( case node.dag.cfg.consensusForkAtEpoch(
forkyBlck.message.slot.epoch) forkyBlck.message.slot.epoch)
of ConsensusFork.Electra:
debugRaiseAssert "initLightClient"
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
callForkchoiceUpdated(PayloadAttributesV3) callForkchoiceUpdated(PayloadAttributesV3)
of ConsensusFork.Capella: of ConsensusFork.Capella:

View File

@ -483,7 +483,8 @@ func init(
func init( func init(
T: type AttestationCache, T: type AttestationCache,
state: altair.HashedBeaconState | bellatrix.HashedBeaconState | state: altair.HashedBeaconState | bellatrix.HashedBeaconState |
capella.HashedBeaconState | deneb.HashedBeaconState, capella.HashedBeaconState | deneb.HashedBeaconState |
electra.HashedBeaconState,
cache: var StateCache): T = cache: var StateCache): T =
# Load attestations that are scheduled for being given rewards for # Load attestations that are scheduled for being given rewards for
let let

View File

@ -69,7 +69,8 @@ func hasBlob*(
func popBlobs*( func popBlobs*(
quarantine: var BlobQuarantine, digest: Eth2Digest, quarantine: var BlobQuarantine, digest: Eth2Digest,
blck: deneb.SignedBeaconBlock): seq[ref BlobSidecar] = blck: deneb.SignedBeaconBlock | electra.SignedBeaconBlock):
seq[ref BlobSidecar] =
var r: seq[ref BlobSidecar] = @[] var r: seq[ref BlobSidecar] = @[]
for idx, kzg_commitment in blck.message.body.blob_kzg_commitments: for idx, kzg_commitment in blck.message.body.blob_kzg_commitments:
var b: ref BlobSidecar var b: ref BlobSidecar
@ -77,8 +78,9 @@ func popBlobs*(
r.add(b) r.add(b)
r r
func hasBlobs*(quarantine: BlobQuarantine, blck: deneb.SignedBeaconBlock): func hasBlobs*(
bool = quarantine: BlobQuarantine,
blck: deneb.SignedBeaconBlock | electra.SignedBeaconBlock): bool =
for idx, kzg_commitment in blck.message.body.blob_kzg_commitments: for idx, kzg_commitment in blck.message.body.blob_kzg_commitments:
if (blck.root, BlobIndex idx, kzg_commitment) notin quarantine.blobs: if (blck.root, BlobIndex idx, kzg_commitment) notin quarantine.blobs:
return false return false

View File

@ -73,7 +73,8 @@ func init*(
T: type BlockRef, root: Eth2Digest, executionValid: bool, T: type BlockRef, root: Eth2Digest, executionValid: bool,
blck: bellatrix.SomeBeaconBlock | bellatrix.TrustedBeaconBlock | blck: bellatrix.SomeBeaconBlock | bellatrix.TrustedBeaconBlock |
capella.SomeBeaconBlock | capella.TrustedBeaconBlock | capella.SomeBeaconBlock | capella.TrustedBeaconBlock |
deneb.SomeBeaconBlock | deneb.TrustedBeaconBlock): BlockRef = deneb.SomeBeaconBlock | deneb.TrustedBeaconBlock |
electra.SomeBeaconBlock | electra.TrustedBeaconBlock): BlockRef =
BlockRef.init( BlockRef.init(
root, Opt.some Eth2Digest(blck.body.execution_payload.block_hash), root, Opt.some Eth2Digest(blck.body.execution_payload.block_hash),
executionValid = executionValid =

View File

@ -293,10 +293,11 @@ type
OnBellatrixBlockAdded* = OnBlockAdded[bellatrix.TrustedSignedBeaconBlock] OnBellatrixBlockAdded* = OnBlockAdded[bellatrix.TrustedSignedBeaconBlock]
OnCapellaBlockAdded* = OnBlockAdded[capella.TrustedSignedBeaconBlock] OnCapellaBlockAdded* = OnBlockAdded[capella.TrustedSignedBeaconBlock]
OnDenebBlockAdded* = OnBlockAdded[deneb.TrustedSignedBeaconBlock] OnDenebBlockAdded* = OnBlockAdded[deneb.TrustedSignedBeaconBlock]
OnElectraBlockAdded* = OnBlockAdded[electra.TrustedSignedBeaconBlock]
OnForkyBlockAdded* = OnForkyBlockAdded* =
OnPhase0BlockAdded | OnAltairBlockAdded | OnBellatrixBlockAdded | OnPhase0BlockAdded | OnAltairBlockAdded | OnBellatrixBlockAdded |
OnCapellaBlockAdded | OnDenebBlockAdded OnCapellaBlockAdded | OnDenebBlockAdded | OnElectraBlockAdded
HeadChangeInfoObject* = object HeadChangeInfoObject* = object
slot*: Slot slot*: Slot
@ -328,7 +329,9 @@ type
optimistic* {.serializedFieldName: "execution_optimistic".}: Option[bool] optimistic* {.serializedFieldName: "execution_optimistic".}: Option[bool]
template OnBlockAddedCallback*(kind: static ConsensusFork): auto = template OnBlockAddedCallback*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[OnElectraBlockAdded]
elif kind == ConsensusFork.Deneb:
typedesc[OnDenebBlockAdded] typedesc[OnDenebBlockAdded]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[OnCapellaBlockAdded] typedesc[OnCapellaBlockAdded]

View File

@ -294,8 +294,7 @@ iterator pop*(quarantine: var Quarantine, root: Eth2Digest):
proc addBlobless*( proc addBlobless*(
quarantine: var Quarantine, finalizedSlot: Slot, quarantine: var Quarantine, finalizedSlot: Slot,
signedBlock: deneb.SignedBeaconBlock): bool = signedBlock: deneb.SignedBeaconBlock | electra.SignedBeaconBlock): bool =
if not isViable(finalizedSlot, signedBlock.message.slot): if not isViable(finalizedSlot, signedBlock.message.slot):
quarantine.addUnviable(signedBlock.root) quarantine.addUnviable(signedBlock.root)
return false return false
@ -306,8 +305,10 @@ proc addBlobless*(
return true return true
debug "block quarantine: Adding blobless", blck = shortLog(signedBlock) debug "block quarantine: Adding blobless", blck = shortLog(signedBlock)
quarantine.blobless[signedBlock.root] = signedBlock debugRaiseAssert "addBlobless; needs consideration how to handle deneb and electra"
quarantine.missing.del(signedBlock.root) when not (signedBlock is electra.SignedBeaconBlock):
quarantine.blobless[signedBlock.root] = signedBlock
quarantine.missing.del(signedBlock.root)
true true
func popBlobless*(quarantine: var Quarantine, root: Eth2Digest): func popBlobless*(quarantine: var Quarantine, root: Eth2Digest):

View File

@ -268,8 +268,11 @@ proc getForkedBlock*(db: BeaconChainDB, root: Eth2Digest):
Opt[ForkedTrustedSignedBeaconBlock] = Opt[ForkedTrustedSignedBeaconBlock] =
# When we only have a digest, we don't know which fork it's from so we try # When we only have a digest, we don't know which fork it's from so we try
# them one by one - this should be used sparingly # them one by one - this should be used sparingly
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb static: doAssert high(ConsensusFork) == ConsensusFork.Electra
if (let blck = db.getBlock(root, deneb.TrustedSignedBeaconBlock); if (let blck = db.getBlock(root, electra.TrustedSignedBeaconBlock);
blck.isSome()):
ok(ForkedTrustedSignedBeaconBlock.init(blck.get()))
elif (let blck = db.getBlock(root, deneb.TrustedSignedBeaconBlock);
blck.isSome()): blck.isSome()):
ok(ForkedTrustedSignedBeaconBlock.init(blck.get())) ok(ForkedTrustedSignedBeaconBlock.init(blck.get()))
elif (let blck = db.getBlock(root, capella.TrustedSignedBeaconBlock); elif (let blck = db.getBlock(root, capella.TrustedSignedBeaconBlock);
@ -1002,6 +1005,12 @@ proc applyBlock(
state_transition( state_transition(
dag.cfg, state, data, cache, info, dag.cfg, state, data, cache, info,
dag.updateFlags + {slotProcessed}, noRollback) dag.updateFlags + {slotProcessed}, noRollback)
of ConsensusFork.Electra:
let data = getBlock(dag, bid, electra.TrustedSignedBeaconBlock).valueOr:
return err("Block load failed")
state_transition(
dag.cfg, state, data, cache, info,
dag.updateFlags + {slotProcessed}, noRollback)
proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB, proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
validatorMonitor: ref ValidatorMonitor, updateFlags: UpdateFlags, validatorMonitor: ref ValidatorMonitor, updateFlags: UpdateFlags,
@ -1155,11 +1164,12 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
let let
configFork = case dag.headState.kind configFork = case dag.headState.kind
of ConsensusFork.Phase0: genesisFork(cfg) of ConsensusFork.Phase0: genesisFork(cfg)
of ConsensusFork.Altair: altairFork(cfg) of ConsensusFork.Altair: altairFork(cfg)
of ConsensusFork.Bellatrix: bellatrixFork(cfg) of ConsensusFork.Bellatrix: bellatrixFork(cfg)
of ConsensusFork.Capella: capellaFork(cfg) of ConsensusFork.Capella: capellaFork(cfg)
of ConsensusFork.Deneb: denebFork(cfg) of ConsensusFork.Deneb: denebFork(cfg)
of ConsensusFork.Electra: electraFork(cfg)
stateFork = getStateField(dag.headState, fork) stateFork = getStateField(dag.headState, fork)
# Here, we check only the `current_version` field because the spec # Here, we check only the `current_version` field because the spec
@ -2398,6 +2408,8 @@ proc updateHead*(
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
if dag.vanityLogs.onUpgradeToDeneb != nil: if dag.vanityLogs.onUpgradeToDeneb != nil:
dag.vanityLogs.onUpgradeToDeneb() dag.vanityLogs.onUpgradeToDeneb()
of ConsensusFork.Electra:
debugRaiseAssert "updateHead"
if dag.vanityLogs.onKnownBlsToExecutionChange != nil and if dag.vanityLogs.onKnownBlsToExecutionChange != nil and
checkBlsToExecutionChanges( checkBlsToExecutionChanges(

View File

@ -379,7 +379,16 @@ proc runProposalForkchoiceUpdated*(
payloadAttributes = some fcPayloadAttributes) payloadAttributes = some fcPayloadAttributes)
debug "Fork-choice updated for proposal", status debug "Fork-choice updated for proposal", status
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb static: doAssert high(ConsensusFork) == ConsensusFork.Electra
when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "runProposalForkchoiceUpdated, probably will be a new payload attributes type here"
callForkchoiceUpdated(PayloadAttributesV3(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData,
suggestedFeeRecipient: feeRecipient,
withdrawals:
toEngineWithdrawals get_expected_withdrawals(forkyState.data),
parentBeaconBlockRoot: beaconHead.blck.bid.root.asBlockHash))
when consensusFork >= ConsensusFork.Deneb: when consensusFork >= ConsensusFork.Deneb:
callForkchoiceUpdated(PayloadAttributesV3( callForkchoiceUpdated(PayloadAttributesV3(
timestamp: Quantity timestamp, timestamp: Quantity timestamp,

View File

@ -561,6 +561,32 @@ func asEngineExecutionPayload*(executionPayload: deneb.ExecutionPayload):
blobGasUsed: Quantity(executionPayload.blob_gas_used), blobGasUsed: Quantity(executionPayload.blob_gas_used),
excessBlobGas: Quantity(executionPayload.excess_blob_gas)) excessBlobGas: Quantity(executionPayload.excess_blob_gas))
func asEngineExecutionPayload*(executionPayload: electra.ExecutionPayload):
ExecutionPayloadV3 =
debugRaiseAssert "asEngineExecutionPayload for electra.ExecutionPayload probably won't use ExecutionPayloadV3"
template getTypedTransaction(tt: bellatrix.Transaction): TypedTransaction =
TypedTransaction(tt.distinctBase)
engine_api.ExecutionPayloadV3(
parentHash: executionPayload.parent_hash.asBlockHash,
feeRecipient: Address(executionPayload.fee_recipient.data),
stateRoot: executionPayload.state_root.asBlockHash,
receiptsRoot: executionPayload.receipts_root.asBlockHash,
logsBloom:
FixedBytes[BYTES_PER_LOGS_BLOOM](executionPayload.logs_bloom.data),
prevRandao: executionPayload.prev_randao.asBlockHash,
blockNumber: Quantity(executionPayload.block_number),
gasLimit: Quantity(executionPayload.gas_limit),
gasUsed: Quantity(executionPayload.gas_used),
timestamp: Quantity(executionPayload.timestamp),
extraData: DynamicBytes[0, MAX_EXTRA_DATA_BYTES](executionPayload.extra_data),
baseFeePerGas: executionPayload.base_fee_per_gas,
blockHash: executionPayload.block_hash.asBlockHash,
transactions: mapIt(executionPayload.transactions, it.getTypedTransaction),
withdrawals: mapIt(executionPayload.withdrawals, it.asEngineWithdrawal),
blobGasUsed: Quantity(executionPayload.blob_gas_used),
excessBlobGas: Quantity(executionPayload.excess_blob_gas))
func isConnected(connection: ELConnection): bool = func isConnected(connection: ELConnection): bool =
connection.web3.isSome connection.web3.isSome
@ -752,6 +778,10 @@ template EngineApiResponseType*(T: type capella.ExecutionPayloadForSigning): typ
template EngineApiResponseType*(T: type deneb.ExecutionPayloadForSigning): type = template EngineApiResponseType*(T: type deneb.ExecutionPayloadForSigning): type =
engine_api.GetPayloadV3Response engine_api.GetPayloadV3Response
template EngineApiResponseType*(T: type electra.ExecutionPayloadForSigning): type =
debugRaiseAssert "EngineApiResponseType electra.ExecutionPayloadForSigning; presumably will be a GetPayloadV4Response"
engine_api.GetPayloadV3Response
template toEngineWithdrawals*(withdrawals: seq[capella.Withdrawal]): seq[WithdrawalV1] = template toEngineWithdrawals*(withdrawals: seq[capella.Withdrawal]): seq[WithdrawalV1] =
mapIt(withdrawals, toEngineWithdrawal(it)) mapIt(withdrawals, toEngineWithdrawal(it))
@ -850,9 +880,15 @@ proc getPayload*(m: ELManager,
deadline.cancelSoon() deadline.cancelSoon()
if bestPayloadIdx.isSome: when PayloadType.kind != ConsensusFork.Electra:
return ok requests[bestPayloadIdx.get].value().asConsensusType if bestPayloadIdx.isSome:
return ok requests[bestPayloadIdx.get].value().asConsensusType
else:
return err()
else: else:
# right now, asConsensusType is confused by Deneb and Electra sharing a
# Payload type. this will probably be resolved in time naturally.
debugRaiseAssert "getPayload ForkyExecutionPayloadForSigning"
return err() return err()
proc waitELToSyncDeposits(connection: ELConnection, proc waitELToSyncDeposits(connection: ELConnection,

View File

@ -447,6 +447,8 @@ iterator getBlockIds*(
if not getPartialState( if not getPartialState(
db, historical_roots, historical_summaries, stateSlot, state[]): db, historical_roots, historical_summaries, stateSlot, state[]):
state = nil # No `return` in iterators state = nil # No `return` in iterators
of ConsensusFork.Electra:
debugRaiseAssert "getBlockIds"
if state == nil: if state == nil:
break break

View File

@ -328,7 +328,7 @@ proc newExecutionPayload*(
proc getExecutionValidity( proc getExecutionValidity(
elManager: ELManager, elManager: ELManager,
blck: bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock | blck: bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock |
deneb.SignedBeaconBlock): deneb.SignedBeaconBlock | electra.SignedBeaconBlock):
Future[NewPayloadStatus] {.async: (raises: [CancelledError]).} = Future[NewPayloadStatus] {.async: (raises: [CancelledError]).} =
if not blck.message.is_execution_block: if not blck.message.is_execution_block:
return NewPayloadStatus.valid # vacuously return NewPayloadStatus.valid # vacuously
@ -361,9 +361,10 @@ proc getExecutionValidity(
blck = shortLog(blck) blck = shortLog(blck)
return NewPayloadStatus.noResponse return NewPayloadStatus.noResponse
proc checkBloblessSignature(self: BlockProcessor, proc checkBloblessSignature(
signed_beacon_block: deneb.SignedBeaconBlock): self: BlockProcessor,
Result[void, cstring] = signed_beacon_block: deneb.SignedBeaconBlock | electra.SignedBeaconBlock):
Result[void, cstring] =
let dag = self.consensusManager.dag let dag = self.consensusManager.dag
let parent = dag.getBlockRef(signed_beacon_block.message.parent_root).valueOr: let parent = dag.getBlockRef(signed_beacon_block.message.parent_root).valueOr:
return err("checkBloblessSignature called with orphan block") return err("checkBloblessSignature called with orphan block")
@ -674,6 +675,9 @@ proc storeBlock(
template callForkChoiceUpdated: auto = template callForkChoiceUpdated: auto =
case self.consensusManager.dag.cfg.consensusForkAtEpoch( case self.consensusManager.dag.cfg.consensusForkAtEpoch(
newHead.get.blck.bid.slot.epoch) newHead.get.blck.bid.slot.epoch)
of ConsensusFork.Electra:
debugRaiseAssert "storeBlock, probably will become PayloadAttributesV3"
callExpectValidFCU(payloadAttributeType = PayloadAttributesV3)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
callExpectValidFCU(payloadAttributeType = PayloadAttributesV3) callExpectValidFCU(payloadAttributeType = PayloadAttributesV3)
of ConsensusFork.Capella: of ConsensusFork.Capella:

View File

@ -268,7 +268,8 @@ template validateBeaconBlockBellatrix(
signed_beacon_block: signed_beacon_block:
bellatrix.SignedBeaconBlock | bellatrix.SignedBeaconBlock |
capella.SignedBeaconBlock | capella.SignedBeaconBlock |
deneb.SignedBeaconBlock, deneb.SignedBeaconBlock |
electra.SignedBeaconBlock,
parent: BlockRef): untyped = parent: BlockRef): untyped =
# If the execution is enabled for the block -- i.e. # If the execution is enabled for the block -- i.e.
# is_execution_enabled(state, block.body) then validate the following: # is_execution_enabled(state, block.body) then validate the following:

View File

@ -830,7 +830,7 @@ template gossipMaxSize(T: untyped): uint32 =
when isFixedSize(T): when isFixedSize(T):
fixedPortionSize(T).uint32 fixedPortionSize(T).uint32
elif T is bellatrix.SignedBeaconBlock or T is capella.SignedBeaconBlock or elif T is bellatrix.SignedBeaconBlock or T is capella.SignedBeaconBlock or
T is deneb.SignedBeaconBlock: T is deneb.SignedBeaconBlock or T is electra.SignedBeaconBlock:
GOSSIP_MAX_SIZE GOSSIP_MAX_SIZE
# TODO https://github.com/status-im/nim-ssz-serialization/issues/20 for # TODO https://github.com/status-im/nim-ssz-serialization/issues/20 for
# Attestation, AttesterSlashing, and SignedAggregateAndProof, which all # Attestation, AttesterSlashing, and SignedAggregateAndProof, which all
@ -2637,6 +2637,12 @@ proc broadcastBeaconBlock*(
let topic = getBeaconBlocksTopic(node.forkDigests.deneb) let topic = getBeaconBlocksTopic(node.forkDigests.deneb)
node.broadcast(topic, blck) node.broadcast(topic, blck)
proc broadcastBeaconBlock*(
node: Eth2Node, blck: electra.SignedBeaconBlock):
Future[SendResult] {.async: (raises: [CancelledError], raw: true).} =
let topic = getBeaconBlocksTopic(node.forkDigests.electra)
node.broadcast(topic, blck)
proc broadcastBlobSidecar*( proc broadcastBlobSidecar*(
node: Eth2Node, subnet_id: BlobId, blob: deneb.BlobSidecar): node: Eth2Node, subnet_id: BlobId, blob: deneb.BlobSidecar):
Future[SendResult] {.async: (raises: [CancelledError], raw: true).} = Future[SendResult] {.async: (raises: [CancelledError], raw: true).} =

View File

@ -275,7 +275,8 @@ when const_preset == "gnosis":
doAssert network.cfg.BELLATRIX_FORK_EPOCH < FAR_FUTURE_EPOCH doAssert network.cfg.BELLATRIX_FORK_EPOCH < FAR_FUTURE_EPOCH
doAssert network.cfg.CAPELLA_FORK_EPOCH < FAR_FUTURE_EPOCH doAssert network.cfg.CAPELLA_FORK_EPOCH < FAR_FUTURE_EPOCH
doAssert network.cfg.DENEB_FORK_EPOCH < FAR_FUTURE_EPOCH doAssert network.cfg.DENEB_FORK_EPOCH < FAR_FUTURE_EPOCH
static: doAssert ConsensusFork.high == ConsensusFork.Deneb doAssert network.cfg.ELECTRA_FORK_EPOCH == FAR_FUTURE_EPOCH
static: doAssert ConsensusFork.high == ConsensusFork.Electra
elif const_preset == "mainnet": elif const_preset == "mainnet":
when incbinEnabled: when incbinEnabled:
@ -340,7 +341,8 @@ elif const_preset == "mainnet":
doAssert network.cfg.BELLATRIX_FORK_EPOCH < FAR_FUTURE_EPOCH doAssert network.cfg.BELLATRIX_FORK_EPOCH < FAR_FUTURE_EPOCH
doAssert network.cfg.CAPELLA_FORK_EPOCH < FAR_FUTURE_EPOCH doAssert network.cfg.CAPELLA_FORK_EPOCH < FAR_FUTURE_EPOCH
doAssert network.cfg.DENEB_FORK_EPOCH < FAR_FUTURE_EPOCH doAssert network.cfg.DENEB_FORK_EPOCH < FAR_FUTURE_EPOCH
static: doAssert ConsensusFork.high == ConsensusFork.Deneb doAssert network.cfg.ELECTRA_FORK_EPOCH == FAR_FUTURE_EPOCH
static: doAssert ConsensusFork.high == ConsensusFork.Electra
proc getMetadataForNetwork*(networkName: string): Eth2NetworkMetadata = proc getMetadataForNetwork*(networkName: string): Eth2NetworkMetadata =
template loadRuntimeMetadata(): auto = template loadRuntimeMetadata(): auto =

View File

@ -137,6 +137,9 @@ func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs =
func getVanityMascot(consensusFork: ConsensusFork): string = func getVanityMascot(consensusFork: ConsensusFork): string =
case consensusFork case consensusFork
of ConsensusFork.Electra:
debugRaiseAssert "getVanityMascot"
" "
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
"🐟" "🐟"
of ConsensusFork.Capella: of ConsensusFork.Capella:
@ -860,7 +863,8 @@ func forkDigests(node: BeaconNode): auto =
node.dag.forkDigests.altair, node.dag.forkDigests.altair,
node.dag.forkDigests.bellatrix, node.dag.forkDigests.bellatrix,
node.dag.forkDigests.capella, node.dag.forkDigests.capella,
node.dag.forkDigests.deneb] node.dag.forkDigests.deneb,
node.dag.forkDigests.electra]
forkDigestsArray forkDigestsArray
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/phase0/p2p-interface.md#attestation-subnet-subscription # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/phase0/p2p-interface.md#attestation-subnet-subscription
@ -1293,7 +1297,8 @@ proc updateGossipStatus(node: BeaconNode, slot: Slot) {.async.} =
removeAltairMessageHandlers, removeAltairMessageHandlers,
removeAltairMessageHandlers, # bellatrix (altair handlers, different forkDigest) removeAltairMessageHandlers, # bellatrix (altair handlers, different forkDigest)
removeCapellaMessageHandlers, removeCapellaMessageHandlers,
removeDenebMessageHandlers removeDenebMessageHandlers,
removeDenebMessageHandlers # Electra (Deneb handler, different forkDigest)
] ]
for gossipFork in oldGossipForks: for gossipFork in oldGossipForks:
@ -1304,7 +1309,8 @@ proc updateGossipStatus(node: BeaconNode, slot: Slot) {.async.} =
addAltairMessageHandlers, addAltairMessageHandlers,
addAltairMessageHandlers, # bellatrix (altair handlers, different forkDigest) addAltairMessageHandlers, # bellatrix (altair handlers, different forkDigest)
addCapellaMessageHandlers, addCapellaMessageHandlers,
addDenebMessageHandlers addDenebMessageHandlers,
addDenebMessageHandlers # Electra (Deneb handler, different forkDigest)
] ]
for gossipFork in newGossipForks: for gossipFork in newGossipForks:

View File

@ -237,6 +237,9 @@ proc installApiHandlers*(node: SigningNodeRef) =
(GeneralizedIndex(401), request.beaconBlockHeader.data) (GeneralizedIndex(401), request.beaconBlockHeader.data)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
(GeneralizedIndex(801), request.beaconBlockHeader.data) (GeneralizedIndex(801), request.beaconBlockHeader.data)
of ConsensusFork.Electra:
debugRaiseAssert "/api/v1/eth2/sign/{validator_key} TODO verify correctness"
(GeneralizedIndex(801), request.beaconBlockHeader.data)
if request.proofs.isNone() or len(request.proofs.get()) == 0: if request.proofs.isNone() or len(request.proofs.get()) == 0:
return errorResponse(Http400, MissingMerkleProofError) return errorResponse(Http400, MissingMerkleProofError)

View File

@ -929,6 +929,13 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
blck, Opt.some(blck.create_blob_sidecars( blck, Opt.some(blck.create_blob_sidecars(
restBlock.denebData.kzg_proofs, restBlock.denebData.blobs))) restBlock.denebData.kzg_proofs, restBlock.denebData.blobs)))
of ConsensusFork.Electra:
debugRaiseAssert "/eth/v1/beacon/blocks POST; can't reach here unless in Electra per check above, but this keeps return value consistent"
var blck = restBlock.denebData.signed_block
blck.root = hash_tree_root(blck.message)
await node.router.routeSignedBeaconBlock(
blck, Opt.some(blck.create_blob_sidecars(
restBlock.denebData.kzg_proofs, restBlock.denebData.blobs)))
if res.isErr(): if res.isErr():
return RestApiResponse.jsonError( return RestApiResponse.jsonError(
@ -1005,6 +1012,13 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
await node.router.routeSignedBeaconBlock( await node.router.routeSignedBeaconBlock(
blck, Opt.some(blck.create_blob_sidecars( blck, Opt.some(blck.create_blob_sidecars(
restBlock.denebData.kzg_proofs, restBlock.denebData.blobs))) restBlock.denebData.kzg_proofs, restBlock.denebData.blobs)))
of ConsensusFork.Electra:
debugRaiseAssert "electra missing; /eth/v2/beacon/blocks will only trigger this codepath when in Electra"
var blck = restBlock.denebData.signed_block
blck.root = hash_tree_root(blck.message)
await node.router.routeSignedBeaconBlock(
blck, Opt.some(blck.create_blob_sidecars(
restBlock.denebData.kzg_proofs, restBlock.denebData.blobs)))
if res.isErr(): if res.isErr():
return RestApiResponse.jsonError( return RestApiResponse.jsonError(
@ -1051,7 +1065,10 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
RestApiResponse.jsonError(Http500, InvalidAcceptError) RestApiResponse.jsonError(Http500, InvalidAcceptError)
withBlck(bdata.asSigned()): withBlck(bdata.asSigned()):
when consensusFork <= ConsensusFork.Altair: when consensusFork == ConsensusFork.Electra:
debugRaiseAssert "/eth/v1/beacon/blinded_block POST"
RestApiResponse.jsonError(Http500, "electra missing")
elif consensusFork <= ConsensusFork.Altair:
respondSszOrJson(forkyBlck, consensusFork) respondSszOrJson(forkyBlck, consensusFork)
else: else:
respondSszOrJson(toSignedBlindedBeaconBlock(forkyBlck), consensusFork) respondSszOrJson(toSignedBlindedBeaconBlock(forkyBlck), consensusFork)
@ -1082,7 +1099,11 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http400, BlockIncorrectFork) return RestApiResponse.jsonError(Http400, BlockIncorrectFork)
withConsensusFork(currentEpochFork): withConsensusFork(currentEpochFork):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "/eth/v1/beacon/blinded_blocks POST"
return RestApiResponse.jsonError(
Http400, $consensusFork & " builder API unsupported")
elif consensusFork >= ConsensusFork.Capella:
let let
restBlock = decodeBodyJsonOrSsz( restBlock = decodeBodyJsonOrSsz(
consensusFork.SignedBlindedBeaconBlock, body).valueOr: consensusFork.SignedBlindedBeaconBlock, body).valueOr:

View File

@ -408,7 +408,13 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return return
withBlck(message.blck): withBlck(message.blck):
let data = let data =
when consensusFork >= ConsensusFork.Deneb: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "/eth/v2/validator/blocks/{slot} GET"
let blobsBundle = message.blobsBundleOpt.get()
deneb.BlockContents(
kzg_proofs: blobsBundle.proofs,
blobs: blobsBundle.blobs)
elif consensusFork >= ConsensusFork.Deneb:
let blobsBundle = message.blobsBundleOpt.get() let blobsBundle = message.blobsBundleOpt.get()
deneb.BlockContents( deneb.BlockContents(
`block`: forkyBlck, `block`: forkyBlck,
@ -522,7 +528,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
contextFork = node.dag.cfg.consensusForkAtEpoch(node.currentSlot.epoch) contextFork = node.dag.cfg.consensusForkAtEpoch(node.currentSlot.epoch)
withConsensusFork(contextFork): withConsensusFork(contextFork):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "/eth/v1/validator/blinded_blocks/{slot} GET 1"
return RestApiResponse.jsonError(
Http400, "Electra builder API not yet supported")
elif consensusFork >= ConsensusFork.Capella:
let res = await makeBlindedBeaconBlockForHeadAndSlot[ let res = await makeBlindedBeaconBlockForHeadAndSlot[
consensusFork.BlindedBeaconBlock]( consensusFork.BlindedBeaconBlock](
node, payloadBuilderClient, qrandao, node, payloadBuilderClient, qrandao,
@ -541,7 +551,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
if res.isErr(): if res.isErr():
return RestApiResponse.jsonError(Http400, res.error()) return RestApiResponse.jsonError(Http400, res.error())
withBlck(res.get().blck): withBlck(res.get().blck):
return responseVersioned(forkyBlck, contextFork) when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "/eth/v1/validator/blinded_blocks/{slot} GET 2"
return RestApiResponse.jsonError(Http400, "")
else:
return responseVersioned(forkyBlck, contextFork)
func getMaybeBlindedHeaders( func getMaybeBlindedHeaders(
consensusFork: ConsensusFork, consensusFork: ConsensusFork,
@ -632,7 +646,10 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) =
return RestApiResponse.jsonError(Http400, InvalidRandaoRevealValue) return RestApiResponse.jsonError(Http400, InvalidRandaoRevealValue)
withConsensusFork(node.dag.cfg.consensusForkAtEpoch(qslot.epoch)): withConsensusFork(node.dag.cfg.consensusForkAtEpoch(qslot.epoch)):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "/eth/v3/validator/blocks/{slot} GET 1"
return RestApiResponse.jsonError(Http500, "")
elif consensusFork >= ConsensusFork.Capella:
let let
message = (await node.makeMaybeBlindedBeaconBlockForHeadAndSlot( message = (await node.makeMaybeBlindedBeaconBlockForHeadAndSlot(
consensusFork, qrandao, qgraffiti, qhead, qslot)).valueOr: consensusFork, qrandao, qgraffiti, qhead, qslot)).valueOr:

View File

@ -84,8 +84,8 @@ func get_validator_churn_limit*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/deneb/beacon-chain.md#new-get_validator_activation_churn_limit # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/deneb/beacon-chain.md#new-get_validator_activation_churn_limit
func get_validator_activation_churn_limit*( func get_validator_activation_churn_limit*(
cfg: RuntimeConfig, state: deneb.BeaconState, cache: var StateCache): cfg: RuntimeConfig, state: deneb.BeaconState | electra.BeaconState,
uint64 = cache: var StateCache): uint64 =
## Return the validator activation churn limit for the current epoch. ## Return the validator activation churn limit for the current epoch.
min( min(
cfg.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, cfg.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT,
@ -154,7 +154,7 @@ func get_slashing_penalty*(state: ForkyBeaconState,
elif state is altair.BeaconState: elif state is altair.BeaconState:
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR
elif state is bellatrix.BeaconState or state is capella.BeaconState or elif state is bellatrix.BeaconState or state is capella.BeaconState or
state is deneb.BeaconState: state is deneb.BeaconState or state is electra.BeaconState:
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX
else: else:
{.fatal: "invalid BeaconState type".} {.fatal: "invalid BeaconState type".}
@ -172,7 +172,8 @@ func get_proposer_reward(state: ForkyBeaconState, whistleblower_reward: Gwei): G
when state is phase0.BeaconState: when state is phase0.BeaconState:
whistleblower_reward div PROPOSER_REWARD_QUOTIENT whistleblower_reward div PROPOSER_REWARD_QUOTIENT
elif state is altair.BeaconState or state is bellatrix.BeaconState or elif state is altair.BeaconState or state is bellatrix.BeaconState or
state is capella.BeaconState or state is deneb.BeaconState: state is capella.BeaconState or state is deneb.BeaconState or
state is electra.BeaconState:
whistleblower_reward * PROPOSER_WEIGHT div WEIGHT_DENOMINATOR whistleblower_reward * PROPOSER_WEIGHT div WEIGHT_DENOMINATOR
else: else:
{.fatal: "invalid BeaconState type".} {.fatal: "invalid BeaconState type".}
@ -292,6 +293,20 @@ func get_initial_beacon_block*(state: deneb.HashedBeaconState):
deneb.TrustedSignedBeaconBlock( deneb.TrustedSignedBeaconBlock(
message: message, root: hash_tree_root(message)) message: message, root: hash_tree_root(message))
from ./datatypes/electra import HashedBeaconState, TrustedSignedBeaconBlock
# TODO spec link here when it exists
func get_initial_beacon_block*(state: electra.HashedBeaconState):
electra.TrustedSignedBeaconBlock =
# The genesis block is implicitly trusted
let message = electra.TrustedBeaconBlock(
slot: state.data.slot,
state_root: state.root)
# parent_root, randao_reveal, eth1_data, signature, and body automatically
# initialized to default values.
electra.TrustedSignedBeaconBlock(
message: message, root: hash_tree_root(message))
func get_initial_beacon_block*(state: ForkedHashedBeaconState): func get_initial_beacon_block*(state: ForkedHashedBeaconState):
ForkedTrustedSignedBeaconBlock = ForkedTrustedSignedBeaconBlock =
withState(state): withState(state):
@ -549,7 +564,7 @@ func get_attestation_participation_flag_indices(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/deneb/beacon-chain.md#modified-get_attestation_participation_flag_indices # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/deneb/beacon-chain.md#modified-get_attestation_participation_flag_indices
func get_attestation_participation_flag_indices( func get_attestation_participation_flag_indices(
state: deneb.BeaconState, state: deneb.BeaconState | electra.BeaconState,
data: AttestationData, inclusion_delay: uint64): set[TimelyFlag] = data: AttestationData, inclusion_delay: uint64): set[TimelyFlag] =
## Return the flag indices that are satisfied by an attestation. ## Return the flag indices that are satisfied by an attestation.
let justified_checkpoint = let justified_checkpoint =
@ -613,7 +628,7 @@ func get_base_reward_per_increment*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_base_reward # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_base_reward
func get_base_reward( func get_base_reward(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
index: ValidatorIndex, base_reward_per_increment: Gwei): Gwei = index: ValidatorIndex, base_reward_per_increment: Gwei): Gwei =
## Return the base reward for the validator defined by ``index`` with respect ## Return the base reward for the validator defined by ``index`` with respect
## to the current ``state``. ## to the current ``state``.
@ -658,7 +673,8 @@ proc check_attestation*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#new-process_bls_to_execution_change # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#new-process_bls_to_execution_change
proc check_bls_to_execution_change*( proc check_bls_to_execution_change*(
genesisFork: Fork, state: capella.BeaconState | deneb.BeaconState, genesisFork: Fork,
state: capella.BeaconState | deneb.BeaconState | electra.BeaconState,
signed_address_change: SignedBLSToExecutionChange, flags: UpdateFlags): signed_address_change: SignedBLSToExecutionChange, flags: UpdateFlags):
Result[void, cstring] = Result[void, cstring] =
let address_change = signed_address_change.message let address_change = signed_address_change.message
@ -746,7 +762,8 @@ proc process_attestation*(
else: else:
addPendingAttestation(state.previous_epoch_attestations) addPendingAttestation(state.previous_epoch_attestations)
elif state is altair.BeaconState or state is bellatrix.BeaconState or elif state is altair.BeaconState or state is bellatrix.BeaconState or
state is capella.BeaconState or state is deneb.BeaconState: state is capella.BeaconState or state is deneb.BeaconState or
state is electra.BeaconState:
template updateParticipationFlags(epoch_participation: untyped) = template updateParticipationFlags(epoch_participation: untyped) =
let proposer_reward = get_proposer_reward( let proposer_reward = get_proposer_reward(
state, attestation, base_reward_per_increment, cache, epoch_participation) state, attestation, base_reward_per_increment, cache, epoch_participation)
@ -765,7 +782,7 @@ proc process_attestation*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_next_sync_committee_indices # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_next_sync_committee_indices
func get_next_sync_committee_keys( func get_next_sync_committee_keys(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState): deneb.BeaconState | electra.BeaconState):
array[SYNC_COMMITTEE_SIZE, ValidatorPubKey] = array[SYNC_COMMITTEE_SIZE, ValidatorPubKey] =
## Return the sequence of sync committee indices, with possible duplicates, ## Return the sequence of sync committee indices, with possible duplicates,
## for the next sync committee. ## for the next sync committee.
@ -825,7 +842,8 @@ func is_partially_withdrawable_validator(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#new-get_expected_withdrawals # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#new-get_expected_withdrawals
func get_expected_withdrawals*( func get_expected_withdrawals*(
state: capella.BeaconState | deneb.BeaconState): seq[Withdrawal] = state: capella.BeaconState | deneb.BeaconState | electra.BeaconState):
seq[Withdrawal] =
let let
epoch = get_current_epoch(state) epoch = get_current_epoch(state)
num_validators = lenu64(state.validators) num_validators = lenu64(state.validators)
@ -862,7 +880,7 @@ func get_expected_withdrawals*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_next_sync_committee # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_next_sync_committee
func get_next_sync_committee*( func get_next_sync_committee*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState): deneb.BeaconState | electra.BeaconState):
SyncCommittee = SyncCommittee =
## Return the next sync committee, with possible pubkey duplicates. ## Return the next sync committee, with possible pubkey duplicates.
var res: SyncCommittee var res: SyncCommittee
@ -1436,7 +1454,7 @@ func latest_block_root*(state: ForkedHashedBeaconState): Eth2Digest =
func get_sync_committee_cache*( func get_sync_committee_cache*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
cache: var StateCache): SyncCommitteeCache = cache: var StateCache): SyncCommitteeCache =
let period = state.slot.sync_committee_period() let period = state.slot.sync_committee_period()

View File

@ -603,6 +603,7 @@ func kzg_commitment_inclusion_proof_gindex*(
# The first member (`randao_reveal`) is 16, subsequent members +1 each. # The first member (`randao_reveal`) is 16, subsequent members +1 each.
# If there are ever more than 16 members in `BeaconBlockBody`, indices change! # If there are ever more than 16 members in `BeaconBlockBody`, indices change!
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/ssz/merkle-proofs.md # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/ssz/merkle-proofs.md
debugRaiseAssert "kzg_commitment_inclusion_proof_gindex; ensure still applies to Electra after whatever changes happen"
const const
# blob_kzg_commitments # blob_kzg_commitments
BLOB_KZG_COMMITMENTS_GINDEX = BLOB_KZG_COMMITMENTS_GINDEX =

View File

@ -608,7 +608,9 @@ proc jsonResponseBlock*(t: typedesc[RestApiResponse],
writer.writeField("execution_optimistic", execOpt.get()) writer.writeField("execution_optimistic", execOpt.get())
writer.writeField("finalized", finalized) writer.writeField("finalized", finalized)
withBlck(data): withBlck(data):
writer.writeField("data", forkyBlck) debugRaiseAssert "jsonResponseBlock: ForkedSignedBeaconBlock"
when consensusFork != ConsensusFork.Electra:
writer.writeField("data", forkyBlck)
writer.endRecord() writer.endRecord()
stream.getOutput(seq[byte]) stream.getOutput(seq[byte])
except SerializationError: except SerializationError:
@ -633,7 +635,9 @@ proc jsonResponseState*(t: typedesc[RestApiResponse],
if execOpt.isSome(): if execOpt.isSome():
writer.writeField("execution_optimistic", execOpt.get()) writer.writeField("execution_optimistic", execOpt.get())
withState(data): withState(data):
writer.writeField("data", forkyState.data) debugRaiseAssert "jsonResponseBlock: ForkedHashedBeaconState"
when consensusFork != ConsensusFork.Electra:
writer.writeField("data", forkyState.data)
writer.endRecord() writer.endRecord()
stream.getOutput(seq[byte]) stream.getOutput(seq[byte])
except SerializationError: except SerializationError:
@ -1559,6 +1563,9 @@ proc readValue*[BlockType: ProduceBlockResponseV2](
reader.raiseUnexpectedValue("Incorrect deneb block format") reader.raiseUnexpectedValue("Incorrect deneb block format")
value = ProduceBlockResponseV2(kind: ConsensusFork.Deneb, value = ProduceBlockResponseV2(kind: ConsensusFork.Deneb,
denebData: res.get()) denebData: res.get())
of ConsensusFork.Electra:
debugRaiseAssert "readValue ProduceBlockResponseV2"
reader.raiseUnexpectedValue("Incorrect electra block format")
proc readValue*[BlockType: ForkedBlindedBeaconBlock]( proc readValue*[BlockType: ForkedBlindedBeaconBlock](
reader: var JsonReader[RestJson], reader: var JsonReader[RestJson],
@ -1625,6 +1632,9 @@ proc readValue*[BlockType: ForkedBlindedBeaconBlock](
exc.formatMsg("BlindedBlock") & "]") exc.formatMsg("BlindedBlock") & "]")
value = ForkedBlindedBeaconBlock(kind: ConsensusFork.Deneb, value = ForkedBlindedBeaconBlock(kind: ConsensusFork.Deneb,
denebData: res) denebData: res)
of ConsensusFork.Electra:
debugRaiseAssert "readValue ForkedBlindedBeaconBlock"
reader.raiseUnexpectedValue("Electra blinded block format unsupported")
proc readValue*[BlockType: Web3SignerForkedBeaconBlock]( proc readValue*[BlockType: Web3SignerForkedBeaconBlock](
reader: var JsonReader[RestJson], reader: var JsonReader[RestJson],
@ -1927,6 +1937,8 @@ proc readValue*(reader: var JsonReader[RestJson],
assign( assign(
value.denebBody.execution_payload.excess_blob_gas, value.denebBody.execution_payload.excess_blob_gas,
ep_src.excess_blob_gas.get()) ep_src.excess_blob_gas.get())
of ConsensusFork.Electra:
debugRaiseAssert "readValue"
## RestPublishedBeaconBlock ## RestPublishedBeaconBlock
proc readValue*(reader: var JsonReader[RestJson], proc readValue*(reader: var JsonReader[RestJson],
@ -2033,6 +2045,16 @@ proc readValue*(reader: var JsonReader[RestJson],
body: body.denebBody body: body.denebBody
) )
) )
of ConsensusFork.Electra:
ForkedBeaconBlock.init(
electra.BeaconBlock(
slot: slot.get(),
proposer_index: proposer_index.get(),
parent_root: parent_root.get(),
state_root: state_root.get(),
body: body.electraBody
)
)
) )
## RestPublishedSignedBeaconBlock ## RestPublishedSignedBeaconBlock
@ -2099,6 +2121,13 @@ proc readValue*(reader: var JsonReader[RestJson],
signature: signature.get() signature: signature.get()
) )
) )
of ConsensusFork.Electra:
ForkedSignedBeaconBlock.init(
electra.SignedBeaconBlock(
message: blck.electraData,
signature: signature.get()
)
)
) )
proc readValue*(reader: var JsonReader[RestJson], proc readValue*(reader: var JsonReader[RestJson],
@ -2156,6 +2185,8 @@ proc readValue*(reader: var JsonReader[RestJson],
reader.raiseUnexpectedValue("Incorrect signed_block format") reader.raiseUnexpectedValue("Incorrect signed_block format")
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
ForkedBeaconBlock.init(blck.denebData.message) ForkedBeaconBlock.init(blck.denebData.message)
of ConsensusFork.Electra:
ForkedBeaconBlock.init(blck.electraData.message)
)) ))
of "kzg_proofs": of "kzg_proofs":
if kzg_proofs.isSome(): if kzg_proofs.isSome():
@ -2243,6 +2274,16 @@ proc readValue*(reader: var JsonReader[RestJson],
blobs: blobs.get() blobs: blobs.get()
) )
) )
of ConsensusFork.Electra:
value = RestPublishedSignedBlockContents(
kind: ConsensusFork.Electra,
electraData: ElectraSignedBlockContents(
# Constructed to be internally consistent
signed_block: signed_message.get().distinctBase.electraData,
kzg_proofs: kzg_proofs.get(),
blobs: blobs.get()
)
)
## ForkedSignedBeaconBlock ## ForkedSignedBeaconBlock
proc readValue*(reader: var JsonReader[RestJson], proc readValue*(reader: var JsonReader[RestJson],
@ -2346,6 +2387,9 @@ proc readValue*(reader: var JsonReader[RestJson],
if res.isNone(): if res.isNone():
reader.raiseUnexpectedValue("Incorrect deneb block format") reader.raiseUnexpectedValue("Incorrect deneb block format")
value = ForkedSignedBeaconBlock.init(res.get()) value = ForkedSignedBeaconBlock.init(res.get())
of ConsensusFork.Electra:
debugRaiseAssert "readValue 3"
reader.raiseUnexpectedValue("Incorrect electra block format")
withBlck(value): withBlck(value):
forkyBlck.root = hash_tree_root(forkyBlck.message) forkyBlck.root = hash_tree_root(forkyBlck.message)
@ -2369,6 +2413,10 @@ proc writeValue*(
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
writer.writeField("version", "deneb") writer.writeField("version", "deneb")
writer.writeField("data", value.denebData) writer.writeField("data", value.denebData)
of ConsensusFork.Electra:
writer.writeField("version", "electra")
debugRaiseAssert "writeValue ForkedSignedBeaconBlock"
#writer.writeField("data", value.electraData)
writer.endRecord() writer.endRecord()
# ForkedHashedBeaconState is used where a `ForkedBeaconState` normally would # ForkedHashedBeaconState is used where a `ForkedBeaconState` normally would
@ -2472,6 +2520,9 @@ proc readValue*(reader: var JsonReader[RestJson],
except SerializationError: except SerializationError:
reader.raiseUnexpectedValue("Incorrect deneb beacon state format") reader.raiseUnexpectedValue("Incorrect deneb beacon state format")
toValue(denebData) toValue(denebData)
of ConsensusFork.Electra:
debugRaiseAssert "readValue ForkedHashedBeaconState"
reader.raiseUnexpectedValue("Incorrect electra beacon state format")
proc writeValue*( proc writeValue*(
writer: var JsonWriter[RestJson], value: ForkedHashedBeaconState writer: var JsonWriter[RestJson], value: ForkedHashedBeaconState
@ -2493,6 +2544,10 @@ proc writeValue*(
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
writer.writeField("version", "deneb") writer.writeField("version", "deneb")
writer.writeField("data", value.denebData.data) writer.writeField("data", value.denebData.data)
of ConsensusFork.Electra:
writer.writeField("version", "electra")
debugRaiseAssert "writeValue ForkedHashedBeaconState"
#writer.writeField("data", value.electraData.data)
writer.endRecord() writer.endRecord()
## SomeForkedLightClientObject ## SomeForkedLightClientObject
@ -3405,18 +3460,20 @@ proc writeValue*(writer: var JsonWriter[RestJson],
value: ProduceBlockResponseV3) {.raises: [IOError].} = value: ProduceBlockResponseV3) {.raises: [IOError].} =
writer.beginRecord() writer.beginRecord()
withForkyMaybeBlindedBlck(value): withForkyMaybeBlindedBlck(value):
writer.writeField("version", consensusFork.toString()) debugRaiseAssert "writeValue ProduceBlockResponseV3"
when isBlinded: when consensusFork != ConsensusFork.Electra:
writer.writeField("execution_payload_blinded", "true") writer.writeField("version", consensusFork.toString())
else: when isBlinded:
writer.writeField("execution_payload_blinded", "false") writer.writeField("execution_payload_blinded", "true")
if value.executionValue.isSome(): else:
writer.writeField("execution_payload_value", writer.writeField("execution_payload_blinded", "false")
$(value.executionValue.get())) if value.executionValue.isSome():
if value.consensusValue.isSome(): writer.writeField("execution_payload_value",
writer.writeField("consensus_block_value", $(value.executionValue.get()))
$(value.consensusValue.get())) if value.consensusValue.isSome():
writer.writeField("data", forkyMaybeBlindedBlck) writer.writeField("consensus_block_value",
$(value.consensusValue.get()))
writer.writeField("data", forkyMaybeBlindedBlck)
writer.endRecord() writer.endRecord()
proc readValue*(reader: var JsonReader[RestJson], proc readValue*(reader: var JsonReader[RestJson],
@ -3442,7 +3499,9 @@ proc readValue*(reader: var JsonReader[RestJson],
reader.raiseUnexpectedValue("Field `data` is missing") reader.raiseUnexpectedValue("Field `data` is missing")
withConsensusFork(version.get): withConsensusFork(version.get):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "readValue ProduceBlockResponseV3"
elif consensusFork >= ConsensusFork.Capella:
if blinded.get: if blinded.get:
value = ForkedMaybeBlindedBeaconBlock.init( value = ForkedMaybeBlindedBeaconBlock.init(
RestJson.decode( RestJson.decode(
@ -3560,6 +3619,10 @@ proc decodeBody*(
return err(RestErrorMessage.init(Http400, UnexpectedDecodeError, return err(RestErrorMessage.init(Http400, UnexpectedDecodeError,
[version, $exc.msg])) [version, $exc.msg]))
ok(RestPublishedSignedBeaconBlock(ForkedSignedBeaconBlock.init(blck))) ok(RestPublishedSignedBeaconBlock(ForkedSignedBeaconBlock.init(blck)))
of ConsensusFork.Electra:
debugRaiseAssert "decodeBody RestPublishedSignedBeaconBlock"
return err(RestErrorMessage.init(Http400, UnexpectedDecodeError,
[version]))
else: else:
err(RestErrorMessage.init(Http415, "Invalid content type", err(RestErrorMessage.init(Http415, "Invalid content type",
[version, $body.contentType])) [version, $body.contentType]))
@ -3650,6 +3713,10 @@ proc decodeBody*(
[version, $exc.msg])) [version, $exc.msg]))
ok(RestPublishedSignedBlockContents( ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Deneb, denebData: blckContents)) kind: ConsensusFork.Deneb, denebData: blckContents))
of ConsensusFork.Electra:
debugRaiseAssert "decodeBody RestPublishedSignedBlockContents"
return err(RestErrorMessage.init(
Http400, "electra missing", [version]))
else: else:
err(RestErrorMessage.init(Http415, "Invalid content type", err(RestErrorMessage.init(Http415, "Invalid content type",
[version, $body.contentType])) [version, $body.contentType]))
@ -3779,6 +3846,11 @@ proc decodeBodyJsonOrSsz*(
[version, $exc.msg])) [version, $exc.msg]))
ok(RestPublishedSignedBlockContents( ok(RestPublishedSignedBlockContents(
kind: ConsensusFork.Deneb, denebData: blckContents)) kind: ConsensusFork.Deneb, denebData: blckContents))
of ConsensusFork.Electra:
debugRaiseAssert "decodeBodyJsonOrSsz RestPublishedSignedBlockContents"
return err(
RestErrorMessage.init(Http400, "electra missing",
[version]))
else: else:
err(RestErrorMessage.init(Http415, "Invalid content type", err(RestErrorMessage.init(Http415, "Invalid content type",
[version, $body.contentType])) [version, $body.contentType]))
@ -3922,6 +3994,9 @@ proc decodeBytes*[T: DecodeConsensysTypes](
let fork = ConsensusFork.decodeString(consensusVersion).valueOr: let fork = ConsensusFork.decodeString(consensusVersion).valueOr:
return err("Invalid or Unsupported consensus version") return err("Invalid or Unsupported consensus version")
case fork case fork
of ConsensusFork.Electra:
debugRaiseAssert "decodeBytes, DecodeConsensysTypes"
return err("Invalid or Unsupported consensus version")
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
let blckContents = ? readSszResBytes(deneb.BlockContents, value) let blckContents = ? readSszResBytes(deneb.BlockContents, value)
ok(ProduceBlockResponseV2(kind: ConsensusFork.Deneb, ok(ProduceBlockResponseV2(kind: ConsensusFork.Deneb,
@ -3946,6 +4021,9 @@ proc decodeBytes*[T: DecodeConsensysTypes](
let fork = ConsensusFork.decodeString(consensusVersion).valueOr: let fork = ConsensusFork.decodeString(consensusVersion).valueOr:
return err("Invalid or Unsupported consensus version") return err("Invalid or Unsupported consensus version")
case fork case fork
of ConsensusFork.Electra:
debugRaiseAssert "decodeBytes DecodeConsensysTypes"
err("Unable to decode blinded block for Electra fork")
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
let let
blck = ? readSszResBytes(deneb_mev.BlindedBeaconBlock, value) blck = ? readSszResBytes(deneb_mev.BlindedBeaconBlock, value)
@ -4018,7 +4096,10 @@ proc decodeBytes*[T: ProduceBlockResponseV3](
except ValueError: except ValueError:
return err("Incorrect `Eth-Consensus-Block-Value` header value") return err("Incorrect `Eth-Consensus-Block-Value` header value")
withConsensusFork(fork): withConsensusFork(fork):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "decodeBytes ProduceBlockV3"
return err("decodeBytes ProduceBlockV3")
elif consensusFork >= ConsensusFork.Capella:
if blinded: if blinded:
let contents = let contents =
? readSszResBytes(consensusFork.BlindedBlockContents, value) ? readSszResBytes(consensusFork.BlindedBlockContents, value)

View File

@ -17,7 +17,7 @@ import
std/[json, tables], std/[json, tables],
stew/base10, web3/primitives, httputils, stew/base10, web3/primitives, httputils,
".."/forks, ".."/forks,
".."/datatypes/[phase0, altair, bellatrix, deneb], ".."/datatypes/[phase0, altair, bellatrix, deneb, electra],
".."/mev/[capella_mev, deneb_mev] ".."/mev/[capella_mev, deneb_mev]
from ".."/datatypes/capella import BeaconBlockBody from ".."/datatypes/capella import BeaconBlockBody
@ -331,6 +331,11 @@ type
kzg_proofs*: deneb.KzgProofs kzg_proofs*: deneb.KzgProofs
blobs*: deneb.Blobs blobs*: deneb.Blobs
ElectraSignedBlockContents* = object
signed_block*: electra.SignedBeaconBlock
kzg_proofs*: deneb.KzgProofs
blobs*: deneb.Blobs
RestPublishedSignedBlockContents* = object RestPublishedSignedBlockContents* = object
case kind*: ConsensusFork case kind*: ConsensusFork
of ConsensusFork.Phase0: phase0Data*: phase0.SignedBeaconBlock of ConsensusFork.Phase0: phase0Data*: phase0.SignedBeaconBlock
@ -338,6 +343,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.SignedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.SignedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella.SignedBeaconBlock of ConsensusFork.Capella: capellaData*: capella.SignedBeaconBlock
of ConsensusFork.Deneb: denebData*: DenebSignedBlockContents of ConsensusFork.Deneb: denebData*: DenebSignedBlockContents
of ConsensusFork.Electra: electraData*: ElectraSignedBlockContents
RestPublishedBeaconBlock* = distinct ForkedBeaconBlock RestPublishedBeaconBlock* = distinct ForkedBeaconBlock
@ -348,6 +354,7 @@ type
of ConsensusFork.Bellatrix: bellatrixBody*: bellatrix.BeaconBlockBody of ConsensusFork.Bellatrix: bellatrixBody*: bellatrix.BeaconBlockBody
of ConsensusFork.Capella: capellaBody*: capella.BeaconBlockBody of ConsensusFork.Capella: capellaBody*: capella.BeaconBlockBody
of ConsensusFork.Deneb: denebBody*: deneb.BeaconBlockBody of ConsensusFork.Deneb: denebBody*: deneb.BeaconBlockBody
of ConsensusFork.Electra: electraBody*: electra.BeaconBlockBody
ProduceBlockResponseV2* = object ProduceBlockResponseV2* = object
case kind*: ConsensusFork case kind*: ConsensusFork
@ -356,6 +363,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.BeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.BeaconBlock
of ConsensusFork.Capella: capellaData*: capella.BeaconBlock of ConsensusFork.Capella: capellaData*: capella.BeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.BlockContents of ConsensusFork.Deneb: denebData*: deneb.BlockContents
of ConsensusFork.Electra: electraData*: electra.BlockContents
ProduceBlockResponseV3* = ForkedMaybeBlindedBeaconBlock ProduceBlockResponseV3* = ForkedMaybeBlindedBeaconBlock
@ -632,6 +640,8 @@ func init*(T: type ForkedSignedBeaconBlock,
ForkedSignedBeaconBlock.init(contents.capellaData) ForkedSignedBeaconBlock.init(contents.capellaData)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
ForkedSignedBeaconBlock.init(contents.denebData.signed_block) ForkedSignedBeaconBlock.init(contents.denebData.signed_block)
of ConsensusFork.Electra:
ForkedSignedBeaconBlock.init(contents.electraData.signed_block)
func init*(t: typedesc[RestPublishedSignedBlockContents], func init*(t: typedesc[RestPublishedSignedBlockContents],
blck: phase0.BeaconBlock, root: Eth2Digest, blck: phase0.BeaconBlock, root: Eth2Digest,
@ -689,6 +699,12 @@ func init*(t: typedesc[RestPublishedSignedBlockContents],
) )
) )
func init*(t: typedesc[RestPublishedSignedBlockContents],
contents: electra.BeaconBlock, root: Eth2Digest,
signature: ValidatorSig): RestPublishedSignedBlockContents =
debugRaiseAssert "init*(t: typedesc[RestPublishedSignedBlockContents],"
default(RestPublishedSignedBlockContents)
func init*(t: typedesc[StateIdent], v: StateIdentType): StateIdent = func init*(t: typedesc[StateIdent], v: StateIdentType): StateIdent =
StateIdent(kind: StateQueryKind.Named, value: v) StateIdent(kind: StateQueryKind.Named, value: v)
@ -1025,3 +1041,7 @@ template withBlck*(x: ProduceBlockResponseV2,
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
template blck: untyped {.inject.} = x.denebData.blck template blck: untyped {.inject.} = x.denebData.blck
body body
of ConsensusFork.Electra:
const consensusFork {.inject, used.} = ConsensusFork.Electra
template blck: untyped {.inject.} = x.electraData.blck
body

View File

@ -46,7 +46,8 @@ type
Altair, Altair,
Bellatrix, Bellatrix,
Capella, Capella,
Deneb Deneb,
Electra
ForkyBeaconState* = ForkyBeaconState* =
phase0.BeaconState | phase0.BeaconState |
@ -71,6 +72,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.HashedBeaconState of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.HashedBeaconState
of ConsensusFork.Capella: capellaData*: capella.HashedBeaconState of ConsensusFork.Capella: capellaData*: capella.HashedBeaconState
of ConsensusFork.Deneb: denebData*: deneb.HashedBeaconState of ConsensusFork.Deneb: denebData*: deneb.HashedBeaconState
of ConsensusFork.Electra: electraData*: electra.HashedBeaconState
ForkyExecutionPayload* = ForkyExecutionPayload* =
bellatrix.ExecutionPayload | bellatrix.ExecutionPayload |
@ -158,6 +160,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.BeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.BeaconBlock
of ConsensusFork.Capella: capellaData*: capella.BeaconBlock of ConsensusFork.Capella: capellaData*: capella.BeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.BeaconBlock of ConsensusFork.Deneb: denebData*: deneb.BeaconBlock
of ConsensusFork.Electra: electraData*: electra.BeaconBlock
ForkedMaybeBlindedBeaconBlock* = object ForkedMaybeBlindedBeaconBlock* = object
case kind*: ConsensusFork case kind*: ConsensusFork
@ -171,6 +174,8 @@ type
capellaData*: capella_mev.MaybeBlindedBeaconBlock capellaData*: capella_mev.MaybeBlindedBeaconBlock
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
denebData*: deneb_mev.MaybeBlindedBeaconBlock denebData*: deneb_mev.MaybeBlindedBeaconBlock
of ConsensusFork.Electra:
electraData*: electra.BeaconBlock
consensusValue*: Opt[UInt256] consensusValue*: Opt[UInt256]
executionValue*: Opt[UInt256] executionValue*: Opt[UInt256]
@ -185,6 +190,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix_mev.BlindedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix_mev.BlindedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella_mev.BlindedBeaconBlock of ConsensusFork.Capella: capellaData*: capella_mev.BlindedBeaconBlock
of ConsensusFork.Deneb: denebData*: deneb_mev.BlindedBeaconBlock of ConsensusFork.Deneb: denebData*: deneb_mev.BlindedBeaconBlock
of ConsensusFork.Electra: electraData*: electra.BeaconBlock
ForkedTrustedBeaconBlock* = object ForkedTrustedBeaconBlock* = object
case kind*: ConsensusFork case kind*: ConsensusFork
@ -193,6 +199,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.TrustedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.TrustedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella.TrustedBeaconBlock of ConsensusFork.Capella: capellaData*: capella.TrustedBeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.TrustedBeaconBlock of ConsensusFork.Deneb: denebData*: deneb.TrustedBeaconBlock
of ConsensusFork.Electra: electraData*: electra.TrustedBeaconBlock
ForkySignedBeaconBlock* = ForkySignedBeaconBlock* =
phase0.SignedBeaconBlock | phase0.SignedBeaconBlock |
@ -209,6 +216,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.SignedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.SignedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella.SignedBeaconBlock of ConsensusFork.Capella: capellaData*: capella.SignedBeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.SignedBeaconBlock of ConsensusFork.Deneb: denebData*: deneb.SignedBeaconBlock
of ConsensusFork.Electra: electraData*: electra.SignedBeaconBlock
ForkySignedBlindedBeaconBlock* = ForkySignedBlindedBeaconBlock* =
phase0.SignedBeaconBlock | phase0.SignedBeaconBlock |
@ -224,6 +232,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix_mev.SignedBlindedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix_mev.SignedBlindedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella_mev.SignedBlindedBeaconBlock of ConsensusFork.Capella: capellaData*: capella_mev.SignedBlindedBeaconBlock
of ConsensusFork.Deneb: denebData*: deneb_mev.SignedBlindedBeaconBlock of ConsensusFork.Deneb: denebData*: deneb_mev.SignedBlindedBeaconBlock
of ConsensusFork.Electra: electraData*: electra.SignedBeaconBlock
ForkySigVerifiedSignedBeaconBlock* = ForkySigVerifiedSignedBeaconBlock* =
phase0.SigVerifiedSignedBeaconBlock | phase0.SigVerifiedSignedBeaconBlock |
@ -256,6 +265,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.MsgTrustedSignedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.MsgTrustedSignedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella.MsgTrustedSignedBeaconBlock of ConsensusFork.Capella: capellaData*: capella.MsgTrustedSignedBeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.MsgTrustedSignedBeaconBlock of ConsensusFork.Deneb: denebData*: deneb.MsgTrustedSignedBeaconBlock
of ConsensusFork.Electra: electraData*: electra.MsgTrustedSignedBeaconBlock
ForkedTrustedSignedBeaconBlock* = object ForkedTrustedSignedBeaconBlock* = object
case kind*: ConsensusFork case kind*: ConsensusFork
@ -264,6 +274,7 @@ type
of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.TrustedSignedBeaconBlock of ConsensusFork.Bellatrix: bellatrixData*: bellatrix.TrustedSignedBeaconBlock
of ConsensusFork.Capella: capellaData*: capella.TrustedSignedBeaconBlock of ConsensusFork.Capella: capellaData*: capella.TrustedSignedBeaconBlock
of ConsensusFork.Deneb: denebData*: deneb.TrustedSignedBeaconBlock of ConsensusFork.Deneb: denebData*: deneb.TrustedSignedBeaconBlock
of ConsensusFork.Electra: electraData*: electra.TrustedSignedBeaconBlock
SomeForkySignedBeaconBlock* = SomeForkySignedBeaconBlock* =
ForkySignedBeaconBlock | ForkySignedBeaconBlock |
@ -377,8 +388,28 @@ template kind*(
deneb_mev.SignedBlindedBeaconBlock]): ConsensusFork = deneb_mev.SignedBlindedBeaconBlock]): ConsensusFork =
ConsensusFork.Deneb ConsensusFork.Deneb
template kind*(
x: typedesc[
electra.BeaconState |
electra.HashedBeaconState |
electra.ExecutionPayload |
electra.ExecutionPayloadForSigning |
electra.ExecutionPayloadHeader |
electra.BeaconBlock |
electra.SignedBeaconBlock |
electra.TrustedBeaconBlock |
electra.BeaconBlockBody |
electra.SigVerifiedBeaconBlockBody |
electra.TrustedBeaconBlockBody |
electra.SigVerifiedSignedBeaconBlock |
electra.MsgTrustedSignedBeaconBlock |
electra.TrustedSignedBeaconBlock]): ConsensusFork =
ConsensusFork.Electra
template BeaconState*(kind: static ConsensusFork): auto = template BeaconState*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[electra.BeaconState]
elif kind == ConsensusFork.Deneb:
typedesc[deneb.BeaconState] typedesc[deneb.BeaconState]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[capella.BeaconState] typedesc[capella.BeaconState]
@ -392,7 +423,9 @@ template BeaconState*(kind: static ConsensusFork): auto =
static: raiseAssert "Unreachable" static: raiseAssert "Unreachable"
template BeaconBlock*(kind: static ConsensusFork): auto = template BeaconBlock*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[electra.BeaconBlock]
elif kind == ConsensusFork.Deneb:
typedesc[deneb.BeaconBlock] typedesc[deneb.BeaconBlock]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[capella.BeaconBlock] typedesc[capella.BeaconBlock]
@ -406,7 +439,9 @@ template BeaconBlock*(kind: static ConsensusFork): auto =
static: raiseAssert "Unreachable" static: raiseAssert "Unreachable"
template BeaconBlockBody*(kind: static ConsensusFork): auto = template BeaconBlockBody*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[electra.BeaconBlockBody]
elif kind == ConsensusFork.Deneb:
typedesc[deneb.BeaconBlockBody] typedesc[deneb.BeaconBlockBody]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[capella.BeaconBlockBody] typedesc[capella.BeaconBlockBody]
@ -420,7 +455,9 @@ template BeaconBlockBody*(kind: static ConsensusFork): auto =
static: raiseAssert "Unreachable" static: raiseAssert "Unreachable"
template SignedBeaconBlock*(kind: static ConsensusFork): auto = template SignedBeaconBlock*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[electra.SignedBeaconBlock]
elif kind == ConsensusFork.Deneb:
typedesc[deneb.SignedBeaconBlock] typedesc[deneb.SignedBeaconBlock]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[capella.SignedBeaconBlock] typedesc[capella.SignedBeaconBlock]
@ -434,7 +471,9 @@ template SignedBeaconBlock*(kind: static ConsensusFork): auto =
static: raiseAssert "Unreachable" static: raiseAssert "Unreachable"
template TrustedSignedBeaconBlock*(kind: static ConsensusFork): auto = template TrustedSignedBeaconBlock*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[electra.TrustedSignedBeaconBlock]
elif kind == ConsensusFork.Deneb:
typedesc[deneb.TrustedSignedBeaconBlock] typedesc[deneb.TrustedSignedBeaconBlock]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[capella.TrustedSignedBeaconBlock] typedesc[capella.TrustedSignedBeaconBlock]
@ -448,7 +487,9 @@ template TrustedSignedBeaconBlock*(kind: static ConsensusFork): auto =
static: raiseAssert "Unreachable" static: raiseAssert "Unreachable"
template ExecutionPayloadForSigning*(kind: static ConsensusFork): auto = template ExecutionPayloadForSigning*(kind: static ConsensusFork): auto =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
typedesc[electra.ExecutionPayloadForSigning]
elif kind == ConsensusFork.Deneb:
typedesc[deneb.ExecutionPayloadForSigning] typedesc[deneb.ExecutionPayloadForSigning]
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
typedesc[capella.ExecutionPayloadForSigning] typedesc[capella.ExecutionPayloadForSigning]
@ -489,7 +530,10 @@ template SignedBlindedBeaconBlock*(kind: static ConsensusFork): auto =
template withAll*( template withAll*(
x: typedesc[ConsensusFork], body: untyped): untyped = x: typedesc[ConsensusFork], body: untyped): untyped =
static: doAssert ConsensusFork.high == ConsensusFork.Deneb static: doAssert ConsensusFork.high == ConsensusFork.Electra
block:
const consensusFork {.inject, used.} = ConsensusFork.Electra
body
block: block:
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
body body
@ -509,6 +553,9 @@ template withAll*(
template withConsensusFork*( template withConsensusFork*(
x: ConsensusFork, body: untyped): untyped = x: ConsensusFork, body: untyped): untyped =
case x case x
of ConsensusFork.Electra:
const consensusFork {.inject, used.} = ConsensusFork.Electra
body
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
body body
@ -567,8 +614,9 @@ template PayloadAttributes*(
{.error: "PayloadAttributes does not support " & $kind.} {.error: "PayloadAttributes does not support " & $kind.}
# `eth2_merkleization` cannot import `forks` (circular), so the check is here # `eth2_merkleization` cannot import `forks` (circular), so the check is here
static: doAssert ConsensusFork.high == ConsensusFork.Deneb, debugRaiseAssert "eth2_merkleization has been checked and `hash_tree_root` is up to date"
"eth2_merkleization has been checked and `hash_tree_root` is up to date" static: doAssert ConsensusFork.high == ConsensusFork.Electra,
"eth2_merkleization has been checked and `hash_tree_root` is up to date" # TODO
# TODO when https://github.com/nim-lang/Nim/issues/21086 fixed, use return type # TODO when https://github.com/nim-lang/Nim/issues/21086 fixed, use return type
# `ref T` # `ref T`
@ -592,6 +640,10 @@ func new*(T: type ForkedHashedBeaconState, data: deneb.BeaconState):
ref ForkedHashedBeaconState = ref ForkedHashedBeaconState =
(ref T)(kind: ConsensusFork.Deneb, denebData: deneb.HashedBeaconState( (ref T)(kind: ConsensusFork.Deneb, denebData: deneb.HashedBeaconState(
data: data, root: hash_tree_root(data))) data: data, root: hash_tree_root(data)))
func new*(T: type ForkedHashedBeaconState, data: electra.BeaconState):
ref ForkedHashedBeaconState =
(ref T)(kind: ConsensusFork.Electra, electraData: electra.HashedBeaconState(
data: data, root: hash_tree_root(data)))
template init*(T: type ForkedBeaconBlock, blck: phase0.BeaconBlock): T = template init*(T: type ForkedBeaconBlock, blck: phase0.BeaconBlock): T =
T(kind: ConsensusFork.Phase0, phase0Data: blck) T(kind: ConsensusFork.Phase0, phase0Data: blck)
@ -603,7 +655,10 @@ template init*(T: type ForkedBeaconBlock, blck: capella.BeaconBlock): T =
T(kind: ConsensusFork.Capella, capellaData: blck) T(kind: ConsensusFork.Capella, capellaData: blck)
template init*(T: type ForkedBeaconBlock, blck: deneb.BeaconBlock): T = template init*(T: type ForkedBeaconBlock, blck: deneb.BeaconBlock): T =
T(kind: ConsensusFork.Deneb, denebData: blck) T(kind: ConsensusFork.Deneb, denebData: blck)
template init*(T: type ForkedBeaconBlock, blck: electra.BeaconBlock): T =
T(kind: ConsensusFork.Electra, electraData: blck)
# TODO are these still used?
template init*(T: type ForkedTrustedBeaconBlock, blck: phase0.TrustedBeaconBlock): T = template init*(T: type ForkedTrustedBeaconBlock, blck: phase0.TrustedBeaconBlock): T =
T(kind: ConsensusFork.Phase0, phase0Data: blck) T(kind: ConsensusFork.Phase0, phase0Data: blck)
template init*(T: type ForkedTrustedBeaconBlock, blck: altair.TrustedBeaconBlock): T = template init*(T: type ForkedTrustedBeaconBlock, blck: altair.TrustedBeaconBlock): T =
@ -623,6 +678,8 @@ template init*(T: type ForkedSignedBeaconBlock, blck: capella.SignedBeaconBlock)
T(kind: ConsensusFork.Capella, capellaData: blck) T(kind: ConsensusFork.Capella, capellaData: blck)
template init*(T: type ForkedSignedBeaconBlock, blck: deneb.SignedBeaconBlock): T = template init*(T: type ForkedSignedBeaconBlock, blck: deneb.SignedBeaconBlock): T =
T(kind: ConsensusFork.Deneb, denebData: blck) T(kind: ConsensusFork.Deneb, denebData: blck)
template init*(T: type ForkedSignedBeaconBlock, blck: electra.SignedBeaconBlock): T =
T(kind: ConsensusFork.Electra, electraData: blck)
func init*(T: type ForkedSignedBeaconBlock, forked: ForkedBeaconBlock, func init*(T: type ForkedSignedBeaconBlock, forked: ForkedBeaconBlock,
blockRoot: Eth2Digest, signature: ValidatorSig): T = blockRoot: Eth2Digest, signature: ValidatorSig): T =
@ -652,6 +709,11 @@ func init*(T: type ForkedSignedBeaconBlock, forked: ForkedBeaconBlock,
denebData: deneb.SignedBeaconBlock(message: forked.denebData, denebData: deneb.SignedBeaconBlock(message: forked.denebData,
root: blockRoot, root: blockRoot,
signature: signature)) signature: signature))
of ConsensusFork.Electra:
T(kind: ConsensusFork.Electra,
electraData: electra.SignedBeaconBlock(message: forked.electraData,
root: blockRoot,
signature: signature))
func init*(T: type ForkedSignedBlindedBeaconBlock, func init*(T: type ForkedSignedBlindedBeaconBlock,
forked: ForkedBlindedBeaconBlock, blockRoot: Eth2Digest, forked: ForkedBlindedBeaconBlock, blockRoot: Eth2Digest,
@ -678,6 +740,9 @@ func init*(T: type ForkedSignedBlindedBeaconBlock,
T(kind: ConsensusFork.Deneb, T(kind: ConsensusFork.Deneb,
denebData: deneb_mev.SignedBlindedBeaconBlock(message: forked.denebData, denebData: deneb_mev.SignedBlindedBeaconBlock(message: forked.denebData,
signature: signature)) signature: signature))
of ConsensusFork.Electra:
debugRaiseAssert "init*(T: type ForkedSignedBlindedBeaconBlock"
T(kind: ConsensusFork.Electra)
template init*(T: type ForkedSignedBlindedBeaconBlock, template init*(T: type ForkedSignedBlindedBeaconBlock,
blck: capella_mev.BlindedBeaconBlock, blockRoot: Eth2Digest, blck: capella_mev.BlindedBeaconBlock, blockRoot: Eth2Digest,
@ -703,6 +768,8 @@ template init*(T: type ForkedMsgTrustedSignedBeaconBlock, blck: capella.MsgTrust
T(kind: ConsensusFork.Capella, capellaData: blck) T(kind: ConsensusFork.Capella, capellaData: blck)
template init*(T: type ForkedMsgTrustedSignedBeaconBlock, blck: deneb.MsgTrustedSignedBeaconBlock): T = template init*(T: type ForkedMsgTrustedSignedBeaconBlock, blck: deneb.MsgTrustedSignedBeaconBlock): T =
T(kind: ConsensusFork.Deneb, denebData: blck) T(kind: ConsensusFork.Deneb, denebData: blck)
template init*(T: type ForkedMsgTrustedSignedBeaconBlock, blck: electra.MsgTrustedSignedBeaconBlock): T =
T(kind: ConsensusFork.Electra, electraData: blck)
template init*(T: type ForkedTrustedSignedBeaconBlock, blck: phase0.TrustedSignedBeaconBlock): T = template init*(T: type ForkedTrustedSignedBeaconBlock, blck: phase0.TrustedSignedBeaconBlock): T =
T(kind: ConsensusFork.Phase0, phase0Data: blck) T(kind: ConsensusFork.Phase0, phase0Data: blck)
@ -714,6 +781,8 @@ template init*(T: type ForkedTrustedSignedBeaconBlock, blck: capella.TrustedSign
T(kind: ConsensusFork.Capella, capellaData: blck) T(kind: ConsensusFork.Capella, capellaData: blck)
template init*(T: type ForkedTrustedSignedBeaconBlock, blck: deneb.TrustedSignedBeaconBlock): T = template init*(T: type ForkedTrustedSignedBeaconBlock, blck: deneb.TrustedSignedBeaconBlock): T =
T(kind: ConsensusFork.Deneb, denebData: blck) T(kind: ConsensusFork.Deneb, denebData: blck)
template init*(T: type ForkedTrustedSignedBeaconBlock, blck: electra.TrustedSignedBeaconBlock): T =
T(kind: ConsensusFork.Electra, electraData: blck)
template toString*(kind: ConsensusFork): string = template toString*(kind: ConsensusFork): string =
case kind case kind
@ -727,9 +796,13 @@ template toString*(kind: ConsensusFork): string =
"capella" "capella"
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
"deneb" "deneb"
of ConsensusFork.Electra:
"electra"
template init*(T: typedesc[ConsensusFork], value: string): Opt[ConsensusFork] = template init*(T: typedesc[ConsensusFork], value: string): Opt[ConsensusFork] =
case value case value
of "electra":
Opt.some ConsensusFork.Electra
of "deneb": of "deneb":
Opt.some ConsensusFork.Deneb Opt.some ConsensusFork.Deneb
of "capella": of "capella":
@ -754,6 +827,10 @@ template init*(T: type ForkedEpochInfo, info: altair.EpochInfo): T =
template withState*(x: ForkedHashedBeaconState, body: untyped): untyped = template withState*(x: ForkedHashedBeaconState, body: untyped): untyped =
case x.kind case x.kind
of ConsensusFork.Electra:
const consensusFork {.inject, used.} = ConsensusFork.Electra
template forkyState: untyped {.inject, used.} = x.electraData
body
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
template forkyState: untyped {.inject, used.} = x.denebData template forkyState: untyped {.inject, used.} = x.denebData
@ -780,7 +857,9 @@ template forky*(
ForkedBeaconBlock | ForkedBeaconBlock |
ForkedHashedBeaconState, ForkedHashedBeaconState,
kind: static ConsensusFork): untyped = kind: static ConsensusFork): untyped =
when kind == ConsensusFork.Deneb: when kind == ConsensusFork.Electra:
x.electraData
elif kind == ConsensusFork.Deneb:
x.denebData x.denebData
elif kind == ConsensusFork.Capella: elif kind == ConsensusFork.Capella:
x.capellaData x.capellaData
@ -855,6 +934,8 @@ func setStateRoot*(x: var ForkedHashedBeaconState, root: Eth2Digest) =
func consensusForkEpoch*( func consensusForkEpoch*(
cfg: RuntimeConfig, consensusFork: ConsensusFork): Epoch = cfg: RuntimeConfig, consensusFork: ConsensusFork): Epoch =
case consensusFork case consensusFork
of ConsensusFork.Electra:
cfg.ELECTRA_FORK_EPOCH
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
cfg.DENEB_FORK_EPOCH cfg.DENEB_FORK_EPOCH
of ConsensusFork.Capella: of ConsensusFork.Capella:
@ -869,14 +950,16 @@ func consensusForkEpoch*(
func consensusForkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): ConsensusFork = func consensusForkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): ConsensusFork =
## Return the current fork for the given epoch. ## Return the current fork for the given epoch.
static: static:
doAssert high(ConsensusFork) == ConsensusFork.Deneb doAssert high(ConsensusFork) == ConsensusFork.Electra
doAssert ConsensusFork.Electra > ConsensusFork.Deneb
doAssert ConsensusFork.Deneb > ConsensusFork.Capella doAssert ConsensusFork.Deneb > ConsensusFork.Capella
doAssert ConsensusFork.Capella > ConsensusFork.Bellatrix doAssert ConsensusFork.Capella > ConsensusFork.Bellatrix
doAssert ConsensusFork.Bellatrix > ConsensusFork.Altair doAssert ConsensusFork.Bellatrix > ConsensusFork.Altair
doAssert ConsensusFork.Altair > ConsensusFork.Phase0 doAssert ConsensusFork.Altair > ConsensusFork.Phase0
doAssert GENESIS_EPOCH == 0 doAssert GENESIS_EPOCH == 0
if epoch >= cfg.DENEB_FORK_EPOCH: ConsensusFork.Deneb if epoch >= cfg.ELECTRA_FORK_EPOCH: ConsensusFork.Electra
elif epoch >= cfg.DENEB_FORK_EPOCH: ConsensusFork.Deneb
elif epoch >= cfg.CAPELLA_FORK_EPOCH: ConsensusFork.Capella elif epoch >= cfg.CAPELLA_FORK_EPOCH: ConsensusFork.Capella
elif epoch >= cfg.BELLATRIX_FORK_EPOCH: ConsensusFork.Bellatrix elif epoch >= cfg.BELLATRIX_FORK_EPOCH: ConsensusFork.Bellatrix
elif epoch >= cfg.ALTAIR_FORK_EPOCH: ConsensusFork.Altair elif epoch >= cfg.ALTAIR_FORK_EPOCH: ConsensusFork.Altair
@ -884,8 +967,10 @@ func consensusForkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): ConsensusFork =
func consensusForkForDigest*( func consensusForkForDigest*(
forkDigests: ForkDigests, forkDigest: ForkDigest): Opt[ConsensusFork] = forkDigests: ForkDigests, forkDigest: ForkDigest): Opt[ConsensusFork] =
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb static: doAssert high(ConsensusFork) == ConsensusFork.Electra
if forkDigest == forkDigests.deneb: if forkDigest == forkDigests.electra:
ok ConsensusFork.Electra
elif forkDigest == forkDigests.deneb:
ok ConsensusFork.Deneb ok ConsensusFork.Deneb
elif forkDigest == forkDigests.capella: elif forkDigest == forkDigests.capella:
ok ConsensusFork.Capella ok ConsensusFork.Capella
@ -901,6 +986,8 @@ func consensusForkForDigest*(
func atConsensusFork*( func atConsensusFork*(
forkDigests: ForkDigests, consensusFork: ConsensusFork): ForkDigest = forkDigests: ForkDigests, consensusFork: ConsensusFork): ForkDigest =
case consensusFork case consensusFork
of ConsensusFork.Electra:
forkDigests.electra
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
forkDigests.deneb forkDigests.deneb
of ConsensusFork.Capella: of ConsensusFork.Capella:
@ -979,6 +1066,10 @@ template withBlck*(
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
template forkyBlck: untyped {.inject, used.} = x.denebData template forkyBlck: untyped {.inject, used.} = x.denebData
body body
of ConsensusFork.Electra:
const consensusFork {.inject, used.} = ConsensusFork.Electra
template forkyBlck: untyped {.inject, used.} = x.electraData
body
func proposer_index*(x: ForkedBeaconBlock): uint64 = func proposer_index*(x: ForkedBeaconBlock): uint64 =
withBlck(x): forkyBlck.proposer_index withBlck(x): forkyBlck.proposer_index
@ -1002,7 +1093,8 @@ template getForkedBlockField*(
of ConsensusFork.Altair: unsafeAddr x.altairData.message.y of ConsensusFork.Altair: unsafeAddr x.altairData.message.y
of ConsensusFork.Bellatrix: unsafeAddr x.bellatrixData.message.y of ConsensusFork.Bellatrix: unsafeAddr x.bellatrixData.message.y
of ConsensusFork.Capella: unsafeAddr x.capellaData.message.y of ConsensusFork.Capella: unsafeAddr x.capellaData.message.y
of ConsensusFork.Deneb: unsafeAddr x.denebData.message.y)[] of ConsensusFork.Deneb: unsafeAddr x.denebData.message.y
of ConsensusFork.Electra: unsafeAddr x.electraData.message.y)[]
template signature*(x: ForkedSignedBeaconBlock | template signature*(x: ForkedSignedBeaconBlock |
ForkedMsgTrustedSignedBeaconBlock | ForkedMsgTrustedSignedBeaconBlock |
@ -1040,6 +1132,12 @@ template withForkyMaybeBlindedBlck*(
b: ForkedMaybeBlindedBeaconBlock, b: ForkedMaybeBlindedBeaconBlock,
body: untyped): untyped = body: untyped): untyped =
case b.kind case b.kind
of ConsensusFork.Electra:
const
consensusFork {.inject, used.} = ConsensusFork.Electra
isBlinded {.inject, used.} = false
template forkyMaybeBlindedBlck: untyped {.inject, used.} = b.electraData
body
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
template d: untyped = b.denebData template d: untyped = b.denebData
@ -1090,6 +1188,11 @@ template withStateAndBlck*(
ForkedTrustedSignedBeaconBlock, ForkedTrustedSignedBeaconBlock,
body: untyped): untyped = body: untyped): untyped =
case s.kind case s.kind
of ConsensusFork.Electra:
const consensusFork {.inject, used.} = ConsensusFork.Electra
template forkyState: untyped {.inject.} = s.electraData
template forkyBlck: untyped {.inject.} = b.electraData
body
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
const consensusFork {.inject, used.} = ConsensusFork.Deneb const consensusFork {.inject, used.} = ConsensusFork.Deneb
template forkyState: untyped {.inject.} = s.denebData template forkyState: untyped {.inject.} = s.denebData
@ -1188,6 +1291,7 @@ func electraFork*(cfg: RuntimeConfig): Fork =
func forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork = func forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork =
case cfg.consensusForkAtEpoch(epoch) case cfg.consensusForkAtEpoch(epoch)
of ConsensusFork.Electra: cfg.electraFork
of ConsensusFork.Deneb: cfg.denebFork of ConsensusFork.Deneb: cfg.denebFork
of ConsensusFork.Capella: cfg.capellaFork of ConsensusFork.Capella: cfg.capellaFork
of ConsensusFork.Bellatrix: cfg.bellatrixFork of ConsensusFork.Bellatrix: cfg.bellatrixFork
@ -1196,6 +1300,7 @@ func forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork =
func forkVersionAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Version = func forkVersionAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Version =
case cfg.consensusForkAtEpoch(epoch) case cfg.consensusForkAtEpoch(epoch)
of ConsensusFork.Electra: cfg.ELECTRA_FORK_VERSION
of ConsensusFork.Deneb: cfg.DENEB_FORK_VERSION of ConsensusFork.Deneb: cfg.DENEB_FORK_VERSION
of ConsensusFork.Capella: cfg.CAPELLA_FORK_VERSION of ConsensusFork.Capella: cfg.CAPELLA_FORK_VERSION
of ConsensusFork.Bellatrix: cfg.BELLATRIX_FORK_VERSION of ConsensusFork.Bellatrix: cfg.BELLATRIX_FORK_VERSION
@ -1203,9 +1308,9 @@ func forkVersionAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Version =
of ConsensusFork.Phase0: cfg.GENESIS_FORK_VERSION of ConsensusFork.Phase0: cfg.GENESIS_FORK_VERSION
func nextForkEpochAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Epoch = func nextForkEpochAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Epoch =
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb
case cfg.consensusForkAtEpoch(epoch) case cfg.consensusForkAtEpoch(epoch)
of ConsensusFork.Deneb: FAR_FUTURE_EPOCH of ConsensusFork.Electra: FAR_FUTURE_EPOCH
of ConsensusFork.Deneb: cfg.ELECTRA_FORK_EPOCH
of ConsensusFork.Capella: cfg.DENEB_FORK_EPOCH of ConsensusFork.Capella: cfg.DENEB_FORK_EPOCH
of ConsensusFork.Bellatrix: cfg.CAPELLA_FORK_EPOCH of ConsensusFork.Bellatrix: cfg.CAPELLA_FORK_EPOCH
of ConsensusFork.Altair: cfg.BELLATRIX_FORK_EPOCH of ConsensusFork.Altair: cfg.BELLATRIX_FORK_EPOCH
@ -1218,6 +1323,7 @@ func forkVersion*(cfg: RuntimeConfig, consensusFork: ConsensusFork): Version =
of ConsensusFork.Bellatrix: cfg.BELLATRIX_FORK_VERSION of ConsensusFork.Bellatrix: cfg.BELLATRIX_FORK_VERSION
of ConsensusFork.Capella: cfg.CAPELLA_FORK_VERSION of ConsensusFork.Capella: cfg.CAPELLA_FORK_VERSION
of ConsensusFork.Deneb: cfg.DENEB_FORK_VERSION of ConsensusFork.Deneb: cfg.DENEB_FORK_VERSION
of ConsensusFork.Electra: cfg.ELECTRA_FORK_VERSION
func lcDataForkAtConsensusFork*( func lcDataForkAtConsensusFork*(
consensusFork: ConsensusFork): LightClientDataFork = consensusFork: ConsensusFork): LightClientDataFork =
@ -1325,7 +1431,7 @@ func compute_fork_digest*(current_version: Version,
func init*(T: type ForkDigests, func init*(T: type ForkDigests,
cfg: RuntimeConfig, cfg: RuntimeConfig,
genesis_validators_root: Eth2Digest): T = genesis_validators_root: Eth2Digest): T =
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb static: doAssert high(ConsensusFork) == ConsensusFork.Electra
T( T(
phase0: phase0:
compute_fork_digest(cfg.GENESIS_FORK_VERSION, genesis_validators_root), compute_fork_digest(cfg.GENESIS_FORK_VERSION, genesis_validators_root),

View File

@ -8,7 +8,7 @@
{.push raises: [].} {.push raises: [].}
import import
./datatypes/[phase0, altair, bellatrix, capella, deneb], ./datatypes/[phase0, altair, bellatrix, capella, deneb, electra],
./eth2_merkleization ./eth2_merkleization
type type
@ -957,9 +957,14 @@ func toLightClientHeader*(
altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock | altair.SignedBeaconBlock | altair.TrustedSignedBeaconBlock |
bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock | bellatrix.SignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock |
capella.SignedBeaconBlock | capella.TrustedSignedBeaconBlock | capella.SignedBeaconBlock | capella.TrustedSignedBeaconBlock |
deneb.SignedBeaconBlock | deneb.TrustedSignedBeaconBlock, deneb.SignedBeaconBlock | deneb.TrustedSignedBeaconBlock |
electra.SignedBeaconBlock | electra.TrustedSignedBeaconBlock,
kind: static LightClientDataFork): auto = kind: static LightClientDataFork): auto =
when kind == LightClientDataFork.Deneb: when blck is electra.SignedBeaconBlock or
blck is electra.TrustedSignedBeaconBlock:
debugRaiseAssert "toLightClientHeader"
default(deneb.LightClientHeader)
elif kind == LightClientDataFork.Deneb:
blck.toDenebLightClientHeader() blck.toDenebLightClientHeader()
elif kind == LightClientDataFork.Capella: elif kind == LightClientDataFork.Capella:
blck.toCapellaLightClientHeader() blck.toCapellaLightClientHeader()

View File

@ -228,7 +228,7 @@ func verify_blob_sidecar_inclusion_proof*(
ok() ok()
func create_blob_sidecars*( func create_blob_sidecars*(
forkyBlck: deneb.SignedBeaconBlock, forkyBlck: deneb.SignedBeaconBlock | electra.SignedBeaconBlock,
kzg_proofs: KzgProofs, kzg_proofs: KzgProofs,
blobs: Blobs): seq[BlobSidecar] = blobs: Blobs): seq[BlobSidecar] =
template kzg_commitments: untyped = template kzg_commitments: untyped =
@ -382,7 +382,8 @@ func contextEpoch*(update: SomeForkyLightClientUpdate): Epoch =
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#is_merge_transition_complete # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#is_merge_transition_complete
func is_merge_transition_complete*( func is_merge_transition_complete*(
state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState): bool = state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState |
electra.BeaconState): bool =
const defaultExecutionPayloadHeader = const defaultExecutionPayloadHeader =
default(typeof(state.latest_execution_payload_header)) default(typeof(state.latest_execution_payload_header))
state.latest_execution_payload_header != defaultExecutionPayloadHeader state.latest_execution_payload_header != defaultExecutionPayloadHeader
@ -398,26 +399,32 @@ func is_execution_block*(blck: SomeForkyBeaconBlock): bool =
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#is_merge_transition_block # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#is_merge_transition_block
func is_merge_transition_block( func is_merge_transition_block(
state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState, state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState |
electra.BeaconState,
body: bellatrix.BeaconBlockBody | bellatrix.TrustedBeaconBlockBody | body: bellatrix.BeaconBlockBody | bellatrix.TrustedBeaconBlockBody |
bellatrix.SigVerifiedBeaconBlockBody | bellatrix.SigVerifiedBeaconBlockBody |
capella.BeaconBlockBody | capella.TrustedBeaconBlockBody | capella.BeaconBlockBody | capella.TrustedBeaconBlockBody |
capella.SigVerifiedBeaconBlockBody | capella.SigVerifiedBeaconBlockBody |
deneb.BeaconBlockBody | deneb.TrustedBeaconBlockBody | deneb.BeaconBlockBody | deneb.TrustedBeaconBlockBody |
deneb.SigVerifiedBeaconBlockBody): bool = deneb.SigVerifiedBeaconBlockBody |
electra.BeaconBlockBody | electra.TrustedBeaconBlockBody |
electra.SigVerifiedBeaconBlockBody): bool =
const defaultExecutionPayload = default(typeof(body.execution_payload)) const defaultExecutionPayload = default(typeof(body.execution_payload))
not is_merge_transition_complete(state) and not is_merge_transition_complete(state) and
body.execution_payload != defaultExecutionPayload body.execution_payload != defaultExecutionPayload
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#is_execution_enabled # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#is_execution_enabled
func is_execution_enabled*( func is_execution_enabled*(
state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState, state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState |
electra.BeaconState,
body: bellatrix.BeaconBlockBody | bellatrix.TrustedBeaconBlockBody | body: bellatrix.BeaconBlockBody | bellatrix.TrustedBeaconBlockBody |
bellatrix.SigVerifiedBeaconBlockBody | bellatrix.SigVerifiedBeaconBlockBody |
capella.BeaconBlockBody | capella.TrustedBeaconBlockBody | capella.BeaconBlockBody | capella.TrustedBeaconBlockBody |
capella.SigVerifiedBeaconBlockBody | capella.SigVerifiedBeaconBlockBody |
deneb.BeaconBlockBody | deneb.TrustedBeaconBlockBody | deneb.BeaconBlockBody | deneb.TrustedBeaconBlockBody |
deneb.SigVerifiedBeaconBlockBody): bool = deneb.SigVerifiedBeaconBlockBody |
electra.BeaconBlockBody | electra.TrustedBeaconBlockBody |
electra.SigVerifiedBeaconBlockBody): bool =
is_merge_transition_block(state, body) or is_merge_transition_complete(state) is_merge_transition_block(state, body) or is_merge_transition_complete(state)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#compute_timestamp_at_slot # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/bellatrix/beacon-chain.md#compute_timestamp_at_slot
@ -449,8 +456,8 @@ func toExecutionWithdrawal*(
# https://eips.ethereum.org/EIPS/eip-4895 # https://eips.ethereum.org/EIPS/eip-4895
proc computeWithdrawalsTrieRoot*( proc computeWithdrawalsTrieRoot*(
payload: capella.ExecutionPayload | deneb.ExecutionPayload payload: capella.ExecutionPayload | deneb.ExecutionPayload |
): ExecutionHash256 = electra.ExecutionPayload): ExecutionHash256 =
if payload.withdrawals.len == 0: if payload.withdrawals.len == 0:
return EMPTY_ROOT_HASH return EMPTY_ROOT_HASH

View File

@ -159,18 +159,15 @@ func noRollback*(state: var altair.HashedBeaconState) =
func noRollback*(state: var bellatrix.HashedBeaconState) = func noRollback*(state: var bellatrix.HashedBeaconState) =
trace "Skipping rollback of broken Bellatrix state" trace "Skipping rollback of broken Bellatrix state"
from ./datatypes/capella import
ExecutionPayload, HashedBeaconState, SignedBLSToExecutionChangeList,
asSigVerified
func noRollback*(state: var capella.HashedBeaconState) = func noRollback*(state: var capella.HashedBeaconState) =
trace "Skipping rollback of broken Capella state" trace "Skipping rollback of broken Capella state"
from ./datatypes/deneb import HashedBeaconState
func noRollback*(state: var deneb.HashedBeaconState) = func noRollback*(state: var deneb.HashedBeaconState) =
trace "Skipping rollback of broken Deneb state" trace "Skipping rollback of broken Deneb state"
func noRollback*(state: var electra.HashedBeaconState) =
trace "Skipping rollback of broken Electra state"
func maybeUpgradeStateToAltair( func maybeUpgradeStateToAltair(
cfg: RuntimeConfig, state: var ForkedHashedBeaconState) = cfg: RuntimeConfig, state: var ForkedHashedBeaconState) =
# Both process_slots() and state_transition_block() call this, so only run it # Both process_slots() and state_transition_block() call this, so only run it
@ -225,6 +222,7 @@ func maybeUpgradeState*(
cfg.maybeUpgradeStateToBellatrix(state) cfg.maybeUpgradeStateToBellatrix(state)
cfg.maybeUpgradeStateToCapella(state) cfg.maybeUpgradeStateToCapella(state)
cfg.maybeUpgradeStateToDeneb(state) cfg.maybeUpgradeStateToDeneb(state)
# TODO cfg.maybeUpgradeStateToElectra
proc process_slots*( proc process_slots*(
cfg: RuntimeConfig, state: var ForkedHashedBeaconState, slot: Slot, cfg: RuntimeConfig, state: var ForkedHashedBeaconState, slot: Slot,
@ -477,6 +475,8 @@ proc makeBeaconBlock*(
]) ])
else: else:
raiseAssert "Attempt to use non-Deneb payload with post-Deneb state" raiseAssert "Attempt to use non-Deneb payload with post-Deneb state"
elif consensusFork == ConsensusFork.Electra:
debugRaiseAssert "makeBeaconBlock"
else: else:
static: raiseAssert "Unreachable" static: raiseAssert "Unreachable"
@ -501,6 +501,10 @@ proc makeBeaconBlock*(
case state.kind case state.kind
of ConsensusFork.Deneb: makeBeaconBlock(deneb) of ConsensusFork.Deneb: makeBeaconBlock(deneb)
else: raiseAssert "Attempt to use Deneb payload with non-Deneb state" else: raiseAssert "Attempt to use Deneb payload with non-Deneb state"
elif payloadFork == ConsensusFork.Electra:
case state.kind
of ConsensusFork.Electra: makeBeaconBlock(electra)
else: raiseAssert "Attempt to use Electra payload with non-Electra state"
else: else:
{.error: "Unsupported fork".} {.error: "Unsupported fork".}

View File

@ -415,7 +415,8 @@ proc process_voluntary_exit*(
ok() ok()
proc process_bls_to_execution_change*( proc process_bls_to_execution_change*(
cfg: RuntimeConfig, state: var (capella.BeaconState | deneb.BeaconState), cfg: RuntimeConfig,
state: var (capella.BeaconState | deneb.BeaconState | electra.BeaconState),
signed_address_change: SignedBLSToExecutionChange): Result[void, cstring] = signed_address_change: SignedBLSToExecutionChange): Result[void, cstring] =
? check_bls_to_execution_change( ? check_bls_to_execution_change(
cfg.genesisFork, state, signed_address_change, {}) cfg.genesisFork, state, signed_address_change, {})
@ -486,7 +487,7 @@ func get_proposer_reward*(participant_reward: Gwei): Gwei =
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#sync-aggregate-processing # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#sync-aggregate-processing
proc process_sync_aggregate*( proc process_sync_aggregate*(
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState), capella.BeaconState | deneb.BeaconState | electra.BeaconState),
sync_aggregate: SomeSyncAggregate, total_active_balance: Gwei, sync_aggregate: SomeSyncAggregate, total_active_balance: Gwei,
flags: UpdateFlags, flags: UpdateFlags,
cache: var StateCache): cache: var StateCache):
@ -687,10 +688,67 @@ proc process_execution_payload*(
ok() ok()
# TODO workaround for https://github.com/nim-lang/Nim/issues/18095
# copy of datatypes/electra.nim
type SomeElectraBeaconBlockBody =
electra.BeaconBlockBody | electra.SigVerifiedBeaconBlockBody |
electra.TrustedBeaconBlockBody
# TODO spec ref URL when available
proc process_execution_payload*(
state: var electra.BeaconState, body: SomeElectraBeaconBlockBody,
notify_new_payload: electra.ExecutePayload): Result[void, cstring] =
template payload: auto = body.execution_payload
# Verify consistency of the parent hash with respect to the previous
# execution payload header
if not (payload.parent_hash ==
state.latest_execution_payload_header.block_hash):
return err("process_execution_payload: payload and state parent hash mismatch")
# Verify prev_randao
if not (payload.prev_randao == get_randao_mix(state, get_current_epoch(state))):
return err("process_execution_payload: payload and state randomness mismatch")
# Verify timestamp
if not (payload.timestamp == compute_timestamp_at_slot(state, state.slot)):
return err("process_execution_payload: invalid timestamp")
# [New in Deneb] Verify commitments are under limit
if not (lenu64(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK):
return err("process_execution_payload: too many KZG commitments")
# Verify the execution payload is valid
if not notify_new_payload(payload):
return err("process_execution_payload: execution payload invalid")
# Cache execution payload header
state.latest_execution_payload_header = electra.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,
base_fee_per_gas: payload.base_fee_per_gas,
block_hash: payload.block_hash,
extra_data: payload.extra_data,
transactions_root: hash_tree_root(payload.transactions),
withdrawals_root: hash_tree_root(payload.withdrawals),
blob_gas_used: payload.blob_gas_used,
excess_blob_gas: payload.excess_blob_gas)
ok()
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/capella/beacon-chain.md#new-process_withdrawals # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/capella/beacon-chain.md#new-process_withdrawals
func process_withdrawals*( func process_withdrawals*(
state: var (capella.BeaconState | deneb.BeaconState), state: var (capella.BeaconState | deneb.BeaconState | electra.BeaconState),
payload: capella.ExecutionPayload | deneb.ExecutionPayload): payload: capella.ExecutionPayload | deneb.ExecutionPayload |
electra.ExecutionPayload):
Result[void, cstring] = Result[void, cstring] =
let expected_withdrawals = get_expected_withdrawals(state) let expected_withdrawals = get_expected_withdrawals(state)
@ -902,3 +960,38 @@ proc process_block*(
state, blck.body.sync_aggregate, total_active_balance, flags, cache) state, blck.body.sync_aggregate, total_active_balance, flags, cache)
ok() ok()
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#block-processing
# TODO workaround for https://github.com/nim-lang/Nim/issues/18095
type SomeElectraBlock =
electra.BeaconBlock | electra.SigVerifiedBeaconBlock | electra.TrustedBeaconBlock
proc process_block*(
cfg: RuntimeConfig,
state: var electra.BeaconState, blck: SomeElectraBlock,
flags: UpdateFlags, cache: var StateCache): Result[void, cstring]=
## When there's a new block, we need to verify that the block is sane and
## update the state accordingly - the state is left in an unknown state when
## block application fails (!)
? process_block_header(state, blck, flags, cache)
# Consensus specs v1.4.0 unconditionally assume is_execution_enabled is
# true, but intentionally keep such a check.
if is_execution_enabled(state, blck.body):
? process_withdrawals(state, blck.body.execution_payload)
? process_execution_payload(
state, blck.body,
func(_: electra.ExecutionPayload): bool = true)
? process_randao(state, blck.body, flags, cache)
? process_eth1_data(state, blck.body)
let
total_active_balance = get_total_active_balance(state, cache)
base_reward_per_increment =
get_base_reward_per_increment(total_active_balance)
? process_operations(
cfg, state, blck.body, base_reward_per_increment, flags, cache)
? process_sync_aggregate(
state, blck.body.sync_aggregate, total_active_balance, flags, cache)
ok()

View File

@ -177,7 +177,8 @@ from ./datatypes/deneb import BeaconState
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_unslashed_participating_indices # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_unslashed_participating_indices
func get_unslashed_participating_balances*( func get_unslashed_participating_balances*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState): UnslashedParticipatingBalances = deneb.BeaconState | electra.BeaconState):
UnslashedParticipatingBalances =
let let
previous_epoch = get_previous_epoch(state) previous_epoch = get_previous_epoch(state)
current_epoch = get_current_epoch(state) current_epoch = get_current_epoch(state)
@ -228,7 +229,7 @@ func get_unslashed_participating_balances*(
func is_unslashed_participating_index( func is_unslashed_participating_index(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
flag_index: TimelyFlag, epoch: Epoch, validator_index: ValidatorIndex): bool = flag_index: TimelyFlag, epoch: Epoch, validator_index: ValidatorIndex): bool =
doAssert epoch in [get_previous_epoch(state), get_current_epoch(state)] doAssert epoch in [get_previous_epoch(state), get_current_epoch(state)]
# TODO hoist this conditional # TODO hoist this conditional
@ -445,7 +446,7 @@ proc compute_unrealized_finality*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#justification-and-finalization # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#justification-and-finalization
proc process_justification_and_finalization*( proc process_justification_and_finalization*(
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState), capella.BeaconState | deneb.BeaconState | electra.BeaconState),
balances: UnslashedParticipatingBalances, balances: UnslashedParticipatingBalances,
flags: UpdateFlags = {}) = flags: UpdateFlags = {}) =
# Initial FFG checkpoint values have a `0x00` stub for `root`. # Initial FFG checkpoint values have a `0x00` stub for `root`.
@ -467,7 +468,7 @@ proc process_justification_and_finalization*(
proc compute_unrealized_finality*( proc compute_unrealized_finality*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState): FinalityCheckpoints = deneb.BeaconState | electra.BeaconState): FinalityCheckpoints =
if get_current_epoch(state) <= GENESIS_EPOCH + 1: if get_current_epoch(state) <= GENESIS_EPOCH + 1:
return FinalityCheckpoints( return FinalityCheckpoints(
justified: state.current_justified_checkpoint, justified: state.current_justified_checkpoint,
@ -658,7 +659,7 @@ func get_attestation_deltas(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_base_reward # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_base_reward
func get_base_reward_increment*( func get_base_reward_increment*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
index: ValidatorIndex, base_reward_per_increment: Gwei): Gwei = index: ValidatorIndex, base_reward_per_increment: Gwei): Gwei =
## Return the base reward for the validator defined by ``index`` with respect ## Return the base reward for the validator defined by ``index`` with respect
## to the current ``state``. ## to the current ``state``.
@ -669,7 +670,7 @@ func get_base_reward_increment*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_flag_index_deltas # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#get_flag_index_deltas
func get_flag_index_reward*( func get_flag_index_reward*(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
base_reward: Gwei, active_increments: Gwei, base_reward: Gwei, active_increments: Gwei,
unslashed_participating_increments: Gwei, unslashed_participating_increments: Gwei,
weight, finality_delay: uint64): Gwei = weight, finality_delay: uint64): Gwei =
@ -697,7 +698,7 @@ func get_active_increments*(
iterator get_flag_and_inactivity_deltas*( iterator get_flag_and_inactivity_deltas*(
cfg: RuntimeConfig, cfg: RuntimeConfig,
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
base_reward_per_increment: Gwei, info: var altair.EpochInfo, base_reward_per_increment: Gwei, info: var altair.EpochInfo,
finality_delay: uint64): finality_delay: uint64):
(ValidatorIndex, Gwei, Gwei, Gwei, Gwei, Gwei, Gwei) = (ValidatorIndex, Gwei, Gwei, Gwei, Gwei, Gwei, Gwei) =
@ -807,7 +808,7 @@ func process_rewards_and_penalties*(
func process_rewards_and_penalties*( func process_rewards_and_penalties*(
cfg: RuntimeConfig, cfg: RuntimeConfig,
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState), capella.BeaconState | deneb.BeaconState | electra.BeaconState),
info: var altair.EpochInfo) = info: var altair.EpochInfo) =
if get_current_epoch(state) == GENESIS_EPOCH: if get_current_epoch(state) == GENESIS_EPOCH:
return return
@ -914,7 +915,7 @@ func get_adjusted_total_slashing_balance*(
elif state is altair.BeaconState: elif state is altair.BeaconState:
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR
elif state is bellatrix.BeaconState or state is capella.BeaconState or elif state is bellatrix.BeaconState or state is capella.BeaconState or
state is deneb.BeaconState: state is deneb.BeaconState or state is electra.BeaconState:
PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX
else: else:
{.fatal: "process_slashings: incorrect BeaconState type".} {.fatal: "process_slashings: incorrect BeaconState type".}
@ -1037,7 +1038,8 @@ func process_participation_record_updates*(state: var phase0.BeaconState) =
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#participation-flags-updates # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#participation-flags-updates
func process_participation_flag_updates*( func process_participation_flag_updates*(
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState)) = capella.BeaconState | deneb.BeaconState |
electra.BeaconState)) =
state.previous_epoch_participation = state.current_epoch_participation state.previous_epoch_participation = state.current_epoch_participation
const zero = 0.ParticipationFlags const zero = 0.ParticipationFlags
@ -1051,7 +1053,8 @@ func process_participation_flag_updates*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#sync-committee-updates # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#sync-committee-updates
func process_sync_committee_updates*( func process_sync_committee_updates*(
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState)) = capella.BeaconState | deneb.BeaconState |
electra.BeaconState)) =
let next_epoch = get_current_epoch(state) + 1 let next_epoch = get_current_epoch(state) + 1
if next_epoch.is_sync_committee_period(): if next_epoch.is_sync_committee_period():
state.current_sync_committee = state.next_sync_committee state.current_sync_committee = state.next_sync_committee
@ -1060,7 +1063,7 @@ func process_sync_committee_updates*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#inactivity-scores # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/altair/beacon-chain.md#inactivity-scores
template compute_inactivity_update( template compute_inactivity_update(
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState, deneb.BeaconState | electra.BeaconState,
info: altair.EpochInfo, pre_inactivity_score: Gwei): Gwei = info: altair.EpochInfo, pre_inactivity_score: Gwei): Gwei =
if not is_eligible_validator(info.validators[index]): if not is_eligible_validator(info.validators[index]):
continue continue
@ -1086,7 +1089,7 @@ template compute_inactivity_update(
func process_inactivity_updates*( func process_inactivity_updates*(
cfg: RuntimeConfig, cfg: RuntimeConfig,
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState), capella.BeaconState | deneb.BeaconState | electra.BeaconState),
info: altair.EpochInfo) = info: altair.EpochInfo) =
# Score updates based on previous epoch participation, skip genesis epoch # Score updates based on previous epoch participation, skip genesis epoch
if get_current_epoch(state) == GENESIS_EPOCH: if get_current_epoch(state) == GENESIS_EPOCH:
@ -1108,7 +1111,7 @@ func process_inactivity_updates*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#historical-summaries-updates # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#historical-summaries-updates
func process_historical_summaries_update*( func process_historical_summaries_update*(
state: var (capella.BeaconState | deneb.BeaconState)): state: var (capella.BeaconState | deneb.BeaconState | electra.BeaconState)):
Result[void, cstring] = Result[void, cstring] =
# Set historical block root accumulator. # Set historical block root accumulator.
let next_epoch = get_current_epoch(state) + 1 let next_epoch = get_current_epoch(state) + 1
@ -1159,7 +1162,7 @@ proc process_epoch*(
func init*( func init*(
info: var altair.EpochInfo, info: var altair.EpochInfo,
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
deneb.BeaconState) = deneb.BeaconState | electra.BeaconState) =
# init participation, overwriting the full structure # init participation, overwriting the full structure
info.balances = get_unslashed_participating_balances(state) info.balances = get_unslashed_participating_balances(state)
info.validators.setLen(state.validators.len()) info.validators.setLen(state.validators.len())
@ -1229,7 +1232,7 @@ proc process_epoch*(
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#epoch-processing # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/capella/beacon-chain.md#epoch-processing
proc process_epoch*( proc process_epoch*(
cfg: RuntimeConfig, cfg: RuntimeConfig,
state: var (capella.BeaconState | deneb.BeaconState), state: var (capella.BeaconState | deneb.BeaconState | electra.BeaconState),
flags: UpdateFlags, cache: var StateCache, info: var altair.EpochInfo): flags: UpdateFlags, cache: var StateCache, info: var altair.EpochInfo):
Result[void, cstring] = Result[void, cstring] =
let epoch = get_current_epoch(state) let epoch = get_current_epoch(state)

View File

@ -2259,6 +2259,9 @@ proc publishBlock*(
publishBlock(it, data.capellaData) publishBlock(it, data.capellaData)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
publishBlock(it, data.denebData) publishBlock(it, data.denebData)
of ConsensusFork.Electra:
debugRaiseAssert "publishBlock RestPublishedSignedBlockContents; denebData will assert via mismatched case object discriminator"
publishBlock(it, data.denebData)
do: do:
if apiResponse.isErr(): if apiResponse.isErr():
handleCommunicationError() handleCommunicationError()
@ -2305,6 +2308,9 @@ proc publishBlock*(
publishBlock(it, data.capellaData) publishBlock(it, data.capellaData)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
publishBlock(it, data.denebData) publishBlock(it, data.denebData)
of ConsensusFork.Electra:
debugRaiseAssert "publishBlock RestPublishedSignedBlockContents; denebData will create invalid case discriminator"
publishBlock(it, data.denebData)
do: do:
if apiResponse.isErr(): if apiResponse.isErr():
@ -2461,6 +2467,9 @@ proc publishBlindedBlock*(
publishBlindedBlock(it, data.capellaData) publishBlindedBlock(it, data.capellaData)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
publishBlindedBlock(it, data.denebData) publishBlindedBlock(it, data.denebData)
of ConsensusFork.Electra:
debugRaiseAssert "publishBlindedBlock ForkedSignedBlindedBeaconBlock; denebData mismatches discriminator"
publishBlindedBlock(it, data.denebData)
do: do:
if apiResponse.isErr(): if apiResponse.isErr():
handleCommunicationError() handleCommunicationError()
@ -2506,6 +2515,9 @@ proc publishBlindedBlock*(
publishBlindedBlock(it, data.capellaData) publishBlindedBlock(it, data.capellaData)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
publishBlindedBlock(it, data.denebData) publishBlindedBlock(it, data.denebData)
of ConsensusFork.Electra:
debugRaiseAssert "publishBlindedBlock ForkedSignedBlindedBeaconBlock; denebData mismatches discriminator"
publishBlindedBlock(it, data.denebData)
do: do:
if apiResponse.isErr(): if apiResponse.isErr():
handleCommunicationError() handleCommunicationError()

View File

@ -96,6 +96,9 @@ proc produceBlock(
data: ForkedBeaconBlock.init(blck), data: ForkedBeaconBlock.init(blck),
kzgProofsOpt: Opt.some(kzgProofs), kzgProofsOpt: Opt.some(kzgProofs),
blobsOpt: Opt.some(blobs))) blobsOpt: Opt.some(blobs)))
of ConsensusFork.Electra:
debugRaiseAssert "produceBlock in block_service.nim"
return Opt.none(PreparedBeaconBlock)
proc produceBlindedBlock( proc produceBlindedBlock(
vc: ValidatorClientRef, vc: ValidatorClientRef,
@ -305,8 +308,11 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
blockRoot = hash_tree_root( blockRoot = hash_tree_root(
when consensusFork < ConsensusFork.Deneb: when consensusFork < ConsensusFork.Deneb:
forkyMaybeBlindedBlck forkyMaybeBlindedBlck
else: elif consensusFork < ConsensusFork.Electra:
forkyMaybeBlindedBlck.`block` forkyMaybeBlindedBlck.`block`
else:
debugRaiseAssert "publishBlockV3 1"
default(Attestation)
) )
signingRoot = signingRoot =
compute_block_signing_root(fork, genesisRoot, slot, blockRoot) compute_block_signing_root(fork, genesisRoot, slot, blockRoot)
@ -318,8 +324,11 @@ proc publishBlockV3(vc: ValidatorClientRef, currentSlot, slot: Slot,
blck = shortLog( blck = shortLog(
when consensusFork < ConsensusFork.Deneb: when consensusFork < ConsensusFork.Deneb:
forkyMaybeBlindedBlck forkyMaybeBlindedBlck
else: elif consensusFork < ConsensusFork.Electra:
forkyMaybeBlindedBlck.`block` forkyMaybeBlindedBlck.`block`
else:
debugRaiseAssert "publishBlockV3 2"
default(bellatrix.BeaconBlock)
) )
block_root = shortLog(blockRoot) block_root = shortLog(blockRoot)
signing_root = shortLog(signingRoot) signing_root = shortLog(signingRoot)
@ -572,6 +581,9 @@ proc publishBlockV2(vc: ValidatorClientRef, currentSlot, slot: Slot,
signature: signature), signature: signature),
kzg_proofs: preparedBlock.kzgProofsOpt.get, kzg_proofs: preparedBlock.kzgProofsOpt.get,
blobs: preparedBlock.blobsOpt.get)) blobs: preparedBlock.blobsOpt.get))
of ConsensusFork.Electra:
debugRaiseAssert "publishBlockV2 2"
default(RestPublishedSignedBlockContents)
res = res =
try: try:

View File

@ -1316,7 +1316,10 @@ proc proposeBlock(node: BeaconNode,
genesis_validators_root, node.config.localBlockValueBoost) genesis_validators_root, node.config.localBlockValueBoost)
return withConsensusFork(node.dag.cfg.consensusForkAtEpoch(slot.epoch)): return withConsensusFork(node.dag.cfg.consensusForkAtEpoch(slot.epoch)):
when consensusFork >= ConsensusFork.Capella: when consensusFork >= ConsensusFork.Electra:
debugRaiseAssert "proposeBlock; fill in Electra support"
default(BlockRef)
elif consensusFork >= ConsensusFork.Capella:
proposeBlockContinuation( proposeBlockContinuation(
consensusFork.SignedBlindedBeaconBlock, consensusFork.SignedBlindedBeaconBlock,
consensusFork.ExecutionPayloadForSigning) consensusFork.ExecutionPayloadForSigning)

View File

@ -565,6 +565,9 @@ proc getBlockSignature*(v: AttachedValidator, fork: Fork,
Web3SignerForkedBeaconBlock(kind: ConsensusFork.Deneb, Web3SignerForkedBeaconBlock(kind: ConsensusFork.Deneb,
data: blck.denebData.toBeaconBlockHeader), data: blck.denebData.toBeaconBlockHeader),
proofs) proofs)
of ConsensusFork.Electra:
debugRaiseAssert "getBlockSignature 2"
default(Web3SignerRequest)
elif blck is capella_mev.BlindedBeaconBlock: elif blck is capella_mev.BlindedBeaconBlock:
case v.data.remoteType case v.data.remoteType
of RemoteSignerType.Web3Signer: of RemoteSignerType.Web3Signer:
@ -668,6 +671,9 @@ proc getBlockSignature*(v: AttachedValidator, fork: Fork,
Web3SignerForkedBeaconBlock(kind: ConsensusFork.Deneb, Web3SignerForkedBeaconBlock(kind: ConsensusFork.Deneb,
data: forkyMaybeBlindedBlck.`block`.toBeaconBlockHeader), data: forkyMaybeBlindedBlck.`block`.toBeaconBlockHeader),
proofs) proofs)
elif consensusFork == ConsensusFork.Electra:
debugRaiseAssert "getBlockSignature 1"
default(Web3SignerRequest)
else: else:
case blck.kind case blck.kind
of ConsensusFork.Phase0, ConsensusFork.Altair: of ConsensusFork.Phase0, ConsensusFork.Altair:
@ -711,6 +717,9 @@ proc getBlockSignature*(v: AttachedValidator, fork: Fork,
Web3SignerForkedBeaconBlock(kind: ConsensusFork.Deneb, Web3SignerForkedBeaconBlock(kind: ConsensusFork.Deneb,
data: blck.denebData.toBeaconBlockHeader), data: blck.denebData.toBeaconBlockHeader),
proofs) proofs)
of ConsensusFork.Electra:
debugRaiseAssert "getBlockSignature"
return SignatureResult.err("Invalid beacon block fork version")
await v.signData(web3signerRequest) await v.signData(web3signerRequest)
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/phase0/validator.md#aggregate-signature # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.7/specs/phase0/validator.md#aggregate-signature

View File

@ -98,6 +98,7 @@ template saveSSZFile(filename: string, value: ForkedHashedBeaconState) =
of ConsensusFork.Bellatrix: SSZ.saveFile(filename, value.bellatrixData.data) of ConsensusFork.Bellatrix: SSZ.saveFile(filename, value.bellatrixData.data)
of ConsensusFork.Capella: SSZ.saveFile(filename, value.capellaData.data) of ConsensusFork.Capella: SSZ.saveFile(filename, value.capellaData.data)
of ConsensusFork.Deneb: SSZ.saveFile(filename, value.denebData.data) of ConsensusFork.Deneb: SSZ.saveFile(filename, value.denebData.data)
of ConsensusFork.Electra: SSZ.saveFile(filename, value.electraData.data)
except IOError: except IOError:
raiseAssert "error saving SSZ file" raiseAssert "error saving SSZ file"

View File

@ -274,7 +274,7 @@ proc collectEpochRewardsAndPenalties*(
proc collectEpochRewardsAndPenalties*( proc collectEpochRewardsAndPenalties*(
rewardsAndPenalties: var seq[RewardsAndPenalties], rewardsAndPenalties: var seq[RewardsAndPenalties],
state: var (altair.BeaconState | bellatrix.BeaconState | state: var (altair.BeaconState | bellatrix.BeaconState |
capella.BeaconState | deneb.BeaconState), capella.BeaconState | deneb.BeaconState | electra.BeaconState),
cache: var StateCache, cfg: RuntimeConfig, flags: UpdateFlags) = cache: var StateCache, cfg: RuntimeConfig, flags: UpdateFlags) =
if get_current_epoch(state) == GENESIS_EPOCH: if get_current_epoch(state) == GENESIS_EPOCH:
return return

View File

@ -240,7 +240,8 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
seq[altair.TrustedSignedBeaconBlock], seq[altair.TrustedSignedBeaconBlock],
seq[bellatrix.TrustedSignedBeaconBlock], seq[bellatrix.TrustedSignedBeaconBlock],
seq[capella.TrustedSignedBeaconBlock], seq[capella.TrustedSignedBeaconBlock],
seq[deneb.TrustedSignedBeaconBlock]) seq[deneb.TrustedSignedBeaconBlock],
seq[electra.TrustedSignedBeaconBlock])
echo "Loaded head slot ", dag.head.slot, echo "Loaded head slot ", dag.head.slot,
" selected ", blockRefs.len, " blocks" " selected ", blockRefs.len, " blocks"
@ -266,6 +267,9 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
blocks[4].add dag.db.getBlock( blocks[4].add dag.db.getBlock(
blck.root, deneb.TrustedSignedBeaconBlock).get() blck.root, deneb.TrustedSignedBeaconBlock).get()
of ConsensusFork.Electra:
blocks[5].add dag.db.getBlock(
blck.root, electra.TrustedSignedBeaconBlock).get()
let stateData = newClone(dag.headState) let stateData = newClone(dag.headState)
@ -277,7 +281,8 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
(ref altair.HashedBeaconState)(), (ref altair.HashedBeaconState)(),
(ref bellatrix.HashedBeaconState)(), (ref bellatrix.HashedBeaconState)(),
(ref capella.HashedBeaconState)(), (ref capella.HashedBeaconState)(),
(ref deneb.HashedBeaconState)()) (ref deneb.HashedBeaconState)(),
(ref electra.HashedBeaconState)())
withTimer(timers[tLoadState]): withTimer(timers[tLoadState]):
doAssert dag.updateState( doAssert dag.updateState(
@ -338,6 +343,9 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
doAssert dbBenchmark.getState( doAssert dbBenchmark.getState(
forkyState.root, loadedState[4][].data, noRollback) forkyState.root, loadedState[4][].data, noRollback)
of ConsensusFork.Electra:
doAssert dbBenchmark.getState(
forkyState.root, loadedState[5][].data, noRollback)
if forkyState.data.slot.epoch mod 16 == 0: if forkyState.data.slot.epoch mod 16 == 0:
let loadedRoot = case consensusFork let loadedRoot = case consensusFork
@ -346,6 +354,7 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
of ConsensusFork.Bellatrix: hash_tree_root(loadedState[2][].data) of ConsensusFork.Bellatrix: hash_tree_root(loadedState[2][].data)
of ConsensusFork.Capella: hash_tree_root(loadedState[3][].data) of ConsensusFork.Capella: hash_tree_root(loadedState[3][].data)
of ConsensusFork.Deneb: hash_tree_root(loadedState[4][].data) of ConsensusFork.Deneb: hash_tree_root(loadedState[4][].data)
of ConsensusFork.Electra: hash_tree_root(loadedState[5][].data)
doAssert hash_tree_root(forkyState.data) == loadedRoot doAssert hash_tree_root(forkyState.data) == loadedRoot
processBlocks(blocks[0]) processBlocks(blocks[0])
@ -353,6 +362,7 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
processBlocks(blocks[2]) processBlocks(blocks[2])
processBlocks(blocks[3]) processBlocks(blocks[3])
processBlocks(blocks[4]) processBlocks(blocks[4])
processBlocks(blocks[5])
printTimers(false, timers) printTimers(false, timers)
@ -366,6 +376,7 @@ proc cmdDumpState(conf: DbConf) =
bellatrixState = (ref bellatrix.HashedBeaconState)() bellatrixState = (ref bellatrix.HashedBeaconState)()
capellaState = (ref capella.HashedBeaconState)() capellaState = (ref capella.HashedBeaconState)()
denebState = (ref deneb.HashedBeaconState)() denebState = (ref deneb.HashedBeaconState)()
electraState = (ref electra.HashedBeaconState)()
for stateRoot in conf.stateRoot: for stateRoot in conf.stateRoot:
if shouldShutDown: quit QuitSuccess if shouldShutDown: quit QuitSuccess
@ -428,6 +439,8 @@ proc cmdDumpBlock(conf: DbConf) =
dump("./", blck.get()) dump("./", blck.get())
elif (let blck = db.getBlock(root, deneb.TrustedSignedBeaconBlock); blck.isSome): elif (let blck = db.getBlock(root, deneb.TrustedSignedBeaconBlock); blck.isSome):
dump("./", blck.get()) dump("./", blck.get())
elif (let blck = db.getBlock(root, electra.TrustedSignedBeaconBlock); blck.isSome):
dump("./", blck.get())
else: else:
echo "Couldn't load ", blockRoot echo "Couldn't load ", blockRoot
except CatchableError as e: except CatchableError as e:

View File

@ -142,6 +142,49 @@ proc makeSimulationBlock(
ok(blck) ok(blck)
proc makeSimulationBlock(
cfg: RuntimeConfig,
state: var electra.HashedBeaconState,
proposer_index: ValidatorIndex,
randao_reveal: ValidatorSig,
eth1_data: Eth1Data,
graffiti: GraffitiBytes,
attestations: seq[Attestation],
deposits: seq[Deposit],
exits: BeaconBlockValidatorChanges,
sync_aggregate: SyncAggregate,
execution_payload: electra.ExecutionPayloadForSigning,
bls_to_execution_changes: SignedBLSToExecutionChangeList,
rollback: RollbackHashedProc[electra.HashedBeaconState],
cache: var StateCache,
# TODO:
# `verificationFlags` is needed only in tests and can be
# removed if we don't use invalid signatures there
verificationFlags: UpdateFlags = {}): Result[electra.BeaconBlock, cstring] =
## Create a block for the given state. The latest block applied to it will
## be used for the parent_root value, and the slot will be take from
## state.slot meaning process_slots must be called up to the slot for which
## the block is to be created.
# To create a block, we'll first apply a partial block to the state, skipping
# some validations.
var blck = partialBeaconBlock(
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
attestations, deposits, exits, sync_aggregate, execution_payload)
let res = process_block(
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
if res.isErr:
rollback(state)
return err(res.error())
state.root = hash_tree_root(state.data)
blck.state_root = state.root
ok(blck)
# TODO confutils is an impenetrable black box. how can a help text be added here? # TODO confutils is an impenetrable black box. how can a help text be added here?
cli do(slots = SLOTS_PER_EPOCH * 7, cli do(slots = SLOTS_PER_EPOCH * 7,
validators = SLOTS_PER_EPOCH * 500, validators = SLOTS_PER_EPOCH * 500,
@ -343,6 +386,8 @@ cli do(slots = SLOTS_PER_EPOCH * 7,
addr state.capellaData addr state.capellaData
elif T is deneb.SignedBeaconBlock: elif T is deneb.SignedBeaconBlock:
addr state.denebData addr state.denebData
elif T is electra.SignedBeaconBlock:
addr state.electraData
else: else:
static: doAssert false static: doAssert false
message = makeSimulationBlock( message = makeSimulationBlock(
@ -359,7 +404,9 @@ cli do(slots = SLOTS_PER_EPOCH * 7,
eth1ProposalData.deposits, eth1ProposalData.deposits,
BeaconBlockValidatorChanges(), BeaconBlockValidatorChanges(),
sync_aggregate, sync_aggregate,
when T is deneb.SignedBeaconBlock: when T is electra.SignedBeaconBlock:
default(electra.ExecutionPayloadForSigning)
elif T is deneb.SignedBeaconBlock:
default(deneb.ExecutionPayloadForSigning) default(deneb.ExecutionPayloadForSigning)
elif T is capella.SignedBeaconBlock: elif T is capella.SignedBeaconBlock:
default(capella.ExecutionPayloadForSigning) default(capella.ExecutionPayloadForSigning)
@ -432,6 +479,28 @@ cli do(slots = SLOTS_PER_EPOCH * 7,
do: do:
raiseAssert "withUpdatedState failed" raiseAssert "withUpdatedState failed"
proc proposeElectraBlock(slot: Slot) =
if rand(r, 1.0) > blockRatio:
return
dag.withUpdatedState(tmpState[], dag.getBlockIdAtSlot(slot).expect("block")) do:
let
newBlock = getNewBlock[electra.SignedBeaconBlock](updatedState, slot, cache)
added = dag.addHeadBlock(verifier, newBlock) do (
blckRef: BlockRef, signedBlock: electra.TrustedSignedBeaconBlock,
epochRef: EpochRef, unrealized: FinalityCheckpoints):
# Callback add to fork choice if valid
attPool.addForkChoice(
epochRef, blckRef, unrealized, signedBlock.message,
blckRef.slot.start_beacon_time)
dag.updateHead(added[], quarantine[], [])
if dag.needStateCachesAndForkChoicePruning():
dag.pruneStateCachesDAG()
attPool.prune()
do:
raiseAssert "withUpdatedState failed"
var var
lastEth1BlockAt = genesisTime lastEth1BlockAt = genesisTime
eth1BlockNum = 1000 eth1BlockNum = 1000
@ -472,6 +541,7 @@ cli do(slots = SLOTS_PER_EPOCH * 7,
if blockRatio > 0.0: if blockRatio > 0.0:
withTimer(timers[t]): withTimer(timers[t]):
case dag.cfg.consensusForkAtEpoch(slot.epoch) case dag.cfg.consensusForkAtEpoch(slot.epoch)
of ConsensusFork.Electra: proposeElectraBlock(slot)
of ConsensusFork.Deneb: proposeDenebBlock(slot) of ConsensusFork.Deneb: proposeDenebBlock(slot)
of ConsensusFork.Capella: proposeCapellaBlock(slot) of ConsensusFork.Capella: proposeCapellaBlock(slot)
of ConsensusFork.Bellatrix, ConsensusFork.Altair, ConsensusFork.Phase0: of ConsensusFork.Bellatrix, ConsensusFork.Altair, ConsensusFork.Phase0:

View File

@ -221,6 +221,15 @@ cli do(validatorsDir: string, secretsDir: string,
fork, genesis_validators_root, slot, blockRoot, fork, genesis_validators_root, slot, blockRoot,
validators[proposer]).toValidatorSig()) validators[proposer]).toValidatorSig())
dump(".", signedBlock) dump(".", signedBlock)
of ConsensusFork.Electra:
blockRoot = hash_tree_root(message.electraData)
let signedBlock = electra.SignedBeaconBlock(
message: message.electraData,
root: blockRoot,
signature: get_block_signature(
fork, genesis_validators_root, slot, blockRoot,
validators[proposer]).toValidatorSig())
dump(".", signedBlock)
except CatchableError: except CatchableError:
raiseAssert "unreachable" raiseAssert "unreachable"
notice "Block proposed", message, blockRoot notice "Block proposed", message, blockRoot

View File

@ -47,6 +47,12 @@ func readValue*(r: var JsonReader, a: var seq[byte]) =
func genesisTestRuntimeConfig*(consensusFork: ConsensusFork): RuntimeConfig = func genesisTestRuntimeConfig*(consensusFork: ConsensusFork): RuntimeConfig =
var res = defaultRuntimeConfig var res = defaultRuntimeConfig
case consensusFork case consensusFork
of ConsensusFork.Electra:
res.ELECTRA_FORK_EPOCH = GENESIS_EPOCH
res.DENEB_FORK_EPOCH = GENESIS_EPOCH
res.CAPELLA_FORK_EPOCH = GENESIS_EPOCH
res.BELLATRIX_FORK_EPOCH = GENESIS_EPOCH
res.ALTAIR_FORK_EPOCH = GENESIS_EPOCH
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
res.DENEB_FORK_EPOCH = GENESIS_EPOCH res.DENEB_FORK_EPOCH = GENESIS_EPOCH
res.CAPELLA_FORK_EPOCH = GENESIS_EPOCH res.CAPELLA_FORK_EPOCH = GENESIS_EPOCH

View File

@ -94,4 +94,5 @@ template runForkBlockTests(consensusFork: static ConsensusFork) =
RandomDir, suiteName, path) RandomDir, suiteName, path)
withAll(ConsensusFork): withAll(ConsensusFork):
runForkBlockTests(consensusFork) when consensusFork != ConsensusFork.Electra:
runForkBlockTests(consensusFork)

View File

@ -25,12 +25,14 @@ suite "Light client" & preset():
headPeriod = 3.SyncCommitteePeriod headPeriod = 3.SyncCommitteePeriod
let let
cfg = block: # Fork schedule so that each `LightClientDataFork` is covered cfg = block: # Fork schedule so that each `LightClientDataFork` is covered
static: doAssert ConsensusFork.high == ConsensusFork.Deneb static: doAssert ConsensusFork.high == ConsensusFork.Electra
var res = defaultRuntimeConfig var res = defaultRuntimeConfig
res.ALTAIR_FORK_EPOCH = 1.Epoch res.ALTAIR_FORK_EPOCH = 1.Epoch
res.BELLATRIX_FORK_EPOCH = 2.Epoch res.BELLATRIX_FORK_EPOCH = 2.Epoch
res.CAPELLA_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 1).Epoch res.CAPELLA_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 1).Epoch
res.DENEB_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 2).Epoch res.DENEB_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 2).Epoch
debugRaiseAssert "light client test; when this is tested, enable Electra"
res.ELECTRA_FORK_EPOCH = FAR_FUTURE_EPOCH
res res
altairStartSlot = cfg.ALTAIR_FORK_EPOCH.start_slot altairStartSlot = cfg.ALTAIR_FORK_EPOCH.start_slot

View File

@ -28,12 +28,14 @@ suite "Light client processor" & preset():
highPeriod = 5.SyncCommitteePeriod highPeriod = 5.SyncCommitteePeriod
let let
cfg = block: # Fork schedule so that each `LightClientDataFork` is covered cfg = block: # Fork schedule so that each `LightClientDataFork` is covered
static: doAssert ConsensusFork.high == ConsensusFork.Deneb static: doAssert ConsensusFork.high == ConsensusFork.Electra
var res = defaultRuntimeConfig var res = defaultRuntimeConfig
res.ALTAIR_FORK_EPOCH = 1.Epoch res.ALTAIR_FORK_EPOCH = 1.Epoch
res.BELLATRIX_FORK_EPOCH = 2.Epoch res.BELLATRIX_FORK_EPOCH = 2.Epoch
res.CAPELLA_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 1).Epoch res.CAPELLA_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 1).Epoch
res.DENEB_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 2).Epoch res.DENEB_FORK_EPOCH = (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * 2).Epoch
res.ELECTRA_FORK_EPOCH = FAR_FUTURE_EPOCH
debugRaiseAssert "Light client processor test, once define/works add Electra to tests"
res res
const numValidators = SLOTS_PER_EPOCH const numValidators = SLOTS_PER_EPOCH

View File

@ -17,6 +17,7 @@ import
from std/os import getEnv, osErrorMsg from std/os import getEnv, osErrorMsg
{.push raises: [].}
{.used.} {.used.}
const const
@ -97,26 +98,33 @@ func init(T: type ForkedBeaconBlock, contents: ProduceBlockResponseV2): T =
return ForkedBeaconBlock.init(contents.capellaData) return ForkedBeaconBlock.init(contents.capellaData)
of ConsensusFork.Deneb: of ConsensusFork.Deneb:
return ForkedBeaconBlock.init(contents.denebData.`block`) return ForkedBeaconBlock.init(contents.denebData.`block`)
of ConsensusFork.Electra:
return ForkedBeaconBlock.init(contents.electraData.`block`)
proc getBlock(fork: ConsensusFork, proc getBlock(fork: ConsensusFork,
feeRecipient = SigningExpectedFeeRecipient): ForkedBeaconBlock = feeRecipient = SigningExpectedFeeRecipient): ForkedBeaconBlock =
let try:
blckData = debugRaiseAssert "getBlock; ConsensusFork.Electra shouldn't use DenebBlockContents, but not tested, so do that together"
case fork let
of ConsensusFork.Phase0: Phase0Block blckData =
of ConsensusFork.Altair: AltairBlock case fork
of ConsensusFork.Bellatrix: BellatrixBlock % [feeRecipient] of ConsensusFork.Phase0: Phase0Block
of ConsensusFork.Capella: CapellaBlock % [feeRecipient] of ConsensusFork.Altair: AltairBlock
of ConsensusFork.Deneb: DenebBlockContents % [feeRecipient] of ConsensusFork.Bellatrix: BellatrixBlock % [feeRecipient]
contentType = ContentTypeData( of ConsensusFork.Capella: CapellaBlock % [feeRecipient]
mediaType: MediaType.init("application/json")) of ConsensusFork.Deneb: DenebBlockContents % [feeRecipient]
of ConsensusFork.Electra: DenebBlockContents % [feeRecipient]
contentType = ContentTypeData(
mediaType: MediaType.init("application/json"))
let b = decodeBytes(ProduceBlockResponseV2, let b = decodeBytes(ProduceBlockResponseV2,
blckData.toOpenArrayByte(0, len(blckData) - 1), blckData.toOpenArrayByte(0, len(blckData) - 1),
Opt.some(contentType), Opt.some(contentType),
$fork).tryGet() $fork).tryGet()
ForkedBeaconBlock.init(b) ForkedBeaconBlock.init(b)
except ValueError:
raiseAssert "unreachable"
func init(t: typedesc[Web3SignerForkedBeaconBlock], func init(t: typedesc[Web3SignerForkedBeaconBlock],
forked: ForkedBeaconBlock): Web3SignerForkedBeaconBlock = forked: ForkedBeaconBlock): Web3SignerForkedBeaconBlock =
@ -135,6 +143,11 @@ func init(t: typedesc[Web3SignerForkedBeaconBlock],
Web3SignerForkedBeaconBlock( Web3SignerForkedBeaconBlock(
kind: ConsensusFork.Deneb, kind: ConsensusFork.Deneb,
data: forked.denebData.toBeaconBlockHeader) data: forked.denebData.toBeaconBlockHeader)
of ConsensusFork.Electra:
debugRaiseAssert "init typedesc[Web3SignerForkedBeaconBlock]"
Web3SignerForkedBeaconBlock(
kind: ConsensusFork.Deneb,
data: forked.electraData.toBeaconBlockHeader)
proc createKeystore(dataDir, pubkey, proc createKeystore(dataDir, pubkey,
store, password: string): Result[void, string] = store, password: string): Result[void, string] =

View File

@ -64,7 +64,7 @@ proc getTestStates*(
info = ForkedEpochInfo() info = ForkedEpochInfo()
cfg = defaultRuntimeConfig cfg = defaultRuntimeConfig
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb static: doAssert high(ConsensusFork) == ConsensusFork.Electra
if consensusFork >= ConsensusFork.Altair: if consensusFork >= ConsensusFork.Altair:
cfg.ALTAIR_FORK_EPOCH = 1.Epoch cfg.ALTAIR_FORK_EPOCH = 1.Epoch
if consensusFork >= ConsensusFork.Bellatrix: if consensusFork >= ConsensusFork.Bellatrix:
@ -73,6 +73,8 @@ proc getTestStates*(
cfg.CAPELLA_FORK_EPOCH = 3.Epoch cfg.CAPELLA_FORK_EPOCH = 3.Epoch
if consensusFork >= ConsensusFork.Deneb: if consensusFork >= ConsensusFork.Deneb:
cfg.DENEB_FORK_EPOCH = 4.Epoch cfg.DENEB_FORK_EPOCH = 4.Epoch
if consensusFork >= ConsensusFork.Electra:
cfg.DENEB_FORK_EPOCH = 5.Epoch
for i, epoch in stateEpochs: for i, epoch in stateEpochs:
let slot = epoch.Epoch.start_slot let slot = epoch.Epoch.start_slot