core, core/state, core/vm: remove exported account getters (#3618)

Removed exported statedb object accessors, reducing the chance for nasty
bugs to creep in. It's also ugly and unnecessary to have these methods.
This commit is contained in:
Jeffrey Wilcke
2017-02-22 23:29:59 +01:00
committed by Felix Lange
parent 46ec4357e7
commit 024d41d0c2
23 changed files with 245 additions and 238 deletions

View File

@ -25,11 +25,20 @@ import (
// ContractRef is a reference to the contract's backing object
type ContractRef interface {
Address() common.Address
Value() *big.Int
SetCode(common.Hash, []byte)
ForEachStorage(callback func(key, value common.Hash) bool)
}
// AccountRef implements ContractRef.
//
// Account references are used during EVM initialisation and
// it's primary use is to fetch addresses. Removing this object
// proves difficult because of the cached jump destinations which
// are fetched from the parent contract (i.e. the caller), which
// is a ContractRef.
type AccountRef common.Address
// Address casts AccountRef to a Address
func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
// Contract represents an ethereum contract in the state database. It contains
// the the contract code, calling arguments. Contract implements ContractRef
type Contract struct {
@ -69,7 +78,8 @@ func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uin
// Gas should be a pointer so it can safely be reduced through the run
// This pointer will be off the state transition
c.Gas = gas
c.value = new(big.Int).Set(value)
// ensures a value is set
c.value = value
return c
}
@ -80,7 +90,10 @@ func (c *Contract) AsDelegate() *Contract {
c.DelegateCall = true
// NOTE: caller must, at all times be a contract. It should never happen
// that caller is something other than a Contract.
c.CallerAddress = c.caller.(*Contract).CallerAddress
parent := c.caller.(*Contract)
c.CallerAddress = parent.CallerAddress
c.value = parent.value
return c
}
@ -138,9 +151,3 @@ func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code [
self.CodeHash = hash
self.CodeAddr = addr
}
// EachStorage iterates the contract's storage and calls a method for every key
// value pair.
func (self *Contract) ForEachStorage(cb func(key, value common.Hash) bool) {
self.caller.ForEachStorage(cb)
}

View File

@ -116,7 +116,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
}
var (
to Account
to = AccountRef(addr)
snapshot = evm.StateDB.Snapshot()
)
if !evm.StateDB.Exist(addr) {
@ -124,9 +124,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
return nil, gas, nil
}
to = evm.StateDB.CreateAccount(addr)
} else {
to = evm.StateDB.GetAccount(addr)
evm.StateDB.CreateAccount(addr)
}
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
@ -169,7 +167,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
var (
snapshot = evm.StateDB.Snapshot()
to = evm.StateDB.GetAccount(caller.Address())
to = AccountRef(caller.Address())
)
// initialise a new contract and set the code that is to be used by the
// E The contract is a scoped evmironment for this execution context
@ -205,11 +203,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
var (
snapshot = evm.StateDB.Snapshot()
to = evm.StateDB.GetAccount(caller.Address())
to = AccountRef(caller.Address())
)
// Iinitialise a new contract and make initialise the delegate values
contract := NewContract(caller, to, caller.Value(), gas).AsDelegate()
contract := NewContract(caller, to, nil, gas).AsDelegate()
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
ret, err = evm.interpreter.Run(contract, input)
@ -243,16 +241,16 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
snapshot := evm.StateDB.Snapshot()
contractAddr = crypto.CreateAddress(caller.Address(), nonce)
to := evm.StateDB.CreateAccount(contractAddr)
evm.StateDB.CreateAccount(contractAddr)
if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
evm.StateDB.SetNonce(contractAddr, 1)
}
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value)
// initialise a new contract and set the code that is to be used by the
// E The contract is a scoped evmironment for this execution context
// only.
contract := NewContract(caller, to, value, gas)
contract := NewContract(caller, AccountRef(contractAddr), value, gas)
contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
ret, err = evm.interpreter.Run(contract, nil)

View File

