cmd/evm, core, tests: review changes

This commit is contained in:
Jeffrey Wilcke 2016-12-05 13:27:44 +01:00
parent 36d8203678
commit bfade2679f
12 changed files with 36 additions and 62 deletions

View file

@ -226,7 +226,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// Execute the call. // Execute the call.
msg := callmsg{call} msg := callmsg{call}
evmContext := core.ToEVMContext(msg, block.Header(), b.blockchain) evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain)
// Create a new environment which holds all relevant information // Create a new environment which holds all relevant information
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEnvironment(evmContext, statedb, chainConfig, vm.Config{}) vmenv := vm.NewEnvironment(evmContext, statedb, chainConfig, vm.Config{})

View file

@ -162,6 +162,7 @@ func run(ctx *cli.Context) error {
Origin: sender.Address(), Origin: sender.Address(),
State: statedb, State: statedb,
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)), GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)),
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
Value: common.Big(ctx.GlobalString(ValueFlag.Name)), Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
EVMConfig: vm.Config{ EVMConfig: vm.Config{
Tracer: logger, Tracer: logger,
@ -175,6 +176,7 @@ func run(ctx *cli.Context) error {
Origin: sender.Address(), Origin: sender.Address(),
State: statedb, State: statedb,
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)), GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)),
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
Value: common.Big(ctx.GlobalString(ValueFlag.Name)), Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
EVMConfig: vm.Config{ EVMConfig: vm.Config{
Tracer: logger, Tracer: logger,

View file

@ -1,5 +1,4 @@
// Copyright 2014 The go-ethereum Authors // Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library. // This file is part of the go-ethereum library.
// //
// The go-ethereum library is free software: you can redistribute it and/or modify // The go-ethereum library is free software: you can redistribute it and/or modify
@ -26,13 +25,13 @@ import (
) )
// BlockFetcher retrieves headers by their hash // BlockFetcher retrieves headers by their hash
type BlockFetcher interface { type HeaderFetcher interface {
// GetHeader returns the hash corresponding to their hash // GetHeader returns the hash corresponding to their hash
GetHeader(common.Hash, uint64) *types.Header GetHeader(common.Hash, uint64) *types.Header
} }
// ToEVMContext creates a new context for use in the EVM. // NewEVMContext creates a new context for use in the EVM.
func ToEVMContext(msg Message, header *types.Header, chain BlockFetcher) vm.Context { func NewEVMContext(msg Message, header *types.Header, chain HeaderFetcher) vm.Context {
return vm.Context{ return vm.Context{
CanTransfer: CanTransfer, CanTransfer: CanTransfer,
Transfer: Transfer, Transfer: Transfer,
@ -48,10 +47,8 @@ func ToEVMContext(msg Message, header *types.Header, chain BlockFetcher) vm.Cont
} }
} }
// GetHashFn returns a function for which the VM env can query block hashes through // GetHashFn returns a GetHashFunc which retrieves header hashes by number
// up to the limit defined by the Yellow Paper and uses the given block chain func GetHashFn(ref *types.Header, chain HeaderFetcher) func(n uint64) common.Hash {
// to query for information.
func GetHashFn(ref *types.Header, chain BlockFetcher) func(n uint64) common.Hash {
return func(n uint64) common.Hash { return func(n uint64) common.Hash {
for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
if header.Number.Uint64() == n { if header.Number.Uint64() == n {
@ -64,6 +61,7 @@ func GetHashFn(ref *types.Header, chain BlockFetcher) func(n uint64) common.Hash
} }
// CanTransfer checks wether there are enough funds in the address' account to make a transfer. // CanTransfer checks wether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool { func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
return db.GetBalance(addr).Cmp(amount) >= 0 return db.GetBalance(addr).Cmp(amount) >= 0
} }

View file

@ -293,6 +293,7 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
* SETTERS * SETTERS
*/ */
// AddBalance adds amount to the account associated with addr
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
@ -300,6 +301,7 @@ func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
} }
} }
// SubBalance subtracts amount from the account associated with addr
func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {

View file

@ -97,7 +97,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, s
return nil, nil, nil, err return nil, nil, nil, err
} }
// Create a new context to be used in the EVM environment // Create a new context to be used in the EVM environment
context := ToEVMContext(msg, header, bc) context := NewEVMContext(msg, header, bc)
// Create a new environment which holds all relevant information // Create a new environment which holds all relevant information
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{})

