github.com/cosmos/cosmos-sdk@v0.50.10/types/simulation/account.go (about)

     1  package simulation
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  
     7  	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
     8  	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
     9  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    10  	sdk "github.com/cosmos/cosmos-sdk/types"
    11  )
    12  
    13  // Account contains a privkey, pubkey, address tuple
    14  // eventually more useful data can be placed in here.
    15  // (e.g. number of coins)
    16  type Account struct {
    17  	PrivKey cryptotypes.PrivKey
    18  	PubKey  cryptotypes.PubKey
    19  	Address sdk.AccAddress
    20  	ConsKey cryptotypes.PrivKey
    21  }
    22  
    23  // Equals returns true if two accounts are equal
    24  func (acc Account) Equals(acc2 Account) bool {
    25  	return acc.Address.Equals(acc2.Address)
    26  }
    27  
    28  // RandomAcc picks and returns a random account and its index from an array.
    29  func RandomAcc(r *rand.Rand, accs []Account) (Account, int) {
    30  	idx := r.Intn(len(accs))
    31  	return accs[idx], idx
    32  }
    33  
    34  // RandomAccounts generates n random accounts
    35  func RandomAccounts(r *rand.Rand, n int) []Account {
    36  	accs := make([]Account, n)
    37  
    38  	for i := 0; i < n; i++ {
    39  		// don't need that much entropy for simulation
    40  		privkeySeed := make([]byte, 15)
    41  		r.Read(privkeySeed)
    42  
    43  		accs[i].PrivKey = secp256k1.GenPrivKeyFromSecret(privkeySeed)
    44  		accs[i].PubKey = accs[i].PrivKey.PubKey()
    45  		accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
    46  
    47  		accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
    48  	}
    49  
    50  	return accs
    51  }
    52  
    53  // FindAccount iterates over all the simulation accounts to find the one that matches
    54  // the given address
    55  func FindAccount(accs []Account, address sdk.Address) (Account, bool) {
    56  	for _, acc := range accs {
    57  		if acc.Address.Equals(address) {
    58  			return acc, true
    59  		}
    60  	}
    61  
    62  	return Account{}, false
    63  }
    64  
    65  // RandomFees returns a random fee by selecting a random coin denomination and
    66  // amount from the account's available balance. If the user doesn't have enough
    67  // funds for paying fees, it returns empty coins.
    68  func RandomFees(r *rand.Rand, ctx sdk.Context, spendableCoins sdk.Coins) (sdk.Coins, error) {
    69  	if spendableCoins.Empty() {
    70  		return nil, nil
    71  	}
    72  
    73  	perm := r.Perm(len(spendableCoins))
    74  	var randCoin sdk.Coin
    75  	for _, index := range perm {
    76  		randCoin = spendableCoins[index]
    77  		if !randCoin.Amount.IsZero() {
    78  			break
    79  		}
    80  	}
    81  
    82  	if randCoin.Amount.IsZero() {
    83  		return nil, fmt.Errorf("no coins found for random fees")
    84  	}
    85  
    86  	amt, err := RandPositiveInt(r, randCoin.Amount)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	// Create a random fee and verify the fees are within the account's spendable
    92  	// balance.
    93  	fees := sdk.NewCoins(sdk.NewCoin(randCoin.Denom, amt))
    94  
    95  	return fees, nil
    96  }