update to devnet-4-compatible engine API (#6657)
This commit is contained in:
parent
6df8f92092
commit
2d3614ff69
4
Makefile
4
Makefile
|
@ -235,7 +235,7 @@ local-testnet-minimal:
|
|||
--remote-validators-count 512 \
|
||||
--signer-type $(SIGNER_TYPE) \
|
||||
--deneb-fork-epoch 0 \
|
||||
--electra-fork-epoch 5 \
|
||||
--electra-fork-epoch 50 \
|
||||
--stop-at-epoch 6 \
|
||||
--disable-htop \
|
||||
--enable-payload-builder \
|
||||
|
@ -264,7 +264,7 @@ local-testnet-mainnet:
|
|||
--data-dir $@ \
|
||||
--nodes 2 \
|
||||
--deneb-fork-epoch 0 \
|
||||
--electra-fork-epoch 5 \
|
||||
--electra-fork-epoch 50 \
|
||||
--stop-at-epoch 6 \
|
||||
--disable-htop \
|
||||
--base-port $$(( $(MAINNET_TESTNET_BASE_PORT) + EXECUTOR_NUMBER * 400 + 0 )) \
|
||||
|
|
|
@ -821,13 +821,15 @@ proc sendNewPayloadToSingleEL(
|
|||
|
||||
proc sendNewPayloadToSingleEL(
|
||||
connection: ELConnection,
|
||||
payload: engine_api.ExecutionPayloadV4,
|
||||
payload: engine_api.ExecutionPayloadV3,
|
||||
versioned_hashes: seq[engine_api.VersionedHash],
|
||||
parent_beacon_block_root: FixedBytes[32]
|
||||
parent_beacon_block_root: FixedBytes[32],
|
||||
executionRequests: array[3, seq[byte]]
|
||||
): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} =
|
||||
let rpcClient = await connection.connectedRpcClient()
|
||||
await rpcClient.engine_newPayloadV4(
|
||||
payload, versioned_hashes, Hash32 parent_beacon_block_root)
|
||||
payload, versioned_hashes, Hash32 parent_beacon_block_root,
|
||||
executionRequests)
|
||||
|
||||
type
|
||||
StatusRelation = enum
|
||||
|
@ -954,8 +956,18 @@ proc sendNewPayload*(
|
|||
let
|
||||
requests = m.elConnections.mapIt:
|
||||
let req =
|
||||
when payload is engine_api.ExecutionPayloadV3 or
|
||||
payload is engine_api.ExecutionPayloadV4:
|
||||
when typeof(blck).kind == ConsensusFork.Electra:
|
||||
# https://github.com/ethereum/execution-apis/blob/4140e528360fea53c34a766d86a000c6c039100e/src/engine/prague.md#engine_newpayloadv4
|
||||
let versioned_hashes = mapIt(
|
||||
blck.body.blob_kzg_commitments,
|
||||
engine_api.VersionedHash(kzg_commitment_to_versioned_hash(it)))
|
||||
sendNewPayloadToSingleEL(
|
||||
it, payload, versioned_hashes,
|
||||
FixedBytes[32] blck.parent_root.data,
|
||||
[SSZ.encode(blck.body.execution_requests.deposits),
|
||||
SSZ.encode(blck.body.execution_requests.withdrawals),
|
||||
SSZ.encode(blck.body.execution_requests.consolidations)])
|
||||
elif typeof(blck).kind == ConsensusFork.Deneb:
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/specs/deneb/beacon-chain.md#process_execution_payload
|
||||
# Verify the execution payload is valid
|
||||
# [Modified in Deneb] Pass `versioned_hashes` to Execution Engine
|
||||
|
@ -965,8 +977,7 @@ proc sendNewPayload*(
|
|||
sendNewPayloadToSingleEL(
|
||||
it, payload, versioned_hashes,
|
||||
FixedBytes[32] blck.parent_root.data)
|
||||
elif payload is engine_api.ExecutionPayloadV1 or
|
||||
payload is engine_api.ExecutionPayloadV2:
|
||||
elif typeof(blck).kind in [ConsensusFork.Bellatrix, ConsensusFork.Capella]:
|
||||
sendNewPayloadToSingleEL(it, payload)
|
||||
else:
|
||||
static: doAssert false
|
||||
|
|
|
@ -129,6 +129,33 @@ func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV3):
|
|||
blob_gas_used: rpcExecutionPayload.blobGasUsed.uint64,
|
||||
excess_blob_gas: rpcExecutionPayload.excessBlobGas.uint64)
|
||||
|
||||
func asElectraConsensusPayload(rpcExecutionPayload: ExecutionPayloadV3):
|
||||
electra.ExecutionPayload =
|
||||
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
||||
bellatrix.Transaction.init(tt.distinctBase)
|
||||
|
||||
electra.ExecutionPayload(
|
||||
parent_hash: rpcExecutionPayload.parentHash.asEth2Digest,
|
||||
feeRecipient:
|
||||
ExecutionAddress(data: rpcExecutionPayload.feeRecipient.distinctBase),
|
||||
state_root: rpcExecutionPayload.stateRoot.asEth2Digest,
|
||||
receipts_root: rpcExecutionPayload.receiptsRoot.asEth2Digest,
|
||||
logs_bloom: BloomLogs(data: rpcExecutionPayload.logsBloom.distinctBase),
|
||||
prev_randao: rpcExecutionPayload.prevRandao.asEth2Digest,
|
||||
block_number: rpcExecutionPayload.blockNumber.uint64,
|
||||
gas_limit: rpcExecutionPayload.gasLimit.uint64,
|
||||
gas_used: rpcExecutionPayload.gasUsed.uint64,
|
||||
timestamp: rpcExecutionPayload.timestamp.uint64,
|
||||
extra_data: List[byte, MAX_EXTRA_DATA_BYTES].init(rpcExecutionPayload.extraData.data),
|
||||
base_fee_per_gas: rpcExecutionPayload.baseFeePerGas,
|
||||
block_hash: rpcExecutionPayload.blockHash.asEth2Digest,
|
||||
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.asConsensusWithdrawal)),
|
||||
blob_gas_used: rpcExecutionPayload.blobGasUsed.uint64,
|
||||
excess_blob_gas: rpcExecutionPayload.excessBlobGas.uint64)
|
||||
|
||||
func asConsensusType*(payload: engine_api.GetPayloadV3Response):
|
||||
deneb.ExecutionPayloadForSigning =
|
||||
deneb.ExecutionPayloadForSigning(
|
||||
|
@ -148,61 +175,11 @@ func asConsensusType*(payload: engine_api.GetPayloadV3Response):
|
|||
blobs: Blobs.init(
|
||||
payload.blobsBundle.blobs.mapIt(it.data))))
|
||||
|
||||
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV4):
|
||||
electra.ExecutionPayload =
|
||||
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
||||
bellatrix.Transaction.init(tt.distinctBase)
|
||||
|
||||
template getDepositRequest(
|
||||
dr: DepositRequestV1): electra.DepositRequest =
|
||||
electra.DepositRequest(
|
||||
pubkey: ValidatorPubKey(blob: dr.pubkey.distinctBase),
|
||||
withdrawal_credentials: dr.withdrawalCredentials.asEth2Digest,
|
||||
amount: dr.amount.Gwei,
|
||||
signature: ValidatorSig(blob: dr.signature.distinctBase),
|
||||
index: dr.index.uint64)
|
||||
|
||||
template getWithdrawalRequest(
|
||||
wr: WithdrawalRequestV1): electra.WithdrawalRequest =
|
||||
electra.WithdrawalRequest(
|
||||
source_address: ExecutionAddress(data: wr.sourceAddress.distinctBase),
|
||||
validator_pubkey: ValidatorPubKey(blob: wr.validatorPubkey.distinctBase),
|
||||
amount: wr.amount.Gwei)
|
||||
|
||||
template getConsolidationRequest(
|
||||
cr: ConsolidationRequestV1): electra.ConsolidationRequest =
|
||||
electra.ConsolidationRequest(
|
||||
source_address: ExecutionAddress(data: cr.sourceAddress.distinctBase),
|
||||
source_pubkey: ValidatorPubKey(blob: cr.sourcePubkey.distinctBase),
|
||||
target_pubkey: ValidatorPubKey(blob: cr.targetPubkey.distinctBase))
|
||||
|
||||
electra.ExecutionPayload(
|
||||
parent_hash: rpcExecutionPayload.parentHash.asEth2Digest,
|
||||
feeRecipient:
|
||||
ExecutionAddress(data: rpcExecutionPayload.feeRecipient.distinctBase),
|
||||
state_root: rpcExecutionPayload.stateRoot.asEth2Digest,
|
||||
receipts_root: rpcExecutionPayload.receiptsRoot.asEth2Digest,
|
||||
logs_bloom: BloomLogs(data: rpcExecutionPayload.logsBloom.distinctBase),
|
||||
prev_randao: rpcExecutionPayload.prevRandao.asEth2Digest,
|
||||
block_number: rpcExecutionPayload.blockNumber.uint64,
|
||||
gas_limit: rpcExecutionPayload.gasLimit.uint64,
|
||||
gas_used: rpcExecutionPayload.gasUsed.uint64,
|
||||
timestamp: rpcExecutionPayload.timestamp.uint64,
|
||||
extra_data: List[byte, MAX_EXTRA_DATA_BYTES].init(
|
||||
rpcExecutionPayload.extraData.data),
|
||||
base_fee_per_gas: rpcExecutionPayload.baseFeePerGas,
|
||||
block_hash: rpcExecutionPayload.blockHash.asEth2Digest,
|
||||
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.asConsensusWithdrawal)),
|
||||
blob_gas_used: rpcExecutionPayload.blobGasUsed.uint64,
|
||||
excess_blob_gas: rpcExecutionPayload.excessBlobGas.uint64)
|
||||
|
||||
func asConsensusType*(payload: engine_api.GetPayloadV4Response):
|
||||
func asConsensusType*(
|
||||
payload: engine_api.GetPayloadV4Response):
|
||||
electra.ExecutionPayloadForSigning =
|
||||
electra.ExecutionPayloadForSigning(
|
||||
executionPayload: payload.executionPayload.asConsensusType,
|
||||
executionPayload: payload.executionPayload.asElectraConsensusPayload,
|
||||
blockValue: payload.blockValue,
|
||||
# TODO
|
||||
# The `mapIt` calls below are necessary only because we use different distinct
|
||||
|
@ -216,7 +193,8 @@ func asConsensusType*(payload: engine_api.GetPayloadV4Response):
|
|||
payload.blobsBundle.proofs.mapIt(
|
||||
kzg_abi.KzgProof(bytes: it.data))),
|
||||
blobs: Blobs.init(
|
||||
payload.blobsBundle.blobs.mapIt(it.data))))
|
||||
payload.blobsBundle.blobs.mapIt(it.data))),
|
||||
executionRequests: payload.executionRequests)
|
||||
|
||||
func asEngineExecutionPayload*(blockBody: bellatrix.BeaconBlockBody):
|
||||
ExecutionPayloadV1 =
|
||||
|
@ -273,7 +251,8 @@ func asEngineExecutionPayload*(blockBody: capella.BeaconBlockBody):
|
|||
transactions: mapIt(executionPayload.transactions, it.getTypedTransaction),
|
||||
withdrawals: mapIt(executionPayload.withdrawals, it.toEngineWithdrawal))
|
||||
|
||||
func asEngineExecutionPayload*(blockBody: deneb.BeaconBlockBody):
|
||||
func asEngineExecutionPayload*(
|
||||
blockBody: deneb.BeaconBlockBody | electra.BeaconBlockBody):
|
||||
ExecutionPayloadV3 =
|
||||
template executionPayload(): untyped = blockBody.execution_payload
|
||||
|
||||
|
@ -299,59 +278,3 @@ func asEngineExecutionPayload*(blockBody: deneb.BeaconBlockBody):
|
|||
withdrawals: mapIt(executionPayload.withdrawals, it.asEngineWithdrawal),
|
||||
blobGasUsed: Quantity(executionPayload.blob_gas_used),
|
||||
excessBlobGas: Quantity(executionPayload.excess_blob_gas))
|
||||
|
||||
func asEngineExecutionPayload*(blockBody: electra.BeaconBlockBody):
|
||||
ExecutionPayloadV4 =
|
||||
template executionPayload(): untyped = blockBody.execution_payload
|
||||
|
||||
template getTypedTransaction(tt: bellatrix.Transaction): TypedTransaction =
|
||||
TypedTransaction(tt.distinctBase)
|
||||
|
||||
template getDepositRequest(
|
||||
dr: electra.DepositRequest): DepositRequestV1 =
|
||||
DepositRequestV1(
|
||||
pubkey: FixedBytes[RawPubKeySize](dr.pubkey.blob),
|
||||
withdrawalCredentials: FixedBytes[32](dr.withdrawal_credentials.data),
|
||||
amount: dr.amount.Quantity,
|
||||
signature: FixedBytes[RawSigSize](dr.signature.blob),
|
||||
index: dr.index.Quantity)
|
||||
|
||||
template getWithdrawalRequest(
|
||||
wr: electra.WithdrawalRequest): WithdrawalRequestV1 =
|
||||
WithdrawalRequestV1(
|
||||
sourceAddress: Address(wr.source_address.data),
|
||||
validatorPubkey: FixedBytes[RawPubKeySize](wr.validator_pubkey.blob),
|
||||
amount: wr.amount.Quantity)
|
||||
|
||||
template getConsolidationRequest(
|
||||
cr: electra.ConsolidationRequest): ConsolidationRequestV1 =
|
||||
ConsolidationRequestV1(
|
||||
sourceAddress: Address(cr.source_address.data),
|
||||
sourcePubkey: FixedBytes[RawPubKeySize](cr.source_pubkey.blob),
|
||||
targetPubkey: FixedBytes[RawPubKeySize](cr.target_pubkey.blob))
|
||||
|
||||
engine_api.ExecutionPayloadV4(
|
||||
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.data.to(Bytes32),
|
||||
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),
|
||||
depositRequests:
|
||||
mapIt(blockBody.execution_requests.deposits, it.getDepositRequest),
|
||||
withdrawalRequests: mapIt(
|
||||
blockBody.execution_requests.withdrawals, it.getWithdrawalRequest),
|
||||
consolidationRequests: mapIt(
|
||||
blockBody.execution_requests.consolidations, it.getConsolidationRequest))
|
||||
|
|
|
@ -1255,31 +1255,23 @@ proc ETHExecutionBlockHeaderCreateFromJson(
|
|||
return nil
|
||||
|
||||
# Check fork consistency
|
||||
static: doAssert totalSerializedFields(BlockObject) == 30,
|
||||
static: doAssert totalSerializedFields(BlockObject) == 27,
|
||||
"Only update this number once code is adjusted to check new fields!"
|
||||
if data.baseFeePerGas.isNone and (
|
||||
data.withdrawals.isSome or data.withdrawalsRoot.isSome or
|
||||
data.blobGasUsed.isSome or data.excessBlobGas.isSome or
|
||||
data.depositRequests.isSome or data.withdrawalRequests.isSome or
|
||||
data.consolidationRequests.isSome or data.requestsRoot.isSome):
|
||||
data.requestsHash.isSome):
|
||||
return nil
|
||||
if data.withdrawalsRoot.isNone and (
|
||||
data.blobGasUsed.isSome or data.excessBlobGas.isSome or
|
||||
data.depositRequests.isSome or data.withdrawalRequests.isSome or
|
||||
data.consolidationRequests.isSome or data.requestsRoot.isSome):
|
||||
data.requestsHash.isSome):
|
||||
return nil
|
||||
if data.blobGasUsed.isNone and (
|
||||
data.depositRequests.isSome or data.withdrawalRequests.isSome or
|
||||
data.consolidationRequests.isSome or data.requestsRoot.isSome):
|
||||
if data.blobGasUsed.isNone and data.requestsHash.isSome:
|
||||
return nil
|
||||
if data.withdrawals.isSome != data.withdrawalsRoot.isSome:
|
||||
return nil
|
||||
if data.blobGasUsed.isSome != data.excessBlobGas.isSome:
|
||||
return nil
|
||||
if data.depositRequests.isSome != data.requestsRoot.isSome or
|
||||
data.withdrawalRequests.isSome != data.requestsRoot.isSome or
|
||||
data.consolidationRequests.isSome != data.requestsRoot.isSome:
|
||||
return nil
|
||||
|
||||
# Construct block header
|
||||
static: # `GasInt` is signed. We only use it for hashing.
|
||||
|
@ -1325,8 +1317,8 @@ proc ETHExecutionBlockHeaderCreateFromJson(
|
|||
else:
|
||||
Opt.none(Hash32),
|
||||
requestsHash:
|
||||
if data.requestsRoot.isSome:
|
||||
Opt.some(data.requestsRoot.get.asEth2Digest.to(Hash32))
|
||||
if data.requestsHash.isSome:
|
||||
Opt.some data.requestsHash.get.asEth2Digest.to(Hash32)
|
||||
else:
|
||||
Opt.none(Hash32))
|
||||
if rlpHash(blockHeader) != executionHash[]:
|
||||
|
@ -1367,119 +1359,12 @@ proc ETHExecutionBlockHeaderCreateFromJson(
|
|||
if tr != data.withdrawalsRoot.get.asEth2Digest:
|
||||
return nil
|
||||
|
||||
# Construct deposit requests
|
||||
var depositRequests: seq[ETHDepositRequest]
|
||||
if data.depositRequests.isSome:
|
||||
depositRequests = newSeqOfCap[ETHDepositRequest](
|
||||
data.depositRequests.get.len)
|
||||
for data in data.depositRequests.get:
|
||||
# Check fork consistency
|
||||
static: doAssert totalSerializedFields(DepositRequestObject) == 5,
|
||||
"Only update this number once code is adjusted to check new fields!"
|
||||
|
||||
# Construct deposit request
|
||||
let
|
||||
req = eth_types.EthDepositRequest(
|
||||
pubkey: distinctBase(data.pubkey).to(Bytes48),
|
||||
withdrawalCredentials: distinctBase(data.withdrawalCredentials).to(Bytes32),
|
||||
amount: distinctBase(data.amount),
|
||||
signature: distinctBase(data.signature).to(Bytes96),
|
||||
index: distinctBase(data.index))
|
||||
rlpBytes =
|
||||
try:
|
||||
rlp.encode(req)
|
||||
except RlpError:
|
||||
raiseAssert "Unreachable"
|
||||
|
||||
depositRequests.add ETHDepositRequest(
|
||||
pubkey: ValidatorPubKey(blob: req.pubkey.data),
|
||||
withdrawalCredentials: req.withdrawalCredentials.data,
|
||||
amount: req.amount,
|
||||
signature: ValidatorSig(blob: req.signature.data),
|
||||
index: req.index,
|
||||
bytes: rlpBytes)
|
||||
|
||||
# Construct withdrawal requests
|
||||
var withdrawalRequests: seq[ETHWithdrawalRequest]
|
||||
if data.withdrawalRequests.isSome:
|
||||
withdrawalRequests = newSeqOfCap[ETHWithdrawalRequest](
|
||||
data.withdrawalRequests.get.len)
|
||||
for data in data.withdrawalRequests.get:
|
||||
# Check fork consistency
|
||||
static: doAssert totalSerializedFields(WithdrawalRequestObject) == 3,
|
||||
"Only update this number once code is adjusted to check new fields!"
|
||||
|
||||
# Construct withdrawal request
|
||||
let
|
||||
req = eth_types.EthWithdrawalRequest(
|
||||
sourceAddress: distinctBase(data.sourceAddress).to(EthAddress),
|
||||
validatorPubkey: distinctBase(data.validatorPubkey).to(Bytes48),
|
||||
amount: distinctBase(data.amount))
|
||||
rlpBytes =
|
||||
try:
|
||||
rlp.encode(req)
|
||||
except RlpError:
|
||||
raiseAssert "Unreachable"
|
||||
|
||||
withdrawalRequests.add ETHWithdrawalRequest(
|
||||
sourceAddress: ExecutionAddress(data: req.sourceAddress.data),
|
||||
validatorPubkey: ValidatorPubKey(blob: req.validatorPubkey.data),
|
||||
amount: req.amount,
|
||||
bytes: rlpBytes)
|
||||
|
||||
# Construct consolidation requests
|
||||
var consolidationRequests: seq[ETHConsolidationRequest]
|
||||
if data.consolidationRequests.isSome:
|
||||
consolidationRequests = newSeqOfCap[ETHConsolidationRequest](
|
||||
data.consolidationRequests.get.len)
|
||||
for data in data.consolidationRequests.get:
|
||||
# Check fork consistency
|
||||
static: doAssert totalSerializedFields(ConsolidationRequestObject) == 3,
|
||||
"Only update this number once code is adjusted to check new fields!"
|
||||
|
||||
# Construct consolidation request
|
||||
let
|
||||
req = eth_types.EthConsolidationRequest(
|
||||
sourceAddress: distinctBase(data.sourceAddress).to(EthAddress),
|
||||
sourcePubkey: distinctBase(data.sourcePubkey).to(Bytes48),
|
||||
targetPubkey: distinctBase(data.targetPubkey).to(Bytes48))
|
||||
rlpBytes =
|
||||
try:
|
||||
rlp.encode(req)
|
||||
except RlpError:
|
||||
raiseAssert "Unreachable"
|
||||
|
||||
consolidationRequests.add ETHConsolidationRequest(
|
||||
sourceAddress: ExecutionAddress(data: req.sourceAddress.data),
|
||||
sourcePubkey: ValidatorPubKey(blob: req.sourcePubkey.data),
|
||||
targetPubkey: ValidatorPubKey(blob: req.targetPubkey.data),
|
||||
bytes: rlpBytes)
|
||||
|
||||
# Verify requests hash
|
||||
if data.depositRequests.isSome or
|
||||
data.withdrawalRequests.isSome or
|
||||
data.consolidationRequests.isSome:
|
||||
doAssert data.requestsRoot.isSome # Checked above
|
||||
|
||||
var b = OrderedTrieRootBuilder.init(
|
||||
depositRequests.len + withdrawalRequests.len + consolidationRequests.len)
|
||||
|
||||
b.add(depositRequests)
|
||||
b.add(withdrawalRequests)
|
||||
b.add(consolidationRequests)
|
||||
|
||||
if b.rootHash() != data.requestsRoot.get.asEth2Digest:
|
||||
return nil
|
||||
|
||||
let executionBlockHeader = ETHExecutionBlockHeader.new()
|
||||
executionBlockHeader[] = ETHExecutionBlockHeader(
|
||||
transactionsRoot: blockHeader.txRoot,
|
||||
withdrawalsRoot: blockHeader.withdrawalsRoot.get(zeroHash32),
|
||||
withdrawals: wds,
|
||||
requestsHash: blockHeader.requestsHash.get(zeroHash32),
|
||||
depositRequests: depositRequests,
|
||||
withdrawalRequests: withdrawalRequests,
|
||||
consolidationRequests: consolidationRequests)
|
||||
requestsHash: blockHeader.requestsHash.get(zeroHash32))
|
||||
executionBlockHeader.toUnmanagedPtr()
|
||||
|
||||
proc ETHExecutionBlockHeaderDestroy(
|
||||
|
|
|
@ -119,6 +119,7 @@ type
|
|||
executionPayload*: ExecutionPayload
|
||||
blockValue*: Wei
|
||||
blobsBundle*: BlobsBundle
|
||||
executionRequests*: array[3, seq[byte]]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/deneb/beacon-chain.md#executionpayloadheader
|
||||
ExecutionPayloadHeader* = object
|
||||
|
|
|
@ -361,8 +361,8 @@ func partialBeaconBlock*(
|
|||
deposits: seq[Deposit],
|
||||
validator_changes: BeaconBlockValidatorChanges,
|
||||
sync_aggregate: SyncAggregate,
|
||||
execution_payload: ForkyExecutionPayloadForSigning
|
||||
): auto =
|
||||
execution_payload: ForkyExecutionPayloadForSigning,
|
||||
_: ExecutionRequests): auto =
|
||||
const consensusFork = typeof(state).kind
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/validator.md#preparing-for-a-beaconblock
|
||||
|
@ -411,8 +411,8 @@ func partialBeaconBlock*(
|
|||
deposits: seq[Deposit],
|
||||
validator_changes: BeaconBlockValidatorChanges,
|
||||
sync_aggregate: SyncAggregate,
|
||||
execution_payload: ForkyExecutionPayloadForSigning
|
||||
): auto =
|
||||
execution_payload: ForkyExecutionPayloadForSigning,
|
||||
execution_requests: ExecutionRequests): auto =
|
||||
const consensusFork = typeof(state).kind
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#preparing-for-a-beaconblock
|
||||
|
@ -433,7 +433,8 @@ func partialBeaconBlock*(
|
|||
sync_aggregate: sync_aggregate,
|
||||
execution_payload: execution_payload.executionPayload,
|
||||
bls_to_execution_changes: validator_changes.bls_to_execution_changes,
|
||||
blob_kzg_commitments: execution_payload.blobsBundle.commitments))
|
||||
blob_kzg_commitments: execution_payload.blobsBundle.commitments,
|
||||
execution_requests: execution_requests))
|
||||
|
||||
proc makeBeaconBlockWithRewards*(
|
||||
cfg: RuntimeConfig,
|
||||
|
@ -455,7 +456,8 @@ proc makeBeaconBlockWithRewards*(
|
|||
verificationFlags: UpdateFlags,
|
||||
transactions_root: Opt[Eth2Digest],
|
||||
execution_payload_root: Opt[Eth2Digest],
|
||||
kzg_commitments: Opt[KzgCommitments]):
|
||||
kzg_commitments: Opt[KzgCommitments],
|
||||
execution_requests: ExecutionRequests):
|
||||
Result[tuple[blck: ForkedBeaconBlock, rewards: BlockRewards], 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
|
||||
|
@ -473,7 +475,7 @@ proc makeBeaconBlockWithRewards*(
|
|||
partialBeaconBlock(
|
||||
cfg, state.`kind Data`, proposer_index, randao_reveal, eth1_data,
|
||||
graffiti, attestations, deposits, validator_changes, sync_aggregate,
|
||||
executionPayload))
|
||||
executionPayload, execution_requests))
|
||||
|
||||
let res = process_block(
|
||||
cfg, state.`kind Data`.data, blck.`kind Data`.asSigVerified(),
|
||||
|
@ -516,6 +518,7 @@ proc makeBeaconBlockWithRewards*(
|
|||
forkyState.data.latest_execution_payload_header.transactions_root =
|
||||
transactions_root.get
|
||||
|
||||
debugComment "verify (again) that this is what builder API needs"
|
||||
when executionPayload is electra.ExecutionPayloadForSigning:
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.3/specs/electra/beacon-chain.md#beaconblockbody
|
||||
forkyState.data.latest_block_header.body_root = hash_tree_root(
|
||||
|
@ -579,14 +582,16 @@ proc makeBeaconBlock*(
|
|||
verificationFlags: UpdateFlags,
|
||||
transactions_root: Opt[Eth2Digest],
|
||||
execution_payload_root: Opt[Eth2Digest],
|
||||
kzg_commitments: Opt[KzgCommitments]):
|
||||
kzg_commitments: Opt[KzgCommitments],
|
||||
execution_requests: ExecutionRequests):
|
||||
Result[ForkedBeaconBlock, cstring] =
|
||||
let blockAndRewards =
|
||||
? makeBeaconBlockWithRewards(
|
||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||
attestations, deposits, validator_changes, sync_aggregate,
|
||||
executionPayload, rollback, cache, verificationFlags,
|
||||
transactions_root, execution_payload_root, kzg_commitments)
|
||||
transactions_root, execution_payload_root, kzg_commitments,
|
||||
execution_requests)
|
||||
ok(blockAndRewards.blck)
|
||||
|
||||
proc makeBeaconBlock*(
|
||||
|
@ -606,7 +611,8 @@ proc makeBeaconBlock*(
|
|||
executionPayload, rollback, cache,
|
||||
verificationFlags = {}, transactions_root = Opt.none Eth2Digest,
|
||||
execution_payload_root = Opt.none Eth2Digest,
|
||||
kzg_commitments = Opt.none KzgCommitments)
|
||||
kzg_commitments = Opt.none KzgCommitments,
|
||||
execution_requests = default(ExecutionRequests))
|
||||
|
||||
proc makeBeaconBlock*(
|
||||
cfg: RuntimeConfig, state: var ForkedHashedBeaconState,
|
||||
|
@ -627,4 +633,5 @@ proc makeBeaconBlock*(
|
|||
verificationFlags = verificationFlags,
|
||||
transactions_root = Opt.none Eth2Digest,
|
||||
execution_payload_root = Opt.none Eth2Digest,
|
||||
kzg_commitments = Opt.none KzgCommitments)
|
||||
kzg_commitments = Opt.none KzgCommitments,
|
||||
execution_requests = default(ExecutionRequests))
|
||||
|
|
|
@ -76,7 +76,7 @@ declarePublicGauge(attached_validator_balance_total,
|
|||
logScope: topics = "beacval"
|
||||
|
||||
type
|
||||
EngineBid* = object
|
||||
EngineBid = object
|
||||
blck*: ForkedBeaconBlock
|
||||
executionPayloadValue*: Wei
|
||||
consensusBlockValue*: UInt256
|
||||
|
@ -457,7 +457,8 @@ proc makeBeaconBlockForHeadAndSlot*(
|
|||
transactions_root: Opt[Eth2Digest],
|
||||
execution_payload_root: Opt[Eth2Digest],
|
||||
withdrawals_root: Opt[Eth2Digest],
|
||||
kzg_commitments: Opt[KzgCommitments]):
|
||||
kzg_commitments: Opt[KzgCommitments],
|
||||
execution_requests: ExecutionRequests): # TODO probably need this for builder API, otherwise remove, maybe needs to be Opt
|
||||
Future[ForkedBlockResult] {.async: (raises: [CancelledError]).} =
|
||||
# Advance state to the slot that we're proposing for
|
||||
var cache = StateCache()
|
||||
|
@ -536,6 +537,26 @@ proc makeBeaconBlockForHeadAndSlot*(
|
|||
slot, validator_index
|
||||
return err("Unable to get execution payload")
|
||||
|
||||
# Don't use the requests passed in, TODO remove that
|
||||
let execution_requests_actual =
|
||||
when PayloadType.kind >= ConsensusFork.Electra:
|
||||
# Don't want un-decoded SSZ going any further/deeper
|
||||
try:
|
||||
ExecutionRequests(
|
||||
deposits: SSZ.decode(
|
||||
payload.executionRequests[0],
|
||||
List[DepositRequest, Limit MAX_DEPOSIT_REQUESTS_PER_PAYLOAD]),
|
||||
withdrawals: SSZ.decode(
|
||||
payload.executionRequests[1],
|
||||
List[WithdrawalRequest, Limit MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]),
|
||||
consolidations: SSZ.decode(
|
||||
payload.executionRequests[2],
|
||||
List[ConsolidationRequest, Limit MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD]))
|
||||
except CatchableError:
|
||||
return err("Unable to deserialize execution layer requests")
|
||||
else:
|
||||
default(ExecutionRequests) # won't be used by block builder
|
||||
|
||||
let res = makeBeaconBlockWithRewards(
|
||||
node.dag.cfg,
|
||||
state[],
|
||||
|
@ -553,7 +574,8 @@ proc makeBeaconBlockForHeadAndSlot*(
|
|||
verificationFlags = {},
|
||||
transactions_root = transactions_root,
|
||||
execution_payload_root = execution_payload_root,
|
||||
kzg_commitments = kzg_commitments).mapErr do (error: cstring) -> string:
|
||||
kzg_commitments = kzg_commitments,
|
||||
execution_requests = execution_requests_actual).mapErr do (error: cstring) -> string:
|
||||
# This is almost certainly a bug, but it's complex enough that there's a
|
||||
# small risk it might happen even when most proposals succeed - thus we
|
||||
# log instead of asserting
|
||||
|
@ -571,11 +593,12 @@ proc makeBeaconBlockForHeadAndSlot*(
|
|||
blck: res.get().blck,
|
||||
executionPayloadValue: payload.blockValue,
|
||||
consensusBlockValue: res.get().rewards.blockConsensusValue(),
|
||||
blobsBundleOpt: blobsBundleOpt
|
||||
blobsBundleOpt: blobsBundleOpt,
|
||||
))
|
||||
else:
|
||||
err(res.error)
|
||||
|
||||
# TODO what is this for
|
||||
proc makeBeaconBlockForHeadAndSlot*(
|
||||
PayloadType: type ForkyExecutionPayloadForSigning, node: BeaconNode, randao_reveal: ValidatorSig,
|
||||
validator_index: ValidatorIndex, graffiti: GraffitiBytes, head: BlockRef,
|
||||
|
@ -587,7 +610,8 @@ proc makeBeaconBlockForHeadAndSlot*(
|
|||
transactions_root = Opt.none(Eth2Digest),
|
||||
execution_payload_root = Opt.none(Eth2Digest),
|
||||
withdrawals_root = Opt.none(Eth2Digest),
|
||||
kzg_commitments = Opt.none(KzgCommitments))
|
||||
kzg_commitments = Opt.none(KzgCommitments),
|
||||
execution_requests = static(default(ExecutionRequests)))
|
||||
|
||||
proc getBlindedExecutionPayload[
|
||||
EPH: deneb_mev.BlindedExecutionPayloadAndBlobsBundle |
|
||||
|
@ -861,6 +885,7 @@ proc getBlindedBlockParts[
|
|||
copyFields(
|
||||
shimExecutionPayload.executionPayload, actualEPH, getFieldNames(DenebEPH))
|
||||
elif EPH is electra_mev.BlindedExecutionPayloadAndBlobsBundle:
|
||||
debugComment "verify (again, after change) this is what builder API needs"
|
||||
type PayloadType = electra.ExecutionPayloadForSigning
|
||||
template actualEPH: untyped =
|
||||
executionPayloadHeader.get.blindedBlckPart.execution_payload_header
|
||||
|
@ -877,13 +902,15 @@ proc getBlindedBlockParts[
|
|||
else:
|
||||
static: doAssert false
|
||||
|
||||
debugComment "the electra builder API bids have these requests"
|
||||
let newBlock = await makeBeaconBlockForHeadAndSlot(
|
||||
PayloadType, node, randao, validator_index, graffiti, head, slot,
|
||||
execution_payload = Opt.some shimExecutionPayload,
|
||||
transactions_root = Opt.some actualEPH.transactions_root,
|
||||
execution_payload_root = Opt.some hash_tree_root(actualEPH),
|
||||
withdrawals_root = withdrawals_root,
|
||||
kzg_commitments = kzg_commitments)
|
||||
kzg_commitments = kzg_commitments,
|
||||
execution_requests = default(ExecutionRequests))
|
||||
|
||||
if newBlock.isErr():
|
||||
# Haven't committed to the MEV block, so allow EL fallback.
|
||||
|
@ -1058,6 +1085,7 @@ proc collectBids(
|
|||
let
|
||||
payloadBuilderBidFut =
|
||||
if usePayloadBuilder:
|
||||
# TODO apparently some capella support still here?
|
||||
when not (EPS is bellatrix.ExecutionPayloadForSigning):
|
||||
getBuilderBid[SBBB](node, payloadBuilderClient, head,
|
||||
validator_pubkey, slot, randao, graffitiBytes,
|
||||
|
@ -2057,11 +2085,11 @@ proc makeMaybeBlindedBeaconBlockForHeadAndSlotImpl[ResultType](
|
|||
|
||||
collectedBids =
|
||||
await collectBids(consensusFork.SignedBlindedBeaconBlock,
|
||||
consensusFork.ExecutionPayloadForSigning,
|
||||
node,
|
||||
payloadBuilderClient, proposerKey,
|
||||
proposer, graffiti, head, slot,
|
||||
randao_reveal)
|
||||
consensusFork.ExecutionPayloadForSigning,
|
||||
node,
|
||||
payloadBuilderClient, proposerKey,
|
||||
proposer, graffiti, head, slot,
|
||||
randao_reveal)
|
||||
useBuilderBlock =
|
||||
if collectedBids.builderBid.isSome():
|
||||
collectedBids.engineBid.isNone() or builderBetterBid(
|
||||
|
|
|
@ -85,7 +85,8 @@ proc makeSimulationBlock(
|
|||
|
||||
var blck = partialBeaconBlock(
|
||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||
attestations, deposits, exits, sync_aggregate, execution_payload)
|
||||
attestations, deposits, exits, sync_aggregate, execution_payload,
|
||||
default(ExecutionRequests))
|
||||
|
||||
let res = process_block(
|
||||
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
|
||||
|
@ -128,7 +129,8 @@ proc makeSimulationBlock(
|
|||
|
||||
var blck = partialBeaconBlock(
|
||||
cfg, state, proposer_index, randao_reveal, eth1_data, graffiti,
|
||||
attestations, deposits, exits, sync_aggregate, execution_payload)
|
||||
attestations, deposits, exits, sync_aggregate, execution_payload,
|
||||
default(ExecutionRequests))
|
||||
|
||||
let res = process_block(
|
||||
cfg, state.data, blck.asSigVerified(), verificationFlags, cache)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c38791832cac2d23eab57cdc32decdd8123e5d36
|
||||
Subproject commit a2710222060de4936ca582ef677614dc4585ff12
|
Loading…
Reference in New Issue