Removal of manual updating of state objects

* You'll only ever need to update the state by calling Update. Update
  will take care of the updating of it's child state objects.
poc8
obscuren 11 years ago
parent 6656f99c54
commit 53e30f750d
  1. 27
      ethchain/state.go
  2. 4
      ethchain/state_manager.go
  3. 26
      ethchain/state_object.go
  4. 26
      ethchain/state_transition.go
  5. 19
      ethchain/vm.go
  6. 2
      ethminer/miner.go

@ -38,12 +38,16 @@ func (s *State) Reset() {
stateObject.state.Reset()
}
s.Empty()
}
// Syncs the trie and all siblings
func (s *State) Sync() {
// Sync all nested states
for _, stateObject := range s.stateObjects {
s.UpdateStateObject(stateObject)
if stateObject.state == nil {
continue
}
@ -52,6 +56,18 @@ func (s *State) Sync() {
}
s.trie.Sync()
s.Empty()
}
func (self *State) Empty() {
self.stateObjects = make(map[string]*StateObject)
}
func (self *State) Update() {
for _, stateObject := range self.stateObjects {
self.UpdateStateObject(stateObject)
}
}
// Purges the current trie.
@ -68,6 +84,7 @@ func (self *State) UpdateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
if self.stateObjects[string(addr)] == nil {
panic("?")
self.stateObjects[string(addr)] = stateObject
}
@ -98,13 +115,19 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
stateObject := self.GetStateObject(addr)
if stateObject == nil {
stateObject = NewStateObject(addr)
self.stateObjects[string(addr)] = stateObject
stateObject = self.NewStateObject(addr)
}
return stateObject
}
func (self *State) NewStateObject(addr []byte) *StateObject {
stateObject := NewStateObject(addr)
self.stateObjects[string(addr)] = stateObject
return stateObject
}
func (self *State) GetAccount(addr []byte) *StateObject {
return self.GetOrNewStateObject(addr)
}

@ -181,7 +181,6 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
coinbase.SetGasPool(block.CalcGasLimit(parent))
// Process the transactions on to current block
//sm.ApplyTransactions(block.Coinbase, state, parent, block.Transactions())
sm.ProcessTransactions(coinbase, state, block, parent, block.Transactions())
// Block validation
@ -197,6 +196,9 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
return err
}
// Update the state with pending changes
state.Update()
if !block.State().Cmp(state) {
return fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().trie.Root, state.trie.Root)
}

@ -4,8 +4,15 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethutil"
"math/big"
"strings"
)
type Code []byte
func (self Code) String() string {
return strings.Join(Disassemble(self), " ")
}
type StateObject struct {
// Address of the object
address []byte
@ -15,8 +22,8 @@ type StateObject struct {
Nonce uint64
// Contract related attributes
state *State
script []byte
initScript []byte
script Code
initScript Code
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
@ -30,12 +37,9 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
if tx.IsContract() {
addr := tx.CreationAddress()
value := tx.Value
contract := NewContract(addr, value, ZeroHash256)
contract := state.NewStateObject(addr)
contract.initScript = tx.Data
state.UpdateStateObject(contract)
contract.state = NewState(ethutil.NewTrie(ethutil.Config.Db, ""))
return contract
}
@ -120,13 +124,13 @@ func (c *StateObject) ReturnGas(gas, price *big.Int, state *State) {
func (c *StateObject) AddAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Add(c.Amount, amount))
ethutil.Config.Log.Printf(ethutil.LogLevelSystem, "%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
ethutil.Config.Log.Printf(ethutil.LogLevelInfo, "%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
}
func (c *StateObject) SubAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Sub(c.Amount, amount))
ethutil.Config.Log.Printf(ethutil.LogLevelSystem, "%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
ethutil.Config.Log.Printf(ethutil.LogLevelInfo, "%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
}
func (c *StateObject) SetAmount(amount *big.Int) {
@ -197,12 +201,12 @@ func (c *StateObject) Address() []byte {
}
// Returns the main script body
func (c *StateObject) Script() []byte {
func (c *StateObject) Script() Code {
return c.script
}
// Returns the initialization script
func (c *StateObject) Init() []byte {
func (c *StateObject) Init() Code {
return c.initScript
}

@ -67,13 +67,8 @@ func (self *StateTransition) Receiver() *StateObject {
func (self *StateTransition) MakeStateObject(state *State, tx *Transaction) *StateObject {
contract := MakeContract(tx, state)
if contract != nil {
state.states[string(tx.CreationAddress())] = contract.state
return contract
}
return nil
return contract
}
func (self *StateTransition) UseGas(amount *big.Int) error {
@ -137,6 +132,8 @@ func (self *StateTransition) TransitionState() (err error) {
receiver *StateObject
)
ethutil.Config.Log.Printf(ethutil.LogLevelInfo, "(~) %x\n", tx.Hash())
// Make sure this transaction's nonce is correct
if sender.Nonce != tx.Nonce {
return NonceError(tx.Nonce, sender.Nonce)
@ -152,15 +149,17 @@ func (self *StateTransition) TransitionState() (err error) {
defer func() {
self.RefundGas()
if sender != nil {
self.state.UpdateStateObject(sender)
}
/*
if sender != nil {
self.state.UpdateStateObject(sender)
}
if receiver != nil {
self.state.UpdateStateObject(receiver)
}
if receiver != nil {
self.state.UpdateStateObject(receiver)
}
self.state.UpdateStateObject(self.Coinbase())
self.state.UpdateStateObject(self.Coinbase())
*/
}()
// Increment the nonce for the next transaction
@ -209,6 +208,7 @@ func (self *StateTransition) TransitionState() (err error) {
receiver.script = code
} else {
if len(receiver.Script()) > 0 {
fmt.Println(receiver.Script())
_, err := self.Eval(receiver.Script(), receiver)
if err != nil {
return fmt.Errorf("Error during code execution %v", err)

@ -95,9 +95,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
step := 0
prevStep := 0
if ethutil.Config.Debug {
ethutil.Config.Log.Debugf("# op\n")
}
ethutil.Config.Log.Debugf("# op\n")
for {
prevStep = step
@ -109,9 +107,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
val := closure.Get(pc)
// Get the opcode (it must be an opcode!)
op := OpCode(val.Uint())
if ethutil.Config.Debug {
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
}
ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String())
gas := new(big.Int)
addStepGasUsage := func(amount *big.Int) {
@ -525,8 +522,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
vm.state.Revert(snapshot)
} else {
stack.Push(ethutil.BigD(addr))
vm.state.UpdateStateObject(contract)
}
case CALL:
// TODO RE-WRITE
@ -569,8 +564,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
} else {
stack.Push(ethutil.BigTrue)
vm.state.UpdateStateObject(contract)
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
}
} else {
@ -589,9 +582,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
receiver := vm.state.GetAccount(stack.Pop().Bytes())
receiver.AddAmount(closure.object.Amount)
vm.state.UpdateStateObject(receiver)
closure.object.state.Purge()
trie := closure.object.state.trie
trie.NewIterator().Each(func(key string, v *ethutil.Value) {
trie.Delete(key)
})
fallthrough
case STOP: // Stop the closure

@ -154,6 +154,8 @@ func (self *Miner) mineNewBlock() {
// Accumulate the rewards included for this block
stateManager.AccumelateRewards(self.block.State(), self.block)
self.block.State().Update()
ethutil.Config.Log.Infoln("[MINER] Mining on block. Includes", len(self.txs), "transactions")
// Find a valid nonce

Loading…
Cancel
Save