github.com/cosmos/cosmos-sdk@v0.50.10/testutil/sims/address_helpers.go (about)

     1  package sims
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"strconv"
     9  
    10  	errorsmod "cosmossdk.io/errors"
    11  	"cosmossdk.io/math"
    12  
    13  	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
    14  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    15  	sdk "github.com/cosmos/cosmos-sdk/types"
    16  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    17  	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
    18  	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    19  )
    20  
    21  type GenerateAccountStrategy func(int) []sdk.AccAddress
    22  
    23  // BondDenomProvider is a subset of the staking keeper's public interface that
    24  // provides the staking bond denom. It is used in arguments in this package's
    25  // functions so that a mock staking keeper can be passed instead of the real one.
    26  type BondDenomProvider interface {
    27  	BondDenom(ctx context.Context) (string, error)
    28  }
    29  
    30  // AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys.
    31  func AddTestAddrsFromPubKeys(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt math.Int) {
    32  	bondDenom, err := stakingKeeper.BondDenom(ctx)
    33  	if err != nil {
    34  		panic(err)
    35  	}
    36  	initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
    37  
    38  	for _, pk := range pubKeys {
    39  		initAccountWithCoins(bankKeeper, ctx, sdk.AccAddress(pk.Address()), initCoins)
    40  	}
    41  }
    42  
    43  // AddTestAddrs constructs and returns accNum amount of accounts with an
    44  // initial balance of accAmt in random order
    45  func AddTestAddrs(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress {
    46  	return addTestAddrs(bankKeeper, stakingKeeper, ctx, accNum, accAmt, CreateRandomAccounts)
    47  }
    48  
    49  // AddTestAddrsIncremental constructs and returns accNum amount of accounts with an initial balance of accAmt in random order
    50  func AddTestAddrsIncremental(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress {
    51  	return addTestAddrs(bankKeeper, stakingKeeper, ctx, accNum, accAmt, CreateIncrementalAccounts)
    52  }
    53  
    54  func addTestAddrs(bankKeeper bankkeeper.Keeper, stakingKeeper BondDenomProvider, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress {
    55  	testAddrs := strategy(accNum)
    56  	bondDenom, err := stakingKeeper.BondDenom(ctx)
    57  	if err != nil {
    58  		panic(err)
    59  	}
    60  	initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
    61  
    62  	for _, addr := range testAddrs {
    63  		initAccountWithCoins(bankKeeper, ctx, addr, initCoins)
    64  	}
    65  
    66  	return testAddrs
    67  }
    68  
    69  func initAccountWithCoins(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) {
    70  	if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, coins); err != nil {
    71  		panic(err)
    72  	}
    73  
    74  	if err := bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins); err != nil {
    75  		panic(err)
    76  	}
    77  }
    78  
    79  // CreateIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order.
    80  func CreateIncrementalAccounts(accNum int) []sdk.AccAddress {
    81  	var addresses []sdk.AccAddress
    82  	var buffer bytes.Buffer
    83  
    84  	// start at 100 so we can make up to 999 test addresses with valid test addresses
    85  	for i := 100; i < (accNum + 100); i++ {
    86  		numString := strconv.Itoa(i)
    87  		buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string
    88  
    89  		buffer.WriteString(numString) // adding on final two digits to make addresses unique
    90  		res, _ := sdk.AccAddressFromHexUnsafe(buffer.String())
    91  		bech := res.String()
    92  		addr, _ := TestAddr(buffer.String(), bech)
    93  
    94  		addresses = append(addresses, addr)
    95  		buffer.Reset()
    96  	}
    97  
    98  	return addresses
    99  }
   100  
   101  // CreateRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
   102  func CreateRandomAccounts(accNum int) []sdk.AccAddress {
   103  	testAddrs := make([]sdk.AccAddress, accNum)
   104  	for i := 0; i < accNum; i++ {
   105  		pk := ed25519.GenPrivKey().PubKey()
   106  		testAddrs[i] = sdk.AccAddress(pk.Address())
   107  	}
   108  
   109  	return testAddrs
   110  }
   111  
   112  func TestAddr(addr, bech string) (sdk.AccAddress, error) {
   113  	res, err := sdk.AccAddressFromHexUnsafe(addr)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	bechexpected := res.String()
   118  	if bech != bechexpected {
   119  		return nil, fmt.Errorf("bech encoding doesn't match reference")
   120  	}
   121  
   122  	bechres, err := sdk.AccAddressFromBech32(bech)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	if !bytes.Equal(bechres, res) {
   127  		return nil, err
   128  	}
   129  
   130  	return res, nil
   131  }
   132  
   133  // ConvertAddrsToValAddrs converts the provided addresses to ValAddress.
   134  func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress {
   135  	valAddrs := make([]sdk.ValAddress, len(addrs))
   136  
   137  	for i, addr := range addrs {
   138  		valAddrs[i] = sdk.ValAddress(addr)
   139  	}
   140  
   141  	return valAddrs
   142  }
   143  
   144  // CreateTestPubKeys returns a total of numPubKeys public keys in ascending order.
   145  func CreateTestPubKeys(numPubKeys int) []cryptotypes.PubKey {
   146  	var publicKeys []cryptotypes.PubKey
   147  	var buffer bytes.Buffer
   148  
   149  	// start at 10 to avoid changing 1 to 01, 2 to 02, etc
   150  	for i := 100; i < (numPubKeys + 100); i++ {
   151  		numString := strconv.Itoa(i)
   152  		buffer.WriteString("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AF") // base pubkey string
   153  		buffer.WriteString(numString)                                                       // adding on final two digits to make pubkeys unique
   154  		publicKeys = append(publicKeys, NewPubKeyFromHex(buffer.String()))
   155  		buffer.Reset()
   156  	}
   157  
   158  	return publicKeys
   159  }
   160  
   161  // NewPubKeyFromHex returns a PubKey from a hex string.
   162  func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) {
   163  	pkBytes, err := hex.DecodeString(pk)
   164  	if err != nil {
   165  		panic(err)
   166  	}
   167  	if len(pkBytes) != ed25519.PubKeySize {
   168  		panic(errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "invalid pubkey size"))
   169  	}
   170  	return &ed25519.PubKey{Key: pkBytes}
   171  }