github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/mock/app.go (about) 1 package mock 2 3 import ( 4 "bytes" 5 "fmt" 6 "math/rand" 7 "os" 8 "sort" 9 10 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types" 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/mpt" 12 13 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 14 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 15 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519" 16 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1" 17 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 18 dbm "github.com/fibonacci-chain/fbc/libs/tm-db" 19 20 bam "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/baseapp" 21 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 22 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 23 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 24 authexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported" 25 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/params" 26 ) 27 28 const chainID = "" 29 30 // App extends an ABCI application, but with most of its parameters exported. 31 // They are exported for convenience in creating helper functions, as object 32 // capabilities aren't needed for testing. 33 type App struct { 34 *bam.BaseApp 35 Cdc *codec.CodecProxy // Cdc is public since the codec is passed into the module anyways 36 KeyMain *sdk.KVStoreKey 37 KeyAccount *sdk.KVStoreKey 38 KeyAccMpt *sdk.KVStoreKey 39 KeyParams *sdk.KVStoreKey 40 TKeyParams *sdk.TransientStoreKey 41 42 // TODO: Abstract this out from not needing to be auth specifically 43 AccountKeeper auth.AccountKeeper 44 ParamsKeeper params.Keeper 45 46 GenesisAccounts []authexported.Account 47 TotalCoinsSupply sdk.Coins 48 } 49 50 // NewApp partially constructs a new app on the memstore for module and genesis 51 // testing. 52 func NewApp() *App { 53 logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") 54 db := dbm.NewMemDB() 55 56 // Create the cdc with some standard codecs 57 cdcP := createCodec() 58 cdc := cdcP.GetCdc() 59 60 // Create your application object 61 app := &App{ 62 BaseApp: bam.NewBaseApp("mock", logger, db, auth.DefaultTxDecoder(cdc)), 63 Cdc: cdcP, 64 KeyMain: sdk.NewKVStoreKey(bam.MainStoreKey), 65 KeyAccount: sdk.NewKVStoreKey(auth.StoreKey), 66 KeyAccMpt: sdk.NewKVStoreKey(mpt.StoreKey), 67 KeyParams: sdk.NewKVStoreKey("params"), 68 TKeyParams: sdk.NewTransientStoreKey("transient_params"), 69 TotalCoinsSupply: sdk.NewCoins(), 70 } 71 72 // define keepers 73 app.ParamsKeeper = params.NewKeeper(app.Cdc.GetCdc(), app.KeyParams, app.TKeyParams) 74 75 app.AccountKeeper = auth.NewAccountKeeper( 76 app.Cdc.GetCdc(), 77 app.KeyAccount, 78 app.KeyAccMpt, 79 app.ParamsKeeper.Subspace(auth.DefaultParamspace), 80 auth.ProtoBaseAccount, 81 ) 82 83 supplyKeeper := NewDummySupplyKeeper(app.AccountKeeper) 84 85 // Initialize the app. The chainers and blockers can be overwritten before 86 // calling complete setup. 87 app.SetInitChainer(app.InitChainer) 88 app.SetAnteHandler(auth.NewAnteHandler(app.AccountKeeper, supplyKeeper, auth.DefaultSigVerificationGasConsumer)) 89 90 // Not sealing for custom extension 91 92 return app 93 } 94 95 // CompleteSetup completes the application setup after the routes have been 96 // registered. 97 func (app *App) CompleteSetup(newKeys ...sdk.StoreKey) error { 98 newKeys = append( 99 newKeys, 100 app.KeyMain, app.KeyAccount, app.KeyParams, app.TKeyParams, 101 ) 102 103 for _, key := range newKeys { 104 switch key.(type) { 105 case *sdk.KVStoreKey: 106 if key.Name() == mpt.StoreKey { 107 app.MountStore(key, sdk.StoreTypeMPT) 108 } else { 109 app.MountStore(key, sdk.StoreTypeIAVL) 110 } 111 case *sdk.TransientStoreKey: 112 app.MountStore(key, sdk.StoreTypeTransient) 113 default: 114 return fmt.Errorf("unsupported StoreKey: %+v", key) 115 } 116 } 117 118 err := app.LoadLatestVersion(app.KeyMain) 119 120 return err 121 } 122 123 // InitChainer performs custom logic for initialization. 124 func (app *App) InitChainer(ctx sdk.Context, _ abci.RequestInitChain) abci.ResponseInitChain { 125 126 // Load the genesis accounts 127 for _, genacc := range app.GenesisAccounts { 128 acc := app.AccountKeeper.NewAccountWithAddress(ctx, genacc.GetAddress()) 129 acc.SetCoins(genacc.GetCoins()) 130 app.AccountKeeper.SetAccount(ctx, acc) 131 } 132 133 auth.InitGenesis(ctx, app.AccountKeeper, auth.DefaultGenesisState()) 134 135 return abci.ResponseInitChain{} 136 } 137 138 // Type that combines an Address with the privKey and pubKey to that address 139 type AddrKeys struct { 140 Address sdk.AccAddress 141 PubKey crypto.PubKey 142 PrivKey crypto.PrivKey 143 } 144 145 func NewAddrKeys(address sdk.AccAddress, pubKey crypto.PubKey, 146 privKey crypto.PrivKey) AddrKeys { 147 148 return AddrKeys{ 149 Address: address, 150 PubKey: pubKey, 151 PrivKey: privKey, 152 } 153 } 154 155 // implement `Interface` in sort package. 156 type AddrKeysSlice []AddrKeys 157 158 func (b AddrKeysSlice) Len() int { 159 return len(b) 160 } 161 162 // Sorts lexographically by Address 163 func (b AddrKeysSlice) Less(i, j int) bool { 164 // bytes package already implements Comparable for []byte. 165 switch bytes.Compare(b[i].Address.Bytes(), b[j].Address.Bytes()) { 166 case -1: 167 return true 168 case 0, 1: 169 return false 170 default: 171 panic("not fail-able with `bytes.Comparable` bounded [-1, 1].") 172 } 173 } 174 175 func (b AddrKeysSlice) Swap(i, j int) { 176 b[j], b[i] = b[i], b[j] 177 } 178 179 // CreateGenAccounts generates genesis accounts loaded with coins, and returns 180 // their addresses, pubkeys, and privkeys. 181 func CreateGenAccounts(numAccs int, genCoins sdk.Coins) (genAccs []authexported.Account, 182 addrs []sdk.AccAddress, pubKeys []crypto.PubKey, privKeys []crypto.PrivKey) { 183 184 addrKeysSlice := AddrKeysSlice{} 185 186 for i := 0; i < numAccs; i++ { 187 privKey := secp256k1.GenPrivKey() 188 pubKey := privKey.PubKey() 189 addr := sdk.AccAddress(pubKey.Address()) 190 191 addrKeysSlice = append(addrKeysSlice, NewAddrKeys(addr, pubKey, privKey)) 192 } 193 194 sort.Sort(addrKeysSlice) 195 196 for i := range addrKeysSlice { 197 addrs = append(addrs, addrKeysSlice[i].Address) 198 pubKeys = append(pubKeys, addrKeysSlice[i].PubKey) 199 privKeys = append(privKeys, addrKeysSlice[i].PrivKey) 200 genAccs = append(genAccs, &auth.BaseAccount{ 201 Address: addrKeysSlice[i].Address, 202 Coins: genCoins, 203 }) 204 } 205 206 return 207 } 208 209 // SetGenesis sets the mock app genesis accounts. 210 func SetGenesis(app *App, accs []authexported.Account) { 211 // Pass the accounts in via the application (lazy) instead of through 212 // RequestInitChain. 213 app.GenesisAccounts = accs 214 215 app.InitChain(abci.RequestInitChain{}) 216 app.Commit(abci.RequestCommit{}) 217 } 218 219 // GenTx generates a signed mock transaction. 220 func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKey) *auth.StdTx { 221 // Make the transaction free 222 fee := auth.StdFee{ 223 Amount: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1)), 224 Gas: 100000, 225 } 226 227 sigs := make([]auth.StdSignature, len(priv)) 228 memo := "testmemotestmemo" 229 230 for i, p := range priv { 231 sig, err := p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, memo)) 232 if err != nil { 233 panic(err) 234 } 235 236 sigs[i] = auth.StdSignature{ 237 PubKey: p.PubKey(), 238 Signature: sig, 239 } 240 } 241 242 return auth.NewStdTx(msgs, fee, sigs, memo) 243 } 244 245 // GeneratePrivKeys generates a total n secp256k1 private keys. 246 func GeneratePrivKeys(n int) (keys []crypto.PrivKey) { 247 // TODO: Randomize this between ed25519 and secp256k1 248 keys = make([]crypto.PrivKey, n) 249 for i := 0; i < n; i++ { 250 keys[i] = secp256k1.GenPrivKey() 251 } 252 253 return 254 } 255 256 // GeneratePrivKeyAddressPairs generates a total of n private key, address 257 // pairs. 258 func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) { 259 keys = make([]crypto.PrivKey, n) 260 addrs = make([]sdk.AccAddress, n) 261 for i := 0; i < n; i++ { 262 if rand.Int63()%2 == 0 { 263 keys[i] = secp256k1.GenPrivKey() 264 } else { 265 keys[i] = ed25519.GenPrivKey() 266 } 267 addrs[i] = sdk.AccAddress(keys[i].PubKey().Address()) 268 } 269 return 270 } 271 272 // GeneratePrivKeyAddressPairsFromRand generates a total of n private key, address 273 // pairs using the provided randomness source. 274 func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) { 275 keys = make([]crypto.PrivKey, n) 276 addrs = make([]sdk.AccAddress, n) 277 for i := 0; i < n; i++ { 278 secret := make([]byte, 32) 279 _, err := rand.Read(secret) 280 if err != nil { 281 panic("Could not read randomness") 282 } 283 if rand.Int63()%2 == 0 { 284 keys[i] = secp256k1.GenPrivKeySecp256k1(secret) 285 } else { 286 keys[i] = ed25519.GenPrivKeyFromSecret(secret) 287 } 288 addrs[i] = sdk.AccAddress(keys[i].PubKey().Address()) 289 } 290 return 291 } 292 293 // RandomSetGenesis set genesis accounts with random coin values using the 294 // provided addresses and coin denominations. 295 func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.AccAddress, denoms []string) { 296 accts := make([]authexported.Account, len(addrs)) 297 randCoinIntervals := []BigInterval{ 298 {sdk.NewIntWithDecimal(1, 0), sdk.NewIntWithDecimal(1, 1)}, 299 {sdk.NewIntWithDecimal(1, 2), sdk.NewIntWithDecimal(1, 3)}, 300 {sdk.NewIntWithDecimal(1, 40), sdk.NewIntWithDecimal(1, 50)}, 301 } 302 303 for i := 0; i < len(accts); i++ { 304 coins := make([]sdk.Coin, len(denoms)) 305 306 // generate a random coin for each denomination 307 for j := 0; j < len(denoms); j++ { 308 coins[j] = sdk.Coin{Denom: denoms[j], 309 Amount: RandFromBigInterval(r, randCoinIntervals).ToDec(), 310 } 311 } 312 313 app.TotalCoinsSupply = app.TotalCoinsSupply.Add(coins...) 314 baseAcc := auth.NewBaseAccountWithAddress(addrs[i]) 315 316 (&baseAcc).SetCoins(coins) 317 accts[i] = &baseAcc 318 } 319 app.GenesisAccounts = accts 320 } 321 322 func createCodec() *codec.CodecProxy { 323 cdc := codec.New() 324 sdk.RegisterCodec(cdc) 325 codec.RegisterCrypto(cdc) 326 auth.RegisterCodec(cdc) 327 reg := types.NewInterfaceRegistry() 328 proc := codec.NewProtoCodec(reg) 329 return codec.NewCodecProxy(proc, cdc) 330 }