Skip to content

Commit

Permalink
feat: Add prepare-genesis command (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
vitsalis authored Oct 19, 2022
1 parent ae35adf commit 6c97e59
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 37 deletions.
56 changes: 56 additions & 0 deletions cmd/babylond/cmd/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package cmd

import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/spf13/cobra"
tmrand "github.com/tendermint/tendermint/libs/rand"
)

type GenesisCLIArgs struct {
ChainID string
MaxActiveValidators uint32
BtcConfirmationDepth uint64
BtcFinalizationTimeout uint64
EpochInterval uint64
BaseBtcHeaderHex string
BaseBtcHeaderHeight uint64
}

func addGenesisFlags(cmd *cobra.Command) {
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
// staking flags
cmd.Flags().Uint32(flagMaxActiveValidators, 10, "Maximum number of validators.")
// btccheckpoint flags
cmd.Flags().Uint64(flagBtcConfirmationDepth, 6, "Confirmation depth for Bitcoin headers.")
cmd.Flags().Uint64(flagBtcFinalizationTimeout, 20, "Finalization timeout for Bitcoin headers.")
// epoch args
cmd.Flags().Uint64(flagEpochInterval, 400, "Number of blocks between epochs. Must be more than 0.")
// btclightclient args
// Genesis header for the simnet
cmd.Flags().String(flagBaseBtcHeaderHex, "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a45068653ffff7f2002000000", "Hex of the base Bitcoin header.")
cmd.Flags().Uint64(flagBaseBtcHeaderHeight, 0, "Height of the base Bitcoin header.")
}

func parseGenesisFlags(cmd *cobra.Command) *GenesisCLIArgs {
chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
maxActiveValidators, _ := cmd.Flags().GetUint32(flagMaxActiveValidators)
btcConfirmationDepth, _ := cmd.Flags().GetUint64(flagBtcConfirmationDepth)
btcFinalizationTimeout, _ := cmd.Flags().GetUint64(flagBtcFinalizationTimeout)
epochInterval, _ := cmd.Flags().GetUint64(flagEpochInterval)
baseBtcHeaderHex, _ := cmd.Flags().GetString(flagBaseBtcHeaderHex)
baseBtcHeaderHeight, _ := cmd.Flags().GetUint64(flagBaseBtcHeaderHeight)

if chainID == "" {
chainID = "chain-" + tmrand.NewRand().Str(6)
}

return &GenesisCLIArgs{
ChainID: chainID,
MaxActiveValidators: maxActiveValidators,
BtcConfirmationDepth: btcConfirmationDepth,
BtcFinalizationTimeout: btcFinalizationTimeout,
EpochInterval: epochInterval,
BaseBtcHeaderHeight: baseBtcHeaderHeight,
BaseBtcHeaderHex: baseBtcHeaderHex,
}
}
81 changes: 77 additions & 4 deletions cmd/babylond/cmd/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,94 @@ import (
checkpointingtypes "github.com/babylonchain/babylon/x/checkpointing/types"
epochingtypes "github.com/babylonchain/babylon/x/epoching/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/client/flags"
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/types"
)

