github.com/cosmos/cosmos-sdk@v0.50.10/x/bank/migrations/v3/store.go (about) 1 package v3 2 3 import ( 4 "cosmossdk.io/core/store" 5 "cosmossdk.io/log" 6 "cosmossdk.io/store/prefix" 7 storetypes "cosmossdk.io/store/types" 8 9 "github.com/cosmos/cosmos-sdk/codec" 10 "github.com/cosmos/cosmos-sdk/runtime" 11 sdk "github.com/cosmos/cosmos-sdk/types" 12 "github.com/cosmos/cosmos-sdk/types/address" 13 v2 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2" 14 "github.com/cosmos/cosmos-sdk/x/bank/types" 15 ) 16 17 // MigrateStore performs in-place store migrations from v0.43 to v0.45. The 18 // migration includes: 19 // 20 // - Migrate coin storage to save only amount. 21 // - Add an additional reverse index from denomination to address. 22 // - Remove duplicate denom from denom metadata store key. 23 func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error { 24 store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx)) 25 err := addDenomReverseIndex(store, cdc, ctx.Logger()) 26 if err != nil { 27 return err 28 } 29 30 return migrateDenomMetadata(store, ctx.Logger()) 31 } 32 33 func addDenomReverseIndex(store storetypes.KVStore, cdc codec.BinaryCodec, logger log.Logger) error { 34 oldBalancesStore := prefix.NewStore(store, v2.BalancesPrefix) 35 36 oldBalancesIter := oldBalancesStore.Iterator(nil, nil) 37 defer sdk.LogDeferred(logger, func() error { return oldBalancesIter.Close() }) 38 39 denomPrefixStores := make(map[string]prefix.Store) // memoize prefix stores 40 41 for ; oldBalancesIter.Valid(); oldBalancesIter.Next() { 42 var balance sdk.Coin 43 if err := cdc.Unmarshal(oldBalancesIter.Value(), &balance); err != nil { 44 return err 45 } 46 47 addr, err := v2.AddressFromBalancesStore(oldBalancesIter.Key()) 48 if err != nil { 49 return err 50 } 51 52 var coin sdk.DecCoin 53 if err := cdc.Unmarshal(oldBalancesIter.Value(), &coin); err != nil { 54 return err 55 } 56 57 bz, err := coin.Amount.Marshal() 58 if err != nil { 59 return err 60 } 61 62 newStore := prefix.NewStore(store, CreateAccountBalancesPrefix(addr)) 63 newStore.Set([]byte(coin.Denom), bz) 64 65 denomPrefixStore, ok := denomPrefixStores[balance.Denom] 66 if !ok { 67 denomPrefixStore = prefix.NewStore(store, CreateDenomAddressPrefix(balance.Denom)) 68 denomPrefixStores[balance.Denom] = denomPrefixStore 69 } 70 71 // Store a reverse index from denomination to account address with a 72 // sentinel value. 73 denomPrefixStore.Set(address.MustLengthPrefix(addr), []byte{0}) 74 } 75 76 return nil 77 } 78 79 func migrateDenomMetadata(store storetypes.KVStore, logger log.Logger) error { 80 oldDenomMetaDataStore := prefix.NewStore(store, v2.DenomMetadataPrefix) 81 82 oldDenomMetaDataIter := oldDenomMetaDataStore.Iterator(nil, nil) 83 defer sdk.LogDeferred(logger, func() error { return oldDenomMetaDataIter.Close() }) 84 85 for ; oldDenomMetaDataIter.Valid(); oldDenomMetaDataIter.Next() { 86 oldKey := oldDenomMetaDataIter.Key() 87 l := len(oldKey) / 2 88 89 newKey := make([]byte, len(types.DenomMetadataPrefix)+l) 90 // old key: prefix_bytes | denom_bytes | denom_bytes 91 copy(newKey, types.DenomMetadataPrefix) 92 copy(newKey[len(types.DenomMetadataPrefix):], oldKey[:l]) 93 store.Set(newKey, oldDenomMetaDataIter.Value()) 94 oldDenomMetaDataStore.Delete(oldKey) 95 } 96 97 return nil 98 } 99 100 // CreateAccountBalancesPrefix creates the prefix for an account's balances. 101 func CreateAccountBalancesPrefix(addr []byte) []byte { 102 return append(types.BalancesPrefix.Bytes(), address.MustLengthPrefix(addr)...) 103 }