forked from cerc-io/plugeth
Auto update state changes notifications
This commit is contained in:
parent
e8fb965ccb
commit
5a0bae1dae
@ -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()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user