From 70f7a0be1187cc0e487e7b95cad238c6530d29ae Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Thu, 16 Oct 2014 13:38:21 +0200
Subject: 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.AddAmount(closure.object.Balance)
+			receiver := state.GetOrNewStateObject(stack.Pop().Bytes())
 
-			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
 					}
 				}
-- 
cgit v1.2.3