nimbus-eth1/nimbus/rpc/merge/mergeutils.nim

254 lines
8.2 KiB
Nim
Raw Normal View History

# Nimbus
# Copyright (c) 2022-2023 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
import
Unified database frontend integration (#1670) * Nimbus folder environment update details: * Integrated `CoreDbRef` for the sources in the `nimbus` sub-folder. * The `nimbus` program does not compile yet as it needs the updates in the parallel `stateless` sub-folder. * Stateless environment update details: * Integrated `CoreDbRef` for the sources in the `stateless` sub-folder. * The `nimbus` program compiles now. * Premix environment update details: * Integrated `CoreDbRef` for the sources in the `premix` sub-folder. * Fluffy environment update details: * Integrated `CoreDbRef` for the sources in the `fluffy` sub-folder. * Tools environment update details: * Integrated `CoreDbRef` for the sources in the `tools` sub-folder. * Nodocker environment update details: * Integrated `CoreDbRef` for the sources in the `hive_integration/nodocker` sub-folder. * Tests environment update details: * Integrated `CoreDbRef` for the sources in the `tests` sub-folder. * The unit tests compile and run cleanly now. * Generalise `CoreDbRef` to any `select_backend` supported database why: Generalisation was just missed due to overcoming some compiler oddity which was tied to rocksdb for testing. * Suppress compiler warning for `newChainDB()` why: Warning was added to this function which must be wrapped so that any `CatchableError` is re-raised as `Defect`. * Split off persistent `CoreDbRef` constructor into separate file why: This allows to compile a memory only database version without linking the backend library. * Use memory `CoreDbRef` database by default detail: Persistent DB constructor needs to import `db/core_db/persistent why: Most tests use memory DB anyway. This avoids linking `-lrocksdb` or any other backend by default. * fix `toLegacyBackend()` availability check why: got garbled after memory/persistent split. * Clarify raw access to MPT for snap sync handler why: Logically, `kvt` is not the raw access for the hexary trie (although this holds for the legacy database)
2023-08-04 12:10:09 +01:00
std/[typetraits, times, strutils],
eth/[rlp, common],
2022-07-04 12:34:10 +07:00
json_rpc/errors,
Unified database frontend integration (#1670) * Nimbus folder environment update details: * Integrated `CoreDbRef` for the sources in the `nimbus` sub-folder. * The `nimbus` program does not compile yet as it needs the updates in the parallel `stateless` sub-folder. * Stateless environment update details: * Integrated `CoreDbRef` for the sources in the `stateless` sub-folder. * The `nimbus` program compiles now. * Premix environment update details: * Integrated `CoreDbRef` for the sources in the `premix` sub-folder. * Fluffy environment update details: * Integrated `CoreDbRef` for the sources in the `fluffy` sub-folder. * Tools environment update details: * Integrated `CoreDbRef` for the sources in the `tools` sub-folder. * Nodocker environment update details: * Integrated `CoreDbRef` for the sources in the `hive_integration/nodocker` sub-folder. * Tests environment update details: * Integrated `CoreDbRef` for the sources in the `tests` sub-folder. * The unit tests compile and run cleanly now. * Generalise `CoreDbRef` to any `select_backend` supported database why: Generalisation was just missed due to overcoming some compiler oddity which was tied to rocksdb for testing. * Suppress compiler warning for `newChainDB()` why: Warning was added to this function which must be wrapped so that any `CatchableError` is re-raised as `Defect`. * Split off persistent `CoreDbRef` constructor into separate file why: This allows to compile a memory only database version without linking the backend library. * Use memory `CoreDbRef` database by default detail: Persistent DB constructor needs to import `db/core_db/persistent why: Most tests use memory DB anyway. This avoids linking `-lrocksdb` or any other backend by default. * fix `toLegacyBackend()` availability check why: got garbled after memory/persistent split. * Clarify raw access to MPT for snap sync handler why: Logically, `kvt` is not the raw access for the hexary trie (although this holds for the legacy database)
2023-08-04 12:10:09 +01:00
nimcrypto/[hash, sha2],
stew/[results, byteutils],
Unified database frontend integration (#1670) * Nimbus folder environment update details: * Integrated `CoreDbRef` for the sources in the `nimbus` sub-folder. * The `nimbus` program does not compile yet as it needs the updates in the parallel `stateless` sub-folder. * Stateless environment update details: * Integrated `CoreDbRef` for the sources in the `stateless` sub-folder. * The `nimbus` program compiles now. * Premix environment update details: * Integrated `CoreDbRef` for the sources in the `premix` sub-folder. * Fluffy environment update details: * Integrated `CoreDbRef` for the sources in the `fluffy` sub-folder. * Tools environment update details: * Integrated `CoreDbRef` for the sources in the `tools` sub-folder. * Nodocker environment update details: * Integrated `CoreDbRef` for the sources in the `hive_integration/nodocker` sub-folder. * Tests environment update details: * Integrated `CoreDbRef` for the sources in the `tests` sub-folder. * The unit tests compile and run cleanly now. * Generalise `CoreDbRef` to any `select_backend` supported database why: Generalisation was just missed due to overcoming some compiler oddity which was tied to rocksdb for testing. * Suppress compiler warning for `newChainDB()` why: Warning was added to this function which must be wrapped so that any `CatchableError` is re-raised as `Defect`. * Split off persistent `CoreDbRef` constructor into separate file why: This allows to compile a memory only database version without linking the backend library. * Use memory `CoreDbRef` database by default detail: Persistent DB constructor needs to import `db/core_db/persistent why: Most tests use memory DB anyway. This avoids linking `-lrocksdb` or any other backend by default. * fix `toLegacyBackend()` availability check why: got garbled after memory/persistent split. * Clarify raw access to MPT for snap sync handler why: Logically, `kvt` is not the raw access for the hexary trie (although this holds for the legacy database)
2023-08-04 12:10:09 +01:00
web3/engine_api_types,
2022-12-02 11:35:41 +07:00
../../constants,
Unified database frontend integration (#1670) * Nimbus folder environment update details: * Integrated `CoreDbRef` for the sources in the `nimbus` sub-folder. * The `nimbus` program does not compile yet as it needs the updates in the parallel `stateless` sub-folder. * Stateless environment update details: * Integrated `CoreDbRef` for the sources in the `stateless` sub-folder. * The `nimbus` program compiles now. * Premix environment update details: * Integrated `CoreDbRef` for the sources in the `premix` sub-folder. * Fluffy environment update details: * Integrated `CoreDbRef` for the sources in the `fluffy` sub-folder. * Tools environment update details: * Integrated `CoreDbRef` for the sources in the `tools` sub-folder. * Nodocker environment update details: * Integrated `CoreDbRef` for the sources in the `hive_integration/nodocker` sub-folder. * Tests environment update details: * Integrated `CoreDbRef` for the sources in the `tests` sub-folder. * The unit tests compile and run cleanly now. * Generalise `CoreDbRef` to any `select_backend` supported database why: Generalisation was just missed due to overcoming some compiler oddity which was tied to rocksdb for testing. * Suppress compiler warning for `newChainDB()` why: Warning was added to this function which must be wrapped so that any `CatchableError` is re-raised as `Defect`. * Split off persistent `CoreDbRef` constructor into separate file why: This allows to compile a memory only database version without linking the backend library. * Use memory `CoreDbRef` database by default detail: Persistent DB constructor needs to import `db/core_db/persistent why: Most tests use memory DB anyway. This avoids linking `-lrocksdb` or any other backend by default. * fix `toLegacyBackend()` availability check why: got garbled after memory/persistent split. * Clarify raw access to MPT for snap sync handler why: Logically, `kvt` is not the raw access for the hexary trie (although this holds for the legacy database)
2023-08-04 12:10:09 +01:00
../../db/core_db,
2023-07-09 09:16:22 +07:00
../../utils/utils,
2023-08-08 14:29:23 +07:00
../../rpc/execution_types,
./mergetypes
type Hash256 = eth_types.Hash256
2023-08-08 14:29:23 +07:00
proc computePayloadId*(headBlockHash: Hash256, params: SomePayloadAttributes): PayloadID =
var dest: Hash256
var ctx: sha256
ctx.init()
ctx.update(headBlockHash.data)
ctx.update(toBytesBE distinctBase params.timestamp)
ctx.update(distinctBase params.prevRandao)
ctx.update(distinctBase params.suggestedFeeRecipient)
# FIXME-Adam: Do we need to include the withdrawals in this calculation?
# https://github.com/ethereum/go-ethereum/pull/25838#discussion_r1024340383
# "The execution api specs define that this ID can be completely random. It
# used to be derived from payload attributes in the past, but maybe it's
# time to use a randomized ID to not break it with any changes to the
# attributes?"
ctx.finish dest.data
ctx.clear()
(distinctBase result)[0..7] = dest.data[0..7]
proc append*(w: var RlpWriter, q: Quantity) =
w.append(uint64(q))
proc append*(w: var RlpWriter, a: Address) =
w.append(distinctBase(a))
template unsafeQuantityToInt64(q: Quantity): int64 =
int64 q
template asEthHash*(hash: engine_api_types.BlockHash): Hash256 =
Hash256(data: distinctBase(hash))
proc calcRootHashRlp*(items: openArray[seq[byte]]): Hash256 =
Unified database frontend integration (#1670) * Nimbus folder environment update details: * Integrated `CoreDbRef` for the sources in the `nimbus` sub-folder. * The `nimbus` program does not compile yet as it needs the updates in the parallel `stateless` sub-folder. * Stateless environment update details: * Integrated `CoreDbRef` for the sources in the `stateless` sub-folder. * The `nimbus` program compiles now. * Premix environment update details: * Integrated `CoreDbRef` for the sources in the `premix` sub-folder. * Fluffy environment update details: * Integrated `CoreDbRef` for the sources in the `fluffy` sub-folder. * Tools environment update details: * Integrated `CoreDbRef` for the sources in the `tools` sub-folder. * Nodocker environment update details: * Integrated `CoreDbRef` for the sources in the `hive_integration/nodocker` sub-folder. * Tests environment update details: * Integrated `CoreDbRef` for the sources in the `tests` sub-folder. * The unit tests compile and run cleanly now. * Generalise `CoreDbRef` to any `select_backend` supported database why: Generalisation was just missed due to overcoming some compiler oddity which was tied to rocksdb for testing. * Suppress compiler warning for `newChainDB()` why: Warning was added to this function which must be wrapped so that any `CatchableError` is re-raised as `Defect`. * Split off persistent `CoreDbRef` constructor into separate file why: This allows to compile a memory only database version without linking the backend library. * Use memory `CoreDbRef` database by default detail: Persistent DB constructor needs to import `db/core_db/persistent why: Most tests use memory DB anyway. This avoids linking `-lrocksdb` or any other backend by default. * fix `toLegacyBackend()` availability check why: got garbled after memory/persistent split. * Clarify raw access to MPT for snap sync handler why: Logically, `kvt` is not the raw access for the hexary trie (although this holds for the legacy database)
2023-08-04 12:10:09 +01:00
var tr = newCoreDbRef(LegacyDbMemory).mptPrune
for i, t in items:
tr.put(rlp.encode(i), t)
return tr.rootHash()
2023-07-09 09:16:22 +07:00
proc toWithdrawal*(w: WithdrawalV1): Withdrawal =
Withdrawal(
index: uint64(w.index),
validatorIndex: uint64(w.validatorIndex),
address: distinctBase(w.address),
amount: uint64(w.amount) # AARDVARK: is this wei or gwei or what?
)
2023-07-09 09:16:22 +07:00
proc toWithdrawalV1*(w: Withdrawal): WithdrawalV1 =
WithdrawalV1(
index: Quantity(w.index),
validatorIndex: Quantity(w.validatorIndex),
address: Address(w.address),
amount: Quantity(w.amount) # AARDVARK: is this wei or gwei or what?
)
2023-08-08 14:29:23 +07:00
proc maybeWithdrawalsRoot(payload: SomeExecutionPayload): Option[Hash256] =
when payload is ExecutionPayloadV1:
2023-07-09 09:16:22 +07:00
none(Hash256)
else:
2023-07-09 09:16:22 +07:00
var wds = newSeqOfCap[Withdrawal](payload.withdrawals.len)
for wd in payload.withdrawals:
wds.add toWithdrawal(wd)
some(utils.calcWithdrawalsRoot(wds))
proc toWithdrawals(withdrawals: openArray[WithdrawalV1]): seq[WithDrawal] =
result = newSeqOfCap[Withdrawal](withdrawals.len)
for wd in withdrawals:
result.add toWithdrawal(wd)
2023-08-08 14:29:23 +07:00
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)
2023-07-09 09:16:22 +07:00
EthBlockHeader(
parentHash : payload.parentHash.asEthHash,
ommersHash : EMPTY_UNCLE_HASH,
coinbase : EthAddress payload.feeRecipient,
stateRoot : payload.stateRoot.asEthHash,
txRoot : txRoot,
receiptRoot : payload.receiptsRoot.asEthHash,
bloom : distinctBase(payload.logsBloom),
difficulty : default(DifficultyInt),
blockNumber : payload.blockNumber.distinctBase.u256,
gasLimit : payload.gasLimit.unsafeQuantityToInt64,
gasUsed : payload.gasUsed.unsafeQuantityToInt64,
timestamp : fromUnix payload.timestamp.unsafeQuantityToInt64,
extraData : bytes payload.extraData,
mixDigest : payload.prevRandao.asEthHash, # EIP-4399 redefine `mixDigest` -> `prevRandao`
nonce : default(BlockNonce),
fee : some payload.baseFeePerGas,
2023-08-08 14:29:23 +07:00
withdrawalsRoot: payload.maybeWithdrawalsRoot, # EIP-4895
blobGasUsed : payload.maybeBlobGasUsed, # EIP-4844
excessBlobGas : payload.maybeExcessBlobGas, # EIP-4844
)
proc toBlockHeader*(payload: ExecutionPayload): EthBlockHeader =
case payload.version
of Version.V1: toBlockHeader(payload.V1)
of Version.V2: toBlockHeader(payload.V2)
of Version.V3: toBlockHeader(payload.V3)
proc toTypedTransaction*(tx: Transaction): TypedTransaction =
TypedTransaction(rlp.encode(tx))
2023-08-08 14:29:23 +07:00
proc toBlockBody*(payload: SomeExecutionPayload): BlockBody =
2022-07-04 12:34:10 +07:00
result.transactions.setLen(payload.transactions.len)
for i, tx in payload.transactions:
result.transactions[i] = rlp.decode(distinctBase tx, Transaction)
when payload is ExecutionPayloadV2:
2023-07-09 09:16:22 +07:00
result.withdrawals = some(payload.withdrawals.toWithdrawals)
2023-08-08 14:29:23 +07:00
when payload is ExecutionPayloadV3:
result.withdrawals = some(payload.withdrawals.toWithdrawals)
2022-07-04 12:34:10 +07:00
proc `$`*(x: BlockHash): string =
toHex(x)
template toValidHash*(x: Hash256): Option[BlockHash] =
some(BlockHash(x.data))
2022-07-04 12:34:10 +07:00
proc validateBlockHash*(header: EthBlockHeader, gotHash: Hash256): Result[void, PayloadStatusV1] =
let wantHash = header.blockHash
if wantHash != gotHash:
2022-07-04 12:34:10 +07:00
let status = PayloadStatusV1(
# This used to say invalid_block_hash, but see here:
# https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_newpayloadv2
# "INVALID_BLOCK_HASH status value is supplanted by INVALID."
status: PayloadExecutionStatus.invalid,
2022-07-04 12:34:10 +07:00
validationError: some("blockhash mismatch, want $1, got $2" % [$wantHash, $gotHash])
)
return err(status)
return ok()
proc simpleFCU*(status: PayloadExecutionStatus): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(payloadStatus: PayloadStatusV1(status: status))
proc simpleFCU*(status: PayloadExecutionStatus, msg: string): ForkchoiceUpdatedResponse =
2022-07-04 12:34:10 +07:00
ForkchoiceUpdatedResponse(
payloadStatus: PayloadStatusV1(
status: status,
validationError: some(msg)
)
)
2022-06-17 07:53:33 +07:00
proc invalidFCU*(hash: Hash256 = Hash256()): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(payloadStatus:
PayloadStatusV1(
status: PayloadExecutionStatus.invalid,
2022-07-04 12:34:10 +07:00
latestValidHash: toValidHash(hash)
2022-06-17 07:53:33 +07:00
)
)
2022-04-08 11:54:11 +07:00
proc validFCU*(id: Option[PayloadID], validHash: Hash256): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(
payloadStatus: PayloadStatusV1(
status: PayloadExecutionStatus.valid,
2022-07-04 12:34:10 +07:00
latestValidHash: toValidHash(validHash)
),
payloadId: id
)
proc invalidStatus*(validHash: Hash256, msg: string): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.invalid,
2022-07-04 12:34:10 +07:00
latestValidHash: toValidHash(validHash),
validationError: some(msg)
)
2022-06-17 07:53:33 +07:00
proc invalidStatus*(validHash: Hash256 = Hash256()): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.invalid,
2022-07-04 12:34:10 +07:00
latestValidHash: toValidHash(validHash)
2022-06-17 07:53:33 +07:00
)
proc acceptedStatus*(validHash: Hash256): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.accepted,
2022-07-04 12:34:10 +07:00
latestValidHash: toValidHash(validHash)
)
2022-07-04 12:34:10 +07:00
proc acceptedStatus*(): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.accepted
)
proc validStatus*(validHash: Hash256): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.valid,
latestValidHash: toValidHash(validHash)
)
proc invalidParams*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiInvalidParams,
msg: msg
)
proc unknownPayload*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiUnknownPayload,
msg: msg
)
proc invalidAttr*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiInvalidPayloadAttributes,
msg: msg
)
2023-08-08 14:29:23 +07:00
proc unsupportedFork*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiUnsupportedFork,
msg: msg
)
proc tooLargeRequest*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiTooLargeRequest,
msg: msg
)