parent
758cdd2206
commit
50f81b173b
14
Makefile
14
Makefile
|
@ -22,7 +22,19 @@ all: tools build lint test
|
|||
|
||||
build: go.sum
|
||||
@go build -mod=readonly ./...
|
||||
.PHONY: build
|
||||
|
||||
build-sim: go.sum
|
||||
ifeq ($(OS),Windows_NT)
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/simd.exe ./simapp/cmd/simd
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/simcli.exe ./simapp/cmd/simcli
|
||||
else
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/simd ./simapp/cmd/simd
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/simcli ./simapp/cmd/simcli
|
||||
endif
|
||||
|
||||
.PHONY: \
|
||||
build \
|
||||
build-sim
|
||||
|
||||
mocks: $(MOCKS_DIR)
|
||||
mockgen -source=x/auth/types/account_retriever.go -package mocks -destination tests/mocks/account_retriever.go
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/client/lcd"
|
||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
codecstd "github.com/cosmos/cosmos-sdk/codec/std"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
||||
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
cdc = codecstd.MakeCodec(simapp.ModuleBasics)
|
||||
appCodec = codecstd.NewAppCodec(cdc)
|
||||
)
|
||||
|
||||
func init() {
|
||||
authclient.Codec = appCodec
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Configure cobra to sort commands
|
||||
cobra.EnableCommandSorting = false
|
||||
|
||||
// Read in the configuration file for the sdk
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
|
||||
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
|
||||
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
|
||||
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
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "simcli",
|
||||
Short: "Command line interface for interacting with simd",
|
||||
}
|
||||
|
||||
// Add --chain-id to persistent flags and mark it required
|
||||
rootCmd.PersistentFlags().String(flags.FlagChainID, "", "Chain ID of tendermint node")
|
||||
rootCmd.PersistentPreRunE = func(_ *cobra.Command, _ []string) error {
|
||||
return initConfig(rootCmd)
|
||||
}
|
||||
|
||||
// Construct Root Command
|
||||
rootCmd.AddCommand(
|
||||
rpc.StatusCommand(),
|
||||
client.ConfigCmd(simapp.DefaultCLIHome),
|
||||
queryCmd(cdc),
|
||||
txCmd(cdc),
|
||||
flags.LineBreak,
|
||||
lcd.ServeCommand(cdc, registerRoutes),
|
||||
flags.LineBreak,
|
||||
keys.Commands(),
|
||||
flags.LineBreak,
|
||||
flags.NewCompletionCmd(rootCmd, true),
|
||||
)
|
||||
|
||||
// Add flags and prefix all env exposed with GA
|
||||
executor := cli.PrepareMainCmd(rootCmd, "GA", simapp.DefaultCLIHome)
|
||||
|
||||
err := executor.Execute()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed executing CLI command: %s, exiting...\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func queryCmd(cdc *amino.Codec) *cobra.Command {
|
||||
queryCmd := &cobra.Command{
|
||||
Use: "query",
|
||||
Aliases: []string{"q"},
|
||||
Short: "Querying subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
queryCmd.AddCommand(
|
||||
authcmd.GetAccountCmd(cdc),
|
||||
flags.LineBreak,
|
||||
rpc.ValidatorCommand(cdc),
|
||||
rpc.BlockCommand(),
|
||||
authcmd.QueryTxsByEventsCmd(cdc),
|
||||
authcmd.QueryTxCmd(cdc),
|
||||
flags.LineBreak,
|
||||
)
|
||||
|
||||
// add modules' query commands
|
||||
simapp.ModuleBasics.AddQueryCommands(queryCmd, cdc)
|
||||
|
||||
return queryCmd
|
||||
}
|
||||
|
||||
func txCmd(cdc *amino.Codec) *cobra.Command {
|
||||
txCmd := &cobra.Command{
|
||||
Use: "tx",
|
||||
Short: "Transactions subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
txCmd.AddCommand(
|
||||
bankcmd.SendTxCmd(cdc),
|
||||
flags.LineBreak,
|
||||
authcmd.GetSignCommand(cdc),
|
||||
authcmd.GetMultiSignCommand(cdc),
|
||||
flags.LineBreak,
|
||||
authcmd.GetBroadcastCommand(cdc),
|
||||
authcmd.GetEncodeCommand(cdc),
|
||||
authcmd.GetDecodeCommand(cdc),
|
||||
flags.LineBreak,
|
||||
)
|
||||
|
||||
// add modules' tx commands
|
||||
simapp.ModuleBasics.AddTxCommands(txCmd, cdc)
|
||||
|
||||
return txCmd
|
||||
}
|
||||
|
||||
// registerRoutes registers the routes from the different modules for the REST client.
|
||||
// NOTE: details on the routes added for each module are in the module documentation
|
||||
func registerRoutes(rs *lcd.RestServer) {
|
||||
client.RegisterRoutes(rs.CliCtx, rs.Mux)
|
||||
authrest.RegisterTxRoutes(rs.CliCtx, rs.Mux)
|
||||
simapp.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
|
||||
}
|
||||
|
||||
func initConfig(cmd *cobra.Command) error {
|
||||
home, err := cmd.PersistentFlags().GetString(cli.HomeFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfgFile := path.Join(home, "config", "config.toml")
|
||||
if _, err := os.Stat(cfgFile); err == nil {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := viper.BindPFlag(flags.FlagChainID, cmd.PersistentFlags().Lookup(flags.FlagChainID)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := viper.BindPFlag(cli.EncodingFlag, cmd.PersistentFlags().Lookup(cli.EncodingFlag)); err != nil {
|
||||
return err
|
||||
}
|
||||
return viper.BindPFlag(cli.OutputFlag, cmd.PersistentFlags().Lookup(cli.OutputFlag))
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/go-amino"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
codecstd "github.com/cosmos/cosmos-sdk/codec/std"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
)
|
||||
|
||||
const (
|
||||
flagClientHome = "home-client"
|
||||
flagVestingStart = "vesting-start-time"
|
||||
flagVestingEnd = "vesting-end-time"
|
||||
flagVestingAmt = "vesting-amount"
|
||||
)
|
||||
|
||||
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
|
||||
func AddGenesisAccountCmd(
|
||||
ctx *server.Context, depCdc *amino.Codec, cdc *codecstd.Codec, defaultNodeHome, defaultClientHome string,
|
||||
) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
|
||||
Short: "Add a genesis account to genesis.json",
|
||||
Long: `Add a genesis account to genesis.json. The provided account must specify
|
||||
the account address or key name and a list of initial coins. If a key name is given,
|
||||
the address will be looked up in the local Keybase. The list of initial tokens must
|
||||
contain valid denominations. Accounts may optionally be supplied with vesting parameters.
|
||||
`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
config := ctx.Config
|
||||
config.SetRoot(viper.GetString(cli.HomeFlag))
|
||||
|
||||
addr, err := sdk.AccAddressFromBech32(args[0])
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
if err != nil {
|
||||
// attempt to lookup address from Keybase if no address was provided
|
||||
kb, err := keyring.New(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
viper.GetString(flagClientHome),
|
||||
inBuf,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := kb.Key(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get address from Keybase: %w", err)
|
||||
}
|
||||
|
||||
addr = info.GetAddress()
|
||||
}
|
||||
|
||||
coins, err := sdk.ParseCoins(args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse coins: %w", err)
|
||||
}
|
||||
|
||||
vestingStart := viper.GetInt64(flagVestingStart)
|
||||
vestingEnd := viper.GetInt64(flagVestingEnd)
|
||||
vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse vesting amount: %w", err)
|
||||
}
|
||||
|
||||
// create concrete account type based on input parameters
|
||||
var genAccount authexported.GenesisAccount
|
||||
|
||||
balances := bank.Balance{Address: addr, Coins: coins.Sort()}
|
||||
baseAccount := auth.NewBaseAccount(addr, nil, 0, 0)
|
||||
if !vestingAmt.IsZero() {
|
||||
baseVestingAccount := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd)
|
||||
|
||||
if (balances.Coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) ||
|
||||
baseVestingAccount.OriginalVesting.IsAnyGT(balances.Coins) {
|
||||
return errors.New("vesting amount cannot be greater than total amount")
|
||||
}
|
||||
|
||||
switch {
|
||||
case vestingStart != 0 && vestingEnd != 0:
|
||||
genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart)
|
||||
|
||||
case vestingEnd != 0:
|
||||
genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount)
|
||||
|
||||
default:
|
||||
return errors.New("invalid vesting parameters; must supply start and end time or end time")
|
||||
}
|
||||
} else {
|
||||
genAccount = baseAccount
|
||||
}
|
||||
|
||||
if err := genAccount.Validate(); err != nil {
|
||||
return fmt.Errorf("failed to validate new genesis account: %w", err)
|
||||
}
|
||||
|
||||
genFile := config.GenesisFile()
|
||||
appState, genDoc, err := genutil.GenesisStateFromGenFile(depCdc, genFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal genesis state: %w", err)
|
||||
}
|
||||
|
||||
authGenState := auth.GetGenesisStateFromAppState(cdc, appState)
|
||||
|
||||
if authGenState.Accounts.Contains(addr) {
|
||||
return fmt.Errorf("cannot add account at existing address %s", addr)
|
||||
}
|
||||
|
||||
// Add the new account to the set of genesis accounts and sanitize the
|
||||
// accounts afterwards.
|
||||
authGenState.Accounts = append(authGenState.Accounts, genAccount)
|
||||
authGenState.Accounts = auth.SanitizeGenesisAccounts(authGenState.Accounts)
|
||||
|
||||
authGenStateBz, err := cdc.MarshalJSON(authGenState)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal auth genesis state: %w", err)
|
||||
}
|
||||
|
||||
appState[auth.ModuleName] = authGenStateBz
|
||||
|
||||
bankGenState := bank.GetGenesisStateFromAppState(depCdc, appState)
|
||||
bankGenState.Balances = append(bankGenState.Balances, balances)
|
||||
bankGenState.Balances = bank.SanitizeGenesisBalances(bankGenState.Balances)
|
||||
|
||||
bankGenStateBz, err := cdc.MarshalJSON(bankGenState)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal bank genesis state: %w", err)
|
||||
}
|
||||
|
||||
appState[bank.ModuleName] = bankGenStateBz
|
||||
|
||||
appStateJSON, err := cdc.MarshalJSON(appState)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal application genesis state: %w", err)
|
||||
}
|
||||
|
||||
genDoc.AppState = appStateJSON
|
||||
return genutil.ExportGenesisFile(genDoc, genFile)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
cmd.Flags().String(flagClientHome, defaultClientHome, "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
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client/debug"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
codecstd "github.com/cosmos/cosmos-sdk/codec/std"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
)
|
||||
|
||||
const flagInvCheckPeriod = "inv-check-period"
|
||||
|
||||
var invCheckPeriod uint
|
||||
|
||||
func main() {
|
||||
cdc := codecstd.MakeCodec(simapp.ModuleBasics)
|
||||
appCodec := codecstd.NewAppCodec(cdc)
|
||||
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
|
||||
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
|
||||
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
|
||||
config.Seal()
|
||||
|
||||
ctx := server.NewDefaultContext()
|
||||
cobra.EnableCommandSorting = false
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "simd",
|
||||
Short: "Simulation Daemon (server)",
|
||||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
|
||||
rootCmd.AddCommand(
|
||||
genutilcli.InitCmd(ctx, cdc, simapp.ModuleBasics, simapp.DefaultNodeHome),
|
||||
genutilcli.CollectGenTxsCmd(ctx, cdc, bank.GenesisBalancesIterator{}, simapp.DefaultNodeHome),
|
||||
genutilcli.MigrateGenesisCmd(ctx, cdc),
|
||||
genutilcli.GenTxCmd(
|
||||
ctx, cdc, simapp.ModuleBasics, staking.AppModuleBasic{},
|
||||
bank.GenesisBalancesIterator{}, simapp.DefaultNodeHome, simapp.DefaultCLIHome,
|
||||
),
|
||||
genutilcli.ValidateGenesisCmd(ctx, cdc, simapp.ModuleBasics),
|
||||
AddGenesisAccountCmd(ctx, cdc, appCodec, simapp.DefaultNodeHome, simapp.DefaultCLIHome),
|
||||
flags.NewCompletionCmd(rootCmd, true),
|
||||
debug.Cmd(cdc))
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
|
||||
|
||||
// prepare and add flags
|
||||
executor := cli.PrepareBaseCmd(rootCmd, "GA", simapp.DefaultNodeHome)
|
||||
rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
|
||||
0, "Assert registered invariants every N blocks")
|
||||
err := executor.Execute()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application {
|
||||
var cache sdk.MultiStorePersistentCache
|
||||
|
||||
if viper.GetBool(server.FlagInterBlockCache) {
|
||||
cache = store.NewCommitKVStoreCacheManager()
|
||||
}
|
||||
|
||||
skipUpgradeHeights := make(map[int64]bool)
|
||||
for _, h := range viper.GetIntSlice(server.FlagUnsafeSkipUpgrades) {
|
||||
skipUpgradeHeights[int64(h)] = true
|
||||
}
|
||||
|
||||
return simapp.NewSimApp(
|
||||
logger, db, traceStore, true, skipUpgradeHeights,
|
||||
viper.GetString(flags.FlagHome), invCheckPeriod,
|
||||
baseapp.SetPruning(store.NewPruningOptionsFromString(viper.GetString("pruning"))),
|
||||
baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
|
||||
baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)),
|
||||
baseapp.SetHaltTime(viper.GetUint64(server.FlagHaltTime)),
|
||||
baseapp.SetInterBlockCache(cache),
|
||||
)
|
||||
}
|
||||
|
||||
func exportAppStateAndTMValidators(
|
||||
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string,
|
||||
) (json.RawMessage, []tmtypes.GenesisValidator, *abci.ConsensusParams, error) {
|
||||
|
||||
var simApp *simapp.SimApp
|
||||
if height != -1 {
|
||||
simApp = simapp.NewSimApp(logger, db, traceStore, false, map[int64]bool{}, "", uint(1))
|
||||
err := simApp.LoadHeight(height)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
} else {
|
||||
simApp = simapp.NewSimApp(logger, db, traceStore, true, map[int64]bool{}, "", uint(1))
|
||||
}
|
||||
return simApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
|
||||
}
|
Loading…
Reference in New Issue