mukan-ignite/ignite/services/chain/runtime.go
Mukan Erkin Törük c32551b6f7
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
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:24 +03:00

248 lines
6.8 KiB
Go

package chain
import (
"context"
"os"
"path/filepath"
"github.com/nqd/flat"
"github.com/pelletier/go-toml"
sdktypes "github.com/cosmos/cosmos-sdk/types"
chainconfig "git.cw.tr/mukan-network/mukan-ignite/ignite/config/chain"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/chaincmd"
chaincmdrunner "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/chaincmd/runner"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/xurl"
)
// Gentx wraps the "testd gentx" command for generating a gentx for a validator.
// Returns path of generated gentx.
func (c Chain) Gentx(ctx context.Context, runner chaincmdrunner.Runner, v Validator) (path string, err error) {
return runner.Gentx(
ctx,
v.Name,
v.StakingAmount,
chaincmd.GentxWithMoniker(v.Moniker),
chaincmd.GentxWithCommissionRate(v.CommissionRate),
chaincmd.GentxWithCommissionMaxRate(v.CommissionMaxRate),
chaincmd.GentxWithCommissionMaxChangeRate(v.CommissionMaxChangeRate),
chaincmd.GentxWithMinSelfDelegation(v.MinSelfDelegation),
chaincmd.GentxWithGasPrices(v.GasPrices),
chaincmd.GentxWithDetails(v.Details),
chaincmd.GentxWithIdentity(v.Identity),
chaincmd.GentxWithWebsite(v.Website),
chaincmd.GentxWithSecurityContact(v.SecurityContact),
)
}
func (c Chain) InPlace(ctx context.Context, runner chaincmdrunner.Runner, args InPlaceArgs) error {
err := runner.InPlace(ctx,
args.NewChainID,
args.NewOperatorAddress,
chaincmd.InPlaceWithPrvKey(args.PrvKeyValidator),
chaincmd.InPlaceWithAccountToFund(args.AccountsToFund),
chaincmd.InPlaceWithSkipConfirmation(),
)
return err
}
// MultiNode sets up multiple nodes in the chain network with the specified arguments and returns an error if any issue occurs.
func (c Chain) MultiNode(ctx context.Context, runner chaincmdrunner.Runner, args MultiNodeArgs) error {
err := runner.MultiNode(ctx,
chaincmd.MultiNodeWithDirOutput(args.OutputDir),
chaincmd.MultiNodeWithNumValidator(args.NumValidator),
chaincmd.MultiNodeWithValidatorsStakeAmount(args.ValidatorsStakeAmount),
chaincmd.MultiNodeDirPrefix(args.NodeDirPrefix),
chaincmd.MultiNodePorts(args.ConvertPorts()),
)
return err
}
// Start wraps the "appd start" command to begin running a chain from the daemon.
func (c Chain) Start(ctx context.Context, runner chaincmdrunner.Runner, cfg *chainconfig.Config) error {
validator, err := chainconfig.FirstValidator(cfg)
if err != nil {
return err
}
servers, err := validator.GetServers()
if err != nil {
return err
}
err = runner.Start(ctx, "--pruning", "nothing", "--grpc.address", servers.GRPC.Address)
return &CannotStartAppError{runner.Cmd().Name(), err}
}
// Configure sets the runtime configurations files for a chain (app.toml, client.toml, config.toml).
func (c Chain) Configure(homePath, chainID string, cfg *chainconfig.Config) error {
if err := appTOML(homePath, cfg); err != nil {
return err
}
if err := clientTOML(homePath, chainID, cfg); err != nil {
return err
}
return configTOML(homePath, cfg)
}
func appTOML(homePath string, cfg *chainconfig.Config) error {
validator, err := chainconfig.FirstValidator(cfg)
if err != nil {
return err
}
// TODO find a better way in order to not delete comments in the toml.yml
path := filepath.Join(homePath, "config/app.toml")
appConfig, err := toml.LoadFile(path)
if err != nil {
return err
}
servers, err := validator.GetServers()
if err != nil {
return err
}
apiAddr, err := xurl.TCP(servers.API.Address)
if err != nil {
return errors.Errorf("invalid api address format %s: %w", servers.API.Address, err)
}
// Set default config values
appConfig.Set("api.enable", true)
appConfig.Set("api.enabled-unsafe-cors", true)
appConfig.Set("rpc.cors_allowed_origins", []string{"*"})
staked, err := sdktypes.ParseCoinNormalized(validator.Bonded)
if err != nil {
return err
}
gas := sdktypes.NewInt64Coin(staked.Denom, 0)
appConfig.Set("minimum-gas-prices", gas.String())
// Update config values with the validator's Cosmos SDK app config
if err := updateTomlTreeValues(appConfig, validator.App); err != nil {
return err
}
// Make sure the API address have the protocol prefix
appConfig.Set("api.address", apiAddr)
file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0o644)
if err != nil {
return err
}
defer file.Close()
_, err = appConfig.WriteTo(file)
return err
}
func configTOML(homePath string, cfg *chainconfig.Config) error {
validator, err := chainconfig.FirstValidator(cfg)
if err != nil {
return err
}
// TODO find a better way in order to not delete comments in the toml.yml
path := filepath.Join(homePath, "config/config.toml")
tmConfig, err := toml.LoadFile(path)
if err != nil {
return err
}
servers, err := validator.GetServers()
if err != nil {
return err
}
rpcAddr, err := xurl.TCP(servers.RPC.Address)
if err != nil {
return errors.Errorf("invalid rpc address format %s: %w", servers.RPC.Address, err)
}
p2pAddr, err := xurl.TCP(servers.P2P.Address)
if err != nil {
return errors.Errorf("invalid p2p address format %s: %w", servers.P2P.Address, err)
}
// Set default config values
tmConfig.Set("mode", "validator")
tmConfig.Set("rpc.cors_allowed_origins", []string{"*"})
tmConfig.Set("consensus.timeout_commit", "1s")
tmConfig.Set("consensus.timeout_propose", "1s")
// Update config values with the validator's Tendermint config
if err := updateTomlTreeValues(tmConfig, validator.Config); err != nil {
return err
}
// Make sure the addresses have the protocol prefix
tmConfig.Set("rpc.laddr", rpcAddr)
tmConfig.Set("p2p.laddr", p2pAddr)
file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0o644)
if err != nil {
return err
}
defer file.Close()
_, err = tmConfig.WriteTo(file)
return err
}
func clientTOML(homePath, chainID string, cfg *chainconfig.Config) error {
validator, err := chainconfig.FirstValidator(cfg)
if err != nil {
return err
}
path := filepath.Join(homePath, "config/client.toml")
clientConfig, err := toml.LoadFile(path)
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
// Set default config values
clientConfig.Set("chain-id", chainID)
clientConfig.Set("keyring-backend", "test")
clientConfig.Set("broadcast-mode", "sync")
// Update config values with the validator's client config
if err := updateTomlTreeValues(clientConfig, validator.Client); err != nil {
return err
}
file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0o644)
if err != nil {
return err
}
defer file.Close()
_, err = clientConfig.WriteTo(file)
return err
}
func (c Chain) appHome() string {
home, _ := os.UserHomeDir()
return filepath.Join(home, "."+c.app.Name)
}
func updateTomlTreeValues(t *toml.Tree, values map[string]interface{}) error {
flatValues, err := flat.Flatten(values, nil)
if err != nil {
return err
}
for name, v := range flatValues {
t.Set(name, v)
}
return nil
}