From ac053bf4c866962592e0207479e9cbcf0a38d4e9 Mon Sep 17 00:00:00 2001 From: andri lim Date: Thu, 16 Jan 2025 12:10:52 +0700 Subject: [PATCH] devnet-5: Add EIP-7840: Add blob schedule to EL config files (#3005) * devnet-5: Add EIP-7840: Add blob schedule to EL config files * Fix test_transaction_json * Add missing blobSchedule to common/helpers --- nimbus/common/chain_config.nim | 66 +++++++++++++++++-- nimbus/common/chain_config_hash.nim | 11 +++- nimbus/common/common.nim | 8 +++ nimbus/common/hardforks.nim | 7 +- nimbus/core/eip7691.nim | 20 ++++-- nimbus/core/executor/process_transaction.nim | 5 +- nimbus/core/tx_pool/tx_desc.nim | 1 + nimbus/core/tx_pool/tx_packer.nim | 11 ++-- nimbus/core/validate.nim | 10 +-- .../blobschedule_cancun_osaka.json | 27 ++++++++ .../blobschedule_cancun_prague.json | 27 ++++++++ tests/customgenesis/blobschedule_prague.json | 23 +++++++ tests/customgenesis/merge.json | 12 +++- tests/test_genesis.nim | 29 +++++++- tests/test_helpers.nim | 42 ++++++------ tests/test_transaction_json.nim | 12 +++- tests/test_txpool.nim | 48 ++++++++++++-- tools/common/helpers.nim | 3 +- 18 files changed, 305 insertions(+), 57 deletions(-) create mode 100644 tests/customgenesis/blobschedule_cancun_osaka.json create mode 100644 tests/customgenesis/blobschedule_cancun_prague.json create mode 100644 tests/customgenesis/blobschedule_prague.json diff --git a/nimbus/common/chain_config.nim b/nimbus/common/chain_config.nim index 30c99b2f28..0120bc2ee6 100644 --- a/nimbus/common/chain_config.nim +++ b/nimbus/common/chain_config.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2021-2024 Status Research & Development GmbH +# Copyright (c) 2021-2025 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -72,6 +72,7 @@ NetworkParams.useDefaultReaderIn JGenesis GenesisAccount.useDefaultReaderIn JGenesis Genesis.useDefaultReaderIn JGenesis ChainConfig.useDefaultReaderIn JGenesis +BlobSchedule.useDefaultReaderIn JGenesis # ------------------------------------------------------------------------------ # Private helper functions @@ -274,6 +275,43 @@ proc readValue(reader: var JsonReader[JGenesis], value: var GenesisAlloc) for key in reader.readObjectFields: value[Address.fromHex(key)] = reader.readValue(GenesisAccount) +const + BlobScheduleTable: array[Cancun..HardFork.high, string] = [ + "cancun", + "prague", + "osaka" + ] + +func ofStmt(fork: HardFork, keyName: string, reader: NimNode, value: NimNode): NimNode = + let branchStmt = quote do: + `value`[`fork`] = reader.readValue(Opt[BlobSchedule]) + + nnkOfBranch.newTree( + newLit(keyName), + branchStmt + ) + +macro blobScheduleParser(reader, key, value: typed): untyped = + # Automated blob schedule parser generator + var caseStmt = nnkCaseStmt.newTree( + quote do: `key` + ) + + for fork in Cancun..HardFork.high: + let keyName = BlobScheduleTable[fork] + caseStmt.add ofStmt(fork, keyName, reader, value) + + caseStmt.add nnkElse.newTree( + quote do: discard + ) + result = caseStmt + +proc readValue(reader: var JsonReader[JGenesis], value: var array[Cancun..HardFork.high, Opt[BlobSchedule]]) + {.gcsafe, raises: [SerializationError, IOError].} = + wrapError: + for key in reader.readObjectFields: + blobScheduleParser(reader, key, value) + macro fillArrayOfBlockNumberBasedForkOptionals(conf, tmp: typed): untyped = result = newStmtList() for i, x in forkBlockField: @@ -304,7 +342,7 @@ func toHardFork*(map: ForkTransitionTable, forkDeterminer: ForkDeterminationInfo # should always have a match doAssert(false, "unreachable code") -proc validateChainConfig*(conf: ChainConfig): bool = +proc validateChainConfig(conf: ChainConfig): bool = result = true # FIXME: factor this to remove the duplication between the @@ -353,6 +391,15 @@ proc validateChainConfig*(conf: ChainConfig): bool = if cur.time.isSome: lastTimeBasedFork = cur +proc configureBlobSchedule(conf: ChainConfig) = + var prevFork = Cancun + if conf.blobSchedule[Cancun].isNone: + conf.blobSchedule[Cancun] = Opt.some(BlobSchedule()) + for fork in Prague..HardFork.high: + if conf.blobSchedule[fork].isNone: + conf.blobSchedule[fork] = conf.blobSchedule[prevFork] + prevFork = fork + proc parseGenesis*(data: string): Genesis {.gcsafe.} = try: @@ -393,6 +440,7 @@ proc validateNetworkParams(params: var NetworkParams, input: string, inputIsFile warn "Loaded custom network contains no 'config' data" params.config = ChainConfig() + configureBlobSchedule(params.config) validateChainConfig(params.config) proc loadNetworkParams*(fileName: string, params: var NetworkParams): @@ -435,6 +483,13 @@ proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool return true +func defaultBlobSchedule*(): array[Cancun..HardFork.high, Opt[BlobSchedule]] = + [ + Cancun: Opt.some(BlobSchedule(target: 3'u64, max: 6'u64)), + Prague: Opt.some(BlobSchedule(target: 6'u64, max: 9'u64)), + Osaka : Opt.some(BlobSchedule(target: 6'u64, max: 9'u64)), + ] + func chainConfigForNetwork*(id: NetworkId): ChainConfig = # For some public networks, NetworkId and ChainId value are identical # but that is not always the case @@ -446,8 +501,8 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig = MAINNET_DEPOSIT_CONTRACT_ADDRESS = address"0x00000000219ab540356cbb839cbe05303d7705fa" ChainConfig( chainId: MainNet.ChainId, - # Genesis (Frontier): # 2015-07-30 15:26:13 UTC - # Frontier Thawing: 200_000.BlockNumber, # 2015-09-07 21:33:09 UTC + # Genesis (Frontier): # 2015-07-30 15:26:13 UTC + # Frontier Thawing: 200_000.BlockNumber, # 2015-09-07 21:33:09 UTC homesteadBlock: Opt.some(1_150_000.BlockNumber), # 2016-03-14 18:49:53 UTC daoForkBlock: Opt.some(1_920_000.BlockNumber), # 2016-07-20 13:20:40 UTC daoForkSupport: true, @@ -469,6 +524,7 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig = shanghaiTime: Opt.some(1_681_338_455.EthTime), # 2023-04-12 10:27:35 UTC cancunTime: Opt.some(1_710_338_135.EthTime), # 2024-03-13 13:55:35 UTC depositContractAddress: Opt.some(MAINNET_DEPOSIT_CONTRACT_ADDRESS), + blobSchedule: defaultBlobSchedule(), ) of SepoliaNet: const sepoliaTTD = parse("17000000000000000",UInt256) @@ -491,6 +547,7 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig = terminalTotalDifficulty: Opt.some(sepoliaTTD), shanghaiTime: Opt.some(1_677_557_088.EthTime), cancunTime: Opt.some(1_706_655_072.EthTime), # 2024-01-30 22:51:12 + blobSchedule: defaultBlobSchedule(), ) of HoleskyNet: #https://github.com/eth-clients/holesky @@ -513,6 +570,7 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig = shanghaiTime: Opt.some(1_696_000_704.EthTime), cancunTime: Opt.some(1_707_305_664.EthTime), # 2024-02-07 11:34:24 depositContractAddress: Opt.some(HOLESKYNET_DEPOSIT_CONTRACT_ADDRESS), + blobSchedule: defaultBlobSchedule(), ) else: ChainConfig() diff --git a/nimbus/common/chain_config_hash.nim b/nimbus/common/chain_config_hash.nim index 27974fe0b2..c11df4ff40 100644 --- a/nimbus/common/chain_config_hash.nim +++ b/nimbus/common/chain_config_hash.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2024 Status Research & Development GmbH +# Copyright (c) 2024-2025 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -25,8 +25,8 @@ import # complicated steps before the genesis hash is ready. See `CommonRef.init`. # If the genesis happen to exists in database belonging to other network, # it will replace the one in CommonRef cache. -# That is the reason why using genesis header or genesis hash + ChainId is -# not a good solution to prevent loading existing data directory for +# That is the reason why using genesis header or genesis hash + ChainId is +# not a good solution to prevent loading existing data directory for # the wrong network. # But the ChainConfig + raw Genesis hash will make the job done before # CommonRef creation. @@ -66,6 +66,11 @@ func update[T: ref](ctx: var sha256, val: T) = for f in fields(val[]): ctx.update(f) +func update(ctx: var sha256, list: openArray[Opt[BlobSchedule]]) = + mixin update + for val in list: + ctx.update(val) + # ------------------------------------------------------------------------------ # Public functions # ------------------------------------------------------------------------------ diff --git a/nimbus/common/common.nim b/nimbus/common/common.nim index e5964b835f..53853040b8 100644 --- a/nimbus/common/common.nim +++ b/nimbus/common/common.nim @@ -416,6 +416,14 @@ func extraData*(com: CommonRef): string = func gasLimit*(com: CommonRef): uint64 = com.gasLimit +func maxBlobsPerBlock*(com: CommonRef, fork: HardFork): uint64 = + doAssert(fork >= Cancun) + com.config.blobSchedule[fork].expect("blobSchedule initialized").max + +func targetBlobsPerBlock*(com: CommonRef, fork: HardFork): uint64 = + doAssert(fork >= Cancun) + com.config.blobSchedule[fork].expect("blobSchedule initialized").target + # ------------------------------------------------------------------------------ # Setters # ------------------------------------------------------------------------------ diff --git a/nimbus/common/hardforks.nim b/nimbus/common/hardforks.nim index 7a75ecd648..25fb58ccab 100644 --- a/nimbus/common/hardforks.nim +++ b/nimbus/common/hardforks.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2022-2024 Status Research & Development GmbH +# Copyright (c) 2022-2025 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -134,6 +134,10 @@ func isGTETransitionThreshold*(map: ForkTransitionTable, forkDeterminer: ForkDet raise newException(Defect, "Why is this hard fork not in one of the above categories?") type + BlobSchedule* = object + target*: uint64 + max* : uint64 + # if you add more fork block # please update forkBlockField constant too ChainConfig* = ref object @@ -172,6 +176,7 @@ type terminalTotalDifficulty*: Opt[UInt256] depositContractAddress*: Opt[Address] + blobSchedule* : array[Cancun..HardFork.high, Opt[BlobSchedule]] # These are used for checking that the values of the fields # are in a valid order. diff --git a/nimbus/core/eip7691.nim b/nimbus/core/eip7691.nim index 860d30e215..2cadf76ed9 100644 --- a/nimbus/core/eip7691.nim +++ b/nimbus/core/eip7691.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2024 Status Research & Development GmbH +# Copyright (c) 2024-2025 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) @@ -11,7 +11,10 @@ {.push raises: [].} import - ../constants + ../constants, + ../common/hardforks, + ../common/evmforks, + ../common/common func getMaxBlobGasPerBlock*(electra: bool): uint64 = if electra: MAX_BLOB_GAS_PER_BLOCK_ELECTRA.uint64 @@ -25,6 +28,13 @@ func getBlobBaseFeeUpdateFraction*(electra: bool): uint64 = if electra: BLOB_BASE_FEE_UPDATE_FRACTION_ELECTRA.uint64 else: BLOB_BASE_FEE_UPDATE_FRACTION.uint64 -func getMaxBlobsPerBlock*(electra: bool): uint64 = - if electra: MAX_BLOBS_PER_BLOCK_ELECTRA.uint64 - else: MAX_BLOBS_PER_BLOCK.uint64 +const + EVMForkToFork: array[FkCancun..EVMFork.high, HardFork] = [ + Cancun, + Prague, + Osaka + ] + +func getMaxBlobsPerBlock*(com: CommonRef, fork: EVMFork): uint64 = + doAssert(fork >= FkCancun) + com.maxBlobsPerBlock(EVMForkToFork[fork]) diff --git a/nimbus/core/executor/process_transaction.nim b/nimbus/core/executor/process_transaction.nim index b737b04e14..baa2875c5c 100644 --- a/nimbus/core/executor/process_transaction.nim +++ b/nimbus/core/executor/process_transaction.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018-2024 Status Research & Development GmbH +# Copyright (c) 2018-2025 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) @@ -103,7 +103,8 @@ proc processTransactionImpl( # of the `processTransaction()` function. So there is no `return err()` # statement, here. let - txRes = roDB.validateTransaction(tx, sender, header.gasLimit, baseFee256, excessBlobGas, fork) + com = vmState.com + txRes = roDB.validateTransaction(tx, sender, header.gasLimit, baseFee256, excessBlobGas, com, fork) res = if txRes.isOk: # EIP-1153 vmState.ledger.clearTransientStorage() diff --git a/nimbus/core/tx_pool/tx_desc.nim b/nimbus/core/tx_pool/tx_desc.nim index c06e5e4211..289bcb1717 100644 --- a/nimbus/core/tx_pool/tx_desc.nim +++ b/nimbus/core/tx_pool/tx_desc.nim @@ -332,6 +332,7 @@ proc addTx*(xp: TxPoolRef, ptx: PooledTransaction): Result[void, TxError] = return err(txErrorAlreadyKnown) validateTxBasic( + xp.com, ptx.tx, xp.nextFork, validateFork = true).isOkOr: diff --git a/nimbus/core/tx_pool/tx_packer.nim b/nimbus/core/tx_pool/tx_packer.nim index a547f657f1..4e921cadc6 100644 --- a/nimbus/core/tx_pool/tx_packer.nim +++ b/nimbus/core/tx_pool/tx_packer.nim @@ -71,10 +71,10 @@ proc classifyValidatePacked(vmState: BaseVMState; item: TxItemRef): bool = baseFee = vmState.blockCtx.baseFeePerGas.get(0.u256) fork = vmState.fork gasLimit = vmState.blockCtx.gasLimit - excessBlobGas = calcExcessBlobGas(vmState.parent, vmState.fork >= FkPrague) + excessBlobGas = calcExcessBlobGas(vmState.parent, fork >= FkPrague) roDB.validateTransaction( - item.tx, item.sender, gasLimit, baseFee, excessBlobGas, fork).isOk + item.tx, item.sender, gasLimit, baseFee, excessBlobGas, vmState.com, fork).isOk proc classifyPacked(vmState: BaseVMState; moreBurned: GasInt): bool = ## Classifier for *packing* (i.e. adding up `gasUsed` values after executing @@ -169,9 +169,10 @@ proc vmExecGrabItem(pst: var TxPacker; item: TxItemRef, xp: TxPoolRef): bool = electra = vmState.fork >= FkPrague # EIP-4844 - let maxBlobsPerBlock = getMaxBlobsPerBlock(electra) - if (pst.numBlobPerBlock + item.tx.versionedHashes.len).uint64 > maxBlobsPerBlock: - return ContinueWithNextAccount + if item.tx.txType == TxEip4844: + let maxBlobsPerBlock = getMaxBlobsPerBlock(vmState.com, vmState.fork) + if (pst.numBlobPerBlock + item.tx.versionedHashes.len).uint64 > maxBlobsPerBlock: + return ContinueWithNextAccount let blobGasUsed = item.tx.getTotalBlobGas diff --git a/nimbus/core/validate.nim b/nimbus/core/validate.nim index 8448525618..aec35981b9 100644 --- a/nimbus/core/validate.nim +++ b/nimbus/core/validate.nim @@ -206,6 +206,7 @@ func gasCost*(tx: Transaction): UInt256 = tx.gasLimit.u256 * tx.gasPrice.u256 proc validateTxBasic*( + com: CommonRef, tx: Transaction; ## tx to validate fork: EVMFork, validateFork: bool = true): Result[void, string] = @@ -260,9 +261,9 @@ proc validateTxBasic*( if tx.versionedHashes.len == 0: return err("invalid tx: there must be at least one blob") - let maxBlobsPerBlob = getMaxBlobsPerBlock(fork >= FkPrague) - if tx.versionedHashes.len.uint64 > maxBlobsPerBlob: - return err(&"invalid tx: versioned hashes len exceeds MAX_BLOBS_PER_BLOCK={maxBlobsPerBlob}. get={tx.versionedHashes.len}") + let maxBlobsPerBlock = getMaxBlobsPerBlock(com, fork) + if tx.versionedHashes.len.uint64 > maxBlobsPerBlock: + return err(&"invalid tx: versioned hashes len exceeds MAX_BLOBS_PER_BLOCK={maxBlobsPerBlock}. get={tx.versionedHashes.len}") for i, bv in tx.versionedHashes: if bv.data[0] != VERSIONED_HASH_VERSION_KZG: @@ -282,9 +283,10 @@ proc validateTransaction*( maxLimit: GasInt; ## gasLimit from block header baseFee: UInt256; ## baseFee from block header excessBlobGas: uint64; ## excessBlobGas from parent block header + com: CommonRef, fork: EVMFork): Result[void, string] = - ? validateTxBasic(tx, fork) + ? validateTxBasic(com, tx, fork) let balance = roDB.getBalance(sender) diff --git a/tests/customgenesis/blobschedule_cancun_osaka.json b/tests/customgenesis/blobschedule_cancun_osaka.json new file mode 100644 index 0000000000..c6b7414e33 --- /dev/null +++ b/tests/customgenesis/blobschedule_cancun_osaka.json @@ -0,0 +1,27 @@ +{ + "config": { + "chainId": 7, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x5de1ee4135274003348e80b788e5afa4b18b18d320a5622218d5c493fedf5689", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6 + }, + "osaka": { + "target": 6, + "max": 9 + } + } + } +} diff --git a/tests/customgenesis/blobschedule_cancun_prague.json b/tests/customgenesis/blobschedule_cancun_prague.json new file mode 100644 index 0000000000..3ca75e5fd5 --- /dev/null +++ b/tests/customgenesis/blobschedule_cancun_prague.json @@ -0,0 +1,27 @@ +{ + "config": { + "chainId": 7, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x5de1ee4135274003348e80b788e5afa4b18b18d320a5622218d5c493fedf5689", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6 + }, + "prague": { + "target": 6, + "max": 9 + } + } + } +} diff --git a/tests/customgenesis/blobschedule_prague.json b/tests/customgenesis/blobschedule_prague.json new file mode 100644 index 0000000000..932db723d4 --- /dev/null +++ b/tests/customgenesis/blobschedule_prague.json @@ -0,0 +1,23 @@ +{ + "config": { + "chainId": 7, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x5de1ee4135274003348e80b788e5afa4b18b18d320a5622218d5c493fedf5689", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "blobSchedule": { + "prague": { + "target": 6, + "max": 9 + } + } + } +} diff --git a/tests/customgenesis/merge.json b/tests/customgenesis/merge.json index 07f82c2efc..2948a8cb6f 100644 --- a/tests/customgenesis/merge.json +++ b/tests/customgenesis/merge.json @@ -13,9 +13,15 @@ "muirGlacierBlock": 0, "berlinBlock": 0, "londonBlock": 0, - "clique": { - "epoch": 3000, - "period": 1 + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6 + }, + "prague": { + "target": 6, + "max": 9 + } } }, "genesis": { diff --git a/tests/test_genesis.nim b/tests/test_genesis.nim index 7f8e320217..66b204efb0 100644 --- a/tests/test_genesis.nim +++ b/tests/test_genesis.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2019-2024 Status Research & Development GmbH +# Copyright (c) 2019-2025 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) @@ -151,10 +151,33 @@ proc customGenesisTest() = (CONSOLIDATION_REQUEST_TYPE, default(seq[byte])) ]) == EmptyRequestsHash + test "BlobSchedule": + template validateBlobSchedule(cg, fork, tgt, mx) = + check cg.config.blobSchedule[fork].isSome + if cg.config.blobSchedule[fork].isSome: + let bs = cg.config.blobSchedule[fork].get + check bs.target == tgt + check bs.max == mx + + var cg: NetworkParams + check loadNetworkParams("blobschedule_cancun_prague.json".findFilePath, cg) + validateBlobSchedule(cg, Cancun, 3, 6) + validateBlobSchedule(cg, Prague, 6, 9) + validateBlobSchedule(cg, Osaka, 6, 9) + + check loadNetworkParams("blobschedule_cancun_osaka.json".findFilePath, cg) + validateBlobSchedule(cg, Cancun, 3, 6) + validateBlobSchedule(cg, Prague, 3, 6) + validateBlobSchedule(cg, Osaka, 6, 9) + + check loadNetworkParams("blobschedule_prague.json".findFilePath, cg) + validateBlobSchedule(cg, Cancun, 0, 0) + validateBlobSchedule(cg, Prague, 6, 9) + validateBlobSchedule(cg, Osaka, 6, 9) + proc genesisMain*() = genesisTest() customGenesisTest() when isMainModule: - genesisTest() - customGenesisTest() + genesisMain() diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim index 1dd9f9b99a..b77d4eba59 100644 --- a/tests/test_helpers.nim +++ b/tests/test_helpers.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018-2024 Status Research & Development GmbH +# Copyright (c) 2018-2025 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) # * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) @@ -13,29 +13,31 @@ import ../nimbus/db/ledger, ../nimbus/common/[context, common] -func revmap(x: Table[EVMFork, string]): Table[string, EVMFork] = - result = Table[string, EVMFork]() - for k, v in x: +func revTable(list: array[EVMFork, string]): Table[string, EVMFork] = + for k, v in list: result[v] = k const # from https://ethereum-tests.readthedocs.io/en/latest/test_types/state_tests.html - forkNames* = { - FkFrontier: "Frontier", - FkHomestead: "Homestead", - FkTangerine: "EIP150", - FkSpurious: "EIP158", - FkByzantium: "Byzantium", - FkConstantinople: "Constantinople", - FkPetersburg: "ConstantinopleFix", - FkIstanbul: "Istanbul", - FkBerlin: "Berlin", - FkLondon: "London", - FkParis: "Merge", - FkPrague: "Prague", - }.toTable - - nameToFork* = revmap(forkNames) + ForkToName: array[EVMFork, string] = [ + "Frontier", # FkFrontier + "Homestead", # FkHomestead + "EIP150", # FkTangerine + "EIP158", # FkSpurious + "Byzantium", # FkByzantium + "Constantinople", # FkConstantinople + "ConstantinopleFix", # FkPetersburg + "Istanbul", # FkIstanbul + "Berlin", # FkBerlin + "London", # FkLondon + "Merge", # FkParis + "Shanghai", # FkShanghai + "Cancun", # FkCancun + "Prague", # FkPrague + "Osaka", # FkOsaka + ] + + nameToFork* = ForkToName.revTable func skipNothing*(folder: string, name: string): bool = false diff --git a/tests/test_transaction_json.nim b/tests/test_transaction_json.nim index 367bfc99f0..86abd55b55 100644 --- a/tests/test_transaction_json.nim +++ b/tests/test_transaction_json.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2019-2024 Status Research & Development GmbH +# Copyright (c) 2019-2025 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) @@ -14,6 +14,9 @@ import eth/rlp, ./test_helpers, eth/common/transaction_utils, + ../tools/common/helpers as chp, + ../nimbus/db/core_db, + ../nimbus/common/common, ../nimbus/transaction, ../nimbus/core/validate, ../nimbus/utils/utils @@ -34,7 +37,12 @@ proc txHash(tx: Transaction): string = rlpHash(tx).toHex() proc testTxByFork(tx: Transaction, forkData: JsonNode, forkName: string, testStatusIMPL: var TestStatus) = - tx.validateTxBasic(nameToFork[forkName]).isOkOr: + let + config = getChainConfig(forkName) + memDB = newCoreDbRef DefaultDbMemory + com = CommonRef.new(memDB, nil, config) + + validateTxBasic(com, tx, nameToFork[forkName]).isOkOr: return if forkData.len > 0 and "sender" in forkData: diff --git a/tests/test_txpool.nim b/tests/test_txpool.nim index ddae00a637..79175a3f3f 100644 --- a/tests/test_txpool.nim +++ b/tests/test_txpool.nim @@ -56,17 +56,21 @@ proc initEnv(envFork: HardFork): TestEnv = doAssert envFork >= MergeFork + let cc = conf.networkParams.config if envFork >= MergeFork: - conf.networkParams.config.mergeNetsplitBlock = Opt.some(0'u64) + cc.mergeNetsplitBlock = Opt.some(0'u64) if envFork >= Shanghai: - conf.networkParams.config.shanghaiTime = Opt.some(0.EthTime) + cc.shanghaiTime = Opt.some(0.EthTime) if envFork >= Cancun: - conf.networkParams.config.cancunTime = Opt.some(0.EthTime) + cc.cancunTime = Opt.some(0.EthTime) if envFork >= Prague: - conf.networkParams.config.pragueTime = Opt.some(0.EthTime) + cc.pragueTime = Opt.some(0.EthTime) + + if envFork >= Osaka: + cc.osakaTime = Opt.some(0.EthTime) conf.networkParams.genesis.alloc[recipient] = GenesisAccount(code: contractCode) @@ -614,5 +618,41 @@ proc txPoolMain*() = # invalid auth, but the tx itself still valid xp.checkImportBlock(1, 0) + test "Blobschedule": + let + cc = env.conf.networkParams.config + acc = mx.getAccount(26) + tc = BlobTx( + txType: Opt.some(TxEip4844), + gasLimit: 75000, + recipient: Opt.some(acc.address), + blobID: 0.BlobID, + blobCount: 1 + ) + tx1 = mx.makeTx(tc, acc, 0) + tx2 = mx.makeTx(tc, acc, 1) + tx3 = mx.makeTx(tc, acc, 2) + tx4 = mx.makeTx(tc, acc, 3) + + xp.checkAddTx(tx1) + xp.checkAddTx(tx2) + xp.checkAddTx(tx3) + xp.checkAddTx(tx4) + + # override current blobSchedule + let bs = cc.blobSchedule[Cancun] + cc.blobSchedule[Cancun] = Opt.some( + BlobSchedule(target: 2, max: 3) + ) + + # allow 3 blobs + xp.checkImportBlock(3, 1) + + # consume the rest of blobs + xp.checkImportBlock(1, 0) + + # restore blobSchedule + cc.blobSchedule[Cancun] = bs + when isMainModule: txPoolMain() diff --git a/tools/common/helpers.nim b/tools/common/helpers.nim index 91d3dc55fd..c8ff8735d3 100644 --- a/tools/common/helpers.nim +++ b/tools/common/helpers.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2022-2024 Status Research & Development GmbH +# Copyright (c) 2022-2025 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) @@ -65,6 +65,7 @@ func getChainConfig*(network: string, c: ChainConfig) = c.daoForkSupport = false c.chainId = 1.ChainId c.terminalTotalDifficulty = Opt.none(UInt256) + c.blobSchedule = defaultBlobSchedule() case network of $TestFork.Frontier: