This commit is contained in:
gary rong 2017-04-04 11:37:39 +00:00 committed by GitHub
commit 2d1ab662eb
6 changed files with 39 additions and 22 deletions

View file

@ -40,6 +40,7 @@ type (
account *common.Address account *common.Address
prev bool // whether account had already suicided prev bool // whether account had already suicided
prevbalance *big.Int prevbalance *big.Int
prevObj *stateObject
} }
// Changes to individual accounts. // Changes to individual accounts.
@ -71,8 +72,9 @@ type (
hash common.Hash hash common.Hash
} }
touchChange struct { touchChange struct {
account *common.Address account *common.Address
prev bool prev bool
prevDirty bool
} }
) )
@ -86,36 +88,43 @@ func (ch resetObjectChange) undo(s *StateDB) {
} }
func (ch suicideChange) undo(s *StateDB) { func (ch suicideChange) undo(s *StateDB) {
obj := s.getStateObject(*ch.account) if !ch.prev {
if obj != nil { ch.prevObj.suicided = ch.prev
obj.suicided = ch.prev ch.prevObj.setBalance(ch.prevbalance)
obj.setBalance(ch.prevbalance) s.setStateObject(ch.prevObj)
} }
} }
var ripemd = common.HexToAddress("0000000000000000000000000000000000000003") var ripemd = common.HexToAddress("0000000000000000000000000000000000000003")
func (ch touchChange) undo(s *StateDB) { func (ch touchChange) undo(s *StateDB) {
if !ch.prev && *ch.account != ripemd { if !ch.prev && !ch.prevDirty && *ch.account != ripemd {
delete(s.stateObjects, *ch.account)
delete(s.stateObjectsDirty, *ch.account) delete(s.stateObjectsDirty, *ch.account)
} }
} }
func (ch balanceChange) undo(s *StateDB) { func (ch balanceChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setBalance(ch.prev) if obj := s.getStateObject(*ch.account); obj != nil {
obj.setBalance(ch.prev)
}
} }
func (ch nonceChange) undo(s *StateDB) { func (ch nonceChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setNonce(ch.prev) if obj := s.getStateObject(*ch.account); obj != nil {
obj.setNonce(ch.prev)
}
} }
func (ch codeChange) undo(s *StateDB) { func (ch codeChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) if obj := s.getStateObject(*ch.account); obj != nil {
obj.setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
}
} }
func (ch storageChange) undo(s *StateDB) { func (ch storageChange) undo(s *StateDB) {
s.getStateObject(*ch.account).setState(ch.key, ch.prevalue) if obj := s.getStateObject(*ch.account); obj != nil {
obj.setState(ch.key, ch.prevalue)
}
} }
func (ch refundChange) undo(s *StateDB) { func (ch refundChange) undo(s *StateDB) {

View file

@ -29,6 +29,7 @@ func create() (*ManagedState, *account) {
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb, _ := New(common.Hash{}, db) statedb, _ := New(common.Hash{}, db)
ms := ManageState(statedb) ms := ManageState(statedb)
ms.StateDB.createObject(addr)
ms.StateDB.SetNonce(addr, 100) ms.StateDB.SetNonce(addr, 100)
ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr)) ms.accounts[addr] = newAccount(ms.StateDB.getStateObject(addr))
return ms, ms.accounts[addr] return ms, ms.accounts[addr]
@ -116,6 +117,7 @@ func TestSetNonce(t *testing.T) {
} }
addr[0] = 1 addr[0] = 1
ms.StateDB.createObject(addr)
ms.StateDB.SetNonce(addr, 1) ms.StateDB.SetNonce(addr, 1)
if ms.GetNonce(addr) != 1 { if ms.GetNonce(addr) != 1 {

View file

@ -136,9 +136,11 @@ func (self *stateObject) markSuicided() {
} }
func (c *stateObject) touch() { func (c *stateObject) touch() {
prevDirty := c.onDirty == nil
c.db.journal = append(c.db.journal, touchChange{ c.db.journal = append(c.db.journal, touchChange{
account: &c.address, account: &c.address,
prev: c.touched, prev: c.touched,
prevDirty: prevDirty,
}) })
if c.onDirty != nil { if c.onDirty != nil {
c.onDirty(c.Address()) c.onDirty(c.Address())

View file

@ -113,6 +113,7 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {
data1 := common.BytesToHash([]byte{42}) data1 := common.BytesToHash([]byte{42})
data2 := common.BytesToHash([]byte{43}) data2 := common.BytesToHash([]byte{43})
s.state.createObject(stateobjaddr)
// set initial state object value // set initial state object value
s.state.SetState(stateobjaddr, storageaddr, data1) s.state.SetState(stateobjaddr, storageaddr, data1)
// get snapshot of current state // get snapshot of current state
@ -143,6 +144,8 @@ func TestSnapshot2(t *testing.T) {
stateobjaddr0 := toAddr([]byte("so0")) stateobjaddr0 := toAddr([]byte("so0"))
stateobjaddr1 := toAddr([]byte("so1")) stateobjaddr1 := toAddr([]byte("so1"))
state.createObject(stateobjaddr0)
state.createObject(stateobjaddr1)
var storageaddr common.Hash var storageaddr common.Hash
data0 := common.BytesToHash([]byte{17}) data0 := common.BytesToHash([]byte{17})

View file

@ -310,7 +310,7 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
// AddBalance adds amount to the account associated with addr // AddBalance adds amount to the account associated with addr
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.AddBalance(amount) stateObject.AddBalance(amount)
} }
@ -318,35 +318,35 @@ func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
// SubBalance subtracts amount from the account associated with addr // SubBalance subtracts amount from the account associated with addr
func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SubBalance(amount) stateObject.SubBalance(amount)
} }
} }
func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) { func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetBalance(amount) stateObject.SetBalance(amount)
} }
} }
func (self *StateDB) SetNonce(addr common.Address, nonce uint64) { func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetNonce(nonce) stateObject.SetNonce(nonce)
} }
} }
func (self *StateDB) SetCode(addr common.Address, code []byte) { func (self *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetCode(crypto.Keccak256Hash(code), code) stateObject.SetCode(crypto.Keccak256Hash(code), code)
} }
} }
func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) { func (self *StateDB) SetState(addr common.Address, key common.Hash, value common.Hash) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.getStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetState(self.db, key, value) stateObject.SetState(self.db, key, value)
} }
@ -366,6 +366,7 @@ func (self *StateDB) Suicide(addr common.Address) bool {
account: &addr, account: &addr,
prev: stateObject.suicided, prev: stateObject.suicided,
prevbalance: new(big.Int).Set(stateObject.Balance()), prevbalance: new(big.Int).Set(stateObject.Balance()),
prevObj: stateObject,
}) })
stateObject.markSuicided() stateObject.markSuicided()
stateObject.data.Balance = new(big.Int) stateObject.data.Balance = new(big.Int)
@ -397,7 +398,7 @@ func (self *StateDB) deleteStateObject(stateObject *stateObject) {
func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) { func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObject) {
// Prefer 'live' objects. // Prefer 'live' objects.
if obj := self.stateObjects[addr]; obj != nil { if obj := self.stateObjects[addr]; obj != nil {
if obj.deleted { if obj.suicided {
return nil return nil
} }
return obj return obj

View file

@ -116,7 +116,7 @@ func TestIntermediateLeaks(t *testing.T) {
} }
func TestSnapshotRandom(t *testing.T) { func TestSnapshotRandom(t *testing.T) {
t.Skip("@fjl fix me please") //t.Skip("@fjl fix me please")
config := &quick.Config{MaxCount: 1000} config := &quick.Config{MaxCount: 1000}
err := quick.Check((*snapshotTest).run, config) err := quick.Check((*snapshotTest).run, config)
if cerr, ok := err.(*quick.CheckError); ok { if cerr, ok := err.(*quick.CheckError); ok {