diff --git a/hive_integration/nodocker/engine/cancun/customizer.nim b/hive_integration/nodocker/engine/cancun/customizer.nim index d6bc7499c..bee6cf99f 100644 --- a/hive_integration/nodocker/engine/cancun/customizer.nim +++ b/hive_integration/nodocker/engine/cancun/customizer.nim @@ -425,7 +425,7 @@ proc customizePayload*(cust: CustomPayloadData, data: ExecutableData): Executabl if cust.versionedHashesCustomizer.isNil.not: doAssert(data.versionedHashes.isSome) result.versionedHashes = cust.versionedHashesCustomizer.getVersionedHashes(data.versionedHashes.get) - + # Base new payload directive call cust. # Used as base to other customizers. type @@ -615,22 +615,22 @@ proc generateInvalidPayload*(sender: TxSender, data: ExecutableData, payloadFiel excessBlobGas: some(modExcessBlobGas), ) of InvalidVersionedHashesVersion: - doAssert(data.versionedHashes.isNone, "no versioned hashes available for modification") + doAssert(data.versionedHashes.isSome, "no versioned hashes available for modification") customPayloadMod = CustomPayloadData( versionedHashesCustomizer: IncreaseVersionVersionedHashes(), ) of InvalidVersionedHashes: - doAssert(data.versionedHashes.isNone, "no versioned hashes available for modification") + doAssert(data.versionedHashes.isSome, "no versioned hashes available for modification") customPayloadMod = CustomPayloadData( versionedHashesCustomizer: CorruptVersionedHashes(), ) of IncompleteVersionedHashes: - doAssert(data.versionedHashes.isNone, "no versioned hashes available for modification") + doAssert(data.versionedHashes.isSome, "no versioned hashes available for modification") customPayloadMod = CustomPayloadData( versionedHashesCustomizer: RemoveVersionedHash(), ) of ExtraVersionedHashes: - doAssert(data.versionedHashes.isNone, "no versioned hashes available for modification") + doAssert(data.versionedHashes.isSome, "no versioned hashes available for modification") customPayloadMod = CustomPayloadData( versionedHashesCustomizer: ExtraVersionedHash(), ) diff --git a/hive_integration/nodocker/engine/cancun/step_sendblobtx.nim b/hive_integration/nodocker/engine/cancun/step_sendblobtx.nim index ebf1fb40f..5485ce675 100644 --- a/hive_integration/nodocker/engine/cancun/step_sendblobtx.nim +++ b/hive_integration/nodocker/engine/cancun/step_sendblobtx.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2023 Status Research & Development GmbH +# Copyright (c) 2023-2024 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) diff --git a/hive_integration/nodocker/engine/cancun_tests.nim b/hive_integration/nodocker/engine/cancun_tests.nim index b8efa6391..110b44206 100644 --- a/hive_integration/nodocker/engine/cancun_tests.nim +++ b/hive_integration/nodocker/engine/cancun_tests.nim @@ -1865,7 +1865,7 @@ proc makeCancunTest(): seq[EngineSpec] = mainFork: ForkCancun, fieldModification: t, ) -#[ + # Invalid Payload Tests const invalidFields = [ @@ -1911,7 +1911,6 @@ proc makeCancunTest(): seq[EngineSpec] = invalidDetectedOnSync: invalidDetectedOnSync, nilLatestValidHash : nilLatestValidHash, ) - ]# # Invalid Transaction ChainID Tests result.add InvalidTxChainIDTest( diff --git a/hive_integration/nodocker/engine/tx_sender.nim b/hive_integration/nodocker/engine/tx_sender.nim index daeab4c19..32d917adc 100644 --- a/hive_integration/nodocker/engine/tx_sender.nim +++ b/hive_integration/nodocker/engine/tx_sender.nim @@ -22,11 +22,16 @@ import type BaseTx* = object of RootObj - recipient*: Option[EthAddress] - gasLimit* : GasInt - amount* : UInt256 - payload* : seq[byte] - txType* : Option[TxType] + recipient* : Option[EthAddress] + gasLimit* : GasInt + amount* : UInt256 + payload* : seq[byte] + txType* : Option[TxType] + gasTip* : GasInt + gasFee* : GasInt + blobGasFee*: UInt256 + blobCount* : int + blobID* : BlobID BigInitcodeTx* = object of BaseTx initcodeLength*: int @@ -35,11 +40,6 @@ type # Blob transaction creator BlobTx* = object of BaseTx - gasFee* : GasInt - gasTip* : GasInt - blobGasFee*: UInt256 - blobID* : BlobID - blobCount* : int TestAccount* = object key* : PrivateKey @@ -77,6 +77,7 @@ const TestAccountCount = 1000 gasPrice* = 30.gwei gasTipPrice* = 1.gwei + blobGasPrice* = 1.gwei func toAddress(key: PrivateKey): EthAddress = toKeyPair(key).pubkey.toCanonicalAddress() @@ -129,37 +130,75 @@ proc getTxType(tc: BaseTx, nonce: uint64): TxType = else: tc.txType.get -proc makeTx(params: MakeTxParams, tc: BaseTx): Transaction = - const - gasFeeCap = gasPrice - gasTipCap = gasTipPrice +proc makeTxOfType(params: MakeTxParams, tc: BaseTx): Transaction = + let + gasFeeCap = if tc.gasFee != 0.GasInt: tc.gasFee + else: gasPrice + gasTipCap = if tc.gasTip != 0.GasInt: tc.gasTip + else: gasTipPrice let txType = tc.getTxType(params.nonce) + case txType + of TxLegacy: + Transaction( + txType : TxLegacy, + nonce : params.nonce, + to : tc.recipient, + value : tc.amount, + gasLimit: tc.gasLimit, + gasPrice: gasPrice, + payload : tc.payload + ) + of TxEip1559: + Transaction( + txType : TxEIP1559, + nonce : params.nonce, + gasLimit: tc.gasLimit, + maxFee : gasFeeCap, + maxPriorityFee: gasTipCap, + to : tc.recipient, + value : tc.amount, + payload : tc.payload, + chainId : params.chainId + ) + of TxEip4844: + doAssert(tc.recipient.isSome, "recipient must be some") + let + blobCount = if tc.blobCount != 0: tc.blobCount + else: MAX_BLOBS_PER_BLOCK + blobFeeCap = if tc.blobGasFee != 0.u256: tc.blobGasFee + else: blobGasPrice.u256 + # Need tx wrap data that will pass blob verification + var blobData = blobDataGenerator(tc.blobID, blobCount) + #tc.blobID += BlobID(blobCount) + + Transaction( + txType : TxEIP4844, + nonce : params.nonce, + chainId : params.chainId, + maxFee : gasFeeCap, + maxPriorityFee: gasTipCap, + gasLimit: tc.gasLimit, + to : tc.recipient, + value : tc.amount, + payload : tc.payload, + #AccessList: tc.AccessList, + maxFeePerBlobGas: blobFeeCap, + versionedHashes: system.move(blobData.hashes), + networkPayload: NetworkPayload( + blobs: system.move(blobData.blobs), + commitments: system.move(blobData.commitments), + proofs: system.move(blobData.proofs), + ) + ) + else: + doAssert(false, "unsupported tx type") + Transaction() + +proc makeTx(params: MakeTxParams, tc: BaseTx): Transaction = # Build the transaction depending on the specified type - let tx = if txType == TxLegacy: - Transaction( - txType : TxLegacy, - nonce : params.nonce, - to : tc.recipient, - value : tc.amount, - gasLimit: tc.gasLimit, - gasPrice: gasPrice, - payload : tc.payload - ) - else: - Transaction( - txType : TxEIP1559, - nonce : params.nonce, - gasLimit: tc.gasLimit, - maxFee : gasFeeCap, - maxPriorityFee: gasTipCap, - to : tc.recipient, - value : tc.amount, - payload : tc.payload, - chainId : params.chainId - ) - + let tx = makeTxOfType(params, tc) signTransaction(tx, params.key, params.chainId, eip155 = true) proc makeTx(params: MakeTxParams, tc: BigInitcodeTx): Transaction = @@ -263,13 +302,13 @@ proc makeTx*(params: MakeTxParams, tc: BlobTx): Transaction = let data = blobDataGenerator(tc.blobID, tc.blobCount) doAssert(tc.recipient.isSome, "nil recipient address") - # Collect fields for transaction let gasFeeCap = if tc.gasFee != 0.GasInt: tc.gasFee else: gasPrice gasTipCap = if tc.gasTip != 0.GasInt: tc.gasTip else: gasTipPrice + # Collect fields for transaction let unsignedTx = Transaction( txType : TxEip4844, chainId : params.chainId, diff --git a/nimbus/beacon/api_handler.nim b/nimbus/beacon/api_handler.nim index 7875cfd90..861a15a61 100644 --- a/nimbus/beacon/api_handler.nim +++ b/nimbus/beacon/api_handler.nim @@ -8,11 +8,6 @@ # those terms. import - std/[options, typetraits], - eth/common, - ./web3_eth_conv, - ./beacon_engine, - web3/execution_types, ./api_handler/api_utils, ./api_handler/api_getpayload, ./api_handler/api_getbodies, @@ -24,25 +19,6 @@ import # Public functions # ------------------------------------------------------------------------------ -{.push gcsafe, raises:[CatchableError].} - -func validateVersionedHashed*(payload: ExecutionPayload, - expected: openArray[Web3Hash]): bool = - var versionedHashes: seq[common.Hash256] - for x in payload.transactions: - let tx = rlp.decode(distinctBase(x), Transaction) - versionedHashes.add tx.versionedHashes - - if versionedHashes.len != expected.len: - return false - - for i, x in expected: - if distinctBase(x) != versionedHashes[i].data: - return false - true - -{.pop.} - export invalidStatus, getPayload, diff --git a/nimbus/beacon/api_handler/api_newpayload.nim b/nimbus/beacon/api_handler/api_newpayload.nim index e261ce8ba..37e74f0b0 100644 --- a/nimbus/beacon/api_handler/api_newpayload.nim +++ b/nimbus/beacon/api_handler/api_newpayload.nim @@ -19,6 +19,21 @@ import {.push gcsafe, raises:[CatchableError].} +func validateVersionedHashed(payload: ExecutionPayload, + expected: openArray[Web3Hash]): bool = + var versionedHashes: seq[common.Hash256] + for x in payload.transactions: + let tx = rlp.decode(distinctBase(x), Transaction) + versionedHashes.add tx.versionedHashes + + if versionedHashes.len != expected.len: + return false + + for i, x in expected: + if distinctBase(x) != versionedHashes[i].data: + return false + true + template validateVersion(com, timestamp, version, apiVersion) = if apiVersion == Version.V4: if not com.isPragueOrLater(timestamp): @@ -83,6 +98,7 @@ template validatePayload(apiVersion, version, payload) = proc newPayload*(ben: BeaconEngineRef, apiVersion: Version, payload: ExecutionPayload, + versionedHashes = none(seq[Web3Hash]), beaconRoot = none(Web3Hash)): PayloadStatusV1 = trace "Engine API request received", @@ -90,7 +106,7 @@ proc newPayload*(ben: BeaconEngineRef, number = payload.blockNumber, hash = payload.blockHash - if apiVersion == Version.V3: + if apiVersion >= Version.V3: if beaconRoot.isNone: raise invalidParams("newPayloadV3 expect beaconRoot but got none") @@ -108,6 +124,12 @@ proc newPayload*(ben: BeaconEngineRef, header.validateBlockHash(blockHash, version).isOkOr: return error + if apiVersion >= Version.V3: + if versionedHashes.isNone: + raise invalidParams("newPayload" & $apiVersion & + " expect blobVersionedHashes but got none") + if not validateVersionedHashed(payload, versionedHashes.get): + return invalidStatus(header.parentHash, "invalid blob versionedHashes") # If we already have the block locally, ignore the entire execution and just # return a fake success. diff --git a/nimbus/rpc/engine_api.nim b/nimbus/rpc/engine_api.nim index ecee40a50..ec384685d 100644 --- a/nimbus/rpc/engine_api.nim +++ b/nimbus/rpc/engine_api.nim @@ -13,8 +13,7 @@ import web3/[conversions, execution_types], ../beacon/api_handler, ../beacon/beacon_engine, - ../beacon/web3_eth_conv, - ../beacon/api_handler/api_utils + ../beacon/web3_eth_conv {.push raises: [].} @@ -53,20 +52,12 @@ proc setupEngineAPI*(engine: BeaconEngineRef, server: RpcServer) = server.rpc("engine_newPayloadV3") do(payload: ExecutionPayload, 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, parentBeaconBlockRoot) + return engine.newPayload(Version.V3, payload, expectedBlobVersionedHashes, parentBeaconBlockRoot) server.rpc("engine_newPayloadV4") do(payload: ExecutionPayload, expectedBlobVersionedHashes: Option[seq[Web3Hash]], parentBeaconBlockRoot: Option[Web3Hash]) -> PayloadStatusV1: - if expectedBlobVersionedHashes.isNone: - raise invalidParams("newPayloadV4 expect blobVersionedHashes but got none") - if not validateVersionedHashed(payload, expectedBlobVersionedHashes.get): - return invalidStatus() - return engine.newPayload(Version.V4, payload, parentBeaconBlockRoot) + return engine.newPayload(Version.V4, payload, expectedBlobVersionedHashes, parentBeaconBlockRoot) server.rpc("engine_getPayloadV1") do(payloadId: PayloadID) -> ExecutionPayloadV1: return engine.getPayload(Version.V1, payloadId).executionPayload.V1