use fcU V3 in Deneb/Cancun (#5293)

This commit is contained in:
tersec 2023-08-15 23:00:35 +00:00 committed by GitHub
parent c3584a9ea7
commit 230626306a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 31 deletions

View File

@ -74,7 +74,9 @@ proc initLightClient*(
payloadAttributes = none attributes)
case node.dag.cfg.consensusForkAtEpoch(blck.message.slot.epoch)
of ConsensusFork.Capella, ConsensusFork.Deneb:
of ConsensusFork.Deneb:
callForkchoiceUpdated(PayloadAttributesV3)
of 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

View File

@ -172,7 +172,9 @@ proc updateExecutionClientHead(self: ref ConsensusManager,
# 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:
of ConsensusFork.Deneb:
callForkchoiceUpdated(PayloadAttributesV3)
of 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:
@ -396,12 +398,21 @@ proc runProposalForkchoiceUpdated*(
debug "Fork-choice updated for proposal", status
static: doAssert high(ConsensusFork) == ConsensusFork.Deneb
when consensusFork >= ConsensusFork.Capella:
when consensusFork >= ConsensusFork.Deneb:
callForkchoiceUpdated(PayloadAttributesV3(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData,
suggestedFeeRecipient: feeRecipient,
withdrawals:
toEngineWithdrawals get_expected_withdrawals(forkyState.data),
parentBeaconBlockRoot: beaconHead.blck.bid.root.asBlockHash))
elif consensusFork >= ConsensusFork.Capella:
callForkchoiceUpdated(PayloadAttributesV2(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData,
suggestedFeeRecipient: feeRecipient,
withdrawals: toEngineWithdrawals get_expected_withdrawals(forkyState.data)))
withdrawals:
toEngineWithdrawals get_expected_withdrawals(forkyState.data)))
else:
callForkchoiceUpdated(PayloadAttributesV1(
timestamp: Quantity timestamp,

View File

@ -140,7 +140,7 @@ type
headBlockHash*: Eth2Digest
safeBlockHash*: Eth2Digest
finalizedBlockHash*: Eth2Digest
payloadAttributes*: PayloadAttributesV2
payloadAttributes*: PayloadAttributesV3
ELManager* = ref object
eth1Network: Option[Eth1Network]
@ -767,7 +767,8 @@ func areSameAs(expectedParams: Option[NextExpectedPayloadParams],
timestamp: uint64,
randomData: Eth2Digest,
feeRecipient: Eth1Address,
withdrawals: seq[WithdrawalV1]): bool =
withdrawals: seq[WithdrawalV1],
parentBeaconBlockRoot: FixedBytes[32]): bool =
expectedParams.isSome and
expectedParams.get.headBlockHash == latestHead and
expectedParams.get.safeBlockHash == latestSafe and
@ -775,17 +776,22 @@ func areSameAs(expectedParams: Option[NextExpectedPayloadParams],
expectedParams.get.payloadAttributes.timestamp.uint64 == timestamp and
expectedParams.get.payloadAttributes.prevRandao.bytes == randomData.data and
expectedParams.get.payloadAttributes.suggestedFeeRecipient == feeRecipient and
expectedParams.get.payloadAttributes.withdrawals == withdrawals
expectedParams.get.payloadAttributes.withdrawals == withdrawals and
expectedParams.get.payloadAttributes.parentBeaconBlockRoot ==
parentBeaconBlockRoot
proc forkchoiceUpdated(rpcClient: RpcClient,
state: ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1] |
Option[PayloadAttributesV2]):
Option[PayloadAttributesV2] |
Option[PayloadAttributesV3]):
Future[ForkchoiceUpdatedResponse] =
when payloadAttributes is Option[PayloadAttributesV1]:
rpcClient.engine_forkchoiceUpdatedV1(state, payloadAttributes)
elif payloadAttributes is Option[PayloadAttributesV2]:
rpcClient.engine_forkchoiceUpdatedV2(state, payloadAttributes)
elif payloadAttributes is Option[PayloadAttributesV3]:
rpcClient.engine_forkchoiceUpdatedV3(state, payloadAttributes)
else:
static: doAssert false
@ -799,6 +805,7 @@ proc getPayloadFromSingleEL(
connection: ELConnection,
GetPayloadResponseType: type,
isForkChoiceUpToDate: bool,
consensusHead: Eth2Digest,
headBlock, safeBlock, finalizedBlock: Eth2Digest,
timestamp: uint64,
randomData: Eth2Digest,
@ -822,8 +829,7 @@ proc getPayloadFromSingleEL(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient))
elif GetPayloadResponseType is engine_api.GetPayloadV2Response or
GetPayloadResponseType is engine_api.GetPayloadV3Response:
elif GetPayloadResponseType is engine_api.GetPayloadV2Response:
let response = await rpcClient.forkchoiceUpdated(
ForkchoiceStateV1(
headBlockHash: headBlock.asBlockHash,
@ -834,6 +840,18 @@ proc getPayloadFromSingleEL(
prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient,
withdrawals: withdrawals))
elif GetPayloadResponseType is engine_api.GetPayloadV3Response:
let response = await rpcClient.forkchoiceUpdated(
ForkchoiceStateV1(
headBlockHash: headBlock.asBlockHash,
safeBlockHash: safeBlock.asBlockHash,
finalizedBlockHash: finalizedBlock.asBlockHash),
some PayloadAttributesV3(
timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData.data,
suggestedFeeRecipient: suggestedFeeRecipient,
withdrawals: withdrawals,
parentBeaconBlockRoot: consensusHead.asBlockHash))
else:
static: doAssert false
@ -849,7 +867,8 @@ proc getPayloadFromSingleEL(
raise newException(CatchableError, "No confirmed execution head yet")
when GetPayloadResponseType is BellatrixExecutionPayloadWithValue:
let payload= await engine_api.getPayload(rpcClient, ExecutionPayloadV1, payloadId)
let payload =
await engine_api.getPayload(rpcClient, ExecutionPayloadV1, payloadId)
return BellatrixExecutionPayloadWithValue(
executionPayload: payload,
blockValue: computeBlockValue payload)
@ -891,6 +910,7 @@ template toFork(T: type ExecutionPayloadV3): ConsensusFork =
proc getPayload*(m: ELManager,
PayloadType: type ForkyExecutionPayloadForSigning,
consensusHead: Eth2Digest,
headBlock, safeBlock, finalizedBlock: Eth2Digest,
timestamp: uint64,
randomData: Eth2Digest,
@ -902,9 +922,10 @@ proc getPayload*(m: ELManager,
let
engineApiWithdrawals = toEngineWithdrawals withdrawals
let isFcUpToDate = m.nextExpectedPayloadParams.areSameAs(
headBlock, safeBlock, finalizedBlock, timestamp,
randomData, suggestedFeeRecipient, engineApiWithdrawals)
isFcUpToDate = m.nextExpectedPayloadParams.areSameAs(
headBlock, safeBlock, finalizedBlock, timestamp,
randomData, suggestedFeeRecipient, engineApiWithdrawals,
consensusHead.asBlockHash)
# `getPayloadFromSingleEL` may introduce additional latency
const extraProcessingOverhead = 500.milliseconds
@ -913,7 +934,7 @@ proc getPayload*(m: ELManager,
deadline = sleepAsync(timeout)
requests = m.elConnections.mapIt(it.getPayloadFromSingleEL(
EngineApiResponseType(PayloadType),
isFcUpToDate, headBlock, safeBlock, finalizedBlock,
isFcUpToDate, consensusHead, headBlock, safeBlock, finalizedBlock,
timestamp, randomData, suggestedFeeRecipient, engineApiWithdrawals
))
requestsCompleted = allFutures(requests)
@ -1221,7 +1242,8 @@ proc forkchoiceUpdatedForSingleEL(
connection: ELConnection,
state: ref ForkchoiceStateV1,
payloadAttributes: Option[PayloadAttributesV1] |
Option[PayloadAttributesV2]):
Option[PayloadAttributesV2] |
Option[PayloadAttributesV3]):
Future[PayloadStatusV1] {.async.} =
let
rpcClient = await connection.connectedRpcClient()
@ -1242,7 +1264,8 @@ proc forkchoiceUpdated*(m: ELManager,
headBlockHash, safeBlockHash,
finalizedBlockHash: Eth2Digest,
payloadAttributes: Option[PayloadAttributesV1] |
Option[PayloadAttributesV2]):
Option[PayloadAttributesV2] |
Option[PayloadAttributesV3]):
Future[(PayloadExecutionStatus, Option[BlockHash])] {.async.} =
doAssert not headBlockHash.isZero
@ -1260,24 +1283,37 @@ proc forkchoiceUpdated*(m: ELManager,
if m.elConnections.len == 0:
return (PayloadExecutionStatus.syncing, none BlockHash)
when payloadAttributes is Option[PayloadAttributesV2]:
template payloadAttributesV2(): auto =
when payloadAttributes is Option[PayloadAttributesV3]:
template payloadAttributesV3(): auto =
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 =
(static(default(PayloadAttributesV3)))
elif payloadAttributes is Option[PayloadAttributesV2]:
template payloadAttributesV3(): auto =
if payloadAttributes.isSome:
PayloadAttributesV2(
PayloadAttributesV3(
timestamp: payloadAttributes.get.timestamp,
prevRandao: payloadAttributes.get.prevRandao,
suggestedFeeRecipient: payloadAttributes.get.suggestedFeeRecipient,
withdrawals: @[])
withdrawals: payloadAttributes.get.withdrawals,
parentBeaconBlockRoot: static(default(FixedBytes[32])))
else:
# As timestamp and prevRandao are both 0, won't false-positive match
(static(default(PayloadAttributesV2)))
(static(default(PayloadAttributesV3)))
elif payloadAttributes is Option[PayloadAttributesV1]:
template payloadAttributesV3(): auto =
if payloadAttributes.isSome:
PayloadAttributesV3(
timestamp: payloadAttributes.get.timestamp,
prevRandao: payloadAttributes.get.prevRandao,
suggestedFeeRecipient: payloadAttributes.get.suggestedFeeRecipient,
withdrawals: @[],
parentBeaconBlockRoot: static(default(FixedBytes[32])))
else:
# As timestamp and prevRandao are both 0, won't false-positive match
(static(default(PayloadAttributesV3)))
else:
static: doAssert false
@ -1319,7 +1355,7 @@ proc forkchoiceUpdated*(m: ELManager,
headBlockHash: headBlockHash,
safeBlockHash: safeBlockHash,
finalizedBlockHash: finalizedBlockHash,
payloadAttributes: payloadAttributesV2))
payloadAttributes: payloadAttributesV3))
if responseProcessor.disagreementAlreadyDetected:
return (PayloadExecutionStatus.invalid, none BlockHash)

View File

@ -233,8 +233,8 @@ proc storeBackfillBlock(
res
from web3/engine_api_types import
PayloadAttributesV1, PayloadAttributesV2, PayloadExecutionStatus,
PayloadStatusV1
PayloadAttributesV1, PayloadAttributesV2, PayloadAttributesV3,
PayloadExecutionStatus, PayloadStatusV1
from ../el/el_manager import
ELManager, forkchoiceUpdated, hasConnection, hasProperlyConfiguredConnection,
sendNewPayload
@ -616,7 +616,9 @@ proc storeBlock*(
case self.consensusManager.dag.cfg.consensusForkAtEpoch(
newHead.get.blck.bid.slot.epoch)
of ConsensusFork.Capella, ConsensusFork.Deneb:
of ConsensusFork.Deneb:
callForkchoiceUpdated(PayloadAttributesV3)
of 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:

View File

@ -311,8 +311,8 @@ proc getExecutionPayload(
else:
@[]
payload = await node.elManager.getPayload(
PayloadType, executionHead, latestSafe, latestFinalized,
timestamp, random, feeRecipient, withdrawals)
PayloadType, beaconHead.blck.bid.root, executionHead, latestSafe,
latestFinalized, timestamp, random, feeRecipient, withdrawals)
if payload.isNone:
error "Failed to obtain execution payload from EL",