add engine API V3 of Cancun
This commit is contained in:
parent
ec17a5a348
commit
a7db7b9101
|
@ -27,7 +27,8 @@ import
|
|||
clique_cfg,
|
||||
clique_sealer],
|
||||
../utils/utils,
|
||||
../common/[common, context]
|
||||
../common/[common, context],
|
||||
../rpc/execution_types
|
||||
|
||||
|
||||
from web3/ethtypes as web3types import nil, TypedTransaction, WithdrawalV1, ExecutionPayloadV1OrV2, toExecutionPayloadV1OrV2, toExecutionPayloadV1
|
||||
|
@ -158,7 +159,7 @@ func toWithdrawals(list: openArray[WithdrawalV1]): seq[Withdrawal] =
|
|||
result.add toWithdrawal(x)
|
||||
|
||||
proc generateExecutionPayload*(engine: SealingEngineRef,
|
||||
payloadAttrs: PayloadAttributesV1 | PayloadAttributesV2): Result[ExecutionPayloadV1OrV2, string] =
|
||||
payloadAttrs: SomePayloadAttributes): Result[ExecutionPayload, string] =
|
||||
let
|
||||
headBlock = try: engine.chain.db.getCanonicalHead()
|
||||
except CatchableError: return err "No head block in database"
|
||||
|
@ -170,6 +171,8 @@ proc generateExecutionPayload*(engine: SealingEngineRef,
|
|||
|
||||
when payloadAttrs is PayloadAttributesV2:
|
||||
engine.txPool.withdrawals = payloadAttrs.withdrawals.toWithdrawals
|
||||
elif payloadAttrs is PayloadAttributesV3:
|
||||
engine.txPool.withdrawals = payloadAttrs.withdrawals.toWithdrawals
|
||||
else:
|
||||
engine.txPool.withdrawals = @[]
|
||||
|
||||
|
@ -199,7 +202,17 @@ proc generateExecutionPayload*(engine: SealingEngineRef,
|
|||
else:
|
||||
none[seq[WithdrawalV1]]()
|
||||
|
||||
return ok(ExecutionPayloadV1OrV2(
|
||||
let blobGasUsed = if blk.header.blobGasUsed.isSome:
|
||||
some(blk.header.blobGasUsed.get.Quantity)
|
||||
else:
|
||||
none(Quantity)
|
||||
|
||||
let excessBlobGas = if blk.header.excessBlobGas.isSome:
|
||||
some(blk.header.excessBlobGas.get.Quantity)
|
||||
else:
|
||||
none(Quantity)
|
||||
|
||||
return ok(ExecutionPayload(
|
||||
parentHash: Web3BlockHash blk.header.parentHash.data,
|
||||
feeRecipient: Web3Address blk.header.coinbase,
|
||||
stateRoot: Web3BlockHash blk.header.stateRoot.data,
|
||||
|
@ -214,13 +227,11 @@ proc generateExecutionPayload*(engine: SealingEngineRef,
|
|||
baseFeePerGas: blk.header.fee.get(UInt256.zero),
|
||||
blockHash: Web3BlockHash blockHash.data,
|
||||
transactions: transactions,
|
||||
withdrawals: withdrawals
|
||||
withdrawals: withdrawals,
|
||||
blobGasUsed: blobGasUsed,
|
||||
excessBlobGas: excessBlobGas
|
||||
))
|
||||
|
||||
proc generateExecutionPayloadV1*(engine: SealingEngineRef,
|
||||
payloadAttrs: PayloadAttributesV1): Result[ExecutionPayloadV1, string] =
|
||||
return generateExecutionPayload(engine, payloadAttrs).map(toExecutionPayloadV1)
|
||||
|
||||
proc new*(_: type SealingEngineRef,
|
||||
chain: ChainRef,
|
||||
ctx: EthContext,
|
||||
|
|
|
@ -11,7 +11,8 @@ import
|
|||
std/[typetraits, times, strutils, sequtils, sets],
|
||||
stew/[results, byteutils],
|
||||
json_rpc/rpcserver,
|
||||
web3/[conversions, engine_api_types],
|
||||
web3/[conversions],
|
||||
web3/engine_api_types as web3types,
|
||||
eth/rlp,
|
||||
eth/common/eth_types,
|
||||
eth/common/eth_types_rlp,
|
||||
|
@ -22,6 +23,7 @@ import
|
|||
../core/[tx_pool, sealer],
|
||||
../evm/async/data_sources,
|
||||
./merge/[mergetypes, mergeutils],
|
||||
./execution_types,
|
||||
# put chronicles import last because Nim
|
||||
# compiler resolve `$` for logging
|
||||
# arguments differently on Windows vs posix
|
||||
|
@ -30,7 +32,11 @@ import
|
|||
|
||||
{.push raises: [].}
|
||||
|
||||
type Hash256 = eth_types.Hash256
|
||||
type
|
||||
Hash256 = eth_types.Hash256
|
||||
Web3Blob = web3types.Blob
|
||||
Web3KZGProof = web3types.KZGProof
|
||||
Web3KZGCommitment = web3types.KZGCommitment
|
||||
|
||||
|
||||
func toPayloadAttributesV1OrPayloadAttributesV2*(a: PayloadAttributesV1OrV2): Result[PayloadAttributesV1, PayloadAttributesV2] =
|
||||
|
@ -92,7 +98,10 @@ template unsafeQuantityToInt64(q: Quantity): int64 =
|
|||
# null.) --Adam
|
||||
|
||||
# https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_newpayloadv1
|
||||
proc handle_newPayload(sealingEngine: SealingEngineRef, api: EngineApiRef, com: CommonRef, maybeAsyncDataSource: Option[AsyncDataSource], payload: ExecutionPayloadV1 | ExecutionPayloadV2): PayloadStatusV1 {.raises: [CatchableError].} =
|
||||
proc handle_newPayload(sealingEngine: SealingEngineRef,
|
||||
api: EngineApiRef,
|
||||
com: CommonRef, maybeAsyncDataSource: Option[AsyncDataSource],
|
||||
payload: SomeExecutionPayload): PayloadStatusV1 {.raises: [CatchableError].} =
|
||||
trace "Engine API request received",
|
||||
meth = "newPayload", number = $(distinctBase payload.blockNumber), hash = payload.blockHash
|
||||
|
||||
|
@ -221,6 +230,41 @@ proc handle_getPayload(api: EngineApiRef, payloadId: PayloadID): GetPayloadV2Res
|
|||
blockValue: blockValue
|
||||
)
|
||||
|
||||
proc handle_getPayloadV3(api: EngineApiRef, com: CommonRef, payloadId: PayloadID): GetPayloadV3Response {.raises: [CatchableError].} =
|
||||
trace "Engine API request received",
|
||||
meth = "GetPayload", id = payloadId.toHex
|
||||
|
||||
var payload: ExecutionPayloadV3
|
||||
if not api.get(payloadId, payload):
|
||||
raise unknownPayload("Unknown payload")
|
||||
|
||||
if not com.isCancunOrLater(fromUnix(payload.timestamp.unsafeQuantityToInt64)):
|
||||
raise unsupportedFork("payload timestamp is less than Cancun activation")
|
||||
|
||||
var
|
||||
blockValue: UInt256
|
||||
blobsBundle: BlobsBundleV1
|
||||
|
||||
try:
|
||||
for ttx in payload.transactions:
|
||||
let tx = rlp.decode(distinctBase(ttx), Transaction)
|
||||
blockValue += u256(tx.gasPrice * tx.maxPriorityFee)
|
||||
if tx.networkPayload.isNil.not:
|
||||
for blob in tx.networkPayload.blobs:
|
||||
blobsBundle.blobs.add Web3Blob(blob)
|
||||
for p in tx.networkPayload.proofs:
|
||||
blobsBundle.proofs.add Web3KZGProof(p)
|
||||
for k in tx.networkPayload.commitments:
|
||||
blobsBundle.commitments.add Web3KZGCommitment(k)
|
||||
except RlpError:
|
||||
doAssert(false, "found TypedTransaction that RLP failed to decode")
|
||||
|
||||
return GetPayloadV3Response(
|
||||
executionPayload: payload,
|
||||
blockValue: blockValue,
|
||||
blobsBundle: blobsBundle
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#engine_exchangetransitionconfigurationv1
|
||||
proc handle_exchangeTransitionConfiguration(sealingEngine: SealingEngineRef, com: CommonRef, conf: TransitionConfigurationV1): TransitionConfigurationV1 {.raises: [CatchableError].} =
|
||||
trace "Engine API request received",
|
||||
|
@ -281,10 +325,16 @@ proc handle_exchangeTransitionConfiguration(sealingEngine: SealingEngineRef, com
|
|||
# If there are payloadAttributes:
|
||||
# we try to assemble a block with the payloadAttributes and return its payloadID
|
||||
# https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_forkchoiceupdatedv2
|
||||
proc handle_forkchoiceUpdated(sealingEngine: SealingEngineRef, com: CommonRef, api: EngineApiRef, update: ForkchoiceStateV1, payloadAttributes: Option[PayloadAttributesV1] | Option[PayloadAttributesV2]): ForkchoiceUpdatedResponse {.raises: [CatchableError].} =
|
||||
proc handle_forkchoiceUpdated(sealingEngine: SealingEngineRef,
|
||||
com: CommonRef, api: EngineApiRef,
|
||||
update: ForkchoiceStateV1,
|
||||
payloadAttributes: SomeOptionalPayloadAttributes): ForkchoiceUpdatedResponse {.raises: [CatchableError].} =
|
||||
|
||||
if payloadAttributes.isSome:
|
||||
if com.isShanghaiOrLater(fromUnix(payloadAttributes.get.timestamp.unsafeQuantityToInt64)):
|
||||
if com.isCancunOrLater(fromUnix(payloadAttributes.get.timestamp.unsafeQuantityToInt64)):
|
||||
when not(payloadAttributes is Option[PayloadAttributesV3]):
|
||||
raise invalidParams("if timestamp is Cancun or later, payloadAttributes must be PayloadAttributesV3")
|
||||
elif com.isShanghaiOrLater(fromUnix(payloadAttributes.get.timestamp.unsafeQuantityToInt64)):
|
||||
when not(payloadAttributes is Option[PayloadAttributesV2]):
|
||||
raise invalidParams("if timestamp is Shanghai or later, payloadAttributes must be PayloadAttributesV2")
|
||||
else:
|
||||
|
@ -475,6 +525,7 @@ const supportedMethods: HashSet[string] =
|
|||
"engine_exchangeTransitionConfigurationV1",
|
||||
"engine_forkchoiceUpdatedV1",
|
||||
"engine_forkchoiceUpdatedV2",
|
||||
"engine_forkchoiceUpdatedV3",
|
||||
"engine_getPayloadBodiesByHashV1"
|
||||
])
|
||||
|
||||
|
@ -498,12 +549,31 @@ proc setupEngineAPI*(
|
|||
server.rpc("engine_newPayloadV1") do(payload: ExecutionPayloadV1) -> PayloadStatusV1:
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, payload)
|
||||
|
||||
server.rpc("engine_newPayloadV2") do(payload: ExecutionPayloadV1OrV2) -> PayloadStatusV1:
|
||||
let p = payload.toExecutionPayloadV1OrExecutionPayloadV2
|
||||
if p.isOk:
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, p.get)
|
||||
server.rpc("engine_newPayloadV2") do(payload: ExecutionPayload) -> PayloadStatusV1:
|
||||
if payload.version == Version.V1:
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, payload.V1)
|
||||
else:
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, p.error)
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, payload.V2)
|
||||
|
||||
server.rpc("engine_newPayloadV3") do(payload: ExecutionPayload,
|
||||
expectedBlobVersionedHashes: seq[FixedBytes[32]],
|
||||
parentBeaconBlockRoot: FixedBytes[32]) -> PayloadStatusV1:
|
||||
case payload.version:
|
||||
of Version.V1:
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, payload.V1)
|
||||
of Version.V2:
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, payload.V2)
|
||||
of Version.V3:
|
||||
if not com.isCancunOrLater(fromUnix(payload.timestamp.unsafeQuantityToInt64)):
|
||||
raise unsupportedFork("payload timestamp is less than Cancun activation")
|
||||
var versionedHashes: seq[Hash256]
|
||||
for x in payload.transactions:
|
||||
let tx = rlp.decode(distinctBase(x), Transaction)
|
||||
versionedHashes.add tx.versionedHashes
|
||||
for i, x in expectedBlobVersionedHashes:
|
||||
if distinctBase(x) != versionedHashes[i].data:
|
||||
return invalidStatus()
|
||||
return handle_newPayload(sealingEngine, api, com, maybeAsyncDataSource, payload.V3)
|
||||
|
||||
server.rpc("engine_getPayloadV1") do(payloadId: PayloadID) -> ExecutionPayloadV1:
|
||||
let r = handle_getPayload(api, payloadId)
|
||||
|
@ -512,6 +582,9 @@ proc setupEngineAPI*(
|
|||
server.rpc("engine_getPayloadV2") do(payloadId: PayloadID) -> GetPayloadV2Response:
|
||||
return handle_getPayload(api, payloadId)
|
||||
|
||||
server.rpc("engine_getPayloadV3") do(payloadId: PayloadID) -> GetPayloadV3Response:
|
||||
return handle_getPayloadV3(api, com, payloadId)
|
||||
|
||||
server.rpc("engine_exchangeTransitionConfigurationV1") do(conf: TransitionConfigurationV1) -> TransitionConfigurationV1:
|
||||
return handle_exchangeTransitionConfiguration(sealingEngine, com, conf)
|
||||
|
||||
|
@ -522,15 +595,30 @@ proc setupEngineAPI*(
|
|||
|
||||
server.rpc("engine_forkchoiceUpdatedV2") do(
|
||||
update: ForkchoiceStateV1,
|
||||
payloadAttributes: Option[PayloadAttributesV1OrV2]) -> ForkchoiceUpdatedResponse:
|
||||
payloadAttributes: Option[PayloadAttributes]) -> ForkchoiceUpdatedResponse:
|
||||
if payloadAttributes.isNone:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, none[PayloadAttributesV2]())
|
||||
else:
|
||||
let a = payloadAttributes.get.toPayloadAttributesV1OrPayloadAttributesV2
|
||||
if a.isOk:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(a.get))
|
||||
let attr = payloadAttributes.get
|
||||
if attr.version == Version.V1:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(attr.V1))
|
||||
else:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(a.error))
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(attr.V2))
|
||||
|
||||
server.rpc("engine_forkchoiceUpdatedV3") do(
|
||||
update: ForkchoiceStateV1,
|
||||
payloadAttributes: Option[PayloadAttributes]) -> ForkchoiceUpdatedResponse:
|
||||
if payloadAttributes.isNone:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, none[PayloadAttributesV3]())
|
||||
else:
|
||||
let attr = payloadAttributes.get
|
||||
case attr.version
|
||||
of Version.V1:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(attr.V1))
|
||||
of Version.V2:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(attr.V2))
|
||||
of Version.V3:
|
||||
return handle_forkchoiceUpdated(sealingEngine, com, api, update, some(attr.V3))
|
||||
|
||||
server.rpc("engine_getPayloadBodiesByHashV1") do(
|
||||
hashes: seq[BlockHash]) -> seq[Option[ExecutionPayloadBodyV1]]:
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
import
|
||||
stint,
|
||||
web3/ethtypes,
|
||||
web3/engine_api_types
|
||||
|
||||
export
|
||||
engine_api_types
|
||||
|
||||
type
|
||||
ExecutionPayload* = object
|
||||
parentHash*: Hash256
|
||||
feeRecipient*: Address
|
||||
stateRoot*: Hash256
|
||||
receiptsRoot*: Hash256
|
||||
logsBloom*: FixedBytes[256]
|
||||
prevRandao*: FixedBytes[32]
|
||||
blockNumber*: Quantity
|
||||
gasLimit*: Quantity
|
||||
gasUsed*: Quantity
|
||||
timestamp*: Quantity
|
||||
extraData*: DynamicBytes[0, 32]
|
||||
baseFeePerGas*: UInt256
|
||||
blockHash*: Hash256
|
||||
transactions*: seq[TypedTransaction]
|
||||
withdrawals*: Option[seq[WithdrawalV1]]
|
||||
blobGasUsed*: Option[Quantity]
|
||||
excessBlobGas*: Option[Quantity]
|
||||
|
||||
PayloadAttributes* = object
|
||||
timestamp*: Quantity
|
||||
prevRandao*: FixedBytes[32]
|
||||
suggestedFeeRecipient*: Address
|
||||
withdrawals*: Option[seq[WithdrawalV1]]
|
||||
parentBeaconBlockRoot*: Option[FixedBytes[32]]
|
||||
|
||||
SomePayloadAttributes* =
|
||||
PayloadAttributesV1 |
|
||||
PayloadAttributesV2 |
|
||||
PayloadAttributesV3
|
||||
|
||||
SomeOptionalPayloadAttributes* =
|
||||
Option[PayloadAttributesV1] |
|
||||
Option[PayloadAttributesV2] |
|
||||
Option[PayloadAttributesV3]
|
||||
|
||||
Version* {.pure.} = enum
|
||||
V1
|
||||
V2
|
||||
V3
|
||||
|
||||
func version*(payload: ExecutionPayload): Version =
|
||||
if payload.blobGasUsed.isSome and payload.excessBlobGas.isSome:
|
||||
return Version.V3
|
||||
|
||||
if payload.withdrawals.isSome:
|
||||
return Version.V2
|
||||
|
||||
Version.V1
|
||||
|
||||
func version*(attr: PayloadAttributes): Version =
|
||||
if attr.parentBeaconBlockRoot.isSome:
|
||||
return Version.V3
|
||||
|
||||
if attr.withdrawals.isSome:
|
||||
return Version.V2
|
||||
|
||||
Version.V1
|
||||
|
||||
func V1V2*(attr: PayloadAttributes): PayloadAttributesV1OrV2 =
|
||||
PayloadAttributesV1OrV2(
|
||||
timestamp: attr.timestamp,
|
||||
prevRandao: attr.prevRandao,
|
||||
suggestedFeeRecipient: attr.suggestedFeeRecipient,
|
||||
withdrawals: attr.withdrawals
|
||||
)
|
||||
|
||||
func V1*(attr: PayloadAttributes): PayloadAttributesV1 =
|
||||
PayloadAttributesV1(
|
||||
timestamp: attr.timestamp,
|
||||
prevRandao: attr.prevRandao,
|
||||
suggestedFeeRecipient: attr.suggestedFeeRecipient
|
||||
)
|
||||
|
||||
func V2*(attr: PayloadAttributes): PayloadAttributesV2 =
|
||||
PayloadAttributesV2(
|
||||
timestamp: attr.timestamp,
|
||||
prevRandao: attr.prevRandao,
|
||||
suggestedFeeRecipient: attr.suggestedFeeRecipient,
|
||||
withdrawals: attr.withdrawals.get
|
||||
)
|
||||
|
||||
func V3*(attr: PayloadAttributes): PayloadAttributesV3 =
|
||||
PayloadAttributesV3(
|
||||
timestamp: attr.timestamp,
|
||||
prevRandao: attr.prevRandao,
|
||||
suggestedFeeRecipient: attr.suggestedFeeRecipient,
|
||||
withdrawals: attr.withdrawals.get,
|
||||
parentBeaconBlockRoot: attr.parentBeaconBlockRoot.get
|
||||
)
|
||||
|
||||
func V1V2*(p: ExecutionPayload): ExecutionPayloadV1OrV2 =
|
||||
ExecutionPayloadV1OrV2(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions,
|
||||
withdrawals: p.withdrawals
|
||||
)
|
||||
|
||||
func V1*(p: ExecutionPayload): ExecutionPayloadV1 =
|
||||
ExecutionPayloadV1(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions
|
||||
)
|
||||
|
||||
func V2*(p: ExecutionPayload): ExecutionPayloadV2 =
|
||||
ExecutionPayloadV2(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions,
|
||||
withdrawals: p.withdrawals.get
|
||||
)
|
||||
|
||||
func V3*(p: ExecutionPayload): ExecutionPayloadV3 =
|
||||
ExecutionPayloadV3(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions,
|
||||
withdrawals: p.withdrawals.get,
|
||||
blobGasUsed: p.blobGasUsed.get,
|
||||
excessBlobGas: p.excessBlobGas.get
|
||||
)
|
||||
|
||||
func executionPayload*(p: ExecutionPayloadV1): ExecutionPayload =
|
||||
ExecutionPayload(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions
|
||||
)
|
||||
|
||||
func executionPayload*(p: ExecutionPayloadV2): ExecutionPayload =
|
||||
ExecutionPayload(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions,
|
||||
withdrawals: some(p.withdrawals)
|
||||
)
|
||||
|
||||
func executionPayload*(p: ExecutionPayloadV3): ExecutionPayload =
|
||||
ExecutionPayload(
|
||||
parentHash: p.parentHash,
|
||||
feeRecipient: p.feeRecipient,
|
||||
stateRoot: p.stateRoot,
|
||||
receiptsRoot: p.receiptsRoot,
|
||||
logsBloom: p.logsBloom,
|
||||
prevRandao: p.prevRandao,
|
||||
blockNumber: p.blockNumber,
|
||||
gasLimit: p.gasLimit,
|
||||
gasUsed: p.gasUsed,
|
||||
timestamp: p.timestamp,
|
||||
extraData: p.extraData,
|
||||
baseFeePerGas: p.baseFeePerGas,
|
||||
blockHash: p.blockHash,
|
||||
transactions: p.transactions,
|
||||
withdrawals: some(p.withdrawals),
|
||||
blobGasUsed: some(p.blobGasUsed),
|
||||
excessBlobGas: some(p.excessBlobGas)
|
||||
)
|
|
@ -28,10 +28,10 @@ type
|
|||
db : CoreDbRef
|
||||
status: TransitionStatus
|
||||
|
||||
proc writeStatus(db: CoreDbRef, status: TransitionStatus) {.gcsafe, raises: [RlpError].} =
|
||||
proc writeStatus(db: CoreDbRef, status: TransitionStatus) {.gcsafe, raises: [].} =
|
||||
db.kvt.put(transitionStatusKey().toOpenArray(), rlp.encode(status))
|
||||
|
||||
proc readStatus(db: CoreDbRef): TransitionStatus {.gcsafe, raises: [RlpError].} =
|
||||
proc readStatus(db: CoreDbRef): TransitionStatus {.gcsafe, raises: [].} =
|
||||
var bytes = db.kvt.get(transitionStatusKey().toOpenArray())
|
||||
if bytes.len > 0:
|
||||
try:
|
||||
|
@ -39,7 +39,7 @@ proc readStatus(db: CoreDbRef): TransitionStatus {.gcsafe, raises: [RlpError].}
|
|||
except CatchableError:
|
||||
error "Failed to decode POS transition status"
|
||||
|
||||
proc new*(_: type MergerRef, db: CoreDbRef): MergerRef {.gcsafe, raises: [RlpError].} =
|
||||
proc new*(_: type MergerRef, db: CoreDbRef): MergerRef {.gcsafe, raises: [].} =
|
||||
MergerRef(
|
||||
db: db,
|
||||
status: db.readStatus()
|
||||
|
@ -47,7 +47,7 @@ proc new*(_: type MergerRef, db: CoreDbRef): MergerRef {.gcsafe, raises: [RlpErr
|
|||
|
||||
# ReachTTD is called whenever the first NewHead message received
|
||||
# from the consensus-layer.
|
||||
proc reachTTD*(m: MergerRef) {.gcsafe, raises: [RlpError].} =
|
||||
proc reachTTD*(m: MergerRef) {.gcsafe, raises: [].} =
|
||||
if m.status.leftPoW:
|
||||
return
|
||||
|
||||
|
@ -58,7 +58,7 @@ proc reachTTD*(m: MergerRef) {.gcsafe, raises: [RlpError].} =
|
|||
|
||||
# FinalizePoS is called whenever the first FinalisedBlock message received
|
||||
# from the consensus-layer.
|
||||
proc finalizePoS*(m: MergerRef) {.gcsafe, raises: [RlpError].} =
|
||||
proc finalizePoS*(m: MergerRef) {.gcsafe, raises: [].} =
|
||||
if m.status.enteredPoS:
|
||||
return
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
import
|
||||
web3/engine_api_types,
|
||||
./merger
|
||||
./merger,
|
||||
../execution_types
|
||||
|
||||
|
||||
import eth/common/eth_types except BlockHeader
|
||||
|
||||
|
@ -40,7 +42,7 @@ type
|
|||
|
||||
PayloadItem = object
|
||||
id: PayloadID
|
||||
payload: ExecutionPayloadV1OrV2
|
||||
payload: ExecutionPayload
|
||||
|
||||
HeaderItem = object
|
||||
hash: Hash256
|
||||
|
@ -81,16 +83,13 @@ proc get*(api: EngineApiRef, hash: Hash256, header: var EthBlockHeader): bool =
|
|||
return true
|
||||
false
|
||||
|
||||
proc put*(api: EngineApiRef, id: PayloadID, payload: ExecutionPayloadV1OrV2) =
|
||||
proc put*(api: EngineApiRef, id: PayloadID, payload: ExecutionPayload) =
|
||||
api.payloadQueue.put(PayloadItem(id: id, payload: payload))
|
||||
|
||||
proc put*(api: EngineApiRef, id: PayloadID, payload: ExecutionPayloadV1) =
|
||||
api.put(id, payload.toExecutionPayloadV1OrV2)
|
||||
proc put*(api: EngineApiRef, id: PayloadID, payload: SomeExecutionPayload) =
|
||||
api.put(id, payload.executionPayload)
|
||||
|
||||
proc put*(api: EngineApiRef, id: PayloadID, payload: ExecutionPayloadV2) =
|
||||
api.put(id, payload.toExecutionPayloadV1OrV2)
|
||||
|
||||
proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayloadV1OrV2): bool =
|
||||
proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayload): bool =
|
||||
for x in api.payloadQueue:
|
||||
if x.id == id:
|
||||
payload = x.payload
|
||||
|
@ -98,9 +97,31 @@ proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayloadV1OrV2)
|
|||
false
|
||||
|
||||
proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayloadV1): bool =
|
||||
var p: ExecutionPayloadV1OrV2
|
||||
var p: ExecutionPayload
|
||||
let found = api.get(id, p)
|
||||
payload = p.toExecutionPayloadV1
|
||||
doAssert(p.version == Version.V1)
|
||||
payload = p.V1
|
||||
return found
|
||||
|
||||
proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayloadV2): bool =
|
||||
var p: ExecutionPayload
|
||||
let found = api.get(id, p)
|
||||
doAssert(p.version == Version.V2)
|
||||
payload = p.V2
|
||||
return found
|
||||
|
||||
proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayloadV3): bool =
|
||||
var p: ExecutionPayload
|
||||
let found = api.get(id, p)
|
||||
doAssert(p.version == Version.V3)
|
||||
payload = p.V3
|
||||
return found
|
||||
|
||||
proc get*(api: EngineApiRef, id: PayloadID, payload: var ExecutionPayloadV1OrV2): bool =
|
||||
var p: ExecutionPayload
|
||||
let found = api.get(id, p)
|
||||
doAssert(p.version in {Version.V1, Version.V2})
|
||||
payload = p.V1V2
|
||||
return found
|
||||
|
||||
proc merger*(api: EngineApiRef): MergerRef =
|
||||
|
|
|
@ -17,11 +17,12 @@ import
|
|||
../../constants,
|
||||
../../db/core_db,
|
||||
../../utils/utils,
|
||||
../../rpc/execution_types,
|
||||
./mergetypes
|
||||
|
||||
type Hash256 = eth_types.Hash256
|
||||
|
||||
proc computePayloadId*(headBlockHash: Hash256, params: PayloadAttributesV1 | PayloadAttributesV2): PayloadID =
|
||||
proc computePayloadId*(headBlockHash: Hash256, params: SomePayloadAttributes): PayloadID =
|
||||
var dest: Hash256
|
||||
var ctx: sha256
|
||||
ctx.init()
|
||||
|
@ -73,7 +74,7 @@ proc toWithdrawalV1*(w: Withdrawal): WithdrawalV1 =
|
|||
amount: Quantity(w.amount) # AARDVARK: is this wei or gwei or what?
|
||||
)
|
||||
|
||||
proc maybeWithdrawalsRoot(payload: ExecutionPayloadV1 | ExecutionPayloadV2): Option[Hash256] =
|
||||
proc maybeWithdrawalsRoot(payload: SomeExecutionPayload): Option[Hash256] =
|
||||
when payload is ExecutionPayloadV1:
|
||||
none(Hash256)
|
||||
else:
|
||||
|
@ -87,7 +88,19 @@ proc toWithdrawals(withdrawals: openArray[WithdrawalV1]): seq[WithDrawal] =
|
|||
for wd in withdrawals:
|
||||
result.add toWithdrawal(wd)
|
||||
|
||||
proc toBlockHeader*(payload: ExecutionPayloadV1 | ExecutionPayloadV2): EthBlockHeader =
|
||||
proc maybeBlobGasUsed(payload: SomeExecutionPayload): Option[uint64] =
|
||||
when payload is ExecutionPayloadV3:
|
||||
some(payload.blobGasUsed.uint64)
|
||||
else:
|
||||
none(uint64)
|
||||
|
||||
proc maybeExcessBlobGas(payload: SomeExecutionPayload): Option[uint64] =
|
||||
when payload is ExecutionPayloadV3:
|
||||
some(payload.excessBlobGas.uint64)
|
||||
else:
|
||||
none(uint64)
|
||||
|
||||
proc toBlockHeader*(payload: SomeExecutionPayload): EthBlockHeader =
|
||||
let transactions = seq[seq[byte]](payload.transactions)
|
||||
let txRoot = calcRootHashRlp(transactions)
|
||||
|
||||
|
@ -108,18 +121,22 @@ proc toBlockHeader*(payload: ExecutionPayloadV1 | ExecutionPayloadV2): EthBlockH
|
|||
mixDigest : payload.prevRandao.asEthHash, # EIP-4399 redefine `mixDigest` -> `prevRandao`
|
||||
nonce : default(BlockNonce),
|
||||
fee : some payload.baseFeePerGas,
|
||||
withdrawalsRoot: payload.maybeWithdrawalsRoot # EIP-4895
|
||||
withdrawalsRoot: payload.maybeWithdrawalsRoot, # EIP-4895
|
||||
blobGasUsed : payload.maybeBlobGasUsed, # EIP-4844
|
||||
excessBlobGas : payload.maybeExcessBlobGas, # EIP-4844
|
||||
)
|
||||
|
||||
proc toTypedTransaction*(tx: Transaction): TypedTransaction =
|
||||
TypedTransaction(rlp.encode(tx))
|
||||
|
||||
proc toBlockBody*(payload: ExecutionPayloadV1 | ExecutionPayloadV2): BlockBody =
|
||||
proc toBlockBody*(payload: SomeExecutionPayload): BlockBody =
|
||||
result.transactions.setLen(payload.transactions.len)
|
||||
for i, tx in payload.transactions:
|
||||
result.transactions[i] = rlp.decode(distinctBase tx, Transaction)
|
||||
when payload is ExecutionPayloadV2:
|
||||
result.withdrawals = some(payload.withdrawals.toWithdrawals)
|
||||
when payload is ExecutionPayloadV3:
|
||||
result.withdrawals = some(payload.withdrawals.toWithdrawals)
|
||||
|
||||
proc `$`*(x: BlockHash): string =
|
||||
toHex(x)
|
||||
|
@ -216,3 +233,9 @@ proc invalidAttr*(msg: string): ref InvalidRequest =
|
|||
code: engineApiInvalidPayloadAttributes,
|
||||
msg: msg
|
||||
)
|
||||
|
||||
proc unsupportedFork*(msg: string): ref InvalidRequest =
|
||||
(ref InvalidRequest)(
|
||||
code: engineApiUnsupportedFork,
|
||||
msg: msg
|
||||
)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 943431de3fa16d7349b363c35ba5ea9f80b423d3
|
||||
Subproject commit e68ff1e3f9f776b3ef77513f052c0aead51c96cb
|
Loading…
Reference in New Issue