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.
This commit is contained in:
obscuren 2014-10-16 13:38:21 +02:00
parent 311c6f8a3f
commit 70f7a0be11
3 changed files with 58 additions and 23 deletions

View File

@ -48,6 +48,13 @@ func (self *State) GetNonce(addr []byte) uint64 {
return 0 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 { func (self *State) GetCode(addr []byte) []byte {
stateObject := self.GetStateObject(addr) stateObject := self.GetStateObject(addr)
if stateObject != nil { if stateObject != nil {
@ -66,6 +73,24 @@ func (self *State) GetState(a, b []byte) []byte {
return nil 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 // Setting, updating & deleting state object methods
// //

View File

@ -104,6 +104,10 @@ func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.SetState(key.Bytes(), 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 { func (self *StateObject) GetState(k []byte) *ethutil.Value {
key := ethutil.LeftPadBytes(k, 32) key := ethutil.LeftPadBytes(k, 32)

View File

@ -48,6 +48,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
pc = big.NewInt(0) pc = big.NewInt(0)
step = 0 step = 0
prevStep = 0 prevStep = 0
state = self.env.State()
require = func(m int) { require = func(m int) {
if stack.Len() < m { if stack.Len() < m {
panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, 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 { if self.logTy == LogTyDiff {
switch op { switch op {
case STOP, RETURN, SUICIDE: 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() value.Decode()
fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes()) 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) { if !closure.UseGas(gas) {
self.Endl()
err := fmt.Errorf("Insufficient gas for %v. req %v has %v", op, gas, closure.Gas) err := fmt.Errorf("Insufficient gas for %v. req %v has %v", op, gas, closure.Gas)
closure.UseGas(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 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()) mem.Resize(newMemSize.Uint64())
switch op { switch op {
@ -494,7 +497,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
require(1) require(1)
addr := stack.Pop().Bytes() addr := stack.Pop().Bytes()
balance := self.env.State().GetBalance(addr) balance := state.GetBalance(addr)
stack.Push(balance) stack.Push(balance)
@ -562,7 +565,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
if op == EXTCODECOPY { if op == EXTCODECOPY {
addr := stack.Pop().Bytes() addr := stack.Pop().Bytes()
code = self.env.State().GetCode(addr) code = state.GetCode(addr)
} else { } else {
code = closure.Code code = closure.Code
} }
@ -576,7 +579,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
if op == EXTCODECOPY { if op == EXTCODECOPY {
addr := stack.Pop().Bytes() addr := stack.Pop().Bytes()
code = self.env.State().GetCode(addr) code = state.GetCode(addr)
} else { } else {
code = closure.Code code = closure.Code
} }
@ -693,15 +696,14 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case SLOAD: case SLOAD:
require(1) require(1)
loc := stack.Pop() loc := stack.Pop()
val := closure.GetStorage(loc) val := ethutil.BigD(state.GetState(closure.Address(), loc.Bytes()))
stack.Push(val)
stack.Push(val.BigInt())
self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes()) self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
case SSTORE: case SSTORE:
require(2) require(2)
val, loc := stack.Popn() 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 // Debug sessions are allowed to run without message
if closure.message != nil { if closure.message != nil {
@ -712,6 +714,11 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case JUMP: case JUMP:
require(1) require(1)
pc = stack.Pop() 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 // Reduce pc by one because of the increment that's at the end of this for loop
self.Printf(" ~> %v", pc).Endl() self.Printf(" ~> %v", pc).Endl()
@ -723,7 +730,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
pc = pos pc = pos
if OpCode(closure.Get(pc).Uint()) != JUMPDEST { 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 continue
@ -755,8 +762,9 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
) )
// Generate a new address // Generate a new address
addr := ethcrypto.CreateAddress(closure.Address(), closure.object.Nonce) n := state.GetNonce(closure.Address())
closure.object.Nonce++ addr := ethcrypto.CreateAddress(closure.Address(), n)
state.SetNonce(closure.Address(), n+1)
self.Printf(" (*) %x", addr).Endl() 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 // Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64()) args := mem.Get(inOffset.Int64(), inSize.Int64())
//snapshot := self.env.State().Copy()
var executeAddr []byte var executeAddr []byte
if op == CALLCODE { if op == CALLCODE {
executeAddr = closure.Address() executeAddr = closure.Address()
@ -813,12 +819,13 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
if err != nil { if err != nil {
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)
//self.env.State().Set(snapshot) vmlogger.Debugln(err)
} else { } else {
stack.Push(ethutil.BigTrue) stack.Push(ethutil.BigTrue)
mem.Set(retOffset.Int64(), retSize.Int64(), ret) mem.Set(retOffset.Int64(), retSize.Int64(), ret)
} }
self.Printf("resume %x", closure.Address())
// Debug hook // Debug hook
if self.Dbg != nil { if self.Dbg != nil {
@ -836,11 +843,10 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
case SUICIDE: case SUICIDE:
require(1) require(1)
receiver := self.env.State().GetOrNewStateObject(stack.Pop().Bytes()) receiver := state.GetOrNewStateObject(stack.Pop().Bytes())
receiver.AddAmount(closure.object.Balance) receiver.AddAmount(state.GetBalance(closure.Address()))
state.Delete(closure.Address())
closure.object.MarkForDeletion()
fallthrough fallthrough
case STOP: // Stop the closure 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 { if pc.Cmp(big.NewInt(instrNo)) == 0 {
self.Stepping = true 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 return nil, nil
} }
} else if self.Stepping { } 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 return nil, nil
} }
} }