mukan-ignite/ignite/services/chain/init.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

333 lines
8.5 KiB
Go

package chain
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"dario.cat/mergo"
chainconfig "git.cw.tr/mukan-network/mukan-ignite/ignite/config/chain"
chaincmdrunner "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/chaincmd/runner"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cliui/view/accountview"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/confile"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/events"
)
type (
// InitArgs represents argument to add additional initialization for the chain.
// InitAccounts initializes chain accounts from the Ignite config.
// InitConfiguration initializes node configuration from the Ignite config.
// InitGenesis initializes genesis state for the chain from Ignite config.
InitArgs struct {
InitAccounts bool
InitConfiguration bool
InitGenesis bool
}
)
const (
moniker = "mynode"
)
var (
// InitArgsAll performs all initialization for the chain.
InitArgsAll = InitArgs{
InitAccounts: true,
InitConfiguration: true,
InitGenesis: true,
}
// InitArgsNone performs minimal initialization for the chain by only initializing a node.
InitArgsNone = InitArgs{
InitAccounts: false,
InitConfiguration: false,
InitGenesis: false,
}
)
// Init initializes the chain and accounts.
func (c *Chain) Init(ctx context.Context, args InitArgs) error {
if err := c.InitChain(ctx, args.InitConfiguration, args.InitGenesis); err != nil {
return err
}
if args.InitAccounts {
conf, err := c.Config()
if err != nil {
return &CannotBuildAppError{err}
}
return c.InitAccounts(ctx, conf)
}
return nil
}
// InitChain initializes the chain.
func (c *Chain) InitChain(ctx context.Context, initConfiguration, initGenesis bool) error {
chainID, err := c.ID()
if err != nil {
return err
}
// cleanup persistent data from previous `serve`.
home, err := c.Home()
if err != nil {
return err
}
if err := os.RemoveAll(home); err != nil {
return err
}
var conf *chainconfig.Config
if initConfiguration || initGenesis {
conf, err = c.Config()
if err != nil {
return err
}
}
commands, err := c.Commands(ctx)
if err != nil {
return err
}
// init node.
var initOptions []string
if denom := conf.DefaultDenom; len(denom) > 0 {
initOptions = append(initOptions,
fmt.Sprintf("--default-denom=%s", denom),
)
}
if err := commands.Init(ctx, moniker, initOptions...); err != nil {
return err
}
// overwrite app config files with the values defined in Ignite's config file
if initConfiguration {
if err := c.Configure(home, chainID, conf); err != nil {
return err
}
}
if initGenesis {
// make sure that chain id given during chain.New() has the most priority.
if conf.Genesis != nil {
conf.Genesis["chain_id"] = chainID
}
// update genesis file with the genesis values defined in the config
if err := c.UpdateGenesisFile(conf.Genesis); err != nil {
return err
}
}
return nil
}
// InitAccounts initializes the chain accounts and creates validator gentxs.
func (c *Chain) InitAccounts(ctx context.Context, cfg *chainconfig.Config) error {
commands, err := c.Commands(ctx)
if err != nil {
return err
}
c.ev.Send("Initializing accounts...", events.ProgressUpdate())
var accounts accountview.Accounts
// add accounts from config into genesis
for _, account := range cfg.Accounts {
var generatedAccount chaincmdrunner.Account
accountAddress := account.Address
// If the account doesn't provide an address, we create one
if accountAddress == "" {
generatedAccount, err = commands.AddAccount(
ctx,
account.Name,
account.Mnemonic,
account.CoinType,
account.AccountNumber,
account.AddressIndex,
)
if err != nil {
return err
}
accountAddress = generatedAccount.Address
}
coins := strings.Join(account.Coins, ",")
if err := commands.AddGenesisAccount(ctx, accountAddress, coins); err != nil {
return err
}
if account.Address == "" {
accounts = accounts.Append(accountview.NewAccount(
generatedAccount.Name,
accountAddress,
accountview.WithMnemonic(generatedAccount.Mnemonic),
))
} else {
accounts = accounts.Append(accountview.NewAccount(account.Name, accountAddress))
}
}
c.ev.SendView(accounts, events.ProgressFinish())
// 0 length validator set when using network config
if len(cfg.Validators) == 0 {
return nil
}
if cfg.IsConsumerChain() {
// we skip early if the chain is a consumer chain
return nil
}
// Sovereign chain writes validators in gentxs.
if _, err := c.IssueGentx(ctx, createValidatorFromConfig(cfg)); err != nil {
return err
}
return nil
}
// IssueGentx generates a gentx from the validator information in chain config and imports it in the chain genesis.
func (c Chain) IssueGentx(ctx context.Context, v Validator) (string, error) {
commands, err := c.Commands(ctx)
if err != nil {
return "", err
}
// create the gentx from the validator from the config
gentxPath, err := c.Gentx(ctx, commands, v)
if err != nil {
return "", err
}
// import the gentx into the genesis
return gentxPath, commands.CollectGentxs(ctx)
}
// IsInitialized checks if the chain is initialized.
// The check is performed by checking if the gentx dir exists in the config,
// unless c is a consumer chain, in which case the check relies on checking if
// the consumer genesis module is filled with validators.
func (c *Chain) IsInitialized() (bool, error) {
home, err := c.Home()
if err != nil {
return false, err
}
cfg, err := c.Config()
if err != nil {
return false, err
}
if cfg.IsConsumerChain() {
// when consumer chain, we skip the IsInialized logic
return true, nil
}
gentxDir := filepath.Join(home, "config", "gentx")
if _, err := os.Stat(gentxDir); os.IsNotExist(err) {
return false, nil
} else if err != nil {
return false, err
}
return true, nil
}
// UpdateGenesisFile updates the chain genesis with a generic map of data.
// Updates are made using an override merge strategy.
func (c Chain) UpdateGenesisFile(data map[string]interface{}) error {
path, err := c.GenesisPath()
if err != nil {
return err
}
genesis := make(map[string]interface{})
cf := confile.New(confile.DefaultJSONEncodingCreator, path)
if err := cf.Load(&genesis); err != nil {
return err
}
if err := mergo.Merge(&genesis, data, mergo.WithOverride); err != nil {
return err
}
return cf.Save(genesis)
}
type Validator struct {
Name string
Moniker string
StakingAmount string
CommissionRate string
CommissionMaxRate string
CommissionMaxChangeRate string
MinSelfDelegation string
GasPrices string
Details string
Identity string
Website string
SecurityContact string
}
// Account represents an account in the chain.
type Account struct {
Name string
Address string
Mnemonic string `json:"mnemonic"`
CoinType string
Coins string
}
func createValidatorFromConfig(conf *chainconfig.Config) (validator Validator) {
// Currently, we support the config file with one valid validator.
validatorFromConfig := conf.Validators[0]
validator.Name = validatorFromConfig.Name
validator.StakingAmount = validatorFromConfig.Bonded
if validatorFromConfig.Gentx != nil {
if validatorFromConfig.Gentx.Amount != "" {
validator.StakingAmount = validatorFromConfig.Gentx.Amount
}
if validatorFromConfig.Gentx.Moniker != "" {
validator.Moniker = validatorFromConfig.Gentx.Moniker
}
if validatorFromConfig.Gentx.CommissionRate != "" {
validator.CommissionRate = validatorFromConfig.Gentx.CommissionRate
}
if validatorFromConfig.Gentx.CommissionMaxRate != "" {
validator.CommissionMaxRate = validatorFromConfig.Gentx.CommissionMaxRate
}
if validatorFromConfig.Gentx.CommissionMaxChangeRate != "" {
validator.CommissionMaxChangeRate = validatorFromConfig.Gentx.CommissionMaxChangeRate
}
if validatorFromConfig.Gentx.GasPrices != "" {
validator.GasPrices = validatorFromConfig.Gentx.GasPrices
}
if validatorFromConfig.Gentx.Details != "" {
validator.Details = validatorFromConfig.Gentx.Details
}
if validatorFromConfig.Gentx.Identity != "" {
validator.Identity = validatorFromConfig.Gentx.Identity
}
if validatorFromConfig.Gentx.Website != "" {
validator.Website = validatorFromConfig.Gentx.Website
}
if validatorFromConfig.Gentx.SecurityContact != "" {
validator.SecurityContact = validatorFromConfig.Gentx.SecurityContact
}
if validatorFromConfig.Gentx.MinSelfDelegation != "" {
validator.MinSelfDelegation = validatorFromConfig.Gentx.MinSelfDelegation
}
}
return validator
}