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) payloadAttributes = none attributes)
case node.dag.cfg.consensusForkAtEpoch(blck.message.slot.epoch) 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 # 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 # Consensus layer client MUST call this method instead of
# `engine_forkchoiceUpdatedV1` under any of the following # `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 # Can't use dag.head here because it hasn't been updated yet
let (payloadExecutionStatus, latestValidHash) = let (payloadExecutionStatus, latestValidHash) =
case self.dag.cfg.consensusForkAtEpoch(newHead.blck.bid.slot.epoch) 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 # 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 # Consensus layer client MUST call this method instead of
# `engine_forkchoiceUpdatedV1` under any of the following conditions: # `engine_forkchoiceUpdatedV1` under any of the following conditions:
@ -396,12 +398,21 @@ proc runProposalForkchoiceUpdated*(
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.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( callForkchoiceUpdated(PayloadAttributesV2(
timestamp: Quantity timestamp, timestamp: Quantity timestamp,
prevRandao: FixedBytes[32] randomData, prevRandao: FixedBytes[32] randomData,
suggestedFeeRecipient: feeRecipient, suggestedFeeRecipient: feeRecipient,
withdrawals: toEngineWithdrawals get_expected_withdrawals(forkyState.data))) withdrawals:
toEngineWithdrawals get_expected_withdrawals(forkyState.data)))
else: else:
callForkchoiceUpdated(PayloadAttributesV1( callForkchoiceUpdated(PayloadAttributesV1(
timestamp: Quantity timestamp, timestamp: Quantity timestamp,

View File

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

View File

@ -233,8 +233,8 @@ proc storeBackfillBlock(
res res
from web3/engine_api_types import from web3/engine_api_types import
PayloadAttributesV1, PayloadAttributesV2, PayloadExecutionStatus, PayloadAttributesV1, PayloadAttributesV2, PayloadAttributesV3,
PayloadStatusV1 PayloadExecutionStatus, PayloadStatusV1
from ../el/el_manager import from ../el/el_manager import
ELManager, forkchoiceUpdated, hasConnection, hasProperlyConfiguredConnection, ELManager, forkchoiceUpdated, hasConnection, hasProperlyConfiguredConnection,
sendNewPayload sendNewPayload
@ -616,7 +616,9 @@ proc storeBlock*(
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.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 # 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 # Consensus layer client MUST call this method instead of
# `engine_forkchoiceUpdatedV1` under any of the following conditions: # `engine_forkchoiceUpdatedV1` under any of the following conditions:

View File

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