Skip to content

Commit

Permalink
update to devnet-4-compatible engine API (#6657)
Browse files Browse the repository at this point in the history
  • Loading branch information
tersec authored Oct 17, 2024
1 parent 6df8f92 commit 2d3614f
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 261 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -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 )) \
Expand Down
25 changes: 18 additions & 7 deletions beacon_chain/el/el_manager.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
133 changes: 28 additions & 105 deletions beacon_chain/el/engine_api_conversions.nim
Original file line number Diff line number Diff line change
Expand Up @@ -129,53 +129,11 @@ func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV3):
blob_gas_used: rpcExecutionPayload.blobGasUsed.uint64,
excess_blob_gas: rpcExecutionPayload.excessBlobGas.uint64)

func asConsensusType*(payload: engine_api.GetPayloadV3Response):
deneb.ExecutionPayloadForSigning =
deneb.ExecutionPayloadForSigning(
executionPayload: payload.executionPayload.asConsensusType,
blockValue: payload.blockValue,
# TODO
# The `mapIt` calls below are necessary only because we use different distinct
# types for KZG commitments and Blobs in the `web3` and the `deneb` spec types.
# Both are defined as `array[N, byte]` under the hood.
blobsBundle: deneb.BlobsBundle(
commitments: KzgCommitments.init(
payload.blobsBundle.commitments.mapIt(
kzg_abi.KzgCommitment(bytes: it.data))),
proofs: KzgProofs.init(
payload.blobsBundle.proofs.mapIt(
kzg_abi.KzgProof(bytes: it.data))),
blobs: Blobs.init(
payload.blobsBundle.blobs.mapIt(it.data))))

func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV4):
func asElectraConsensusPayload(rpcExecutionPayload: ExecutionPayloadV3):
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:
Expand All @@ -188,8 +146,7 @@ func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV4):
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),
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(
Expand All @@ -199,9 +156,9 @@ func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV4):
blob_gas_used: rpcExecutionPayload.blobGasUsed.uint64,
excess_blob_gas: rpcExecutionPayload.excessBlobGas.uint64)

func asConsensusType*(payload: engine_api.GetPayloadV4Response):
electra.ExecutionPayloadForSigning =
electra.ExecutionPayloadForSigning(
func asConsensusType*(payload: engine_api.GetPayloadV3Response):
deneb.ExecutionPayloadForSigning =
deneb.ExecutionPayloadForSigning(
executionPayload: payload.executionPayload.asConsensusType,
blockValue: payload.blockValue,
# TODO
Expand All @@ -218,6 +175,27 @@ func asConsensusType*(payload: engine_api.GetPayloadV4Response):
blobs: Blobs.init(
payload.blobsBundle.blobs.mapIt(it.data))))

func asConsensusType*(
payload: engine_api.GetPayloadV4Response):
electra.ExecutionPayloadForSigning =
electra.ExecutionPayloadForSigning(
executionPayload: payload.executionPayload.asElectraConsensusPayload,
blockValue: payload.blockValue,
# TODO
# The `mapIt` calls below are necessary only because we use different distinct
# types for KZG commitments and Blobs in the `web3` and the `deneb` spec types.
# Both are defined as `array[N, byte]` under the hood.
blobsBundle: deneb.BlobsBundle(
commitments: KzgCommitments.init(
payload.blobsBundle.commitments.mapIt(
kzg_abi.KzgCommitment(bytes: it.data))),
proofs: KzgProofs.init(
payload.blobsBundle.proofs.mapIt(
kzg_abi.KzgProof(bytes: it.data))),
blobs: Blobs.init(
payload.blobsBundle.blobs.mapIt(it.data))),
executionRequests: payload.executionRequests)

func asEngineExecutionPayload*(blockBody: bellatrix.BeaconBlockBody):
ExecutionPayloadV1 =
template executionPayload(): untyped = blockBody.execution_payload
Expand Down Expand Up @@ -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

Expand All @@ -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))
Loading

0 comments on commit 2d3614f

Please sign in to comment.