Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[occ] Fix parent store readset validation #348

Merged
merged 4 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions proto/cosmos/accesscontrol/constants.proto
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ enum ResourceType {
KV_DEX_SHORT_ORDER_COUNT = 92; // child of KV_DEX

KV_BANK_DEFERRED = 93; // child of KV
reserved 94;
KV_BANK_DEFERRED_MODULE_TX_INDEX = 95; // child of KV_BANK_DEFERRED

KV_DEX_MEM_CONTRACTS_TO_PROCESS = 96; // child of KV_DEX_MEM
KV_DEX_MEM_DOWNSTREAM_CONTRACTS = 97; // child of KV_DEX_MEM
}

enum WasmMessageSubtype {
Expand Down
4 changes: 2 additions & 2 deletions store/multiversion/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,10 @@ func (s *Store) checkReadsetAtIndex(index int) (bool, []int) {
// get the latest value from the multiversion store
latestValue := s.GetLatestBeforeIndex(index, []byte(key))
if latestValue == nil {
// TODO: maybe we don't even do this check?
// this is possible if we previously read a value from a transaction write that was later reverted, so this time we read from parent store
parentVal := s.parentStore.Get([]byte(key))
if !bytes.Equal(parentVal, value) {
panic("there shouldn't be readset conflicts with parent kv store, since it shouldn't change")
valid = false
}
} else {
// if estimate, mark as conflict index - but don't invalidate
Expand Down
47 changes: 44 additions & 3 deletions store/multiversion/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,51 @@ func TestMultiVersionStoreValidateState(t *testing.T) {
valid, conflicts = mvs.ValidateTransactionState(5)
require.False(t, valid)
require.Equal(t, []int{4}, conflicts)
}

func TestMultiVersionStoreParentValidationMismatch(t *testing.T) {
parentKVStore := dbadapter.Store{DB: dbm.NewMemDB()}
mvs := multiversion.NewMultiVersionStore(parentKVStore)

parentKVStore.Set([]byte("key2"), []byte("value0"))
parentKVStore.Set([]byte("key3"), []byte("value3"))
parentKVStore.Set([]byte("key4"), []byte("value4"))
parentKVStore.Set([]byte("key5"), []byte("value5"))

writeset := make(multiversion.WriteSet)
writeset["key1"] = []byte("value1")
writeset["key2"] = []byte("value2")
writeset["key3"] = nil
mvs.SetWriteset(1, 2, writeset)

// assert panic for parent store mismatch
parentKVStore.Set([]byte("key5"), []byte("value6"))
require.Panics(t, func() { mvs.ValidateTransactionState(5) })
readset := make(multiversion.ReadSet)
readset["key1"] = []byte("value1")
readset["key2"] = []byte("value2")
readset["key3"] = nil
readset["key4"] = []byte("value4")
readset["key5"] = []byte("value5")
mvs.SetReadset(5, readset)

// assert no readset is valid
valid, conflicts := mvs.ValidateTransactionState(4)
require.True(t, valid)
require.Empty(t, conflicts)

// assert readset index 5 is valid
valid, conflicts = mvs.ValidateTransactionState(5)
require.True(t, valid)
require.Empty(t, conflicts)

// overwrite tx writeset for tx1 - no longer writes key1
writeset2 := make(multiversion.WriteSet)
writeset2["key2"] = []byte("value2")
writeset2["key3"] = nil
mvs.SetWriteset(1, 3, writeset2)

// assert readset index 5 is invalid - because of mismatch with parent store
valid, conflicts = mvs.ValidateTransactionState(5)
require.False(t, valid)
require.Empty(t, conflicts)
}

func TestMVSValidationWithOnlyEstimate(t *testing.T) {
Expand Down
Loading
Loading