748 lines
33 KiB
Nim
748 lines
33 KiB
Nim
# beacon_chain
|
|
# Copyright (c) 2024 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).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.push raises: [].}
|
|
|
|
import
|
|
kzg4844/[kzg_abi, kzg],
|
|
../spec/datatypes/[bellatrix, capella, deneb, electra, fulu],
|
|
web3/[engine_api, engine_api_types, eth_api_types]
|
|
|
|
from std/sequtils import mapIt
|
|
|
|
type
|
|
BellatrixExecutionPayloadWithValue* = object
|
|
executionPayload*: ExecutionPayloadV1
|
|
blockValue*: UInt256
|
|
|
|
func asEth2Digest*(x: Hash32|Bytes32): Eth2Digest =
|
|
Eth2Digest(data: array[32, byte](x))
|
|
|
|
template asBlockHash*(x: Eth2Digest): Hash32 =
|
|
Hash32(x.data)
|
|
|
|
func asConsensusWithdrawal*(w: WithdrawalV1): capella.Withdrawal =
|
|
capella.Withdrawal(
|
|
index: w.index.uint64,
|
|
validator_index: w.validatorIndex.uint64,
|
|
address: ExecutionAddress(data: w.address.distinctBase),
|
|
amount: Gwei w.amount)
|
|
|
|
func asEngineWithdrawal(w: capella.Withdrawal): WithdrawalV1 =
|
|
WithdrawalV1(
|
|
index: Quantity(w.index),
|
|
validatorIndex: Quantity(w.validator_index),
|
|
address: Address(w.address.data),
|
|
amount: Quantity(w.amount))
|
|
|
|
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1):
|
|
bellatrix.ExecutionPayload =
|
|
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
|
bellatrix.Transaction.init(tt.distinctBase)
|
|
|
|
bellatrix.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)))
|
|
|
|
func asConsensusType*(payloadWithValue: BellatrixExecutionPayloadWithValue):
|
|
bellatrix.ExecutionPayloadForSigning =
|
|
bellatrix.ExecutionPayloadForSigning(
|
|
executionPayload: payloadWithValue.executionPayload.asConsensusType,
|
|
blockValue: payloadWithValue.blockValue)
|
|
|
|
template maybeDeref*[T](o: Opt[T]): T = o.get
|
|
template maybeDeref*[V](v: V): V = v
|
|
|
|
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV1OrV2|ExecutionPayloadV2):
|
|
capella.ExecutionPayload =
|
|
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
|
bellatrix.Transaction.init(tt.distinctBase)
|
|
|
|
capella.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(maybeDeref rpcExecutionPayload.withdrawals, it.asConsensusWithdrawal)))
|
|
|
|
func asConsensusType*(payloadWithValue: engine_api.GetPayloadV2Response):
|
|
capella.ExecutionPayloadForSigning =
|
|
capella.ExecutionPayloadForSigning(
|
|
executionPayload: payloadWithValue.executionPayload.asConsensusType,
|
|
blockValue: payloadWithValue.blockValue)
|
|
|
|
func asConsensusType*(rpcExecutionPayload: ExecutionPayloadV3):
|
|
deneb.ExecutionPayload =
|
|
template getTransaction(tt: TypedTransaction): bellatrix.Transaction =
|
|
bellatrix.Transaction.init(tt.distinctBase)
|
|
|
|
deneb.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 asElectraConsensusPayload(rpcExecutionPayload: ExecutionPayloadV4):
|
|
electra.ExecutionPayload =
|
|
template getTransaction(
|
|
tt: engine_api_types.TransactionV1): electra.Eip6404Transaction =
|
|
electra.Eip6404Transaction(
|
|
payload: Eip6404TransactionPayload(
|
|
`type`:
|
|
if tt.payload.`type`.isSome:
|
|
Opt.some(tt.payload.`type`.get.uint64.uint8)
|
|
else:
|
|
Opt.none(uint8),
|
|
chain_id:
|
|
if tt.payload.chainId.isSome:
|
|
Opt.some(distinctBase(tt.payload.chainId.get))
|
|
else:
|
|
Opt.none(electra.ChainId),
|
|
nonce:
|
|
if tt.payload.nonce.isSome:
|
|
Opt.some(tt.payload.nonce.get.uint64)
|
|
else:
|
|
Opt.none(uint64),
|
|
max_fees_per_gas:
|
|
if tt.payload.maxFeesPerGas.isSome:
|
|
Opt.some(Eip6404FeesPerGas(
|
|
regular:
|
|
if tt.payload.maxFeesPerGas.get.regular.isSome:
|
|
Opt.some(tt.payload.maxFeesPerGas.get.regular.get)
|
|
else:
|
|
Opt.none(Uint256),
|
|
blob:
|
|
if tt.payload.maxFeesPerGas.get.blob.isSome:
|
|
Opt.some(tt.payload.maxFeesPerGas.get.blob.get)
|
|
else:
|
|
Opt.none(Uint256)))
|
|
else:
|
|
Opt.none(Eip6404FeesPerGas),
|
|
gas:
|
|
if tt.payload.gas.isSome:
|
|
Opt.some(tt.payload.gas.get.uint64)
|
|
else:
|
|
Opt.none(uint64),
|
|
to:
|
|
if tt.payload.to.isSome:
|
|
Opt.some(ExecutionAddress(data: tt.payload.to.get.distinctBase))
|
|
else:
|
|
Opt.none(ExecutionAddress),
|
|
value:
|
|
if tt.payload.value.isSome:
|
|
Opt.some(tt.payload.value.get)
|
|
else:
|
|
Opt.none(UInt256),
|
|
input:
|
|
if tt.payload.input.isSome:
|
|
Opt.some(List[byte, Limit MAX_CALLDATA_SIZE].init(
|
|
tt.payload.input.get))
|
|
else:
|
|
Opt.none(List[byte, Limit MAX_CALLDATA_SIZE]),
|
|
access_list:
|
|
if tt.payload.accessList.isSome:
|
|
Opt.some(List[Eip6404AccessTuple, Limit MAX_ACCESS_LIST_SIZE].init(
|
|
tt.payload.accessList.get.mapIt(
|
|
Eip6404AccessTuple(
|
|
address: ExecutionAddress(data: distinctBase(it.address)),
|
|
storage_keys:
|
|
List[Eth2Digest, Limit MAX_ACCESS_LIST_STORAGE_KEYS]
|
|
.init(it.storage_keys.mapIt(
|
|
Eth2Digest(data: distinctBase(it))))))))
|
|
else:
|
|
Opt.none(List[Eip6404AccessTuple, Limit MAX_ACCESS_LIST_SIZE]),
|
|
max_priority_fees_per_gas:
|
|
if tt.payload.maxPriorityFeesPerGas.isSome:
|
|
Opt.some(Eip6404FeesPerGas(
|
|
regular:
|
|
if tt.payload.maxPriorityFeesPerGas.get.regular.isSome:
|
|
Opt.some(tt.payload.maxPriorityFeesPerGas.get.regular.get)
|
|
else:
|
|
Opt.none(Uint256),
|
|
blob:
|
|
if tt.payload.maxPriorityFeesPerGas.get.blob.isSome:
|
|
Opt.some(tt.payload.maxPriorityFeesPerGas.get.blob.get)
|
|
else:
|
|
Opt.none(Uint256)))
|
|
else:
|
|
Opt.none(Eip6404FeesPerGas),
|
|
blob_versioned_hashes:
|
|
if tt.payload.blobVersionedHashes.isSome:
|
|
Opt.some(
|
|
List[stable.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
|
|
.init(tt.payload.blobVersionedHashes.get.mapIt(
|
|
stable.VersionedHash(it))))
|
|
else:
|
|
Opt.none(
|
|
List[stable.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]),
|
|
authorization_list:
|
|
if tt.payload.authorizationList.isSome:
|
|
Opt.some(
|
|
List[Eip6404Authorization, Limit MAX_AUTHORIZATION_LIST_SIZE]
|
|
.init(tt.payload.authorizationList.get.mapIt(
|
|
Eip6404Authorization(
|
|
payload: Eip6404AuthorizationPayload(
|
|
magic:
|
|
if it.payload.magic.isSome:
|
|
Opt.some(distinctBase(it.payload.magic.get).uint8)
|
|
else:
|
|
Opt.none(TransactionType),
|
|
chainId:
|
|
if it.payload.chainId.isSome:
|
|
Opt.some(distinctBase(it.payload.chainId.get))
|
|
else:
|
|
Opt.none(electra.ChainId),
|
|
address:
|
|
if it.payload.address.isSome:
|
|
Opt.some(ExecutionAddress(
|
|
data: distinctBase(it.payload.address.get)))
|
|
else:
|
|
Opt.none(ExecutionAddress),
|
|
nonce:
|
|
if it.payload.nonce.isSome:
|
|
Opt.some(distinctBase(it.payload.nonce.get))
|
|
else:
|
|
Opt.none(uint64)),
|
|
signature: Eip6404ExecutionSignature(
|
|
secp256k1:
|
|
if it.signature.secp256k1.isSome:
|
|
Opt.some(array[65, byte](it.signature.secp256k1.get))
|
|
else:
|
|
Opt.none(array[65, byte]))))))
|
|
else:
|
|
Opt.none(
|
|
List[Eip6404Authorization, Limit MAX_AUTHORIZATION_LIST_SIZE])),
|
|
signature: Eip6404ExecutionSignature(
|
|
secp256k1:
|
|
if tt.signature.secp256k1.isSome:
|
|
Opt.some(array[65, byte](tt.signature.secp256k1.get))
|
|
else:
|
|
Opt.none(array[65, byte])))
|
|
|
|
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[Eip6404Transaction, 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,
|
|
system_logs_root: rpcExecutionPayload.systemLogsRoot.asEth2Digest)
|
|
|
|
func asFuluConsensusPayload(rpcExecutionPayload: ExecutionPayloadV4):
|
|
fulu.ExecutionPayload =
|
|
template getTransaction(
|
|
tt: engine_api_types.TransactionV1): electra.Eip6404Transaction =
|
|
electra.Eip6404Transaction(
|
|
payload: Eip6404TransactionPayload(
|
|
`type`:
|
|
if tt.payload.`type`.isSome:
|
|
Opt.some(tt.payload.`type`.get.uint64.uint8)
|
|
else:
|
|
Opt.none(uint8),
|
|
chain_id:
|
|
if tt.payload.chainId.isSome:
|
|
Opt.some(distinctBase(tt.payload.chainId.get))
|
|
else:
|
|
Opt.none(electra.ChainId),
|
|
nonce:
|
|
if tt.payload.nonce.isSome:
|
|
Opt.some(tt.payload.nonce.get.uint64)
|
|
else:
|
|
Opt.none(uint64),
|
|
max_fees_per_gas:
|
|
if tt.payload.maxFeesPerGas.isSome:
|
|
Opt.some(Eip6404FeesPerGas(
|
|
regular:
|
|
if tt.payload.maxFeesPerGas.get.regular.isSome:
|
|
Opt.some(tt.payload.maxFeesPerGas.get.regular.get)
|
|
else:
|
|
Opt.none(Uint256),
|
|
blob:
|
|
if tt.payload.maxFeesPerGas.get.blob.isSome:
|
|
Opt.some(tt.payload.maxFeesPerGas.get.blob.get)
|
|
else:
|
|
Opt.none(Uint256)))
|
|
else:
|
|
Opt.none(Eip6404FeesPerGas),
|
|
gas:
|
|
if tt.payload.gas.isSome:
|
|
Opt.some(tt.payload.gas.get.uint64)
|
|
else:
|
|
Opt.none(uint64),
|
|
to:
|
|
if tt.payload.to.isSome:
|
|
Opt.some(ExecutionAddress(data: tt.payload.to.get.distinctBase))
|
|
else:
|
|
Opt.none(ExecutionAddress),
|
|
value:
|
|
if tt.payload.value.isSome:
|
|
Opt.some(tt.payload.value.get)
|
|
else:
|
|
Opt.none(UInt256),
|
|
input:
|
|
if tt.payload.input.isSome:
|
|
Opt.some(List[byte, Limit MAX_CALLDATA_SIZE].init(
|
|
tt.payload.input.get))
|
|
else:
|
|
Opt.none(List[byte, Limit MAX_CALLDATA_SIZE]),
|
|
access_list:
|
|
if tt.payload.accessList.isSome:
|
|
Opt.some(List[Eip6404AccessTuple, Limit MAX_ACCESS_LIST_SIZE].init(
|
|
tt.payload.accessList.get.mapIt(
|
|
Eip6404AccessTuple(
|
|
address: ExecutionAddress(data: distinctBase(it.address)),
|
|
storage_keys:
|
|
List[Eth2Digest, Limit MAX_ACCESS_LIST_STORAGE_KEYS]
|
|
.init(it.storage_keys.mapIt(
|
|
Eth2Digest(data: distinctBase(it))))))))
|
|
else:
|
|
Opt.none(List[Eip6404AccessTuple, Limit MAX_ACCESS_LIST_SIZE]),
|
|
max_priority_fees_per_gas:
|
|
if tt.payload.maxPriorityFeesPerGas.isSome:
|
|
Opt.some(Eip6404FeesPerGas(
|
|
regular:
|
|
if tt.payload.maxPriorityFeesPerGas.get.regular.isSome:
|
|
Opt.some(tt.payload.maxPriorityFeesPerGas.get.regular.get)
|
|
else:
|
|
Opt.none(Uint256),
|
|
blob:
|
|
if tt.payload.maxPriorityFeesPerGas.get.blob.isSome:
|
|
Opt.some(tt.payload.maxPriorityFeesPerGas.get.blob.get)
|
|
else:
|
|
Opt.none(Uint256)))
|
|
else:
|
|
Opt.none(Eip6404FeesPerGas),
|
|
blob_versioned_hashes:
|
|
if tt.payload.blobVersionedHashes.isSome:
|
|
Opt.some(
|
|
List[stable.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
|
|
.init(tt.payload.blobVersionedHashes.get.mapIt(
|
|
stable.VersionedHash(it))))
|
|
else:
|
|
Opt.none(
|
|
List[stable.VersionedHash, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]),
|
|
authorization_list:
|
|
if tt.payload.authorizationList.isSome:
|
|
Opt.some(
|
|
List[Eip6404Authorization, Limit MAX_AUTHORIZATION_LIST_SIZE]
|
|
.init(tt.payload.authorizationList.get.mapIt(
|
|
Eip6404Authorization(
|
|
payload: Eip6404AuthorizationPayload(
|
|
magic:
|
|
if it.payload.magic.isSome:
|
|
Opt.some(distinctBase(it.payload.magic.get).uint8)
|
|
else:
|
|
Opt.none(TransactionType),
|
|
chainId:
|
|
if it.payload.chainId.isSome:
|
|
Opt.some(distinctBase(it.payload.chainId.get))
|
|
else:
|
|
Opt.none(electra.ChainId),
|
|
address:
|
|
if it.payload.address.isSome:
|
|
Opt.some(ExecutionAddress(
|
|
data: distinctBase(it.payload.address.get)))
|
|
else:
|
|
Opt.none(ExecutionAddress),
|
|
nonce:
|
|
if it.payload.nonce.isSome:
|
|
Opt.some(distinctBase(it.payload.nonce.get))
|
|
else:
|
|
Opt.none(uint64)),
|
|
signature: Eip6404ExecutionSignature(
|
|
secp256k1:
|
|
if it.signature.secp256k1.isSome:
|
|
Opt.some(array[65, byte](it.signature.secp256k1.get))
|
|
else:
|
|
Opt.none(array[65, byte]))))))
|
|
else:
|
|
Opt.none(
|
|
List[Eip6404Authorization, Limit MAX_AUTHORIZATION_LIST_SIZE])),
|
|
signature: Eip6404ExecutionSignature(
|
|
secp256k1:
|
|
if tt.signature.secp256k1.isSome:
|
|
Opt.some(array[65, byte](tt.signature.secp256k1.get))
|
|
else:
|
|
Opt.none(array[65, byte])))
|
|
|
|
fulu.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[Eip6404Transaction, 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,
|
|
system_logs_root: rpcExecutionPayload.systemLogsRoot.asEth2Digest)
|
|
|
|
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*(
|
|
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 asConsensusTypeFulu*(
|
|
payload: GetPayloadV4Response):
|
|
fulu.ExecutionPayloadForSigning =
|
|
fulu.ExecutionPayloadForSigning(
|
|
executionPayload: payload.executionPayload.asFuluConsensusPayload,
|
|
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
|
|
|
|
template getTypedTransaction(tt: bellatrix.Transaction): TypedTransaction =
|
|
TypedTransaction(tt.distinctBase)
|
|
|
|
engine_api.ExecutionPayloadV1(
|
|
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))
|
|
|
|
template toEngineWithdrawal*(w: capella.Withdrawal): WithdrawalV1 =
|
|
WithdrawalV1(
|
|
index: Quantity(w.index),
|
|
validatorIndex: Quantity(w.validator_index),
|
|
address: Address(w.address.data),
|
|
amount: Quantity(w.amount))
|
|
|
|
func asEngineExecutionPayload*(blockBody: capella.BeaconBlockBody):
|
|
ExecutionPayloadV2 =
|
|
template executionPayload(): untyped = blockBody.execution_payload
|
|
|
|
template getTypedTransaction(tt: bellatrix.Transaction): TypedTransaction =
|
|
TypedTransaction(tt.distinctBase)
|
|
engine_api.ExecutionPayloadV2(
|
|
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.toEngineWithdrawal))
|
|
|
|
func asEngineExecutionPayload*(
|
|
blockBody: deneb.BeaconBlockBody):
|
|
ExecutionPayloadV3 =
|
|
template executionPayload(): untyped = blockBody.execution_payload
|
|
|
|
template getTypedTransaction(tt: bellatrix.Transaction): TypedTransaction =
|
|
TypedTransaction(tt.distinctBase)
|
|
|
|
engine_api.ExecutionPayloadV3(
|
|
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))
|
|
|
|
func asEngineExecutionPayload*(
|
|
blockBody: electra.BeaconBlockBody | fulu.BeaconBlockBody):
|
|
ExecutionPayloadV4 =
|
|
template executionPayload(): untyped = blockBody.execution_payload
|
|
|
|
template getTypedTransaction(
|
|
tt: electra.Eip6404Transaction): engine_api_types.TransactionV1 =
|
|
engine_api_types.TransactionV1(
|
|
payload: engine_api_types.TransactionPayloadV1(
|
|
`type`:
|
|
if tt.payload.`type`.isSome:
|
|
Opt.some(tt.payload.`type`.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity),
|
|
chainId:
|
|
if tt.payload.chain_id.isSome:
|
|
Opt.some(tt.payload.chain_id.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity),
|
|
nonce:
|
|
if tt.payload.nonce.isSome:
|
|
Opt.some(tt.payload.nonce.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity),
|
|
maxFeesPerGas:
|
|
if tt.payload.max_fees_per_gas.isSome:
|
|
Opt.some(engine_api_types.FeesPerGasV1(
|
|
regular:
|
|
if tt.payload.max_fees_per_gas.get.regular.isSome:
|
|
Opt.some(tt.payload.max_fees_per_gas.get.regular.get)
|
|
else:
|
|
Opt.none(UInt256),
|
|
blob:
|
|
if tt.payload.max_fees_per_gas.get.blob.isSome:
|
|
Opt.some(tt.payload.max_fees_per_gas.get.blob.get)
|
|
else:
|
|
Opt.none(UInt256)))
|
|
else:
|
|
Opt.none(engine_api_types.FeesPerGasV1),
|
|
gas:
|
|
if tt.payload.gas.isSome:
|
|
Opt.some(tt.payload.gas.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity),
|
|
to:
|
|
if tt.payload.to.isSome:
|
|
Opt.some(Address(tt.payload.to.get.data))
|
|
else:
|
|
Opt.none(Address),
|
|
value:
|
|
if tt.payload.value.isSome:
|
|
Opt.some(tt.payload.value.get)
|
|
else:
|
|
Opt.none(UInt256),
|
|
input:
|
|
if tt.payload.input.isSome:
|
|
Opt.some(distinctBase(tt.payload.input.get))
|
|
else:
|
|
Opt.none(seq[byte]),
|
|
accessList:
|
|
if tt.payload.access_list.isSome:
|
|
Opt.some(distinctBase(tt.payload.access_list.get).mapIt(
|
|
AccessTupleV1(
|
|
address: Address(it.address.data),
|
|
storage_keys: distinctBase(it.storage_keys)
|
|
.mapIt(FixedBytes[32](it.data)))))
|
|
else:
|
|
Opt.none(seq[AccessTupleV1]),
|
|
maxPriorityFeesPerGas:
|
|
if tt.payload.max_priority_fees_per_gas.isSome:
|
|
Opt.some(engine_api_types.FeesPerGasV1(
|
|
regular:
|
|
if tt.payload.max_priority_fees_per_gas.get.regular.isSome:
|
|
Opt.some(
|
|
tt.payload.max_priority_fees_per_gas.get.regular.get)
|
|
else:
|
|
Opt.none(UInt256),
|
|
blob:
|
|
if tt.payload.max_priority_fees_per_gas.get.blob.isSome:
|
|
Opt.some(
|
|
tt.payload.max_priority_fees_per_gas.get.blob.get)
|
|
else:
|
|
Opt.none(UInt256)))
|
|
else:
|
|
Opt.none(engine_api_types.FeesPerGasV1),
|
|
blobVersionedHashes:
|
|
if tt.payload.blob_versioned_hashes.isSome:
|
|
Opt.some(distinctBase(tt.payload.blob_versioned_hashes.get)
|
|
.mapIt(FixedBytes[32](it)))
|
|
else:
|
|
Opt.none(seq[FixedBytes[32]]),
|
|
authorizationList:
|
|
if tt.payload.authorization_list.isSome:
|
|
Opt.some(distinctBase(tt.payload.authorization_list.get).mapIt(
|
|
AuthorizationV1(
|
|
payload: AuthorizationPayloadV1(
|
|
magic:
|
|
if it.payload.magic.isSome:
|
|
Opt.some(it.payload.magic.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity),
|
|
chainId:
|
|
if it.payload.chain_id.isSome:
|
|
Opt.some(it.payload.chain_id.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity),
|
|
address:
|
|
if it.payload.address.isSome:
|
|
Opt.some(Address(it.payload.address.get.data))
|
|
else:
|
|
Opt.none(Address),
|
|
nonce:
|
|
if it.payload.nonce.isSome:
|
|
Opt.some(it.payload.nonce.get.Quantity)
|
|
else:
|
|
Opt.none(Quantity)),
|
|
signature: engine_api_types.ExecutionSignatureV1(
|
|
secp256k1:
|
|
if it.signature.secp256k1.isSome:
|
|
Opt.some(FixedBytes[65](it.signature.secp256k1.get))
|
|
else:
|
|
Opt.none(FixedBytes[65])))))
|
|
else:
|
|
Opt.none(seq[AuthorizationV1])),
|
|
signature: engine_api_types.ExecutionSignatureV1(
|
|
secp256k1:
|
|
if tt.signature.secp256k1.isSome:
|
|
Opt.some(FixedBytes[65](tt.signature.secp256k1.get))
|
|
else:
|
|
Opt.none(FixedBytes[65])))
|
|
|
|
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),
|
|
systemLogsRoot: executionPayload.system_logs_root.asBlockHash)
|