Skip to content

Commit bb06900

Browse files
mergify[bot]JeancarloBarrios
authored andcommitted
fix: app-hash mismatch if upgrade migration commit is interrupted (backport cosmos#13530) (cosmos#13627)
1 parent b772aff commit bb06900

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
4545
## Bug Fixes
4646

4747
* (x/auth/tx) [#12474](https://github.com/cosmos/cosmos-sdk/pull/12474) Remove condition in GetTxsEvent that disallowed multiple equal signs, which would break event queries with base64 strings (i.e. query by signature).
48+
* (store) [#13530](https://github.com/cosmos/cosmos-sdk/pull/13530) Fix app-hash mismatch if upgrade migration commit is interrupted.
4849

4950
## [v0.46.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.3) - 2022-10-20
5051

store/rootmulti/store.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,8 +1140,18 @@ func commitStores(version int64, storeMap map[types.StoreKey]types.CommitKVStore
11401140
commitID = store.Commit()
11411141
}
11421142

1143-
storeType := store.GetStoreType()
1144-
if storeType == types.StoreTypeTransient || storeType == types.StoreTypeMemory {
1143+
for key, store := range storeMap {
1144+
last := store.LastCommitID()
1145+
1146+
// If a commit event execution is interrupted, a new iavl store's version will be larger than the rootmulti's metadata, when the block is replayed, we should avoid committing that iavl store again.
1147+
var commitID types.CommitID
1148+
if last.Version >= version {
1149+
last.Version = version
1150+
commitID = last
1151+
} else {
1152+
commitID = store.Commit()
1153+
}
1154+
if store.GetStoreType() == types.StoreTypeTransient {
11451155
continue
11461156
}
11471157

store/rootmulti/store_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,3 +904,76 @@ func TestStateListeners(t *testing.T) {
904904
cacheMulti.Write()
905905
require.Equal(t, 1, len(listener.stateCache))
906906
}
907+
908+
type commitKVStoreStub struct {
909+
types.CommitKVStore
910+
Committed int
911+
}
912+
913+
func (stub *commitKVStoreStub) Commit() types.CommitID {
914+
commitID := stub.CommitKVStore.Commit()
915+
stub.Committed += 1
916+
return commitID
917+
}
918+
919+
func prepareStoreMap() map[types.StoreKey]types.CommitKVStore {
920+
var db dbm.DB = dbm.NewMemDB()
921+
store := NewStore(db, log.NewNopLogger())
922+
store.MountStoreWithDB(types.NewKVStoreKey("iavl1"), types.StoreTypeIAVL, nil)
923+
store.MountStoreWithDB(types.NewKVStoreKey("iavl2"), types.StoreTypeIAVL, nil)
924+
store.MountStoreWithDB(types.NewTransientStoreKey("trans1"), types.StoreTypeTransient, nil)
925+
store.LoadLatestVersion()
926+
return map[types.StoreKey]types.CommitKVStore{
927+
testStoreKey1: &commitKVStoreStub{
928+
CommitKVStore: store.GetStoreByName("iavl1").(types.CommitKVStore),
929+
},
930+
testStoreKey2: &commitKVStoreStub{
931+
CommitKVStore: store.GetStoreByName("iavl2").(types.CommitKVStore),
932+
},
933+
testStoreKey3: &commitKVStoreStub{
934+
CommitKVStore: store.GetStoreByName("trans1").(types.CommitKVStore),
935+
},
936+
}
937+
}
938+
939+
func TestCommitStores(t *testing.T) {
940+
testCases := []struct {
941+
name string
942+
committed int
943+
exptectCommit int
944+
}{
945+
{
946+
"when upgrade not get interrupted",
947+
0,
948+
1,
949+
},
950+
{
951+
"when upgrade get interrupted once",
952+
1,
953+
0,
954+
},
955+
{
956+
"when upgrade get interrupted twice",
957+
2,
958+
0,
959+
},
960+
}
961+
for _, tc := range testCases {
962+
t.Run(tc.name, func(t *testing.T) {
963+
storeMap := prepareStoreMap()
964+
store := storeMap[testStoreKey1].(*commitKVStoreStub)
965+
for i := tc.committed; i > 0; i-- {
966+
store.Commit()
967+
}
968+
store.Committed = 0
969+
var version int64 = 1
970+
removalMap := map[types.StoreKey]bool{}
971+
res := commitStores(version, storeMap, removalMap)
972+
for _, s := range res.StoreInfos {
973+
require.Equal(t, version, s.CommitId.Version)
974+
}
975+
require.Equal(t, version, res.Version)
976+
require.Equal(t, tc.exptectCommit, store.Committed)
977+
})
978+
}
979+
}

0 commit comments

Comments
 (0)