capella forkchoiceUpdated support (#4462)
* capella forkchoiceUpdated support * match V2 fcU with V2 getPayload
This commit is contained in:
parent
75d0e0d4c8
commit
47cb0f7991
|
@ -1,5 +1,5 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
@ -16,6 +16,8 @@ import
|
|||
../consensus_object_pools/[blockchain_dag, block_quarantine, attestation_pool],
|
||||
../eth1/eth1_monitor
|
||||
|
||||
from ../spec/beaconstate import get_expected_withdrawals
|
||||
from ../spec/datatypes/capella import Withdrawal
|
||||
from ../spec/eth2_apis/dynamic_fee_recipients import
|
||||
DynamicFeeRecipientsStore, getDynamicFeeRecipient
|
||||
from ../validators/keystore_management import
|
||||
|
@ -30,6 +32,7 @@ type
|
|||
finalizedBlockRoot*: Eth2Digest
|
||||
timestamp*: uint64
|
||||
feeRecipient*: Eth1Address
|
||||
withdrawals*: Opt[seq[Withdrawal]]
|
||||
|
||||
ConsensusManager* = object
|
||||
expectedSlot: Slot
|
||||
|
@ -360,6 +363,11 @@ proc runProposalForkchoiceUpdated*(
|
|||
get_randao_mix(forkyState.data, get_current_epoch(forkyState.data)).data
|
||||
feeRecipient = self[].getFeeRecipient(
|
||||
nextProposer, Opt.some(validatorIndex), nextWallSlot.epoch)
|
||||
withdrawals = withState(self.dag.headState):
|
||||
when stateFork >= BeaconStateFork.Capella:
|
||||
Opt.some get_expected_withdrawals(forkyState.data)
|
||||
else:
|
||||
Opt.none(seq[Withdrawal])
|
||||
beaconHead = self.attestationPool[].getBeaconHead(self.dag.head)
|
||||
headBlockRoot = self.dag.loadExecutionBlockRoot(beaconHead.blck)
|
||||
|
||||
|
@ -369,11 +377,9 @@ proc runProposalForkchoiceUpdated*(
|
|||
try:
|
||||
let fcResult = awaitWithTimeout(
|
||||
forkchoiceUpdated(
|
||||
self.eth1Monitor,
|
||||
headBlockRoot,
|
||||
beaconHead.safeExecutionPayloadHash,
|
||||
beaconHead.finalizedExecutionPayloadHash,
|
||||
timestamp, randomData, feeRecipient),
|
||||
self.eth1Monitor, headBlockRoot, beaconHead.safeExecutionPayloadHash,
|
||||
beaconHead.finalizedExecutionPayloadHash, timestamp, randomData,
|
||||
feeRecipient, withdrawals),
|
||||
FORKCHOICEUPDATED_TIMEOUT):
|
||||
debug "runProposalForkchoiceUpdated: forkchoiceUpdated timed out"
|
||||
ForkchoiceUpdatedResponse(
|
||||
|
@ -389,7 +395,8 @@ proc runProposalForkchoiceUpdated*(
|
|||
safeBlockRoot: beaconHead.safeExecutionPayloadHash,
|
||||
finalizedBlockRoot: beaconHead.finalizedExecutionPayloadHash,
|
||||
timestamp: timestamp,
|
||||
feeRecipient: feeRecipient)
|
||||
feeRecipient: feeRecipient,
|
||||
withdrawals: withdrawals)
|
||||
except CatchableError as err:
|
||||
error "Engine API fork-choice update failed", err = err.msg
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
@ -323,6 +323,24 @@ template asBlockHash*(x: Eth2Digest): BlockHash =
|
|||
|
||||
const weiInGwei = 1_000_000_000.u256
|
||||
|
||||
from ../spec/datatypes/capella import ExecutionPayload, Withdrawal
|
||||
|
||||
func asConsensusWithdrawal(w: WithdrawalV1): capella.Withdrawal =
|
||||
capella.Withdrawal(
|
||||
index: w.index.uint64,
|
||||
validator_index: w.validatorIndex.uint64,
|
||||
address: ExecutionAddress(data: w.address.distinctBase),
|
||||
|
||||
# TODO spec doesn't mention non-even-multiples, also overflow
|
||||
amount: (w.amount.u256 div weiInGwei).truncate(uint64))
|
||||
|
||||
func asEngineWithdrawal(w: capella.Withdrawal): WithdrawalV1 =
|
||||
WithdrawalV1(
|
||||
index: Quantity(w.index),
|
||||
validatorIndex: Quantity(w.validator_index),
|
||||
address: Address(w.address.data),
|
||||
amount: w.amount.u256 * weiInGwei)
|
||||
|
||||
func asConsensusExecutionPayload*(rpcExecutionPayload: ExecutionPayloadV1):
|
||||
bellatrix.ExecutionPayload =
|
||||
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
||||
|
@ -348,18 +366,10 @@ func asConsensusExecutionPayload*(rpcExecutionPayload: ExecutionPayloadV1):
|
|||
transactions: List[bellatrix.Transaction, MAX_TRANSACTIONS_PER_PAYLOAD].init(
|
||||
mapIt(rpcExecutionPayload.transactions, it.getTransaction)))
|
||||
|
||||
from ../spec/datatypes/capella import ExecutionPayload, Withdrawal
|
||||
|
||||
func asConsensusExecutionPayload*(rpcExecutionPayload: ExecutionPayloadV2):
|
||||
capella.ExecutionPayload =
|
||||
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
||||
bellatrix.Transaction.init(tt.distinctBase)
|
||||
template getConsensusWithdrawal(w: WithdrawalV1): capella.Withdrawal =
|
||||
capella.Withdrawal(
|
||||
index: w.index.uint64,
|
||||
validator_index: w.validatorIndex.uint64,
|
||||
address: ExecutionAddress(data: w.address.distinctBase),
|
||||
amount: (w.amount.u256 div weiInGwei).truncate(uint64)) # TODO spec doesn't mention non-even-multiples, also overflow
|
||||
|
||||
capella.ExecutionPayload(
|
||||
parent_hash: rpcExecutionPayload.parentHash.asEth2Digest,
|
||||
|
@ -381,7 +391,7 @@ func asConsensusExecutionPayload*(rpcExecutionPayload: ExecutionPayloadV2):
|
|||
transactions: List[bellatrix.Transaction, MAX_TRANSACTIONS_PER_PAYLOAD].init(
|
||||
mapIt(rpcExecutionPayload.transactions, it.getTransaction)),
|
||||
withdrawals: List[capella.Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD].init(
|
||||
mapIt(rpcExecutionPayload.withdrawals, it.getConsensusWithdrawal)))
|
||||
mapIt(rpcExecutionPayload.withdrawals, it.asConsensusWithdrawal)))
|
||||
|
||||
func asEngineExecutionPayload*(executionPayload: bellatrix.ExecutionPayload):
|
||||
ExecutionPayloadV1 =
|
||||
|
@ -410,12 +420,6 @@ func asEngineExecutionPayload*(executionPayload: capella.ExecutionPayload):
|
|||
ExecutionPayloadV2 =
|
||||
template getTypedTransaction(tt: bellatrix.Transaction): TypedTransaction =
|
||||
TypedTransaction(tt.distinctBase)
|
||||
template getEngineWithdrawal(w: capella.Withdrawal): WithdrawalV1 =
|
||||
WithdrawalV1(
|
||||
index: Quantity(w.index),
|
||||
validatorIndex: Quantity(w.validator_index),
|
||||
address: Address(w.address.data),
|
||||
amount: w.amount.u256 * weiInGwei)
|
||||
|
||||
engine_api.ExecutionPayloadV2(
|
||||
parentHash: executionPayload.parent_hash.asBlockHash,
|
||||
|
@ -434,7 +438,7 @@ func asEngineExecutionPayload*(executionPayload: capella.ExecutionPayload):
|
|||
baseFeePerGas: executionPayload.base_fee_per_gas,
|
||||
blockHash: executionPayload.block_hash.asBlockHash,
|
||||
transactions: mapIt(executionPayload.transactions, it.getTypedTransaction),
|
||||
withdrawals: mapIt(executionPayload.withdrawals, it.getEngineWithdrawal))
|
||||
withdrawals: mapIt(executionPayload.withdrawals, it.asEngineWithdrawal))
|
||||
|
||||
func shortLog*(b: Eth1Block): string =
|
||||
try:
|
||||
|
@ -589,9 +593,9 @@ proc newPayload*(p: Eth1Monitor, payload: engine_api.ExecutionPayloadV2):
|
|||
|
||||
p.dataProvider.web3.provider.engine_newPayloadV2(payload)
|
||||
|
||||
proc forkchoiceUpdated*(p: Eth1Monitor,
|
||||
headBlock, safeBlock, finalizedBlock: Eth2Digest):
|
||||
Future[engine_api.ForkchoiceUpdatedResponse] =
|
||||
proc forkchoiceUpdated*(
|
||||
p: Eth1Monitor, headBlock, safeBlock, finalizedBlock: Eth2Digest):
|
||||
Future[engine_api.ForkchoiceUpdatedResponse] =
|
||||
# Eth1 monitor can recycle connections without (external) warning; at least,
|
||||
# don't crash.
|
||||
if p.isNil or p.dataProvider.isNil:
|
||||
|
@ -608,12 +612,12 @@ proc forkchoiceUpdated*(p: Eth1Monitor,
|
|||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||
none(engine_api.PayloadAttributesV1))
|
||||
|
||||
proc forkchoiceUpdated*(p: Eth1Monitor,
|
||||
headBlock, safeBlock, finalizedBlock: Eth2Digest,
|
||||
timestamp: uint64,
|
||||
randomData: array[32, byte],
|
||||
suggestedFeeRecipient: Eth1Address):
|
||||
Future[engine_api.ForkchoiceUpdatedResponse] =
|
||||
proc forkchoiceUpdated*(
|
||||
p: Eth1Monitor, headBlock, safeBlock, finalizedBlock: Eth2Digest,
|
||||
timestamp: uint64, randomData: array[32, byte],
|
||||
suggestedFeeRecipient: Eth1Address,
|
||||
withdrawals: Opt[seq[capella.Withdrawal]]):
|
||||
Future[engine_api.ForkchoiceUpdatedResponse] =
|
||||
# Eth1 monitor can recycle connections without (external) warning; at least,
|
||||
# don't crash.
|
||||
if p.isNil or p.dataProvider.isNil:
|
||||
|
@ -623,15 +627,26 @@ proc forkchoiceUpdated*(p: Eth1Monitor,
|
|||
payloadStatus: PayloadStatusV1(status: PayloadExecutionStatus.syncing)))
|
||||
return fcuR
|
||||
|
||||
p.dataProvider.web3.provider.engine_forkchoiceUpdatedV1(
|
||||
ForkchoiceStateV1(
|
||||
headBlockHash: headBlock.asBlockHash,
|
||||
safeBlockHash: safeBlock.asBlockHash,
|
||||
finalizedBlockHash: finalizedBlock.asBlockHash),
|
||||
some(engine_api.PayloadAttributesV1(
|
||||
timestamp: Quantity timestamp,
|
||||
prevRandao: FixedBytes[32] randomData,
|
||||
suggestedFeeRecipient: suggestedFeeRecipient)))
|
||||
let forkchoiceState = ForkchoiceStateV1(
|
||||
headBlockHash: headBlock.asBlockHash,
|
||||
safeBlockHash: safeBlock.asBlockHash,
|
||||
finalizedBlockHash: finalizedBlock.asBlockHash)
|
||||
|
||||
if withdrawals.isNone:
|
||||
p.dataProvider.web3.provider.engine_forkchoiceUpdatedV1(
|
||||
forkchoiceState,
|
||||
some(engine_api.PayloadAttributesV1(
|
||||
timestamp: Quantity timestamp,
|
||||
prevRandao: FixedBytes[32] randomData,
|
||||
suggestedFeeRecipient: suggestedFeeRecipient)))
|
||||
else:
|
||||
p.dataProvider.web3.provider.engine_forkchoiceUpdatedV2(
|
||||
forkchoiceState,
|
||||
some(engine_api.PayloadAttributesV2(
|
||||
timestamp: Quantity timestamp,
|
||||
prevRandao: FixedBytes[32] randomData,
|
||||
suggestedFeeRecipient: suggestedFeeRecipient,
|
||||
withdrawals: mapIt(withdrawals.get, it.asEngineWithdrawal))))
|
||||
|
||||
# TODO can't be defined within exchangeTransitionConfiguration
|
||||
proc `==`(x, y: Quantity): bool {.borrow, noSideEffect.}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
@ -818,6 +818,74 @@ func get_next_sync_committee_keys(
|
|||
i += 1'u64
|
||||
res
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/capella/beacon-chain.md#has_eth1_withdrawal_credential
|
||||
func has_eth1_withdrawal_credential(validator: Validator): bool =
|
||||
## Check if ``validator`` has an 0x01 prefixed "eth1" withdrawal credential.
|
||||
validator.withdrawal_credentials.data[0] == ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/capella/beacon-chain.md#is_fully_withdrawable_validator
|
||||
func is_fully_withdrawable_validator(
|
||||
validator: Validator, balance: Gwei, epoch: Epoch): bool =
|
||||
## Check if ``validator`` is fully withdrawable.
|
||||
has_eth1_withdrawal_credential(validator) and
|
||||
validator.withdrawable_epoch <= epoch and balance > 0
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/capella/beacon-chain.md#is_partially_withdrawable_validator
|
||||
func is_partially_withdrawable_validator(
|
||||
validator: Validator, balance: Gwei): bool =
|
||||
## Check if ``validator`` is partially withdrawable.
|
||||
let
|
||||
has_max_effective_balance =
|
||||
validator.effective_balance == MAX_EFFECTIVE_BALANCE
|
||||
has_excess_balance = balance > MAX_EFFECTIVE_BALANCE
|
||||
has_eth1_withdrawal_credential(validator) and
|
||||
has_max_effective_balance and has_excess_balance
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/capella/beacon-chain.md#new-get_expected_withdrawals
|
||||
func get_expected_withdrawals*(state: capella.BeaconState): seq[Withdrawal] =
|
||||
let
|
||||
epoch = get_current_epoch(state)
|
||||
num_validators = lenu64(state.validators)
|
||||
var
|
||||
withdrawal_index = state.next_withdrawal_index
|
||||
validator_index = state.next_withdrawal_validator_index
|
||||
withdrawals: seq[Withdrawal] = @[]
|
||||
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
for _ in 0 ..< bound:
|
||||
let
|
||||
validator = state.validators[validator_index]
|
||||
balance = state.balances[validator_index]
|
||||
if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
var w = Withdrawal(
|
||||
index: withdrawal_index,
|
||||
validator_index: validator_index,
|
||||
amount: balance)
|
||||
w.address.data[0..19] = validator.withdrawal_credentials.data[12..^1]
|
||||
withdrawals.add w
|
||||
withdrawal_index = WithdrawalIndex(withdrawal_index + 1)
|
||||
elif is_partially_withdrawable_validator(validator, balance):
|
||||
var w = Withdrawal(
|
||||
index: withdrawal_index,
|
||||
validator_index: validator_index,
|
||||
amount: balance - MAX_EFFECTIVE_BALANCE)
|
||||
w.address.data[0..19] = validator.withdrawal_credentials.data[12..^1]
|
||||
withdrawals.add w
|
||||
withdrawal_index = WithdrawalIndex(withdrawal_index + 1)
|
||||
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
break
|
||||
validator_index = (validator_index + 1) mod num_validators
|
||||
withdrawals
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/eip4844/beacon-chain.md#disabling-withdrawals
|
||||
func get_expected_withdrawals*(state: eip4844.BeaconState): seq[Withdrawal] =
|
||||
# During testing we avoid Capella-specific updates to the state transition.
|
||||
#
|
||||
# ...
|
||||
#
|
||||
# The `get_expected_withdrawals` function is also modified to return an empty
|
||||
# withdrawals list.
|
||||
@[]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/altair/beacon-chain.md#get_next_sync_committee
|
||||
func get_next_sync_committee*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState |
|
||||
|
|
|
@ -673,72 +673,6 @@ proc process_execution_payload*(
|
|||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.1/specs/capella/beacon-chain.md#has_eth1_withdrawal_credential
|
||||
func has_eth1_withdrawal_credential(validator: Validator): bool =
|
||||
## Check if ``validator`` has an 0x01 prefixed "eth1" withdrawal credential.
|
||||
validator.withdrawal_credentials.data[0] == ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.1/specs/capella/beacon-chain.md#is_fully_withdrawable_validator
|
||||
func is_fully_withdrawable_validator(
|
||||
validator: Validator, balance: Gwei, epoch: Epoch): bool =
|
||||
## Check if ``validator`` is fully withdrawable.
|
||||
has_eth1_withdrawal_credential(validator) and
|
||||
validator.withdrawable_epoch <= epoch and balance > 0
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.1/specs/capella/beacon-chain.md#is_partially_withdrawable_validator
|
||||
func is_partially_withdrawable_validator(
|
||||
validator: Validator, balance: Gwei): bool =
|
||||
## Check if ``validator`` is partially withdrawable.
|
||||
let
|
||||
has_max_effective_balance =
|
||||
validator.effective_balance == MAX_EFFECTIVE_BALANCE
|
||||
has_excess_balance = balance > MAX_EFFECTIVE_BALANCE
|
||||
has_eth1_withdrawal_credential(validator) and
|
||||
has_max_effective_balance and has_excess_balance
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.2/specs/capella/beacon-chain.md#new-get_expected_withdrawals
|
||||
func get_expected_withdrawals(state: capella.BeaconState): seq[Withdrawal] =
|
||||
let epoch = get_current_epoch(state)
|
||||
var
|
||||
withdrawal_index = state.next_withdrawal_index
|
||||
validator_index = state.next_withdrawal_validator_index
|
||||
withdrawals: seq[Withdrawal] = @[]
|
||||
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
for _ in 0 ..< bound:
|
||||
let
|
||||
validator = state.validators[validator_index]
|
||||
balance = state.balances[validator_index]
|
||||
if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
var w = Withdrawal(
|
||||
index: withdrawal_index,
|
||||
validator_index: validator_index,
|
||||
amount: balance)
|
||||
w.address.data[0..19] = validator.withdrawal_credentials.data[12..^1]
|
||||
withdrawals.add w
|
||||
withdrawal_index = WithdrawalIndex(withdrawal_index + 1)
|
||||
elif is_partially_withdrawable_validator(validator, balance):
|
||||
var w = Withdrawal(
|
||||
index: withdrawal_index,
|
||||
validator_index: validator_index,
|
||||
amount: balance - MAX_EFFECTIVE_BALANCE)
|
||||
w.address.data[0..19] = validator.withdrawal_credentials.data[12..^1]
|
||||
withdrawals.add w
|
||||
withdrawal_index = WithdrawalIndex(withdrawal_index + 1)
|
||||
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
break
|
||||
validator_index = (validator_index + 1) mod lenu64(state.validators)
|
||||
withdrawals
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.1/specs/eip4844/beacon-chain.md#disabling-withdrawals
|
||||
func get_expected_withdrawals(state: eip4844.BeaconState): seq[Withdrawal] =
|
||||
# During testing we avoid Capella-specific updates to the state transition.
|
||||
#
|
||||
# ...
|
||||
#
|
||||
# The `get_expected_withdrawals` function is also modified to return an empty
|
||||
# withdrawals list.
|
||||
@[]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.1/specs/capella/beacon-chain.md#new-process_withdrawals
|
||||
func process_withdrawals*(
|
||||
state: var capella.BeaconState,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2022 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2023 Status Research & Development GmbH
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
@ -282,7 +282,8 @@ from web3/engine_api import ForkchoiceUpdatedResponse
|
|||
proc forkchoice_updated(
|
||||
head_block_hash: Eth2Digest, safe_block_hash: Eth2Digest,
|
||||
finalized_block_hash: Eth2Digest, timestamp: uint64, random: Eth2Digest,
|
||||
fee_recipient: ethtypes.Address, execution_engine: Eth1Monitor):
|
||||
fee_recipient: ethtypes.Address, withdrawals: Opt[seq[Withdrawal]],
|
||||
execution_engine: Eth1Monitor):
|
||||
Future[Option[bellatrix.PayloadID]] {.async.} =
|
||||
logScope:
|
||||
head_block_hash
|
||||
|
@ -295,7 +296,7 @@ proc forkchoice_updated(
|
|||
awaitWithTimeout(
|
||||
execution_engine.forkchoiceUpdated(
|
||||
head_block_hash, safe_block_hash, finalized_block_hash,
|
||||
timestamp, random.data, fee_recipient),
|
||||
timestamp, random.data, fee_recipient, withdrawals),
|
||||
FORKCHOICEUPDATED_TIMEOUT):
|
||||
error "Engine API fork-choice update timed out"
|
||||
default(ForkchoiceUpdatedResponse)
|
||||
|
@ -396,13 +397,19 @@ proc getExecutionPayload[T](
|
|||
lastFcU = node.consensusManager.forkchoiceUpdatedInfo
|
||||
timestamp = withState(proposalState[]):
|
||||
compute_timestamp_at_slot(forkyState.data, forkyState.data.slot)
|
||||
withdrawals = withState(proposalState[]):
|
||||
when stateFork >= BeaconStateFork.Capella:
|
||||
Opt.some get_expected_withdrawals(forkyState.data)
|
||||
else:
|
||||
Opt.none(seq[Withdrawal])
|
||||
payload_id =
|
||||
if lastFcU.isSome and
|
||||
lastFcU.get.headBlockRoot == latestHead and
|
||||
lastFcU.get.safeBlockRoot == latestSafe and
|
||||
lastFcU.get.finalizedBlockRoot == latestFinalized and
|
||||
lastFcU.get.timestamp == timestamp and
|
||||
lastFcU.get.feeRecipient == feeRecipient:
|
||||
lastFcU.get.feeRecipient == feeRecipient and
|
||||
lastFcU.get.withdrawals == withdrawals:
|
||||
some bellatrix.PayloadID(lastFcU.get.payloadId)
|
||||
else:
|
||||
debug "getExecutionPayload: didn't find payloadId, re-querying",
|
||||
|
@ -411,11 +418,11 @@ proc getExecutionPayload[T](
|
|||
feeRecipient,
|
||||
cachedForkchoiceUpdateInformation = lastFcU
|
||||
|
||||
let random = withState(proposalState[]):
|
||||
get_randao_mix(forkyState.data, get_current_epoch(forkyState.data))
|
||||
let random = withState(proposalState[]): get_randao_mix(
|
||||
forkyState.data, get_current_epoch(forkyState.data))
|
||||
(await forkchoice_updated(
|
||||
latestHead, latestSafe, latestFinalized, timestamp, random,
|
||||
feeRecipient, node.consensusManager.eth1Monitor))
|
||||
feeRecipient, withdrawals, node.consensusManager.eth1Monitor))
|
||||
payload = try:
|
||||
awaitWithTimeout(
|
||||
get_execution_payload[T](payload_id, node.consensusManager.eth1Monitor),
|
||||
|
|
Loading…
Reference in New Issue