diff options
Diffstat (limited to 'light')
-rw-r--r-- | light/odr_test.go | 13 | ||||
-rw-r--r-- | light/state.go | 9 | ||||
-rw-r--r-- | light/state_object.go | 2 | ||||
-rw-r--r-- | light/vm_env.go | 119 |
4 files changed, 40 insertions, 103 deletions
diff --git a/light/odr_test.go b/light/odr_test.go index 50255a7f3..2f60f32fd 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -157,6 +157,8 @@ func (callmsg) CheckNonce() bool { return false } func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc *LightChain, bhash common.Hash) []byte { data := common.Hex2Bytes("60CD26850000000000000000000000000000000000000000000000000000000000000000") + config := params.TestChainConfig + var res []byte for i := 0; i < 3; i++ { data[35] = byte(i) @@ -168,7 +170,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain from.SetBalance(common.MaxBig) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} - vmenv := core.NewEnv(statedb, testChainConfig(), bc, msg, header, vm.Config{}) + + context := core.NewEVMContext(msg, header, bc) + vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) + gp := new(core.GasPool).AddGas(common.MaxBig) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, ret...) @@ -176,15 +181,17 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain } else { header := lc.GetHeaderByHash(bhash) state := NewLightState(StateTrieID(header), lc.Odr()) + vmstate := NewVMState(ctx, state) from, err := state.GetOrNewStateObject(ctx, testBankAddress) if err == nil { from.SetBalance(common.MaxBig) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} - vmenv := NewEnv(ctx, state, testChainConfig(), lc, msg, header, vm.Config{}) + context := core.NewEVMContext(msg, header, lc) + vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{}) gp := new(core.GasPool).AddGas(common.MaxBig) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) - if vmenv.Error() == nil { + if vmstate.Error() == nil { res = append(res, ret...) } } diff --git a/light/state.go b/light/state.go index 9f2376809..f8b75c588 100644 --- a/light/state.go +++ b/light/state.go @@ -141,6 +141,15 @@ func (self *LightState) AddBalance(ctx context.Context, addr common.Address, amo return err } +// SubBalance adds the given amount to the balance of the specified account +func (self *LightState) SubBalance(ctx context.Context, addr common.Address, amount *big.Int) error { + stateObject, err := self.GetOrNewStateObject(ctx, addr) + if err == nil && stateObject != nil { + stateObject.SubBalance(amount) + } + return err +} + // SetNonce sets the nonce of the specified account func (self *LightState) SetNonce(ctx context.Context, addr common.Address, nonce uint64) error { stateObject, err := self.GetOrNewStateObject(ctx, addr) diff --git a/light/state_object.go b/light/state_object.go index 6161d2dfb..56f607bff 100644 --- a/light/state_object.go +++ b/light/state_object.go @@ -179,7 +179,7 @@ func (c *StateObject) SetBalance(amount *big.Int) { } // ReturnGas returns the gas back to the origin. Used by the Virtual machine or Closures -func (c *StateObject) ReturnGas(gas, price *big.Int) {} +func (c *StateObject) ReturnGas(gas *big.Int) {} // Copy creates a copy of the state object func (self *StateObject) Copy() *StateObject { diff --git a/light/vm_env.go b/light/vm_env.go index d4d7bcce7..cc0c568c9 100644 --- a/light/vm_env.go +++ b/light/vm_env.go @@ -20,123 +20,38 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" "golang.org/x/net/context" ) -// VMEnv is the light client version of the vm execution environment. -// Unlike other structures, VMEnv holds a context that is applied by state -// retrieval requests through the entire execution. If any state operation -// returns an error, the execution fails. -type VMEnv struct { - vm.Environment - ctx context.Context - chainConfig *params.ChainConfig - evm *vm.EVM - state *VMState - header *types.Header - msg core.Message - depth int - chain *LightChain - err error -} - -// NewEnv creates a new execution environment based on an ODR capable light state -func NewEnv(ctx context.Context, state *LightState, chainConfig *params.ChainConfig, chain *LightChain, msg core.Message, header *types.Header, cfg vm.Config) *VMEnv { - env := &VMEnv{ - chainConfig: chainConfig, - chain: chain, - header: header, - msg: msg, - } - env.state = &VMState{ctx: ctx, state: state, env: env} - - env.evm = vm.New(env, cfg) - return env -} - -func (self *VMEnv) ChainConfig() *params.ChainConfig { return self.chainConfig } -func (self *VMEnv) Vm() vm.Vm { return self.evm } -func (self *VMEnv) Origin() common.Address { return self.msg.From() } -func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number } -func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase } -func (self *VMEnv) Time() *big.Int { return self.header.Time } -func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty } -func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit } -func (self *VMEnv) Db() vm.Database { return self.state } -func (self *VMEnv) Depth() int { return self.depth } -func (self *VMEnv) SetDepth(i int) { self.depth = i } -func (self *VMEnv) GetHash(n uint64) common.Hash { - for header := self.chain.GetHeader(self.header.ParentHash, self.header.Number.Uint64()-1); header != nil; header = self.chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { - if header.Number.Uint64() == n { - return header.Hash() - } - } - - return common.Hash{} -} - -func (self *VMEnv) AddLog(log *vm.Log) { - //self.state.AddLog(log) -} -func (self *VMEnv) CanTransfer(from common.Address, balance *big.Int) bool { - return self.state.GetBalance(from).Cmp(balance) >= 0 -} - -func (self *VMEnv) SnapshotDatabase() int { - return self.state.SnapshotDatabase() -} - -func (self *VMEnv) RevertToSnapshot(idx int) { - self.state.RevertToSnapshot(idx) -} - -func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) { - core.Transfer(from, to, amount) -} - -func (self *VMEnv) Call(me vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - return core.Call(self, me, addr, data, gas, price, value) -} -func (self *VMEnv) CallCode(me vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - return core.CallCode(self, me, addr, data, gas, price, value) -} - -func (self *VMEnv) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) { - return core.DelegateCall(self, me, addr, data, gas, price) -} - -func (self *VMEnv) Create(me vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) { - return core.Create(self, me, data, gas, price, value) -} - -// Error returns the error (if any) that happened during execution. -func (self *VMEnv) Error() error { - return self.err -} - // VMState is a wrapper for the light state that holds the actual context and // passes it to any state operation that requires it. type VMState struct { - vm.Database ctx context.Context state *LightState snapshots []*LightState - env *VMEnv + err error +} + +func NewVMState(ctx context.Context, state *LightState) *VMState { + return &VMState{ctx: ctx, state: state} +} + +func (s *VMState) Error() error { + return s.err } +func (s *VMState) AddLog(log *vm.Log) {} + // errHandler handles and stores any state error that happens during execution. func (s *VMState) errHandler(err error) { - if err != nil && s.env.err == nil { - s.env.err = err + if err != nil && s.err == nil { + s.err = err } } -func (self *VMState) SnapshotDatabase() int { +func (self *VMState) Snapshot() int { self.snapshots = append(self.snapshots, self.state.Copy()) return len(self.snapshots) - 1 } @@ -175,6 +90,12 @@ func (s *VMState) AddBalance(addr common.Address, amount *big.Int) { s.errHandler(err) } +// SubBalance adds the given amount to the balance of the specified account +func (s *VMState) SubBalance(addr common.Address, amount *big.Int) { + err := s.state.SubBalance(s.ctx, addr, amount) + s.errHandler(err) +} + // GetBalance retrieves the balance from the given address or 0 if the account does // not exist func (s *VMState) GetBalance(addr common.Address) *big.Int { |