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,
)
47 changes: 33 additions & 14 deletions execution_chain/beacon/api_handler/api_newpayload.nim
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,41 @@ func validateVersionedHashed(payload: ExecutionPayload,
true

template validateVersion(com, timestamp, payloadVersion, apiVersion) =
if apiVersion == Version.V4:
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)

elif apiVersion == Version.V4:
if not com.isPragueOrLater(timestamp):
raise unsupportedFork("newPayloadV4 expect payload timestamp fall within Prague")

if com.isPragueOrLater(timestamp):
if payloadVersion != Version.V3:
raise invalidParams("if timestamp is Prague or later, " &
"payload must be ExecutionPayloadV3, got ExecutionPayload" & $payloadVersion)
raise invalidParams("newPayload" & $apiVersion &
" expect ExecutionPayloadV3" &
" but got ExecutionPayload" & $payloadVersion)

if apiVersion == Version.V3:
elif apiVersion == Version.V3:
if not com.isCancunOrLater(timestamp):
raise unsupportedFork("newPayloadV3 expect payload timestamp fall within Cancun")
if payloadVersion != Version.V3:
raise invalidParams("newPayload" & $apiVersion &
" expect ExecutionPayloadV3" &
" but got ExecutionPayload" & $payloadVersion)

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

elif com.isPragueOrLater(timestamp):
if payloadVersion != Version.V3:
raise invalidParams("if timestamp is Prague or later, " &
"payload must be ExecutionPayloadV3, got ExecutionPayload" & $payloadVersion)

elif com.isCancunOrLater(timestamp):
if payloadVersion != Version.V3:
raise invalidParams("if timestamp is Cancun or later, " &
"payload must be ExecutionPayloadV3, got ExecutionPayload" & $payloadVersion)
Expand All @@ -68,13 +89,6 @@ template validateVersion(com, timestamp, payloadVersion, apiVersion) =
raise invalidParams("if timestamp is earlier than Shanghai, " &
"payload must be ExecutionPayloadV1, got ExecutionPayload" & $payloadVersion)

if apiVersion == Version.V3 or apiVersion == Version.V4:
# both newPayloadV3 and newPayloadV4 expect ExecutionPayloadV3
if payloadVersion != Version.V3:
raise invalidParams("newPayload" & $apiVersion &
" expect ExecutionPayload3" &
" but got ExecutionPayload" & $payloadVersion)

template validatePayload(apiVersion, payloadVersion, payload) =
if payloadVersion >= Version.V2:
if payload.withdrawals.isNone:
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: 7 additions & 5 deletions execution_chain/block_access_list/block_access_list_builder.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type
accounts*: Table[Address, AccountData]
## Maps address -> account data

BlockAccessListRef* = ref BlockAccessList

template init*(T: type AccountData): T =
AccountData()

Expand Down Expand Up @@ -116,11 +118,11 @@ func balIndexCmp(x, y: StorageChange | BalanceChange | NonceChange | CodeChange)
func slotChangesCmp(x, y: SlotChanges): int =
cmp(x.slot, y.slot)

func addressCmp(x, y: AccountChanges): int =
func accChangesCmp(x, y: AccountChanges): int =
cmp(x.address.data.toHex(), y.address.data.toHex())

func buildBlockAccessList*(builder: BlockAccessListBuilderRef): BlockAccessList =
var blockAccessList: BlockAccessList
func buildBlockAccessList*(builder: BlockAccessListBuilderRef): BlockAccessListRef =
let blockAccessList: BlockAccessListRef = new BlockAccessList

for address, accData in builder.accounts.mpairs():
# Collect and sort storageChanges
Expand Down Expand Up @@ -160,7 +162,7 @@ func buildBlockAccessList*(builder: BlockAccessListBuilderRef): BlockAccessList
codeChanges.add((BlockAccessIndex(balIndex), Bytecode(code)))
codeChanges.sort(balIndexCmp)

blockAccessList.add(AccountChanges(
blockAccessList[].add(AccountChanges(
address: address,
storageChanges: storageChanges,
storageReads: storageReads,
Expand All @@ -169,6 +171,6 @@ func buildBlockAccessList*(builder: BlockAccessListBuilderRef): BlockAccessList
codeChanges: codeChanges
))

blockAccessList.sort(addressCmp)
blockAccessList[].sort(accChangesCmp)

blockAccessList
Loading
Loading