nimbus-eth1/nimbus/beacon/api_handler/api_utils.nim

200 lines
5.8 KiB
Nim

# Nimbus
# Copyright (c) 2022-2024 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
std/[typetraits, strutils],
eth/[rlp],
json_rpc/errors,
nimcrypto/[hash, sha2],
stew/endians2,
results,
../../constants,
../../db/core_db,
../../utils/utils,
../../common/common,
web3/execution_types,
../web3_eth_conv
{.push gcsafe, raises:[].}
proc update(ctx: var sha256, wd: WithdrawalV1) =
ctx.update(toBytesBE distinctBase wd.index)
ctx.update(toBytesBE distinctBase wd.validatorIndex)
ctx.update(distinctBase wd.address)
ctx.update(toBytesBE distinctBase wd.amount)
proc computePayloadId*(blockHash: common.Hash256,
params: PayloadAttributes): PayloadID =
var dest: common.Hash256
var ctx: sha256
ctx.init()
ctx.update(blockHash.data)
ctx.update(toBytesBE distinctBase params.timestamp)
ctx.update(distinctBase params.prevRandao)
ctx.update(distinctBase params.suggestedFeeRecipient)
if params.withdrawals.isSome:
for wd in params.withdrawals.get:
ctx.update(wd)
if params.parentBeaconBlockRoot.isSome:
ctx.update(distinctBase params.parentBeaconBlockRoot.get)
ctx.finish dest.data
ctx.clear()
(distinctBase result)[0..7] = dest.data[0..7]
proc validateBlockHash*(header: common.BlockHeader,
gotHash: common.Hash256,
version: Version): Result[void, PayloadStatusV1]
{.gcsafe, raises: [ValueError].} =
let wantHash = header.blockHash
if wantHash != gotHash:
let status = if version == Version.V1:
PayloadExecutionStatus.invalid_block_hash
else:
PayloadExecutionStatus.invalid
let res = PayloadStatusV1(
status: status,
validationError: Opt.some("blockhash mismatch, want $1, got $2" % [
$wantHash, $gotHash])
)
return err(res)
return ok()
template toValidHash*(x: common.Hash256): Opt[Web3Hash] =
Opt.some(w3Hash x)
proc simpleFCU*(status: PayloadStatusV1): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(payloadStatus: status)
proc simpleFCU*(status: PayloadExecutionStatus): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(payloadStatus: PayloadStatusV1(status: status))
proc simpleFCU*(status: PayloadExecutionStatus,
msg: string): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(
payloadStatus: PayloadStatusV1(
status: status,
validationError: Opt.some(msg)
)
)
proc invalidFCU*(
validationError: string,
hash = common.Hash256()): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(payloadStatus:
PayloadStatusV1(
status: PayloadExecutionStatus.invalid,
latestValidHash: toValidHash(hash),
validationError: Opt.some validationError
)
)
proc validFCU*(id: Opt[PayloadID],
validHash: common.Hash256): ForkchoiceUpdatedResponse =
ForkchoiceUpdatedResponse(
payloadStatus: PayloadStatusV1(
status: PayloadExecutionStatus.valid,
latestValidHash: toValidHash(validHash)
),
payloadId: id
)
proc invalidStatus*(validHash: common.Hash256, msg: string): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.invalid,
latestValidHash: toValidHash(validHash),
validationError: Opt.some(msg)
)
proc invalidStatus*(validHash = common.Hash256()): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.invalid,
latestValidHash: toValidHash(validHash)
)
proc acceptedStatus*(validHash: common.Hash256): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.accepted,
latestValidHash: toValidHash(validHash)
)
proc acceptedStatus*(): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.accepted
)
proc validStatus*(validHash: common.Hash256): PayloadStatusV1 =
PayloadStatusV1(
status: PayloadExecutionStatus.valid,
latestValidHash: toValidHash(validHash)
)
proc invalidParams*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiInvalidParams,
msg: msg
)
proc invalidForkChoiceState*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiInvalidForkchoiceState,
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
)
proc unsupportedFork*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiUnsupportedFork,
msg: msg
)
proc tooLargeRequest*(msg: string): ref InvalidRequest =
(ref InvalidRequest)(
code: engineApiTooLargeRequest,
msg: msg
)
proc latestValidHash*(db: CoreDbRef,
parent: common.BlockHeader,
ttd: DifficultyInt): common.Hash256 =
if parent.isGenesis:
return common.Hash256()
let ptd = db.getScore(parent.parentHash).valueOr(0.u256)
if ptd >= ttd:
parent.blockHash
else:
# If the most recent valid ancestor is a PoW block,
# latestValidHash MUST be set to ZERO
common.Hash256()
proc invalidFCU*(validationError: string,
com: CommonRef,
header: common.BlockHeader): ForkchoiceUpdatedResponse =
var parent: common.BlockHeader
if not com.db.getBlockHeader(header.parentHash, parent):
return invalidFCU(validationError)
let blockHash = try:
latestValidHash(com.db, parent, com.ttd.get(high(UInt256)))
except RlpError:
default(common.Hash256)
invalidFCU(validationError, blockHash)