Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions execution_chain/beacon/api_handler.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export
getPayloadV3,
getPayloadV4,
getPayloadV5,
getPayloadV6,
getPayloadBodiesByHash,
getPayloadBodiesByRange,
newPayload,
Expand Down
36 changes: 33 additions & 3 deletions execution_chain/beacon/api_handler/api_getpayload.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ proc getPayload*(ben: BeaconEngineRef,
let bundle = ben.getPayloadBundle(id).valueOr:
raise unknownPayload("Unknown bundle")

let
let
version = bundle.payload.version
com = ben.com

Expand Down Expand Up @@ -112,7 +112,7 @@ proc getPayloadV5*(ben: BeaconEngineRef, id: Bytes8): GetPayloadV5Response =

let version = bundle.payload.version
if version != Version.V3:
raise unsupportedFork("getPayloadV5 expect payloadV3 but get payload" & $version)
raise unsupportedFork("getPayloadV5 expect ExecutionPayloadV3 but got ExecutionPayload" & $version)
if bundle.blobsBundle.isNil:
raise unsupportedFork("getPayloadV5 is missing BlobsBundleV2")
if bundle.executionRequests.isNone:
Expand All @@ -122,10 +122,40 @@ proc getPayloadV5*(ben: BeaconEngineRef, id: Bytes8): GetPayloadV5Response =
if not com.isOsakaOrLater(ethTime bundle.payload.timestamp):
raise unsupportedFork("bundle timestamp is less than Osaka activation")

if com.isAmsterdamOrLater(ethTime bundle.payload.timestamp):
raise unsupportedFork("bundle timestamp greater than Amsterdam must use getPayloadV6")

GetPayloadV5Response(
executionPayload: bundle.payload.V3,
blockValue: bundle.blockValue,
blobsBundle: bundle.blobsBundle.V2,
shouldOverrideBuilder: false,
executionRequests: bundle.executionRequests.get,
)
)

proc getPayloadV6*(ben: BeaconEngineRef, id: Bytes8): GetPayloadV6Response =
trace "Engine API request received",
meth = "GetPayload", id

let bundle = ben.getPayloadBundle(id).valueOr:
raise unknownPayload("Unknown bundle")

let version = bundle.payload.version
if version != Version.V4:
raise unsupportedFork("getPayloadV6 expect ExecutionPayloadV4 but got ExecutionPayload" & $version)
if bundle.blobsBundle.isNil:
raise unsupportedFork("getPayloadV6 is missing BlobsBundleV2")
if bundle.executionRequests.isNone:
raise unsupportedFork("getPayloadV6 is missing executionRequests")

let com = ben.com
if not com.isAmsterdamOrLater(ethTime bundle.payload.timestamp):
raise unsupportedFork("bundle timestamp is less than Amsterdam activation")

