always use fcUV2 in shapella even for non-proposer fcUs (#4817)
* always use fcUV2 in shapella even for non-proposer fcUs * avoid template/proc naming conflict with libp2p/signed_envelope.nim having a payload proc
This commit is contained in:
parent
addb7bda2f
commit
75be7d267d
|
@ -47,11 +47,11 @@ proc initLightClient*(
|
|||
withBlck(signedBlock):
|
||||
when consensusFork >= ConsensusFork.Bellatrix:
|
||||
if blck.message.is_execution_block:
|
||||
template payload(): auto = blck.message.body.execution_payload
|
||||
template blckPayload(): auto = blck.message.body.execution_payload
|
||||
|
||||
if not payload.block_hash.isZero:
|
||||
if not blckPayload.block_hash.isZero:
|
||||
# engine_newPayloadV1
|
||||
discard await node.elManager.newExecutionPayload(payload)
|
||||
discard await node.elManager.newExecutionPayload(blckPayload)
|
||||
|
||||
# Retain optimistic head for other `forkchoiceUpdated` callers.
|
||||
# May temporarily block `forkchoiceUpdatedV1` calls, e.g., Geth:
|
||||
|
@ -60,15 +60,32 @@ proc initLightClient*(
|
|||
# Once DAG sync catches up or as new optimistic heads are fetched
|
||||
# the situation recovers
|
||||
node.consensusManager[].setOptimisticHead(
|
||||
blck.toBlockId(), payload.block_hash)
|
||||
blck.toBlockId(), blckPayload.block_hash)
|
||||
|
||||
# engine_forkchoiceUpdatedV1
|
||||
# engine_forkchoiceUpdatedV1 or engine_forkchoiceUpdatedV2,
|
||||
# depending on pre or post-Shapella
|
||||
let beaconHead = node.attestationPool[].getBeaconHead(nil)
|
||||
discard await node.elManager.forkchoiceUpdated(
|
||||
headBlockHash = payload.block_hash,
|
||||
safeBlockHash = beaconHead.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = beaconHead.finalizedExecutionPayloadHash,
|
||||
payloadAttributes = NoPayloadAttributes)
|
||||
|
||||
template callForkchoiceUpdated(attributes: untyped) =
|
||||
discard await node.elManager.forkchoiceUpdated(
|
||||
headBlockHash = blckPayload.block_hash,
|
||||
safeBlockHash = beaconHead.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = beaconHead.finalizedExecutionPayloadHash,
|
||||
payloadAttributes = none attributes)
|
||||
|
||||
case node.dag.cfg.consensusForkAtEpoch(beaconHead.blck.bid.slot.epoch)
|
||||
of ConsensusFork.Capella, ConsensusFork.Deneb:
|
||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#specification-1
|
||||
# Consensus layer client MUST call this method instead of
|
||||
# `engine_forkchoiceUpdatedV1` under any of the following
|
||||
# conditions:
|
||||
# `headBlockHash` references a block which `timestamp` is
|
||||
# greater or equal to the Shanghai timestamp
|
||||
callForkchoiceUpdated(PayloadAttributesV2)
|
||||
of ConsensusFork.Bellatrix:
|
||||
callForkchoiceUpdated(PayloadAttributesV1)
|
||||
of ConsensusFork.Phase0, ConsensusFork.Altair:
|
||||
discard
|
||||
else: discard
|
||||
|
||||
optimisticProcessor = initOptimisticProcessor(
|
||||
|
|
|
@ -164,13 +164,25 @@ proc updateExecutionClientHead(self: ref ConsensusManager,
|
|||
self.dag.markBlockVerified(self.quarantine[], newHead.blck.root)
|
||||
return Opt[void].ok()
|
||||
|
||||
# Can't use dag.head here because it hasn't been updated yet
|
||||
let (payloadExecutionStatus, latestValidHash) =
|
||||
template callForkchoiceUpdated(attributes: untyped): auto =
|
||||
await self.elManager.forkchoiceUpdated(
|
||||
headBlockHash = headExecutionPayloadHash,
|
||||
safeBlockHash = newHead.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = newHead.finalizedExecutionPayloadHash,
|
||||
payloadAttributes = NoPayloadAttributes)
|
||||
payloadAttributes = none attributes)
|
||||
|
||||
# Can't use dag.head here because it hasn't been updated yet
|
||||
let (payloadExecutionStatus, latestValidHash) =
|
||||
case self.dag.cfg.consensusForkAtEpoch(newHead.blck.bid.slot.epoch)
|
||||
of ConsensusFork.Capella, ConsensusFork.Deneb:
|
||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#specification-1
|
||||
# Consensus layer client MUST call this method instead of
|
||||
# `engine_forkchoiceUpdatedV1` under any of the following conditions:
|
||||
# `headBlockHash` references a block which `timestamp` is greater or
|
||||
# equal to the Shanghai timestamp
|
||||
callForkchoiceUpdated(PayloadAttributesV2)
|
||||
of ConsensusFork.Phase0, ConsensusFork.Altair, ConsensusFork.Bellatrix:
|
||||
callForkchoiceUpdated(PayloadAttributesV1)
|
||||
|
||||
case payloadExecutionStatus
|
||||
of PayloadExecutionStatus.valid:
|
||||
|
@ -360,7 +372,7 @@ proc runProposalForkchoiceUpdated*(
|
|||
let (status, _) = await self.elManager.forkchoiceUpdated(
|
||||
headBlockHash, safeBlockHash,
|
||||
beaconHead.finalizedExecutionPayloadHash,
|
||||
payloadAttributes = fcPayloadAttributes)
|
||||
payloadAttributes = some fcPayloadAttributes)
|
||||
debug "Fork-choice updated for proposal", status
|
||||
|
||||
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb
|
||||
|
|
|
@ -133,10 +133,6 @@ type
|
|||
hasConsensusViolation: bool
|
||||
## The local chain contradicts the observed consensus on the network
|
||||
|
||||
NoPayloadAttributesType = object
|
||||
## A type with exactly one value, and which is not constructed via a `nil`
|
||||
## value for a ref object, which which Nim 1.6 crashes with an ICE.
|
||||
|
||||
NextExpectedPayloadParams* = object
|
||||
headBlockHash*: Eth2Digest
|
||||
safeBlockHash*: Eth2Digest
|
||||
|
@ -255,9 +251,6 @@ type
|
|||
GetPayloadV2Response |
|
||||
CancunExecutionPayloadAndBlobs
|
||||
|
||||
const
|
||||
NoPayloadAttributes* = default(NoPayloadAttributesType)
|
||||
|
||||
declareCounter failed_web3_requests,
|
||||
"Failed web3 requests"
|
||||
|
||||
|
@ -764,16 +757,13 @@ func areSameAs(expectedParams: Option[NextExpectedPayloadParams],
|
|||
|
||||
proc forkchoiceUpdated(rpcClient: RpcClient,
|
||||
state: ForkchoiceStateV1,
|
||||
payloadAttributes: PayloadAttributesV1 |
|
||||
PayloadAttributesV2 |
|
||||
NoPayloadAttributesType):
|
||||
payloadAttributes: Option[PayloadAttributesV1] |
|
||||
Option[PayloadAttributesV2]):
|
||||
Future[ForkchoiceUpdatedResponse] =
|
||||
when payloadAttributes is NoPayloadAttributesType:
|
||||
rpcClient.engine_forkchoiceUpdatedV1(state, none PayloadAttributesV1)
|
||||
elif payloadAttributes is PayloadAttributesV1:
|
||||
rpcClient.engine_forkchoiceUpdatedV1(state, some payloadAttributes)
|
||||
elif payloadAttributes is PayloadAttributesV2:
|
||||
rpcClient.engine_forkchoiceUpdatedV2(state, some payloadAttributes)
|
||||
when payloadAttributes is Option[PayloadAttributesV1]:
|
||||
rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes)
|
||||
elif payloadAttributes is Option[PayloadAttributesV2]:
|
||||
rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes)
|
||||
else:
|
||||
static: doAssert false
|
||||
|
||||
|
@ -806,7 +796,7 @@ proc getPayloadFromSingleEL(
|
|||
headBlockHash: headBlock.asBlockHash,
|
||||
safeBlockHash: safeBlock.asBlockHash,
|
||||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||
PayloadAttributesV1(
|
||||
some PayloadAttributesV1(
|
||||
timestamp: Quantity timestamp,
|
||||
prevRandao: FixedBytes[32] randomData.data,
|
||||
suggestedFeeRecipient: suggestedFeeRecipient))
|
||||
|
@ -816,7 +806,7 @@ proc getPayloadFromSingleEL(
|
|||
headBlockHash: headBlock.asBlockHash,
|
||||
safeBlockHash: safeBlock.asBlockHash,
|
||||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||
PayloadAttributesV2(
|
||||
some PayloadAttributesV2(
|
||||
timestamp: Quantity timestamp,
|
||||
prevRandao: FixedBytes[32] randomData.data,
|
||||
suggestedFeeRecipient: suggestedFeeRecipient,
|
||||
|
@ -1204,8 +1194,8 @@ proc sendNewPayload*(m: ELManager,
|
|||
proc forkchoiceUpdatedForSingleEL(
|
||||
connection: ELConnection,
|
||||
state: ref ForkchoiceStateV1,
|
||||
payloadAttributes: PayloadAttributesV1 | PayloadAttributesV2 |
|
||||
NoPayloadAttributesType):
|
||||
payloadAttributes: Option[PayloadAttributesV1] |
|
||||
Option[PayloadAttributesV2]):
|
||||
Future[PayloadStatusV1] {.async.} =
|
||||
let
|
||||
rpcClient = await connection.connectedRpcClient()
|
||||
|
@ -1223,9 +1213,10 @@ proc forkchoiceUpdatedForSingleEL(
|
|||
return response.payloadStatus
|
||||
|
||||
proc forkchoiceUpdated*(m: ELManager,
|
||||
headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest,
|
||||
payloadAttributes: PayloadAttributesV1 | PayloadAttributesV2 |
|
||||
NoPayloadAttributesType):
|
||||
headBlockHash, safeBlockHash,
|
||||
finalizedBlockHash: Eth2Digest,
|
||||
payloadAttributes: Option[PayloadAttributesV1] |
|
||||
Option[PayloadAttributesV2]):
|
||||
Future[(PayloadExecutionStatus, Option[BlockHash])] {.async.} =
|
||||
doAssert not headBlockHash.isZero
|
||||
|
||||
|
@ -1243,18 +1234,24 @@ proc forkchoiceUpdated*(m: ELManager,
|
|||
if m.elConnections.len == 0:
|
||||
return (PayloadExecutionStatus.syncing, none BlockHash)
|
||||
|
||||
when payloadAttributes is PayloadAttributesV2:
|
||||
template payloadAttributesV2(): auto = payloadAttributes
|
||||
elif payloadAttributes is PayloadAttributesV1:
|
||||
template payloadAttributesV2(): auto = PayloadAttributesV2(
|
||||
timestamp: payloadAttributes.timestamp,
|
||||
prevRandao: payloadAttributes.prevRandao,
|
||||
suggestedFeeRecipient: payloadAttributes.suggestedFeeRecipient,
|
||||
withdrawals: @[])
|
||||
elif payloadAttributes is NoPayloadAttributesType:
|
||||
when payloadAttributes is Option[PayloadAttributesV2]:
|
||||
template payloadAttributesV2(): auto =
|
||||
# Because timestamp and prevRandao are both 0, won't false-positive match
|
||||
(static(default(PayloadAttributesV2)))
|
||||
if payloadAttributes.isSome:
|
||||
payloadAttributes.get
|
||||
else:
|
||||
# As timestamp and prevRandao are both 0, won't false-positive match
|
||||
(static(default(PayloadAttributesV2)))
|
||||
elif payloadAttributes is Option[PayloadAttributesV1]:
|
||||
template payloadAttributesV2(): auto =
|
||||
if payloadAttributes.isSome:
|
||||
PayloadAttributesV2(
|
||||
timestamp: payloadAttributes.get.timestamp,
|
||||
prevRandao: payloadAttributes.get.prevRandao,
|
||||
suggestedFeeRecipient: payloadAttributes.get.suggestedFeeRecipient,
|
||||
withdrawals: @[])
|
||||
else:
|
||||
# As timestamp and prevRandao are both 0, won't false-positive match
|
||||
(static(default(PayloadAttributesV2)))
|
||||
else:
|
||||
static: doAssert false
|
||||
|
||||
|
|
|
@ -214,14 +214,14 @@ proc storeBackfillBlock(
|
|||
|
||||
res
|
||||
|
||||
|
||||
from web3/engine_api_types import PayloadExecutionStatus, PayloadStatusV1
|
||||
from web3/engine_api_types import
|
||||
PayloadAttributesV1, PayloadAttributesV2, PayloadExecutionStatus,
|
||||
PayloadStatusV1
|
||||
from ../eth1/eth1_monitor import
|
||||
ELManager, NoPayloadAttributes, asEngineExecutionPayload, sendNewPayload,
|
||||
forkchoiceUpdated
|
||||
ELManager, asEngineExecutionPayload, sendNewPayload, forkchoiceUpdated
|
||||
|
||||
proc expectValidForkchoiceUpdated(
|
||||
elManager: ELManager,
|
||||
elManager: ELManager, headBlockPayloadAttributesType: typedesc,
|
||||
headBlockHash, safeBlockHash, finalizedBlockHash: Eth2Digest,
|
||||
receivedBlock: ForkySignedBeaconBlock): Future[void] {.async.} =
|
||||
let
|
||||
|
@ -229,7 +229,7 @@ proc expectValidForkchoiceUpdated(
|
|||
headBlockHash = headBlockHash,
|
||||
safeBlockHash = safeBlockHash,
|
||||
finalizedBlockHash = finalizedBlockHash,
|
||||
payloadAttributes = NoPayloadAttributes)
|
||||
payloadAttributes = none headBlockPayloadAttributesType)
|
||||
receivedExecutionBlockHash =
|
||||
when typeof(receivedBlock).toFork >= ConsensusFork.Bellatrix:
|
||||
receivedBlock.message.body.execution_payload.block_hash
|
||||
|
@ -525,7 +525,7 @@ proc storeBlock*(
|
|||
# > Client software MAY skip an update of the forkchoice state and MUST
|
||||
# NOT begin a payload build process if `forkchoiceState.headBlockHash`
|
||||
# references an ancestor of the head of canonical chain.
|
||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.2/src/engine/paris.md#specification-1
|
||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#specification-1
|
||||
#
|
||||
# However, in practice, an EL client may not have completed importing all
|
||||
# block headers, so may be unaware of a block's ancestor status.
|
||||
|
@ -534,11 +534,27 @@ proc storeBlock*(
|
|||
# - "Beacon chain gapped" from DAG head to optimistic head,
|
||||
# - followed by "Beacon chain reorged" from optimistic head back to DAG.
|
||||
self.consensusManager[].updateHead(newHead.get.blck)
|
||||
discard await elManager.forkchoiceUpdated(
|
||||
headBlockHash = self.consensusManager[].optimisticExecutionPayloadHash,
|
||||
safeBlockHash = newHead.get.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = newHead.get.finalizedExecutionPayloadHash,
|
||||
payloadAttributes = NoPayloadAttributes)
|
||||
|
||||
template callForkchoiceUpdated(attributes: untyped) =
|
||||
discard await elManager.forkchoiceUpdated(
|
||||
headBlockHash = self.consensusManager[].optimisticExecutionPayloadHash,
|
||||
safeBlockHash = newHead.get.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = newHead.get.finalizedExecutionPayloadHash,
|
||||
payloadAttributes = none attributes)
|
||||
|
||||
case self.consensusManager.dag.cfg.consensusForkAtEpoch(
|
||||
newHead.get.blck.bid.slot.epoch)
|
||||
of ConsensusFork.Capella, ConsensusFork.Deneb:
|
||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#specification-1
|
||||
# Consensus layer client MUST call this method instead of
|
||||
# `engine_forkchoiceUpdatedV1` under any of the following conditions:
|
||||
# `headBlockHash` references a block which `timestamp` is greater or
|
||||
# equal to the Shanghai timestamp
|
||||
callForkchoiceUpdated(PayloadAttributesV2)
|
||||
of ConsensusFork.Bellatrix:
|
||||
callForkchoiceUpdated(PayloadAttributesV1)
|
||||
of ConsensusFork.Phase0, ConsensusFork.Altair:
|
||||
discard
|
||||
else:
|
||||
let
|
||||
headExecutionPayloadHash =
|
||||
|
@ -557,11 +573,22 @@ proc storeBlock*(
|
|||
|
||||
if self.consensusManager.checkNextProposer(wallSlot).isNone:
|
||||
# No attached validator is next proposer, so use non-proposal fcU
|
||||
await elManager.expectValidForkchoiceUpdated(
|
||||
headBlockHash = headExecutionPayloadHash,
|
||||
safeBlockHash = newHead.get.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = newHead.get.finalizedExecutionPayloadHash,
|
||||
receivedBlock = signedBlock)
|
||||
|
||||
template callForkchoiceUpdated(payloadAttributeType: untyped): auto =
|
||||
await elManager.expectValidForkchoiceUpdated(
|
||||
headBlockPayloadAttributesType = payloadAttributeType,
|
||||
headBlockHash = headExecutionPayloadHash,
|
||||
safeBlockHash = newHead.get.safeExecutionPayloadHash,
|
||||
finalizedBlockHash = newHead.get.finalizedExecutionPayloadHash,
|
||||
receivedBlock = signedBlock)
|
||||
|
||||
case self.consensusManager.dag.cfg.consensusForkAtEpoch(
|
||||
newHead.get.blck.bid.slot.epoch)
|
||||
of ConsensusFork.Capella, ConsensusFork.Deneb:
|
||||
callForkchoiceUpdated(payloadAttributeType = PayloadAttributesV2)
|
||||
of ConsensusFork.Phase0, ConsensusFork.Altair,
|
||||
ConsensusFork.Bellatrix:
|
||||
callForkchoiceUpdated(payloadAttributeType = PayloadAttributesV1)
|
||||
else:
|
||||
# Some attached validator is next proposer, so prepare payload. As
|
||||
# updateHead() updated the DAG head, runProposalForkchoiceUpdated,
|
||||
|
|
|
@ -105,7 +105,12 @@ programMain:
|
|||
opt = signedBlock.toBlockId(),
|
||||
wallSlot = getBeaconTime().slotOrZero
|
||||
withBlck(signedBlock):
|
||||
when consensusFork >= ConsensusFork.Bellatrix:
|
||||
when consensusFork >= ConsensusFork.Capella:
|
||||
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/shanghai.md#specification-1
|
||||
# Consensus layer client MUST call this method instead of
|
||||
# `engine_forkchoiceUpdatedV1` under any of the following conditions:
|
||||
# `headBlockHash` references a block which `timestamp` is greater or
|
||||
# equal to the Shanghai timestamp
|
||||
if blck.message.is_execution_block:
|
||||
template payload(): auto = blck.message.body.execution_payload
|
||||
|
||||
|
@ -115,7 +120,18 @@ programMain:
|
|||
headBlockHash = payload.block_hash,
|
||||
safeBlockHash = payload.block_hash, # stub value
|
||||
finalizedBlockHash = ZERO_HASH,
|
||||
payloadAttributes = NoPayloadAttributes)
|
||||
payloadAttributes = none PayloadAttributesV2)
|
||||
elif consensusFork >= ConsensusFork.Bellatrix:
|
||||
if blck.message.is_execution_block:
|
||||
template payload(): auto = blck.message.body.execution_payload
|
||||
|
||||
if elManager != nil and not payload.block_hash.isZero:
|
||||
discard await elManager.newExecutionPayload(payload)
|
||||
discard await elManager.forkchoiceUpdated(
|
||||
headBlockHash = payload.block_hash,
|
||||
safeBlockHash = payload.block_hash, # stub value
|
||||
finalizedBlockHash = ZERO_HASH,
|
||||
payloadAttributes = none PayloadAttributesV1)
|
||||
else: discard
|
||||
optimisticProcessor = initOptimisticProcessor(
|
||||
getBeaconTime, optimisticHandler)
|
||||
|
|
Loading…
Reference in New Issue