aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-10-16 19:38:21 +0800
committerobscuren <geffobscura@gmail.com>2014-10-16 19:38:21 +0800
commit70f7a0be1187cc0e487e7b95cad238c6530d29ae (patch)
treef7b2787bf598db75ae6750e0d7c3fbf1fdfb4ede
parent311c6f8a3fed5ac03ee4b442fd0f420072bc41b4 (diff)
downloadgo-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.tar
go-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.tar.gz
go-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.tar.bz2
go-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.tar.lz
go-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.tar.xz
go-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.tar.zst
go-tangerine-70f7a0be1187cc0e487e7b95cad238c6530d29ae.zip
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.
-rw-r--r--ethstate/state.go25
-rw-r--r--ethstate/state_object.go4
-rw-r--r--ethvm/vm_debug.go52
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
}
}