From b7365085ae766398b836ce3bdcd5e19962a6ffb8 Mon Sep 17 00:00:00 2001 From: andri lim Date: Sun, 1 Oct 2023 14:24:15 +0700 Subject: [PATCH] Implement EIP-7516: BLOBBASEFEE opcode (#1791) * Implement EIP-7516: BLOBBASEFEE opcode --- nimbus/evm/computation.nim | 14 +- nimbus/evm/evmc_api.nim | 1 + nimbus/evm/interpreter/gas_costs.nim | 1 + nimbus/evm/interpreter/op_codes.nim | 3 +- .../interpreter/op_handlers/oph_blockdata.nim | 14 ++ nimbus/evm/state_transactions.nim | 8 +- nimbus/evm/types.nim | 14 +- nimbus/transaction/call_common.nim | 9 +- nimbus/transaction/evmc_host_glue.nim | 6 +- nimbus/transaction/evmc_vm_glue.nim | 6 +- nimbus/transaction/host_services.nim | 12 +- nimbus/utils/debug.nim | 6 +- nimbus/vm_types.nim | 3 +- tests/test_op_env.nim | 140 +++++++++--------- vendor/nim-evmc | 2 +- 15 files changed, 138 insertions(+), 101 deletions(-) diff --git a/nimbus/evm/computation.nim b/nimbus/evm/computation.nim index 12bb203bc..3cbff129d 100644 --- a/nimbus/evm/computation.nim +++ b/nimbus/evm/computation.nim @@ -107,25 +107,31 @@ template getOrigin*(c: Computation): EthAddress = when evmc_enabled: c.host.getTxContext().tx_origin else: - c.vmState.txOrigin + c.vmState.txCtx.origin template getGasPrice*(c: Computation): GasInt = when evmc_enabled: UInt256.fromEvmc(c.host.getTxContext().tx_gas_price).truncate(GasInt) else: - c.vmState.txGasPrice + c.vmState.txCtx.gasPrice template getVersionedHash*(c: Computation, index: int): VersionedHash = when evmc_enabled: cast[ptr UncheckedArray[VersionedHash]](c.host.getTxContext().blob_hashes)[index] else: - c.vmState.txVersionedHashes[index] + c.vmState.txCtx.versionedHashes[index] template getVersionedHashesLen*(c: Computation): int = when evmc_enabled: c.host.getTxContext().blob_hashes_count.int else: - c.vmState.txVersionedHashes.len + c.vmState.txCtx.versionedHashes.len + +template getBlobBaseFee*(c: Computation): UInt256 = + when evmc_enabled: + UInt256.fromEvmc c.host.getTxContext().blob_base_fee + else: + c.vmState.txCtx.blobBaseFee proc getBlockHash*(c: Computation, number: UInt256): Hash256 {.gcsafe, raises: [CatchableError].} = diff --git a/nimbus/evm/evmc_api.nim b/nimbus/evm/evmc_api.nim index a3ce55297..073c3571a 100644 --- a/nimbus/evm/evmc_api.nim +++ b/nimbus/evm/evmc_api.nim @@ -30,6 +30,7 @@ type block_base_fee* : evmc_uint256be # The block base fee. blob_hashes* : ptr evmc_bytes32 # The array of blob hashes (EIP-4844). blob_hashes_count*: csize_t # The number of blob hashes (EIP-4844). + blob_base_fee* : evmc_uint256be # The blob base fee (EIP-7516). nimbus_message* = object kind* : evmc_call_kind diff --git a/nimbus/evm/interpreter/gas_costs.nim b/nimbus/evm/interpreter/gas_costs.nim index 04f2c1c5f..332784e8c 100644 --- a/nimbus/evm/interpreter/gas_costs.nim +++ b/nimbus/evm/interpreter/gas_costs.nim @@ -620,6 +620,7 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) = SelfBalance: fixed GasLow, BaseFee: fixed GasBase, BlobHash: fixed GasVeryLow, + BlobBaseFee: fixed GasBase, # 50s: Stack, Memory, Storage and Flow Operations Pop: fixed GasBase, diff --git a/nimbus/evm/interpreter/op_codes.nim b/nimbus/evm/interpreter/op_codes.nim index 46ec4f8bd..13a447d3b 100644 --- a/nimbus/evm/interpreter/op_codes.nim +++ b/nimbus/evm/interpreter/op_codes.nim @@ -105,8 +105,9 @@ type SelfBalance = 0x47, ## Get current contract's balance. BaseFee = 0x48, ## Get block’s base fee. EIP-3198 BlobHash = 0x49, ## Get transaction's versionedHash. EIP-4844 + BlobBaseFee = 0x4A, ## Returns the current data-blob base-fee - Nop0x4A, Nop0x4B, Nop0x4C, Nop0x4D, + Nop0x4B, Nop0x4C, Nop0x4D, Nop0x4E, Nop0x4F, ## .. # 50s: Stack, Memory, Storage and Flow Operations diff --git a/nimbus/evm/interpreter/op_handlers/oph_blockdata.nim b/nimbus/evm/interpreter/op_handlers/oph_blockdata.nim index 72c5b3304..fdb25969f 100644 --- a/nimbus/evm/interpreter/op_handlers/oph_blockdata.nim +++ b/nimbus/evm/interpreter/op_handlers/oph_blockdata.nim @@ -93,6 +93,12 @@ const k.cpt.stack.push: 0 + blobBaseFeeOp: Vm2OpFn = proc (k: var Vm2Ctx) = + ## 0x4a, Get the block's base fee. + k.cpt.stack.push: + k.cpt.getBlobBaseFee + + # ------------------------------------------------------------------------------ # Public, op exec table entries # ------------------------------------------------------------------------------ @@ -178,6 +184,14 @@ const info: "Get current transaction's EIP-4844 versioned hash", exec: (prep: vm2OpIgnore, run: blobHashOp, + post: vm2OpIgnore)), + + (opCode: BlobBaseFee, ## 0x4a, EIP-7516 Returns the current data-blob base-fee + forks: Vm2OpCancunAndLater, + name: "blobBaseFee", + info: "Returns the current data-blob base-fee", + exec: (prep: vm2OpIgnore, + run: blobBaseFeeOp, post: vm2OpIgnore))] # ------------------------------------------------------------------------------ diff --git a/nimbus/evm/state_transactions.nim b/nimbus/evm/state_transactions.nim index aaf7c0346..db9a10f03 100644 --- a/nimbus/evm/state_transactions.nim +++ b/nimbus/evm/state_transactions.nim @@ -24,21 +24,17 @@ import {.push raises: [].} proc setupTxContext*(vmState: BaseVMState, - origin: EthAddress, - gasPrice: GasInt, - versionedHashes: openArray[VersionedHash], + txCtx: sink TxContext, forkOverride=none(EVMFork)) = ## this proc will be called each time a new transaction ## is going to be executed - vmState.txOrigin = origin - vmState.txGasPrice = gasPrice + vmState.txCtx = system.move(txCtx) vmState.fork = if forkOverride.isSome: forkOverride.get else: vmState.determineFork vmState.gasCosts = vmState.fork.forkToSchedule - vmState.txVersionedHashes = @versionedHashes # FIXME-awkwardFactoring: the factoring out of the pre and # post parts feels awkward to me, but for now I'd really like diff --git a/nimbus/evm/types.nim b/nimbus/evm/types.nim index 4227d8c79..f9c23202a 100644 --- a/nimbus/evm/types.nim +++ b/nimbus/evm/types.nim @@ -51,21 +51,25 @@ type coinbase* : EthAddress excessBlobGas* : uint64 + TxContext* = object + origin* : EthAddress + gasPrice* : GasInt + versionedHashes*: VersionedHashes + blobBaseFee* : UInt256 + BaseVMState* = ref object of RootObj com* : CommonRef + stateDB* : AccountsCache gasPool* : GasInt parent* : BlockHeader blockCtx* : BlockContext + txCtx* : TxContext flags* : set[VMFlag] + fork* : EVMFork tracer* : TracerRef receipts* : seq[Receipt] - stateDB* : AccountsCache cumulativeGasUsed*: GasInt - txOrigin* : EthAddress - txGasPrice* : GasInt - txVersionedHashes*: VersionedHashes gasCosts* : GasCosts - fork* : EVMFork asyncFactory* : AsyncOperationFactory Computation* = ref object diff --git a/nimbus/transaction/call_common.nim b/nimbus/transaction/call_common.nim index afb41dc0f..8c680109e 100644 --- a/nimbus/transaction/call_common.nim +++ b/nimbus/transaction/call_common.nim @@ -127,9 +127,12 @@ proc initialAccessListEIP2929(call: CallParams) = proc setupHost(call: CallParams): TransactionHost = let vmState = call.vmState vmState.setupTxContext( - origin = call.origin.get(call.sender), - gasPrice = call.gasPrice, - versionedHashes = call.versionedHashes, + TxContext( + origin : call.origin.get(call.sender), + gasPrice : call.gasPrice, + versionedHashes: call.versionedHashes, + blobBaseFee : getBlobGasprice(vmState.blockCtx.excessBlobGas), + ), forkOverride = call.forkOverride ) diff --git a/nimbus/transaction/evmc_host_glue.nim b/nimbus/transaction/evmc_host_glue.nim index 841e3ad14..9c402e18c 100644 --- a/nimbus/transaction/evmc_host_glue.nim +++ b/nimbus/transaction/evmc_host_glue.nim @@ -154,8 +154,8 @@ proc evmcExecComputation*(host: TransactionHost): EvmcResult host.showCallReturn(result) -# This code assumes fields, methods and types of ABI version 10, and must be +# This code assumes fields, methods and types of ABI version 11, and must be # checked for compatibility if the `import evmc/evmc` major version is updated. -when EVMC_ABI_VERSION != 10: - {.error: ("This code assumes EVMC_ABI_VERSION 10;" & +when EVMC_ABI_VERSION != 11: + {.error: ("This code assumes EVMC_ABI_VERSION 11;" & " update the code to use EVMC_ABI_VERSION " & $EVMC_ABI_VERSION).} diff --git a/nimbus/transaction/evmc_vm_glue.nim b/nimbus/transaction/evmc_vm_glue.nim index 7df2b527b..25efa9188 100644 --- a/nimbus/transaction/evmc_vm_glue.nim +++ b/nimbus/transaction/evmc_vm_glue.nim @@ -101,8 +101,8 @@ proc evmc_create_nimbus_evm(): ptr evmc_vm {.cdecl, exportc.} = GC_ref(vm) return cast[ptr evmc_vm](vm) -# This code assumes fields, methods and types of ABI version 10, and must be +# This code assumes fields, methods and types of ABI version 11, and must be # checked for compatibility if the `import evmc/evmc` major version is updated. -when EVMC_ABI_VERSION != 10: - {.error: ("This code assumes EVMC_ABI_VERSION 10;" & +when EVMC_ABI_VERSION != 11: + {.error: ("This code assumes EVMC_ABI_VERSION 11;" & " update the code to use EVMC_ABI_VERSION " & $EVMC_ABI_VERSION).} diff --git a/nimbus/transaction/host_services.nim b/nimbus/transaction/host_services.nim index 399fa9511..28c315d7d 100644 --- a/nimbus/transaction/host_services.nim +++ b/nimbus/transaction/host_services.nim @@ -50,8 +50,8 @@ proc setupTxContext(host: TransactionHost) = # values over much of the 256-bit range. let vmState = host.vmState - host.txContext.tx_gas_price = vmState.txGasPrice.u256.toEvmc - host.txContext.tx_origin = vmState.txOrigin.toEvmc + host.txContext.tx_gas_price = vmState.txCtx.gasPrice.u256.toEvmc + host.txContext.tx_origin = vmState.txCtx.origin.toEvmc # vmState.coinbase now unused host.txContext.block_coinbase = vmState.blockCtx.coinbase.toEvmc # vmState.blockNumber now unused @@ -65,20 +65,22 @@ proc setupTxContext(host: TransactionHost) = host.txContext.chain_id = vmState.com.chainId.uint.u256.toEvmc host.txContext.block_base_fee = vmState.blockCtx.fee.get(0.u256).toEvmc - if vmState.txVersionedHashes.len > 0: + if vmState.txCtx.versionedHashes.len > 0: type BlobHashPtr = typeof host.txContext.blob_hashes - host.txContext.blob_hashes = cast[BlobHashPtr](vmState.txVersionedHashes[0].addr) + host.txContext.blob_hashes = cast[BlobHashPtr](vmState.txCtx.versionedHashes[0].addr) else: host.txContext.blob_hashes = nil - host.txContext.blob_hashes_count= vmState.txVersionedHashes.len.csize_t + host.txContext.blob_hashes_count= vmState.txCtx.versionedHashes.len.csize_t + host.txContext.blob_base_fee = vmState.txCtx.blobBaseFee.toEvmc # Most host functions do `flip256` in `evmc_host_glue`, but due to this # result being cached, it's better to do `flip256` when filling the cache. host.txContext.tx_gas_price = flip256(host.txContext.tx_gas_price) host.txContext.chain_id = flip256(host.txContext.chain_id) host.txContext.block_base_fee = flip256(host.txContext.block_base_fee) + host.txContext.blob_base_fee = flip256(host.txContext.blob_base_fee) # EIP-4399 # Transfer block randomness to difficulty OPCODE diff --git a/nimbus/utils/debug.nim b/nimbus/utils/debug.nim index f4b1faf2e..10969e9a5 100644 --- a/nimbus/utils/debug.nim +++ b/nimbus/utils/debug.nim @@ -108,8 +108,10 @@ proc debug*(vms: BaseVMState): string = result.add "receipts.len : " & $vms.receipts.len & "\n" result.add "stateDB.root : " & $vms.stateDB.rootHash & "\n" result.add "cumulativeGasUsed: " & $vms.cumulativeGasUsed & "\n" - result.add "txOrigin : " & $vms.txOrigin & "\n" - result.add "txGasPrice : " & $vms.txGasPrice & "\n" + result.add "tx.origin : " & $vms.txCtx.origin & "\n" + result.add "tx.gasPrice : " & $vms.txCtx.gasPrice & "\n" + result.add "tx.blobHash.len : " & $vms.txCtx.versionedHashes.len & "\n" + result.add "tx.blobBaseFee : " & $vms.txCtx.blobBaseFee & "\n" result.add "fork : " & $vms.fork & "\n" proc `$`(x: ChainId): string = diff --git a/nimbus/vm_types.nim b/nimbus/vm_types.nim index 4e56da5b7..56658a29f 100644 --- a/nimbus/vm_types.nim +++ b/nimbus/vm_types.nim @@ -22,7 +22,8 @@ export vmt.TracerFlags, vmt.TracerRef, vmt.VMFlag, - vmt.BlockContext + vmt.BlockContext, + vmt.TxContext when defined(evmc_enabled): import diff --git a/tests/test_op_env.nim b/tests/test_op_env.nim index 634c99a5a..bb8e6239b 100644 --- a/tests/test_op_env.nim +++ b/tests/test_op_env.nim @@ -374,79 +374,85 @@ proc opEnvMain*() = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" fork: Merge - # from here onward, versionedHashes is taken from - # tx.versionedHashes = @[EMPTY_UNCLE_HASH, EMPTY_SHA3] - # preset in macro_assembler: createSignedTx - when not defined(evmc_enabled): - assembler: - title: "EIP-4844: BlobHash 1" - code: - PUSH1 "0x01" - BlobHash - STOP - stack: - "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 1" + code: + PUSH1 "0x01" + BlobHash + STOP + stack: + "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + fork: Cancun - assembler: - title: "EIP-4844: BlobHash 0" - code: - PUSH1 "0x00" - BlobHash - STOP - stack: - "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 0" + code: + PUSH1 "0x00" + BlobHash + STOP + stack: + "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + fork: Cancun - assembler: - title: "EIP-4844: BlobHash 2" - code: - PUSH1 "0x02" - BlobHash - STOP - stack: - "0x0000000000000000000000000000000000000000000000000000000000000000" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 2" + code: + PUSH1 "0x02" + BlobHash + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000000" + fork: Cancun - assembler: - title: "EIP-4844: BlobHash 32 Bit high" - code: - PUSH4 "0xffffffff" - BlobHash - STOP - stack: - "0x0000000000000000000000000000000000000000000000000000000000000000" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 32 Bit high" + code: + PUSH4 "0xffffffff" + BlobHash + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000000" + fork: Cancun - assembler: - title: "EIP-4844: BlobHash 64 Bit high" - code: - PUSH8 "0xffffffffffffffff" - BlobHash - STOP - stack: - "0x0000000000000000000000000000000000000000000000000000000000000000" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 64 Bit high" + code: + PUSH8 "0xffffffffffffffff" + BlobHash + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000000" + fork: Cancun - assembler: - title: "EIP-4844: BlobHash 128 Bit high" - code: - PUSH16 "0xffffffffffffffffffffffffffffffff" - BlobHash - STOP - stack: - "0x0000000000000000000000000000000000000000000000000000000000000000" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 128 Bit high" + code: + PUSH16 "0xffffffffffffffffffffffffffffffff" + BlobHash + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000000" + fork: Cancun - assembler: - title: "EIP-4844: BlobHash 256 Bit high" - code: - PUSH32 "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - BlobHash - STOP - stack: - "0x0000000000000000000000000000000000000000000000000000000000000000" - fork: Cancun + assembler: + title: "EIP-4844: BlobHash 256 Bit high" + code: + PUSH32 "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + BlobHash + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000000" + fork: Cancun + + assembler: + title: "EIP-7516: BlobBaseFee" + code: + BlobBaseFee + STOP + stack: + "0x0000000000000000000000000000000000000000000000000000000000000001" + gasused: 2 + fork: Cancun when isMainModule: opEnvMain() diff --git a/vendor/nim-evmc b/vendor/nim-evmc index 51bdaa5dd..42cde520d 160000 --- a/vendor/nim-evmc +++ b/vendor/nim-evmc @@ -1 +1 @@ -Subproject commit 51bdaa5ddb488f874477afa0f4bd23b5111a3806 +Subproject commit 42cde520d383c7f4613bf710144727d40e9ae4b5