Auto update state changes notifications
This commit is contained in:
		@@ -11,7 +11,7 @@ type ClosureRef interface {
 | 
				
			|||||||
	ReturnGas(*big.Int, *big.Int, *State)
 | 
						ReturnGas(*big.Int, *big.Int, *State)
 | 
				
			||||||
	Address() []byte
 | 
						Address() []byte
 | 
				
			||||||
	GetMem(*big.Int) *ethutil.Value
 | 
						GetMem(*big.Int) *ethutil.Value
 | 
				
			||||||
	SetMem(*big.Int, *ethutil.Value)
 | 
						SetStore(*big.Int, *ethutil.Value)
 | 
				
			||||||
	N() *big.Int
 | 
						N() *big.Int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,8 +64,8 @@ func (c *Closure) Gets(x, y *big.Int) *ethutil.Value {
 | 
				
			|||||||
	return ethutil.NewValue(partial)
 | 
						return ethutil.NewValue(partial)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) {
 | 
					func (c *Closure) SetStorage(x *big.Int, val *ethutil.Value) {
 | 
				
			||||||
	c.object.SetMem(x, val)
 | 
						c.object.SetStorage(x, val)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Closure) Address() []byte {
 | 
					func (c *Closure) Address() []byte {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,11 +15,13 @@ type State struct {
 | 
				
			|||||||
	trie *ethutil.Trie
 | 
						trie *ethutil.Trie
 | 
				
			||||||
	// Nested states
 | 
						// Nested states
 | 
				
			||||||
	states map[string]*State
 | 
						states map[string]*State
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manifest *Manifest
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create a new state from a given trie
 | 
					// Create a new state from a given trie
 | 
				
			||||||
func NewState(trie *ethutil.Trie) *State {
 | 
					func NewState(trie *ethutil.Trie) *State {
 | 
				
			||||||
	return &State{trie: trie, states: make(map[string]*State)}
 | 
						return &State{trie: trie, states: make(map[string]*State), manifest: NewManifest()}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Resets the trie and all siblings
 | 
					// Resets the trie and all siblings
 | 
				
			||||||
@@ -124,36 +126,6 @@ const (
 | 
				
			|||||||
	UnknownTy
 | 
						UnknownTy
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
// Returns the object stored at key and the type stored at key
 | 
					 | 
				
			||||||
// Returns nil if nothing is stored
 | 
					 | 
				
			||||||
func (s *State) GetStateObject(key []byte) (*ethutil.Value, ObjType) {
 | 
					 | 
				
			||||||
	// Fetch data from the trie
 | 
					 | 
				
			||||||
	data := s.trie.Get(string(key))
 | 
					 | 
				
			||||||
	// Returns the nil type, indicating nothing could be retrieved.
 | 
					 | 
				
			||||||
	// Anything using this function should check for this ret val
 | 
					 | 
				
			||||||
	if data == "" {
 | 
					 | 
				
			||||||
		return nil, NilTy
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var typ ObjType
 | 
					 | 
				
			||||||
	val := ethutil.NewValueFromBytes([]byte(data))
 | 
					 | 
				
			||||||
	// Check the length of the retrieved value.
 | 
					 | 
				
			||||||
	// Len 2 = Account
 | 
					 | 
				
			||||||
	// Len 3 = Contract
 | 
					 | 
				
			||||||
	// Other = invalid for now. If other types emerge, add them here
 | 
					 | 
				
			||||||
	if val.Len() == 2 {
 | 
					 | 
				
			||||||
		typ = AccountTy
 | 
					 | 
				
			||||||
	} else if val.Len() == 3 {
 | 
					 | 
				
			||||||
		typ = ContractTy
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		typ = UnknownTy
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return val, typ
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Updates any given state object
 | 
					// Updates any given state object
 | 
				
			||||||
func (s *State) UpdateStateObject(object *StateObject) {
 | 
					func (s *State) UpdateStateObject(object *StateObject) {
 | 
				
			||||||
	addr := object.Address()
 | 
						addr := object.Address()
 | 
				
			||||||
@@ -163,6 +135,7 @@ func (s *State) UpdateStateObject(object *StateObject) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s.trie.Update(string(addr), string(object.RlpEncode()))
 | 
						s.trie.Update(string(addr), string(object.RlpEncode()))
 | 
				
			||||||
 | 
						s.manifest.AddObjectChange(object)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *State) Put(key, object []byte) {
 | 
					func (s *State) Put(key, object []byte) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,9 @@ type StateManager struct {
 | 
				
			|||||||
	// the main states.
 | 
						// the main states.
 | 
				
			||||||
	transState *State
 | 
						transState *State
 | 
				
			||||||
	// Manifest for keeping changes regarding state objects. See `notify`
 | 
						// Manifest for keeping changes regarding state objects. See `notify`
 | 
				
			||||||
	manifest *Manifest
 | 
						// XXX Should we move the manifest to the State object. Benefit:
 | 
				
			||||||
 | 
						// * All states can keep their own local changes
 | 
				
			||||||
 | 
						//manifest *Manifest
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewStateManager(ethereum EthManager) *StateManager {
 | 
					func NewStateManager(ethereum EthManager) *StateManager {
 | 
				
			||||||
@@ -57,7 +59,7 @@ func NewStateManager(ethereum EthManager) *StateManager {
 | 
				
			|||||||
		Pow:      &EasyPow{},
 | 
							Pow:      &EasyPow{},
 | 
				
			||||||
		Ethereum: ethereum,
 | 
							Ethereum: ethereum,
 | 
				
			||||||
		bc:       ethereum.BlockChain(),
 | 
							bc:       ethereum.BlockChain(),
 | 
				
			||||||
		manifest: NewManifest(),
 | 
							//manifest: NewManifest(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sm.procState = ethereum.BlockChain().CurrentBlock.State()
 | 
						sm.procState = ethereum.BlockChain().CurrentBlock.State()
 | 
				
			||||||
	sm.transState = sm.procState.Copy()
 | 
						sm.transState = sm.procState.Copy()
 | 
				
			||||||
@@ -190,7 +192,7 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			sm.notifyChanges()
 | 
								sm.notifyChanges()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sm.manifest.Reset()
 | 
								sm.procState.manifest.Reset()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		fmt.Println("total diff failed")
 | 
							fmt.Println("total diff failed")
 | 
				
			||||||
@@ -315,18 +317,15 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Update the account (refunds)
 | 
						// Update the account (refunds)
 | 
				
			||||||
	sm.procState.UpdateStateObject(account)
 | 
						sm.procState.UpdateStateObject(account)
 | 
				
			||||||
	sm.manifest.AddObjectChange(account)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sm.procState.UpdateStateObject(object)
 | 
						sm.procState.UpdateStateObject(object)
 | 
				
			||||||
	sm.manifest.AddObjectChange(object)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (sm *StateManager) notifyChanges() {
 | 
					func (sm *StateManager) notifyChanges() {
 | 
				
			||||||
	for addr, stateObject := range sm.manifest.objectChanges {
 | 
						for addr, stateObject := range sm.procState.manifest.objectChanges {
 | 
				
			||||||
		sm.Ethereum.Reactor().Post("object:"+addr, stateObject)
 | 
							sm.Ethereum.Reactor().Post("object:"+addr, stateObject)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for stateObjectAddr, mappedObjects := range sm.manifest.storageChanges {
 | 
						for stateObjectAddr, mappedObjects := range sm.procState.manifest.storageChanges {
 | 
				
			||||||
		for addr, value := range mappedObjects {
 | 
							for addr, value := range mappedObjects {
 | 
				
			||||||
			sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &StorageState{[]byte(stateObjectAddr), []byte(addr), value})
 | 
								sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &StorageState{[]byte(stateObjectAddr), []byte(addr), value})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,7 @@ func (c *StateObject) SetAddr(addr []byte, value interface{}) {
 | 
				
			|||||||
	c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
 | 
						c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *StateObject) SetMem(num *big.Int, val *ethutil.Value) {
 | 
					func (c *StateObject) SetStorage(num *big.Int, val *ethutil.Value) {
 | 
				
			||||||
	addr := ethutil.BigToBytes(num, 256)
 | 
						addr := ethutil.BigToBytes(num, 256)
 | 
				
			||||||
	c.SetAddr(addr, val)
 | 
						c.SetAddr(addr, val)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -395,10 +395,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
 | 
				
			|||||||
		case oSSTORE:
 | 
							case oSSTORE:
 | 
				
			||||||
			require(2)
 | 
								require(2)
 | 
				
			||||||
			val, loc := stack.Popn()
 | 
								val, loc := stack.Popn()
 | 
				
			||||||
			closure.SetMem(loc, ethutil.NewValue(val))
 | 
								closure.SetStorage(loc, ethutil.NewValue(val))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Add the change to manifest
 | 
								// Add the change to manifest
 | 
				
			||||||
			vm.stateManager.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val)
 | 
								vm.state.manifest.AddStorageChange(closure.Object(), loc.Bytes(), val)
 | 
				
			||||||
		case oJUMP:
 | 
							case oJUMP:
 | 
				
			||||||
			require(1)
 | 
								require(1)
 | 
				
			||||||
			pc = stack.Pop()
 | 
								pc = stack.Pop()
 | 
				
			||||||
@@ -473,7 +473,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			// Fetch the contract which will serve as the closure body
 | 
								// Fetch the contract which will serve as the closure body
 | 
				
			||||||
			contract := vm.state.GetContract(addr.Bytes())
 | 
								contract := vm.state.GetContract(addr.Bytes())
 | 
				
			||||||
			fmt.Println("before", contract.Amount)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if contract != nil {
 | 
								if contract != nil {
 | 
				
			||||||
				// Prepay for the gas
 | 
									// Prepay for the gas
 | 
				
			||||||
@@ -497,12 +496,9 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
 | 
				
			|||||||
					//contract.State().Reset()
 | 
										//contract.State().Reset()
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					stack.Push(ethutil.BigTrue)
 | 
										stack.Push(ethutil.BigTrue)
 | 
				
			||||||
					// Notify of the changes
 | 
					 | 
				
			||||||
					vm.stateManager.manifest.AddObjectChange(contract)
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				vm.state.SetStateObject(contract)
 | 
									vm.state.SetStateObject(contract)
 | 
				
			||||||
				fmt.Println("after", contract.Amount)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				mem.Set(retOffset.Int64(), retSize.Int64(), ret)
 | 
									mem.Set(retOffset.Int64(), retSize.Int64(), ret)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
@@ -520,8 +516,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			receiver := vm.state.GetAccount(stack.Pop().Bytes())
 | 
								receiver := vm.state.GetAccount(stack.Pop().Bytes())
 | 
				
			||||||
			receiver.AddAmount(closure.object.Amount)
 | 
								receiver.AddAmount(closure.object.Amount)
 | 
				
			||||||
 | 
								vm.state.SetStateObject(receiver)
 | 
				
			||||||
			vm.stateManager.manifest.AddObjectChange(receiver)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			closure.object.state.Purge()
 | 
								closure.object.state.Purge()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user