diff options
-rw-r--r-- | ethchain/state.go | 5 | ||||
-rw-r--r-- | ethchain/state_manager.go | 38 | ||||
-rw-r--r-- | ethchain/state_object.go | 52 | ||||
-rw-r--r-- | ethchain/state_transition.go | 17 | ||||
-rw-r--r-- | ethchain/transaction.go | 8 | ||||
-rw-r--r-- | ethchain/vm.go | 10 | ||||
-rw-r--r-- | ethutil/config.go | 1 | ||||
-rw-r--r-- | ethutil/value.go | 13 | ||||
-rw-r--r-- | peer.go | 2 |
9 files changed, 77 insertions, 69 deletions
diff --git a/ethchain/state.go b/ethchain/state.go index 8df79dcef..66c298b3c 100644 --- a/ethchain/state.go +++ b/ethchain/state.go @@ -145,7 +145,6 @@ func (self *State) Set(state *State) { self.trie = state.trie self.stateObjects = state.stateObjects - //*self = *state } func (s *State) Root() interface{} { @@ -212,9 +211,9 @@ func (self *State) Update() { // Debug stuff func (self *State) CreateOutputForDiff() { for addr, stateObject := range self.stateObjects { - fmt.Printf("0x%x 0x%x 0x%x 0x%x\n", addr, stateObject.state.Root(), stateObject.Amount.Bytes(), stateObject.Nonce) + fmt.Printf("%x %x %x %x\n", addr, stateObject.state.Root(), stateObject.Amount.Bytes(), stateObject.Nonce) stateObject.state.EachStorage(func(addr string, value *ethutil.Value) { - fmt.Printf("0x%x 0x%x\n", addr, value.Bytes()) + fmt.Printf("%x %x\n", addr, value.Bytes()) }) } } diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 62fcda8a5..129b30ba6 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -148,10 +148,15 @@ done: accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas)) receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative} + original := block.Receipts()[i] + if !original.Cmp(receipt) { + return nil, nil, nil, fmt.Errorf("err diff #%d (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", i+1, original.CumulativeGasUsed, original.PostState[0:4], receipt.CumulativeGasUsed, receipt.PostState[0:4], receipt.Tx.Hash()) + } + receipts = append(receipts, receipt) handled = append(handled, tx) - if ethutil.Config.Diff { + if ethutil.Config.Diff && ethutil.Config.DiffType == "all" { state.CreateOutputForDiff() } } @@ -187,36 +192,11 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) { // before that. defer state.Reset() - if ethutil.Config.Diff { - fmt.Printf("## 0x%x 0x%x ##\n", block.Hash(), block.Number) + if ethutil.Config.Diff && ethutil.Config.DiffType == "all" { + fmt.Printf("## %x %x ##\n", block.Hash(), block.Number) } - receipts, err := sm.ApplyDiff(state, parent, block) - defer func() { - if err != nil { - if len(receipts) == len(block.Receipts()) { - for i, receipt := range block.Receipts() { - statelogger.Infof("diff (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", receipt.CumulativeGasUsed, receipt.PostState[0:4], receipts[i].CumulativeGasUsed, receipts[i].PostState[0:4], receipt.Tx.Hash()) - } - } else { - statelogger.Warnln("Unable to print receipt diff. Length didn't match", len(receipts), "for", len(block.Receipts())) - } - } else { - /* - for i, receipt := range receipts { - gu := new(big.Int) - if i != 0 { - gu.Sub(receipt.CumulativeGasUsed, receipts[i-1].CumulativeGasUsed) - } else { - gu.Set(receipt.CumulativeGasUsed) - } - - statelogger.Infof("[r] %v ~ %x (%x)\n", gu, receipt.PostState[0:4], receipt.Tx.Hash()) - } - */ - } - }() - + _, err = sm.ApplyDiff(state, parent, block) if err != nil { return err } diff --git a/ethchain/state_object.go b/ethchain/state_object.go index ebc050863..5791c6ed1 100644 --- a/ethchain/state_object.go +++ b/ethchain/state_object.go @@ -15,6 +15,18 @@ func (self Code) String() string { return strings.Join(Disassemble(self), " ") } +type Storage map[string]*ethutil.Value + +func (self Storage) Copy() Storage { + cpy := make(Storage) + for key, value := range self { + // XXX Do we need a 'value' copy or is this sufficient? + cpy[key] = value + } + + return cpy +} + type StateObject struct { // Address of the object address []byte @@ -27,7 +39,7 @@ type StateObject struct { script Code initScript Code - storage map[string]*ethutil.Value + storage Storage // Total gas pool is the total amount of gas currently // left if this object is the coinbase. Gas is directly @@ -41,7 +53,8 @@ type StateObject struct { } func (self *StateObject) Reset() { - self.storage = make(map[string]*ethutil.Value) + self.storage = make(Storage) + self.state.Reset() } // Converts an transaction in to a state object @@ -66,7 +79,7 @@ func NewStateObject(addr []byte) *StateObject { object := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)} object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) - object.storage = make(map[string]*ethutil.Value) + object.storage = make(Storage) return object } @@ -95,7 +108,7 @@ func NewStateObjectFromBytes(address, data []byte) *StateObject { func (self *StateObject) MarkForDeletion() { self.remove = true - statelogger.Infof("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount) + statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount) } func (c *StateObject) GetAddr(addr []byte) *ethutil.Value { @@ -113,23 +126,24 @@ func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) { self.setStorage(key.Bytes(), value) } -func (self *StateObject) getStorage(key []byte) *ethutil.Value { - k := ethutil.LeftPadBytes(key, 32) +func (self *StateObject) getStorage(k []byte) *ethutil.Value { + key := ethutil.LeftPadBytes(k, 32) - value := self.storage[string(k)] + value := self.storage[string(key)] if value == nil { - value = self.GetAddr(k) + value = self.GetAddr(key) - self.storage[string(k)] = value + if !value.IsNil() { + self.storage[string(key)] = value + } } return value } -func (self *StateObject) setStorage(key []byte, value *ethutil.Value) { - k := ethutil.LeftPadBytes(key, 32) - - self.storage[string(k)] = value +func (self *StateObject) setStorage(k []byte, value *ethutil.Value) { + key := ethutil.LeftPadBytes(k, 32) + self.storage[string(key)] = value.Copy() } func (self *StateObject) Sync() { @@ -140,9 +154,16 @@ func (self *StateObject) Sync() { } self.SetAddr([]byte(key), value) + } + valid, t2 := ethtrie.ParanoiaCheck(self.state.trie) + if !valid { + self.state.trie = t2 + + statelogger.Infoln("Warn: PARANOIA: Different state storage root during copy") } } + func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { if int64(len(c.script)-1) < pc.Int64() { return ethutil.NewValue(0) @@ -154,13 +175,13 @@ func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { func (c *StateObject) AddAmount(amount *big.Int) { c.SetAmount(new(big.Int).Add(c.Amount, amount)) - statelogger.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount) + statelogger.DebugDetailf("%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)) - statelogger.Infof("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount) + statelogger.DebugDetailf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount) } func (c *StateObject) SetAmount(amount *big.Int) { @@ -222,6 +243,7 @@ func (self *StateObject) Copy() *StateObject { } stateObject.script = ethutil.CopyBytes(self.script) stateObject.initScript = ethutil.CopyBytes(self.initScript) + stateObject.storage = self.storage.Copy() return stateObject } diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go index 314d858f2..8cface9e8 100644 --- a/ethchain/state_transition.go +++ b/ethchain/state_transition.go @@ -2,8 +2,6 @@ package ethchain import ( "fmt" - "github.com/ethereum/eth-go/ethtrie" - "github.com/ethereum/eth-go/ethutil" "math/big" ) @@ -275,20 +273,5 @@ func (self *StateTransition) Eval(script []byte, context *StateObject, typ strin func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error) { ret, _, err = closure.Call(vm, data) - if ethutil.Config.Paranoia { - var ( - context = closure.object - trie = context.state.trie - ) - - valid, t2 := ethtrie.ParanoiaCheck(trie) - if !valid { - // TODO FIXME ASAP - context.state.trie = t2 - - statelogger.Infoln("Warn: PARANOIA: Different state object roots during copy") - } - } - return } diff --git a/ethchain/transaction.go b/ethchain/transaction.go index da3f9bcf2..5686a7edb 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -227,6 +227,14 @@ func (self *Receipt) String() string { self.CumulativeGasUsed) } +func (self *Receipt) Cmp(other *Receipt) bool { + if bytes.Compare(self.PostState, other.PostState) != 0 { + return false + } + + return true +} + // Transaction slice type for basic sorting type Transactions []*Transaction diff --git a/ethchain/vm.go b/ethchain/vm.go index f1794ff77..788bde886 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -184,7 +184,8 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) { var mult *big.Int y, x := stack.Peekn() val := closure.GetStorage(x) - if val.IsEmpty() && len(y.Bytes()) > 0 { + //if val.IsEmpty() && len(y.Bytes()) > 0 { + if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 { mult = ethutil.Big2 } else if !val.IsEmpty() && len(y.Bytes()) == 0 { mult = ethutil.Big0 @@ -482,7 +483,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) { case ORIGIN: stack.Push(ethutil.BigD(vm.vars.Origin)) - vm.Printf(" => %v", vm.vars.Origin) + vm.Printf(" => %x", vm.vars.Origin) case CALLER: caller := closure.caller.Address() stack.Push(ethutil.BigD(caller)) @@ -550,10 +551,10 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) { } code := closure.Script[cOff : cOff+l] - fmt.Println("len:", l, "code off:", cOff, "mem off:", mOff) + //fmt.Println("len:", l, "code off:", cOff, "mem off:", mOff) mem.Set(mOff, l, code) - fmt.Println(Code(mem.Get(mOff, l))) + //fmt.Println(Code(mem.Get(mOff, l))) case GASPRICE: stack.Push(closure.Price) @@ -743,6 +744,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) { if closure.object.Amount.Cmp(value) < 0 { vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount) + closure.ReturnGas(gas, nil, nil) stack.Push(ethutil.BigFalse) diff --git a/ethutil/config.go b/ethutil/config.go index 2f3d706fe..41bece21d 100644 --- a/ethutil/config.go +++ b/ethutil/config.go @@ -14,6 +14,7 @@ type ConfigManager struct { ExecPath string Debug bool Diff bool + DiffType string Paranoia bool conf *globalconf.GlobalConf diff --git a/ethutil/value.go b/ethutil/value.go index b37b33c28..ecb9d1511 100644 --- a/ethutil/value.go +++ b/ethutil/value.go @@ -190,6 +190,19 @@ func (val *Value) Get(idx int) *Value { return NewValue(nil) } +func (self *Value) Copy() *Value { + switch val := self.Val.(type) { + case *big.Int: + return NewValue(new(big.Int).Set(val)) + case []byte: + return NewValue(CopyBytes(val)) + default: + return NewValue(self.Val) + } + + return nil +} + func (val *Value) Cmp(o *Value) bool { return reflect.DeepEqual(val.Val, o.Val) } @@ -754,7 +754,7 @@ func (p *Peer) CatchupWithPeer(blockHash []byte) { if !p.catchingUp { // Make sure nobody else is catching up when you want to do this p.catchingUp = true - msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(10)}) + msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(30)}) p.QueueMessage(msg) peerlogger.DebugDetailf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr()) |