From 70f7a0be1187cc0e487e7b95cad238c6530d29ae Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 16 Oct 2014 13:38:21 +0200 Subject: [PATCH] Use the state instead of the state object directly. If a state gets reset and you still hold a pointer to the previous, incorrect, state object you'll operate on the wrong object. Using the state to set/get objects and attributes you won't have this problem since the state will always have the correct object. --- ethstate/state.go | 25 +++++++++++++++++++ ethstate/state_object.go | 4 ++++ ethvm/vm_debug.go | 52 ++++++++++++++++++++++------------------ 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/ethstate/state.go b/ethstate/state.go index b897b7ce3..2efe2a311 100644 --- a/ethstate/state.go +++ b/ethstate/state.go @@ -48,6 +48,13 @@ func (self *State) GetNonce(addr []byte) uint64 { return 0 } +func (self *State) SetNonce(addr []byte, nonce uint64) { + stateObject := self.GetStateObject(addr) + if stateObject != nil { + stateObject.Nonce = nonce + } +} + func (self *State) GetCode(addr []byte) []byte { stateObject := self.GetStateObject(addr) if stateObject != nil { @@ -66,6 +73,24 @@ func (self *State) GetState(a, b []byte) []byte { return nil } +func (self *State) SetState(addr, key []byte, value interface{}) { + stateObject := self.GetStateObject(addr) + if stateObject != nil { + stateObject.SetState(key, ethutil.NewValue(value)) + } +} + +func (self *State) Delete(addr []byte) bool { + stateObject := self.GetStateObject(addr) + if stateObject != nil { + stateObject.MarkForDeletion() + + return true + } + + return false +} + // // Setting, updating & deleting state object methods // diff --git a/ethstate/state_object.go b/ethstate/state_object.go index 4d2aae1a7..a5b7c65e9 100644 --- a/ethstate/state_object.go +++ b/ethstate/state_object.go @@ -104,6 +104,10 @@ func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) { self.SetState(key.Bytes(), value) } +func (self *StateObject) Storage() map[string]*ethutil.Value { + return self.storage +} + func (self *StateObject) GetState(k []byte) *ethutil.Value { key := ethutil.LeftPadBytes(k, 32) diff --git a/ethvm/vm_debug.go b/ethvm/vm_debug.go index d3d3d7696..6d42c6b1e 100644 --- a/ethvm/vm_debug.go +++ b/ethvm/vm_debug.go @@ -48,6 +48,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { pc = big.NewInt(0) step = 0 prevStep = 0 + state = self.env.State() require = func(m int) { if stack.Len() < m { panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m)) @@ -93,7 +94,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { if self.logTy == LogTyDiff { switch op { case STOP, RETURN, SUICIDE: - closure.object.EachStorage(func(key string, value *ethutil.Value) { + state.GetStateObject(closure.Address()).EachStorage(func(key string, value *ethutil.Value) { value.Decode() fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes()) }) @@ -200,7 +201,12 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { } } + self.Printf("(pc) %-3d -o- %-14s", pc, op.String()) + self.Printf(" (g) %-3v (%v)", gas, closure.Gas) + if !closure.UseGas(gas) { + self.Endl() + err := fmt.Errorf("Insufficient gas for %v. req %v has %v", op, gas, closure.Gas) closure.UseGas(closure.Gas) @@ -208,9 +214,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { return closure.Return(nil), err } - self.Printf("(pc) %-3d -o- %-14s", pc, op.String()) - self.Printf(" (g) %-3v (%v)", gas, closure.Gas) - mem.Resize(newMemSize.Uint64()) switch op { @@ -494,7 +497,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { require(1) addr := stack.Pop().Bytes() - balance := self.env.State().GetBalance(addr) + balance := state.GetBalance(addr) stack.Push(balance) @@ -562,7 +565,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { if op == EXTCODECOPY { addr := stack.Pop().Bytes() - code = self.env.State().GetCode(addr) + code = state.GetCode(addr) } else { code = closure.Code } @@ -576,7 +579,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { if op == EXTCODECOPY { addr := stack.Pop().Bytes() - code = self.env.State().GetCode(addr) + code = state.GetCode(addr) } else { code = closure.Code } @@ -693,15 +696,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { case SLOAD: require(1) loc := stack.Pop() - val := closure.GetStorage(loc) - - stack.Push(val.BigInt()) + val := ethutil.BigD(state.GetState(closure.Address(), loc.Bytes())) + stack.Push(val) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) case SSTORE: require(2) val, loc := stack.Popn() - closure.SetStorage(loc, ethutil.NewValue(val)) + state.SetState(closure.Address(), loc.Bytes(), val) // Debug sessions are allowed to run without message if closure.message != nil { @@ -712,6 +714,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { case JUMP: require(1) pc = stack.Pop() + + if OpCode(closure.Get(pc).Uint()) != JUMPDEST { + panic(fmt.Sprintf("JUMP missed JUMPDEST %v", pc)) + } + // Reduce pc by one because of the increment that's at the end of this for loop self.Printf(" ~> %v", pc).Endl() @@ -723,7 +730,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { pc = pos if OpCode(closure.Get(pc).Uint()) != JUMPDEST { - return closure.Return(nil), fmt.Errorf("JUMP missed JUMPDEST %v", pc) + panic(fmt.Sprintf("JUMP missed JUMPDEST %v", pc)) } continue @@ -755,8 +762,9 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { ) // Generate a new address - addr := ethcrypto.CreateAddress(closure.Address(), closure.object.Nonce) - closure.object.Nonce++ + n := state.GetNonce(closure.Address()) + addr := ethcrypto.CreateAddress(closure.Address(), n) + state.SetNonce(closure.Address(), n+1) self.Printf(" (*) %x", addr).Endl() @@ -799,8 +807,6 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { // Get the arguments from the memory args := mem.Get(inOffset.Int64(), inSize.Int64()) - //snapshot := self.env.State().Copy() - var executeAddr []byte if op == CALLCODE { executeAddr = closure.Address() @@ -813,12 +819,13 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { if err != nil { stack.Push(ethutil.BigFalse) - //self.env.State().Set(snapshot) + vmlogger.Debugln(err) } else { stack.Push(ethutil.BigTrue) mem.Set(retOffset.Int64(), retSize.Int64(), ret) } + self.Printf("resume %x", closure.Address()) // Debug hook if self.Dbg != nil { @@ -836,11 +843,10 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { case SUICIDE: require(1) - receiver := self.env.State().GetOrNewStateObject(stack.Pop().Bytes()) + receiver := state.GetOrNewStateObject(stack.Pop().Bytes()) - receiver.AddAmount(closure.object.Balance) - - closure.object.MarkForDeletion() + receiver.AddAmount(state.GetBalance(closure.Address())) + state.Delete(closure.Address()) fallthrough case STOP: // Stop the closure @@ -864,11 +870,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) { if pc.Cmp(big.NewInt(instrNo)) == 0 { self.Stepping = true - if !self.Dbg.BreakHook(prevStep, op, mem, stack, closure.Object()) { + if !self.Dbg.BreakHook(prevStep, op, mem, stack, state.GetStateObject(closure.Address())) { return nil, nil } } else if self.Stepping { - if !self.Dbg.StepHook(prevStep, op, mem, stack, closure.Object()) { + if !self.Dbg.StepHook(prevStep, op, mem, stack, state.GetStateObject(closure.Address())) { return nil, nil } }