Some checks failed
Docs Deploy / build_and_deploy (push) Has been cancelled
Generate Docs / cli (push) Has been cancelled
Generate Config Doc / cli (push) Has been cancelled
Go formatting / go-formatting (push) Has been cancelled
Check links / markdown-link-check (push) Has been cancelled
Integration / pre-test (push) Has been cancelled
Integration / test on (push) Has been cancelled
Integration / status (push) Has been cancelled
Lint / Lint Go code (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
166 lines
4.6 KiB
Go
166 lines
4.6 KiB
Go
package ignitecmd
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
"strconv"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/spf13/cobra"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
cmdmodel "git.cw.tr/mukan-network/mukan-ignite/ignite/cmd/bubblemodel"
|
|
igcfg "git.cw.tr/mukan-network/mukan-ignite/ignite/config"
|
|
v1 "git.cw.tr/mukan-network/mukan-ignite/ignite/config/chain/v1"
|
|
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/availableport"
|
|
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cliui"
|
|
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/xfilepath"
|
|
"git.cw.tr/mukan-network/mukan-ignite/ignite/services/chain"
|
|
)
|
|
|
|
const (
|
|
flagNodeDirPrefix = "node-dir-prefix"
|
|
)
|
|
|
|
func NewTestnetMultiNode() *cobra.Command {
|
|
c := &cobra.Command{
|
|
Use: "multi-node",
|
|
Short: "Initialize and provide multi-node on/off functionality",
|
|
Long: `Initialize the test network with the number of nodes and bonded from the config.yml file::
|
|
...
|
|
validators:
|
|
- name: alice
|
|
bonded: 100000000stake
|
|
- name: validator1
|
|
bonded: 100000000stake
|
|
- name: validator2
|
|
bonded: 200000000stake
|
|
- name: validator3
|
|
bonded: 300000000stake
|
|
|
|
|
|
The "multi-node" command allows developers to easily set up, initialize, and manage multiple nodes for a
|
|
testnet environment. This command provides full flexibility in enabling or disabling each node as desired,
|
|
making it a powerful tool for simulating a multi-node blockchain network during development.
|
|
|
|
Usage:
|
|
ignite testnet multi-node [flags]
|
|
|
|
`,
|
|
Args: cobra.NoArgs,
|
|
RunE: testnetMultiNodeHandler,
|
|
}
|
|
flagSetPath(c)
|
|
flagSetClearCache(c)
|
|
c.Flags().AddFlagSet(flagSetHome())
|
|
c.Flags().AddFlagSet(flagSetCheckDependencies())
|
|
c.Flags().AddFlagSet(flagSetSkipProto())
|
|
c.Flags().AddFlagSet(flagSetVerbose())
|
|
c.Flags().BoolP(flagResetOnce, "r", false, "reset the app state once on init")
|
|
c.Flags().String(flagNodeDirPrefix, "validator", "prefix of dir node")
|
|
|
|
return c
|
|
}
|
|
|
|
func testnetMultiNodeHandler(cmd *cobra.Command, _ []string) error {
|
|
session := cliui.New(
|
|
cliui.WithVerbosity(getVerbosity(cmd)),
|
|
cliui.WithoutUserInteraction(getYes(cmd)),
|
|
)
|
|
defer session.End()
|
|
|
|
return testnetMultiNode(cmd, session)
|
|
}
|
|
|
|
func testnetMultiNode(cmd *cobra.Command, session *cliui.Session) error {
|
|
chainOption := []chain.Option{
|
|
chain.WithOutputer(session),
|
|
chain.CollectEvents(session.EventBus()),
|
|
chain.CheckCosmosSDKVersion(),
|
|
}
|
|
|
|
if flagGetCheckDependencies(cmd) {
|
|
chainOption = append(chainOption, chain.CheckDependencies())
|
|
}
|
|
|
|
// check if custom config is defined
|
|
config, _ := cmd.Flags().GetString(flagConfig)
|
|
if config != "" {
|
|
chainOption = append(chainOption, chain.ConfigFile(config))
|
|
}
|
|
|
|
c, err := chain.NewWithHomeFlags(cmd, chainOption...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg, err := c.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
numVal, amountDetails, err := getValidatorAmountStake(cfg.Validators)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix)
|
|
|
|
outputDir, err := xfilepath.Join(igcfg.DirPath, xfilepath.Path(path.Join("local-chains", c.Name(), "testnet")))()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ports, err := availableport.Find(uint(numVal)) //nolint:gosec,nolintlint // conversion is fine
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
args := chain.MultiNodeArgs{
|
|
OutputDir: outputDir,
|
|
NumValidator: strconv.Itoa(numVal),
|
|
ValidatorsStakeAmount: amountDetails,
|
|
NodeDirPrefix: nodeDirPrefix,
|
|
ListPorts: ports,
|
|
}
|
|
|
|
resetOnce, _ := cmd.Flags().GetBool(flagResetOnce)
|
|
if resetOnce {
|
|
// If resetOnce is true, the app state will be reset by deleting the output directory.
|
|
if err := os.RemoveAll(outputDir); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err = c.TestnetMultiNode(cmd.Context(), args); err != nil {
|
|
return err
|
|
}
|
|
|
|
model, err := cmdmodel.NewModel(cmd.Context(), c.Name(), args)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = tea.NewProgram(model, tea.WithInput(cmd.InOrStdin())).Run()
|
|
return err
|
|
}
|
|
|
|
// getValidatorAmountStake returns the number of validators and the amountStakes arg from config.MultiNode.
|
|
func getValidatorAmountStake(validators []v1.Validator) (int, string, error) {
|
|
numVal := len(validators)
|
|
var amounts string
|
|
|
|
for _, v := range validators {
|
|
stakeAmount, err := sdk.ParseCoinNormalized(v.Bonded)
|
|
if err != nil {
|
|
return numVal, amounts, err
|
|
}
|
|
if amounts == "" {
|
|
amounts = stakeAmount.Amount.String()
|
|
} else {
|
|
amounts = amounts + "," + stakeAmount.Amount.String()
|
|
}
|
|
}
|
|
|
|
return numVal, amounts, nil
|
|
}
|