cleanup sstore gasCost

This commit is contained in:
jangko 2020-07-21 20:13:58 +07:00
parent 2f3a22d840
commit 6ffb33ccac
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 34 additions and 46 deletions

View File

@ -69,8 +69,6 @@ type
of Sstore: of Sstore:
when defined(evmc_enabled): when defined(evmc_enabled):
s_status*: evmc_storage_status s_status*: evmc_storage_status
else:
s_isStorageEmpty*: bool
s_currentValue*: Uint256 s_currentValue*: Uint256
s_originalValue*: Uint256 s_originalValue*: Uint256
of Call, CallCode, DelegateCall, StaticCall: of Call, CallCode, DelegateCall, StaticCall:
@ -216,54 +214,53 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
func `prefix gasSstore`(value: Uint256, gasParams: Gasparams): GasResult {.nimcall.} = func `prefix gasSstore`(value: Uint256, gasParams: Gasparams): GasResult {.nimcall.} =
## Value is word to save ## Value is word to save
const
NoopGas = FeeSchedule[GasSload] # if the value doesn't change.
DirtyGas = FeeSchedule[GasSload] # if a dirty value is changed.
InitGas = FeeSchedule[GasSset] # from clean zero to non-zero
InitRefund = FeeSchedule[GasSset] - FeeSchedule[GasSload] # resetting to the original zero value
CleanGas = FeeSchedule[GasSreset]# from clean non-zero to something else
CleanRefund = FeeSchedule[GasSreset] - FeeSchedule[GasSload] # resetting to the original non-zero value
ClearRefund = FeeSchedule[RefundsClear]# clearing an originally existing storage slot
when defined(evmc_enabled): when defined(evmc_enabled):
const const
sstoreLoad {.used.} = FeeSchedule[GasSload] sstoreDirty = when fork < FkConstantinople or fork == FkPetersburg: CleanGas
sstoreSet = FeeSchedule[GasSset] else: DirtyGas
sstoreReset= FeeSchedule[GasSreset]
sstoreDirty= when fork < FkConstantinople or fork == FkPetersburg: sstoreReset
else: sstoreLoad
InitRefundEIP2200 = FeeSchedule[GasSset] - FeeSchedule[GasSload]
CleanRefundEIP2200 = FeeSchedule[GasSreset] - FeeSchedule[GasSload]
ClearRefundEIP2200 = FeeSchedule[RefundsClear]
case gasParams.s_status case gasParams.s_status
of EVMC_STORAGE_ADDED: result.gasCost = sstoreSet of EVMC_STORAGE_ADDED: result.gasCost = InitGas
of EVMC_STORAGE_MODIFIED: result.gasCost = sstoreReset of EVMC_STORAGE_MODIFIED: result.gasCost = CleanGas
of EVMC_STORAGE_DELETED: of EVMC_STORAGE_DELETED:
result.gasCost = sstoreReset result.gasCost = CleanGas
result.gasRefund += ClearRefundEIP2200 result.gasRefund += ClearRefund
of EVMC_STORAGE_UNCHANGED: result.gasCost = sstoreDirty of EVMC_STORAGE_UNCHANGED: result.gasCost = sstoreDirty
of EVMC_STORAGE_MODIFIED_AGAIN: of EVMC_STORAGE_MODIFIED_AGAIN:
result.gasCost = sstoreDirty result.gasCost = sstoreDirty
if not gasParams.s_originalValue.isZero: if not gasParams.s_originalValue.isZero:
if gasParams.s_currentValue.isZero: if gasParams.s_currentValue.isZero:
result.gasRefund -= ClearRefundEIP2200 result.gasRefund -= ClearRefund
if value.isZero: if value.isZero:
result.gasRefund += ClearRefundEIP2200 result.gasRefund += ClearRefund
if gasParams.s_originalValue == value: if gasParams.s_originalValue == value:
if gasParams.s_originalValue.isZero: if gasParams.s_originalValue.isZero:
result.gasRefund += InitRefundEIP2200 result.gasRefund += InitRefund
else: else:
result.gasRefund += CleanRefundEIP2200 result.gasRefund += CleanRefund
else: else:
when fork < FkConstantinople or fork == FkPetersburg: when fork < FkConstantinople or fork == FkPetersburg:
# workaround for static evaluation not working for if expression let isStorageEmpty = gasParams.s_currentValue.isZero
const
gSet = FeeSchedule[GasSset]
gSreset = FeeSchedule[GasSreset]
# Gas cost - literal translation of Yellow Paper # Gas cost - literal translation of Yellow Paper
result.gasCost = if value.isZero.not and gasParams.s_isStorageEmpty: result.gasCost = if value.isZero.not and isStorageEmpty:
gSet InitGas
else: else:
gSreset CleanGas
# Refund # Refund
if value.isZero and not gasParams.s_isStorageEmpty: if value.isZero and not isStorageEmpty:
result.gasRefund = static(FeeSchedule[RefundsClear]) result.gasRefund = ClearRefund
else: else:
# 0. If *gasleft* is less than or equal to 2300, fail the current call. # 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. # 1. If current value equals new value (this is a no-op), SSTORE_NOOP_GAS gas is deducted.
@ -278,44 +275,36 @@ template gasCosts(fork: Fork, prefix, ResultGasCostsName: untyped) =
# 2.2.2. If original value equals new value (this storage slot is reset): # 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.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. # 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 # Gas sentry honoured, do the actual gas calculation based on the stored value
if gasParams.s_currentValue == value: # noop (1) if gasParams.s_currentValue == value: # noop (1)
result.gasCost = NoopGasEIP2200 result.gasCost = NoopGas
return return
if gasParams.s_originalValue == gasParams.s_currentValue: if gasParams.s_originalValue == gasParams.s_currentValue:
if gasParams.s_originalValue.isZero: # create slot (2.1.1) if gasParams.s_originalValue.isZero: # create slot (2.1.1)
result.gasCost = InitGasEIP2200 result.gasCost = InitGas
return return
if value.isZero: # delete slot (2.1.2b) if value.isZero: # delete slot (2.1.2b)
result.gasRefund = ClearRefundEIP2200 result.gasRefund = ClearRefund
result.gasCost = CleanGasEIP2200 # write existing slot (2.1.2) result.gasCost = CleanGas # write existing slot (2.1.2)
return return
if not gasParams.s_originalValue.isZero: if not gasParams.s_originalValue.isZero:
if gasParams.s_currentValue.isZero: # recreate slot (2.2.1.1) if gasParams.s_currentValue.isZero: # recreate slot (2.2.1.1)
result.gasRefund -= ClearRefundEIP2200 result.gasRefund -= ClearRefund
if value.isZero: # delete slot (2.2.1.2) if value.isZero: # delete slot (2.2.1.2)
result.gasRefund += ClearRefundEIP2200 result.gasRefund += ClearRefund
if gasParams.s_originalValue == value: if gasParams.s_originalValue == value:
if gasParams.s_originalValue.isZero: # reset to original inexistent slot (2.2.2.1) if gasParams.s_originalValue.isZero: # reset to original inexistent slot (2.2.2.1)
result.gasRefund += InitRefundEIP2200 result.gasRefund += InitRefund
else: # reset to original existing slot (2.2.2.2) else: # reset to original existing slot (2.2.2.2)
result.gasRefund += CleanRefundEIP2200 result.gasRefund += CleanRefund
result.gasCost = DirtyGasEIP2200 # dirty update (2.2) result.gasCost = DirtyGas # dirty update (2.2)
func `prefix gasLog0`(currentMemSize, memOffset, memLength: GasNatural): GasInt {.nimcall.} = func `prefix gasLog0`(currentMemSize, memOffset, memLength: GasNatural): GasInt {.nimcall.} =
result = `prefix gasMemoryExpansion`(currentMemSize, memOffset, memLength) result = `prefix gasMemoryExpansion`(currentMemSize, memOffset, memLength)

