Engine API: Route more wiring from CoreDb to ForkedChain (#2844)
This commit is contained in:
parent
6b86acfb8d
commit
70a1f768f7
|
@ -177,7 +177,7 @@ proc forkchoiceUpdated*(ben: BeaconEngineRef,
|
||||||
db.safeHeaderHash(safeBlockHash)
|
db.safeHeaderHash(safeBlockHash)
|
||||||
|
|
||||||
chain.forkChoice(blockHash, finalizedBlockHash).isOkOr:
|
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
|
# 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
|
# sealed by the beacon client. The payload will be requested later, and we
|
||||||
|
|
|
@ -13,7 +13,6 @@ import
|
||||||
../web3_eth_conv,
|
../web3_eth_conv,
|
||||||
../beacon_engine,
|
../beacon_engine,
|
||||||
web3/execution_types,
|
web3/execution_types,
|
||||||
../../db/core_db,
|
|
||||||
./api_utils
|
./api_utils
|
||||||
|
|
||||||
{.push gcsafe, raises:[CatchableError].}
|
{.push gcsafe, raises:[CatchableError].}
|
||||||
|
@ -21,32 +20,6 @@ import
|
||||||
const
|
const
|
||||||
maxBodyRequest = 32
|
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:[].} =
|
func toPayloadBody(blk: Block): ExecutionPayloadBodyV1 {.raises:[].} =
|
||||||
var wds: seq[WithdrawalV1]
|
var wds: seq[WithdrawalV1]
|
||||||
if blk.withdrawals.isSome:
|
if blk.withdrawals.isSome:
|
||||||
|
@ -87,9 +60,6 @@ proc getPayloadBodiesByRange*(ben: BeaconEngineRef,
|
||||||
if count > maxBodyRequest:
|
if count > maxBodyRequest:
|
||||||
raise tooLargeRequest("request exceeds max allowed " & $maxBodyRequest)
|
raise tooLargeRequest("request exceeds max allowed " & $maxBodyRequest)
|
||||||
|
|
||||||
let
|
|
||||||
db = ben.com.db
|
|
||||||
|
|
||||||
var
|
var
|
||||||
last = start+count-1
|
last = start+count-1
|
||||||
|
|
||||||
|
@ -102,10 +72,10 @@ proc getPayloadBodiesByRange*(ben: BeaconEngineRef,
|
||||||
|
|
||||||
# get bodies from database
|
# get bodies from database
|
||||||
for bn in start..ben.chain.baseNumber:
|
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)
|
result.add Opt.none(ExecutionPayloadBodyV1)
|
||||||
continue
|
continue
|
||||||
db.getPayloadBodyByHeader(header, result)
|
result.add Opt.some(blk.toPayloadBody)
|
||||||
|
|
||||||
if last > ben.chain.baseNumber:
|
if last > ben.chain.baseNumber:
|
||||||
let blocks = ben.chain.blockFromBaseTo(last)
|
let blocks = ben.chain.blockFromBaseTo(last)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[typetraits, strutils],
|
std/[typetraits, strutils],
|
||||||
|
web3/execution_types,
|
||||||
json_rpc/errors,
|
json_rpc/errors,
|
||||||
nimcrypto/sha2,
|
nimcrypto/sha2,
|
||||||
stew/endians2,
|
stew/endians2,
|
||||||
|
@ -17,7 +18,7 @@ import
|
||||||
../../db/core_db,
|
../../db/core_db,
|
||||||
../../utils/utils,
|
../../utils/utils,
|
||||||
../../common/common,
|
../../common/common,
|
||||||
web3/execution_types,
|
../../core/chain,
|
||||||
../web3_eth_conv
|
../web3_eth_conv
|
||||||
|
|
||||||
{.push gcsafe, raises:[].}
|
{.push gcsafe, raises:[].}
|
||||||
|
@ -185,12 +186,12 @@ proc latestValidHash*(db: CoreDbRef,
|
||||||
default(Hash32)
|
default(Hash32)
|
||||||
|
|
||||||
proc invalidFCU*(validationError: string,
|
proc invalidFCU*(validationError: string,
|
||||||
com: CommonRef,
|
chain: ForkedChainRef,
|
||||||
header: common.Header): ForkchoiceUpdatedResponse =
|
header: Header): ForkchoiceUpdatedResponse =
|
||||||
let parent = com.db.getBlockHeader(header.parentHash).valueOr:
|
let parent = chain.headerByHash(header.parentHash).valueOr:
|
||||||
return invalidFCU(validationError)
|
return invalidFCU(validationError)
|
||||||
|
|
||||||
let blockHash =
|
let blockHash =
|
||||||
latestValidHash(com.db, parent, com.ttd.get(high(UInt256)))
|
latestValidHash(chain.db, parent, chain.com.ttd.get(high(UInt256)))
|
||||||
|
|
||||||
invalidFCU(validationError, blockHash)
|
invalidFCU(validationError, blockHash)
|
||||||
|
|
|
@ -9,15 +9,14 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, tables],
|
std/[sequtils, tables],
|
||||||
./web3_eth_conv,
|
eth/common/[hashes, headers],
|
||||||
./payload_conv,
|
|
||||||
chronicles,
|
chronicles,
|
||||||
web3/execution_types,
|
web3/execution_types,
|
||||||
|
./web3_eth_conv,
|
||||||
|
./payload_conv,
|
||||||
./payload_queue,
|
./payload_queue,
|
||||||
./api_handler/api_utils,
|
./api_handler/api_utils,
|
||||||
../db/core_db,
|
../core/[tx_pool, casper, chain]
|
||||||
../core/[tx_pool, casper, chain],
|
|
||||||
eth/common/[hashes, headers]
|
|
||||||
|
|
||||||
export
|
export
|
||||||
chain,
|
chain,
|
||||||
|
@ -178,8 +177,8 @@ proc generateExecutionBundle*(ben: BeaconEngineRef,
|
||||||
if bundle.blobsBundle.isSome:
|
if bundle.blobsBundle.isSome:
|
||||||
template blobData: untyped = bundle.blobsBundle.get
|
template blobData: untyped = bundle.blobsBundle.get
|
||||||
blobsBundle = Opt.some BlobsBundleV1(
|
blobsBundle = Opt.some BlobsBundleV1(
|
||||||
commitments: blobData.commitments.mapIt it.Web3KZGCommitment,
|
commitments: blobData.commitments,
|
||||||
proofs: blobData.proofs.mapIt it.Web3KZGProof,
|
proofs: blobData.proofs,
|
||||||
blobs: blobData.blobs.mapIt it.Web3Blob)
|
blobs: blobData.blobs.mapIt it.Web3Blob)
|
||||||
|
|
||||||
ok ExecutionBundle(
|
ok ExecutionBundle(
|
||||||
|
@ -196,13 +195,13 @@ func setInvalidAncestor*(ben: BeaconEngineRef, header: Header, blockHash: Hash32
|
||||||
# bad ancestor. If yes, it constructs the payload failure response to return.
|
# bad ancestor. If yes, it constructs the payload failure response to return.
|
||||||
proc checkInvalidAncestor*(ben: BeaconEngineRef,
|
proc checkInvalidAncestor*(ben: BeaconEngineRef,
|
||||||
check, head: Hash32): Opt[PayloadStatusV1] =
|
check, head: Hash32): Opt[PayloadStatusV1] =
|
||||||
proc latestValidHash(db: CoreDbRef, invalid: auto): Hash32 =
|
proc latestValidHash(chain: ForkedChainRef, invalid: auto): Hash32 =
|
||||||
let parent = db.getBlockHeader(invalid.parentHash).valueOr:
|
let parent = chain.headerByHash(invalid.parentHash).valueOr:
|
||||||
return invalid.parentHash
|
return invalid.parentHash
|
||||||
if parent.difficulty != 0.u256:
|
if parent.difficulty != 0.u256:
|
||||||
return default(Hash32)
|
return default(Hash32)
|
||||||
invalid.parentHash
|
invalid.parentHash
|
||||||
|
|
||||||
# If the hash to check is unknown, return valid
|
# If the hash to check is unknown, return valid
|
||||||
ben.invalidTipsets.withValue(check, invalid) do:
|
ben.invalidTipsets.withValue(check, invalid) do:
|
||||||
# If the bad hash was hit too many times, evict it and try to reprocess in
|
# If the bad hash was hit too many times, evict it and try to reprocess in
|
||||||
|
@ -244,7 +243,7 @@ proc checkInvalidAncestor*(ben: BeaconEngineRef,
|
||||||
ben.invalidTipsets[head] = invalid[]
|
ben.invalidTipsets[head] = invalid[]
|
||||||
|
|
||||||
# If the last valid hash is the terminal pow block, return 0x0 for latest valid hash
|
# 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")
|
return Opt.some invalidStatus(lastValid, "links to previously rejected block")
|
||||||
do:
|
do:
|
||||||
return Opt.none(PayloadStatusV1)
|
return Opt.none(PayloadStatusV1)
|
||||||
|
|
|
@ -26,11 +26,8 @@ export
|
||||||
type
|
type
|
||||||
Web3Quantity* = web3types.Quantity
|
Web3Quantity* = web3types.Quantity
|
||||||
Web3ExtraData* = web3types.DynamicBytes[0, 32]
|
Web3ExtraData* = web3types.DynamicBytes[0, 32]
|
||||||
Web3BlockNumber* = Quantity
|
|
||||||
Web3Tx* = engine_api_types.TypedTransaction
|
Web3Tx* = engine_api_types.TypedTransaction
|
||||||
Web3Blob* = engine_api_types.Blob
|
Web3Blob* = engine_api_types.Blob
|
||||||
Web3KZGProof* = engine_api_types.KzgProof
|
|
||||||
Web3KZGCommitment* = engine_api_types.KzgCommitment
|
|
||||||
|
|
||||||
{.push gcsafe, raises:[].}
|
{.push gcsafe, raises:[].}
|
||||||
|
|
||||||
|
@ -57,17 +54,17 @@ func u64*(x: Opt[Web3Quantity]): Opt[uint64] =
|
||||||
if x.isNone: Opt.none(uint64)
|
if x.isNone: Opt.none(uint64)
|
||||||
else: Opt.some(uint64 x.get)
|
else: Opt.some(uint64 x.get)
|
||||||
|
|
||||||
func u256*(x: Web3BlockNumber): UInt256 =
|
func u256*(x: Web3Quantity): UInt256 =
|
||||||
u256(x.uint64)
|
u256(x.uint64)
|
||||||
|
|
||||||
func u256*(x: common.FixedBytes[32]): UInt256 =
|
func u256*(x: FixedBytes[32]): UInt256 =
|
||||||
UInt256.fromBytesBE(x.data)
|
UInt256.fromBytesBE(x.data)
|
||||||
|
|
||||||
func ethTime*(x: Web3Quantity): common.EthTime =
|
func ethTime*(x: Web3Quantity): EthTime =
|
||||||
common.EthTime(x)
|
EthTime(x)
|
||||||
|
|
||||||
func ethGasInt*(x: Web3Quantity): common.GasInt =
|
func ethGasInt*(x: Web3Quantity): GasInt =
|
||||||
common.GasInt x
|
GasInt x
|
||||||
|
|
||||||
func ethBlob*(x: Web3ExtraData): seq[byte] =
|
func ethBlob*(x: Web3ExtraData): seq[byte] =
|
||||||
distinctBase x
|
distinctBase x
|
||||||
|
@ -79,14 +76,14 @@ func ethWithdrawal*(x: WithdrawalV1): common.Withdrawal =
|
||||||
result.amount = x.amount.uint64
|
result.amount = x.amount.uint64
|
||||||
|
|
||||||
func ethWithdrawals*(list: openArray[WithdrawalV1]):
|
func ethWithdrawals*(list: openArray[WithdrawalV1]):
|
||||||
seq[common.Withdrawal] =
|
seq[Withdrawal] =
|
||||||
result = newSeqOfCap[common.Withdrawal](list.len)
|
result = newSeqOfCap[Withdrawal](list.len)
|
||||||
for x in list:
|
for x in list:
|
||||||
result.add ethWithdrawal(x)
|
result.add ethWithdrawal(x)
|
||||||
|
|
||||||
func ethWithdrawals*(x: Opt[seq[WithdrawalV1]]):
|
func ethWithdrawals*(x: Opt[seq[WithdrawalV1]]):
|
||||||
Opt[seq[common.Withdrawal]] =
|
Opt[seq[Withdrawal]] =
|
||||||
if x.isNone: Opt.none(seq[common.Withdrawal])
|
if x.isNone: Opt.none(seq[Withdrawal])
|
||||||
else: Opt.some(ethWithdrawals x.get)
|
else: Opt.some(ethWithdrawals x.get)
|
||||||
|
|
||||||
func ethTx*(x: Web3Tx): common.Transaction {.gcsafe, raises:[RlpError].} =
|
func ethTx*(x: Web3Tx): common.Transaction {.gcsafe, raises:[RlpError].} =
|
||||||
|
@ -105,10 +102,10 @@ func ethTxs*(list: openArray[Web3Tx]):
|
||||||
func w3Qty*(x: UInt256): Web3Quantity =
|
func w3Qty*(x: UInt256): Web3Quantity =
|
||||||
Web3Quantity x.truncate(uint64)
|
Web3Quantity x.truncate(uint64)
|
||||||
|
|
||||||
func w3Qty*(x: common.EthTime): Web3Quantity =
|
func w3Qty*(x: EthTime): Web3Quantity =
|
||||||
Web3Quantity x.uint64
|
Web3Quantity x.uint64
|
||||||
|
|
||||||
func w3Qty*(x: common.EthTime, y: int): Web3Quantity =
|
func w3Qty*(x: EthTime, y: int): Web3Quantity =
|
||||||
Web3Quantity(x + y.EthTime)
|
Web3Quantity(x + y.EthTime)
|
||||||
|
|
||||||
func w3Qty*(x: Web3Quantity, y: int): Web3Quantity =
|
func w3Qty*(x: Web3Quantity, y: int): Web3Quantity =
|
||||||
|
@ -130,16 +127,6 @@ func w3Qty*(x: uint64): Web3Quantity =
|
||||||
func w3Qty*(x: int64): Web3Quantity =
|
func w3Qty*(x: int64): Web3Quantity =
|
||||||
Web3Quantity(x)
|
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 =
|
func w3ExtraData*(x: seq[byte]): Web3ExtraData =
|
||||||
Web3ExtraData x
|
Web3ExtraData x
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ proc newChain*(com: CommonRef): ChainRef =
|
||||||
com: com,
|
com: com,
|
||||||
extraValidation: extraValidation,
|
extraValidation: extraValidation,
|
||||||
)
|
)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public `Chain` getters
|
# Public `Chain` getters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -85,12 +85,6 @@ func verifyFrom*(c: ChainRef): BlockNumber =
|
||||||
## Getter
|
## Getter
|
||||||
c.verifyFrom
|
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
|
# Public `Chain` setters
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -198,30 +198,6 @@ proc persistBlocksImpl(
|
||||||
|
|
||||||
ok((blks, txs, gas))
|
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*(
|
proc persistBlocks*(
|
||||||
c: ChainRef, blocks: openArray[Block], flags: PersistBlockFlags = {}
|
c: ChainRef, blocks: openArray[Block], flags: PersistBlockFlags = {}
|
||||||
): Result[PersistStats, string] =
|
): Result[PersistStats, string] =
|
||||||
|
|
|
@ -68,33 +68,6 @@ template wrapRlpException(info: static[string]; code: untyped) =
|
||||||
except RlpError as e:
|
except RlpError as e:
|
||||||
return err(info & ": " & e.msg)
|
return err(info & ": " & e.msg)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private iterators
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc findNewAncestors(
|
|
||||||
db: CoreDbRef;
|
|
||||||
header: Header;
|
|
||||||
): Result[seq[Header], string] =
|
|
||||||
## Returns the chain leading up from the given header until the first
|
|
||||||
## ancestor it has in common with our canonical chain.
|
|
||||||
var
|
|
||||||
h = header
|
|
||||||
res = newSeq[Header]()
|
|
||||||
while true:
|
|
||||||
let orig = ?db.getBlockHeader(h.number)
|
|
||||||
if orig.rlpHash == h.rlpHash:
|
|
||||||
break
|
|
||||||
|
|
||||||
res.add(h)
|
|
||||||
|
|
||||||
if h.parentHash == GENESIS_PARENT_HASH:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
h = ?db.getBlockHeader(h.parentHash)
|
|
||||||
|
|
||||||
ok(res)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public iterators
|
# Public iterators
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -174,108 +147,6 @@ iterator getReceipts*(
|
||||||
break body
|
break body
|
||||||
yield rlp.decode(data, Receipt)
|
yield rlp.decode(data, Receipt)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Private helpers
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc removeTransactionFromCanonicalChain(
|
|
||||||
db: CoreDbRef;
|
|
||||||
transactionHash: Hash32;
|
|
||||||
) =
|
|
||||||
## Removes the transaction specified by the given hash from the canonical
|
|
||||||
## chain.
|
|
||||||
db.ctx.getKvt.del(transactionHashToBlockKey(transactionHash).toOpenArray).isOkOr:
|
|
||||||
warn "removeTransactionFromCanonicalChain",
|
|
||||||
transactionHash, error=($$error)
|
|
||||||
|
|
||||||
proc setAsCanonicalChainHead(
|
|
||||||
db: CoreDbRef;
|
|
||||||
headerHash: Hash32;
|
|
||||||
header: Header;
|
|
||||||
): Result[void, string] =
|
|
||||||
## Sets the header as the canonical chain HEAD.
|
|
||||||
# TODO This code handles reorgs - this should be moved elsewhere because we'll
|
|
||||||
# be handling reorgs mainly in-memory
|
|
||||||
if header.number == 0 or
|
|
||||||
db.getCanonicalHeaderHash().valueOr(default(Hash32)) != header.parentHash:
|
|
||||||
var newCanonicalHeaders = ?db.findNewAncestors(header)
|
|
||||||
reverse(newCanonicalHeaders)
|
|
||||||
for h in newCanonicalHeaders:
|
|
||||||
let
|
|
||||||
oldHash = ?db.getBlockHash(h.number)
|
|
||||||
oldHeader = ?db.getBlockHeader(oldHash)
|
|
||||||
for txHash in db.getBlockTransactionHashes(oldHeader):
|
|
||||||
db.removeTransactionFromCanonicalChain(txHash)
|
|
||||||
# TODO re-add txn to internal pending pool (only if local sender)
|
|
||||||
|
|
||||||
for h in newCanonicalHeaders:
|
|
||||||
# TODO don't recompute block hash
|
|
||||||
db.addBlockNumberToHashLookup(h.number, h.blockHash)
|
|
||||||
|
|
||||||
let canonicalHeadHash = canonicalHeadHashKey()
|
|
||||||
db.ctx.getKvt.put(canonicalHeadHash.toOpenArray, rlp.encode(headerHash)).isOkOr:
|
|
||||||
return err($$error)
|
|
||||||
ok()
|
|
||||||
|
|
||||||
proc markCanonicalChain(
|
|
||||||
db: CoreDbRef;
|
|
||||||
header: Header;
|
|
||||||
headerHash: Hash32;
|
|
||||||
): Result[void, string] =
|
|
||||||
## mark this chain as canonical by adding block number to hash lookup
|
|
||||||
## down to forking point
|
|
||||||
const
|
|
||||||
info = "markCanonicalChain()"
|
|
||||||
var
|
|
||||||
currHash = headerHash
|
|
||||||
currHeader = header
|
|
||||||
|
|
||||||
# mark current header as canonical
|
|
||||||
let
|
|
||||||
kvt = db.ctx.getKvt()
|
|
||||||
key = blockNumberToHashKey(currHeader.number)
|
|
||||||
kvt.put(key.toOpenArray, rlp.encode(currHash)).isOkOr:
|
|
||||||
return err($$error)
|
|
||||||
|
|
||||||
# it is a genesis block, done
|
|
||||||
if currHeader.parentHash == default(Hash32):
|
|
||||||
return ok()
|
|
||||||
|
|
||||||
# mark ancestor blocks as canonical too
|
|
||||||
currHash = currHeader.parentHash
|
|
||||||
currHeader = ?db.getBlockHeader(currHeader.parentHash)
|
|
||||||
|
|
||||||
template rlpDecodeOrZero(data: openArray[byte]): Hash32 =
|
|
||||||
try:
|
|
||||||
rlp.decode(data, Hash32)
|
|
||||||
except RlpError as exc:
|
|
||||||
warn info, key, error=exc.msg
|
|
||||||
default(Hash32)
|
|
||||||
|
|
||||||
while currHash != default(Hash32):
|
|
||||||
let key = blockNumberToHashKey(currHeader.number)
|
|
||||||
let data = kvt.getOrEmpty(key.toOpenArray).valueOr:
|
|
||||||
return err($$error)
|
|
||||||
if data.len == 0:
|
|
||||||
# not marked, mark it
|
|
||||||
kvt.put(key.toOpenArray, rlp.encode(currHash)).isOkOr:
|
|
||||||
return err($$error)
|
|
||||||
elif rlpDecodeOrZero(data) != currHash:
|
|
||||||
# replace prev chain
|
|
||||||
kvt.put(key.toOpenArray, rlp.encode(currHash)).isOkOr:
|
|
||||||
return err($$error)
|
|
||||||
else:
|
|
||||||
# forking point, done
|
|
||||||
break
|
|
||||||
|
|
||||||
if currHeader.parentHash == default(Hash32):
|
|
||||||
break
|
|
||||||
|
|
||||||
currHash = currHeader.parentHash
|
|
||||||
currHeader = ?db.getBlockHeader(currHeader.parentHash)
|
|
||||||
|
|
||||||
ok()
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions
|
# Public functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -632,9 +503,6 @@ proc setHead*(
|
||||||
db: CoreDbRef;
|
db: CoreDbRef;
|
||||||
blockHash: Hash32;
|
blockHash: Hash32;
|
||||||
): Result[void, string] =
|
): Result[void, string] =
|
||||||
let header = ?db.getBlockHeader(blockHash)
|
|
||||||
?db.markCanonicalChain(header, blockHash)
|
|
||||||
|
|
||||||
let canonicalHeadHash = canonicalHeadHashKey()
|
let canonicalHeadHash = canonicalHeadHashKey()
|
||||||
db.ctx.getKvt.put(canonicalHeadHash.toOpenArray, rlp.encode(blockHash)).isOkOr:
|
db.ctx.getKvt.put(canonicalHeadHash.toOpenArray, rlp.encode(blockHash)).isOkOr:
|
||||||
return err($$error)
|
return err($$error)
|
||||||
|
@ -650,7 +518,6 @@ proc setHead*(
|
||||||
if writeHeader:
|
if writeHeader:
|
||||||
kvt.put(genericHashKey(headerHash).toOpenArray, rlp.encode(header)).isOkOr:
|
kvt.put(genericHashKey(headerHash).toOpenArray, rlp.encode(header)).isOkOr:
|
||||||
return err($$error)
|
return err($$error)
|
||||||
?db.markCanonicalChain(header, headerHash)
|
|
||||||
let canonicalHeadHash = canonicalHeadHashKey()
|
let canonicalHeadHash = canonicalHeadHashKey()
|
||||||
kvt.put(canonicalHeadHash.toOpenArray, rlp.encode(headerHash)).isOkOr:
|
kvt.put(canonicalHeadHash.toOpenArray, rlp.encode(headerHash)).isOkOr:
|
||||||
return err($$error)
|
return err($$error)
|
||||||
|
@ -751,7 +618,7 @@ proc persistHeader*(
|
||||||
if score <= canonScore:
|
if score <= canonScore:
|
||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
db.setAsCanonicalChainHead(blockHash, header)
|
db.setHead(blockHash)
|
||||||
|
|
||||||
proc persistHeader*(
|
proc persistHeader*(
|
||||||
db: CoreDbRef;
|
db: CoreDbRef;
|
||||||
|
|
|
@ -433,14 +433,14 @@ proc rpcMain*() =
|
||||||
test "eth_getTransactionByHash":
|
test "eth_getTransactionByHash":
|
||||||
let res = await client.eth_getTransactionByHash(env.txHash)
|
let res = await client.eth_getTransactionByHash(env.txHash)
|
||||||
check res.isNil.not
|
check res.isNil.not
|
||||||
check res.blockNumber.get() == w3BlockNumber(1'u64)
|
check res.blockNumber.get() == w3Qty(1'u64)
|
||||||
let res2 = await client.eth_getTransactionByHash(env.blockHash)
|
let res2 = await client.eth_getTransactionByHash(env.blockHash)
|
||||||
check res2.isNil
|
check res2.isNil
|
||||||
|
|
||||||
test "eth_getTransactionByBlockHashAndIndex":
|
test "eth_getTransactionByBlockHashAndIndex":
|
||||||
let res = await client.eth_getTransactionByBlockHashAndIndex(env.blockHash, w3Qty(0'u64))
|
let res = await client.eth_getTransactionByBlockHashAndIndex(env.blockHash, w3Qty(0'u64))
|
||||||
check res.isNil.not
|
check res.isNil.not
|
||||||
check res.blockNumber.get() == w3BlockNumber(1'u64)
|
check res.blockNumber.get() == w3Qty(1'u64)
|
||||||
|
|
||||||
let res2 = await client.eth_getTransactionByBlockHashAndIndex(env.blockHash, w3Qty(3'u64))
|
let res2 = await client.eth_getTransactionByBlockHashAndIndex(env.blockHash, w3Qty(3'u64))
|
||||||
check res2.isNil
|
check res2.isNil
|
||||||
|
@ -451,7 +451,7 @@ proc rpcMain*() =
|
||||||
test "eth_getTransactionByBlockNumberAndIndex":
|
test "eth_getTransactionByBlockNumberAndIndex":
|
||||||
let res = await client.eth_getTransactionByBlockNumberAndIndex("latest", w3Qty(1'u64))
|
let res = await client.eth_getTransactionByBlockNumberAndIndex("latest", w3Qty(1'u64))
|
||||||
check res.isNil.not
|
check res.isNil.not
|
||||||
check res.blockNumber.get() == w3BlockNumber(1'u64)
|
check res.blockNumber.get() == w3Qty(1'u64)
|
||||||
|
|
||||||
let res2 = await client.eth_getTransactionByBlockNumberAndIndex("latest", w3Qty(3'u64))
|
let res2 = await client.eth_getTransactionByBlockNumberAndIndex("latest", w3Qty(3'u64))
|
||||||
check res2.isNil
|
check res2.isNil
|
||||||
|
@ -470,7 +470,7 @@ proc rpcMain*() =
|
||||||
# test "eth_getTransactionReceipt":
|
# test "eth_getTransactionReceipt":
|
||||||
# let res = await client.eth_getTransactionReceipt(env.txHash)
|
# let res = await client.eth_getTransactionReceipt(env.txHash)
|
||||||
# check res.isNil.not
|
# check res.isNil.not
|
||||||
# check res.blockNumber == w3BlockNumber(1'u64)
|
# check res.blockNumber == w3Qty(1'u64)
|
||||||
|
|
||||||
# let res2 = await client.eth_getTransactionReceipt(env.blockHash)
|
# let res2 = await client.eth_getTransactionReceipt(env.blockHash)
|
||||||
# check res2.isNil
|
# check res2.isNil
|
||||||
|
@ -478,7 +478,7 @@ proc rpcMain*() =
|
||||||
test "eth_getUncleByBlockHashAndIndex":
|
test "eth_getUncleByBlockHashAndIndex":
|
||||||
let res = await client.eth_getUncleByBlockHashAndIndex(env.blockHash, w3Qty(0'u64))
|
let res = await client.eth_getUncleByBlockHashAndIndex(env.blockHash, w3Qty(0'u64))
|
||||||
check res.isNil.not
|
check res.isNil.not
|
||||||
check res.number == w3BlockNumber(1'u64)
|
check res.number == w3Qty(1'u64)
|
||||||
|
|
||||||
let res2 = await client.eth_getUncleByBlockHashAndIndex(env.blockHash, w3Qty(1'u64))
|
let res2 = await client.eth_getUncleByBlockHashAndIndex(env.blockHash, w3Qty(1'u64))
|
||||||
check res2.isNil
|
check res2.isNil
|
||||||
|
@ -489,7 +489,7 @@ proc rpcMain*() =
|
||||||
test "eth_getUncleByBlockNumberAndIndex":
|
test "eth_getUncleByBlockNumberAndIndex":
|
||||||
let res = await client.eth_getUncleByBlockNumberAndIndex("latest", w3Qty(0'u64))
|
let res = await client.eth_getUncleByBlockNumberAndIndex("latest", w3Qty(0'u64))
|
||||||
check res.isNil.not
|
check res.isNil.not
|
||||||
check res.number == w3BlockNumber(1'u64)
|
check res.number == w3Qty(1'u64)
|
||||||
|
|
||||||
let res2 = await client.eth_getUncleByBlockNumberAndIndex("latest", w3Qty(1'u64))
|
let res2 = await client.eth_getUncleByBlockNumberAndIndex("latest", w3Qty(1'u64))
|
||||||
check res2.isNil
|
check res2.isNil
|
||||||
|
|
Loading…
Reference in New Issue