github.com/Finschia/finschia-sdk@v0.48.1/x/bank/legacy/v043/store.go (about)

     1  package v043
     2  
     3  import (
     4  	"github.com/Finschia/finschia-sdk/codec"
     5  	"github.com/Finschia/finschia-sdk/store/prefix"
     6  	sdk "github.com/Finschia/finschia-sdk/types"
     7  	v040auth "github.com/Finschia/finschia-sdk/x/auth/legacy/v040"
     8  	v040bank "github.com/Finschia/finschia-sdk/x/bank/legacy/v040"
     9  	"github.com/Finschia/finschia-sdk/x/bank/types"
    10  )
    11  
    12  // migrateSupply migrates the supply to be stored by denom key instead in a
    13  // single blob.
    14  // ref: https://github.com/cosmos/cosmos-sdk/issues/7092
    15  func migrateSupply(store sdk.KVStore, cdc codec.BinaryCodec) error {
    16  	// Old supply was stored as a single blob under the SupplyKey.
    17  	var oldSupplyI v040bank.SupplyI
    18  	err := cdc.UnmarshalInterface(store.Get(v040bank.SupplyKey), &oldSupplyI)
    19  	if err != nil {
    20  		return err
    21  	}
    22  
    23  	// We delete the single key holding the whole blob.
    24  	store.Delete(v040bank.SupplyKey)
    25  
    26  	if oldSupplyI == nil {
    27  		return nil
    28  	}
    29  
    30  	// We add a new key for each denom
    31  	supplyStore := prefix.NewStore(store, types.SupplyKey)
    32  
    33  	// We're sure that SupplyI is a Supply struct, there's no other
    34  	// implementation.
    35  	oldSupply := oldSupplyI.(*types.Supply) //nolint:staticcheck
    36  	for i := range oldSupply.Total {
    37  		coin := oldSupply.Total[i]
    38  		coinBz, err := coin.Amount.Marshal()
    39  		if err != nil {
    40  			return err
    41  		}
    42  
    43  		supplyStore.Set([]byte(coin.Denom), coinBz)
    44  	}
    45  
    46  	return nil
    47  }
    48  
    49  // migrateBalanceKeys migrate the balances keys to cater for variable-length
    50  // addresses.
    51  func migrateBalanceKeys(store sdk.KVStore) {
    52  	// old key is of format:
    53  	// prefix ("balances") || addrBytes (20 bytes) || denomBytes
    54  	// new key is of format
    55  	// prefix (0x02) || addrLen (1 byte) || addrBytes || denomBytes
    56  	oldStore := prefix.NewStore(store, v040bank.BalancesPrefix)
    57  
    58  	oldStoreIter := oldStore.Iterator(nil, nil)
    59  	defer oldStoreIter.Close()
    60  
    61  	for ; oldStoreIter.Valid(); oldStoreIter.Next() {
    62  		addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key())
    63  		denom := oldStoreIter.Key()[v040auth.AddrLen:]
    64  		newStoreKey := types.CreatePrefixedAccountStoreKey(addr, denom)
    65  
    66  		// Set new key on store. Values don't change.
    67  		store.Set(newStoreKey, oldStoreIter.Value())
    68  		oldStore.Delete(oldStoreIter.Key())
    69  	}
    70  }
    71  
    72  // MigrateStore performs in-place store migrations from v0.40 to v0.43. The
    73  // migration includes:
    74  //
    75  // - Change addresses to be length-prefixed.
    76  // - Change balances prefix to 1 byte
    77  // - Change supply to be indexed by denom
    78  // - Prune balances & supply with zero coins (ref: https://github.com/cosmos/cosmos-sdk/pull/9229)
    79  func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, cdc codec.BinaryCodec) error {
    80  	store := ctx.KVStore(storeKey)
    81  	migrateBalanceKeys(store)
    82  
    83  	if err := pruneZeroBalances(store, cdc); err != nil {
    84  		return err
    85  	}
    86  
    87  	if err := migrateSupply(store, cdc); err != nil {
    88  		return err
    89  	}
    90  
    91  	return pruneZeroSupply(store)
    92  }
    93  
    94  // pruneZeroBalances removes the zero balance addresses from balances store.
    95  func pruneZeroBalances(store sdk.KVStore, cdc codec.BinaryCodec) error {
    96  	balancesStore := prefix.NewStore(store, BalancesPrefix)
    97  	iterator := balancesStore.Iterator(nil, nil)
    98  	defer iterator.Close()
    99  
   100  	for ; iterator.Valid(); iterator.Next() {
   101  		var balance sdk.Coin
   102  		if err := cdc.Unmarshal(iterator.Value(), &balance); err != nil {
   103  			return err
   104  		}
   105  
   106  		if balance.IsZero() {
   107  			balancesStore.Delete(iterator.Key())
   108  		}
   109  	}
   110  	return nil
   111  }
   112  
   113  // pruneZeroSupply removes zero balance denom from supply store.
   114  func pruneZeroSupply(store sdk.KVStore) error {
   115  	supplyStore := prefix.NewStore(store, SupplyKey)
   116  	iterator := supplyStore.Iterator(nil, nil)
   117  	defer iterator.Close()
   118  
   119  	for ; iterator.Valid(); iterator.Next() {
   120  		var amount sdk.Int
   121  		if err := amount.Unmarshal(iterator.Value()); err != nil {
   122  			return err
   123  		}
   124  
   125  		if amount.IsZero() {
   126  			supplyStore.Delete(iterator.Key())
   127  		}
   128  	}
   129  
   130  	return nil
   131  }