View File

@ -434,7 +434,7 @@ when not evmc_enabled:
let currentValue {.inject.} = c.getStorage(slot) let currentValue {.inject.} = c.getStorage(slot)
let let
gasParam = GasParams(kind: Op.Sstore, s_isStorageEmpty: currentValue.isZero) gasParam = GasParams(kind: Op.Sstore, s_currentValue: currentValue)
(gasCost, gasRefund) = c.gasCosts[Sstore].c_handler(newValue, gasParam) (gasCost, gasRefund) = c.gasCosts[Sstore].c_handler(newValue, gasParam)
c.gasMeter.consumeGas(gasCost, &"SSTORE: {c.msg.contractAddress}[{slot}] -> {newValue} ({currentValue})") c.gasMeter.consumeGas(gasCost, &"SSTORE: {c.msg.contractAddress}[{slot}] -> {newValue} ({currentValue})")
@ -470,7 +470,6 @@ when not evmc_enabled:
let let
gasParam = GasParams(kind: Op.Sstore, gasParam = GasParams(kind: Op.Sstore,
s_isStorageEmpty: currentValue.isZero,
s_currentValue: currentValue, s_currentValue: currentValue,
s_originalValue: stateDB.getCommittedStorage(c.msg.contractAddress, slot) s_originalValue: stateDB.getCommittedStorage(c.msg.contractAddress, slot)
) )