From 5721fcf668f8ab798b6602dc6ff88726bf0c8f86 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Jun 2015 10:20:33 +0200 Subject: core/state, core/vm: cleanup refunds --- core/state/statedb.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'core/state') diff --git a/core/state/statedb.go b/core/state/statedb.go index b3050515b..895d9fe8b 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -21,7 +21,7 @@ type StateDB struct { stateObjects map[string]*StateObject - refund map[string]*big.Int + refund *big.Int thash, bhash common.Hash txIndex int @@ -31,7 +31,7 @@ type StateDB struct { // Create a new state from a given trie func New(root common.Hash, db common.Database) *StateDB { trie := trie.NewSecure(root[:], db) - return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int), logs: make(map[common.Hash]Logs)} + return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: new(big.Int), logs: make(map[common.Hash]Logs)} } func (self *StateDB) PrintRoot() { @@ -63,12 +63,8 @@ func (self *StateDB) Logs() Logs { return logs } -func (self *StateDB) Refund(address common.Address, gas *big.Int) { - addr := address.Str() - if self.refund[addr] == nil { - self.refund[addr] = new(big.Int) - } - self.refund[addr].Add(self.refund[addr], gas) +func (self *StateDB) Refund(gas *big.Int) { + self.refund.Add(self.refund, gas) } /* @@ -268,9 +264,7 @@ func (self *StateDB) Copy() *StateDB { state.stateObjects[k] = stateObject.Copy() } - for addr, refund := range self.refund { - state.refund[addr] = new(big.Int).Set(refund) - } + state.refund.Set(self.refund) for hash, logs := range self.logs { state.logs[hash] = make(Logs, len(logs)) @@ -330,15 +324,15 @@ func (s *StateDB) Sync() { func (self *StateDB) Empty() { self.stateObjects = make(map[string]*StateObject) - self.refund = make(map[string]*big.Int) + self.refund = new(big.Int) } -func (self *StateDB) Refunds() map[string]*big.Int { +func (self *StateDB) Refunds() *big.Int { return self.refund } func (self *StateDB) Update() { - self.refund = make(map[string]*big.Int) + self.refund = new(big.Int) for _, stateObject := range self.stateObjects { if stateObject.dirty { -- cgit v1.2.3 From 787a61bb27b9f51f4af67c69eb8f1c5869ae3144 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Jun 2015 11:24:40 +0200 Subject: core/state, core/vm: reworked storage get / set to use common.Hash --- core/state/state_object.go | 47 ++++++++++++++++++++-------------------------- core/state/statedb.go | 10 +++++----- 2 files changed, 25 insertions(+), 32 deletions(-) (limited to 'core/state') diff --git a/core/state/state_object.go b/core/state/state_object.go index 6d2455d79..42dac632b 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -19,11 +19,11 @@ func (self Code) String() string { return string(self) //strings.Join(Disassemble(self), " ") } -type Storage map[string]*common.Value +type Storage map[string]common.Hash func (self Storage) String() (str string) { for key, value := range self { - str += fmt.Sprintf("%X : %X\n", key, value.Bytes()) + str += fmt.Sprintf("%X : %X\n", key, value) } return @@ -32,7 +32,6 @@ func (self Storage) String() (str string) { 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 } @@ -112,7 +111,7 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data object.balance = extobject.Balance object.codeHash = extobject.CodeHash object.State = New(extobject.Root, db) - object.storage = make(map[string]*common.Value) + object.storage = make(map[string]common.Hash) object.gasPool = new(big.Int) object.prepaid = new(big.Int) object.code, _ = db.Get(extobject.CodeHash) @@ -129,35 +128,29 @@ func (self *StateObject) MarkForDeletion() { } } -func (c *StateObject) getAddr(addr common.Hash) *common.Value { - return common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:]))) +func (c *StateObject) getAddr(addr common.Hash) (ret common.Hash) { + return common.BytesToHash(common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:]))).Bytes()) } -func (c *StateObject) setAddr(addr []byte, value interface{}) { - c.State.trie.Update(addr, common.Encode(value)) -} - -func (self *StateObject) GetStorage(key *big.Int) *common.Value { - fmt.Printf("%v: get %v %v", self.address.Hex(), key) - return self.GetState(common.BytesToHash(key.Bytes())) -} - -func (self *StateObject) SetStorage(key *big.Int, value *common.Value) { - fmt.Printf("%v: set %v -> %v", self.address.Hex(), key, value) - self.SetState(common.BytesToHash(key.Bytes()), value) +func (c *StateObject) setAddr(addr []byte, value common.Hash) { + v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00")) + if err != nil { + // if RLPing failed we better panic and not fail silently. This would be considered a consensus issue + panic(err) + } + c.State.trie.Update(addr, v) } func (self *StateObject) Storage() Storage { return self.storage } -func (self *StateObject) GetState(key common.Hash) *common.Value { +func (self *StateObject) GetState(key common.Hash) common.Hash { strkey := key.Str() - value := self.storage[strkey] - if value == nil { + value, exists := self.storage[strkey] + if !exists { value = self.getAddr(key) - - if !value.IsNil() { + if (value != common.Hash{}) { self.storage[strkey] = value } } @@ -165,14 +158,14 @@ func (self *StateObject) GetState(key common.Hash) *common.Value { return value } -func (self *StateObject) SetState(k common.Hash, value *common.Value) { - self.storage[k.Str()] = value.Copy() +func (self *StateObject) SetState(k, value common.Hash) { + self.storage[k.Str()] = value self.dirty = true } func (self *StateObject) Sync() { for key, value := range self.storage { - if value.Len() == 0 { + if (value == common.Hash{}) { self.State.trie.Delete([]byte(key)) continue } @@ -370,7 +363,7 @@ func (c *StateObject) RlpDecode(data []byte) { c.nonce = decoder.Get(0).Uint() c.balance = decoder.Get(1).BigInt() c.State = New(common.BytesToHash(decoder.Get(2).Bytes()), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface())) - c.storage = make(map[string]*common.Value) + c.storage = make(map[string]common.Hash) c.gasPool = new(big.Int) c.codeHash = decoder.Get(3).Bytes() diff --git a/core/state/statedb.go b/core/state/statedb.go index 895d9fe8b..1c75ee4db 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -103,13 +103,13 @@ func (self *StateDB) GetCode(addr common.Address) []byte { return nil } -func (self *StateDB) GetState(a common.Address, b common.Hash) []byte { +func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { stateObject := self.GetStateObject(a) if stateObject != nil { - return stateObject.GetState(b).Bytes() + return stateObject.GetState(b) } - return nil + return common.Hash{} } func (self *StateDB) IsDeleted(addr common.Address) bool { @@ -145,10 +145,10 @@ func (self *StateDB) SetCode(addr common.Address, code []byte) { } } -func (self *StateDB) SetState(addr common.Address, key common.Hash, value interface{}) { +func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { - stateObject.SetState(key, common.NewValue(value)) + stateObject.SetState(key, value) } } -- cgit v1.2.3 From 30b27336ea73f7d65c62363047fa37fdd0a54de1 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Jun 2015 11:30:42 +0200 Subject: core/state: remove the need for common.Value --- core/state/state_object.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'core/state') diff --git a/core/state/state_object.go b/core/state/state_object.go index 42dac632b..1deb9bf02 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -128,8 +128,10 @@ func (self *StateObject) MarkForDeletion() { } } -func (c *StateObject) getAddr(addr common.Hash) (ret common.Hash) { - return common.BytesToHash(common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:]))).Bytes()) +func (c *StateObject) getAddr(addr common.Hash) common.Hash { + var ret []byte + rlp.DecodeBytes(c.State.trie.Get(addr[:]), &ret) + return common.BytesToHash(ret) } func (c *StateObject) setAddr(addr []byte, value common.Hash) { -- cgit v1.2.3 From aaddc99c35f1fcc9b5d7198dd6571dfa43718ae8 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Jun 2015 12:53:22 +0200 Subject: core/state: fixed state tests --- core/state/state_test.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'core/state') diff --git a/core/state/state_test.go b/core/state/state_test.go index 09a65de54..00e133dab 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -70,37 +70,34 @@ func TestNull(t *testing.T) { address := common.HexToAddress("0x823140710bf13990e4500136726d8b55") state.CreateAccount(address) //value := common.FromHex("0x823140710bf13990e4500136726d8b55") - value := make([]byte, 16) + var value common.Hash state.SetState(address, common.Hash{}, value) state.Update() state.Sync() value = state.GetState(address, common.Hash{}) + if !common.EmptyHash(value) { + t.Errorf("expected empty hash. got %x", value) + } } func (s *StateSuite) TestSnapshot(c *checker.C) { stateobjaddr := toAddr([]byte("aa")) - storageaddr := common.Big("0") - data1 := common.NewValue(42) - data2 := common.NewValue(43) + var storageaddr common.Hash + data1 := common.BytesToHash([]byte{42}) + data2 := common.BytesToHash([]byte{43}) - // get state object - stateObject := s.state.GetOrNewStateObject(stateobjaddr) // set inital state object value - stateObject.SetStorage(storageaddr, data1) + s.state.SetState(stateobjaddr, storageaddr, data1) // get snapshot of current state snapshot := s.state.Copy() - // get state object. is this strictly necessary? - stateObject = s.state.GetStateObject(stateobjaddr) // set new state object value - stateObject.SetStorage(storageaddr, data2) + s.state.SetState(stateobjaddr, storageaddr, data2) // restore snapshot s.state.Set(snapshot) - // get state object - stateObject = s.state.GetStateObject(stateobjaddr) // get state storage value - res := stateObject.GetStorage(storageaddr) + res := s.state.GetState(stateobjaddr, storageaddr) c.Assert(data1, checker.DeepEquals, res) } -- cgit v1.2.3 From aa699a1283c93740bba15f94c774d92ea6fe1980 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Jun 2015 13:27:51 +0200 Subject: core/state: removed state from state object --- core/state/dump.go | 6 +++--- core/state/state_object.go | 33 +++++++++++++++------------------ core/state/statedb.go | 12 ++---------- 3 files changed, 20 insertions(+), 31 deletions(-) (limited to 'core/state') diff --git a/core/state/dump.go b/core/state/dump.go index 70ea21691..f6f2f9029 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -34,7 +34,7 @@ func (self *StateDB) RawDump() World { account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash)} account.Storage = make(map[string]string) - storageIt := stateObject.State.trie.Iterator() + storageIt := stateObject.trie.Iterator() for storageIt.Next() { account.Storage[common.Bytes2Hex(self.trie.GetKey(storageIt.Key))] = common.Bytes2Hex(storageIt.Value) } @@ -54,8 +54,8 @@ 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) - it := self.State.trie.Iterator() + fmt.Printf("%x %x %x %x\n", self.Address(), self.Root(), self.balance.Bytes(), self.nonce) + it := self.trie.Iterator() for it.Next() { fmt.Printf("%x %x\n", it.Key, it.Value) } diff --git a/core/state/state_object.go b/core/state/state_object.go index 1deb9bf02..2e4fe3269 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -40,9 +40,8 @@ func (self Storage) Copy() Storage { type StateObject struct { // State database for storing state changes - db common.Database - // The state object - State *StateDB + db common.Database + trie *trie.SecureTrie // Address belonging to this account address common.Address @@ -75,7 +74,6 @@ type StateObject struct { func (self *StateObject) Reset() { self.storage = make(Storage) - self.State.Reset() } func NewStateObject(address common.Address, db common.Database) *StateObject { @@ -83,7 +81,7 @@ func NewStateObject(address common.Address, db common.Database) *StateObject { //address := common.ToAddress(addr) object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true} - object.State = New(common.Hash{}, db) //New(trie.New(common.Config.Db, "")) + object.trie = trie.NewSecure((common.Hash{}).Bytes(), db) object.storage = make(Storage) object.gasPool = new(big.Int) object.prepaid = new(big.Int) @@ -110,7 +108,7 @@ func NewStateObjectFromBytes(address common.Address, data []byte, db common.Data object.nonce = extobject.Nonce object.balance = extobject.Balance object.codeHash = extobject.CodeHash - object.State = New(extobject.Root, db) + object.trie = trie.NewSecure(extobject.Root[:], db) object.storage = make(map[string]common.Hash) object.gasPool = new(big.Int) object.prepaid = new(big.Int) @@ -130,7 +128,7 @@ func (self *StateObject) MarkForDeletion() { func (c *StateObject) getAddr(addr common.Hash) common.Hash { var ret []byte - rlp.DecodeBytes(c.State.trie.Get(addr[:]), &ret) + rlp.DecodeBytes(c.trie.Get(addr[:]), &ret) return common.BytesToHash(ret) } @@ -140,7 +138,7 @@ func (c *StateObject) setAddr(addr []byte, value common.Hash) { // if RLPing failed we better panic and not fail silently. This would be considered a consensus issue panic(err) } - c.State.trie.Update(addr, v) + c.trie.Update(addr, v) } func (self *StateObject) Storage() Storage { @@ -165,10 +163,11 @@ func (self *StateObject) SetState(k, value common.Hash) { self.dirty = true } -func (self *StateObject) Sync() { +// Update updates the current cached storage to the trie +func (self *StateObject) Update() { for key, value := range self.storage { if (value == common.Hash{}) { - self.State.trie.Delete([]byte(key)) + self.trie.Delete([]byte(key)) continue } @@ -261,9 +260,7 @@ func (self *StateObject) Copy() *StateObject { stateObject.balance.Set(self.balance) stateObject.codeHash = common.CopyBytes(self.codeHash) stateObject.nonce = self.nonce - if self.State != nil { - stateObject.State = self.State.Copy() - } + stateObject.trie = self.trie stateObject.code = common.CopyBytes(self.code) stateObject.initCode = common.CopyBytes(self.initCode) stateObject.storage = self.storage.Copy() @@ -301,11 +298,11 @@ func (c *StateObject) Init() Code { } func (self *StateObject) Trie() *trie.SecureTrie { - return self.State.trie + return self.trie } func (self *StateObject) Root() []byte { - return self.Trie().Root() + return self.trie.Root() } func (self *StateObject) Code() []byte { @@ -337,10 +334,10 @@ func (self *StateObject) EachStorage(cb func(key, value []byte)) { cb([]byte(h), v.Bytes()) } - it := self.State.trie.Iterator() + it := self.trie.Iterator() for it.Next() { // ignore cached values - key := self.State.trie.GetKey(it.Key) + key := self.trie.GetKey(it.Key) if _, ok := self.storage[string(key)]; !ok { cb(key, it.Value) } @@ -364,7 +361,7 @@ func (c *StateObject) RlpDecode(data []byte) { decoder := common.NewValueFromBytes(data) c.nonce = decoder.Get(0).Uint() c.balance = decoder.Get(1).BigInt() - c.State = New(common.BytesToHash(decoder.Get(2).Bytes()), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface())) + c.trie = trie.NewSecure(decoder.Get(2).Bytes(), c.db) c.storage = make(map[string]common.Hash) c.gasPool = new(big.Int) diff --git a/core/state/statedb.go b/core/state/statedb.go index 1c75ee4db..134c4b3c7 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -296,10 +296,6 @@ func (s *StateDB) Reset() { // Reset all nested states for _, stateObject := range s.stateObjects { - if stateObject.State == nil { - continue - } - stateObject.Reset() } @@ -310,11 +306,7 @@ func (s *StateDB) Reset() { func (s *StateDB) Sync() { // Sync all nested states for _, stateObject := range s.stateObjects { - if stateObject.State == nil { - continue - } - - stateObject.State.Sync() + stateObject.trie.Commit() } s.trie.Commit() @@ -339,7 +331,7 @@ func (self *StateDB) Update() { if stateObject.remove { self.DeleteStateObject(stateObject) } else { - stateObject.Sync() + stateObject.Update() self.UpdateStateObject(stateObject) } -- cgit v1.2.3 From bdd63837ea20f3103cd44a2fb76591be074dcade Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Jun 2015 13:39:19 +0200 Subject: core/state: removed trie copy --- core/state/statedb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/state') diff --git a/core/state/statedb.go b/core/state/statedb.go index 134c4b3c7..f6f63f329 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -259,7 +259,7 @@ func (s *StateDB) Cmp(other *StateDB) bool { func (self *StateDB) Copy() *StateDB { state := New(common.Hash{}, self.db) - state.trie = self.trie.Copy() + state.trie = self.trie for k, stateObject := range self.stateObjects { state.stateObjects[k] = stateObject.Copy() } -- cgit v1.2.3