View file

@ -74,17 +74,20 @@ type Environment struct {
} }
// NewEnvironment retutrns a new EVM environment. // NewEnvironment retutrns a new EVM environment.
func NewEnvironment(context Context, statedb StateDB, chainConfig *params.ChainConfig, vmCfg Config) *Environment { func NewEnvironment(context Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *Environment {
env := &Environment{ env := &Environment{
Context: context, Context: context,
StateDB: statedb, StateDB: statedb,
vmConfig: vmCfg, vmConfig: vmConfig,
chainConfig: chainConfig, chainConfig: chainConfig,
} }
env.evm = New(env, vmCfg) env.evm = New(env, vmConfig)
return env return env
} }
// Call executes the contract associated with the addr with the given input as paramaters. It also handles any
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
// case of an execution error or failed value transfer.
func (env *Environment) Call(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) { func (env *Environment) Call(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) {
if env.vmConfig.NoRecursion && env.Depth > 0 { if env.vmConfig.NoRecursion && env.Depth > 0 {
caller.ReturnGas(gas) caller.ReturnGas(gas)
@ -140,7 +143,11 @@ func (env *Environment) Call(caller ContractRef, addr common.Address, input []by
return ret, err return ret, err
} }
// Take another's contract code and execute within our own context // CallCode executes the contract associated with the addr with the given input as paramaters. It also handles any
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
// case of an execution error or failed value transfer.
//
// CallCode differs from Call in the sense that it executes the given address' code with the caller as context.
func (env *Environment) CallCode(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) { func (env *Environment) CallCode(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) {
if env.vmConfig.NoRecursion && env.Depth > 0 { if env.vmConfig.NoRecursion && env.Depth > 0 {
caller.ReturnGas(gas) caller.ReturnGas(gas)
@ -182,7 +189,11 @@ func (env *Environment) CallCode(caller ContractRef, addr common.Address, input
return ret, err return ret, err
} }
// Same as CallCode except sender and value is propagated from parent to child scope // DelegateCall executes the contract associated with the addr with the given input as paramaters.
// It reverses the state in case of an execution error.
//
// DelegateCall differs from CallCode in the sense that it executes the given address' code with the caller as context
// and the caller is set to the caller of the caller.
func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas *big.Int) ([]byte, error) { func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas *big.Int) ([]byte, error) {
if env.vmConfig.NoRecursion && env.Depth > 0 { if env.vmConfig.NoRecursion && env.Depth > 0 {
caller.ReturnGas(gas) caller.ReturnGas(gas)
@ -217,7 +228,7 @@ func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, in
return ret, err return ret, err
} }
// Create a new contract // Create creates a new contract using code as deployment code.
func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.Int) ([]byte, common.Address, error) { func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.Int) ([]byte, common.Address, error) {
if env.vmConfig.NoRecursion && env.Depth > 0 { if env.vmConfig.NoRecursion && env.Depth > 0 {
caller.ReturnGas(gas) caller.ReturnGas(gas)

View file

@ -515,7 +515,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
if err != nil { if err != nil {
return nil, fmt.Errorf("sender retrieval failed: %v", err) return nil, fmt.Errorf("sender retrieval failed: %v", err)
} }
context := core.ToEVMContext(msg, block.Header(), api.eth.BlockChain()) context := core.NewEVMContext(msg, block.Header(), api.eth.BlockChain())
// Mutate the state if we haven't reached the tracing transaction yet // Mutate the state if we haven't reached the tracing transaction yet
if uint64(idx) < txIndex { if uint64(idx) < txIndex {

View file

@ -112,7 +112,7 @@ func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state et
from.SetBalance(common.MaxBig) from.SetBalance(common.MaxBig)
vmError := func() error { return nil } vmError := func() error { return nil }
context := core.ToEVMContext(msg, header, b.eth.BlockChain()) context := core.NewEVMContext(msg, header, b.eth.BlockChain())
return vm.NewEnvironment(context, statedb, b.eth.chainConfig, vm.Config{}), vmError, nil return vm.NewEnvironment(context, statedb, b.eth.chainConfig, vm.Config{}), vmError, nil
} }

View file

@ -98,7 +98,7 @@ func (b *LesApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state et
from.SetBalance(common.MaxBig) from.SetBalance(common.MaxBig)
vmstate := light.NewVMState(ctx, stateDb) vmstate := light.NewVMState(ctx, stateDb)
context := core.ToEVMContext(msg, header, b.eth.blockchain) context := core.NewEVMContext(msg, header, b.eth.blockchain)
return vm.NewEnvironment(context, vmstate, b.eth.chainConfig, vm.Config{}), vmstate.Error, nil return vm.NewEnvironment(context, vmstate, b.eth.chainConfig, vm.Config{}), vmstate.Error, nil
} }

View file

@ -122,7 +122,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)}
context := core.ToEVMContext(msg, header, bc) context := core.NewEVMContext(msg, header, bc)
vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{})
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
@ -140,7 +140,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)}
context := core.ToEVMContext(msg, header, lc) context := core.NewEVMContext(msg, header, lc)
vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{}) vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{})
//vmenv := light.NewEnv(ctx, state, config, lc, msg, header, vm.Config{}) //vmenv := light.NewEnv(ctx, state, config, lc, msg, header, vm.Config{})

View file

@ -171,7 +171,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)}
context := core.ToEVMContext(msg, header, bc) context := core.NewEVMContext(msg, header, bc)
vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{})
gp := new(core.GasPool).AddGas(common.MaxBig) gp := new(core.GasPool).AddGas(common.MaxBig)
@ -187,7 +187,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
from.SetBalance(common.MaxBig) from.SetBalance(common.MaxBig)
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)}
context := core.ToEVMContext(msg, header, lc) context := core.NewEVMContext(msg, header, lc)
vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{}) vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{})
gp := new(core.GasPool).AddGas(common.MaxBig) gp := new(core.GasPool).AddGas(common.MaxBig)
ret, _, _ := core.ApplyMessage(vmenv, msg, gp) ret, _, _ := core.ApplyMessage(vmenv, msg, gp)

