fix state object bugs causing tx reverts (#445)
This commit is contained in:
parent
1cb712fb16
commit
ca0a79f103
@ -141,10 +141,6 @@ func (so *stateObject) setState(key, value ethcmn.Hash) {
|
|||||||
so.dirtyStorage = append(so.dirtyStorage, NewState(key, value))
|
so.dirtyStorage = append(so.dirtyStorage, NewState(key, value))
|
||||||
idx = len(so.dirtyStorage) - 1
|
idx = len(so.dirtyStorage) - 1
|
||||||
so.keyToDirtyStorageIndex[key] = idx
|
so.keyToDirtyStorageIndex[key] = idx
|
||||||
|
|
||||||
so.originStorage = append(so.originStorage, State{})
|
|
||||||
idx = len(so.originStorage) - 1
|
|
||||||
so.keyToOriginStorageIndex[key] = idx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCode sets the state object's code.
|
// SetCode sets the state object's code.
|
||||||
@ -246,6 +242,13 @@ func (so *stateObject) commitState() {
|
|||||||
store := prefix.NewStore(ctx.KVStore(so.stateDB.storeKey), AddressStoragePrefix(so.Address()))
|
store := prefix.NewStore(ctx.KVStore(so.stateDB.storeKey), AddressStoragePrefix(so.Address()))
|
||||||
|
|
||||||
for _, state := range so.dirtyStorage {
|
for _, state := range so.dirtyStorage {
|
||||||
|
// NOTE: key is already prefixed from GetStorageByAddressKey
|
||||||
|
|
||||||
|
// delete empty values from the store
|
||||||
|
if (state.Value == ethcmn.Hash{}) {
|
||||||
|
store.Delete(state.Key.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
delete(so.keyToDirtyStorageIndex, state.Key)
|
delete(so.keyToDirtyStorageIndex, state.Key)
|
||||||
|
|
||||||
// skip no-op changes, persist actual changes
|
// skip no-op changes, persist actual changes
|
||||||
@ -254,20 +257,16 @@ func (so *stateObject) commitState() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.Value == ethcmn.Hash{}) {
|
||||||
|
delete(so.keyToOriginStorageIndex, state.Key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if state.Value == so.originStorage[idx].Value {
|
if state.Value == so.originStorage[idx].Value {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
so.originStorage[idx].Value = state.Value
|
so.originStorage[idx].Value = state.Value
|
||||||
|
|
||||||
// NOTE: key is already prefixed from GetStorageByAddressKey
|
|
||||||
|
|
||||||
// delete empty values from the store
|
|
||||||
if (state.Value == ethcmn.Hash{}) {
|
|
||||||
store.Delete(state.Key.Bytes())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
store.Set(state.Key.Bytes(), state.Value.Bytes())
|
store.Set(state.Key.Bytes(), state.Value.Bytes())
|
||||||
}
|
}
|
||||||
// clean storage as all entries are dirty
|
// clean storage as all entries are dirty
|
||||||
@ -348,7 +347,8 @@ func (so *stateObject) GetState(db ethstate.Database, key ethcmn.Hash) ethcmn.Ha
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise return the entry's original value
|
// otherwise return the entry's original value
|
||||||
return so.GetCommittedState(db, key)
|
value := so.GetCommittedState(db, key)
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommittedState retrieves a value from the committed account storage trie.
|
// GetCommittedState retrieves a value from the committed account storage trie.
|
||||||
@ -363,14 +363,9 @@ func (so *stateObject) GetCommittedState(_ ethstate.Database, key ethcmn.Hash) e
|
|||||||
return so.originStorage[idx].Value
|
return so.originStorage[idx].Value
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(so.originStorage) == 0 {
|
|
||||||
so.originStorage = append(so.originStorage, NewState(prefixKey, ethcmn.Hash{}))
|
|
||||||
so.keyToOriginStorageIndex[prefixKey] = len(so.originStorage) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
state := so.originStorage[idx]
|
|
||||||
|
|
||||||
// otherwise load the value from the KVStore
|
// otherwise load the value from the KVStore
|
||||||
|
state := NewState(prefixKey, ethcmn.Hash{})
|
||||||
|
|
||||||
ctx := so.stateDB.ctx
|
ctx := so.stateDB.ctx
|
||||||
store := prefix.NewStore(ctx.KVStore(so.stateDB.storeKey), AddressStoragePrefix(so.Address()))
|
store := prefix.NewStore(ctx.KVStore(so.stateDB.storeKey), AddressStoragePrefix(so.Address()))
|
||||||
rawValue := store.Get(prefixKey.Bytes())
|
rawValue := store.Get(prefixKey.Bytes())
|
||||||
@ -379,7 +374,8 @@ func (so *stateObject) GetCommittedState(_ ethstate.Database, key ethcmn.Hash) e
|
|||||||
state.Value.SetBytes(rawValue)
|
state.Value.SetBytes(rawValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
so.originStorage[idx] = state
|
so.originStorage = append(so.originStorage, state)
|
||||||
|
so.keyToOriginStorageIndex[prefixKey] = len(so.originStorage) - 1
|
||||||
return state.Value
|
return state.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,16 @@ func (suite *StateDBTestSuite) TestStateObject_State() {
|
|||||||
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key1")), ethcmn.BytesToHash([]byte("value2")))
|
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key1")), ethcmn.BytesToHash([]byte("value2")))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"update various keys",
|
||||||
|
ethcmn.BytesToHash([]byte("key1")),
|
||||||
|
ethcmn.BytesToHash([]byte("value1")),
|
||||||
|
func() {
|
||||||
|
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key1")), ethcmn.BytesToHash([]byte("value1")))
|
||||||
|
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key2")), ethcmn.BytesToHash([]byte("value2")))
|
||||||
|
suite.stateObject.SetState(nil, ethcmn.BytesToHash([]byte("key3")), ethcmn.BytesToHash([]byte("value3")))
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCase {
|
for _, tc := range testCase {
|
||||||
|
Loading…
Reference in New Issue
Block a user