GetPayloadV6Response(
executionPayload: bundle.payload.V4,
blockValue: bundle.blockValue,
blobsBundle: bundle.blobsBundle.V2,
shouldOverrideBuilder: false,
executionRequests: bundle.executionRequests.get,
)
21 changes: 20 additions & 1 deletion execution_chain/beacon/api_handler/api_newpayload.nim
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ func validateVersionedHashed(payload: ExecutionPayload,
true

template validateVersion(com, timestamp, payloadVersion, apiVersion) =
if apiVersion == Version.V5:
if not com.isAmsterdamOrLater(timestamp):
raise unsupportedFork("newPayloadV5 expect payload timestamp fall within Amsterdam")

if payloadVersion != Version.V4:
raise invalidParams("newPayload" & $apiVersion &
" expect ExecutionPayloadV4" &
" but got ExecutionPayload" & $payloadVersion)

if com.isAmsterdamOrLater(timestamp):
if payloadVersion != Version.V4:
raise invalidParams("if timestamp is Amsterdam or later, " &
"payload must be ExecutionPayloadV4, got ExecutionPayload" & $payloadVersion)

if apiVersion == Version.V4:
if not com.isPragueOrLater(timestamp):
raise unsupportedFork("newPayloadV4 expect payload timestamp fall within Prague")
Expand Down Expand Up @@ -72,7 +86,7 @@ template validateVersion(com, timestamp, payloadVersion, apiVersion) =
# both newPayloadV3 and newPayloadV4 expect ExecutionPayloadV3
if payloadVersion != Version.V3:
raise invalidParams("newPayload" & $apiVersion &
" expect ExecutionPayload3" &
" expect ExecutionPayloadV3" &
" but got ExecutionPayload" & $payloadVersion)

template validatePayload(apiVersion, payloadVersion, payload) =
Expand All @@ -89,6 +103,11 @@ template validatePayload(apiVersion, payloadVersion, payload) =
raise invalidParams("newPayload" & $apiVersion &
"excessBlobGas is expected from execution payload")

if apiVersion >= Version.V5 or payloadVersion >= Version.V4:
if payload.blockAccessList.isNone:
raise invalidParams("newPayload" & $apiVersion &
"blockAccessList is expected from execution payload")

# https://github.com/ethereum/execution-apis/blob/40088597b8b4f48c45184da002e27ffc3c37641f/src/engine/prague.md#request
func validateExecutionRequest(blockHash: Hash32,
requests: openArray[seq[byte]], apiVersion: Version):
Expand Down
14 changes: 12 additions & 2 deletions execution_chain/beacon/payload_conv.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func wdRoot(x: Opt[seq[WithdrawalV1]]): Opt[Hash32] =
func txRoot(list: openArray[Web3Tx]): Hash32 =
orderedTrieRoot(list)

func balHash(bal: Opt[seq[byte]]): Opt[Hash32] =
if bal.isNone():
Opt.none(Hash32)
else:
Opt.some(keccak256(bal.get))

# ------------------------------------------------------------------------------
# Public functions
# ------------------------------------------------------------------------------
Expand All @@ -63,6 +69,7 @@ func executionPayload*(blk: Block): ExecutionPayload =
withdrawals : w3Withdrawals blk.withdrawals,
blobGasUsed : w3Qty blk.header.blobGasUsed,
excessBlobGas: w3Qty blk.header.excessBlobGas,
blockAccessList: w3BlockAccessList blk.blockAccessList
)

func executionPayloadV1V2*(blk: Block): ExecutionPayloadV1OrV2 =
Expand Down Expand Up @@ -110,23 +117,26 @@ func blockHeader*(p: ExecutionPayload,
excessBlobGas : u64(p.excessBlobGas),
parentBeaconBlockRoot: parentBeaconBlockRoot,
requestsHash : requestsHash,
blockAccessListHash: balHash p.blockAccessList,
)

func blockBody*(p: ExecutionPayload):
BlockBody {.gcsafe, raises:[RlpError].} =
BlockBody {.gcsafe, raises: [RlpError].} =
BlockBody(
uncles : @[],
transactions: ethTxs p.transactions,
withdrawals : ethWithdrawals p.withdrawals,
blockAccessList: ethBlockAccessList p.blockAccessList,
)

func ethBlock*(p: ExecutionPayload,
parentBeaconBlockRoot: Opt[Hash32],
requestsHash: Opt[Hash32]):
Block {.gcsafe, raises:[RlpError].} =
Block {.gcsafe, raises: [RlpError].} =
Block(
header : blockHeader(p, parentBeaconBlockRoot, requestsHash),
uncles : @[],
transactions: ethTxs p.transactions,
withdrawals : ethWithdrawals p.withdrawals,
blockAccessList: ethBlockAccessList p.blockAccessList,
)
24 changes: 22 additions & 2 deletions execution_chain/beacon/web3_eth_conv.nim
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,26 @@ func ethWithdrawals*(x: Opt[seq[WithdrawalV1]]):
if x.isNone: Opt.none(seq[Withdrawal])
else: Opt.some(ethWithdrawals x.get)

func ethTx*(x: Web3Tx): common.Transaction {.gcsafe, raises:[RlpError].} =
func ethTx*(x: Web3Tx): common.Transaction {.gcsafe, raises: [RlpError].} =
result = rlp.decode(distinctBase x, common.Transaction)

