Skip to content

Commit feb8821

Browse files
mergify[bot]jaeseung-bae0Tech
authored
fix: app-hash mismatch if upgrade migration commit is interrupted(backport cosmos/cosmos-sdk#13530) (backport #1310) (#1318)
* fix: app-hash mismatch if upgrade migration commit is interrupted(backport cosmos/cosmos-sdk#13530) (#1310) * fix: possible app-hash mismatch(cherry-pick cosmos-sdk #13530) * chore: fix testcase * chore: update changelog * chore: lint fix * chore: not a breaking change --------- Co-authored-by: mmsqe <[email protected]> (cherry picked from commit 9105ff4) # Conflicts: # CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: jaeseung-bae <[email protected]> Co-authored-by: Youngtaek Yoon <[email protected]>
1 parent 581d50c commit feb8821

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
5454
* (types) [\#1299](https://github.com/Finschia/finschia-sdk/pull/1299) add missing nil checks
5555
* (x/staking) [\#1301](https://github.com/Finschia/finschia-sdk/pull/1301) Use bytes instead of string comparison in delete validator queue (backport cosmos/cosmos-sdk#12303)
5656
* (client/keys) [#1312](https://github.com/Finschia/finschia-sdk/pull/1312) ignore error when key not found in `keys delete`
57+
* (store) [\#1310](https://github.com/Finschia/finschia-sdk/pull/1310) fix app-hash mismatch if upgrade migration commit is interrupted(backport cosmos/cosmos-sdk#13530)
5758

5859
### Removed
5960

store/rootmulti/store.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -985,8 +985,16 @@ func commitStores(version int64, storeMap map[types.StoreKey]types.CommitKVStore
985985
storeInfos := make([]types.StoreInfo, 0, len(storeMap))
986986

987987
for key, store := range storeMap {
988-
commitID := store.Commit()
988+
last := store.LastCommitID()
989989

990+
// 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.
991+
var commitID types.CommitID
992+
if last.Version >= version {
993+
last.Version = version
994+
commitID = last
995+
} else {
996+
commitID = store.Commit()
997+
}
990998
if store.GetStoreType() == types.StoreTypeTransient {
991999
continue
9921000
}

store/rootmulti/store_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -918,3 +918,78 @@ func TestSetIAVLDIsableFastNode(t *testing.T) {
918918
multi.SetIAVLDisableFastNode(false)
919919
require.Equal(t, multi.iavlDisableFastNode, false)
920920
}
921+
922+
type commitKVStoreStub struct {
923+
types.CommitKVStore
924+
Committed int
925+
}
926+
927+
func (stub *commitKVStoreStub) Commit() types.CommitID {
928+
commitID := stub.CommitKVStore.Commit()
929+
stub.Committed += 1
930+
return commitID
931+
}
932+
933+
func prepareStoreMap() map[types.StoreKey]types.CommitKVStore {
934+
var db dbm.DB = dbm.NewMemDB()
935+
store := NewStore(db, log.NewNopLogger())
936+
store.MountStoreWithDB(types.NewKVStoreKey("iavl1"), types.StoreTypeIAVL, nil)
937+
store.MountStoreWithDB(types.NewKVStoreKey("iavl2"), types.StoreTypeIAVL, nil)
938+
store.MountStoreWithDB(types.NewTransientStoreKey("trans1"), types.StoreTypeTransient, nil)
939+
err := store.LoadLatestVersion()
940+
if err != nil {
941+
panic(err)
942+
}
943+
return map[types.StoreKey]types.CommitKVStore{
944+
testStoreKey1: &commitKVStoreStub{
945+
CommitKVStore: store.GetStoreByName("iavl1").(types.CommitKVStore),
946+
},
947+
testStoreKey2: &commitKVStoreStub{
948+
CommitKVStore: store.GetStoreByName("iavl2").(types.CommitKVStore),
949+
},
950+
testStoreKey3: &commitKVStoreStub{
951+
CommitKVStore: store.GetStoreByName("trans1").(types.CommitKVStore),
952+
},
953+
}
954+
}
955+
956+
func TestCommitStores(t *testing.T) {
957+
testCases := []struct {
958+
name string
959+
committed int
960+
exptectCommit int
961+
}{
962+
{
963+
"when upgrade not get interrupted",
964+
0,
965+
1,
966+
},
967+
{
968+
"when upgrade get interrupted once",
969+
1,
970+
0,
971+
},
972+
{
973+
"when upgrade get interrupted twice",
974+
2,
975+
0,
976+
},
977+
}
978+
for _, tc := range testCases {
979+
t.Run(tc.name, func(t *testing.T) {
980+
storeMap := prepareStoreMap()
981+
store := storeMap[testStoreKey1].(*commitKVStoreStub)
982+
for i := tc.committed; i > 0; i-- {
983+
store.Commit()
984+
}
985+
store.Committed = 0
986+
var version int64 = 1
987+
res := commitStores(version, storeMap)
988+
for _, s := range res.StoreInfos {
989+
require.Equal(t, version, s.CommitId.Version)
990+
}
991+
require.Equal(t, version, res.Version)
992+
require.Equal(t, tc.exptectCommit, store.Committed)
993+
})
994+
}
995+
}

0 commit comments

Comments
 (0)