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  }