mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 07:07:26 +00:00 
			
		
		
		
	
						commit
						3d9c5a5f19
					
				
							
								
								
									
										60
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								README.md
									
									
									
									
									
								
							@ -1 +1,59 @@
 | 
			
		||||
# _
 | 
			
		||||
<p align="center">
 | 
			
		||||
  <img src="./kava-logo.svg" width="300">
 | 
			
		||||
</p>
 | 
			
		||||
<h3 align="center">DeFi for Crypto.</h3>
 | 
			
		||||
 | 
			
		||||
<div align="center">
 | 
			
		||||
 | 
			
		||||
[](https://goreportcard.com/report/github.com/kava-labs/kava)
 | 
			
		||||
[](https://godoc.org/github.com/Kava-Labs/kava)
 | 
			
		||||
[](https://github.com/Kava-Labs/kava/blob/master/LICENSE.md)
 | 
			
		||||
[](https://twitter.com/kava_labs)
 | 
			
		||||
[](https://riot.im/app/#/room/#kava-validators:matrix.org)
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div align="center">
 | 
			
		||||
 | 
			
		||||
[Telegram](https://t.me/kavalabs) |
 | 
			
		||||
[Medium](https://medium.com/kava-labs) |
 | 
			
		||||
[Validator Chat](https://riot.im/app/#/room/#kava-validators:matrix.org)
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
## Installing
 | 
			
		||||
 | 
			
		||||
This guide assumes you have worked with `cosmos-sdk` blockchains previously. If you are just getting started, great! See the complete guide [here](https://medium.com/kava-labs).
 | 
			
		||||
 | 
			
		||||
#### Installing KVD
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git clone https://github.com/Kava-Labs/kava.git
 | 
			
		||||
cd kava
 | 
			
		||||
go install ./cmd/kvd ./cmd/kvcli
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Create a Wallet
 | 
			
		||||
```
 | 
			
		||||
kvd init --chain-id=kava-testnet-1 <your-moniker>
 | 
			
		||||
kvcli keys add <your_wallet_name>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**Be sure to back up your mnemonic!**
 | 
			
		||||
 | 
			
		||||
#### Create a Genesis Transaction
 | 
			
		||||
```
 | 
			
		||||
kvd add-genesis-account $(kvcli keys show <your_wallet_name> -a) 1000000kava
 | 
			
		||||
kvd gentx --name <your_wallet_name> --amount 1000000kava
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
A genesis transaction should be written to `$HOME/.kvd/config/gentx/gentx-<gen_tx_hash>.json`
 | 
			
		||||
 | 
			
		||||
#### Submit Genesis Transaction
 | 
			
		||||
To be included in the genesis file for testnet one, post your genesis transaction as a PR on this repo [here](https://github.com/Kava-Labs/kava/pulls)
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
Copyright © Kava Labs, Inc. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Licensed under the [Apache v2 License](LICENSE).
 | 
			
		||||
							
								
								
									
										423
									
								
								app/app.go
									
									
									
									
									
								
							
							
						
						
									
										423
									
								
								app/app.go
									
									
									
									
									
								
							@ -1,11 +1,10 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sort"
 | 
			
		||||
 | 
			
		||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
			
		||||
	cmn "github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
@ -15,69 +14,29 @@ import (
 | 
			
		||||
	bam "github.com/cosmos/cosmos-sdk/baseapp"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/types/module"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/version"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/crisis"
 | 
			
		||||
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
 | 
			
		||||
	distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/genutil"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/gov"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/mint"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/params"
 | 
			
		||||
	paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/slashing"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const appName = "KavaApp"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// default home directories for cli
 | 
			
		||||
	DefaultCLIHome = os.ExpandEnv("$HOME/.kvcli")
 | 
			
		||||
 | 
			
		||||
	// default home directories for daemon
 | 
			
		||||
	DefaultNodeHome = os.ExpandEnv("$HOME/.kvd")
 | 
			
		||||
 | 
			
		||||
	// The ModuleBasicManager is in charge of setting up basic,
 | 
			
		||||
	// non-dependant module elements, such as codec registration
 | 
			
		||||
	// and genesis verification.
 | 
			
		||||
	ModuleBasics module.BasicManager
 | 
			
		||||
const (
 | 
			
		||||
	appName = "kava"
 | 
			
		||||
	// DefaultKeyPass contains the default key password for genesis transactions
 | 
			
		||||
	DefaultKeyPass   = "12345678"
 | 
			
		||||
	Bech32MainPrefix = "k"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	ModuleBasics = module.NewBasicManager(
 | 
			
		||||
		genaccounts.AppModuleBasic{},
 | 
			
		||||
		genutil.AppModuleBasic{},
 | 
			
		||||
		auth.AppModuleBasic{},
 | 
			
		||||
		bank.AppModuleBasic{},
 | 
			
		||||
		staking.AppModuleBasic{},
 | 
			
		||||
		mint.AppModuleBasic{},
 | 
			
		||||
		distr.AppModuleBasic{},
 | 
			
		||||
		gov.NewAppModuleBasic(paramsclient.ProposalHandler, distrclient.ProposalHandler),
 | 
			
		||||
		params.AppModuleBasic{},
 | 
			
		||||
		crisis.AppModuleBasic{},
 | 
			
		||||
		slashing.AppModuleBasic{},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// custom tx codec
 | 
			
		||||
func MakeCodec() *codec.Codec {
 | 
			
		||||
	var cdc = codec.New()
 | 
			
		||||
	ModuleBasics.RegisterCodec(cdc)
 | 
			
		||||
	sdk.RegisterCodec(cdc)
 | 
			
		||||
	codec.RegisterCrypto(cdc)
 | 
			
		||||
	return cdc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetAddressPrefixes sets the bech32 address prefixes on an sdk config.
 | 
			
		||||
func SetAddressPrefixes(config *sdk.Config) {
 | 
			
		||||
	config.SetBech32PrefixForAccount("k", "k"+"pub")
 | 
			
		||||
	config.SetBech32PrefixForValidator("k"+"val"+"oper", "k"+"val"+"oper"+"pub")
 | 
			
		||||
	config.SetBech32PrefixForConsensusNode("k"+"val"+"cons", "k"+"val"+"cons"+"pub")
 | 
			
		||||
}
 | 
			
		||||
// default home directories for expected binaries
 | 
			
		||||
var (
 | 
			
		||||
	DefaultCLIHome  = os.ExpandEnv("$HOME/.kvcli")
 | 
			
		||||
	DefaultNodeHome = os.ExpandEnv("$HOME/.kvd")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Extended ABCI application
 | 
			
		||||
type App struct {
 | 
			
		||||
@ -100,7 +59,7 @@ type App struct {
 | 
			
		||||
	keyParams        *sdk.KVStoreKey
 | 
			
		||||
	tkeyParams       *sdk.TransientStoreKey
 | 
			
		||||
 | 
			
		||||
	// keepers
 | 
			
		||||
	// Manage getting and setting accounts
 | 
			
		||||
	accountKeeper       auth.AccountKeeper
 | 
			
		||||
	feeCollectionKeeper auth.FeeCollectionKeeper
 | 
			
		||||
	bankKeeper          bank.Keeper
 | 
			
		||||
@ -111,20 +70,17 @@ type App struct {
 | 
			
		||||
	govKeeper           gov.Keeper
 | 
			
		||||
	crisisKeeper        crisis.Keeper
 | 
			
		||||
	paramsKeeper        params.Keeper
 | 
			
		||||
 | 
			
		||||
	// the module manager
 | 
			
		||||
	mm *module.Manager
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewApp returns a reference to an initialized App.
 | 
			
		||||
func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
			
		||||
	invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp)) *App {
 | 
			
		||||
	invCheckPeriod uint,
 | 
			
		||||
	baseAppOptions ...func(*bam.BaseApp)) *App {
 | 
			
		||||
 | 
			
		||||
	cdc := MakeCodec()
 | 
			
		||||
 | 
			
		||||
	bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...)
 | 
			
		||||
	bApp.SetCommitMultiStoreTracer(traceStore)
 | 
			
		||||
	bApp.SetAppVersion(version.Version)
 | 
			
		||||
 | 
			
		||||
	var app = &App{
 | 
			
		||||
		BaseApp:          bApp,
 | 
			
		||||
@ -144,82 +100,99 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
			
		||||
		tkeyParams:       sdk.NewTransientStoreKey(params.TStoreKey),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// init params keeper and subspaces
 | 
			
		||||
	app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams, params.DefaultCodespace)
 | 
			
		||||
	authSubspace := app.paramsKeeper.Subspace(auth.DefaultParamspace)
 | 
			
		||||
	bankSubspace := app.paramsKeeper.Subspace(bank.DefaultParamspace)
 | 
			
		||||
	stakingSubspace := app.paramsKeeper.Subspace(staking.DefaultParamspace)
 | 
			
		||||
	mintSubspace := app.paramsKeeper.Subspace(mint.DefaultParamspace)
 | 
			
		||||
	distrSubspace := app.paramsKeeper.Subspace(distr.DefaultParamspace)
 | 
			
		||||
	slashingSubspace := app.paramsKeeper.Subspace(slashing.DefaultParamspace)
 | 
			
		||||
	govSubspace := app.paramsKeeper.Subspace(gov.DefaultParamspace)
 | 
			
		||||
	crisisSubspace := app.paramsKeeper.Subspace(crisis.DefaultParamspace)
 | 
			
		||||
	app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams)
 | 
			
		||||
 | 
			
		||||
	// add keepers
 | 
			
		||||
	app.accountKeeper = auth.NewAccountKeeper(app.cdc, app.keyAccount, authSubspace, auth.ProtoBaseAccount)
 | 
			
		||||
	app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace)
 | 
			
		||||
	app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection)
 | 
			
		||||
	stakingKeeper := staking.NewKeeper(app.cdc, app.keyStaking, app.tkeyStaking, app.bankKeeper,
 | 
			
		||||
		stakingSubspace, staking.DefaultCodespace)
 | 
			
		||||
	app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint, mintSubspace, &stakingKeeper, app.feeCollectionKeeper)
 | 
			
		||||
	app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, distrSubspace, app.bankKeeper, &stakingKeeper,
 | 
			
		||||
		app.feeCollectionKeeper, distr.DefaultCodespace)
 | 
			
		||||
	app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, &stakingKeeper,
 | 
			
		||||
		slashingSubspace, slashing.DefaultCodespace)
 | 
			
		||||
	app.crisisKeeper = crisis.NewKeeper(crisisSubspace, invCheckPeriod, app.distrKeeper,
 | 
			
		||||
		app.bankKeeper, app.feeCollectionKeeper)
 | 
			
		||||
 | 
			
		||||
	// register the proposal types
 | 
			
		||||
	govRouter := gov.NewRouter()
 | 
			
		||||
	govRouter.AddRoute(gov.RouterKey, gov.ProposalHandler).
 | 
			
		||||
		AddRoute(params.RouterKey, params.NewParamChangeProposalHandler(app.paramsKeeper)).
 | 
			
		||||
		AddRoute(distr.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.distrKeeper))
 | 
			
		||||
	app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper, govSubspace,
 | 
			
		||||
		app.bankKeeper, &stakingKeeper, gov.DefaultCodespace, govRouter)
 | 
			
		||||
 | 
			
		||||
	// register the staking hooks
 | 
			
		||||
	// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
 | 
			
		||||
	app.stakingKeeper = *stakingKeeper.SetHooks(
 | 
			
		||||
		staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()))
 | 
			
		||||
 | 
			
		||||
	app.mm = module.NewManager(
 | 
			
		||||
		genaccounts.NewAppModule(app.accountKeeper),
 | 
			
		||||
		genutil.NewAppModule(app.accountKeeper, app.stakingKeeper, app.BaseApp.DeliverTx),
 | 
			
		||||
		auth.NewAppModule(app.accountKeeper, app.feeCollectionKeeper),
 | 
			
		||||
		bank.NewAppModule(app.bankKeeper, app.accountKeeper),
 | 
			
		||||
		crisis.NewAppModule(app.crisisKeeper, app.Logger()),
 | 
			
		||||
		distr.NewAppModule(app.distrKeeper),
 | 
			
		||||
		gov.NewAppModule(app.govKeeper),
 | 
			
		||||
		mint.NewAppModule(app.mintKeeper),
 | 
			
		||||
		slashing.NewAppModule(app.slashingKeeper, app.stakingKeeper),
 | 
			
		||||
		staking.NewAppModule(app.stakingKeeper, app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper),
 | 
			
		||||
	// define the accountKeeper
 | 
			
		||||
	app.accountKeeper = auth.NewAccountKeeper(
 | 
			
		||||
		app.cdc,
 | 
			
		||||
		app.keyAccount,
 | 
			
		||||
		app.paramsKeeper.Subspace(auth.DefaultParamspace),
 | 
			
		||||
		auth.ProtoBaseAccount,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// During begin block slashing happens after distr.BeginBlocker so that
 | 
			
		||||
	// there is nothing left over in the validator fee pool, so as to keep the
 | 
			
		||||
	// CanWithdrawInvariant invariant.
 | 
			
		||||
	app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName)
 | 
			
		||||
	// add handlers
 | 
			
		||||
	app.bankKeeper = bank.NewBaseKeeper(
 | 
			
		||||
		app.accountKeeper,
 | 
			
		||||
		app.paramsKeeper.Subspace(bank.DefaultParamspace),
 | 
			
		||||
		bank.DefaultCodespace,
 | 
			
		||||
	)
 | 
			
		||||
	app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(
 | 
			
		||||
		app.cdc,
 | 
			
		||||
		app.keyFeeCollection,
 | 
			
		||||
	)
 | 
			
		||||
	stakingKeeper := staking.NewKeeper(
 | 
			
		||||
		app.cdc,
 | 
			
		||||
		app.keyStaking, app.tkeyStaking,
 | 
			
		||||
		app.bankKeeper, app.paramsKeeper.Subspace(staking.DefaultParamspace),
 | 
			
		||||
		staking.DefaultCodespace,
 | 
			
		||||
	)
 | 
			
		||||
	app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint,
 | 
			
		||||
		app.paramsKeeper.Subspace(mint.DefaultParamspace),
 | 
			
		||||
		&stakingKeeper, app.feeCollectionKeeper,
 | 
			
		||||
	)
 | 
			
		||||
	app.distrKeeper = distr.NewKeeper(
 | 
			
		||||
		app.cdc,
 | 
			
		||||
		app.keyDistr,
 | 
			
		||||
		app.paramsKeeper.Subspace(distr.DefaultParamspace),
 | 
			
		||||
		app.bankKeeper, &stakingKeeper, app.feeCollectionKeeper,
 | 
			
		||||
		distr.DefaultCodespace,
 | 
			
		||||
	)
 | 
			
		||||
	app.slashingKeeper = slashing.NewKeeper(
 | 
			
		||||
		app.cdc,
 | 
			
		||||
		app.keySlashing,
 | 
			
		||||
		&stakingKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace),
 | 
			
		||||
		slashing.DefaultCodespace,
 | 
			
		||||
	)
 | 
			
		||||
	app.govKeeper = gov.NewKeeper(
 | 
			
		||||
		app.cdc,
 | 
			
		||||
		app.keyGov,
 | 
			
		||||
		app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, &stakingKeeper,
 | 
			
		||||
		gov.DefaultCodespace,
 | 
			
		||||
	)
 | 
			
		||||
	app.crisisKeeper = crisis.NewKeeper(
 | 
			
		||||
		app.paramsKeeper.Subspace(crisis.DefaultParamspace),
 | 
			
		||||
		app.distrKeeper,
 | 
			
		||||
		app.bankKeeper,
 | 
			
		||||
		app.feeCollectionKeeper,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	app.mm.SetOrderEndBlockers(gov.ModuleName, staking.ModuleName)
 | 
			
		||||
	// register the staking hooks
 | 
			
		||||
	// NOTE: The stakingKeeper above is passed by reference, so that it can be
 | 
			
		||||
	// modified like below:
 | 
			
		||||
	app.stakingKeeper = *stakingKeeper.SetHooks(
 | 
			
		||||
		NewStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// genutils must occur after staking so that pools are properly
 | 
			
		||||
	// initialized with tokens from genesis accounts.
 | 
			
		||||
	app.mm.SetOrderInitGenesis(genaccounts.ModuleName, distr.ModuleName,
 | 
			
		||||
		staking.ModuleName, auth.ModuleName, bank.ModuleName, slashing.ModuleName,
 | 
			
		||||
		gov.ModuleName, mint.ModuleName, crisis.ModuleName, genutil.ModuleName)
 | 
			
		||||
	// register the crisis routes
 | 
			
		||||
	bank.RegisterInvariants(&app.crisisKeeper, app.accountKeeper)
 | 
			
		||||
	distr.RegisterInvariants(&app.crisisKeeper, app.distrKeeper, app.stakingKeeper)
 | 
			
		||||
	staking.RegisterInvariants(&app.crisisKeeper, app.stakingKeeper, app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper)
 | 
			
		||||
 | 
			
		||||
	app.mm.RegisterInvariants(&app.crisisKeeper)
 | 
			
		||||
	app.mm.RegisterRoutes(app.Router(), app.QueryRouter())
 | 
			
		||||
	// register message routes
 | 
			
		||||
	app.Router().
 | 
			
		||||
		AddRoute(bank.RouterKey, bank.NewHandler(app.bankKeeper)).
 | 
			
		||||
		AddRoute(staking.RouterKey, staking.NewHandler(app.stakingKeeper)).
 | 
			
		||||
		AddRoute(distr.RouterKey, distr.NewHandler(app.distrKeeper)).
 | 
			
		||||
		AddRoute(slashing.RouterKey, slashing.NewHandler(app.slashingKeeper)).
 | 
			
		||||
		AddRoute(gov.RouterKey, gov.NewHandler(app.govKeeper)).
 | 
			
		||||
		AddRoute(crisis.RouterKey, crisis.NewHandler(app.crisisKeeper))
 | 
			
		||||
 | 
			
		||||
	// initialize stores
 | 
			
		||||
	app.MountStores(app.keyMain, app.keyAccount, app.keyStaking, app.keyMint,
 | 
			
		||||
		app.keyDistr, app.keySlashing, app.keyGov, app.keyFeeCollection,
 | 
			
		||||
		app.keyParams, app.tkeyParams, app.tkeyStaking, app.tkeyDistr)
 | 
			
		||||
	app.QueryRouter().
 | 
			
		||||
		AddRoute(auth.QuerierRoute, auth.NewQuerier(app.accountKeeper)).
 | 
			
		||||
		AddRoute(distr.QuerierRoute, distr.NewQuerier(app.distrKeeper)).
 | 
			
		||||
		AddRoute(gov.QuerierRoute, gov.NewQuerier(app.govKeeper)).
 | 
			
		||||
		AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)).
 | 
			
		||||
		AddRoute(staking.QuerierRoute, staking.NewQuerier(app.stakingKeeper, app.cdc)).
 | 
			
		||||
		AddRoute(mint.QuerierRoute, mint.NewQuerier(app.mintKeeper))
 | 
			
		||||
 | 
			
		||||
	// initialize BaseApp
 | 
			
		||||
	app.SetInitChainer(app.InitChainer)
 | 
			
		||||
	app.MountStores(app.keyMain, app.keyAccount, app.keyStaking, app.keyMint, app.keyDistr,
 | 
			
		||||
		app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams,
 | 
			
		||||
		app.tkeyParams, app.tkeyStaking, app.tkeyDistr,
 | 
			
		||||
	)
 | 
			
		||||
	app.SetInitChainer(app.initChainer)
 | 
			
		||||
	app.SetBeginBlocker(app.BeginBlocker)
 | 
			
		||||
	app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper, auth.DefaultSigVerificationGasConsumer))
 | 
			
		||||
	app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper))
 | 
			
		||||
	app.SetEndBlocker(app.EndBlocker)
 | 
			
		||||
 | 
			
		||||
	if loadLatest {
 | 
			
		||||
@ -228,27 +201,209 @@ func NewApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
 | 
			
		||||
			cmn.Exit(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return app
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// application updates every begin block
 | 
			
		||||
func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
 | 
			
		||||
	return app.mm.BeginBlock(ctx, req)
 | 
			
		||||
// custom tx codec
 | 
			
		||||
func MakeCodec() *codec.Codec {
 | 
			
		||||
	var cdc = codec.New()
 | 
			
		||||
	bank.RegisterCodec(cdc)
 | 
			
		||||
	staking.RegisterCodec(cdc)
 | 
			
		||||
	distr.RegisterCodec(cdc)
 | 
			
		||||
	slashing.RegisterCodec(cdc)
 | 
			
		||||
	gov.RegisterCodec(cdc)
 | 
			
		||||
	auth.RegisterCodec(cdc)
 | 
			
		||||
	crisis.RegisterCodec(cdc)
 | 
			
		||||
	sdk.RegisterCodec(cdc)
 | 
			
		||||
	codec.RegisterCrypto(cdc)
 | 
			
		||||
	return cdc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// application updates every end block
 | 
			
		||||
func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
 | 
			
		||||
	return app.mm.EndBlock(ctx, req)
 | 
			
		||||
func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
 | 
			
		||||
	// mint new tokens for the previous block
 | 
			
		||||
	mint.BeginBlocker(ctx, app.mintKeeper)
 | 
			
		||||
 | 
			
		||||
	// distribute rewards for the previous block
 | 
			
		||||
	distr.BeginBlocker(ctx, req, app.distrKeeper)
 | 
			
		||||
 | 
			
		||||
	// slash anyone who double signed.
 | 
			
		||||
	// NOTE: This should happen after distr.BeginBlocker so that
 | 
			
		||||
	// there is nothing left over in the validator fee pool,
 | 
			
		||||
	// so as to keep the CanWithdrawInvariant invariant.
 | 
			
		||||
	// TODO: This should really happen at EndBlocker.
 | 
			
		||||
	tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
 | 
			
		||||
 | 
			
		||||
	return abci.ResponseBeginBlock{
 | 
			
		||||
		Tags: tags.ToKVPairs(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// application update at chain initialization
 | 
			
		||||
func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
 | 
			
		||||
// application updates every end block
 | 
			
		||||
// nolint: unparam
 | 
			
		||||
func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
 | 
			
		||||
	tags := gov.EndBlocker(ctx, app.govKeeper)
 | 
			
		||||
	validatorUpdates, endBlockerTags := staking.EndBlocker(ctx, app.stakingKeeper)
 | 
			
		||||
	tags = append(tags, endBlockerTags...)
 | 
			
		||||
 | 
			
		||||
	if app.invCheckPeriod != 0 && ctx.BlockHeight()%int64(app.invCheckPeriod) == 0 {
 | 
			
		||||
		app.assertRuntimeInvariants()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return abci.ResponseEndBlock{
 | 
			
		||||
		ValidatorUpdates: validatorUpdates,
 | 
			
		||||
		Tags:             tags,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// initialize store from a genesis state
 | 
			
		||||
func (app *App) initFromGenesisState(ctx sdk.Context, genesisState GenesisState) []abci.ValidatorUpdate {
 | 
			
		||||
	genesisState.Sanitize()
 | 
			
		||||
 | 
			
		||||
	// load the accounts
 | 
			
		||||
	for _, gacc := range genesisState.Accounts {
 | 
			
		||||
		acc := gacc.ToAccount()
 | 
			
		||||
		acc = app.accountKeeper.NewAccount(ctx, acc) // set account number
 | 
			
		||||
		app.accountKeeper.SetAccount(ctx, acc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// initialize distribution (must happen before staking)
 | 
			
		||||
	distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)
 | 
			
		||||
 | 
			
		||||
	// load the initial staking information
 | 
			
		||||
	validators, err := staking.InitGenesis(ctx, app.stakingKeeper, genesisState.StakingData)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err) // TODO find a way to do this w/o panics
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// initialize module-specific stores
 | 
			
		||||
	auth.InitGenesis(ctx, app.accountKeeper, app.feeCollectionKeeper, genesisState.AuthData)
 | 
			
		||||
	bank.InitGenesis(ctx, app.bankKeeper, genesisState.BankData)
 | 
			
		||||
	slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakingData.Validators.ToSDKValidators())
 | 
			
		||||
	gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
 | 
			
		||||
	crisis.InitGenesis(ctx, app.crisisKeeper, genesisState.CrisisData)
 | 
			
		||||
	mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
 | 
			
		||||
 | 
			
		||||
	// validate genesis state
 | 
			
		||||
	if err := ValidateGenesisState(genesisState); err != nil {
 | 
			
		||||
		panic(err) // TODO find a way to do this w/o panics
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(genesisState.GenTxs) > 0 {
 | 
			
		||||
		for _, genTx := range genesisState.GenTxs {
 | 
			
		||||
			var tx auth.StdTx
 | 
			
		||||
			err = app.cdc.UnmarshalJSON(genTx, &tx)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err)
 | 
			
		||||
			}
 | 
			
		||||
			bz := app.cdc.MustMarshalBinaryLengthPrefixed(tx)
 | 
			
		||||
			res := app.BaseApp.DeliverTx(bz)
 | 
			
		||||
			if !res.IsOK() {
 | 
			
		||||
				panic(res.Log)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		validators = app.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
 | 
			
		||||
	}
 | 
			
		||||
	return validators
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// custom logic for app initialization
 | 
			
		||||
func (app *App) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
 | 
			
		||||
	stateJSON := req.AppStateBytes
 | 
			
		||||
	// TODO is this now the whole genesis file?
 | 
			
		||||
 | 
			
		||||
	var genesisState GenesisState
 | 
			
		||||
	app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState)
 | 
			
		||||
	return app.mm.InitGenesis(ctx, genesisState)
 | 
			
		||||
	err := app.cdc.UnmarshalJSON(stateJSON, &genesisState)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
 | 
			
		||||
		// return sdk.ErrGenesisParse("").TraceCause(err, "")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	validators := app.initFromGenesisState(ctx, genesisState)
 | 
			
		||||
 | 
			
		||||
	// sanity check
 | 
			
		||||
	if len(req.Validators) > 0 {
 | 
			
		||||
		if len(req.Validators) != len(validators) {
 | 
			
		||||
			panic(fmt.Errorf("len(RequestInitChain.Validators) != len(validators) (%d != %d)",
 | 
			
		||||
				len(req.Validators), len(validators)))
 | 
			
		||||
		}
 | 
			
		||||
		sort.Sort(abci.ValidatorUpdates(req.Validators))
 | 
			
		||||
		sort.Sort(abci.ValidatorUpdates(validators))
 | 
			
		||||
		for i, val := range validators {
 | 
			
		||||
			if !val.Equal(req.Validators[i]) {
 | 
			
		||||
				panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// assert runtime invariants
 | 
			
		||||
	app.assertRuntimeInvariants()
 | 
			
		||||
 | 
			
		||||
	return abci.ResponseInitChain{
 | 
			
		||||
		Validators: validators,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// load a particular height
 | 
			
		||||
func (app *App) LoadHeight(height int64) error {
 | 
			
		||||
	return app.LoadVersion(height, app.keyMain)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ______________________________________________________________________________________________
 | 
			
		||||
 | 
			
		||||
var _ sdk.StakingHooks = StakingHooks{}
 | 
			
		||||
 | 
			
		||||
// StakingHooks contains combined distribution and slashing hooks needed for the
 | 
			
		||||
// staking module.
 | 
			
		||||
type StakingHooks struct {
 | 
			
		||||
	dh distr.Hooks
 | 
			
		||||
	sh slashing.Hooks
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStakingHooks(dh distr.Hooks, sh slashing.Hooks) StakingHooks {
 | 
			
		||||
	return StakingHooks{dh, sh}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nolint
 | 
			
		||||
func (h StakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.AfterValidatorCreated(ctx, valAddr)
 | 
			
		||||
	h.sh.AfterValidatorCreated(ctx, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.BeforeValidatorModified(ctx, valAddr)
 | 
			
		||||
	h.sh.BeforeValidatorModified(ctx, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.AfterValidatorRemoved(ctx, consAddr, valAddr)
 | 
			
		||||
	h.sh.AfterValidatorRemoved(ctx, consAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.AfterValidatorBonded(ctx, consAddr, valAddr)
 | 
			
		||||
	h.sh.AfterValidatorBonded(ctx, consAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
 | 
			
		||||
	h.sh.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.BeforeDelegationCreated(ctx, delAddr, valAddr)
 | 
			
		||||
	h.sh.BeforeDelegationCreated(ctx, delAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
 | 
			
		||||
	h.sh.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.BeforeDelegationRemoved(ctx, delAddr, valAddr)
 | 
			
		||||
	h.sh.BeforeDelegationRemoved(ctx, delAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
 | 
			
		||||
	h.dh.AfterDelegationModified(ctx, delAddr, valAddr)
 | 
			
		||||
	h.sh.AfterDelegationModified(ctx, delAddr, valAddr)
 | 
			
		||||
}
 | 
			
		||||
func (h StakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) {
 | 
			
		||||
	h.dh.BeforeValidatorSlashed(ctx, valAddr, fraction)
 | 
			
		||||
	h.sh.BeforeValidatorSlashed(ctx, valAddr, fraction)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								app/app_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								app/app_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/crisis"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/db"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/log"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/gov"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/mint"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/slashing"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
 | 
			
		||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func setGenesis(app *App, accs ...*auth.BaseAccount) error {
 | 
			
		||||
	genaccs := make([]GenesisAccount, len(accs))
 | 
			
		||||
	for i, acc := range accs {
 | 
			
		||||
		genaccs[i] = NewGenesisAccount(acc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	genesisState := NewGenesisState(
 | 
			
		||||
		genaccs,
 | 
			
		||||
		auth.DefaultGenesisState(),
 | 
			
		||||
		bank.DefaultGenesisState(),
 | 
			
		||||
		staking.DefaultGenesisState(),
 | 
			
		||||
		mint.DefaultGenesisState(),
 | 
			
		||||
		distr.DefaultGenesisState(),
 | 
			
		||||
		gov.DefaultGenesisState(),
 | 
			
		||||
		crisis.DefaultGenesisState(),
 | 
			
		||||
		slashing.DefaultGenesisState(),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	stateBytes, err := codec.MarshalJSONIndent(app.cdc, genesisState)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Initialize the chain
 | 
			
		||||
	vals := []abci.ValidatorUpdate{}
 | 
			
		||||
	app.InitChain(abci.RequestInitChain{Validators: vals, AppStateBytes: stateBytes})
 | 
			
		||||
	app.Commit()
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestExport(t *testing.T) {
 | 
			
		||||
	db := db.NewMemDB()
 | 
			
		||||
	app := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, 0)
 | 
			
		||||
	setGenesis(app)
 | 
			
		||||
 | 
			
		||||
	// Making a new app object with the db, so that initchain hasn't been called
 | 
			
		||||
	newApp := NewApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, 0)
 | 
			
		||||
	_, _, err := newApp.ExportAppStateAndValidators(false, []string{})
 | 
			
		||||
	require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								app/benchmarks/txsize_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/benchmarks/txsize_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// This will fail half the time with the second output being 173
 | 
			
		||||
// This is due to secp256k1 signatures not being constant size.
 | 
			
		||||
// nolint: vet
 | 
			
		||||
func ExampleTxSendSize() {
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
	var gas uint64 = 1
 | 
			
		||||
 | 
			
		||||
	priv1 := secp256k1.GenPrivKeySecp256k1([]byte{0})
 | 
			
		||||
	addr1 := sdk.AccAddress(priv1.PubKey().Address())
 | 
			
		||||
	priv2 := secp256k1.GenPrivKeySecp256k1([]byte{1})
 | 
			
		||||
	addr2 := sdk.AccAddress(priv2.PubKey().Address())
 | 
			
		||||
	coins := sdk.Coins{sdk.NewCoin("denom", sdk.NewInt(10))}
 | 
			
		||||
	msg1 := bank.MsgMultiSend{
 | 
			
		||||
		Inputs:  []bank.Input{bank.NewInput(addr1, coins)},
 | 
			
		||||
		Outputs: []bank.Output{bank.NewOutput(addr2, coins)},
 | 
			
		||||
	}
 | 
			
		||||
	fee := auth.NewStdFee(gas, coins)
 | 
			
		||||
	signBytes := auth.StdSignBytes("example-chain-ID",
 | 
			
		||||
		1, 1, fee, []sdk.Msg{msg1}, "")
 | 
			
		||||
	sig, _ := priv1.Sign(signBytes)
 | 
			
		||||
	sigs := []auth.StdSignature{{nil, sig}}
 | 
			
		||||
	tx := auth.NewStdTx([]sdk.Msg{msg1}, fee, sigs, "")
 | 
			
		||||
	fmt.Println(len(cdc.MustMarshalBinaryBare([]sdk.Msg{msg1})))
 | 
			
		||||
	fmt.Println(len(cdc.MustMarshalBinaryBare(tx)))
 | 
			
		||||
	// output: 80
 | 
			
		||||
	// 169
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,3 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
@ -12,13 +9,19 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/crisis"
 | 
			
		||||
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/gov"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/mint"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/slashing"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// export the state of the app for a genesis file
 | 
			
		||||
func (app *App) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []string,
 | 
			
		||||
) (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
 | 
			
		||||
func (app *App) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []string) (
 | 
			
		||||
	appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
 | 
			
		||||
 | 
			
		||||
	// as if they could withdraw from the start of the next block
 | 
			
		||||
	ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
 | 
			
		||||
@ -27,7 +30,26 @@ func (app *App) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []
 | 
			
		||||
		app.prepForZeroHeightGenesis(ctx, jailWhiteList)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	genState := app.mm.ExportGenesis(ctx)
 | 
			
		||||
	// iterate to get the accounts
 | 
			
		||||
	accounts := []GenesisAccount{}
 | 
			
		||||
	appendAccount := func(acc auth.Account) (stop bool) {
 | 
			
		||||
		account := NewGenesisAccountI(acc)
 | 
			
		||||
		accounts = append(accounts, account)
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	app.accountKeeper.IterateAccounts(ctx, appendAccount)
 | 
			
		||||
 | 
			
		||||
	genState := NewGenesisState(
 | 
			
		||||
		accounts,
 | 
			
		||||
		auth.ExportGenesis(ctx, app.accountKeeper, app.feeCollectionKeeper),
 | 
			
		||||
		bank.ExportGenesis(ctx, app.bankKeeper),
 | 
			
		||||
		staking.ExportGenesis(ctx, app.stakingKeeper),
 | 
			
		||||
		mint.ExportGenesis(ctx, app.mintKeeper),
 | 
			
		||||
		distr.ExportGenesis(ctx, app.distrKeeper),
 | 
			
		||||
		gov.ExportGenesis(ctx, app.govKeeper),
 | 
			
		||||
		crisis.ExportGenesis(ctx, app.crisisKeeper),
 | 
			
		||||
		slashing.ExportGenesis(ctx, app.slashingKeeper),
 | 
			
		||||
	)
 | 
			
		||||
	appState, err = codec.MarshalJSONIndent(app.cdc, genState)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
@ -37,8 +59,6 @@ func (app *App) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// prepare for fresh start at zero height
 | 
			
		||||
// NOTE zero height genesis is a temporary feature which will be deprecated
 | 
			
		||||
//      in favour of export at a block height
 | 
			
		||||
func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) {
 | 
			
		||||
	applyWhiteList := false
 | 
			
		||||
 | 
			
		||||
@ -58,12 +78,12 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Just to be safe, assert the invariants on current state. */
 | 
			
		||||
	app.crisisKeeper.AssertInvariants(ctx, app.Logger())
 | 
			
		||||
	app.assertRuntimeInvariantsOnContext(ctx)
 | 
			
		||||
 | 
			
		||||
	/* Handle fee distribution state. */
 | 
			
		||||
 | 
			
		||||
	// withdraw all validator commission
 | 
			
		||||
	app.stakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) {
 | 
			
		||||
	app.stakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) {
 | 
			
		||||
		_, _ = app.distrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator())
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
@ -85,7 +105,7 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string
 | 
			
		||||
	ctx = ctx.WithBlockHeight(0)
 | 
			
		||||
 | 
			
		||||
	// reinitialize all validators
 | 
			
		||||
	app.stakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) {
 | 
			
		||||
	app.stakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) {
 | 
			
		||||
 | 
			
		||||
		// donate any unwithdrawn outstanding reward fraction tokens to the community pool
 | 
			
		||||
		scraps := app.distrKeeper.GetValidatorOutstandingRewards(ctx, val.GetOperator())
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										419
									
								
								app/genesis.go
									
									
									
									
									
								
							
							
						
						
									
										419
									
								
								app/genesis.go
									
									
									
									
									
								
							@ -1,22 +1,417 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/crisis"
 | 
			
		||||
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/gov"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/mint"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/slashing"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// The genesis state of the blockchain is represented here as a map of raw json
 | 
			
		||||
// messages key'd by a identifier string.
 | 
			
		||||
// The identifier is used to determine which module genesis information belongs
 | 
			
		||||
// to so it may be appropriately routed during init chain.
 | 
			
		||||
// Within this application default genesis information is retrieved from
 | 
			
		||||
// the ModuleBasicManager which populates json from each BasicModule
 | 
			
		||||
// object provided to it during init.
 | 
			
		||||
type GenesisState map[string]json.RawMessage
 | 
			
		||||
var (
 | 
			
		||||
	// bonded tokens given to genesis validators/accounts
 | 
			
		||||
	freeTokensPerAcc = sdk.TokensFromTendermintPower(150)
 | 
			
		||||
	defaultBondDenom = sdk.DefaultBondDenom
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// State to Unmarshal
 | 
			
		||||
type GenesisState struct {
 | 
			
		||||
	Accounts     []GenesisAccount      `json:"accounts"`
 | 
			
		||||
	AuthData     auth.GenesisState     `json:"auth"`
 | 
			
		||||
	BankData     bank.GenesisState     `json:"bank"`
 | 
			
		||||
	StakingData  staking.GenesisState  `json:"staking"`
 | 
			
		||||
	MintData     mint.GenesisState     `json:"mint"`
 | 
			
		||||
	DistrData    distr.GenesisState    `json:"distr"`
 | 
			
		||||
	GovData      gov.GenesisState      `json:"gov"`
 | 
			
		||||
	CrisisData   crisis.GenesisState   `json:"crisis"`
 | 
			
		||||
	SlashingData slashing.GenesisState `json:"slashing"`
 | 
			
		||||
	GenTxs       []json.RawMessage     `json:"gentxs"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewGenesisState(accounts []GenesisAccount, authData auth.GenesisState,
 | 
			
		||||
	bankData bank.GenesisState,
 | 
			
		||||
	stakingData staking.GenesisState, mintData mint.GenesisState,
 | 
			
		||||
	distrData distr.GenesisState, govData gov.GenesisState, crisisData crisis.GenesisState,
 | 
			
		||||
	slashingData slashing.GenesisState) GenesisState {
 | 
			
		||||
 | 
			
		||||
	return GenesisState{
 | 
			
		||||
		Accounts:     accounts,
 | 
			
		||||
		AuthData:     authData,
 | 
			
		||||
		BankData:     bankData,
 | 
			
		||||
		StakingData:  stakingData,
 | 
			
		||||
		MintData:     mintData,
 | 
			
		||||
		DistrData:    distrData,
 | 
			
		||||
		GovData:      govData,
 | 
			
		||||
		CrisisData:   crisisData,
 | 
			
		||||
		SlashingData: slashingData,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sanitize sorts accounts and coin sets.
 | 
			
		||||
func (gs GenesisState) Sanitize() {
 | 
			
		||||
	sort.Slice(gs.Accounts, func(i, j int) bool {
 | 
			
		||||
		return gs.Accounts[i].AccountNumber < gs.Accounts[j].AccountNumber
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	for _, acc := range gs.Accounts {
 | 
			
		||||
		acc.Coins = acc.Coins.Sort()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenesisAccount defines an account initialized at genesis.
 | 
			
		||||
type GenesisAccount struct {
 | 
			
		||||
	Address       sdk.AccAddress `json:"address"`
 | 
			
		||||
	Coins         sdk.Coins      `json:"coins"`
 | 
			
		||||
	Sequence      uint64         `json:"sequence_number"`
 | 
			
		||||
	AccountNumber uint64         `json:"account_number"`
 | 
			
		||||
 | 
			
		||||
	// vesting account fields
 | 
			
		||||
	OriginalVesting  sdk.Coins `json:"original_vesting"`  // total vesting coins upon initialization
 | 
			
		||||
	DelegatedFree    sdk.Coins `json:"delegated_free"`    // delegated vested coins at time of delegation
 | 
			
		||||
	DelegatedVesting sdk.Coins `json:"delegated_vesting"` // delegated vesting coins at time of delegation
 | 
			
		||||
	StartTime        int64     `json:"start_time"`        // vesting start time (UNIX Epoch time)
 | 
			
		||||
	EndTime          int64     `json:"end_time"`          // vesting end time (UNIX Epoch time)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
 | 
			
		||||
	return GenesisAccount{
 | 
			
		||||
		Address:       acc.Address,
 | 
			
		||||
		Coins:         acc.Coins,
 | 
			
		||||
		AccountNumber: acc.AccountNumber,
 | 
			
		||||
		Sequence:      acc.Sequence,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewGenesisAccountI(acc auth.Account) GenesisAccount {
 | 
			
		||||
	gacc := GenesisAccount{
 | 
			
		||||
		Address:       acc.GetAddress(),
 | 
			
		||||
		Coins:         acc.GetCoins(),
 | 
			
		||||
		AccountNumber: acc.GetAccountNumber(),
 | 
			
		||||
		Sequence:      acc.GetSequence(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vacc, ok := acc.(auth.VestingAccount)
 | 
			
		||||
	if ok {
 | 
			
		||||
		gacc.OriginalVesting = vacc.GetOriginalVesting()
 | 
			
		||||
		gacc.DelegatedFree = vacc.GetDelegatedFree()
 | 
			
		||||
		gacc.DelegatedVesting = vacc.GetDelegatedVesting()
 | 
			
		||||
		gacc.StartTime = vacc.GetStartTime()
 | 
			
		||||
		gacc.EndTime = vacc.GetEndTime()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gacc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// convert GenesisAccount to auth.BaseAccount
 | 
			
		||||
func (ga *GenesisAccount) ToAccount() auth.Account {
 | 
			
		||||
	bacc := &auth.BaseAccount{
 | 
			
		||||
		Address:       ga.Address,
 | 
			
		||||
		Coins:         ga.Coins.Sort(),
 | 
			
		||||
		AccountNumber: ga.AccountNumber,
 | 
			
		||||
		Sequence:      ga.Sequence,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !ga.OriginalVesting.IsZero() {
 | 
			
		||||
		baseVestingAcc := &auth.BaseVestingAccount{
 | 
			
		||||
			BaseAccount:      bacc,
 | 
			
		||||
			OriginalVesting:  ga.OriginalVesting,
 | 
			
		||||
			DelegatedFree:    ga.DelegatedFree,
 | 
			
		||||
			DelegatedVesting: ga.DelegatedVesting,
 | 
			
		||||
			EndTime:          ga.EndTime,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ga.StartTime != 0 && ga.EndTime != 0 {
 | 
			
		||||
			return &auth.ContinuousVestingAccount{
 | 
			
		||||
				BaseVestingAccount: baseVestingAcc,
 | 
			
		||||
				StartTime:          ga.StartTime,
 | 
			
		||||
			}
 | 
			
		||||
		} else if ga.EndTime != 0 {
 | 
			
		||||
			return &auth.DelayedVestingAccount{
 | 
			
		||||
				BaseVestingAccount: baseVestingAcc,
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			panic(fmt.Sprintf("invalid genesis vesting account: %+v", ga))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bacc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create the core parameters for genesis initialization for gaia
 | 
			
		||||
// note that the pubkey input is this machines pubkey
 | 
			
		||||
func AppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
 | 
			
		||||
	genesisState GenesisState, err error) {
 | 
			
		||||
 | 
			
		||||
	if err = cdc.UnmarshalJSON(genDoc.AppState, &genesisState); err != nil {
 | 
			
		||||
		return genesisState, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if there are no gen txs to be processed, return the default empty state
 | 
			
		||||
	if len(appGenTxs) == 0 {
 | 
			
		||||
		return genesisState, errors.New("there must be at least one genesis tx")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stakingData := genesisState.StakingData
 | 
			
		||||
	for i, genTx := range appGenTxs {
 | 
			
		||||
		var tx auth.StdTx
 | 
			
		||||
		if err := cdc.UnmarshalJSON(genTx, &tx); err != nil {
 | 
			
		||||
			return genesisState, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		msgs := tx.GetMsgs()
 | 
			
		||||
		if len(msgs) != 1 {
 | 
			
		||||
			return genesisState, errors.New(
 | 
			
		||||
				"must provide genesis StdTx with exactly 1 CreateValidator message")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, ok := msgs[0].(staking.MsgCreateValidator); !ok {
 | 
			
		||||
			return genesisState, fmt.Errorf(
 | 
			
		||||
				"Genesis transaction %v does not contain a MsgCreateValidator", i)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, acc := range genesisState.Accounts {
 | 
			
		||||
		for _, coin := range acc.Coins {
 | 
			
		||||
			if coin.Denom == genesisState.StakingData.Params.BondDenom {
 | 
			
		||||
				stakingData.Pool.NotBondedTokens = stakingData.Pool.NotBondedTokens.
 | 
			
		||||
					Add(coin.Amount) // increase the supply
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	genesisState.StakingData = stakingData
 | 
			
		||||
	genesisState.GenTxs = appGenTxs
 | 
			
		||||
 | 
			
		||||
	return genesisState, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultGenesisState generates the default state for gaia.
 | 
			
		||||
func NewDefaultGenesisState() GenesisState {
 | 
			
		||||
	return ModuleBasics.DefaultGenesis()
 | 
			
		||||
	return GenesisState{
 | 
			
		||||
		Accounts:     nil,
 | 
			
		||||
		AuthData:     auth.DefaultGenesisState(),
 | 
			
		||||
		BankData:     bank.DefaultGenesisState(),
 | 
			
		||||
		StakingData:  staking.DefaultGenesisState(),
 | 
			
		||||
		MintData:     mint.DefaultGenesisState(),
 | 
			
		||||
		DistrData:    distr.DefaultGenesisState(),
 | 
			
		||||
		GovData:      gov.DefaultGenesisState(),
 | 
			
		||||
		CrisisData:   crisis.DefaultGenesisState(),
 | 
			
		||||
		SlashingData: slashing.DefaultGenesisState(),
 | 
			
		||||
		GenTxs:       nil,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValidateGenesisState ensures that the genesis state obeys the expected invariants
 | 
			
		||||
// TODO: No validators are both bonded and jailed (#2088)
 | 
			
		||||
// TODO: Error if there is a duplicate validator (#1708)
 | 
			
		||||
// TODO: Ensure all state machine parameters are in genesis (#1704)
 | 
			
		||||
func ValidateGenesisState(genesisState GenesisState) error {
 | 
			
		||||
	if err := validateGenesisStateAccounts(genesisState.Accounts); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// skip stakingData validation as genesis is created from txs
 | 
			
		||||
	if len(genesisState.GenTxs) > 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := auth.ValidateGenesis(genesisState.AuthData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := bank.ValidateGenesis(genesisState.BankData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := staking.ValidateGenesis(genesisState.StakingData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := mint.ValidateGenesis(genesisState.MintData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := distr.ValidateGenesis(genesisState.DistrData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := gov.ValidateGenesis(genesisState.GovData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := crisis.ValidateGenesis(genesisState.CrisisData); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return slashing.ValidateGenesis(genesisState.SlashingData)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// validateGenesisStateAccounts performs validation of genesis accounts. It
 | 
			
		||||
// ensures that there are no duplicate accounts in the genesis state and any
 | 
			
		||||
// provided vesting accounts are valid.
 | 
			
		||||
func validateGenesisStateAccounts(accs []GenesisAccount) error {
 | 
			
		||||
	addrMap := make(map[string]bool, len(accs))
 | 
			
		||||
	for _, acc := range accs {
 | 
			
		||||
		addrStr := acc.Address.String()
 | 
			
		||||
 | 
			
		||||
		// disallow any duplicate accounts
 | 
			
		||||
		if _, ok := addrMap[addrStr]; ok {
 | 
			
		||||
			return fmt.Errorf("duplicate account found in genesis state; address: %s", addrStr)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// validate any vesting fields
 | 
			
		||||
		if !acc.OriginalVesting.IsZero() {
 | 
			
		||||
			if acc.EndTime == 0 {
 | 
			
		||||
				return fmt.Errorf("missing end time for vesting account; address: %s", addrStr)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if acc.StartTime >= acc.EndTime {
 | 
			
		||||
				return fmt.Errorf(
 | 
			
		||||
					"vesting start time must before end time; address: %s, start: %s, end: %s",
 | 
			
		||||
					addrStr,
 | 
			
		||||
					time.Unix(acc.StartTime, 0).UTC().Format(time.RFC3339),
 | 
			
		||||
					time.Unix(acc.EndTime, 0).UTC().Format(time.RFC3339),
 | 
			
		||||
				)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		addrMap[addrStr] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AppGenState but with JSON
 | 
			
		||||
func AppGenStateJSON(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) (
 | 
			
		||||
	appState json.RawMessage, err error) {
 | 
			
		||||
	// create the final app state
 | 
			
		||||
	genesisState, err := AppGenState(cdc, genDoc, appGenTxs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return codec.MarshalJSONIndent(cdc, genesisState)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CollectStdTxs processes and validates application's genesis StdTxs and returns
 | 
			
		||||
// the list of appGenTxs, and persistent peers required to generate genesis.json.
 | 
			
		||||
func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tmtypes.GenesisDoc) (
 | 
			
		||||
	appGenTxs []auth.StdTx, persistentPeers string, err error) {
 | 
			
		||||
 | 
			
		||||
	var fos []os.FileInfo
 | 
			
		||||
	fos, err = ioutil.ReadDir(genTxsDir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return appGenTxs, persistentPeers, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// prepare a map of all accounts in genesis state to then validate
 | 
			
		||||
	// against the validators addresses
 | 
			
		||||
	var appState GenesisState
 | 
			
		||||
	if err := cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil {
 | 
			
		||||
		return appGenTxs, persistentPeers, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	addrMap := make(map[string]GenesisAccount, len(appState.Accounts))
 | 
			
		||||
	for i := 0; i < len(appState.Accounts); i++ {
 | 
			
		||||
		acc := appState.Accounts[i]
 | 
			
		||||
		addrMap[acc.Address.String()] = acc
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// addresses and IPs (and port) validator server info
 | 
			
		||||
	var addressesIPs []string
 | 
			
		||||
 | 
			
		||||
	for _, fo := range fos {
 | 
			
		||||
		filename := filepath.Join(genTxsDir, fo.Name())
 | 
			
		||||
		if !fo.IsDir() && (filepath.Ext(filename) != ".json") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// get the genStdTx
 | 
			
		||||
		var jsonRawTx []byte
 | 
			
		||||
		if jsonRawTx, err = ioutil.ReadFile(filename); err != nil {
 | 
			
		||||
			return appGenTxs, persistentPeers, err
 | 
			
		||||
		}
 | 
			
		||||
		var genStdTx auth.StdTx
 | 
			
		||||
		if err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx); err != nil {
 | 
			
		||||
			return appGenTxs, persistentPeers, err
 | 
			
		||||
		}
 | 
			
		||||
		appGenTxs = append(appGenTxs, genStdTx)
 | 
			
		||||
 | 
			
		||||
		// the memo flag is used to store
 | 
			
		||||
		// the ip and node-id, for example this may be:
 | 
			
		||||
		// "528fd3df22b31f4969b05652bfe8f0fe921321d5@192.168.2.37:26656"
 | 
			
		||||
		nodeAddrIP := genStdTx.GetMemo()
 | 
			
		||||
		if len(nodeAddrIP) == 0 {
 | 
			
		||||
			return appGenTxs, persistentPeers, fmt.Errorf(
 | 
			
		||||
				"couldn't find node's address and IP in %s", fo.Name())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// genesis transactions must be single-message
 | 
			
		||||
		msgs := genStdTx.GetMsgs()
 | 
			
		||||
		if len(msgs) != 1 {
 | 
			
		||||
 | 
			
		||||
			return appGenTxs, persistentPeers, errors.New(
 | 
			
		||||
				"each genesis transaction must provide a single genesis message")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		msg := msgs[0].(staking.MsgCreateValidator)
 | 
			
		||||
		// validate delegator and validator addresses and funds against the accounts in the state
 | 
			
		||||
		delAddr := msg.DelegatorAddress.String()
 | 
			
		||||
		valAddr := sdk.AccAddress(msg.ValidatorAddress).String()
 | 
			
		||||
 | 
			
		||||
		delAcc, delOk := addrMap[delAddr]
 | 
			
		||||
		_, valOk := addrMap[valAddr]
 | 
			
		||||
 | 
			
		||||
		accsNotInGenesis := []string{}
 | 
			
		||||
		if !delOk {
 | 
			
		||||
			accsNotInGenesis = append(accsNotInGenesis, delAddr)
 | 
			
		||||
		}
 | 
			
		||||
		if !valOk {
 | 
			
		||||
			accsNotInGenesis = append(accsNotInGenesis, valAddr)
 | 
			
		||||
		}
 | 
			
		||||
		if len(accsNotInGenesis) != 0 {
 | 
			
		||||
			return appGenTxs, persistentPeers, fmt.Errorf(
 | 
			
		||||
				"account(s) %v not in genesis.json: %+v", strings.Join(accsNotInGenesis, " "), addrMap)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if delAcc.Coins.AmountOf(msg.Value.Denom).LT(msg.Value.Amount) {
 | 
			
		||||
			return appGenTxs, persistentPeers, fmt.Errorf(
 | 
			
		||||
				"insufficient fund for delegation %v: %v < %v",
 | 
			
		||||
				delAcc.Address, delAcc.Coins.AmountOf(msg.Value.Denom), msg.Value.Amount,
 | 
			
		||||
			)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// exclude itself from persistent peers
 | 
			
		||||
		if msg.Description.Moniker != moniker {
 | 
			
		||||
			addressesIPs = append(addressesIPs, nodeAddrIP)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Strings(addressesIPs)
 | 
			
		||||
	persistentPeers = strings.Join(addressesIPs, ",")
 | 
			
		||||
 | 
			
		||||
	return appGenTxs, persistentPeers, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount {
 | 
			
		||||
	accAuth := auth.NewBaseAccountWithAddress(addr)
 | 
			
		||||
	coins := sdk.Coins{
 | 
			
		||||
		sdk.NewCoin("footoken", sdk.NewInt(1000)),
 | 
			
		||||
		sdk.NewCoin(defaultBondDenom, freeTokensPerAcc),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	coins.Sort()
 | 
			
		||||
 | 
			
		||||
	accAuth.Coins = coins
 | 
			
		||||
	return NewGenesisAccount(&accAuth)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										188
									
								
								app/genesis_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								app/genesis_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,188 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto/ed25519"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
			
		||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	pk1   = ed25519.GenPrivKey().PubKey()
 | 
			
		||||
	pk2   = ed25519.GenPrivKey().PubKey()
 | 
			
		||||
	pk3   = ed25519.GenPrivKey().PubKey()
 | 
			
		||||
	addr1 = sdk.ValAddress(pk1.Address())
 | 
			
		||||
	addr2 = sdk.ValAddress(pk2.Address())
 | 
			
		||||
	addr3 = sdk.ValAddress(pk3.Address())
 | 
			
		||||
 | 
			
		||||
	emptyAddr   sdk.ValAddress
 | 
			
		||||
	emptyPubkey crypto.PubKey
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState {
 | 
			
		||||
	// start with the default staking genesis state
 | 
			
		||||
	appState := NewDefaultGenesisState()
 | 
			
		||||
	stakingData := appState.StakingData
 | 
			
		||||
	genAccs := make([]GenesisAccount, len(genTxs))
 | 
			
		||||
 | 
			
		||||
	for i, genTx := range genTxs {
 | 
			
		||||
		msgs := genTx.GetMsgs()
 | 
			
		||||
		require.Equal(t, 1, len(msgs))
 | 
			
		||||
		msg := msgs[0].(staking.MsgCreateValidator)
 | 
			
		||||
 | 
			
		||||
		acc := auth.NewBaseAccountWithAddress(sdk.AccAddress(msg.ValidatorAddress))
 | 
			
		||||
		acc.Coins = sdk.NewCoins(sdk.NewInt64Coin(defaultBondDenom, 150))
 | 
			
		||||
		genAccs[i] = NewGenesisAccount(&acc)
 | 
			
		||||
		stakingData.Pool.NotBondedTokens = stakingData.Pool.NotBondedTokens.Add(sdk.NewInt(150)) // increase the supply
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// create the final app state
 | 
			
		||||
	appState.Accounts = genAccs
 | 
			
		||||
	return appState
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestToAccount(t *testing.T) {
 | 
			
		||||
	priv := ed25519.GenPrivKey()
 | 
			
		||||
	addr := sdk.AccAddress(priv.PubKey().Address())
 | 
			
		||||
	authAcc := auth.NewBaseAccountWithAddress(addr)
 | 
			
		||||
	authAcc.SetCoins(sdk.NewCoins(sdk.NewInt64Coin(defaultBondDenom, 150)))
 | 
			
		||||
	genAcc := NewGenesisAccount(&authAcc)
 | 
			
		||||
	acc := genAcc.ToAccount()
 | 
			
		||||
	require.IsType(t, &auth.BaseAccount{}, acc)
 | 
			
		||||
	require.Equal(t, &authAcc, acc.(*auth.BaseAccount))
 | 
			
		||||
 | 
			
		||||
	vacc := auth.NewContinuousVestingAccount(
 | 
			
		||||
		&authAcc, time.Now().Unix(), time.Now().Add(24*time.Hour).Unix(),
 | 
			
		||||
	)
 | 
			
		||||
	genAcc = NewGenesisAccountI(vacc)
 | 
			
		||||
	acc = genAcc.ToAccount()
 | 
			
		||||
	require.IsType(t, &auth.ContinuousVestingAccount{}, acc)
 | 
			
		||||
	require.Equal(t, vacc, acc.(*auth.ContinuousVestingAccount))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAppGenTx(t *testing.T) {
 | 
			
		||||
	cdc := MakeCodec()
 | 
			
		||||
	_ = cdc
 | 
			
		||||
 | 
			
		||||
	//TODO test that key overwrite flags work / no overwrites if set off
 | 
			
		||||
	//TODO test validator created has provided pubkey
 | 
			
		||||
	//TODO test the account created has the correct pubkey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAppGenState(t *testing.T) {
 | 
			
		||||
	cdc := MakeCodec()
 | 
			
		||||
	_ = cdc
 | 
			
		||||
	var genDoc tmtypes.GenesisDoc
 | 
			
		||||
 | 
			
		||||
	// test unmarshalling error
 | 
			
		||||
	_, err := AppGenState(cdc, genDoc, []json.RawMessage{})
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	appState := makeGenesisState(t, []auth.StdTx{})
 | 
			
		||||
	genDoc.AppState, err = json.Marshal(appState)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	// test validation error
 | 
			
		||||
	_, err = AppGenState(cdc, genDoc, []json.RawMessage{})
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// TODO test must provide at least genesis transaction
 | 
			
		||||
	// TODO test with both one and two genesis transactions:
 | 
			
		||||
	// TODO        correct: genesis account created, canididates created, pool token variance
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
 | 
			
		||||
	desc := staking.NewDescription(name, "", "", "")
 | 
			
		||||
	comm := staking.CommissionMsg{}
 | 
			
		||||
	msg := staking.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(defaultBondDenom,
 | 
			
		||||
		50), desc, comm, sdk.OneInt())
 | 
			
		||||
	return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGenesisValidation(t *testing.T) {
 | 
			
		||||
	genTxs := []auth.StdTx{makeMsg("test-0", pk1), makeMsg("test-1", pk2)}
 | 
			
		||||
	dupGenTxs := []auth.StdTx{makeMsg("test-0", pk1), makeMsg("test-1", pk1)}
 | 
			
		||||
 | 
			
		||||
	// require duplicate accounts fails validation
 | 
			
		||||
	genesisState := makeGenesisState(t, dupGenTxs)
 | 
			
		||||
	err := ValidateGenesisState(genesisState)
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// require invalid vesting account fails validation (invalid end time)
 | 
			
		||||
	genesisState = makeGenesisState(t, genTxs)
 | 
			
		||||
	genesisState.Accounts[0].OriginalVesting = genesisState.Accounts[0].Coins
 | 
			
		||||
	err = ValidateGenesisState(genesisState)
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
	genesisState.Accounts[0].StartTime = 1548888000
 | 
			
		||||
	genesisState.Accounts[0].EndTime = 1548775410
 | 
			
		||||
	err = ValidateGenesisState(genesisState)
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// require bonded + jailed validator fails validation
 | 
			
		||||
	genesisState = makeGenesisState(t, genTxs)
 | 
			
		||||
	val1 := staking.NewValidator(addr1, pk1, staking.NewDescription("test #2", "", "", ""))
 | 
			
		||||
	val1.Jailed = true
 | 
			
		||||
	val1.Status = sdk.Bonded
 | 
			
		||||
	genesisState.StakingData.Validators = append(genesisState.StakingData.Validators, val1)
 | 
			
		||||
	err = ValidateGenesisState(genesisState)
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	// require duplicate validator fails validation
 | 
			
		||||
	val1.Jailed = false
 | 
			
		||||
	genesisState = makeGenesisState(t, genTxs)
 | 
			
		||||
	val2 := staking.NewValidator(addr1, pk1, staking.NewDescription("test #3", "", "", ""))
 | 
			
		||||
	genesisState.StakingData.Validators = append(genesisState.StakingData.Validators, val1)
 | 
			
		||||
	genesisState.StakingData.Validators = append(genesisState.StakingData.Validators, val2)
 | 
			
		||||
	err = ValidateGenesisState(genesisState)
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewDefaultGenesisAccount(t *testing.T) {
 | 
			
		||||
	addr := secp256k1.GenPrivKeySecp256k1([]byte("")).PubKey().Address()
 | 
			
		||||
	acc := NewDefaultGenesisAccount(sdk.AccAddress(addr))
 | 
			
		||||
	require.Equal(t, sdk.NewInt(1000), acc.Coins.AmountOf("footoken"))
 | 
			
		||||
	require.Equal(t, sdk.TokensFromTendermintPower(150), acc.Coins.AmountOf(defaultBondDenom))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGenesisStateSanitize(t *testing.T) {
 | 
			
		||||
	genesisState := makeGenesisState(t, nil)
 | 
			
		||||
	require.Nil(t, ValidateGenesisState(genesisState))
 | 
			
		||||
 | 
			
		||||
	addr1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
 | 
			
		||||
	authAcc1 := auth.NewBaseAccountWithAddress(addr1)
 | 
			
		||||
	authAcc1.SetCoins(sdk.Coins{
 | 
			
		||||
		sdk.NewInt64Coin("bcoin", 150),
 | 
			
		||||
		sdk.NewInt64Coin("acoin", 150),
 | 
			
		||||
	})
 | 
			
		||||
	authAcc1.SetAccountNumber(1)
 | 
			
		||||
	genAcc1 := NewGenesisAccount(&authAcc1)
 | 
			
		||||
 | 
			
		||||
	addr2 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address())
 | 
			
		||||
	authAcc2 := auth.NewBaseAccountWithAddress(addr2)
 | 
			
		||||
	authAcc2.SetCoins(sdk.Coins{
 | 
			
		||||
		sdk.NewInt64Coin("acoin", 150),
 | 
			
		||||
		sdk.NewInt64Coin("bcoin", 150),
 | 
			
		||||
	})
 | 
			
		||||
	genAcc2 := NewGenesisAccount(&authAcc2)
 | 
			
		||||
 | 
			
		||||
	genesisState.Accounts = []GenesisAccount{genAcc1, genAcc2}
 | 
			
		||||
	require.True(t, genesisState.Accounts[0].AccountNumber > genesisState.Accounts[1].AccountNumber)
 | 
			
		||||
	require.Equal(t, genesisState.Accounts[0].Coins[0].Denom, "bcoin")
 | 
			
		||||
	require.Equal(t, genesisState.Accounts[0].Coins[1].Denom, "acoin")
 | 
			
		||||
	require.Equal(t, genesisState.Accounts[1].Address, addr2)
 | 
			
		||||
	genesisState.Sanitize()
 | 
			
		||||
	require.False(t, genesisState.Accounts[0].AccountNumber > genesisState.Accounts[1].AccountNumber)
 | 
			
		||||
	require.Equal(t, genesisState.Accounts[1].Address, addr1)
 | 
			
		||||
	require.Equal(t, genesisState.Accounts[1].Coins[0].Denom, "acoin")
 | 
			
		||||
	require.Equal(t, genesisState.Accounts[1].Coins[1].Denom, "bcoin")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								app/invariants.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/invariants.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (app *App) assertRuntimeInvariants() {
 | 
			
		||||
	ctx := app.NewContext(false, abci.Header{Height: app.LastBlockHeight() + 1})
 | 
			
		||||
	app.assertRuntimeInvariantsOnContext(ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (app *App) assertRuntimeInvariantsOnContext(ctx sdk.Context) {
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	invarRoutes := app.crisisKeeper.Routes()
 | 
			
		||||
	for _, ir := range invarRoutes {
 | 
			
		||||
		if err := ir.Invar(ctx); err != nil {
 | 
			
		||||
			panic(fmt.Errorf("invariant broken: %s\n"+
 | 
			
		||||
				"\tCRITICAL please submit the following transaction:\n"+
 | 
			
		||||
				"\t\t kvcli tx crisis invariant-broken %v %v", err, ir.ModuleName, ir.Route))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	end := time.Now()
 | 
			
		||||
	diff := end.Sub(start)
 | 
			
		||||
	app.BaseApp.Logger().With("module", "invariants").Info(
 | 
			
		||||
		"Asserted all invariants", "duration", diff, "height", app.LastBlockHeight())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										564
									
								
								app/sim_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										564
									
								
								app/sim_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,564 @@
 | 
			
		||||
package app
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
 | 
			
		||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
			
		||||
	dbm "github.com/tendermint/tendermint/libs/db"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/log"
 | 
			
		||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/baseapp"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
 | 
			
		||||
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
 | 
			
		||||
	distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/gov"
 | 
			
		||||
	govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/mint"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/simulation"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/slashing"
 | 
			
		||||
	slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
	stakingsim "github.com/cosmos/cosmos-sdk/x/staking/simulation"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	genesisFile string
 | 
			
		||||
	seed        int64
 | 
			
		||||
	numBlocks   int
 | 
			
		||||
	blockSize   int
 | 
			
		||||
	enabled     bool
 | 
			
		||||
	verbose     bool
 | 
			
		||||
	lean        bool
 | 
			
		||||
	commit      bool
 | 
			
		||||
	period      int
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	flag.StringVar(&genesisFile, "SimulationGenesis", "", "custom simulation genesis file")
 | 
			
		||||
	flag.Int64Var(&seed, "SimulationSeed", 42, "simulation random seed")
 | 
			
		||||
	flag.IntVar(&numBlocks, "SimulationNumBlocks", 500, "number of blocks")
 | 
			
		||||
	flag.IntVar(&blockSize, "SimulationBlockSize", 200, "operations per block")
 | 
			
		||||
	flag.BoolVar(&enabled, "SimulationEnabled", false, "enable the simulation")
 | 
			
		||||
	flag.BoolVar(&verbose, "SimulationVerbose", false, "verbose log output")
 | 
			
		||||
	flag.BoolVar(&lean, "SimulationLean", false, "lean simulation log output")
 | 
			
		||||
	flag.BoolVar(&commit, "SimulationCommit", false, "have the simulation commit")
 | 
			
		||||
	flag.IntVar(&period, "SimulationPeriod", 1, "run slow invariants only once every period assertions")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// helper function for populating input for SimulateFromSeed
 | 
			
		||||
func getSimulateFromSeedInput(tb testing.TB, app *App) (
 | 
			
		||||
	testing.TB, *baseapp.BaseApp, simulation.AppStateFn, int64,
 | 
			
		||||
	simulation.WeightedOperations, sdk.Invariants, int, int, bool, bool) {
 | 
			
		||||
 | 
			
		||||
	return tb, app.BaseApp, appStateFn, seed,
 | 
			
		||||
		testAndRunTxs(app), invariants(app), numBlocks, blockSize, commit, lean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func appStateFromGenesisFileFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time) (json.RawMessage, []simulation.Account, string) {
 | 
			
		||||
	var genesis tmtypes.GenesisDoc
 | 
			
		||||
	cdc := MakeCodec()
 | 
			
		||||
	bytes, err := ioutil.ReadFile(genesisFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	cdc.MustUnmarshalJSON(bytes, &genesis)
 | 
			
		||||
	var appState GenesisState
 | 
			
		||||
	cdc.MustUnmarshalJSON(genesis.AppState, &appState)
 | 
			
		||||
	var newAccs []simulation.Account
 | 
			
		||||
	for _, acc := range appState.Accounts {
 | 
			
		||||
		// Pick a random private key, since we don't know the actual key
 | 
			
		||||
		// This should be fine as it's only used for mock Tendermint validators
 | 
			
		||||
		// and these keys are never actually used to sign by mock Tendermint.
 | 
			
		||||
		privkeySeed := make([]byte, 15)
 | 
			
		||||
		r.Read(privkeySeed)
 | 
			
		||||
		privKey := secp256k1.GenPrivKeySecp256k1(privkeySeed)
 | 
			
		||||
		newAccs = append(newAccs, simulation.Account{privKey, privKey.PubKey(), acc.Address})
 | 
			
		||||
	}
 | 
			
		||||
	return genesis.AppState, newAccs, genesis.ChainID
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func appStateRandomizedFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time) (json.RawMessage, []simulation.Account, string) {
 | 
			
		||||
 | 
			
		||||
	var genesisAccounts []GenesisAccount
 | 
			
		||||
 | 
			
		||||
	amount := int64(r.Intn(1e12))
 | 
			
		||||
	numInitiallyBonded := int64(r.Intn(250))
 | 
			
		||||
	numAccs := int64(len(accs))
 | 
			
		||||
	if numInitiallyBonded > numAccs {
 | 
			
		||||
		numInitiallyBonded = numAccs
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated parameters for simulated genesis:\n"+
 | 
			
		||||
		"\t{amount of stake per account: %v, initially bonded validators: %v}\n",
 | 
			
		||||
		amount, numInitiallyBonded)
 | 
			
		||||
 | 
			
		||||
	// randomly generate some genesis accounts
 | 
			
		||||
	for i, acc := range accs {
 | 
			
		||||
		coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(amount))}
 | 
			
		||||
		bacc := auth.NewBaseAccountWithAddress(acc.Address)
 | 
			
		||||
		bacc.SetCoins(coins)
 | 
			
		||||
 | 
			
		||||
		var gacc GenesisAccount
 | 
			
		||||
 | 
			
		||||
		// Only consider making a vesting account once the initial bonded validator
 | 
			
		||||
		// set is exhausted due to needing to track DelegatedVesting.
 | 
			
		||||
		if int64(i) > numInitiallyBonded && r.Intn(100) < 50 {
 | 
			
		||||
			var (
 | 
			
		||||
				vacc    auth.VestingAccount
 | 
			
		||||
				endTime int64
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
			startTime := genesisTimestamp.Unix()
 | 
			
		||||
 | 
			
		||||
			// Allow for some vesting accounts to vest very quickly while others very
 | 
			
		||||
			// slowly.
 | 
			
		||||
			if r.Intn(100) < 50 {
 | 
			
		||||
				endTime = int64(simulation.RandIntBetween(r, int(startTime), int(startTime+(60*60*24*30))))
 | 
			
		||||
			} else {
 | 
			
		||||
				endTime = int64(simulation.RandIntBetween(r, int(startTime), int(startTime+(60*60*12))))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if startTime == endTime {
 | 
			
		||||
				endTime += 1
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if r.Intn(100) < 50 {
 | 
			
		||||
				vacc = auth.NewContinuousVestingAccount(&bacc, startTime, endTime)
 | 
			
		||||
			} else {
 | 
			
		||||
				vacc = auth.NewDelayedVestingAccount(&bacc, endTime)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			gacc = NewGenesisAccountI(vacc)
 | 
			
		||||
		} else {
 | 
			
		||||
			gacc = NewGenesisAccount(&bacc)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		genesisAccounts = append(genesisAccounts, gacc)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	authGenesis := auth.GenesisState{
 | 
			
		||||
		Params: auth.Params{
 | 
			
		||||
			MaxMemoCharacters:      uint64(simulation.RandIntBetween(r, 100, 200)),
 | 
			
		||||
			TxSigLimit:             uint64(r.Intn(7) + 1),
 | 
			
		||||
			TxSizeCostPerByte:      uint64(simulation.RandIntBetween(r, 5, 15)),
 | 
			
		||||
			SigVerifyCostED25519:   uint64(simulation.RandIntBetween(r, 500, 1000)),
 | 
			
		||||
			SigVerifyCostSecp256k1: uint64(simulation.RandIntBetween(r, 500, 1000)),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated auth parameters:\n\t%+v\n", authGenesis)
 | 
			
		||||
 | 
			
		||||
	bankGenesis := bank.NewGenesisState(r.Int63n(2) == 0)
 | 
			
		||||
	fmt.Printf("Selected randomly generated bank parameters:\n\t%+v\n", bankGenesis)
 | 
			
		||||
 | 
			
		||||
	// Random genesis states
 | 
			
		||||
	vp := time.Duration(r.Intn(2*172800)) * time.Second
 | 
			
		||||
	govGenesis := gov.GenesisState{
 | 
			
		||||
		StartingProposalID: uint64(r.Intn(100)),
 | 
			
		||||
		DepositParams: gov.DepositParams{
 | 
			
		||||
			MinDeposit:       sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, int64(r.Intn(1e3)))},
 | 
			
		||||
			MaxDepositPeriod: vp,
 | 
			
		||||
		},
 | 
			
		||||
		VotingParams: gov.VotingParams{
 | 
			
		||||
			VotingPeriod: vp,
 | 
			
		||||
		},
 | 
			
		||||
		TallyParams: gov.TallyParams{
 | 
			
		||||
			Quorum:    sdk.NewDecWithPrec(334, 3),
 | 
			
		||||
			Threshold: sdk.NewDecWithPrec(5, 1),
 | 
			
		||||
			Veto:      sdk.NewDecWithPrec(334, 3),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated governance parameters:\n\t%+v\n", govGenesis)
 | 
			
		||||
 | 
			
		||||
	stakingGenesis := staking.GenesisState{
 | 
			
		||||
		Pool: staking.InitialPool(),
 | 
			
		||||
		Params: staking.Params{
 | 
			
		||||
			UnbondingTime: time.Duration(simulation.RandIntBetween(r, 60, 60*60*24*3*2)) * time.Second,
 | 
			
		||||
			MaxValidators: uint16(r.Intn(250) + 1),
 | 
			
		||||
			BondDenom:     sdk.DefaultBondDenom,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated staking parameters:\n\t%+v\n", stakingGenesis)
 | 
			
		||||
 | 
			
		||||
	slashingGenesis := slashing.GenesisState{
 | 
			
		||||
		Params: slashing.Params{
 | 
			
		||||
			MaxEvidenceAge:          stakingGenesis.Params.UnbondingTime,
 | 
			
		||||
			SignedBlocksWindow:      int64(simulation.RandIntBetween(r, 10, 1000)),
 | 
			
		||||
			MinSignedPerWindow:      sdk.NewDecWithPrec(int64(r.Intn(10)), 1),
 | 
			
		||||
			DowntimeJailDuration:    time.Duration(simulation.RandIntBetween(r, 60, 60*60*24)) * time.Second,
 | 
			
		||||
			SlashFractionDoubleSign: sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(50) + 1))),
 | 
			
		||||
			SlashFractionDowntime:   sdk.NewDec(1).Quo(sdk.NewDec(int64(r.Intn(200) + 1))),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated slashing parameters:\n\t%+v\n", slashingGenesis)
 | 
			
		||||
 | 
			
		||||
	mintGenesis := mint.GenesisState{
 | 
			
		||||
		Minter: mint.InitialMinter(
 | 
			
		||||
			sdk.NewDecWithPrec(int64(r.Intn(99)), 2)),
 | 
			
		||||
		Params: mint.NewParams(
 | 
			
		||||
			sdk.DefaultBondDenom,
 | 
			
		||||
			sdk.NewDecWithPrec(int64(r.Intn(99)), 2),
 | 
			
		||||
			sdk.NewDecWithPrec(20, 2),
 | 
			
		||||
			sdk.NewDecWithPrec(7, 2),
 | 
			
		||||
			sdk.NewDecWithPrec(67, 2),
 | 
			
		||||
			uint64(60*60*8766/5)),
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated minting parameters:\n\t%+v\n", mintGenesis)
 | 
			
		||||
 | 
			
		||||
	var validators []staking.Validator
 | 
			
		||||
	var delegations []staking.Delegation
 | 
			
		||||
 | 
			
		||||
	valAddrs := make([]sdk.ValAddress, numInitiallyBonded)
 | 
			
		||||
	for i := 0; i < int(numInitiallyBonded); i++ {
 | 
			
		||||
		valAddr := sdk.ValAddress(accs[i].Address)
 | 
			
		||||
		valAddrs[i] = valAddr
 | 
			
		||||
 | 
			
		||||
		validator := staking.NewValidator(valAddr, accs[i].PubKey, staking.Description{})
 | 
			
		||||
		validator.Tokens = sdk.NewInt(amount)
 | 
			
		||||
		validator.DelegatorShares = sdk.NewDec(amount)
 | 
			
		||||
		delegation := staking.Delegation{accs[i].Address, valAddr, sdk.NewDec(amount)}
 | 
			
		||||
		validators = append(validators, validator)
 | 
			
		||||
		delegations = append(delegations, delegation)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stakingGenesis.Pool.NotBondedTokens = sdk.NewInt((amount * numAccs) + (numInitiallyBonded * amount))
 | 
			
		||||
	stakingGenesis.Validators = validators
 | 
			
		||||
	stakingGenesis.Delegations = delegations
 | 
			
		||||
 | 
			
		||||
	distrGenesis := distr.GenesisState{
 | 
			
		||||
		FeePool:             distr.InitialFeePool(),
 | 
			
		||||
		CommunityTax:        sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2)),
 | 
			
		||||
		BaseProposerReward:  sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2)),
 | 
			
		||||
		BonusProposerReward: sdk.NewDecWithPrec(1, 2).Add(sdk.NewDecWithPrec(int64(r.Intn(30)), 2)),
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Printf("Selected randomly generated distribution parameters:\n\t%+v\n", distrGenesis)
 | 
			
		||||
 | 
			
		||||
	genesis := GenesisState{
 | 
			
		||||
		Accounts:     genesisAccounts,
 | 
			
		||||
		AuthData:     authGenesis,
 | 
			
		||||
		BankData:     bankGenesis,
 | 
			
		||||
		StakingData:  stakingGenesis,
 | 
			
		||||
		MintData:     mintGenesis,
 | 
			
		||||
		DistrData:    distrGenesis,
 | 
			
		||||
		SlashingData: slashingGenesis,
 | 
			
		||||
		GovData:      govGenesis,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Marshal genesis
 | 
			
		||||
	appState, err := MakeCodec().MarshalJSON(genesis)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return appState, accs, "simulation"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func appStateFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time) (json.RawMessage, []simulation.Account, string) {
 | 
			
		||||
	if genesisFile != "" {
 | 
			
		||||
		return appStateFromGenesisFileFn(r, accs, genesisTimestamp)
 | 
			
		||||
	}
 | 
			
		||||
	return appStateRandomizedFn(r, accs, genesisTimestamp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func testAndRunTxs(app *App) []simulation.WeightedOperation {
 | 
			
		||||
	return []simulation.WeightedOperation{
 | 
			
		||||
		{5, authsim.SimulateDeductFee(app.accountKeeper, app.feeCollectionKeeper)},
 | 
			
		||||
		{100, banksim.SimulateMsgSend(app.accountKeeper, app.bankKeeper)},
 | 
			
		||||
		{10, banksim.SimulateSingleInputMsgMultiSend(app.accountKeeper, app.bankKeeper)},
 | 
			
		||||
		{50, distrsim.SimulateMsgSetWithdrawAddress(app.accountKeeper, app.distrKeeper)},
 | 
			
		||||
		{50, distrsim.SimulateMsgWithdrawDelegatorReward(app.accountKeeper, app.distrKeeper)},
 | 
			
		||||
		{50, distrsim.SimulateMsgWithdrawValidatorCommission(app.accountKeeper, app.distrKeeper)},
 | 
			
		||||
		{5, govsim.SimulateSubmittingVotingAndSlashingForProposal(app.govKeeper)},
 | 
			
		||||
		{100, govsim.SimulateMsgDeposit(app.govKeeper)},
 | 
			
		||||
		{100, stakingsim.SimulateMsgCreateValidator(app.accountKeeper, app.stakingKeeper)},
 | 
			
		||||
		{5, stakingsim.SimulateMsgEditValidator(app.stakingKeeper)},
 | 
			
		||||
		{100, stakingsim.SimulateMsgDelegate(app.accountKeeper, app.stakingKeeper)},
 | 
			
		||||
		{100, stakingsim.SimulateMsgUndelegate(app.accountKeeper, app.stakingKeeper)},
 | 
			
		||||
		{100, stakingsim.SimulateMsgBeginRedelegate(app.accountKeeper, app.stakingKeeper)},
 | 
			
		||||
		{100, slashingsim.SimulateMsgUnjail(app.slashingKeeper)},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func invariants(app *App) []sdk.Invariant {
 | 
			
		||||
	return []sdk.Invariant{
 | 
			
		||||
		simulation.PeriodicInvariant(bank.NonnegativeBalanceInvariant(app.accountKeeper), period, 0),
 | 
			
		||||
		simulation.PeriodicInvariant(distr.AllInvariants(app.distrKeeper, app.stakingKeeper), period, 0),
 | 
			
		||||
		simulation.PeriodicInvariant(staking.AllInvariants(app.stakingKeeper, app.feeCollectionKeeper,
 | 
			
		||||
			app.distrKeeper, app.accountKeeper), period, 0),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pass this in as an option to use a dbStoreAdapter instead of an IAVLStore for simulation speed.
 | 
			
		||||
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
 | 
			
		||||
	bapp.SetFauxMerkleMode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Profile with:
 | 
			
		||||
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -SimulationCommit=true -cpuprofile cpu.out
 | 
			
		||||
func BenchmarkFullGaiaSimulation(b *testing.B) {
 | 
			
		||||
	// Setup Gaia application
 | 
			
		||||
	logger := log.NewNopLogger()
 | 
			
		||||
 | 
			
		||||
	var db dbm.DB
 | 
			
		||||
	dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
 | 
			
		||||
	db, _ = sdk.NewLevelDB("Simulation", dir)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		db.Close()
 | 
			
		||||
		os.RemoveAll(dir)
 | 
			
		||||
	}()
 | 
			
		||||
	app := NewApp(logger, db, nil, true, 0)
 | 
			
		||||
 | 
			
		||||
	// Run randomized simulation
 | 
			
		||||
	// TODO parameterize numbers, save for a later PR
 | 
			
		||||
	_, err := simulation.SimulateFromSeed(getSimulateFromSeedInput(b, app))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
		b.Fail()
 | 
			
		||||
	}
 | 
			
		||||
	if commit {
 | 
			
		||||
		fmt.Println("GoLevelDB Stats")
 | 
			
		||||
		fmt.Println(db.Stats()["leveldb.stats"])
 | 
			
		||||
		fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestFullGaiaSimulation(t *testing.T) {
 | 
			
		||||
	if !enabled {
 | 
			
		||||
		t.Skip("Skipping Gaia simulation")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Setup Gaia application
 | 
			
		||||
	var logger log.Logger
 | 
			
		||||
	if verbose {
 | 
			
		||||
		logger = log.TestingLogger()
 | 
			
		||||
	} else {
 | 
			
		||||
		logger = log.NewNopLogger()
 | 
			
		||||
	}
 | 
			
		||||
	var db dbm.DB
 | 
			
		||||
	dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
 | 
			
		||||
	db, _ = sdk.NewLevelDB("Simulation", dir)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		db.Close()
 | 
			
		||||
		os.RemoveAll(dir)
 | 
			
		||||
	}()
 | 
			
		||||
	app := NewApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
 | 
			
		||||
	require.Equal(t, "kava", app.Name())
 | 
			
		||||
 | 
			
		||||
	// Run randomized simulation
 | 
			
		||||
	_, err := simulation.SimulateFromSeed(getSimulateFromSeedInput(t, app))
 | 
			
		||||
	if commit {
 | 
			
		||||
		// for memdb:
 | 
			
		||||
		// fmt.Println("Database Size", db.Stats()["database.size"])
 | 
			
		||||
		fmt.Println("GoLevelDB Stats")
 | 
			
		||||
		fmt.Println(db.Stats()["leveldb.stats"])
 | 
			
		||||
		fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
 | 
			
		||||
	}
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGaiaImportExport(t *testing.T) {
 | 
			
		||||
	if !enabled {
 | 
			
		||||
		t.Skip("Skipping Gaia import/export simulation")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Setup Gaia application
 | 
			
		||||
	var logger log.Logger
 | 
			
		||||
	if verbose {
 | 
			
		||||
		logger = log.TestingLogger()
 | 
			
		||||
	} else {
 | 
			
		||||
		logger = log.NewNopLogger()
 | 
			
		||||
	}
 | 
			
		||||
	var db dbm.DB
 | 
			
		||||
	dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
 | 
			
		||||
	db, _ = sdk.NewLevelDB("Simulation", dir)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		db.Close()
 | 
			
		||||
		os.RemoveAll(dir)
 | 
			
		||||
	}()
 | 
			
		||||
	app := NewApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
 | 
			
		||||
	require.Equal(t, "kava", app.Name())
 | 
			
		||||
 | 
			
		||||
	// Run randomized simulation
 | 
			
		||||
	_, err := simulation.SimulateFromSeed(getSimulateFromSeedInput(t, app))
 | 
			
		||||
 | 
			
		||||
	if commit {
 | 
			
		||||
		// for memdb:
 | 
			
		||||
		// fmt.Println("Database Size", db.Stats()["database.size"])
 | 
			
		||||
		fmt.Println("GoLevelDB Stats")
 | 
			
		||||
		fmt.Println(db.Stats()["leveldb.stats"])
 | 
			
		||||
		fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
 | 
			
		||||
	}
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("Exporting genesis...\n")
 | 
			
		||||
 | 
			
		||||
	appState, _, err := app.ExportAppStateAndValidators(false, []string{})
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	fmt.Printf("Importing genesis...\n")
 | 
			
		||||
 | 
			
		||||
	newDir, _ := ioutil.TempDir("", "goleveldb-gaia-sim-2")
 | 
			
		||||
	newDB, _ := sdk.NewLevelDB("Simulation-2", dir)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		newDB.Close()
 | 
			
		||||
		os.RemoveAll(newDir)
 | 
			
		||||
	}()
 | 
			
		||||
	newApp := NewApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt)
 | 
			
		||||
	require.Equal(t, "kava", newApp.Name())
 | 
			
		||||
	var genesisState GenesisState
 | 
			
		||||
	err = app.cdc.UnmarshalJSON(appState, &genesisState)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	ctxB := newApp.NewContext(true, abci.Header{})
 | 
			
		||||
	newApp.initFromGenesisState(ctxB, genesisState)
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("Comparing stores...\n")
 | 
			
		||||
	ctxA := app.NewContext(true, abci.Header{})
 | 
			
		||||
	type StoreKeysPrefixes struct {
 | 
			
		||||
		A        sdk.StoreKey
 | 
			
		||||
		B        sdk.StoreKey
 | 
			
		||||
		Prefixes [][]byte
 | 
			
		||||
	}
 | 
			
		||||
	storeKeysPrefixes := []StoreKeysPrefixes{
 | 
			
		||||
		{app.keyMain, newApp.keyMain, [][]byte{}},
 | 
			
		||||
		{app.keyAccount, newApp.keyAccount, [][]byte{}},
 | 
			
		||||
		{app.keyStaking, newApp.keyStaking, [][]byte{staking.UnbondingQueueKey,
 | 
			
		||||
			staking.RedelegationQueueKey, staking.ValidatorQueueKey}}, // ordering may change but it doesn't matter
 | 
			
		||||
		{app.keySlashing, newApp.keySlashing, [][]byte{}},
 | 
			
		||||
		{app.keyMint, newApp.keyMint, [][]byte{}},
 | 
			
		||||
		{app.keyDistr, newApp.keyDistr, [][]byte{}},
 | 
			
		||||
		{app.keyFeeCollection, newApp.keyFeeCollection, [][]byte{}},
 | 
			
		||||
		{app.keyParams, newApp.keyParams, [][]byte{}},
 | 
			
		||||
		{app.keyGov, newApp.keyGov, [][]byte{}},
 | 
			
		||||
	}
 | 
			
		||||
	for _, storeKeysPrefix := range storeKeysPrefixes {
 | 
			
		||||
		storeKeyA := storeKeysPrefix.A
 | 
			
		||||
		storeKeyB := storeKeysPrefix.B
 | 
			
		||||
		prefixes := storeKeysPrefix.Prefixes
 | 
			
		||||
		storeA := ctxA.KVStore(storeKeyA)
 | 
			
		||||
		storeB := ctxB.KVStore(storeKeyB)
 | 
			
		||||
		kvA, kvB, count, equal := sdk.DiffKVStores(storeA, storeB, prefixes)
 | 
			
		||||
		fmt.Printf("Compared %d key/value pairs between %s and %s\n", count, storeKeyA, storeKeyB)
 | 
			
		||||
		require.True(t, equal,
 | 
			
		||||
			"unequal stores: %s / %s:\nstore A %X => %X\nstore B %X => %X",
 | 
			
		||||
			storeKeyA, storeKeyB, kvA.Key, kvA.Value, kvB.Key, kvB.Value,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGaiaSimulationAfterImport(t *testing.T) {
 | 
			
		||||
	if !enabled {
 | 
			
		||||
		t.Skip("Skipping Gaia simulation after import")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Setup Gaia application
 | 
			
		||||
	var logger log.Logger
 | 
			
		||||
	if verbose {
 | 
			
		||||
		logger = log.TestingLogger()
 | 
			
		||||
	} else {
 | 
			
		||||
		logger = log.NewNopLogger()
 | 
			
		||||
	}
 | 
			
		||||
	dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
 | 
			
		||||
	db, _ := sdk.NewLevelDB("Simulation", dir)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		db.Close()
 | 
			
		||||
		os.RemoveAll(dir)
 | 
			
		||||
	}()
 | 
			
		||||
	app := NewApp(logger, db, nil, true, 0, fauxMerkleModeOpt)
 | 
			
		||||
	require.Equal(t, "kava", app.Name())
 | 
			
		||||
 | 
			
		||||
	// Run randomized simulation
 | 
			
		||||
	stopEarly, err := simulation.SimulateFromSeed(getSimulateFromSeedInput(t, app))
 | 
			
		||||
 | 
			
		||||
	if commit {
 | 
			
		||||
		// for memdb:
 | 
			
		||||
		// fmt.Println("Database Size", db.Stats()["database.size"])
 | 
			
		||||
		fmt.Println("GoLevelDB Stats")
 | 
			
		||||
		fmt.Println(db.Stats()["leveldb.stats"])
 | 
			
		||||
		fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
 | 
			
		||||
	}
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	if stopEarly {
 | 
			
		||||
		// we can't export or import a zero-validator genesis
 | 
			
		||||
		fmt.Printf("We can't export or import a zero-validator genesis, exiting test...\n")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("Exporting genesis...\n")
 | 
			
		||||
 | 
			
		||||
	appState, _, err := app.ExportAppStateAndValidators(true, []string{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("Importing genesis...\n")
 | 
			
		||||
 | 
			
		||||
	newDir, _ := ioutil.TempDir("", "goleveldb-gaia-sim-2")
 | 
			
		||||
	newDB, _ := sdk.NewLevelDB("Simulation-2", dir)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		newDB.Close()
 | 
			
		||||
		os.RemoveAll(newDir)
 | 
			
		||||
	}()
 | 
			
		||||
	newApp := NewApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt)
 | 
			
		||||
	require.Equal(t, "kava", newApp.Name())
 | 
			
		||||
	newApp.InitChain(abci.RequestInitChain{
 | 
			
		||||
		AppStateBytes: appState,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// Run randomized simulation on imported app
 | 
			
		||||
	_, err = simulation.SimulateFromSeed(getSimulateFromSeedInput(t, newApp))
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Make another test for the fuzzer itself, which just has noOp txs
 | 
			
		||||
// and doesn't depend on gaia
 | 
			
		||||
func TestAppStateDeterminism(t *testing.T) {
 | 
			
		||||
	if !enabled {
 | 
			
		||||
		t.Skip("Skipping Gaia simulation")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	numSeeds := 3
 | 
			
		||||
	numTimesToRunPerSeed := 5
 | 
			
		||||
	appHashList := make([]json.RawMessage, numTimesToRunPerSeed)
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < numSeeds; i++ {
 | 
			
		||||
		seed := rand.Int63()
 | 
			
		||||
		for j := 0; j < numTimesToRunPerSeed; j++ {
 | 
			
		||||
			logger := log.NewNopLogger()
 | 
			
		||||
			db := dbm.NewMemDB()
 | 
			
		||||
			app := NewApp(logger, db, nil, true, 0)
 | 
			
		||||
 | 
			
		||||
			// Run randomized simulation
 | 
			
		||||
			simulation.SimulateFromSeed(
 | 
			
		||||
				t, app.BaseApp, appStateFn, seed,
 | 
			
		||||
				testAndRunTxs(app),
 | 
			
		||||
				[]sdk.Invariant{},
 | 
			
		||||
				50,
 | 
			
		||||
				100,
 | 
			
		||||
				true,
 | 
			
		||||
				false,
 | 
			
		||||
			)
 | 
			
		||||
			appHash := app.LastCommitID().Hash
 | 
			
		||||
			appHashList[j] = appHash
 | 
			
		||||
		}
 | 
			
		||||
		for k := 1; k < numTimesToRunPerSeed; k++ {
 | 
			
		||||
			require.Equal(t, appHashList[0], appHashList[k], "appHash list: %v", appHashList)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,3 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
@ -8,6 +5,14 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/mint"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
 | 
			
		||||
	amino "github.com/tendermint/go-amino"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/keys"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/lcd"
 | 
			
		||||
@ -15,18 +20,29 @@ import (
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/tx"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/version"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
 | 
			
		||||
	at "github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
 | 
			
		||||
	bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
 | 
			
		||||
	dist "github.com/cosmos/cosmos-sdk/x/distribution/client/rest"
 | 
			
		||||
	gv "github.com/cosmos/cosmos-sdk/x/gov"
 | 
			
		||||
	gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest"
 | 
			
		||||
	mintrest "github.com/cosmos/cosmos-sdk/x/mint/client/rest"
 | 
			
		||||
	sl "github.com/cosmos/cosmos-sdk/x/slashing"
 | 
			
		||||
	slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
 | 
			
		||||
	st "github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
	staking "github.com/cosmos/cosmos-sdk/x/staking/client/rest"
 | 
			
		||||
 | 
			
		||||
	authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/bank"
 | 
			
		||||
	bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
 | 
			
		||||
	"github.com/tendermint/go-amino"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/_/app"
 | 
			
		||||
	crisisclient "github.com/cosmos/cosmos-sdk/x/crisis/client"
 | 
			
		||||
	distcmd "github.com/cosmos/cosmos-sdk/x/distribution"
 | 
			
		||||
	distClient "github.com/cosmos/cosmos-sdk/x/distribution/client"
 | 
			
		||||
	govClient "github.com/cosmos/cosmos-sdk/x/gov/client"
 | 
			
		||||
	mintclient "github.com/cosmos/cosmos-sdk/x/mint/client"
 | 
			
		||||
	slashingclient "github.com/cosmos/cosmos-sdk/x/slashing/client"
 | 
			
		||||
	stakingclient "github.com/cosmos/cosmos-sdk/x/staking/client"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
@ -38,13 +54,26 @@ func main() {
 | 
			
		||||
 | 
			
		||||
	// Read in the configuration file for the sdk
 | 
			
		||||
	config := sdk.GetConfig()
 | 
			
		||||
	app.SetAddressPrefixes(config)
 | 
			
		||||
	config.SetBech32PrefixForAccount(app.Bech32MainPrefix, app.Bech32MainPrefix+sdk.PrefixPublic)
 | 
			
		||||
	config.SetBech32PrefixForValidator(app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator, app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic)
 | 
			
		||||
	config.SetBech32PrefixForConsensusNode(app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus, app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic)
 | 
			
		||||
	config.Seal()
 | 
			
		||||
 | 
			
		||||
	// TODO: setup keybase, viper object, etc. to be passed into
 | 
			
		||||
	// the below functions and eliminate global vars, like we do
 | 
			
		||||
	// with the cdc
 | 
			
		||||
 | 
			
		||||
	// Module clients hold cli commnads (tx,query) and lcd routes
 | 
			
		||||
	// TODO: Make the lcd command take a list of ModuleClient
 | 
			
		||||
	mc := []sdk.ModuleClients{
 | 
			
		||||
		govClient.NewModuleClient(gv.StoreKey, cdc),
 | 
			
		||||
		distClient.NewModuleClient(distcmd.StoreKey, cdc),
 | 
			
		||||
		stakingclient.NewModuleClient(st.StoreKey, cdc),
 | 
			
		||||
		mintclient.NewModuleClient(mint.StoreKey, cdc),
 | 
			
		||||
		slashingclient.NewModuleClient(sl.StoreKey, cdc),
 | 
			
		||||
		crisisclient.NewModuleClient(sl.StoreKey, cdc),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rootCmd := &cobra.Command{
 | 
			
		||||
		Use:   "kvcli",
 | 
			
		||||
		Short: "Command line interface for interacting with kvd",
 | 
			
		||||
@ -60,14 +89,14 @@ func main() {
 | 
			
		||||
	rootCmd.AddCommand(
 | 
			
		||||
		rpc.StatusCommand(),
 | 
			
		||||
		client.ConfigCmd(app.DefaultCLIHome),
 | 
			
		||||
		queryCmd(cdc),
 | 
			
		||||
		txCmd(cdc),
 | 
			
		||||
		queryCmd(cdc, mc),
 | 
			
		||||
		txCmd(cdc, mc),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		lcd.ServeCommand(cdc, registerRoutes),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		keys.Commands(),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		version.Cmd,
 | 
			
		||||
		version.VersionCmd,
 | 
			
		||||
		client.NewCompletionCmd(rootCmd, true),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -81,7 +110,7 @@ func main() {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func queryCmd(cdc *amino.Codec) *cobra.Command {
 | 
			
		||||
func queryCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command {
 | 
			
		||||
	queryCmd := &cobra.Command{
 | 
			
		||||
		Use:     "query",
 | 
			
		||||
		Aliases: []string{"q"},
 | 
			
		||||
@ -89,22 +118,25 @@ func queryCmd(cdc *amino.Codec) *cobra.Command {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	queryCmd.AddCommand(
 | 
			
		||||
		authcmd.GetAccountCmd(cdc),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		rpc.ValidatorCommand(cdc),
 | 
			
		||||
		rpc.BlockCommand(),
 | 
			
		||||
		tx.SearchTxCmd(cdc),
 | 
			
		||||
		tx.QueryTxCmd(cdc),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		authcmd.GetAccountCmd(at.StoreKey, cdc),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// add modules' query commands
 | 
			
		||||
	app.ModuleBasics.AddQueryCommands(queryCmd, cdc)
 | 
			
		||||
	for _, m := range mc {
 | 
			
		||||
		mQueryCmd := m.GetQueryCmd()
 | 
			
		||||
		if mQueryCmd != nil {
 | 
			
		||||
			queryCmd.AddCommand(mQueryCmd)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return queryCmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func txCmd(cdc *amino.Codec) *cobra.Command {
 | 
			
		||||
func txCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command {
 | 
			
		||||
	txCmd := &cobra.Command{
 | 
			
		||||
		Use:   "tx",
 | 
			
		||||
		Short: "Transactions subcommands",
 | 
			
		||||
@ -115,26 +147,15 @@ func txCmd(cdc *amino.Codec) *cobra.Command {
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		authcmd.GetSignCommand(cdc),
 | 
			
		||||
		authcmd.GetMultiSignCommand(cdc),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
		tx.GetBroadcastCommand(cdc),
 | 
			
		||||
		tx.GetEncodeCommand(cdc),
 | 
			
		||||
		client.LineBreak,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// add modules' tx commands
 | 
			
		||||
	app.ModuleBasics.AddTxCommands(txCmd, cdc)
 | 
			
		||||
 | 
			
		||||
	// remove auth and bank commands as they're mounted under the root tx command
 | 
			
		||||
	var cmdsToRemove []*cobra.Command
 | 
			
		||||
 | 
			
		||||
	for _, cmd := range txCmd.Commands() {
 | 
			
		||||
		if cmd.Use == auth.ModuleName || cmd.Use == bank.ModuleName {
 | 
			
		||||
			cmdsToRemove = append(cmdsToRemove, cmd)
 | 
			
		||||
		}
 | 
			
		||||
	for _, m := range mc {
 | 
			
		||||
		txCmd.AddCommand(m.GetTxCmd())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	txCmd.RemoveCommand(cmdsToRemove...)
 | 
			
		||||
 | 
			
		||||
	return txCmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -142,8 +163,15 @@ func txCmd(cdc *amino.Codec) *cobra.Command {
 | 
			
		||||
// NOTE: details on the routes added for each module are in the module documentation
 | 
			
		||||
// NOTE: If making updates here you also need to update the test helper in client/lcd/test_helper.go
 | 
			
		||||
func registerRoutes(rs *lcd.RestServer) {
 | 
			
		||||
	client.RegisterRoutes(rs.CliCtx, rs.Mux)
 | 
			
		||||
	app.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
 | 
			
		||||
	rpc.RegisterRoutes(rs.CliCtx, rs.Mux)
 | 
			
		||||
	tx.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
 | 
			
		||||
	auth.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, at.StoreKey)
 | 
			
		||||
	bank.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
 | 
			
		||||
	dist.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, distcmd.StoreKey)
 | 
			
		||||
	staking.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
 | 
			
		||||
	slashing.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc, rs.KeyBase)
 | 
			
		||||
	gov.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
 | 
			
		||||
	mintrest.RegisterRoutes(rs.CliCtx, rs.Mux, rs.Cdc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initConfig(cmd *cobra.Command) error {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,3 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
@ -10,25 +7,22 @@ import (
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/baseapp"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/store"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"
 | 
			
		||||
	genaccscli "github.com/cosmos/cosmos-sdk/x/auth/genaccounts/client/cli"
 | 
			
		||||
	genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
	dbm "github.com/tendermint/tendermint/libs/db"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/log"
 | 
			
		||||
	tmtypes "github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/_/app"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/baseapp"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/store"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	initPkg "github.com/kava-labs/kava/init"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// gaiad custom flags
 | 
			
		||||
// kvd custom flags
 | 
			
		||||
const flagInvCheckPeriod = "inv-check-period"
 | 
			
		||||
 | 
			
		||||
var invCheckPeriod uint
 | 
			
		||||
@ -37,7 +31,9 @@ func main() {
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
 | 
			
		||||
	config := sdk.GetConfig()
 | 
			
		||||
	app.SetAddressPrefixes(config)
 | 
			
		||||
	config.SetBech32PrefixForAccount(app.Bech32MainPrefix, app.Bech32MainPrefix+sdk.PrefixPublic)
 | 
			
		||||
	config.SetBech32PrefixForValidator(app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator, app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic)
 | 
			
		||||
	config.SetBech32PrefixForConsensusNode(app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus, app.Bech32MainPrefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic)
 | 
			
		||||
	config.Seal()
 | 
			
		||||
 | 
			
		||||
	ctx := server.NewDefaultContext()
 | 
			
		||||
@ -48,24 +44,23 @@ func main() {
 | 
			
		||||
		PersistentPreRunE: server.PersistentPreRunEFn(ctx),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rootCmd.AddCommand(genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, app.DefaultNodeHome))
 | 
			
		||||
	rootCmd.AddCommand(genutilcli.CollectGenTxsCmd(ctx, cdc, genaccounts.AppModuleBasic{}, app.DefaultNodeHome))
 | 
			
		||||
	rootCmd.AddCommand(genutilcli.GenTxCmd(ctx, cdc, app.ModuleBasics, staking.AppModuleBasic{},
 | 
			
		||||
		genaccounts.AppModuleBasic{}, app.DefaultNodeHome, app.DefaultCLIHome))
 | 
			
		||||
	rootCmd.AddCommand(genutilcli.ValidateGenesisCmd(ctx, cdc, app.ModuleBasics))
 | 
			
		||||
	rootCmd.AddCommand(genaccscli.AddGenesisAccountCmd(ctx, cdc, app.DefaultNodeHome, app.DefaultCLIHome))
 | 
			
		||||
	rootCmd.AddCommand(initPkg.InitCmd(ctx, cdc))
 | 
			
		||||
	rootCmd.AddCommand(initPkg.CollectGenTxsCmd(ctx, cdc))
 | 
			
		||||
	rootCmd.AddCommand(initPkg.TestnetFilesCmd(ctx, cdc))
 | 
			
		||||
	rootCmd.AddCommand(initPkg.GenTxCmd(ctx, cdc))
 | 
			
		||||
	rootCmd.AddCommand(initPkg.AddGenesisAccountCmd(ctx, cdc))
 | 
			
		||||
	rootCmd.AddCommand(initPkg.ValidateGenesisCmd(ctx, cdc))
 | 
			
		||||
	rootCmd.AddCommand(client.NewCompletionCmd(rootCmd, true))
 | 
			
		||||
	rootCmd.AddCommand(testnetCmd(ctx, cdc, app.ModuleBasics, genaccounts.AppModuleBasic{}))
 | 
			
		||||
	rootCmd.AddCommand(replayCmd())
 | 
			
		||||
 | 
			
		||||
	server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
 | 
			
		||||
 | 
			
		||||
	// prepare and add flags
 | 
			
		||||
	executor := cli.PrepareBaseCmd(rootCmd, "KA", app.DefaultNodeHome)
 | 
			
		||||
	executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)
 | 
			
		||||
	rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
 | 
			
		||||
		0, "Assert registered invariants every N blocks")
 | 
			
		||||
	err := executor.Execute()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// handle with #870
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -75,7 +70,6 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application
 | 
			
		||||
		logger, db, traceStore, true, invCheckPeriod,
 | 
			
		||||
		baseapp.SetPruning(store.NewPruningOptionsFromString(viper.GetString("pruning"))),
 | 
			
		||||
		baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
 | 
			
		||||
		baseapp.SetHaltHeight(uint64(viper.GetInt(server.FlagHaltHeight))),
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -84,13 +78,13 @@ func exportAppStateAndTMValidators(
 | 
			
		||||
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
 | 
			
		||||
 | 
			
		||||
	if height != -1 {
 | 
			
		||||
		appStruct := app.NewApp(logger, db, traceStore, false, uint(1))
 | 
			
		||||
		err := appStruct.LoadHeight(height)
 | 
			
		||||
		gApp := app.NewApp(logger, db, traceStore, false, uint(1))
 | 
			
		||||
		err := gApp.LoadHeight(height)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return appStruct.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
			
		||||
		return gApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
			
		||||
	}
 | 
			
		||||
	appStruct := app.NewApp(logger, db, traceStore, true, uint(1))
 | 
			
		||||
	return appStruct.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
			
		||||
	gApp := app.NewApp(logger, db, traceStore, true, uint(1))
 | 
			
		||||
	return gApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,193 +0,0 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	cpm "github.com/otiai10/copy"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/baseapp"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/store"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	abci "github.com/tendermint/tendermint/abci/types"
 | 
			
		||||
	bcm "github.com/tendermint/tendermint/blockchain"
 | 
			
		||||
	cmn "github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
	"github.com/tendermint/tendermint/proxy"
 | 
			
		||||
	tmsm "github.com/tendermint/tendermint/state"
 | 
			
		||||
	tm "github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/_/app"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func replayCmd() *cobra.Command {
 | 
			
		||||
	return &cobra.Command{
 | 
			
		||||
		Use:   "replay <root-dir>",
 | 
			
		||||
		Short: "Replay transactions",
 | 
			
		||||
		RunE: func(_ *cobra.Command, args []string) error {
 | 
			
		||||
			return replayTxs(args[0])
 | 
			
		||||
		},
 | 
			
		||||
		Args: cobra.ExactArgs(1),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func replayTxs(rootDir string) error {
 | 
			
		||||
 | 
			
		||||
	if false {
 | 
			
		||||
		// Copy the rootDir to a new directory, to preserve the old one.
 | 
			
		||||
		fmt.Fprintln(os.Stderr, "Copying rootdir over")
 | 
			
		||||
		oldRootDir := rootDir
 | 
			
		||||
		rootDir = oldRootDir + "_replay"
 | 
			
		||||
		if cmn.FileExists(rootDir) {
 | 
			
		||||
			cmn.Exit(fmt.Sprintf("temporary copy dir %v already exists", rootDir))
 | 
			
		||||
		}
 | 
			
		||||
		if err := cpm.Copy(oldRootDir, rootDir); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configDir := filepath.Join(rootDir, "config")
 | 
			
		||||
	dataDir := filepath.Join(rootDir, "data")
 | 
			
		||||
	ctx := server.NewDefaultContext()
 | 
			
		||||
 | 
			
		||||
	// App DB
 | 
			
		||||
	// appDB := dbm.NewMemDB()
 | 
			
		||||
	fmt.Fprintln(os.Stderr, "Opening app database")
 | 
			
		||||
	appDB, err := sdk.NewLevelDB("application", dataDir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TM DB
 | 
			
		||||
	// tmDB := dbm.NewMemDB()
 | 
			
		||||
	fmt.Fprintln(os.Stderr, "Opening tendermint state database")
 | 
			
		||||
	tmDB, err := sdk.NewLevelDB("state", dataDir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Blockchain DB
 | 
			
		||||
	fmt.Fprintln(os.Stderr, "Opening blockstore database")
 | 
			
		||||
	bcDB, err := sdk.NewLevelDB("blockstore", dataDir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TraceStore
 | 
			
		||||
	var traceStoreWriter io.Writer
 | 
			
		||||
	var traceStoreDir = filepath.Join(dataDir, "trace.log")
 | 
			
		||||
	traceStoreWriter, err = os.OpenFile(
 | 
			
		||||
		traceStoreDir,
 | 
			
		||||
		os.O_WRONLY|os.O_APPEND|os.O_CREATE,
 | 
			
		||||
		0666,
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Application
 | 
			
		||||
	fmt.Fprintln(os.Stderr, "Creating application")
 | 
			
		||||
	myapp := app.NewApp(
 | 
			
		||||
		ctx.Logger, appDB, traceStoreWriter, true, uint(1),
 | 
			
		||||
		baseapp.SetPruning(store.PruneEverything), // nothing
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Genesis
 | 
			
		||||
	var genDocPath = filepath.Join(configDir, "genesis.json")
 | 
			
		||||
	genDoc, err := tm.GenesisDocFromFile(genDocPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	genState, err := tmsm.MakeGenesisState(genDoc)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// tmsm.SaveState(tmDB, genState)
 | 
			
		||||
 | 
			
		||||
	cc := proxy.NewLocalClientCreator(myapp)
 | 
			
		||||
	proxyApp := proxy.NewAppConns(cc)
 | 
			
		||||
	err = proxyApp.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer func() {
 | 
			
		||||
		_ = proxyApp.Stop()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	state := tmsm.LoadState(tmDB)
 | 
			
		||||
	if state.LastBlockHeight == 0 {
 | 
			
		||||
		// Send InitChain msg
 | 
			
		||||
		fmt.Fprintln(os.Stderr, "Sending InitChain msg")
 | 
			
		||||
		validators := tm.TM2PB.ValidatorUpdates(genState.Validators)
 | 
			
		||||
		csParams := tm.TM2PB.ConsensusParams(genDoc.ConsensusParams)
 | 
			
		||||
		req := abci.RequestInitChain{
 | 
			
		||||
			Time:            genDoc.GenesisTime,
 | 
			
		||||
			ChainId:         genDoc.ChainID,
 | 
			
		||||
			ConsensusParams: csParams,
 | 
			
		||||
			Validators:      validators,
 | 
			
		||||
			AppStateBytes:   genDoc.AppState,
 | 
			
		||||
		}
 | 
			
		||||
		res, err := proxyApp.Consensus().InitChainSync(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		newValidatorz, err := tm.PB2TM.ValidatorUpdates(res.Validators)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		newValidators := tm.NewValidatorSet(newValidatorz)
 | 
			
		||||
 | 
			
		||||
		// Take the genesis state.
 | 
			
		||||
		state = genState
 | 
			
		||||
		state.Validators = newValidators
 | 
			
		||||
		state.NextValidators = newValidators
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create executor
 | 
			
		||||
	fmt.Fprintln(os.Stderr, "Creating block executor")
 | 
			
		||||
	blockExec := tmsm.NewBlockExecutor(tmDB, ctx.Logger, proxyApp.Consensus(),
 | 
			
		||||
		tmsm.MockMempool{}, tmsm.MockEvidencePool{})
 | 
			
		||||
 | 
			
		||||
	// Create block store
 | 
			
		||||
	fmt.Fprintln(os.Stderr, "Creating block store")
 | 
			
		||||
	blockStore := bcm.NewBlockStore(bcDB)
 | 
			
		||||
 | 
			
		||||
	tz := []time.Duration{0, 0, 0}
 | 
			
		||||
	for i := int(state.LastBlockHeight) + 1; ; i++ {
 | 
			
		||||
		fmt.Fprintln(os.Stderr, "Running block ", i)
 | 
			
		||||
		t1 := time.Now()
 | 
			
		||||
 | 
			
		||||
		// Apply block
 | 
			
		||||
		fmt.Printf("loading and applying block %d\n", i)
 | 
			
		||||
		blockmeta := blockStore.LoadBlockMeta(int64(i))
 | 
			
		||||
		if blockmeta == nil {
 | 
			
		||||
			fmt.Printf("Couldn't find block meta %d... done?\n", i)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		block := blockStore.LoadBlock(int64(i))
 | 
			
		||||
		if block == nil {
 | 
			
		||||
			return fmt.Errorf("couldn't find block %d", i)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t2 := time.Now()
 | 
			
		||||
 | 
			
		||||
		state, err = blockExec.ApplyBlock(state, blockmeta.BlockID, block)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t3 := time.Now()
 | 
			
		||||
		tz[0] += t2.Sub(t1)
 | 
			
		||||
		tz[1] += t3.Sub(t2)
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "new app hash: %X\n", state.AppHash)
 | 
			
		||||
		fmt.Fprintln(os.Stderr, tz)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								go.mod
									
									
									
									
									
								
							@ -1,35 +1,15 @@
 | 
			
		||||
module github.com/kava-labs/_
 | 
			
		||||
module github.com/kava-labs/kava
 | 
			
		||||
 | 
			
		||||
go 1.12
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c // indirect
 | 
			
		||||
	github.com/cosmos/cosmos-sdk v0.28.2-0.20190606154315-3180e68c7b57
 | 
			
		||||
	github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d // indirect
 | 
			
		||||
	github.com/google/gofuzz v1.0.0 // indirect
 | 
			
		||||
	github.com/gorilla/mux v1.7.2 // indirect
 | 
			
		||||
	github.com/magiconair/properties v1.8.1 // indirect
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.8 // indirect
 | 
			
		||||
	github.com/onsi/ginkgo v1.8.0 // indirect
 | 
			
		||||
	github.com/onsi/gomega v1.5.0 // indirect
 | 
			
		||||
	github.com/otiai10/copy v1.0.1
 | 
			
		||||
	github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml v1.4.0 // indirect
 | 
			
		||||
	github.com/prometheus/common v0.4.1 // indirect
 | 
			
		||||
	github.com/prometheus/procfs v0.0.0-20190523193104-a7aeb8df3389 // indirect
 | 
			
		||||
	github.com/rakyll/statik v0.1.6 // indirect
 | 
			
		||||
	github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect
 | 
			
		||||
	github.com/spf13/afero v1.2.2 // indirect
 | 
			
		||||
	github.com/spf13/cobra v0.0.4
 | 
			
		||||
	github.com/spf13/viper v1.4.0
 | 
			
		||||
	github.com/syndtr/goleveldb v1.0.0 // indirect
 | 
			
		||||
	github.com/tendermint/go-amino v0.15.0
 | 
			
		||||
	github.com/cosmos/cosmos-sdk v0.34.7
 | 
			
		||||
	github.com/rakyll/statik v0.1.4
 | 
			
		||||
	github.com/spf13/cobra v0.0.3
 | 
			
		||||
	github.com/spf13/viper v1.0.3
 | 
			
		||||
	github.com/stretchr/testify v1.3.0
 | 
			
		||||
	github.com/tendermint/go-amino v0.14.1
 | 
			
		||||
	github.com/tendermint/tendermint v0.31.5
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20190527104216-9cd6430ef91e // indirect
 | 
			
		||||
	golang.org/x/text v0.3.2 // indirect
 | 
			
		||||
	google.golang.org/appengine v1.4.0 // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
replace golang.org/x/crypto => github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										64
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								go.sum
									
									
									
									
									
								
							@ -9,17 +9,17 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
 | 
			
		||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 | 
			
		||||
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8=
 | 
			
		||||
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk=
 | 
			
		||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
 | 
			
		||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 | 
			
		||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
 | 
			
		||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 | 
			
		||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
 | 
			
		||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 | 
			
		||||
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d h1:xG8Pj6Y6J760xwETNmMzmlt38QSwz0BLp1cZ09g27uw=
 | 
			
		||||
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
 | 
			
		||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q=
 | 
			
		||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
 | 
			
		||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
 | 
			
		||||
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE=
 | 
			
		||||
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
 | 
			
		||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
 | 
			
		||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
 | 
			
		||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
 | 
			
		||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
 | 
			
		||||
@ -34,10 +34,12 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
 | 
			
		||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 | 
			
		||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
			
		||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
			
		||||
github.com/cosmos/cosmos-sdk v0.28.2-0.20190606154315-3180e68c7b57 h1:bLViLq/BPtEMhxsYhE5NxxTM664Bt1Z+vM6SJflQXTU=
 | 
			
		||||
github.com/cosmos/cosmos-sdk v0.28.2-0.20190606154315-3180e68c7b57/go.mod h1:MvaJDmjgAK7X1rTnpk8+c6tUFfIZ++iuNCp2sUWzprM=
 | 
			
		||||
github.com/cosmos/cosmos-sdk v0.34.7 h1:S6yMldhrAMB/SDMsR2Hvz05tpUpQQGCHf0INXAZ7VW0=
 | 
			
		||||
github.com/cosmos/cosmos-sdk v0.34.7/go.mod h1:ruF+G4D7hRf34uzZQvf/SIja9fsIThU5D7GirwTMQ9I=
 | 
			
		||||
github.com/cosmos/cosmos-sdk v0.35.0 h1:EPeie1aKHwnXtTzKggvabG7aAPN+DDmju2xquvjFwao=
 | 
			
		||||
github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8 h1:Iwin12wRQtyZhH6FV3ykFcdGNlYEzoeR0jN8Vn+JWsI=
 | 
			
		||||
github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
 | 
			
		||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
 | 
			
		||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
 | 
			
		||||
github.com/cosmos/ledger-cosmos-go v0.10.3/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
 | 
			
		||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
 | 
			
		||||
@ -58,25 +60,26 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
 | 
			
		||||
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
 | 
			
		||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 | 
			
		||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 | 
			
		||||
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
 | 
			
		||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 | 
			
		||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
 | 
			
		||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 | 
			
		||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 | 
			
		||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 | 
			
		||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 | 
			
		||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
 | 
			
		||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
 | 
			
		||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 | 
			
		||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 | 
			
		||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 | 
			
		||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
 | 
			
		||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 | 
			
		||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
			
		||||
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
 | 
			
		||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 | 
			
		||||
github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I=
 | 
			
		||||
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 | 
			
		||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
 | 
			
		||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 | 
			
		||||
@ -100,11 +103,11 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
 | 
			
		||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
			
		||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
			
		||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
			
		||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
 | 
			
		||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
			
		||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 | 
			
		||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.6 h1:SrwhHcpV4nWrMGdNcC2kXpMfcBVYGDuTArqyhocJgvA=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 | 
			
		||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 | 
			
		||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 | 
			
		||||
@ -118,14 +121,14 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
 | 
			
		||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 | 
			
		||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 | 
			
		||||
github.com/otiai10/copy v1.0.1 h1:gtBjD8aq4nychvRZ2CyJvFWAw0aja+VHazDdruZKGZA=
 | 
			
		||||
github.com/otiai10/copy v0.0.0-20180813032824-7e9a647135a1/go.mod h1:pXzZSDlN+HPzSdyIBnKNN9ptD9Hx7iZMWIJPTwo4FPE=
 | 
			
		||||
github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc=
 | 
			
		||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
 | 
			
		||||
github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4=
 | 
			
		||||
github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw=
 | 
			
		||||
github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M=
 | 
			
		||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
 | 
			
		||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 | 
			
		||||
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
 | 
			
		||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 | 
			
		||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
			
		||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 | 
			
		||||
@ -133,30 +136,30 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 | 
			
		||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 | 
			
		||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 | 
			
		||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
 | 
			
		||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 | 
			
		||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 | 
			
		||||
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
 | 
			
		||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190227231451-bbced9601137 h1:3l8oligPtjd4JuM+OZ+U8sjtwFGJs98cdWsqs6QZRWs=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190227231451-bbced9601137/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190523193104-a7aeb8df3389 h1:F/k2nob1S9M6v5Xkq7KjSTQirOYaYQord0jR4TwyVmY=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190523193104-a7aeb8df3389/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 | 
			
		||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 | 
			
		||||
github.com/rakyll/statik v0.1.4 h1:zCS/YQCxfo/fQjCtGVGIyWGFnRbQ18Y55mhS3XPE+Oo=
 | 
			
		||||
github.com/rakyll/statik v0.1.4/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
 | 
			
		||||
github.com/rakyll/statik v0.1.6 h1:uICcfUXpgqtw2VopbIncslhAmE5hwc4g20TEyEENBNs=
 | 
			
		||||
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
 | 
			
		||||
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFEuGCb2mBZbBb24RdNRL08b/wb+xBOYpuk=
 | 
			
		||||
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 | 
			
		||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
 | 
			
		||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 | 
			
		||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 | 
			
		||||
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
 | 
			
		||||
@ -166,38 +169,40 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
 | 
			
		||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 | 
			
		||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 | 
			
		||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 | 
			
		||||
github.com/spf13/afero v1.2.1 h1:qgMbHoJbPbw579P+1zVY+6n4nIFuIchaIjzZ/I/Yq8M=
 | 
			
		||||
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 | 
			
		||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
 | 
			
		||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 | 
			
		||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
 | 
			
		||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 | 
			
		||||
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
 | 
			
		||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 | 
			
		||||
github.com/spf13/cobra v0.0.4 h1:S0tLZ3VOKl2Te0hpq8+ke0eSJPfCnNTPiDlsfwi1/NE=
 | 
			
		||||
github.com/spf13/cobra v0.0.4/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 | 
			
		||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 | 
			
		||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 | 
			
		||||
github.com/spf13/viper v1.0.3 h1:z5LPUc2iz8VLT5Cw1UyrESG6FUUnOGecYGY08BLKSuc=
 | 
			
		||||
github.com/spf13/viper v1.0.3/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
 | 
			
		||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 | 
			
		||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
 | 
			
		||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
			
		||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 | 
			
		||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
			
		||||
github.com/syndtr/goleveldb v0.0.0-20180708030551-c4c61651e9e3 h1:sAlSBRDl4psFR3ysKXRSE8ss6Mt90+ma1zRTroTNBJA=
 | 
			
		||||
github.com/syndtr/goleveldb v0.0.0-20180708030551-c4c61651e9e3/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 | 
			
		||||
github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s=
 | 
			
		||||
github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U=
 | 
			
		||||
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 h1:u8i49c+BxloX3XQ55cvzFNXplizZP/q00i+IlttUjAU=
 | 
			
		||||
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
 | 
			
		||||
github.com/tendermint/go-amino v0.15.0 h1:TC4e66P59W7ML9+bxio17CPKnxW3nKIRAYskntMAoRk=
 | 
			
		||||
github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk=
 | 
			
		||||
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
 | 
			
		||||
github.com/tendermint/go-amino v0.15.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
 | 
			
		||||
github.com/tendermint/iavl v0.12.2 h1:Ls5p5VINCM1HRT9g5Vvs2zmDOCU/CCIvIHzd/pZ8P0E=
 | 
			
		||||
github.com/tendermint/iavl v0.12.1 h1:JDfyhM/Hhrumu1CL1Nxrypm8sNTPYqmeHo1IZLiJoXM=
 | 
			
		||||
github.com/tendermint/iavl v0.12.1/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM=
 | 
			
		||||
github.com/tendermint/iavl v0.12.2/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM=
 | 
			
		||||
github.com/tendermint/tendermint v0.31.5 h1:vTet8tCq3B9/J9Yo11dNZ8pOB7NtSy++bVSfkP4KzR4=
 | 
			
		||||
github.com/tendermint/tendermint v0.31.5/go.mod h1:ymcPyWblXCplCPQjbOYbrF1fWnpslATMVqiGgWbZrlc=
 | 
			
		||||
@ -211,6 +216,9 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
			
		||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
			
		||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 | 
			
		||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
			
		||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 | 
			
		||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 | 
			
		||||
@ -219,11 +227,11 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
 | 
			
		||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
 | 
			
		||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
 | 
			
		||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
@ -237,11 +245,11 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
 | 
			
		||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190527104216-9cd6430ef91e h1:Pzdi8HRppinixnWWzN6KSa0QkBM+GKsTJaWwwfJskNw=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190527104216-9cd6430ef91e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
			
		||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
			
		||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
@ -251,12 +259,12 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
 | 
			
		||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
			
		||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 | 
			
		||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 h1:4rNOqY4ULrKzS6twXa619uQgI7h9PaVd4ZhjFQ7C5zs=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 | 
			
		||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
 | 
			
		||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 | 
			
		||||
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
 | 
			
		||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 | 
			
		||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										145
									
								
								init/collect.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								init/collect.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,145 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
// DONTCOVER
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	cfg "github.com/tendermint/tendermint/config"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
	"github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	flagGenTxDir = "gentx-dir"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type initConfig struct {
 | 
			
		||||
	ChainID   string
 | 
			
		||||
	GenTxsDir string
 | 
			
		||||
	Name      string
 | 
			
		||||
	NodeID    string
 | 
			
		||||
	ValPubKey crypto.PubKey
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nolint
 | 
			
		||||
func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:   "collect-gentxs",
 | 
			
		||||
		Short: "Collect genesis txs and output a genesis.json file",
 | 
			
		||||
		RunE: func(_ *cobra.Command, _ []string) error {
 | 
			
		||||
			config := ctx.Config
 | 
			
		||||
			config.SetRoot(viper.GetString(cli.HomeFlag))
 | 
			
		||||
			name := viper.GetString(client.FlagName)
 | 
			
		||||
			nodeID, valPubKey, err := InitializeNodeValidatorFiles(config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			genDoc, err := LoadGenesisDoc(cdc, config.GenesisFile())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			genTxsDir := viper.GetString(flagGenTxDir)
 | 
			
		||||
			if genTxsDir == "" {
 | 
			
		||||
				genTxsDir = filepath.Join(config.RootDir, "config", "gentx")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			toPrint := newPrintInfo(config.Moniker, genDoc.ChainID, nodeID, genTxsDir, json.RawMessage(""))
 | 
			
		||||
			initCfg := newInitConfig(genDoc.ChainID, genTxsDir, name, nodeID, valPubKey)
 | 
			
		||||
 | 
			
		||||
			appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			toPrint.AppMessage = appMessage
 | 
			
		||||
 | 
			
		||||
			// print out some key information
 | 
			
		||||
			return displayInfo(cdc, toPrint)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
 | 
			
		||||
	cmd.Flags().String(flagGenTxDir, "",
 | 
			
		||||
		"override default \"gentx\" directory from which collect and execute "+
 | 
			
		||||
			"genesis transactions; default [--home]/config/gentx/")
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func genAppStateFromConfig(
 | 
			
		||||
	cdc *codec.Codec, config *cfg.Config, initCfg initConfig, genDoc types.GenesisDoc,
 | 
			
		||||
) (appState json.RawMessage, err error) {
 | 
			
		||||
 | 
			
		||||
	genFile := config.GenesisFile()
 | 
			
		||||
	var (
 | 
			
		||||
		appGenTxs       []auth.StdTx
 | 
			
		||||
		persistentPeers string
 | 
			
		||||
		genTxs          []json.RawMessage
 | 
			
		||||
		jsonRawTx       json.RawMessage
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// process genesis transactions, else create default genesis.json
 | 
			
		||||
	appGenTxs, persistentPeers, err = app.CollectStdTxs(
 | 
			
		||||
		cdc, config.Moniker, initCfg.GenTxsDir, genDoc,
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	genTxs = make([]json.RawMessage, len(appGenTxs))
 | 
			
		||||
	config.P2P.PersistentPeers = persistentPeers
 | 
			
		||||
 | 
			
		||||
	for i, stdTx := range appGenTxs {
 | 
			
		||||
		jsonRawTx, err = cdc.MarshalJSON(stdTx)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		genTxs[i] = jsonRawTx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
 | 
			
		||||
 | 
			
		||||
	appState, err = app.AppGenStateJSON(cdc, genDoc, genTxs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = ExportGenesisFile(genFile, initCfg.ChainID, nil, appState)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInitConfig(chainID, genTxsDir, name, nodeID string,
 | 
			
		||||
	valPubKey crypto.PubKey) initConfig {
 | 
			
		||||
 | 
			
		||||
	return initConfig{
 | 
			
		||||
		ChainID:   chainID,
 | 
			
		||||
		GenTxsDir: genTxsDir,
 | 
			
		||||
		Name:      name,
 | 
			
		||||
		NodeID:    nodeID,
 | 
			
		||||
		ValPubKey: valPubKey,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newPrintInfo(moniker, chainID, nodeID, genTxsDir string,
 | 
			
		||||
	appMessage json.RawMessage) printInfo {
 | 
			
		||||
 | 
			
		||||
	return printInfo{
 | 
			
		||||
		Moniker:    moniker,
 | 
			
		||||
		ChainID:    chainID,
 | 
			
		||||
		NodeID:     nodeID,
 | 
			
		||||
		GenTxsDir:  genTxsDir,
 | 
			
		||||
		AppMessage: appMessage,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										141
									
								
								init/genesis_accts.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								init/genesis_accts.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/keys"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
 | 
			
		||||
func AddGenesisAccountCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:   "add-genesis-account [address_or_key_name] [coin][,[coin]]",
 | 
			
		||||
		Short: "Add genesis account to genesis.json",
 | 
			
		||||
		Args:  cobra.ExactArgs(2),
 | 
			
		||||
		RunE: func(_ *cobra.Command, args []string) error {
 | 
			
		||||
			config := ctx.Config
 | 
			
		||||
			config.SetRoot(viper.GetString(cli.HomeFlag))
 | 
			
		||||
 | 
			
		||||
			addr, err := sdk.AccAddressFromBech32(args[0])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				kb, err := keys.NewKeyBaseFromDir(viper.GetString(flagClientHome))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				info, err := kb.Get(args[0])
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				addr = info.GetAddress()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			coins, err := sdk.ParseCoins(args[1])
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			vestingStart := viper.GetInt64(flagVestingStart)
 | 
			
		||||
			vestingEnd := viper.GetInt64(flagVestingEnd)
 | 
			
		||||
			vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			genFile := config.GenesisFile()
 | 
			
		||||
			if !common.FileExists(genFile) {
 | 
			
		||||
				return fmt.Errorf("%s does not exist, run `kvd init` first", genFile)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			genDoc, err := LoadGenesisDoc(cdc, genFile)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var appState app.GenesisState
 | 
			
		||||
			if err = cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			appState, err = addGenesisAccount(cdc, appState, addr, coins, vestingAmt, vestingStart, vestingEnd)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			appStateJSON, err := cdc.MarshalJSON(appState)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return ExportGenesisFile(genFile, genDoc.ChainID, nil, appStateJSON)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
 | 
			
		||||
	cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
 | 
			
		||||
	cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts")
 | 
			
		||||
	cmd.Flags().Uint64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts")
 | 
			
		||||
	cmd.Flags().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts")
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addGenesisAccount(
 | 
			
		||||
	cdc *codec.Codec, appState app.GenesisState, addr sdk.AccAddress,
 | 
			
		||||
	coins, vestingAmt sdk.Coins, vestingStart, vestingEnd int64,
 | 
			
		||||
) (app.GenesisState, error) {
 | 
			
		||||
 | 
			
		||||
	for _, stateAcc := range appState.Accounts {
 | 
			
		||||
		if stateAcc.Address.Equals(addr) {
 | 
			
		||||
			return appState, fmt.Errorf("the application state already contains account %v", addr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	acc := auth.NewBaseAccountWithAddress(addr)
 | 
			
		||||
	acc.Coins = coins
 | 
			
		||||
 | 
			
		||||
	if !vestingAmt.IsZero() {
 | 
			
		||||
		var vacc auth.VestingAccount
 | 
			
		||||
 | 
			
		||||
		bvacc := &auth.BaseVestingAccount{
 | 
			
		||||
			BaseAccount:     &acc,
 | 
			
		||||
			OriginalVesting: vestingAmt,
 | 
			
		||||
			EndTime:         vestingEnd,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if bvacc.OriginalVesting.IsAllGT(acc.Coins) {
 | 
			
		||||
			return appState, fmt.Errorf("vesting amount cannot be greater than total amount")
 | 
			
		||||
		}
 | 
			
		||||
		if vestingStart >= vestingEnd {
 | 
			
		||||
			return appState, fmt.Errorf("vesting start time must before end time")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if vestingStart != 0 {
 | 
			
		||||
			vacc = &auth.ContinuousVestingAccount{
 | 
			
		||||
				BaseVestingAccount: bvacc,
 | 
			
		||||
				StartTime:          vestingStart,
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			vacc = &auth.DelayedVestingAccount{
 | 
			
		||||
				BaseVestingAccount: bvacc,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		appState.Accounts = append(appState.Accounts, app.NewGenesisAccountI(vacc))
 | 
			
		||||
	} else {
 | 
			
		||||
		appState.Accounts = append(appState.Accounts, app.NewGenesisAccount(&acc))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return appState, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										88
									
								
								init/genesis_accts_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								init/genesis_accts_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto/secp256k1"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestAddGenesisAccount(t *testing.T) {
 | 
			
		||||
	cdc := codec.New()
 | 
			
		||||
	addr1 := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
 | 
			
		||||
	type args struct {
 | 
			
		||||
		appState     app.GenesisState
 | 
			
		||||
		addr         sdk.AccAddress
 | 
			
		||||
		coins        sdk.Coins
 | 
			
		||||
		vestingAmt   sdk.Coins
 | 
			
		||||
		vestingStart int64
 | 
			
		||||
		vestingEnd   int64
 | 
			
		||||
	}
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name    string
 | 
			
		||||
		args    args
 | 
			
		||||
		wantErr bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			"valid account",
 | 
			
		||||
			args{
 | 
			
		||||
				app.GenesisState{},
 | 
			
		||||
				addr1,
 | 
			
		||||
				sdk.NewCoins(),
 | 
			
		||||
				sdk.NewCoins(),
 | 
			
		||||
				0,
 | 
			
		||||
				0,
 | 
			
		||||
			},
 | 
			
		||||
			false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"dup account",
 | 
			
		||||
			args{
 | 
			
		||||
				app.GenesisState{Accounts: []app.GenesisAccount{{Address: addr1}}},
 | 
			
		||||
				addr1,
 | 
			
		||||
				sdk.NewCoins(),
 | 
			
		||||
				sdk.NewCoins(),
 | 
			
		||||
				0,
 | 
			
		||||
				0,
 | 
			
		||||
			},
 | 
			
		||||
			true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"invalid vesting amount",
 | 
			
		||||
			args{
 | 
			
		||||
				app.GenesisState{},
 | 
			
		||||
				addr1,
 | 
			
		||||
				sdk.NewCoins(sdk.NewInt64Coin("stake", 50)),
 | 
			
		||||
				sdk.NewCoins(sdk.NewInt64Coin("stake", 100)),
 | 
			
		||||
				0,
 | 
			
		||||
				0,
 | 
			
		||||
			},
 | 
			
		||||
			true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"invalid vesting times",
 | 
			
		||||
			args{
 | 
			
		||||
				app.GenesisState{},
 | 
			
		||||
				addr1,
 | 
			
		||||
				sdk.NewCoins(sdk.NewInt64Coin("stake", 50)),
 | 
			
		||||
				sdk.NewCoins(sdk.NewInt64Coin("stake", 50)),
 | 
			
		||||
				1654668078,
 | 
			
		||||
				1554668078,
 | 
			
		||||
			},
 | 
			
		||||
			true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			_, err := addGenesisAccount(
 | 
			
		||||
				cdc, tt.args.appState, tt.args.addr, tt.args.coins,
 | 
			
		||||
				tt.args.vestingAmt, tt.args.vestingStart, tt.args.vestingEnd,
 | 
			
		||||
			)
 | 
			
		||||
			require.Equal(t, tt.wantErr, (err != nil))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										312
									
								
								init/gentx.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								init/gentx.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,312 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
// DONTCOVER
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
 | 
			
		||||
	cfg "github.com/tendermint/tendermint/config"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto"
 | 
			
		||||
	tmcli "github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/context"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/keys"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/utils"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	kbkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	defaultTokens                  = sdk.TokensFromTendermintPower(100)
 | 
			
		||||
	defaultAmount                  = defaultTokens.String() + sdk.DefaultBondDenom
 | 
			
		||||
	defaultCommissionRate          = "0.1"
 | 
			
		||||
	defaultCommissionMaxRate       = "0.2"
 | 
			
		||||
	defaultCommissionMaxChangeRate = "0.01"
 | 
			
		||||
	defaultMinSelfDelegation       = "1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GenTxCmd builds the kvd gentx command.
 | 
			
		||||
// nolint: errcheck
 | 
			
		||||
func GenTxCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:   "gentx",
 | 
			
		||||
		Short: "Generate a genesis tx carrying a self delegation",
 | 
			
		||||
		Args:  cobra.NoArgs,
 | 
			
		||||
		Long: fmt.Sprintf(`This command is an alias of the 'kvd tx create-validator' command'.
 | 
			
		||||
 | 
			
		||||
It creates a genesis piece carrying a self delegation with the
 | 
			
		||||
following delegation and commission default parameters:
 | 
			
		||||
 | 
			
		||||
	delegation amount:           %s
 | 
			
		||||
	commission rate:             %s
 | 
			
		||||
	commission max rate:         %s
 | 
			
		||||
	commission max change rate:  %s
 | 
			
		||||
	minimum self delegation:     %s
 | 
			
		||||
`, defaultAmount, defaultCommissionRate, defaultCommissionMaxRate, defaultCommissionMaxChangeRate, defaultMinSelfDelegation),
 | 
			
		||||
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
			
		||||
 | 
			
		||||
			config := ctx.Config
 | 
			
		||||
			config.SetRoot(viper.GetString(tmcli.HomeFlag))
 | 
			
		||||
			nodeID, valPubKey, err := InitializeNodeValidatorFiles(ctx.Config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Read --nodeID, if empty take it from priv_validator.json
 | 
			
		||||
			if nodeIDString := viper.GetString(cli.FlagNodeID); nodeIDString != "" {
 | 
			
		||||
				nodeID = nodeIDString
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ip := viper.GetString(cli.FlagIP)
 | 
			
		||||
			if ip == "" {
 | 
			
		||||
				fmt.Fprintf(os.Stderr, "couldn't retrieve an external IP; "+
 | 
			
		||||
					"the tx's memo field will be unset")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			genDoc, err := LoadGenesisDoc(cdc, config.GenesisFile())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			genesisState := app.GenesisState{}
 | 
			
		||||
			if err = cdc.UnmarshalJSON(genDoc.AppState, &genesisState); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err = app.ValidateGenesisState(genesisState); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			kb, err := keys.NewKeyBaseFromDir(viper.GetString(flagClientHome))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			name := viper.GetString(client.FlagName)
 | 
			
		||||
			key, err := kb.Get(name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Read --pubkey, if empty take it from priv_validator.json
 | 
			
		||||
			if valPubKeyString := viper.GetString(cli.FlagPubKey); valPubKeyString != "" {
 | 
			
		||||
				valPubKey, err = sdk.GetConsPubKeyBech32(valPubKeyString)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			website := viper.GetString(cli.FlagWebsite)
 | 
			
		||||
			details := viper.GetString(cli.FlagDetails)
 | 
			
		||||
			identity := viper.GetString(cli.FlagIdentity)
 | 
			
		||||
 | 
			
		||||
			// Set flags for creating gentx
 | 
			
		||||
			prepareFlagsForTxCreateValidator(config, nodeID, ip, genDoc.ChainID, valPubKey, website, details, identity)
 | 
			
		||||
 | 
			
		||||
			// Fetch the amount of coins staked
 | 
			
		||||
			amount := viper.GetString(cli.FlagAmount)
 | 
			
		||||
			coins, err := sdk.ParseCoins(amount)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = accountInGenesis(genesisState, key.GetAddress(), coins)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			txBldr := authtxb.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
 | 
			
		||||
			cliCtx := context.NewCLIContext().WithCodec(cdc)
 | 
			
		||||
 | 
			
		||||
			// XXX: Set the generate-only flag here after the CLI context has
 | 
			
		||||
			// been created. This allows the from name/key to be correctly populated.
 | 
			
		||||
			//
 | 
			
		||||
			// TODO: Consider removing the manual setting of generate-only in
 | 
			
		||||
			// favor of a 'gentx' flag in the create-validator command.
 | 
			
		||||
			viper.Set(client.FlagGenerateOnly, true)
 | 
			
		||||
 | 
			
		||||
			// create a 'create-validator' message
 | 
			
		||||
			txBldr, msg, err := cli.BuildCreateValidatorMsg(cliCtx, txBldr)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			info, err := txBldr.Keybase().Get(name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if info.GetType() == kbkeys.TypeOffline || info.GetType() == kbkeys.TypeMulti {
 | 
			
		||||
				fmt.Println("Offline key passed in. Use `kvcli tx sign` command to sign:")
 | 
			
		||||
				return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, true)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// write the unsigned transaction to the buffer
 | 
			
		||||
			w := bytes.NewBuffer([]byte{})
 | 
			
		||||
			cliCtx = cliCtx.WithOutput(w)
 | 
			
		||||
 | 
			
		||||
			if err = utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, true); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// read the transaction
 | 
			
		||||
			stdTx, err := readUnsignedGenTxFile(cdc, w)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// sign the transaction and write it to the output file
 | 
			
		||||
			signedTx, err := utils.SignStdTx(txBldr, cliCtx, name, stdTx, false, true)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Fetch output file name
 | 
			
		||||
			outputDocument := viper.GetString(client.FlagOutputDocument)
 | 
			
		||||
			if outputDocument == "" {
 | 
			
		||||
				outputDocument, err = makeOutputFilepath(config.RootDir, nodeID)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err := writeSignedGenTx(cdc, outputDocument, signedTx); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "Genesis transaction written to %q\n", outputDocument)
 | 
			
		||||
			return nil
 | 
			
		||||
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ip, _ := server.ExternalIP()
 | 
			
		||||
 | 
			
		||||
	cmd.Flags().String(tmcli.HomeFlag, app.DefaultNodeHome, "node's home directory")
 | 
			
		||||
	cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
 | 
			
		||||
	cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx")
 | 
			
		||||
	cmd.Flags().String(client.FlagOutputDocument, "",
 | 
			
		||||
		"write the genesis transaction JSON document to the given file instead of the default location")
 | 
			
		||||
	cmd.Flags().String(cli.FlagIP, ip, "The node's public IP")
 | 
			
		||||
	cmd.Flags().String(cli.FlagNodeID, "", "The node's NodeID")
 | 
			
		||||
	cmd.Flags().String(cli.FlagWebsite, "", "The validator's (optional) website")
 | 
			
		||||
	cmd.Flags().String(cli.FlagDetails, "", "The validator's (optional) details")
 | 
			
		||||
	cmd.Flags().String(cli.FlagIdentity, "", "The (optional) identity signature (ex. UPort or Keybase)")
 | 
			
		||||
	cmd.Flags().AddFlagSet(cli.FsCommissionCreate)
 | 
			
		||||
	cmd.Flags().AddFlagSet(cli.FsMinSelfDelegation)
 | 
			
		||||
	cmd.Flags().AddFlagSet(cli.FsAmount)
 | 
			
		||||
	cmd.Flags().AddFlagSet(cli.FsPk)
 | 
			
		||||
	cmd.MarkFlagRequired(client.FlagName)
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func accountInGenesis(genesisState app.GenesisState, key sdk.AccAddress, coins sdk.Coins) error {
 | 
			
		||||
	accountIsInGenesis := false
 | 
			
		||||
	bondDenom := genesisState.StakingData.Params.BondDenom
 | 
			
		||||
 | 
			
		||||
	// Check if the account is in genesis
 | 
			
		||||
	for _, acc := range genesisState.Accounts {
 | 
			
		||||
		// Ensure that account is in genesis
 | 
			
		||||
		if acc.Address.Equals(key) {
 | 
			
		||||
 | 
			
		||||
			// Ensure account contains enough funds of default bond denom
 | 
			
		||||
			if coins.AmountOf(bondDenom).GT(acc.Coins.AmountOf(bondDenom)) {
 | 
			
		||||
				return fmt.Errorf(
 | 
			
		||||
					"account %v is in genesis, but it only has %v%v available to stake, not %v%v",
 | 
			
		||||
					key.String(), acc.Coins.AmountOf(bondDenom), bondDenom, coins.AmountOf(bondDenom), bondDenom,
 | 
			
		||||
				)
 | 
			
		||||
			}
 | 
			
		||||
			accountIsInGenesis = true
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if accountIsInGenesis {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Errorf("account %s in not in the app_state.accounts array of genesis.json", key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func prepareFlagsForTxCreateValidator(
 | 
			
		||||
	config *cfg.Config, nodeID, ip, chainID string, valPubKey crypto.PubKey, website, details, identity string,
 | 
			
		||||
) {
 | 
			
		||||
	viper.Set(tmcli.HomeFlag, viper.GetString(flagClientHome))
 | 
			
		||||
	viper.Set(client.FlagChainID, chainID)
 | 
			
		||||
	viper.Set(client.FlagFrom, viper.GetString(client.FlagName))
 | 
			
		||||
	viper.Set(cli.FlagNodeID, nodeID)
 | 
			
		||||
	viper.Set(cli.FlagIP, ip)
 | 
			
		||||
	viper.Set(cli.FlagPubKey, sdk.MustBech32ifyConsPub(valPubKey))
 | 
			
		||||
	viper.Set(cli.FlagMoniker, config.Moniker)
 | 
			
		||||
	viper.Set(cli.FlagWebsite, website)
 | 
			
		||||
	viper.Set(cli.FlagDetails, details)
 | 
			
		||||
	viper.Set(cli.FlagIdentity, identity)
 | 
			
		||||
 | 
			
		||||
	if config.Moniker == "" {
 | 
			
		||||
		viper.Set(cli.FlagMoniker, viper.GetString(client.FlagName))
 | 
			
		||||
	}
 | 
			
		||||
	if viper.GetString(cli.FlagAmount) == "" {
 | 
			
		||||
		viper.Set(cli.FlagAmount, defaultAmount)
 | 
			
		||||
	}
 | 
			
		||||
	if viper.GetString(cli.FlagCommissionRate) == "" {
 | 
			
		||||
		viper.Set(cli.FlagCommissionRate, defaultCommissionRate)
 | 
			
		||||
	}
 | 
			
		||||
	if viper.GetString(cli.FlagCommissionMaxRate) == "" {
 | 
			
		||||
		viper.Set(cli.FlagCommissionMaxRate, defaultCommissionMaxRate)
 | 
			
		||||
	}
 | 
			
		||||
	if viper.GetString(cli.FlagCommissionMaxChangeRate) == "" {
 | 
			
		||||
		viper.Set(cli.FlagCommissionMaxChangeRate, defaultCommissionMaxChangeRate)
 | 
			
		||||
	}
 | 
			
		||||
	if viper.GetString(cli.FlagMinSelfDelegation) == "" {
 | 
			
		||||
		viper.Set(cli.FlagMinSelfDelegation, defaultMinSelfDelegation)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeOutputFilepath(rootDir, nodeID string) (string, error) {
 | 
			
		||||
	writePath := filepath.Join(rootDir, "config", "gentx")
 | 
			
		||||
	if err := common.EnsureDir(writePath, 0700); err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return filepath.Join(writePath, fmt.Sprintf("gentx-%v.json", nodeID)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readUnsignedGenTxFile(cdc *codec.Codec, r io.Reader) (auth.StdTx, error) {
 | 
			
		||||
	var stdTx auth.StdTx
 | 
			
		||||
	bytes, err := ioutil.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return stdTx, err
 | 
			
		||||
	}
 | 
			
		||||
	err = cdc.UnmarshalJSON(bytes, &stdTx)
 | 
			
		||||
	return stdTx, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nolint: errcheck
 | 
			
		||||
func writeSignedGenTx(cdc *codec.Codec, outputDocument string, tx auth.StdTx) error {
 | 
			
		||||
	outputFile, err := os.OpenFile(outputDocument, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer outputFile.Close()
 | 
			
		||||
	json, err := cdc.MarshalJSON(tx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = fmt.Fprintf(outputFile, "%s\n", json)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								init/gentx_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								init/gentx_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
 | 
			
		||||
	cfg "github.com/tendermint/tendermint/config"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Test_prepareFlagsForTxCreateValidator(t *testing.T) {
 | 
			
		||||
	defer server.SetupViper(t)()
 | 
			
		||||
	defer setupClientHome(t)()
 | 
			
		||||
	config, err := tcmd.ParseConfig()
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	logger := log.NewNopLogger()
 | 
			
		||||
	ctx := server.NewContext(config, logger)
 | 
			
		||||
 | 
			
		||||
	valPubKey, _ := sdk.GetConsPubKeyBech32("cosmosvalconspub1zcjduepq7jsrkl9fgqk0wj3ahmfr8pgxj6vakj2wzn656s8pehh0zhv2w5as5gd80a")
 | 
			
		||||
 | 
			
		||||
	type args struct {
 | 
			
		||||
		config    *cfg.Config
 | 
			
		||||
		nodeID    string
 | 
			
		||||
		ip        string
 | 
			
		||||
		chainID   string
 | 
			
		||||
		valPubKey crypto.PubKey
 | 
			
		||||
		website   string
 | 
			
		||||
		details   string
 | 
			
		||||
		identity  string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type extraParams struct {
 | 
			
		||||
		amount                  string
 | 
			
		||||
		commissionRate          string
 | 
			
		||||
		commissionMaxRate       string
 | 
			
		||||
		commissionMaxChangeRate string
 | 
			
		||||
		minSelfDelegation       string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type testcase struct {
 | 
			
		||||
		name string
 | 
			
		||||
		args args
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	runTest := func(t *testing.T, tt testcase, params extraParams) {
 | 
			
		||||
		prepareFlagsForTxCreateValidator(tt.args.config, tt.args.nodeID, tt.args.ip, tt.args.chainID, tt.args.valPubKey, tt.args.website, tt.args.details, tt.args.identity)
 | 
			
		||||
		require.Equal(t, tt.args.website, viper.GetString(cli.FlagWebsite))
 | 
			
		||||
		require.Equal(t, tt.args.details, viper.GetString(cli.FlagDetails))
 | 
			
		||||
		require.Equal(t, tt.args.identity, viper.GetString(cli.FlagIdentity))
 | 
			
		||||
		require.Equal(t, params.amount, viper.GetString(cli.FlagAmount))
 | 
			
		||||
		require.Equal(t, params.commissionRate, viper.GetString(cli.FlagCommissionRate))
 | 
			
		||||
		require.Equal(t, params.commissionMaxRate, viper.GetString(cli.FlagCommissionMaxRate))
 | 
			
		||||
		require.Equal(t, params.commissionMaxChangeRate, viper.GetString(cli.FlagCommissionMaxChangeRate))
 | 
			
		||||
		require.Equal(t, params.minSelfDelegation, viper.GetString(cli.FlagMinSelfDelegation))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []testcase{
 | 
			
		||||
		{"No parameters", args{ctx.Config, "X", "0.0.0.0", "chainId", valPubKey, "", "", ""}},
 | 
			
		||||
		{"Optional parameters fed", args{ctx.Config, "X", "0.0.0.0", "chainId", valPubKey, "cosmos.network", "details", "identity"}},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defaultParams := extraParams{defaultAmount, defaultCommissionRate, defaultCommissionMaxRate, defaultCommissionMaxChangeRate, defaultMinSelfDelegation}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) {
 | 
			
		||||
			t.Run(tt.name, func(t *testing.T) { runTest(t, tt, defaultParams) })
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Override default params
 | 
			
		||||
	params := extraParams{"5stake", "1.0", "1.0", "1.0", "1.0"}
 | 
			
		||||
	viper.Set(cli.FlagAmount, params.amount)
 | 
			
		||||
	viper.Set(cli.FlagCommissionRate, params.commissionRate)
 | 
			
		||||
	viper.Set(cli.FlagCommissionMaxRate, params.commissionMaxRate)
 | 
			
		||||
	viper.Set(cli.FlagCommissionMaxChangeRate, params.commissionMaxChangeRate)
 | 
			
		||||
	viper.Set(cli.FlagMinSelfDelegation, params.minSelfDelegation)
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		t.Run(tt.name, func(t *testing.T) { runTest(t, tt, params) })
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								init/init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								init/init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,95 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	cfg "github.com/tendermint/tendermint/config"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	flagOverwrite    = "overwrite"
 | 
			
		||||
	flagClientHome   = "home-client"
 | 
			
		||||
	flagVestingStart = "vesting-start-time"
 | 
			
		||||
	flagVestingEnd   = "vesting-end-time"
 | 
			
		||||
	flagVestingAmt   = "vesting-amount"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type printInfo struct {
 | 
			
		||||
	Moniker    string          `json:"moniker"`
 | 
			
		||||
	ChainID    string          `json:"chain_id"`
 | 
			
		||||
	NodeID     string          `json:"node_id"`
 | 
			
		||||
	GenTxsDir  string          `json:"gentxs_dir"`
 | 
			
		||||
	AppMessage json.RawMessage `json:"app_message"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func displayInfo(cdc *codec.Codec, info printInfo) error {
 | 
			
		||||
	out, err := codec.MarshalJSONIndent(cdc, info)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(os.Stderr, "%s\n", string(out)) // nolint: errcheck
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InitCmd returns a command that initializes all files needed for Tendermint
 | 
			
		||||
// and the respective application.
 | 
			
		||||
func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command { // nolint: golint
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:   "init [moniker]",
 | 
			
		||||
		Short: "Initialize private validator, p2p, genesis, and application configuration files",
 | 
			
		||||
		Long:  `Initialize validators's and node's configuration files.`,
 | 
			
		||||
		Args:  cobra.ExactArgs(1),
 | 
			
		||||
		RunE: func(_ *cobra.Command, args []string) error {
 | 
			
		||||
			config := ctx.Config
 | 
			
		||||
			config.SetRoot(viper.GetString(cli.HomeFlag))
 | 
			
		||||
 | 
			
		||||
			chainID := viper.GetString(client.FlagChainID)
 | 
			
		||||
			if chainID == "" {
 | 
			
		||||
				chainID = fmt.Sprintf("test-chain-%v", common.RandStr(6))
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			nodeID, _, err := InitializeNodeValidatorFiles(config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			config.Moniker = args[0]
 | 
			
		||||
 | 
			
		||||
			var appState json.RawMessage
 | 
			
		||||
			genFile := config.GenesisFile()
 | 
			
		||||
 | 
			
		||||
			if appState, err = initializeEmptyGenesis(cdc, genFile, chainID,
 | 
			
		||||
				viper.GetBool(flagOverwrite)); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err = ExportGenesisFile(genFile, chainID, nil, appState); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState)
 | 
			
		||||
 | 
			
		||||
			cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)
 | 
			
		||||
			return displayInfo(cdc, toPrint)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
 | 
			
		||||
	cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file")
 | 
			
		||||
	cmd.Flags().String(client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								init/init_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								init/init_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,136 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server/mock"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
	abciServer "github.com/tendermint/tendermint/abci/server"
 | 
			
		||||
	tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/cli"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestInitCmd(t *testing.T) {
 | 
			
		||||
	defer server.SetupViper(t)()
 | 
			
		||||
	defer setupClientHome(t)()
 | 
			
		||||
 | 
			
		||||
	logger := log.NewNopLogger()
 | 
			
		||||
	cfg, err := tcmd.ParseConfig()
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	ctx := server.NewContext(cfg, logger)
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
	cmd := InitCmd(ctx, cdc)
 | 
			
		||||
 | 
			
		||||
	require.NoError(t, cmd.RunE(nil, []string{"kavanode-test"}))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setupClientHome(t *testing.T) func() {
 | 
			
		||||
	clientDir, err := ioutil.TempDir("", "mock-sdk-cmd")
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	viper.Set(flagClientHome, clientDir)
 | 
			
		||||
	return func() {
 | 
			
		||||
		if err := os.RemoveAll(clientDir); err != nil {
 | 
			
		||||
			// TODO: Handle with #870
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestEmptyState(t *testing.T) {
 | 
			
		||||
	defer server.SetupViper(t)()
 | 
			
		||||
	defer setupClientHome(t)()
 | 
			
		||||
 | 
			
		||||
	logger := log.NewNopLogger()
 | 
			
		||||
	cfg, err := tcmd.ParseConfig()
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
 | 
			
		||||
	ctx := server.NewContext(cfg, logger)
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
 | 
			
		||||
	cmd := InitCmd(ctx, cdc)
 | 
			
		||||
	require.NoError(t, cmd.RunE(nil, []string{"kavanode-test"}))
 | 
			
		||||
 | 
			
		||||
	old := os.Stdout
 | 
			
		||||
	r, w, _ := os.Pipe()
 | 
			
		||||
	os.Stdout = w
 | 
			
		||||
	cmd = server.ExportCmd(ctx, cdc, nil)
 | 
			
		||||
 | 
			
		||||
	err = cmd.RunE(nil, nil)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	outC := make(chan string)
 | 
			
		||||
	go func() {
 | 
			
		||||
		var buf bytes.Buffer
 | 
			
		||||
		io.Copy(&buf, r)
 | 
			
		||||
		outC <- buf.String()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	w.Close()
 | 
			
		||||
	os.Stdout = old
 | 
			
		||||
	out := <-outC
 | 
			
		||||
	require.Contains(t, out, "genesis_time")
 | 
			
		||||
	require.Contains(t, out, "chain_id")
 | 
			
		||||
	require.Contains(t, out, "consensus_params")
 | 
			
		||||
	require.Contains(t, out, "validators")
 | 
			
		||||
	require.Contains(t, out, "app_hash")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestStartStandAlone(t *testing.T) {
 | 
			
		||||
	home, err := ioutil.TempDir("", "mock-sdk-cmd")
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		os.RemoveAll(home)
 | 
			
		||||
	}()
 | 
			
		||||
	viper.Set(cli.HomeFlag, home)
 | 
			
		||||
	defer setupClientHome(t)()
 | 
			
		||||
 | 
			
		||||
	logger := log.NewNopLogger()
 | 
			
		||||
	cfg, err := tcmd.ParseConfig()
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	ctx := server.NewContext(cfg, logger)
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
	initCmd := InitCmd(ctx, cdc)
 | 
			
		||||
	require.NoError(t, initCmd.RunE(nil, []string{"kavanode-test"}))
 | 
			
		||||
 | 
			
		||||
	app, err := mock.NewApp(home, logger)
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	svrAddr, _, err := server.FreeTCPAddr()
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	svr, err := abciServer.NewServer(svrAddr, "socket", app)
 | 
			
		||||
	require.Nil(t, err, "error creating listener")
 | 
			
		||||
	svr.SetLogger(logger.With("module", "abci-server"))
 | 
			
		||||
	svr.Start()
 | 
			
		||||
 | 
			
		||||
	timer := time.NewTimer(time.Duration(2) * time.Second)
 | 
			
		||||
	select {
 | 
			
		||||
	case <-timer.C:
 | 
			
		||||
		svr.Stop()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestInitNodeValidatorFiles(t *testing.T) {
 | 
			
		||||
	home, err := ioutil.TempDir("", "mock-sdk-cmd")
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		os.RemoveAll(home)
 | 
			
		||||
	}()
 | 
			
		||||
	viper.Set(cli.HomeFlag, home)
 | 
			
		||||
	viper.Set(client.FlagName, "moniker")
 | 
			
		||||
	cfg, err := tcmd.ParseConfig()
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	nodeID, valPubKey, err := InitializeNodeValidatorFiles(cfg)
 | 
			
		||||
	require.Nil(t, err)
 | 
			
		||||
	require.NotEqual(t, "", nodeID)
 | 
			
		||||
	require.NotEqual(t, 0, len(valPubKey.Bytes()))
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,4 @@
 | 
			
		||||
// Copyright 2016 All in Bits, inc
 | 
			
		||||
// Modifications copyright 2019 Kava Labs
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
// DONTCOVER
 | 
			
		||||
 | 
			
		||||
@ -12,6 +9,17 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/keys"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	srvconfig "github.com/cosmos/cosmos-sdk/server/config"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	authtx "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	tmconfig "github.com/tendermint/tendermint/config"
 | 
			
		||||
@ -20,17 +28,7 @@ import (
 | 
			
		||||
	"github.com/tendermint/tendermint/types"
 | 
			
		||||
	tmtime "github.com/tendermint/tendermint/types/time"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/keys"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	srvconfig "github.com/cosmos/cosmos-sdk/server/config"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/types/module"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/auth/genaccounts"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/genutil"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/staking"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
@ -38,17 +36,18 @@ var (
 | 
			
		||||
	flagNumValidators     = "v"
 | 
			
		||||
	flagOutputDir         = "output-dir"
 | 
			
		||||
	flagNodeDaemonHome    = "node-daemon-home"
 | 
			
		||||
	flagNodeCLIHome       = "node-cli-home"
 | 
			
		||||
	flagNodeCliHome       = "node-cli-home"
 | 
			
		||||
	flagStartingIPAddress = "starting-ip-address"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const nodeDirPerm = 0755
 | 
			
		||||
 | 
			
		||||
// get cmd to initialize all files for tendermint testnet and application
 | 
			
		||||
func testnetCmd(ctx *server.Context, cdc *codec.Codec,
 | 
			
		||||
	mbm module.BasicManager, genAccIterator genutil.GenesisAccountsIterator) *cobra.Command {
 | 
			
		||||
func TestnetFilesCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:   "testnet",
 | 
			
		||||
		Short: "Initialize files for a kvd testnet",
 | 
			
		||||
		Short: "Initialize files for a testnet",
 | 
			
		||||
		Long: `testnet will create "v" number of directories and populate each with
 | 
			
		||||
necessary files (private validator, genesis, config, etc.).
 | 
			
		||||
 | 
			
		||||
@ -59,49 +58,46 @@ Example:
 | 
			
		||||
	`,
 | 
			
		||||
		RunE: func(_ *cobra.Command, _ []string) error {
 | 
			
		||||
			config := ctx.Config
 | 
			
		||||
 | 
			
		||||
			outputDir := viper.GetString(flagOutputDir)
 | 
			
		||||
			chainID := viper.GetString(client.FlagChainID)
 | 
			
		||||
			minGasPrices := viper.GetString(server.FlagMinGasPrices)
 | 
			
		||||
			nodeDirPrefix := viper.GetString(flagNodeDirPrefix)
 | 
			
		||||
			nodeDaemonHome := viper.GetString(flagNodeDaemonHome)
 | 
			
		||||
			nodeCLIHome := viper.GetString(flagNodeCLIHome)
 | 
			
		||||
			startingIPAddress := viper.GetString(flagStartingIPAddress)
 | 
			
		||||
			numValidators := viper.GetInt(flagNumValidators)
 | 
			
		||||
 | 
			
		||||
			return InitTestnet(config, cdc, mbm, genAccIterator, outputDir, chainID, minGasPrices,
 | 
			
		||||
				nodeDirPrefix, nodeDaemonHome, nodeCLIHome, startingIPAddress, numValidators)
 | 
			
		||||
			return initTestnet(config, cdc)
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd.Flags().Int(flagNumValidators, 4,
 | 
			
		||||
		"Number of validators to initialize the testnet with")
 | 
			
		||||
		"Number of validators to initialize the testnet with",
 | 
			
		||||
	)
 | 
			
		||||
	cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet",
 | 
			
		||||
		"Directory to store initialization data for the testnet")
 | 
			
		||||
		"Directory to store initialization data for the testnet",
 | 
			
		||||
	)
 | 
			
		||||
	cmd.Flags().String(flagNodeDirPrefix, "node",
 | 
			
		||||
		"Prefix the directory name for each node with (node results in node0, node1, ...)")
 | 
			
		||||
		"Prefix the directory name for each node with (node results in node0, node1, ...)",
 | 
			
		||||
	)
 | 
			
		||||
	cmd.Flags().String(flagNodeDaemonHome, "kvd",
 | 
			
		||||
		"Home directory of the node's daemon configuration")
 | 
			
		||||
	cmd.Flags().String(flagNodeCLIHome, "kvcli",
 | 
			
		||||
		"Home directory of the node's cli configuration")
 | 
			
		||||
		"Home directory of the node's daemon configuration",
 | 
			
		||||
	)
 | 
			
		||||
	cmd.Flags().String(flagNodeCliHome, "kvcli",
 | 
			
		||||
		"Home directory of the node's cli configuration",
 | 
			
		||||
	)
 | 
			
		||||
	cmd.Flags().String(flagStartingIPAddress, "192.168.0.1",
 | 
			
		||||
		"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
 | 
			
		||||
 | 
			
		||||
	cmd.Flags().String(
 | 
			
		||||
		client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
 | 
			
		||||
		client.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created",
 | 
			
		||||
	)
 | 
			
		||||
	cmd.Flags().String(
 | 
			
		||||
		server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
 | 
			
		||||
		"Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)")
 | 
			
		||||
		"Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)",
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const nodeDirPerm = 0755
 | 
			
		||||
func initTestnet(config *tmconfig.Config, cdc *codec.Codec) error {
 | 
			
		||||
	var chainID string
 | 
			
		||||
 | 
			
		||||
// Initialize the testnet
 | 
			
		||||
func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicManager,
 | 
			
		||||
	genAccIterator genutil.GenesisAccountsIterator,
 | 
			
		||||
	outputDir, chainID, minGasPrices, nodeDirPrefix, nodeDaemonHome,
 | 
			
		||||
	nodeCLIHome, startingIPAddress string, numValidators int) error {
 | 
			
		||||
	outDir := viper.GetString(flagOutputDir)
 | 
			
		||||
	numValidators := viper.GetInt(flagNumValidators)
 | 
			
		||||
 | 
			
		||||
	chainID = viper.GetString(client.FlagChainID)
 | 
			
		||||
	if chainID == "" {
 | 
			
		||||
		chainID = "chain-" + cmn.RandStr(6)
 | 
			
		||||
	}
 | 
			
		||||
@ -111,46 +107,48 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
	valPubKeys := make([]crypto.PubKey, numValidators)
 | 
			
		||||
 | 
			
		||||
	appConfig := srvconfig.DefaultConfig()
 | 
			
		||||
	appConfig.MinGasPrices = minGasPrices
 | 
			
		||||
	appConfig.MinGasPrices = viper.GetString(server.FlagMinGasPrices)
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		accs     []genaccounts.GenesisAccount
 | 
			
		||||
		accs     []app.GenesisAccount
 | 
			
		||||
		genFiles []string
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// generate private keys, node IDs, and initial transactions
 | 
			
		||||
	for i := 0; i < numValidators; i++ {
 | 
			
		||||
		nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
 | 
			
		||||
		nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
 | 
			
		||||
		clientDir := filepath.Join(outputDir, nodeDirName, nodeCLIHome)
 | 
			
		||||
		gentxsDir := filepath.Join(outputDir, "gentxs")
 | 
			
		||||
		nodeDirName := fmt.Sprintf("%s%d", viper.GetString(flagNodeDirPrefix), i)
 | 
			
		||||
		nodeDaemonHomeName := viper.GetString(flagNodeDaemonHome)
 | 
			
		||||
		nodeCliHomeName := viper.GetString(flagNodeCliHome)
 | 
			
		||||
		nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
 | 
			
		||||
		clientDir := filepath.Join(outDir, nodeDirName, nodeCliHomeName)
 | 
			
		||||
		gentxsDir := filepath.Join(outDir, "gentxs")
 | 
			
		||||
 | 
			
		||||
		config.SetRoot(nodeDir)
 | 
			
		||||
 | 
			
		||||
		err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = os.MkdirAll(clientDir, nodeDirPerm)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		monikers = append(monikers, nodeDirName)
 | 
			
		||||
		config.Moniker = nodeDirName
 | 
			
		||||
 | 
			
		||||
		ip, err := getIP(i, startingIPAddress)
 | 
			
		||||
		ip, err := getIP(i, viper.GetString(flagStartingIPAddress))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(config)
 | 
			
		||||
		nodeIDs[i], valPubKeys[i], err = InitializeNodeValidatorFiles(config)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -159,7 +157,7 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
 | 
			
		||||
		buf := client.BufferStdin()
 | 
			
		||||
		prompt := fmt.Sprintf(
 | 
			
		||||
			"Password for account '%s' (default %s):", nodeDirName, client.DefaultKeyPass,
 | 
			
		||||
			"Password for account '%s' (default %s):", nodeDirName, app.DefaultKeyPass,
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		keyPass, err := client.GetPassword(prompt, buf)
 | 
			
		||||
@ -171,12 +169,12 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if keyPass == "" {
 | 
			
		||||
			keyPass = client.DefaultKeyPass
 | 
			
		||||
			keyPass = app.DefaultKeyPass
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		addr, secret, err := server.GenerateSaveCoinKey(clientDir, nodeDirName, keyPass, true)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -195,7 +193,7 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
 | 
			
		||||
		accTokens := sdk.TokensFromTendermintPower(1000)
 | 
			
		||||
		accStakingTokens := sdk.TokensFromTendermintPower(500)
 | 
			
		||||
		accs = append(accs, genaccounts.GenesisAccount{
 | 
			
		||||
		accs = append(accs, app.GenesisAccount{
 | 
			
		||||
			Address: addr,
 | 
			
		||||
			Coins: sdk.Coins{
 | 
			
		||||
				sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), accTokens),
 | 
			
		||||
@ -209,7 +207,7 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
			valPubKeys[i],
 | 
			
		||||
			sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
 | 
			
		||||
			staking.NewDescription(nodeDirName, "", "", ""),
 | 
			
		||||
			staking.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
 | 
			
		||||
			staking.NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
 | 
			
		||||
			sdk.OneInt(),
 | 
			
		||||
		)
 | 
			
		||||
		kb, err := keys.NewKeyBaseFromDir(clientDir)
 | 
			
		||||
@ -217,40 +215,38 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		tx := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo)
 | 
			
		||||
		txBldr := auth.NewTxBuilderFromCLI().WithChainID(chainID).WithMemo(memo).WithKeybase(kb)
 | 
			
		||||
		txBldr := authtx.NewTxBuilderFromCLI().WithChainID(chainID).WithMemo(memo).WithKeybase(kb)
 | 
			
		||||
 | 
			
		||||
		signedTx, err := txBldr.SignStdTx(nodeDirName, client.DefaultKeyPass, tx, false)
 | 
			
		||||
		signedTx, err := txBldr.SignStdTx(nodeDirName, app.DefaultKeyPass, tx, false)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		txBytes, err := cdc.MarshalJSON(signedTx)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// gather gentxs folder
 | 
			
		||||
		err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = os.RemoveAll(outputDir)
 | 
			
		||||
			_ = os.RemoveAll(outDir)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// TODO: Rename config file to server.toml as it's not particular to Gaia
 | 
			
		||||
		// (REF: https://github.com/cosmos/cosmos-sdk/issues/4125).
 | 
			
		||||
		appConfigFilePath := filepath.Join(nodeDir, "config/gaiad.toml")
 | 
			
		||||
		appConfigFilePath := filepath.Join(nodeDir, "config/kvd.toml")
 | 
			
		||||
		srvconfig.WriteConfigFile(appConfigFilePath, appConfig)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := initGenFiles(cdc, mbm, chainID, accs, genFiles, numValidators); err != nil {
 | 
			
		||||
	if err := initGenFiles(cdc, chainID, accs, genFiles, numValidators); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := collectGenFiles(
 | 
			
		||||
		cdc, config, chainID, monikers, nodeIDs, valPubKeys, numValidators,
 | 
			
		||||
		outputDir, nodeDirPrefix, nodeDaemonHome, genAccIterator,
 | 
			
		||||
		outDir, viper.GetString(flagNodeDirPrefix), viper.GetString(flagNodeDaemonHome),
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@ -260,13 +256,13 @@ func InitTestnet(config *tmconfig.Config, cdc *codec.Codec, mbm module.BasicMana
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initGenFiles(cdc *codec.Codec, mbm module.BasicManager, chainID string,
 | 
			
		||||
	accs []genaccounts.GenesisAccount, genFiles []string, numValidators int) error {
 | 
			
		||||
func initGenFiles(
 | 
			
		||||
	cdc *codec.Codec, chainID string, accs []app.GenesisAccount,
 | 
			
		||||
	genFiles []string, numValidators int,
 | 
			
		||||
) error {
 | 
			
		||||
 | 
			
		||||
	appGenState := mbm.DefaultGenesis()
 | 
			
		||||
 | 
			
		||||
	// set the accounts in the genesis state
 | 
			
		||||
	appGenState = genaccounts.SetGenesisStateInAppState(cdc, appGenState, accs)
 | 
			
		||||
	appGenState := app.NewDefaultGenesisState()
 | 
			
		||||
	appGenState.Accounts = accs
 | 
			
		||||
 | 
			
		||||
	appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@ -285,36 +281,37 @@ func initGenFiles(cdc *codec.Codec, mbm module.BasicManager, chainID string,
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func collectGenFiles(
 | 
			
		||||
	cdc *codec.Codec, config *tmconfig.Config, chainID string,
 | 
			
		||||
	monikers, nodeIDs []string, valPubKeys []crypto.PubKey,
 | 
			
		||||
	numValidators int, outputDir, nodeDirPrefix, nodeDaemonHome string,
 | 
			
		||||
	genAccIterator genutil.GenesisAccountsIterator) error {
 | 
			
		||||
	numValidators int, outDir, nodeDirPrefix, nodeDaemonHomeName string,
 | 
			
		||||
) error {
 | 
			
		||||
 | 
			
		||||
	var appState json.RawMessage
 | 
			
		||||
	genTime := tmtime.Now()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < numValidators; i++ {
 | 
			
		||||
		nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
 | 
			
		||||
		nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
 | 
			
		||||
		gentxsDir := filepath.Join(outputDir, "gentxs")
 | 
			
		||||
		nodeDir := filepath.Join(outDir, nodeDirName, nodeDaemonHomeName)
 | 
			
		||||
		gentxsDir := filepath.Join(outDir, "gentxs")
 | 
			
		||||
		moniker := monikers[i]
 | 
			
		||||
		config.Moniker = nodeDirName
 | 
			
		||||
 | 
			
		||||
		config.SetRoot(nodeDir)
 | 
			
		||||
 | 
			
		||||
		nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
 | 
			
		||||
		initCfg := genutil.NewInitConfig(chainID, gentxsDir, moniker, nodeID, valPubKey)
 | 
			
		||||
		initCfg := newInitConfig(chainID, gentxsDir, moniker, nodeID, valPubKey)
 | 
			
		||||
 | 
			
		||||
		genDoc, err := types.GenesisDocFromFile(config.GenesisFile())
 | 
			
		||||
		genDoc, err := LoadGenesisDoc(cdc, config.GenesisFile())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		nodeAppState, err := genutil.GenAppStateFromConfig(cdc, config, initCfg, *genDoc, genAccIterator)
 | 
			
		||||
		nodeAppState, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
@ -327,7 +324,7 @@ func collectGenFiles(
 | 
			
		||||
		genFile := config.GenesisFile()
 | 
			
		||||
 | 
			
		||||
		// overwrite each validator's genesis file to have a canonical genesis time
 | 
			
		||||
		err = genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime)
 | 
			
		||||
		err = ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
@ -336,28 +333,25 @@ func collectGenFiles(
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getIP(i int, startingIPAddr string) (ip string, err error) {
 | 
			
		||||
func getIP(i int, startingIPAddr string) (string, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		ip  string
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if len(startingIPAddr) == 0 {
 | 
			
		||||
		ip, err = server.ExternalIP()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		return ip, nil
 | 
			
		||||
	}
 | 
			
		||||
	return calculateIP(startingIPAddr, i)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calculateIP(ip string, i int) (string, error) {
 | 
			
		||||
	ipv4 := net.ParseIP(ip).To4()
 | 
			
		||||
	if ipv4 == nil {
 | 
			
		||||
		return "", fmt.Errorf("%v: non ipv4 address", ip)
 | 
			
		||||
	} else {
 | 
			
		||||
		ip, err = calculateIP(startingIPAddr, i)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for j := 0; j < i; j++ {
 | 
			
		||||
		ipv4[3]++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ipv4.String(), nil
 | 
			
		||||
	return ip, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func writeFile(name string, dir string, contents []byte) error {
 | 
			
		||||
@ -376,3 +370,16 @@ func writeFile(name string, dir string, contents []byte) error {
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calculateIP(ip string, i int) (string, error) {
 | 
			
		||||
	ipv4 := net.ParseIP(ip).To4()
 | 
			
		||||
	if ipv4 == nil {
 | 
			
		||||
		return "", fmt.Errorf("%v: non ipv4 address", ip)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for j := 0; j < i; j++ {
 | 
			
		||||
		ipv4[3]++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ipv4.String(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								init/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								init/utils.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	amino "github.com/tendermint/go-amino"
 | 
			
		||||
	cfg "github.com/tendermint/tendermint/config"
 | 
			
		||||
	"github.com/tendermint/tendermint/crypto"
 | 
			
		||||
	"github.com/tendermint/tendermint/libs/common"
 | 
			
		||||
	"github.com/tendermint/tendermint/p2p"
 | 
			
		||||
	"github.com/tendermint/tendermint/privval"
 | 
			
		||||
	"github.com/tendermint/tendermint/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ExportGenesisFile creates and writes the genesis configuration to disk. An
 | 
			
		||||
// error is returned if building or writing the configuration to file fails.
 | 
			
		||||
func ExportGenesisFile(
 | 
			
		||||
	genFile, chainID string, validators []types.GenesisValidator, appState json.RawMessage,
 | 
			
		||||
) error {
 | 
			
		||||
 | 
			
		||||
	genDoc := types.GenesisDoc{
 | 
			
		||||
		ChainID:    chainID,
 | 
			
		||||
		Validators: validators,
 | 
			
		||||
		AppState:   appState,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := genDoc.ValidateAndComplete(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return genDoc.SaveAs(genFile)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExportGenesisFileWithTime creates and writes the genesis configuration to disk.
 | 
			
		||||
// An error is returned if building or writing the configuration to file fails.
 | 
			
		||||
func ExportGenesisFileWithTime(
 | 
			
		||||
	genFile, chainID string, validators []types.GenesisValidator,
 | 
			
		||||
	appState json.RawMessage, genTime time.Time,
 | 
			
		||||
) error {
 | 
			
		||||
 | 
			
		||||
	genDoc := types.GenesisDoc{
 | 
			
		||||
		GenesisTime: genTime,
 | 
			
		||||
		ChainID:     chainID,
 | 
			
		||||
		Validators:  validators,
 | 
			
		||||
		AppState:    appState,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := genDoc.ValidateAndComplete(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return genDoc.SaveAs(genFile)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
 | 
			
		||||
func InitializeNodeValidatorFiles(
 | 
			
		||||
	config *cfg.Config) (nodeID string, valPubKey crypto.PubKey, err error,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
	nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nodeID, valPubKey, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nodeID = string(nodeKey.ID())
 | 
			
		||||
	server.UpgradeOldPrivValFile(config)
 | 
			
		||||
 | 
			
		||||
	pvKeyFile := config.PrivValidatorKeyFile()
 | 
			
		||||
	if err := common.EnsureDir(filepath.Dir(pvKeyFile), 0777); err != nil {
 | 
			
		||||
		return nodeID, valPubKey, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pvStateFile := config.PrivValidatorStateFile()
 | 
			
		||||
	if err := common.EnsureDir(filepath.Dir(pvStateFile), 0777); err != nil {
 | 
			
		||||
		return nodeID, valPubKey, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	valPubKey = privval.LoadOrGenFilePV(pvKeyFile, pvStateFile).GetPubKey()
 | 
			
		||||
 | 
			
		||||
	return nodeID, valPubKey, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadGenesisDoc reads and unmarshals GenesisDoc from the given file.
 | 
			
		||||
func LoadGenesisDoc(cdc *amino.Codec, genFile string) (genDoc types.GenesisDoc, err error) {
 | 
			
		||||
	genContents, err := ioutil.ReadFile(genFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return genDoc, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := cdc.UnmarshalJSON(genContents, &genDoc); err != nil {
 | 
			
		||||
		return genDoc, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return genDoc, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initializeEmptyGenesis(
 | 
			
		||||
	cdc *codec.Codec, genFile, chainID string, overwrite bool,
 | 
			
		||||
) (appState json.RawMessage, err error) {
 | 
			
		||||
 | 
			
		||||
	if !overwrite && common.FileExists(genFile) {
 | 
			
		||||
		return nil, fmt.Errorf("genesis.json file already exists: %v", genFile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return codec.MarshalJSONIndent(cdc, app.NewDefaultGenesisState())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								init/utils_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								init/utils_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/tests"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestExportGenesisFileWithTime(t *testing.T) {
 | 
			
		||||
	t.Parallel()
 | 
			
		||||
	dir, cleanup := tests.NewTestCaseDir(t)
 | 
			
		||||
	defer cleanup()
 | 
			
		||||
 | 
			
		||||
	fname := filepath.Join(dir, "genesis.json")
 | 
			
		||||
	require.NoError(t, ExportGenesisFileWithTime(fname, "test", nil, json.RawMessage(""), time.Now()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestLoadGenesisDoc(t *testing.T) {
 | 
			
		||||
	t.Parallel()
 | 
			
		||||
	dir, cleanup := tests.NewTestCaseDir(t)
 | 
			
		||||
	defer cleanup()
 | 
			
		||||
 | 
			
		||||
	fname := filepath.Join(dir, "genesis.json")
 | 
			
		||||
	require.NoError(t, ExportGenesisFileWithTime(fname, "test", nil, json.RawMessage(""), time.Now()))
 | 
			
		||||
 | 
			
		||||
	_, err := LoadGenesisDoc(codec.Cdc, fname)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	// Non-existing file
 | 
			
		||||
	_, err = LoadGenesisDoc(codec.Cdc, "non-existing-file")
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
 | 
			
		||||
	malformedFilename := filepath.Join(dir, "malformed")
 | 
			
		||||
	malformedFile, err := os.Create(malformedFilename)
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	fmt.Fprint(malformedFile, "invalidjson")
 | 
			
		||||
	malformedFile.Close()
 | 
			
		||||
	// Non-existing file
 | 
			
		||||
	_, err = LoadGenesisDoc(codec.Cdc, malformedFilename)
 | 
			
		||||
	require.Error(t, err)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								init/validate_genesis.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								init/validate_genesis.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
package init
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/codec"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/server"
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/tendermint/tendermint/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Validate genesis command takes
 | 
			
		||||
func ValidateGenesisCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
 | 
			
		||||
	return &cobra.Command{
 | 
			
		||||
		Use:   "validate-genesis [file]",
 | 
			
		||||
		Args:  cobra.RangeArgs(0, 1),
 | 
			
		||||
		Short: "validates the genesis file at the default location or at the location passed as an arg",
 | 
			
		||||
		RunE: func(cmd *cobra.Command, args []string) (err error) {
 | 
			
		||||
 | 
			
		||||
			// Load default if passed no args, otherwise load passed file
 | 
			
		||||
			var genesis string
 | 
			
		||||
			if len(args) == 0 {
 | 
			
		||||
				genesis = ctx.Config.GenesisFile()
 | 
			
		||||
			} else {
 | 
			
		||||
				genesis = args[0]
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//nolint
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "validating genesis file at %s\n", genesis)
 | 
			
		||||
 | 
			
		||||
			var genDoc types.GenesisDoc
 | 
			
		||||
			if genDoc, err = LoadGenesisDoc(cdc, genesis); err != nil {
 | 
			
		||||
				return fmt.Errorf("Error loading genesis doc from %s: %s", genesis, err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var genstate app.GenesisState
 | 
			
		||||
			if err = cdc.UnmarshalJSON(genDoc.AppState, &genstate); err != nil {
 | 
			
		||||
				return fmt.Errorf("Error unmarshaling genesis doc %s: %s", genesis, err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if err = app.ValidateGenesisState(genstate); err != nil {
 | 
			
		||||
				return fmt.Errorf("Error validating genesis file %s: %s", genesis, err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			fmt.Printf("File at %s is a valid genesis file for kvd\n", genesis)
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								kava-logo.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								kava-logo.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 | 
			
		||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 | 
			
		||||
	 width="725px" height="213px" viewBox="0 0 725 213" enable-background="new 0 0 725 213" xml:space="preserve">
 | 
			
		||||
<g>
 | 
			
		||||
	<g opacity="0.2">
 | 
			
		||||
		<polygon fill="#FF564F" points="30,213 111.625,106.851 30,0 20.246,38.336 72.809,106.851 22.664,171.296 		"/>
 | 
			
		||||
	</g>
 | 
			
		||||
	<g>
 | 
			
		||||
		<polygon fill="#FF564F" points="154.344,213 72.211,106.851 154.125,0 193,0 111.027,106.851 193.625,213 		"/>
 | 
			
		||||
	</g>
 | 
			
		||||
	<g>
 | 
			
		||||
		<rect fill="#FF564F" width="30" height="213"/>
 | 
			
		||||
	</g>
 | 
			
		||||
	<g>
 | 
			
		||||
		<path fill="#FF564F" d="M288.04,39.144c-12.1,0-23.001,1.318-32.403,3.917c-9.313,2.58-18.633,6.056-27.701,10.332l-2.473,1.167
 | 
			
		||||
			l9.252,25.495l2.977-1.405c7.314-3.451,14.881-6.231,22.489-8.262c7.549-2.01,16.08-3.028,25.355-3.028
 | 
			
		||||
			c14.401,0,25.424,3.462,33.168,10.29C326.336,84.381,330,94.554,330,107.887v1.038c-6-1.637-12.337-2.99-18.681-4.032
 | 
			
		||||
			c-7.742-1.272-16.909-1.918-27.45-1.918c-10.432,0-20.067,1.193-28.741,3.548c-8.765,2.384-16.429,5.904-22.829,10.463
 | 
			
		||||
			c-6.528,4.646-11.531,10.538-15.07,17.512c-3.538,6.964-5.23,15.158-5.23,24.357v0.626c0,8.815,1.772,16.671,5.445,23.348
 | 
			
		||||
			c3.632,6.604,8.441,12.239,14.38,16.745c5.909,4.489,12.749,7.867,20.369,10.039c7.543,2.152,15.284,3.244,23.028,3.244
 | 
			
		||||
			c14.647,0,26.893-2.927,36.813-8.698c7.052-4.105,12.965-8.749,17.965-13.859V213h30V107.539c0-21.171-5.885-37.887-17.68-49.682
 | 
			
		||||
			C329.902,45.439,311.703,39.144,288.04,39.144z M280.081,187.145c-5.101,0-10.005-0.691-14.581-2.057
 | 
			
		||||
			c-4.535-1.347-8.585-3.293-12.042-5.786c-3.356-2.419-5.818-5.483-7.772-9.111c-1.935-3.584-2.686-7.661-2.686-12.118v-0.626
 | 
			
		||||
			c0-8.815,3.391-15.708,10.839-21.071c7.658-5.517,18.654-8.313,32.907-8.313c9.735,0,18.548,0.716,26.031,2.128
 | 
			
		||||
			c6.664,1.263,12.223,2.613,18.223,4.023v12.649c0,5.912-1.437,11.356-3.999,16.185c-2.594,4.894-6.277,9.184-10.81,12.751
 | 
			
		||||
			c-4.585,3.604-10.025,6.423-16.101,8.377C293.978,186.146,287.223,187.145,280.081,187.145z"/>
 | 
			
		||||
		<polygon fill="#FF564F" points="473.281,171.271 420.85,42 387.678,42 461.364,213 484.532,213 558.564,42 526.015,42 		"/>
 | 
			
		||||
		<path fill="#FF564F" d="M707.237,57.857c-12.418-12.418-30.707-18.714-54.369-18.714c-12.1,0-22.999,1.318-32.4,3.917
 | 
			
		||||
			c-9.313,2.58-18.631,6.056-27.7,10.332l-2.472,1.167l9.252,25.495l2.978-1.405c7.314-3.451,14.881-6.231,22.489-8.262
 | 
			
		||||
			c7.549-2.01,16.08-3.028,25.355-3.028c14.401,0,25.507,3.462,33.251,10.29C691.253,84.381,695,94.554,695,107.887v1.038
 | 
			
		||||
			c-6-1.637-12.42-2.99-18.764-4.032c-7.742-1.272-16.951-1.918-27.491-1.918c-10.432,0-20.088,1.193-28.762,3.548
 | 
			
		||||
			c-8.765,2.384-16.439,5.904-22.839,10.463c-6.528,4.646-11.453,10.538-14.992,17.512c-3.538,6.964-5.152,15.158-5.152,24.357
 | 
			
		||||
			v0.626c0,8.815,1.689,16.671,5.362,23.348c3.632,6.604,8.399,12.239,14.339,16.745c5.909,4.489,12.728,7.867,20.348,10.039
 | 
			
		||||
			c7.543,2.152,15.273,3.244,23.017,3.244c14.647,0,26.971-2.927,36.891-8.698c7.052-4.105,13.043-8.749,18.043-13.859V213h30
 | 
			
		||||
			V107.539C725,86.368,719.032,69.652,707.237,57.857z M644.915,187.145c-5.101,0-10.005-0.691-14.581-2.057
 | 
			
		||||
			c-4.535-1.347-8.585-3.293-12.042-5.786c-3.356-2.419-6.235-5.483-8.189-9.111c-1.935-3.584-3.103-7.661-3.103-12.118v-0.626
 | 
			
		||||
			c0-8.815,3.808-15.708,11.256-21.071c7.658-5.517,18.862-8.313,33.116-8.313c9.735,0,18.735,0.716,26.218,2.128
 | 
			
		||||
			c6.664,1.263,12.41,2.613,18.41,4.023v12.649c0,5.912-1.52,11.356-4.082,16.185c-2.594,4.894-6.318,9.184-10.852,12.751
 | 
			
		||||
			c-4.585,3.604-10.046,6.423-16.122,8.377C658.833,186.146,652.057,187.145,644.915,187.145z"/>
 | 
			
		||||
	</g>
 | 
			
		||||
</g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 3.7 KiB  | 
		Loading…
	
		Reference in New Issue
	
	Block a user