Skip to content

Commit

Permalink
Engine API: Route more wiring from CoreDb to ForkedChain (#2844)
Browse files Browse the repository at this point in the history
  • Loading branch information
jangko authored Nov 7, 2024
1 parent 6b86acf commit 70a1f76
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 246 deletions.
2 changes: 1 addition & 1 deletion nimbus/beacon/api_handler/api_forkchoice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ proc forkchoiceUpdated*(ben: BeaconEngineRef,
db.safeHeaderHash(safeBlockHash)

chain.forkChoice(blockHash, finalizedBlockHash).isOkOr:
return invalidFCU(error, com, header)
return invalidFCU(error, chain, header)

# If payload generation was requested, create a new block to be potentially
# sealed by the beacon client. The payload will be requested later, and we
Expand Down
34 changes: 2 additions & 32 deletions nimbus/beacon/api_handler/api_getbodies.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,13 @@ import
../web3_eth_conv,
../beacon_engine,
web3/execution_types,
../../db/core_db,
./api_utils

{.push gcsafe, raises:[CatchableError].}

const
maxBodyRequest = 32

proc getPayloadBodyByHeader(db: CoreDbRef,
header: Header,
output: var seq[Opt[ExecutionPayloadBodyV1]]) {.raises:[].} =

let body = db.getBlockBody(header).valueOr:
output.add Opt.none(ExecutionPayloadBodyV1)
return

let txs = w3Txs body.transactions
var wds: seq[WithdrawalV1]
if body.withdrawals.isSome:
for w in body.withdrawals.get:
wds.add w3Withdrawal(w)

output.add(
Opt.some(ExecutionPayloadBodyV1(
transactions: txs,
# pre Shanghai block return null withdrawals
# post Shanghai block return at least empty slice
withdrawals: if header.withdrawalsRoot.isSome:
Opt.some(wds)
else:
Opt.none(seq[WithdrawalV1])
))
)

func toPayloadBody(blk: Block): ExecutionPayloadBodyV1 {.raises:[].} =
var wds: seq[WithdrawalV1]
if blk.withdrawals.isSome:
Expand Down Expand Up @@ -87,9 +60,6 @@ proc getPayloadBodiesByRange*(ben: BeaconEngineRef,
if count > maxBodyRequest:
raise tooLargeRequest("request exceeds max allowed " & $maxBodyRequest)

let
db = ben.com.db

var
last = start+count-1

Expand All @@ -102,10 +72,10 @@ proc getPayloadBodiesByRange*(ben: BeaconEngineRef,

# get bodies from database
for bn in start..ben.chain.baseNumber:
let header = db.getBlockHeader(bn).valueOr:
let blk = ben.chain.blockByNumber(bn).valueOr:
result.add Opt.none(ExecutionPayloadBodyV1)
continue
db.getPayloadBodyByHeader(header, result)
result.add Opt.some(blk.toPayloadBody)

if last > ben.chain.baseNumber:
let blocks = ben.chain.blockFromBaseTo(last)
Expand Down
11 changes: 6 additions & 5 deletions nimbus/beacon/api_handler/api_utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import
std/[typetraits, strutils],
web3/execution_types,
json_rpc/errors,
nimcrypto/sha2,
stew/endians2,
Expand All @@ -17,7 +18,7 @@ import
../../db/core_db,
../../utils/utils,
../../common/common,
web3/execution_types,
../../core/chain,
../web3_eth_conv

{.push gcsafe, raises:[].}
Expand Down Expand Up @@ -185,12 +186,12 @@ proc latestValidHash*(db: CoreDbRef,
default(Hash32)

proc invalidFCU*(validationError: string,
com: CommonRef,
header: common.Header): ForkchoiceUpdatedResponse =
let parent = com.db.getBlockHeader(header.parentHash).valueOr:
chain: ForkedChainRef,
header: Header): ForkchoiceUpdatedResponse =
let parent = chain.headerByHash(header.parentHash).valueOr:
return invalidFCU(validationError)

let blockHash =
latestValidHash(com.db, parent, com.ttd.get(high(UInt256)))
latestValidHash(chain.db, parent, chain.com.ttd.get(high(UInt256)))

invalidFCU(validationError, blockHash)
23 changes: 11 additions & 12 deletions nimbus/beacon/beacon_engine.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@

import
std/[sequtils, tables],
./web3_eth_conv,
./payload_conv,
eth/common/[hashes, headers],
chronicles,
web3/execution_types,
./web3_eth_conv,
./payload_conv,
./payload_queue,
./api_handler/api_utils,
../db/core_db,
../core/[tx_pool, casper, chain],
eth/common/[hashes, headers]
../core/[tx_pool, casper, chain]

export
chain,
Expand Down Expand Up @@ -178,8 +177,8 @@ proc generateExecutionBundle*(ben: BeaconEngineRef,
if bundle.blobsBundle.isSome:
template blobData: untyped = bundle.blobsBundle.get
blobsBundle = Opt.some BlobsBundleV1(
commitments: blobData.commitments.mapIt it.Web3KZGCommitment,
proofs: blobData.proofs.mapIt it.Web3KZGProof,
commitments: blobData.commitments,
proofs: blobData.proofs,
blobs: blobData.blobs.mapIt it.Web3Blob)

ok ExecutionBundle(
Expand All @@ -196,13 +195,13 @@ func setInvalidAncestor*(ben: BeaconEngineRef, header: Header, blockHash: Hash32
# bad ancestor. If yes, it constructs the payload failure response to return.
proc checkInvalidAncestor*(ben: BeaconEngineRef,
check, head: Hash32): Opt[PayloadStatusV1] =
proc latestValidHash(db: CoreDbRef, invalid: auto): Hash32 =
let parent = db.getBlockHeader(invalid.parentHash).valueOr:
return invalid.parentHash
proc latestValidHash(chain: ForkedChainRef, invalid: auto): Hash32 =
let parent = chain.headerByHash(invalid.parentHash).valueOr:
return invalid.parentHash
if parent.difficulty != 0.u256:
return default(Hash32)
invalid.parentHash

# If the hash to check is unknown, return valid
ben.invalidTipsets.withValue(check, invalid) do:
# If the bad hash was hit too many times, evict it and try to reprocess in
Expand Down Expand Up @@ -244,7 +243,7 @@ proc checkInvalidAncestor*(ben: BeaconEngineRef,
ben.invalidTipsets[head] = invalid[]

# If the last valid hash is the terminal pow block, return 0x0 for latest valid hash
let lastValid = latestValidHash(ben.com.db, invalid)
let lastValid = latestValidHash(ben.chain, invalid)
return Opt.some invalidStatus(lastValid, "links to previously rejected block")
do:
return Opt.none(PayloadStatusV1)
Expand Down
37 changes: 12 additions & 25 deletions nimbus/beacon/web3_eth_conv.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@ export
type
Web3Quantity* = web3types.Quantity
Web3ExtraData* = web3types.DynamicBytes[0, 32]
Web3BlockNumber* = Quantity
Web3Tx* = engine_api_types.TypedTransaction
Web3Blob* = engine_api_types.Blob
Web3KZGProof* = engine_api_types.KzgProof
Web3KZGCommitment* = engine_api_types.KzgCommitment

{.push gcsafe, raises:[].}

Expand All @@ -57,17 +54,17 @@ func u64*(x: Opt[Web3Quantity]): Opt[uint64] =
if x.isNone: Opt.none(uint64)
else: Opt.some(uint64 x.get)

func u256*(x: Web3BlockNumber): UInt256 =
func u256*(x: Web3Quantity): UInt256 =
u256(x.uint64)

func u256*(x: common.FixedBytes[32]): UInt256 =
func u256*(x: FixedBytes[32]): UInt256 =
UInt256.fromBytesBE(x.data)

func ethTime*(x: Web3Quantity): common.EthTime =
common.EthTime(x)
func ethTime*(x: Web3Quantity): EthTime =
EthTime(x)

func ethGasInt*(x: Web3Quantity): common.GasInt =
common.GasInt x
func ethGasInt*(x: Web3Quantity): GasInt =
GasInt x

func ethBlob*(x: Web3ExtraData): seq[byte] =
distinctBase x
Expand All @@ -79,14 +76,14 @@ func ethWithdrawal*(x: WithdrawalV1): common.Withdrawal =
result.amount = x.amount.uint64

func ethWithdrawals*(list: openArray[WithdrawalV1]):
seq[common.Withdrawal] =
result = newSeqOfCap[common.Withdrawal](list.len)
seq[Withdrawal] =
result = newSeqOfCap[Withdrawal](list.len)
for x in list:
result.add ethWithdrawal(x)

func ethWithdrawals*(x: Opt[seq[WithdrawalV1]]):
Opt[seq[common.Withdrawal]] =
if x.isNone: Opt.none(seq[common.Withdrawal])
Opt[seq[Withdrawal]] =
if x.isNone: Opt.none(seq[Withdrawal])
else: Opt.some(ethWithdrawals x.get)

func ethTx*(x: Web3Tx): common.Transaction {.gcsafe, raises:[RlpError].} =
Expand All @@ -105,10 +102,10 @@ func ethTxs*(list: openArray[Web3Tx]):
func w3Qty*(x: UInt256): Web3Quantity =
Web3Quantity x.truncate(uint64)

func w3Qty*(x: common.EthTime): Web3Quantity =
func w3Qty*(x: EthTime): Web3Quantity =
Web3Quantity x.uint64

func w3Qty*(x: common.EthTime, y: int): Web3Quantity =
func w3Qty*(x: EthTime, y: int): Web3Quantity =
Web3Quantity(x + y.EthTime)

func w3Qty*(x: Web3Quantity, y: int): Web3Quantity =
Expand All @@ -130,16 +127,6 @@ func w3Qty*(x: uint64): Web3Quantity =
func w3Qty*(x: int64): Web3Quantity =
Web3Quantity(x)

func w3BlockNumber*(x: Opt[uint64]): Opt[Web3BlockNumber] =
if x.isNone: Opt.none(Web3BlockNumber)
else: Opt.some(Web3BlockNumber x.get)

func w3BlockNumber*(x: uint64): Web3BlockNumber =
Web3BlockNumber(x)

func w3BlockNumber*(x: UInt256): Web3BlockNumber =
Web3BlockNumber x.truncate(uint64)

func w3ExtraData*(x: seq[byte]): Web3ExtraData =
Web3ExtraData x

Expand Down
8 changes: 1 addition & 7 deletions nimbus/core/chain/chain_desc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ proc newChain*(com: CommonRef): ChainRef =
com: com,
extraValidation: extraValidation,
)

# ------------------------------------------------------------------------------
# Public `Chain` getters
# ------------------------------------------------------------------------------
Expand All @@ -85,12 +85,6 @@ func verifyFrom*(c: ChainRef): BlockNumber =
## Getter
c.verifyFrom

proc currentBlock*(c: ChainRef): Result[Header, string] =
## currentBlock retrieves the current head block of the canonical chain.
## Ideally the block should be retrieved from the blockchain's internal cache.
## but now it's enough to retrieve it from database
c.db.getCanonicalHead()

# ------------------------------------------------------------------------------
# Public `Chain` setters
# ------------------------------------------------------------------------------
Expand Down
24 changes: 0 additions & 24 deletions nimbus/core/chain/persist_blocks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -198,30 +198,6 @@ proc persistBlocksImpl(

ok((blks, txs, gas))

# ------------------------------------------------------------------------------
# Public `ChainDB` methods
# ------------------------------------------------------------------------------

proc insertBlockWithoutSetHead*(c: ChainRef, blk: Block): Result[void, string] =
discard ?c.persistBlocksImpl([blk], {NoPersistHeader, NoPersistReceipts})
c.db.persistHeader(blk.header.blockHash, blk.header, c.com.startOfHistory)

proc setCanonical*(c: ChainRef, header: Header): Result[void, string] =
if header.parentHash == default(Hash32):
return c.db.setHead(header)

var body = ?c.db.getBlockBody(header)
discard
?c.persistBlocksImpl(
[Block.init(header, move(body))], {NoPersistHeader, NoPersistTransactions}
)

c.db.setHead(header)

proc setCanonical*(c: ChainRef, blockHash: Hash32): Result[void, string] =
let header = ?c.db.getBlockHeader(blockHash)
setCanonical(c, header)

proc persistBlocks*(
c: ChainRef, blocks: openArray[Block], flags: PersistBlockFlags = {}
): Result[PersistStats, string] =
Expand Down
Loading

0 comments on commit 70a1f76

Please sign in to comment.