github.com/Finschia/finschia-sdk@v0.48.1/types/simulation/account.go (about)

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