func PrepareGenesis(clientCtx client.Context, appState map[string]json.RawMessage, genesisParams GenesisParams) (map[string]json.RawMessage, error) {
func PrepareGenesisCmd(defaultNodeHome string, mbm module.BasicManager) *cobra.Command {
cmd := &cobra.Command{
Use: "prepare-genesis <testnet|mainnet> <chain-id>",
Args: cobra.ExactArgs(2),
Short: "Prepare a genesis file",
Long: `Prepare a genesis file.
Example:
babylond prepare-genesis testnet babylon-test-1
`,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config

genesisCliArgs := parseGenesisFlags(cmd)

genFile := config.GenesisFile()
appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile)
if err != nil {
return fmt.Errorf("failed to unmarshal genesis state: %s", err)
}

network := args[0]
chainID := args[1]

var genesisParams GenesisParams
if network == "testnet" {
genesisParams = TestnetGenesisParams(genesisCliArgs.MaxActiveValidators,
genesisCliArgs.BtcConfirmationDepth, genesisCliArgs.BtcFinalizationTimeout,
genesisCliArgs.EpochInterval, genesisCliArgs.BaseBtcHeaderHex,
genesisCliArgs.BaseBtcHeaderHeight)
} else if network == "mainnet" {
// TODO: mainnet genesis params
} else {
return fmt.Errorf("please choose testnet or mainnet")
}

appState, genDoc, err = PrepareGenesis(clientCtx, appState, genDoc, genesisParams, chainID)

if err = mbm.ValidateGenesis(clientCtx.Codec, clientCtx.TxConfig, appState); err != nil {
return fmt.Errorf("error validating genesis file: %s", err)
}

appStateJSON, err := json.Marshal(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(flags.FlagHome, defaultNodeHome, "The application home directory")
addGenesisFlags(cmd)

return cmd
}

func PrepareGenesis(clientCtx client.Context, appState map[string]json.RawMessage,
genDoc *types.GenesisDoc, genesisParams GenesisParams, chainID string) (map[string]json.RawMessage, *types.GenesisDoc, error) {

depCdc := clientCtx.Codec
cdc := depCdc

// Add ChainID
genDoc.ChainID = chainID

// Set the confirmation and finalization parameters
btccheckpointGenState := btccheckpointtypes.DefaultGenesis()
btccheckpointGenState.Params = genesisParams.BtccheckpointParams
Expand Down Expand Up @@ -85,7 +158,7 @@ func PrepareGenesis(clientCtx client.Context, appState map[string]json.RawMessag
appState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankGenState)

// return appState
return appState, nil
return appState, genDoc, nil
}

type GenesisParams struct {
Expand All @@ -97,7 +170,7 @@ type GenesisParams struct {
GovParams govtypes.Params

CrisisConstantFee sdk.Coin
AuthAccounts []*types.Any
AuthAccounts []*cdctypes.Any
BankGenBalances []banktypes.Balance
CheckpointingGenKeys []*checkpointingtypes.GenesisKey

Expand Down
1 change: 1 addition & 0 deletions cmd/babylond/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
genutilcli.MigrateGenesisCmd(),
genutilcli.GenTxCmd(app.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome),
genutilcli.ValidateGenesisCmd(app.ModuleBasics),
PrepareGenesisCmd(app.DefaultNodeHome, app.ModuleBasics),
AddGenesisAccountCmd(app.DefaultNodeHome),
tmcli.NewCompletionCmd(rootCmd, true),
testnetCmd(app.ModuleBasics, banktypes.GenesisBalancesIterator{}),
Expand Down
43 changes: 10 additions & 33 deletions cmd/babylond/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,24 @@ import (
"errors"
"fmt"
appparams "github.com/babylonchain/babylon/app/params"
txformat "github.com/babylonchain/babylon/btctxformatter"
bbn "github.com/babylonchain/babylon/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"net"
"os"
"path/filepath"

"github.com/babylonchain/babylon/app"
txformat "github.com/babylonchain/babylon/btctxformatter"
"github.com/cosmos/cosmos-sdk/crypto/hd"

"github.com/babylonchain/babylon/privval"
"github.com/babylonchain/babylon/testutil/datagen"
bbn "github.com/babylonchain/babylon/types"
checkpointingtypes "github.com/babylonchain/babylon/x/checkpointing/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"

"github.com/spf13/cobra"
tmconfig "github.com/tendermint/tendermint/config"
tmos "github.com/tendermint/tendermint/libs/os"
tmrand "github.com/tendermint/tendermint/libs/rand"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"

Expand Down Expand Up @@ -84,38 +83,30 @@ Example:

serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
genesisCliArgs := parseGenesisFlags(cmd)

outputDir, _ := cmd.Flags().GetString(flagOutputDir)
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices)
nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix)
nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome)
startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress)
numValidators, _ := cmd.Flags().GetInt(flagNumValidators)
algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
// staking args
maxActiveValidators, _ := cmd.Flags().GetUint32(flagMaxActiveValidators)
// btccheckpoint args
btcNetwork, _ := cmd.Flags().GetString(flagBtcNetwork)
btcCheckpointTag, _ := cmd.Flags().GetString(flagBtcCheckpointTag)
btcConfirmationDepth, _ := cmd.Flags().GetUint64(flagBtcConfirmationDepth)
btcFinalizationTimeout, _ := cmd.Flags().GetUint64(flagBtcFinalizationTimeout)
// epoching args
epochInterval, _ := cmd.Flags().GetUint64(flagEpochInterval)
// btclightclient args
baseBtcHeaderHex, _ := cmd.Flags().GetString(flagBaseBtcHeaderHex)
baseBtcHeaderHeight, err := cmd.Flags().GetUint64(flagBaseBtcHeaderHeight)
additionalAccount, _ := cmd.Flags().GetBool(flagAdditionalSenderAccount)
if err != nil {
return errors.New("base Bitcoin header height should be a uint64")
}

genesisParams := TestnetGenesisParams(maxActiveValidators, btcConfirmationDepth,
btcFinalizationTimeout, epochInterval, baseBtcHeaderHex, baseBtcHeaderHeight)
genesisParams := TestnetGenesisParams(genesisCliArgs.MaxActiveValidators,
genesisCliArgs.BtcConfirmationDepth, genesisCliArgs.BtcFinalizationTimeout,
genesisCliArgs.EpochInterval, genesisCliArgs.BaseBtcHeaderHex,
genesisCliArgs.BaseBtcHeaderHeight)

return InitTestnet(
clientCtx, cmd, config, mbm, genBalIterator, outputDir, chainID, minGasPrices,
clientCtx, cmd, config, mbm, genBalIterator, outputDir, genesisCliArgs.ChainID, minGasPrices,
nodeDirPrefix, nodeDaemonHome, startingIPAddress, keyringBackend, algo, numValidators,
btcNetwork, btcCheckpointTag, additionalAccount, genesisParams,
)
Expand All @@ -127,23 +118,13 @@ Example:
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "babylond", "Home directory of the node's daemon 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(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", appparams.BaseCoinUnit), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.001bbn)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
// btccheckpoint args
cmd.Flags().String(flagBtcNetwork, string(bbn.BtcSimnet), "Bitcoin network to use. Available networks: simnet, testnet, mainnet")
cmd.Flags().String(flagBtcCheckpointTag, string(txformat.DefaultTestTagStr), "Tag to use for Bitcoin checkpoints.")
cmd.Flags().Uint64(flagBtcConfirmationDepth, 6, "Confirmation depth for Bitcoin headers.")
cmd.Flags().Uint64(flagBtcFinalizationTimeout, 20, "Finalization timeout for Bitcoin headers.")
// epoch args
cmd.Flags().Uint64(flagEpochInterval, 10, "Number of blocks between epochs. Must be more than 0.")
// btclightclient args
// Simnet genesis header
cmd.Flags().String(flagBaseBtcHeaderHex, "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a45068653ffff7f2002000000", "Hex of the base Bitcoin header.")
cmd.Flags().Uint64(flagBaseBtcHeaderHeight, 0, "Height of the base Bitcoin header.")
cmd.Flags().Uint32(flagMaxActiveValidators, 10, "Maximum number of validators.")
cmd.Flags().Bool(flagAdditionalSenderAccount, false, "If there should be additional pre funded account per validator")
addGenesisFlags(cmd)

return cmd
}
Expand Down Expand Up @@ -172,10 +153,6 @@ func InitTestnet(
genesisParams GenesisParams,
) error {

if chainID == "" {
chainID = "chain-" + tmrand.NewRand().Str(6)
}

nodeIDs := make([]string, numValidators)
valKeys := make([]*privval.ValidatorKeys, numValidators)

Expand Down Expand Up @@ -413,7 +390,7 @@ func initGenFiles(
// set the bls keys for the checkpointing module
genesisParams.CheckpointingGenKeys = genKeys

appGenState, err = PrepareGenesis(clientCtx, appGenState, genesisParams)
appGenState, _, err = PrepareGenesis(clientCtx, appGenState, &types.GenesisDoc{}, genesisParams, chainID)
if err != nil {
return err
}
Expand Down

0 comments on commit 6c97e59

Please sign in to comment.