diff options
author | obscuren <geffobscura@gmail.com> | 2015-02-21 01:13:46 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2015-02-21 01:13:46 +0800 |
commit | bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca (patch) | |
tree | 46ab5943fd5e26198067aeec4a44287452eb2a32 /state | |
parent | 771bfe9e78f9952002a71cccc8d41c8c544fdfcb (diff) | |
parent | d586a633ff005ac01c9f1eb33552d147cf6c883e (diff) | |
download | go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.tar go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.tar.gz go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.tar.bz2 go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.tar.lz go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.tar.xz go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.tar.zst go-tangerine-bd7ebbcd5b77ce4fdd471b44f0acda80f2b3ceca.zip |
Merge branch 'release/0.9.0'
Diffstat (limited to 'state')
-rw-r--r-- | state/dump.go | 30 | ||||
-rw-r--r-- | state/manifest.go | 55 | ||||
-rw-r--r-- | state/state_object.go | 165 | ||||
-rw-r--r-- | state/state_test.go | 50 | ||||
-rw-r--r-- | state/statedb.go (renamed from state/state.go) | 138 |
5 files changed, 211 insertions, 227 deletions
diff --git a/state/dump.go b/state/dump.go index c1f5ecf3a..81895f1a3 100644 --- a/state/dump.go +++ b/state/dump.go @@ -22,22 +22,23 @@ type World struct { func (self *StateDB) Dump() []byte { world := World{ - Root: ethutil.Bytes2Hex(self.Trie.GetRoot()), + Root: ethutil.Bytes2Hex(self.trie.Root()), Accounts: make(map[string]Account), } - self.Trie.NewIterator().Each(func(key string, value *ethutil.Value) { - stateObject := NewStateObjectFromBytes([]byte(key), value.Bytes()) + it := self.trie.Iterator() + for it.Next() { + stateObject := NewStateObjectFromBytes(it.Key, it.Value, self.db) - account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.Nonce, Root: ethutil.Bytes2Hex(stateObject.Root()), CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)} + account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: ethutil.Bytes2Hex(stateObject.Root()), CodeHash: ethutil.Bytes2Hex(stateObject.codeHash)} account.Storage = make(map[string]string) - stateObject.EachStorage(func(key string, value *ethutil.Value) { - value.Decode() - account.Storage[ethutil.Bytes2Hex([]byte(key))] = ethutil.Bytes2Hex(value.Bytes()) - }) - world.Accounts[ethutil.Bytes2Hex([]byte(key))] = account - }) + storageIt := stateObject.State.trie.Iterator() + for storageIt.Next() { + account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value) + } + world.Accounts[ethutil.Bytes2Hex(it.Key)] = account + } json, err := json.MarshalIndent(world, "", " ") if err != nil { @@ -49,8 +50,9 @@ func (self *StateDB) Dump() []byte { // Debug stuff func (self *StateObject) CreateOutputForDiff() { - fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.Nonce) - self.EachStorage(func(addr string, value *ethutil.Value) { - fmt.Printf("%x %x\n", addr, value.Bytes()) - }) + fmt.Printf("%x %x %x %x\n", self.Address(), self.State.Root(), self.balance.Bytes(), self.nonce) + it := self.State.trie.Iterator() + for it.Next() { + fmt.Printf("%x %x\n", it.Key, it.Value) + } } diff --git a/state/manifest.go b/state/manifest.go deleted file mode 100644 index 21cd04a1a..000000000 --- a/state/manifest.go +++ /dev/null @@ -1,55 +0,0 @@ -package state - -import ( - "fmt" - "math/big" -) - -// Object manifest -// -// The object manifest is used to keep changes to the state so we can keep track of the changes -// that occurred during a state transitioning phase. -type Manifest struct { - Messages Messages -} - -func NewManifest() *Manifest { - m := &Manifest{} - m.Reset() - - return m -} - -func (m *Manifest) Reset() { - m.Messages = nil -} - -func (self *Manifest) AddMessage(msg *Message) *Message { - self.Messages = append(self.Messages, msg) - - return msg -} - -type Messages []*Message -type Message struct { - To, From []byte - Input []byte - Output []byte - Path int - Origin []byte - Timestamp int64 - Coinbase []byte - Block []byte - Number *big.Int - Value *big.Int - - ChangedAddresses [][]byte -} - -func (self *Message) AddStorageChange(addr []byte) { - self.ChangedAddresses = append(self.ChangedAddresses, addr) -} - -func (self *Message) String() string { - return fmt.Sprintf("Message{to: %x from: %x input: %x output: %x origin: %x coinbase: %x block: %x number: %v timestamp: %d path: %d value: %v", self.To, self.From, self.Input, self.Output, self.Origin, self.Coinbase, self.Block, self.Number, self.Timestamp, self.Path, self.Value) -} diff --git a/state/state_object.go b/state/state_object.go index b8af4e702..477b912a1 100644 --- a/state/state_object.go +++ b/state/state_object.go @@ -1,11 +1,13 @@ package state import ( + "bytes" "fmt" "math/big" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) @@ -28,16 +30,17 @@ func (self Storage) Copy() Storage { } type StateObject struct { + db ethutil.Database // Address of the object address []byte // Shared attributes balance *big.Int codeHash []byte - Nonce uint64 + nonce uint64 // Contract related attributes State *StateDB - Code Code - InitCode Code + code Code + initCode Code storage Storage @@ -50,6 +53,7 @@ type StateObject struct { // When an object is marked for deletion it will be delete from the trie // during the "update" phase of the state transition remove bool + dirty bool } func (self *StateObject) Reset() { @@ -57,44 +61,57 @@ func (self *StateObject) Reset() { self.State.Reset() } -func NewStateObject(addr []byte) *StateObject { +func NewStateObject(addr []byte, db ethutil.Database) *StateObject { // This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter. address := ethutil.Address(addr) - object := &StateObject{address: address, balance: new(big.Int), gasPool: new(big.Int)} - object.State = New(trie.New(ethutil.Config.Db, "")) + object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true} + object.State = New(nil, db) //New(trie.New(ethutil.Config.Db, "")) object.storage = make(Storage) object.gasPool = new(big.Int) return object } -func NewContract(address []byte, balance *big.Int, root []byte) *StateObject { - contract := NewStateObject(address) - contract.balance = balance - contract.State = New(trie.New(ethutil.Config.Db, string(root))) - - return contract -} +func NewStateObjectFromBytes(address, data []byte, db ethutil.Database) *StateObject { + // TODO clean me up + var extobject struct { + Nonce uint64 + Balance *big.Int + Root []byte + CodeHash []byte + } + err := rlp.Decode(bytes.NewReader(data), &extobject) + if err != nil { + fmt.Println(err) + return nil + } -func NewStateObjectFromBytes(address, data []byte) *StateObject { - object := &StateObject{address: address} - object.RlpDecode(data) + object := &StateObject{address: address, db: db} + //object.RlpDecode(data) + object.nonce = extobject.Nonce + object.balance = extobject.Balance + object.codeHash = extobject.CodeHash + object.State = New(extobject.Root, db) + object.storage = make(map[string]*ethutil.Value) + object.gasPool = new(big.Int) + object.code, _ = db.Get(extobject.CodeHash) return object } func (self *StateObject) MarkForDeletion() { self.remove = true - statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.balance) + self.dirty = true + statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.nonce, self.balance) } -func (c *StateObject) GetAddr(addr []byte) *ethutil.Value { - return ethutil.NewValueFromBytes([]byte(c.State.Trie.Get(string(addr)))) +func (c *StateObject) getAddr(addr []byte) *ethutil.Value { + return ethutil.NewValueFromBytes([]byte(c.State.trie.Get(addr))) } -func (c *StateObject) SetAddr(addr []byte, value interface{}) { - c.State.Trie.Update(string(addr), string(ethutil.NewValue(value).Encode())) +func (c *StateObject) setAddr(addr []byte, value interface{}) { + c.State.trie.Update(addr, ethutil.Encode(value)) } func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value { @@ -102,6 +119,7 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value { } func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) { self.SetState(key.Bytes(), value) + self.dirty = true } func (self *StateObject) Storage() map[string]*ethutil.Value { @@ -113,7 +131,7 @@ func (self *StateObject) GetState(k []byte) *ethutil.Value { value := self.storage[string(key)] if value == nil { - value = self.GetAddr(key) + value = self.getAddr(key) if !value.IsNil() { self.storage[string(key)] = value @@ -126,72 +144,48 @@ func (self *StateObject) GetState(k []byte) *ethutil.Value { func (self *StateObject) SetState(k []byte, value *ethutil.Value) { key := ethutil.LeftPadBytes(k, 32) self.storage[string(key)] = value.Copy() -} - -// Iterate over each storage address and yield callback -func (self *StateObject) EachStorage(cb trie.EachCallback) { - // First loop over the uncommit/cached values in storage - for key, value := range self.storage { - // XXX Most iterators Fns as it stands require encoded values - encoded := ethutil.NewValue(value.Encode()) - cb(key, encoded) - } - - it := self.State.Trie.NewIterator() - it.Each(func(key string, value *ethutil.Value) { - // If it's cached don't call the callback. - if self.storage[key] == nil { - cb(key, value) - } - }) + self.dirty = true } func (self *StateObject) Sync() { for key, value := range self.storage { if value.Len() == 0 { - self.State.Trie.Delete(string(key)) + self.State.trie.Delete([]byte(key)) continue } - self.SetAddr([]byte(key), value) - } - - valid, t2 := trie.ParanoiaCheck(self.State.Trie) - if !valid { - statelogger.Infof("Warn: PARANOIA: Different state storage root during copy %x vs %x\n", self.State.Root(), t2.GetRoot()) - - self.State.Trie = t2 + self.setAddr([]byte(key), value) } + self.storage = make(Storage) } func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value { - if int64(len(c.Code)-1) < pc.Int64() { + if int64(len(c.code)-1) < pc.Int64() { return ethutil.NewValue(0) } - return ethutil.NewValueFromBytes([]byte{c.Code[pc.Int64()]}) + return ethutil.NewValueFromBytes([]byte{c.code[pc.Int64()]}) } func (c *StateObject) AddBalance(amount *big.Int) { c.SetBalance(new(big.Int).Add(c.balance, amount)) - statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.balance, amount) + statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount) } func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) } func (c *StateObject) SubBalance(amount *big.Int) { c.SetBalance(new(big.Int).Sub(c.balance, amount)) - statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.balance, amount) + statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount) } func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) } func (c *StateObject) SetBalance(amount *big.Int) { c.balance = amount + c.dirty = true } -func (self *StateObject) Balance() *big.Int { return self.balance } - // // Gas setters and getters // @@ -206,6 +200,8 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error { c.SubAmount(total) + c.dirty = true + return nil } @@ -220,11 +216,15 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error { return GasLimitError(self.gasPool, gas) } + self.gasPool.Sub(self.gasPool, gas) + rGas := new(big.Int).Set(gas) rGas.Mul(rGas, price) self.AddAmount(rGas) + self.dirty = true + return nil } @@ -238,18 +238,19 @@ func (self *StateObject) RefundGas(gas, price *big.Int) { } func (self *StateObject) Copy() *StateObject { - stateObject := NewStateObject(self.Address()) + stateObject := NewStateObject(self.Address(), self.db) stateObject.balance.Set(self.balance) stateObject.codeHash = ethutil.CopyBytes(self.codeHash) - stateObject.Nonce = self.Nonce + stateObject.nonce = self.nonce if self.State != nil { stateObject.State = self.State.Copy() } - stateObject.Code = ethutil.CopyBytes(self.Code) - stateObject.InitCode = ethutil.CopyBytes(self.InitCode) + stateObject.code = ethutil.CopyBytes(self.code) + stateObject.initCode = ethutil.CopyBytes(self.initCode) stateObject.storage = self.storage.Copy() stateObject.gasPool.Set(self.gasPool) stateObject.remove = self.remove + stateObject.dirty = self.dirty return stateObject } @@ -262,8 +263,12 @@ func (self *StateObject) Set(stateObject *StateObject) { // Attribute accessors // +func (self *StateObject) Balance() *big.Int { + return self.balance +} + func (c *StateObject) N() *big.Int { - return big.NewInt(int64(c.Nonce)) + return big.NewInt(int64(c.nonce)) } // Returns the address of the contract/account @@ -273,15 +278,38 @@ func (c *StateObject) Address() []byte { // Returns the initialization Code func (c *StateObject) Init() Code { - return c.InitCode + return c.initCode +} + +func (self *StateObject) Trie() *trie.Trie { + return self.State.trie } func (self *StateObject) Root() []byte { - return self.State.Trie.GetRoot() + return self.Trie().Root() +} + +func (self *StateObject) Code() []byte { + return self.code } func (self *StateObject) SetCode(code []byte) { - self.Code = code + self.code = code + self.dirty = true +} + +func (self *StateObject) SetInitCode(code []byte) { + self.initCode = code + self.dirty = true +} + +func (self *StateObject) SetNonce(nonce uint64) { + self.nonce = nonce + self.dirty = true +} + +func (self *StateObject) Nonce() uint64 { + return self.nonce } // @@ -290,25 +318,24 @@ func (self *StateObject) SetCode(code []byte) { // State object encoding methods func (c *StateObject) RlpEncode() []byte { - return ethutil.Encode([]interface{}{c.Nonce, c.balance, c.Root(), c.CodeHash()}) + return ethutil.Encode([]interface{}{c.nonce, c.balance, c.Root(), c.CodeHash()}) } func (c *StateObject) CodeHash() ethutil.Bytes { - return crypto.Sha3(c.Code) + return crypto.Sha3(c.code) } func (c *StateObject) RlpDecode(data []byte) { decoder := ethutil.NewValueFromBytes(data) - - c.Nonce = decoder.Get(0).Uint() + c.nonce = decoder.Get(0).Uint() c.balance = decoder.Get(1).BigInt() - c.State = New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface())) + c.State = New(decoder.Get(2).Bytes(), c.db) //New(trie.New(ethutil.Config.Db, decoder.Get(2).Interface())) c.storage = make(map[string]*ethutil.Value) c.gasPool = new(big.Int) c.codeHash = decoder.Get(3).Bytes() - c.Code, _ = ethutil.Config.Db.Get(c.codeHash) + c.code, _ = c.db.Get(c.codeHash) } // Storage change object. Used by the manifest for notifying changes to diff --git a/state/state_test.go b/state/state_test.go index 28e4fc5da..ee1cf9286 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -1,11 +1,12 @@ package state import ( + "math/big" + checker "gopkg.in/check.v1" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/trie" ) type StateSuite struct { @@ -17,19 +18,48 @@ var _ = checker.Suite(&StateSuite{}) // var ZeroHash256 = make([]byte, 32) func (s *StateSuite) TestDump(c *checker.C) { - key := []byte{0x01} - value := "foo" - node := []interface{}{key, value} - s.state.Trie.Put(node) - dump := s.state.Dump() - c.Assert(dump, checker.NotNil) + // generate a few entries + obj1 := s.state.GetOrNewStateObject([]byte{0x01}) + obj1.AddBalance(big.NewInt(22)) + obj2 := s.state.GetOrNewStateObject([]byte{0x01, 0x02}) + obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3}) + obj3 := s.state.GetOrNewStateObject([]byte{0x02}) + obj3.SetBalance(big.NewInt(44)) + + // write some of them to the trie + s.state.UpdateStateObject(obj1) + s.state.UpdateStateObject(obj2) + + // check that dump contains the state objects that are in trie + got := string(s.state.Dump()) + want := `{ + "root": "4e3a59299745ba6752247c8b91d0f716dac9ec235861c91f5ac1894a361d87ba", + "accounts": { + "0000000000000000000000000000000000000001": { + "balance": "22", + "nonce": 0, + "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "codeHash": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "storage": {} + }, + "0000000000000000000000000000000000000102": { + "balance": "0", + "nonce": 0, + "root": "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "codeHash": "87874902497a5bb968da31a2998d8f22e949d1ef6214bcdedd8bae24cca4b9e3", + "storage": {} + } + } +}` + if got != want { + c.Errorf("dump mismatch:\ngot: %s\nwant: %s\n", got, want) + } } func (s *StateSuite) SetUpTest(c *checker.C) { - db, _ := ethdb.NewMemDatabase() ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "") - ethutil.Config.Db = db - s.state = New(trie.New(db, "")) + db, _ := ethdb.NewMemDatabase() + s.state = New(nil, db) } func (s *StateSuite) TestSnapshot(c *checker.C) { diff --git a/state/state.go b/state/statedb.go index f77da72f0..7e2b24b94 100644 --- a/state/state.go +++ b/state/statedb.go @@ -1,6 +1,7 @@ package state import ( + "bytes" "math/big" "github.com/ethereum/go-ethereum/ethutil" @@ -16,21 +17,20 @@ var statelogger = logger.NewLogger("STATE") // * Contracts // * Accounts type StateDB struct { - // The trie for this structure - Trie *trie.Trie + db ethutil.Database + trie *trie.Trie stateObjects map[string]*StateObject - manifest *Manifest - refund map[string]*big.Int logs Logs } // Create a new state from a given trie -func New(trie *trie.Trie) *StateDB { - return &StateDB{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)} +func New(root []byte, db ethutil.Database) *StateDB { + trie := trie.New(ethutil.CopyBytes(root), db) + return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int)} } func (self *StateDB) EmptyLogs() { @@ -45,6 +45,13 @@ func (self *StateDB) Logs() Logs { return self.logs } +func (self *StateDB) Refund(addr []byte, gas *big.Int) { + if self.refund[string(addr)] == nil { + self.refund[string(addr)] = new(big.Int) + } + self.refund[string(addr)].Add(self.refund[string(addr)], gas) +} + // Retrieve the balance from the given address or 0 if object not found func (self *StateDB) GetBalance(addr []byte) *big.Int { stateObject := self.GetStateObject(addr) @@ -55,13 +62,6 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int { return ethutil.Big0 } -func (self *StateDB) Refund(addr []byte, gas *big.Int) { - if self.refund[string(addr)] == nil { - self.refund[string(addr)] = new(big.Int) - } - self.refund[string(addr)].Add(self.refund[string(addr)], gas) -} - func (self *StateDB) AddBalance(addr []byte, amount *big.Int) { stateObject := self.GetStateObject(addr) if stateObject != nil { @@ -72,42 +72,42 @@ func (self *StateDB) AddBalance(addr []byte, amount *big.Int) { func (self *StateDB) GetNonce(addr []byte) uint64 { stateObject := self.GetStateObject(addr) if stateObject != nil { - return stateObject.Nonce + return stateObject.nonce } return 0 } -func (self *StateDB) SetNonce(addr []byte, nonce uint64) { +func (self *StateDB) GetCode(addr []byte) []byte { stateObject := self.GetStateObject(addr) if stateObject != nil { - stateObject.Nonce = nonce + return stateObject.code } + + return nil } -func (self *StateDB) GetCode(addr []byte) []byte { - stateObject := self.GetStateObject(addr) +func (self *StateDB) GetState(a, b []byte) []byte { + stateObject := self.GetStateObject(a) if stateObject != nil { - return stateObject.Code + return stateObject.GetState(b).Bytes() } return nil } -func (self *StateDB) SetCode(addr, code []byte) { +func (self *StateDB) SetNonce(addr []byte, nonce uint64) { stateObject := self.GetStateObject(addr) if stateObject != nil { - stateObject.SetCode(code) + stateObject.SetNonce(nonce) } } -func (self *StateDB) GetState(a, b []byte) []byte { - stateObject := self.GetStateObject(a) +func (self *StateDB) SetCode(addr, code []byte) { + stateObject := self.GetStateObject(addr) if stateObject != nil { - return stateObject.GetState(b).Bytes() + stateObject.SetCode(code) } - - return nil } func (self *StateDB) SetState(addr, key []byte, value interface{}) { @@ -137,15 +137,15 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) { addr := stateObject.Address() if len(stateObject.CodeHash()) > 0 { - ethutil.Config.Db.Put(stateObject.CodeHash(), stateObject.Code) + self.db.Put(stateObject.CodeHash(), stateObject.code) } - self.Trie.Update(string(addr), string(stateObject.RlpEncode())) + self.trie.Update(addr, stateObject.RlpEncode()) } // Delete the given state object and delete it from the state trie func (self *StateDB) DeleteStateObject(stateObject *StateObject) { - self.Trie.Delete(string(stateObject.Address())) + self.trie.Delete(stateObject.Address()) delete(self.stateObjects, string(stateObject.Address())) } @@ -159,12 +159,12 @@ func (self *StateDB) GetStateObject(addr []byte) *StateObject { return stateObject } - data := self.Trie.Get(string(addr)) + data := self.trie.Get(addr) if len(data) == 0 { return nil } - stateObject = NewStateObjectFromBytes(addr, []byte(data)) + stateObject = NewStateObjectFromBytes(addr, []byte(data), self.db) self.SetStateObject(stateObject) return stateObject @@ -190,7 +190,7 @@ func (self *StateDB) NewStateObject(addr []byte) *StateObject { statelogger.Debugf("(+) %x\n", addr) - stateObject := NewStateObject(addr) + stateObject := NewStateObject(addr, self.db) self.stateObjects[string(addr)] = stateObject return stateObject @@ -206,48 +206,42 @@ func (self *StateDB) GetAccount(addr []byte) *StateObject { // func (s *StateDB) Cmp(other *StateDB) bool { - return s.Trie.Cmp(other.Trie) + return bytes.Equal(s.trie.Root(), other.trie.Root()) } func (self *StateDB) Copy() *StateDB { - if self.Trie != nil { - state := New(self.Trie.Copy()) - for k, stateObject := range self.stateObjects { - state.stateObjects[k] = stateObject.Copy() - } - - for addr, refund := range self.refund { - state.refund[addr] = new(big.Int).Set(refund) - } - - logs := make(Logs, len(self.logs)) - copy(logs, self.logs) - state.logs = logs + state := New(nil, self.db) + state.trie = self.trie.Copy() + for k, stateObject := range self.stateObjects { + state.stateObjects[k] = stateObject.Copy() + } - return state + for addr, refund := range self.refund { + state.refund[addr] = new(big.Int).Set(refund) } - return nil + logs := make(Logs, len(self.logs)) + copy(logs, self.logs) + state.logs = logs + + return state } func (self *StateDB) Set(state *StateDB) { - if state == nil { - panic("Tried setting 'state' to nil through 'Set'") - } - - self.Trie = state.Trie + self.trie = state.trie self.stateObjects = state.stateObjects + self.refund = state.refund self.logs = state.logs } func (s *StateDB) Root() []byte { - return s.Trie.GetRoot() + return s.trie.Root() } // Resets the trie and all siblings func (s *StateDB) Reset() { - s.Trie.Undo() + s.trie.Reset() // Reset all nested states for _, stateObject := range s.stateObjects { @@ -272,7 +266,7 @@ func (s *StateDB) Sync() { stateObject.State.Sync() } - s.Trie.Sync() + s.trie.Commit() s.Empty() } @@ -287,34 +281,20 @@ func (self *StateDB) Refunds() map[string]*big.Int { } func (self *StateDB) Update(gasUsed *big.Int) { - var deleted bool - self.refund = make(map[string]*big.Int) for _, stateObject := range self.stateObjects { - if stateObject.remove { - self.DeleteStateObject(stateObject) - deleted = true - } else { - stateObject.Sync() - - self.UpdateStateObject(stateObject) + if stateObject.dirty { + if stateObject.remove { + self.DeleteStateObject(stateObject) + } else { + stateObject.Sync() + + self.UpdateStateObject(stateObject) + } + stateObject.dirty = false } } - - // FIXME trie delete is broken - if deleted { - valid, t2 := trie.ParanoiaCheck(self.Trie) - if !valid { - statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.Trie.GetRoot(), t2.GetRoot()) - - self.Trie = t2 - } - } -} - -func (self *StateDB) Manifest() *Manifest { - return self.manifest } // Debug stuff |