diff --git a/nimbus/beacon/api_handler/api_forkchoice.nim b/nimbus/beacon/api_handler/api_forkchoice.nim index ee77a1482c..24a06892f9 100644 --- a/nimbus/beacon/api_handler/api_forkchoice.nim +++ b/nimbus/beacon/api_handler/api_forkchoice.nim @@ -39,7 +39,7 @@ template validateVersion(attrsOpt, com, expectedVersion) = raise invalidParams("if timestamp is earlier than Shanghai," & " payloadAttributes must be PayloadAttributesV1") - if version != expectedVersion: + if expectedVersion == Version.V3 and version != expectedVersion: raise invalidParams("forkChoiceUpdated" & $expectedVersion & " expect PayloadAttributes" & $expectedVersion & " but got PayloadAttributes" & $version) diff --git a/nimbus/beacon/api_handler/api_getpayload.nim b/nimbus/beacon/api_handler/api_getpayload.nim index 5375ad77e0..45faa084c2 100644 --- a/nimbus/beacon/api_handler/api_getpayload.nim +++ b/nimbus/beacon/api_handler/api_getpayload.nim @@ -18,17 +18,25 @@ import {.push gcsafe, raises:[CatchableError].} -proc getPayload*(ben: BeaconEngineRef, id: PayloadID): GetPayloadV2Response = +proc getPayload*(ben: BeaconEngineRef, + expectedVersion: Version, + id: PayloadID): GetPayloadV2Response = trace "Engine API request received", meth = "GetPayload", id - var payload: ExecutionPayloadV1OrV2 + var payloadGeneric: ExecutionPayload var blockValue: UInt256 - if not ben.get(id, blockValue, payload): + if not ben.get(id, blockValue, payloadGeneric): raise unknownPayload("Unknown payload") + let version = payloadGeneric.version + if version > expectedVersion: + raise unsupportedFork("getPayload" & $expectedVersion & + " expect ExecutionPayload" & $expectedVersion & + " but get ExecutionPayload" & $version) + GetPayloadV2Response( - executionPayload: payload, + executionPayload: payloadGeneric.V1V2, blockValue: blockValue ) @@ -36,11 +44,16 @@ proc getPayloadV3*(ben: BeaconEngineRef, id: PayloadID): GetPayloadV3Response = trace "Engine API request received", meth = "GetPayload", id - var payload: ExecutionPayloadV3 + var payloadGeneric: ExecutionPayload var blockValue: UInt256 - if not ben.get(id, blockValue, payload): + if not ben.get(id, blockValue, payloadGeneric): raise unknownPayload("Unknown payload") + let version = payloadGeneric.version + if version != Version.V3: + raise unsupportedFork("getPayloadV3 expect ExecutionPayloadV3 but get ExecutionPayload" & $version) + + let payload = payloadGeneric.V3 let com = ben.com if not com.isCancunOrLater(ethTime payload.timestamp): raise unsupportedFork("payload timestamp is less than Cancun activation") diff --git a/nimbus/beacon/api_handler/api_newpayload.nim b/nimbus/beacon/api_handler/api_newpayload.nim index f679aac513..7527f98fcf 100644 --- a/nimbus/beacon/api_handler/api_newpayload.nim +++ b/nimbus/beacon/api_handler/api_newpayload.nim @@ -38,7 +38,7 @@ template validateVersion(com, timestamp, version, expectedVersion) = raise invalidParams("if timestamp is earlier than Shanghai, " & "payload must be ExecutionPayloadV1") - if version != expectedVersion: + if expectedVersion == Version.V3 and version != expectedVersion: raise invalidParams("newPayload" & $expectedVersion & " expect ExecutionPayload" & $expectedVersion & " but got ExecutionPayload" & $version) @@ -54,6 +54,10 @@ proc newPayload*(ben: BeaconEngineRef, number = payload.blockNumber, hash = payload.blockHash + if expectedVersion == Version.V3: + if beaconRoot.isNone: + raise invalidParams("newPayloadV3 expect beaconRoot but got none") + let com = ben.com db = com.db diff --git a/nimbus/beacon/web3_eth_conv.nim b/nimbus/beacon/web3_eth_conv.nim index 8c02bbc300..05b59102cf 100644 --- a/nimbus/beacon/web3_eth_conv.nim +++ b/nimbus/beacon/web3_eth_conv.nim @@ -71,6 +71,9 @@ func w3PrevRandao*(): Web3PrevRandao = func w3Address*(): Web3Address = discard +func w3Hash*(): Web3Hash = + discard + # ------------------------------------------------------------------------------ # Web3 types to Eth types # ------------------------------------------------------------------------------ @@ -144,6 +147,19 @@ func ethTxs*(list: openArray[Web3Tx], removeBlobs = false): func w3Hash*(x: common.Hash256): Web3Hash = Web3Hash x.data +func w3Hashes*(list: openArray[common.Hash256]): seq[Web3Hash] = + for x in list: + result.add Web3Hash x.data + +func w3Hashes*(z: Option[seq[common.Hash256]]): Option[seq[Web3Hash]] = + if z.isNone: none(seq[Web3Hash]) + else: + let list = z.get + var v = newSeq[Web3Hash](list.len) + for x in list: + v.add Web3Hash x.data + some(v) + func w3Hash*(x: Option[common.Hash256]): Option[BlockHash] = if x.isNone: none(BlockHash) else: some(BlockHash x.get.data) diff --git a/nimbus/core/tx_pool/tx_tasks/tx_classify.nim b/nimbus/core/tx_pool/tx_tasks/tx_classify.nim index 7460af04bf..6a5bb6872f 100644 --- a/nimbus/core/tx_pool/tx_tasks/tx_classify.nim +++ b/nimbus/core/tx_pool/tx_tasks/tx_classify.nim @@ -37,7 +37,13 @@ logScope: # ------------------------------------------------------------------------------ proc checkTxBasic(xp: TxPoolRef; item: TxItemRef): bool = - let res = validateTxBasic(item.tx.removeNetworkPayload, xp.chain.nextFork) + let res = validateTxBasic( + item.tx.removeNetworkPayload, + xp.chain.nextFork, + # A new transaction of the next fork may be + # coming before the fork activated + validateFork = false + ) if res.isOk: return true item.info = res.error diff --git a/nimbus/core/validate.nim b/nimbus/core/validate.nim index bd4257566b..1922366409 100644 --- a/nimbus/core/validate.nim +++ b/nimbus/core/validate.nim @@ -226,16 +226,18 @@ func gasCost*(tx: Transaction): UInt256 = proc validateTxBasic*( tx: Transaction; ## tx to validate - fork: EVMFork): Result[void, string] = - - if tx.txType == TxEip2930 and fork < FkBerlin: - return err("invalid tx: Eip2930 Tx type detected before Berlin") - - if tx.txType == TxEip1559 and fork < FkLondon: - return err("invalid tx: Eip1559 Tx type detected before London") - - if tx.txType == TxEip4844 and fork < FkCancun: - return err("invalid tx: Eip4844 Tx type detected before Cancun") + fork: EVMFork, + validateFork: bool = true): Result[void, string] = + + if validateFork: + if tx.txType == TxEip2930 and fork < FkBerlin: + return err("invalid tx: Eip2930 Tx type detected before Berlin") + + if tx.txType == TxEip1559 and fork < FkLondon: + return err("invalid tx: Eip1559 Tx type detected before London") + + if tx.txType == TxEip4844 and fork < FkCancun: + return err("invalid tx: Eip4844 Tx type detected before Cancun") if fork >= FkShanghai and tx.contractCreation and tx.payload.len > EIP3860_MAX_INITCODE_SIZE: return err("invalid tx: initcode size exceeds maximum") diff --git a/nimbus/rpc/engine_api.nim b/nimbus/rpc/engine_api.nim index b284d4866c..5d0a0300fb 100644 --- a/nimbus/rpc/engine_api.nim +++ b/nimbus/rpc/engine_api.nim @@ -15,7 +15,8 @@ import ../beacon/api_handler, ../beacon/beacon_engine, ../beacon/web3_eth_conv, - ../beacon/execution_types + ../beacon/execution_types, + ../beacon/api_handler/api_utils {.push raises: [].} @@ -50,17 +51,19 @@ proc setupEngineAPI*(engine: BeaconEngineRef, server: RpcServer) = return engine.newPayload(Version.V2, payload) server.rpc("engine_newPayloadV3") do(payload: ExecutionPayload, - expectedBlobVersionedHashes: seq[Web3Hash], - parentBeaconBlockRoot: Web3Hash) -> PayloadStatusV1: - if not validateVersionedHashed(payload, expectedBlobVersionedHashes): + expectedBlobVersionedHashes: Option[seq[Web3Hash]], + parentBeaconBlockRoot: Option[Web3Hash]) -> PayloadStatusV1: + if expectedBlobVersionedHashes.isNone: + raise invalidParams("newPayloadV3 expect blobVersionedHashes but got none") + if not validateVersionedHashed(payload, expectedBlobVersionedHashes.get): return invalidStatus() - return engine.newPayload(Version.V3, payload, some(parentBeaconBlockRoot)) + return engine.newPayload(Version.V3, payload, parentBeaconBlockRoot) server.rpc("engine_getPayloadV1") do(payloadId: PayloadID) -> ExecutionPayloadV1: - return engine.getPayload(payloadId).executionPayload.V1 + return engine.getPayload(Version.V1, payloadId).executionPayload.V1 server.rpc("engine_getPayloadV2") do(payloadId: PayloadID) -> GetPayloadV2Response: - return engine.getPayload(payloadId) + return engine.getPayload(Version.V2, payloadId) server.rpc("engine_getPayloadV3") do(payloadId: PayloadID) -> GetPayloadV3Response: return engine.getPayloadV3(payloadId)