From c0c62b94b8d572a62775d7c0f3fb171e86420422 Mon Sep 17 00:00:00 2001 From: andri lim Date: Tue, 12 Nov 2019 19:49:46 +0700 Subject: [PATCH] implement EIP-2200 stub --- nimbus/vm/interpreter/gas_costs.nim | 50 +++++++++++++++++++------- nimbus/vm/interpreter/opcodes_impl.nim | 4 +++ nimbus/vm/interpreter_dispatch.nim | 1 + 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index b101d6dcf..670689d4f 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -208,20 +208,45 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) = func `prefix gasSstore`(value: Uint256, gasParams: Gasparams): GasResult {.nimcall.} = ## Value is word to save - # workaround for static evaluation not working for if expression - const - gSet = FeeSchedule[GasSset] - gSreset = FeeSchedule[GasSreset] + when fork < FkIstanbul: + # workaround for static evaluation not working for if expression + const + gSet = FeeSchedule[GasSset] + gSreset = FeeSchedule[GasSreset] - # Gas cost - literal translation of Yellow Paper - result.gasCost = if value.isZero.not and gasParams.s_isStorageEmpty: - gSet - else: - gSreset + # Gas cost - literal translation of Yellow Paper + result.gasCost = if value.isZero.not and gasParams.s_isStorageEmpty: + gSet + else: + gSreset - # Refund - if value.isZero and not gasParams.s_isStorageEmpty: - result.gasRefund = static(FeeSchedule[RefundSclear]) + # Refund + if value.isZero and not gasParams.s_isStorageEmpty: + result.gasRefund = static(FeeSchedule[RefundSclear]) + else: + # 0. If *gasleft* is less than or equal to 2300, fail the current call. + # 1. If current value equals new value (this is a no-op), SSTORE_NOOP_GAS gas is deducted. + # 2. If current value does not equal new value: + # 2.1. If original value equals current value (this storage slot has not been changed by the current execution context): + # 2.1.1. If original value is 0, SSTORE_INIT_GAS gas is deducted. + # 2.1.2. Otherwise, SSTORE_CLEAN_GAS gas is deducted. If new value is 0, add SSTORE_CLEAR_REFUND to refund counter. + # 2.2. If original value does not equal current value (this storage slot is dirty), SSTORE_DIRTY_GAS gas is deducted. Apply both of the following clauses: + # 2.2.1. If original value is not 0: + # 2.2.1.1. If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEAR_REFUND gas from refund counter. We can prove that refund counter will never go below 0. + # 2.2.1.2. If new value is 0 (also means that current value is not 0), add SSTORE_CLEAR_REFUND gas to refund counter. + # 2.2.2. If original value equals new value (this storage slot is reset): + # 2.2.2.1. If original value is 0, add SSTORE_INIT_REFUND to refund counter. + # 2.2.2.2. Otherwise, add SSTORE_CLEAN_REFUND gas to refund counter. + const + NoopGasEIP2200 = FeeSchedule[GasSload] # if the value doesn't change. + DirtyGasEIP2200 = FeeSchedule[GasSload] # if a dirty value is changed. + InitGasEIP2200 = FeeSchedule[GasSset] # from clean zero to non-zero + InitRefundEIP2200 = FeeSchedule[GasSset] - FeeSchedule[GasSload] # resetting to the original zero value + CleanGasEIP2200 = FeeSchedule[GasSreset]# from clean non-zero to something else + CleanRefundEIP2200 = FeeSchedule[GasSreset] - FeeSchedule[GasSload] # resetting to the original non-zero value + ClearRefundEIP2200 = FeeSchedule[RefundSclear]# clearing an originally existing storage slot + + # Gas sentry honoured, do the actual gas calculation based on the stored value func `prefix gasLog0`(currentMemSize, memOffset, memLength: GasNatural): GasInt {.nimcall.} = result = `prefix gasMemoryExpansion`(currentMemSize, memOffset, memLength) @@ -611,6 +636,7 @@ func istanbulGasFees(previous_fees: GasFeeSchedule): GasFeeSchedule = result[GasExtCodeHash] = 700 result[GasBalance] = 700 result[GasTXDataNonZero]= 16 + const HomesteadGasFees = BaseGasFees.homesteadGasFees TangerineGasFees = HomesteadGasFees.tangerineGasFees diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index 257551270..c3ad82616 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -930,3 +930,7 @@ op extCodeHash, inline = true: push: 0 else: push: computation.vmState.readOnlyStateDB.getCodeHash(address) + +op sstoreEIP2200, inline = false, slot, value: + checkInStaticContext(computation) + # TODO: stub diff --git a/nimbus/vm/interpreter_dispatch.nim b/nimbus/vm/interpreter_dispatch.nim index b59278349..3d3d2bece 100644 --- a/nimbus/vm/interpreter_dispatch.nim +++ b/nimbus/vm/interpreter_dispatch.nim @@ -219,6 +219,7 @@ proc genIstanbulJumpTable(ops: array[Op, NimNode]): array[Op, NimNode] {.compile result = ops result[ChainId] = newIdentNode "chainId" result[SelfBalance] = newIdentNode "selfBalance" + result[SStore] = newIdentNode "sstoreEIP2200" let IstanbulOpDispatch {.compileTime.}: array[Op, NimNode] = genIstanbulJumpTable(ConstantinopleOpDispatch)