View file

@ -221,43 +221,4 @@ func RunState(chainConfig *params.ChainConfig, statedb *state.StateDB, env, tx m
statedb.Commit(chainConfig.IsEIP158(environment.Context.BlockNumber)) statedb.Commit(chainConfig.IsEIP158(environment.Context.BlockNumber))
return ret, statedb.Logs(), gasUsed, err return ret, statedb.Logs(), gasUsed, err
/*
var (
data = common.FromHex(tx["data"])
gas = common.Big(tx["gasLimit"])
price = common.Big(tx["gasPrice"])
value = common.Big(tx["value"])
nonce = common.Big(tx["nonce"]).Uint64()
)
var to *common.Address
if len(tx["to"]) > 2 {
t := common.HexToAddress(tx["to"])
to = &t
}
// Set pre compiled contracts
vm.Precompiled = vm.PrecompiledContracts()
gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"]))
key, _ := hex.DecodeString(tx["secretKey"])
addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey)
message := types.NewMessage(addr, to, nonce, value, gas, price, data, true)
vmenv := NewEnvFromMap(chainConfig, statedb, env, tx)
vmenv.origin = addr
root, _ := statedb.Commit(false)
statedb.Reset(root)
snapshot := statedb.Snapshot()
ret, _, err := core.ApplyMessage(vmenv, message, gaspool)
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) {
statedb.RevertToSnapshot(snapshot)
}
statedb.Commit(chainConfig.IsEIP158(vmenv.BlockNumber()))
return ret, vmenv.state.Logs(), vmenv.Gas, err
*/
} }