Skip to content

Commit

Permalink
wrap StateDB postAP1 via hook
Browse files Browse the repository at this point in the history
  • Loading branch information
darioush committed Sep 19, 2024
1 parent 0b8529e commit 0d110a0
Show file tree
Hide file tree
Showing 10 changed files with 27 additions and 93 deletions.
20 changes: 20 additions & 0 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,34 @@ import (

"github.com/ava-labs/coreth/consensus"
"github.com/ava-labs/coreth/consensus/misc/eip4844"
"github.com/ava-labs/coreth/core/state"
"github.com/ava-labs/coreth/core/types"
"github.com/ava-labs/coreth/core/vm"
"github.com/ava-labs/coreth/params"
"github.com/ava-labs/coreth/predicate"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
)

func init() {
vm.StateDbHook = func(rules params.Rules, db vm.StateDB) vm.StateDB {
if rules.IsApricotPhase1 {
return &StateDbAP1{db}
}
return db
}
}

type StateDbAP1 struct {
vm.StateDB
}

func (s *StateDbAP1) GetCommittedState(addr common.Address, key common.Hash) common.Hash {
state.NormalizeStateKey(&key)
return s.StateDB.GetCommittedState(addr, key)
}

// ChainContext supports retrieving headers and consensus parameters from the
// current blockchain to be used during transaction processing.
type ChainContext interface {
Expand Down
10 changes: 0 additions & 10 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,16 +419,6 @@ func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) commo
return common.Hash{}
}

// GetCommittedStateAP1 retrieves a value from the given account's committed storage trie.
func (s *StateDB) GetCommittedStateAP1(addr common.Address, hash common.Hash) common.Hash {
stateObject := s.getStateObject(addr)
if stateObject != nil {
NormalizeStateKey(&hash)
return stateObject.GetCommittedState(hash)
}
return common.Hash{}
}

// Database retrieves the low level database supporting the lower level trie ops.
func (s *StateDB) Database() Database {
return s.db
Expand Down
3 changes: 3 additions & 0 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ type EVM struct {
callGasTemp uint64
}

var StateDbHook = func(_ params.Rules, x StateDB) StateDB { return x }

// NewEVM returns a new EVM. The returned EVM is not thread safe and should
// only ever be used *once*.
func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM {
Expand All @@ -220,6 +222,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time),
}
evm.StateDB = StateDbHook(evm.chainRules, evm.StateDB)
evm.interpreter = NewEVMInterpreter(evm)
return evm
}
Expand Down
55 changes: 0 additions & 55 deletions core/vm/gas_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,41 +233,6 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
return params.SloadGasEIP2200, nil // dirty update (2.2)
}

// gasSStoreAP1 simplifies the dynamic gas cost of SSTORE by removing all refund logic
//
// 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), SLOAD_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_SET_GAS (20K) gas is deducted.
// 2.1.2. Otherwise, SSTORE_RESET_GAS gas is deducted. If new value is 0, add SSTORE_CLEARS_SCHEDULE to refund counter.
// 2.2. If original value does not equal current value (this storage slot is dirty), SLOAD_GAS gas is deducted. Apply both of the following clauses:
func gasSStoreAP1(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// If we fail the minimum gas availability invariant, fail (0)
if contract.Gas <= params.SstoreSentryGasEIP2200 {
return 0, errors.New("not enough gas for reentrancy sentry")
}
// Gas sentry honoured, do the actual gas calculation based on the stored value
var (
y, x = stack.Back(1), stack.Back(0)
current = evm.StateDB.GetState(contract.Address(), x.Bytes32())
)
value := common.Hash(y.Bytes32())

if current == value { // noop (1)
return params.SloadGasEIP2200, nil
}
original := evm.StateDB.GetCommittedStateAP1(contract.Address(), x.Bytes32())
if original == current {
if original == (common.Hash{}) { // create slot (2.1.1)
return params.SstoreSetGasEIP2200, nil
}
return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2)
}

return params.SloadGasEIP2200, nil // dirty update (2.2)
}

func makeGasLog(n uint64) gasFunc {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
requestedSize, overflow := stack.Back(1).Uint64WithOverflow()
Expand Down Expand Up @@ -523,23 +488,3 @@ func gasSelfdestruct(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
}
return gas, nil
}

func gasSelfdestructAP1(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var gas uint64
// EIP150 homestead gas reprice fork:
if evm.chainRules.IsEIP150 {
gas = params.SelfdestructGasEIP150
var address = common.Address(stack.Back(0).Bytes20())

if evm.chainRules.IsEIP158 {
// if empty and transfers value
if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 {
gas += params.CreateBySelfdestructGas
}
} else if !evm.StateDB.Exist(address) {
gas += params.CreateBySelfdestructGas
}
}

return gas, nil
}
1 change: 0 additions & 1 deletion core/vm/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ type StateDB interface {
GetRefund() uint64

GetCommittedState(common.Address, common.Hash) common.Hash
GetCommittedStateAP1(common.Address, common.Hash) common.Hash
GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash)

Expand Down
2 changes: 1 addition & 1 deletion core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
case evm.chainRules.IsApricotPhase2:
table = &apricotPhase2InstructionSet
case evm.chainRules.IsApricotPhase1:
table = &apricotPhase1InstructionSet
table = &istanbulInstructionSet
case evm.chainRules.IsIstanbul:
table = &istanbulInstructionSet
case evm.chainRules.IsConstantinople:
Expand Down
3 changes: 1 addition & 2 deletions core/vm/jump_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ var (
byzantiumInstructionSet = newByzantiumInstructionSet()
constantinopleInstructionSet = newConstantinopleInstructionSet()
istanbulInstructionSet = newIstanbulInstructionSet()
apricotPhase1InstructionSet = newApricotPhase1InstructionSet()
apricotPhase2InstructionSet = newBerlinInstructionSet()
apricotPhase3InstructionSet = newLondonInstructionSet()
durangoInstructionSet = newShanghaiInstructionSet()
Expand Down Expand Up @@ -131,7 +130,7 @@ func newLondonInstructionSet() JumpTable {
// constantinople, istanbul, petersburg and berlin instructions.
// Additionally, it enable AP1.
func newBerlinInstructionSet() JumpTable {
instructionSet := newApricotPhase1InstructionSet()
instructionSet := newIstanbulInstructionSet()
enable2929(&instructionSet) // Gas cost increases for state access opcodes https://eips.ethereum.org/EIPS/eip-2929
return validate(instructionSet)
}
Expand Down
4 changes: 1 addition & 3 deletions core/vm/jump_table_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
return newLondonInstructionSet(), nil
case rules.IsApricotPhase2:
return newBerlinInstructionSet(), nil
case rules.IsApricotPhase1:
return newApricotPhase1InstructionSet(), nil
case rules.IsIstanbul:
case rules.IsApricotPhase1, rules.IsIstanbul:
return newIstanbulInstructionSet(), nil
case rules.IsConstantinople:
return newConstantinopleInstructionSet(), nil
Expand Down
20 changes: 0 additions & 20 deletions core/vm/jump_table_ext.go

This file was deleted.

2 changes: 1 addition & 1 deletion core/vm/operations_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func makeGasSStoreFunc() gasFunc {
// return params.SloadGasEIP2200, nil
return cost + params.WarmStorageReadCostEIP2929, nil // SLOAD_GAS
}
original := evm.StateDB.GetCommittedStateAP1(contract.Address(), x.Bytes32())
original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32())
if original == current {
if original == (common.Hash{}) { // create slot (2.1.1)
return cost + params.SstoreSetGasEIP2200, nil
Expand Down

0 comments on commit 0d110a0

Please sign in to comment.