diff --git a/ethchain/state.go b/ethchain/state.go index 5d023df7b..6abf21c39 100644 --- a/ethchain/state.go +++ b/ethchain/state.go @@ -67,11 +67,19 @@ func (self *State) Empty() { func (self *State) Update() { for _, stateObject := range self.stateObjects { if stateObject.remove { - self.trie.Delete(string(stateObject.Address())) + self.DeleteStateObject(stateObject) } else { + println(ethutil.Bytes2Hex(stateObject.Address())) self.UpdateStateObject(stateObject) } } + + // FIXME trie delete is broken + valid, t2 := ethtrie.ParanoiaCheck(self.trie) + if !valid { + self.trie = t2 + } + } // Purges the current trie. @@ -100,6 +108,12 @@ func (self *State) UpdateStateObject(stateObject *StateObject) { self.manifest.AddObjectChange(stateObject) } +func (self *State) DeleteStateObject(stateObject *StateObject) { + self.trie.Delete(string(stateObject.Address())) + + delete(self.stateObjects, string(stateObject.Address())) +} + func (self *State) GetStateObject(addr []byte) *StateObject { stateObject := self.stateObjects[string(addr)] if stateObject != nil { diff --git a/ethchain/state_object.go b/ethchain/state_object.go index 5a43de35c..2c7f36e65 100644 --- a/ethchain/state_object.go +++ b/ethchain/state_object.go @@ -84,6 +84,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) } func (c *StateObject) GetAddr(addr []byte) *ethutil.Value { diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go index 10a795cb8..314d858f2 100644 --- a/ethchain/state_transition.go +++ b/ethchain/state_transition.go @@ -176,15 +176,23 @@ func (self *StateTransition) TransitionState() (err error) { return } - receiver = self.Receiver() + /* FIXME + * If tx goes TO "0", goes OOG during init, reverse changes, but initial endowment should happen. The ether is lost forever + */ + var snapshot *State // If the receiver is nil it's a contract (\0*32). - if receiver == nil { + if tx.CreatesContract() { + snapshot = self.state.Copy() + // Create a new state object for the contract receiver = self.MakeStateObject(self.state, tx) + self.rec = receiver if receiver == nil { return fmt.Errorf("Unable to create contract") } + } else { + receiver = self.Receiver() } // Transfer value from sender to receiver @@ -192,7 +200,9 @@ func (self *StateTransition) TransitionState() (err error) { return } - snapshot := self.state.Copy() + if snapshot == nil { + snapshot = self.state.Copy() + } // Process the init code and create 'valid' contract if IsContractAddr(self.receiver) {