func ethTxs*(list: openArray[Web3Tx]):
seq[common.Transaction] {.gcsafe, raises:[RlpError].} =
seq[common.Transaction] {.gcsafe, raises: [RlpError].} =
result = newSeqOfCap[common.Transaction](list.len)
for x in list:
result.add ethTx(x)

func ethBlockAccessList*(
bal: openArray[byte]): BlockAccessList {.gcsafe, raises: [RlpError].} =
rlp.decode(bal, BlockAccessList)

func ethBlockAccessList*(
bal: Opt[seq[byte]]): Opt[BlockAccessList] {.gcsafe, raises: [RlpError].} =
if bal.isNone():
Opt.none(BlockAccessList)
else:
Opt.some(ethBlockAccessList(bal.get))

# ------------------------------------------------------------------------------
# Eth types to Web3 types
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -154,4 +165,13 @@ func w3Txs*(list: openArray[common.Transaction]): seq[Web3Tx] =
for tx in list:
result.add w3Tx(tx)

func w3BlockAccessList*(bal: BlockAccessList): seq[byte] =
bal.encode()

func w3BlockAccessList*(bal: Opt[BlockAccessList]): Opt[seq[byte]] =
if bal.isNone():
Opt.none(seq[byte])
else:
Opt.some(w3BlockAccessList(bal.get))

chronicles.formatIt(Quantity): $(distinctBase it)
12 changes: 12 additions & 0 deletions execution_chain/rpc/engine_api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ const supportedMethods: HashSet[string] =
"engine_newPayloadV2",
"engine_newPayloadV3",
"engine_newPayloadV4",
"engine_newPayloadV5",
"engine_getPayloadV1",
"engine_getPayloadV2",
"engine_getPayloadV3",
"engine_getPayloadV4",
"engine_getPayloadV5",
"engine_getPayloadV6",
"engine_forkchoiceUpdatedV1",
"engine_forkchoiceUpdatedV2",
"engine_forkchoiceUpdatedV3",
Expand Down Expand Up @@ -66,6 +68,13 @@ proc setupEngineAPI*(engine: BeaconEngineRef, server: RpcServer) =
await engine.newPayload(Version.V4, payload,
expectedBlobVersionedHashes, parentBeaconBlockRoot, executionRequests)

server.rpc("engine_newPayloadV5") do(payload: ExecutionPayload,
expectedBlobVersionedHashes: Opt[seq[Hash32]],
parentBeaconBlockRoot: Opt[Hash32],
executionRequests: Opt[seq[seq[byte]]]) -> PayloadStatusV1:
await engine.newPayload(Version.V5, payload,
expectedBlobVersionedHashes, parentBeaconBlockRoot, executionRequests)

server.rpc("engine_getPayloadV1") do(payloadId: Bytes8) -> ExecutionPayloadV1:
return engine.getPayload(Version.V1, payloadId).executionPayload.V1

Expand All @@ -81,6 +90,9 @@ proc setupEngineAPI*(engine: BeaconEngineRef, server: RpcServer) =
server.rpc("engine_getPayloadV5") do(payloadId: Bytes8) -> GetPayloadV5Response:
return engine.getPayloadV5(payloadId)

server.rpc("engine_getPayloadV6") do(payloadId: Bytes8) -> GetPayloadV6Response:
return engine.getPayloadV6(payloadId)

server.rpc("engine_forkchoiceUpdatedV1") do(update: ForkchoiceStateV1,
attrs: Opt[PayloadAttributesV1]) -> ForkchoiceUpdatedResponse:
await engine.forkchoiceUpdated(Version.V1, update, attrs.payloadAttributes)
Expand Down
3 changes: 2 additions & 1 deletion hive_integration/engine_client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ proc newPayload*(client: RpcClient,
payload.versionedHashes,
payload.beaconRoot,
payload.executionRequests)
of Version.V6: discard
of Version.V6:
discard # TODO: Hive testing for Amsterdam

proc exchangeCapabilities*(client: RpcClient,
methods: seq[string]):
Expand Down