@ -25,8 +25,7 @@ import (
// StateDB is an EVM database for full state querying.
type StateDB interface {
GetAccount(common.Address) Account
CreateAccount(common.Address) Account
CreateAccount(common.Address)
SubBalance(common.Address, *big.Int)
AddBalance(common.Address, *big.Int)
@ -61,20 +60,8 @@ type StateDB interface {
AddLog(*types.Log)
AddPreimage(common.Hash, []byte)
}
// Account represents a contract or basic ethereum account.
type Account interface {
SubBalance(amount *big.Int)
AddBalance(amount *big.Int)
SetBalance(*big.Int)
SetNonce(uint64)
Balance() *big.Int
Address() common.Address
ReturnGas(*big.Int)
SetCode(common.Hash, []byte)
ForEachStorage(cb func(key, value common.Hash) bool)
Value() *big.Int
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool)
}
// CallContext provides a basic interface for the EVM calling conventions. The EVM EVM

View File

@ -144,7 +144,8 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost *b
storage = make(Storage)
// Get the contract account and loop over each storage entry. This may involve looping over
// the trie and is a very expensive process.
env.StateDB.GetAccount(contract.Address()).ForEachStorage(func(key, value common.Hash) bool {
env.StateDB.ForEachStorage(contract.Address(), func(key, value common.Hash) bool {
storage[key] = value
// Return true, indicating we'd like to continue.
return true

View File

@ -46,10 +46,6 @@ type dummyStateDB struct {
ref *dummyContractRef
}
func (d dummyStateDB) GetAccount(common.Address) Account {
return d.ref
}
func TestStoreCapture(t *testing.T) {
var (
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{EnableJit: false, ForceJit: false})

View File

@ -45,26 +45,26 @@ func (NoopEVMCallContext) DelegateCall(me ContractRef, addr common.Address, data
type NoopStateDB struct{}
func (NoopStateDB) GetAccount(common.Address) Account { return nil }
func (NoopStateDB) CreateAccount(common.Address) Account { return nil }
func (NoopStateDB) SubBalance(common.Address, *big.Int) {}
func (NoopStateDB) AddBalance(common.Address, *big.Int) {}
func (NoopStateDB) GetBalance(common.Address) *big.Int { return nil }
func (NoopStateDB) GetNonce(common.Address) uint64 { return 0 }
func (NoopStateDB) SetNonce(common.Address, uint64) {}
func (NoopStateDB) GetCodeHash(common.Address) common.Hash { return common.Hash{} }
func (NoopStateDB) GetCode(common.Address) []byte { return nil }
func (NoopStateDB) SetCode(common.Address, []byte) {}
func (NoopStateDB) GetCodeSize(common.Address) int { return 0 }
func (NoopStateDB) AddRefund(*big.Int) {}
func (NoopStateDB) GetRefund() *big.Int { return nil }
func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} }
func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {}
func (NoopStateDB) Suicide(common.Address) bool { return false }
func (NoopStateDB) HasSuicided(common.Address) bool { return false }
func (NoopStateDB) Exist(common.Address) bool { return false }
func (NoopStateDB) Empty(common.Address) bool { return false }
func (NoopStateDB) RevertToSnapshot(int) {}
func (NoopStateDB) Snapshot() int { return 0 }
func (NoopStateDB) AddLog(*types.Log) {}
func (NoopStateDB) AddPreimage(common.Hash, []byte) {}
func (NoopStateDB) CreateAccount(common.Address) {}
func (NoopStateDB) SubBalance(common.Address, *big.Int) {}
func (NoopStateDB) AddBalance(common.Address, *big.Int) {}
func (NoopStateDB) GetBalance(common.Address) *big.Int { return nil }
func (NoopStateDB) GetNonce(common.Address) uint64 { return 0 }
func (NoopStateDB) SetNonce(common.Address, uint64) {}
func (NoopStateDB) GetCodeHash(common.Address) common.Hash { return common.Hash{} }
func (NoopStateDB) GetCode(common.Address) []byte { return nil }
func (NoopStateDB) SetCode(common.Address, []byte) {}
func (NoopStateDB) GetCodeSize(common.Address) int { return 0 }
func (NoopStateDB) AddRefund(*big.Int) {}
func (NoopStateDB) GetRefund() *big.Int { return nil }
func (NoopStateDB) GetState(common.Address, common.Hash) common.Hash { return common.Hash{} }
func (NoopStateDB) SetState(common.Address, common.Hash, common.Hash) {}
func (NoopStateDB) Suicide(common.Address) bool { return false }
func (NoopStateDB) HasSuicided(common.Address) bool { return false }
func (NoopStateDB) Exist(common.Address) bool { return false }
func (NoopStateDB) Empty(common.Address) bool { return false }
func (NoopStateDB) RevertToSnapshot(int) {}
func (NoopStateDB) Snapshot() int { return 0 }
func (NoopStateDB) AddLog(*types.Log) {}
func (NoopStateDB) AddPreimage(common.Hash, []byte) {}
func (NoopStateDB) ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) {}

View File

@ -105,17 +105,17 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
cfg.State, _ = state.New(common.Hash{}, db)
}
var (
vmenv = NewEnv(cfg, cfg.State)
sender = cfg.State.CreateAccount(cfg.Origin)
receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
address = common.StringToAddress("contract")
vmenv = NewEnv(cfg, cfg.State)
sender = vm.AccountRef(cfg.Origin)
)
cfg.State.CreateAccount(address)
// set the receiver's (the executing contract) code for execution.
receiver.SetCode(crypto.Keccak256Hash(code), code)
cfg.State.SetCode(address, code)
// Call the code with the given configuration.
ret, _, err := vmenv.Call(
sender,
receiver.Address(),
common.StringToAddress("contract"),
input,
cfg.GasLimit,
cfg.Value,
@ -137,7 +137,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, error) {
}
var (
vmenv = NewEnv(cfg, cfg.State)
sender = cfg.State.CreateAccount(cfg.Origin)
sender = vm.AccountRef(cfg.Origin)
)
// Call the code with the given configuration.