diff --git a/app/app.go b/app/app.go index edbf21a0..ff9042e5 100644 --- a/app/app.go +++ b/app/app.go @@ -727,25 +727,65 @@ func (app *App) GetSubspace(moduleName string) paramstypes.Subspace { return subspace } -func getNetworkInfo(app *App, ctx sdk.Context) (*NetworkConfig, error) { +func getNetworkInfo(app *App, ctx *sdk.Context, manifest *UpgradeManifest, expectedChainIdOfMergeSourceGenesis string) (*NetworkConfig, error) { // Load network config from file if given var networkInfo *NetworkConfig var err error if app.cudosMigrationConfigPath != "" { + app.Logger().Info("cudos merge: loading network config", "file", app.cudosMigrationConfigPath, "hash", app.cudosMigrationConfigSha256) networkInfo, err = LoadNetworkConfigFromFile(app.cudosMigrationConfigPath, &app.cudosMigrationConfigSha256) if err != nil { return nil, err } + + if networkInfo.MergeSourceChainID != expectedChainIdOfMergeSourceGenesis { + return nil, fmt.Errorf("mismatch of Merge Source ChainID: the \"merge_source_chain_id\" value in the NetworkConfig file contains \"%s\", expected value is chan-id from input merge source genesis json file, which is \"%s\"", networkInfo.MergeSourceChainID, expectedChainIdOfMergeSourceGenesis) + } + if networkInfo.DestinationChainID != ctx.ChainID() { + return nil, fmt.Errorf("mismatch of Destination ChainID: the \"destination_chain_id\" value in the NetworkConfig file contains \"%s\", expected value is chan-id of the current running chain, which is \"%s\"", networkInfo.DestinationChainID, ctx.ChainID()) + } + + manifest.NetworkConfigFileSha256 = app.cudosMigrationConfigSha256 + // Config file not given, config from hardcoded map } else if info, ok := NetworkInfos[ctx.ChainID()]; ok { + app.Logger().Info("cudos merge: loading network from map", "chain", ctx.ChainID()) + manifest.NetworkConfigFileSha256 = "config map" networkInfo = &info + } else { return nil, fmt.Errorf("network info not found for chain id: %s", ctx.ChainID()) } + manifest.MergeSourceChainID = expectedChainIdOfMergeSourceGenesis + manifest.DestinationChainID = ctx.ChainID() + return networkInfo, nil } +func LoadAndParseMergeSourceInputFiles(app *App, ctx *sdk.Context, manifest *UpgradeManifest) (*GenesisData, *NetworkConfig, error) { + + cudosJsonData, cudosGenDoc, err := LoadCudosGenesis(app, manifest) + + if err != nil { + return nil, nil, fmt.Errorf("failed to load genesis data: %w", err) + } + + networkInfo, err := getNetworkInfo(app, ctx, manifest, cudosGenDoc.ChainID) + if err != nil { + return nil, nil, fmt.Errorf("failed to load network config: %w", err) + } + + cudosConfig := NewCudosMergeConfig(networkInfo.CudosMerge) + + genesisData, err := parseGenesisData(*cudosJsonData, cudosConfig, manifest) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse genesis data: %w", err) + } + + return genesisData, networkInfo, nil +} + func (app *App) RegisterUpgradeHandlers(cfg module.Configurator) { app.UpgradeKeeper.SetUpgradeHandler("v0.11.3", func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return app.mm.RunMigrations(ctx, cfg, fromVM) @@ -755,13 +795,9 @@ func (app *App) RegisterUpgradeHandlers(cfg module.Configurator) { manifest := NewUpgradeManifest() - if app.cudosGenesisPath == "" { - return nil, fmt.Errorf("cudos path not set") - } - - networkInfo, err := getNetworkInfo(app, ctx) + cudosGenesisData, networkInfo, err := LoadAndParseMergeSourceInputFiles(app, &ctx, manifest) if err != nil { - return nil, err + return nil, fmt.Errorf("cudos merge: %w", err) } err = app.DeleteContractStates(ctx, networkInfo, manifest) @@ -790,7 +826,7 @@ func (app *App) RegisterUpgradeHandlers(cfg module.Configurator) { } cudosConfig := NewCudosMergeConfig(networkInfo.CudosMerge) - err = CudosMergeUpgradeHandler(app, ctx, cudosConfig, manifest) + err = CudosMergeUpgradeHandler(app, ctx, cudosConfig, cudosGenesisData, manifest) if err != nil { return nil, err } diff --git a/app/upgrade_cudos.go b/app/upgrade_cudos.go index 100ac44a..c015e7a6 100644 --- a/app/upgrade_cudos.go +++ b/app/upgrade_cudos.go @@ -20,6 +20,7 @@ import ( ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" ibccore "github.com/cosmos/ibc-go/v3/modules/core/24-host" "github.com/spf13/cast" + tmtypes "github.com/tendermint/tendermint/types" "strings" ) @@ -142,87 +143,102 @@ type GenesisData struct { collisionMap *OrderedMap[string, string] } -func CudosMergeUpgradeHandler(app *App, ctx sdk.Context, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) error { - if cudosCfg == nil { - return fmt.Errorf("cudos CudosMergeConfig not provided (null pointer passed in)") - } +func LoadCudosGenesis(app *App, manifest *UpgradeManifest) (*map[string]interface{}, *tmtypes.GenesisDoc, error) { if app.cudosGenesisPath == "" { - return fmt.Errorf("cudos path not set") + return nil, nil, fmt.Errorf("cudos path not set") } actualGenesisSha256Hex, err := GenerateSHA256FromFile(app.cudosGenesisPath) if err != nil { - return fmt.Errorf("failed to generate sha256 out of genesis file %v: %w", app.cudosGenesisPath, err) + return nil, nil, fmt.Errorf("failed to generate sha256 out of genesis file %v: %w", app.cudosGenesisPath, err) } if app.cudosGenesisSha256 != actualGenesisSha256Hex { - return fmt.Errorf("sha256 failed to verify: genesis file \"%v\" hash %v does not match expected hash %v", app.cudosGenesisPath, actualGenesisSha256Hex, app.cudosGenesisSha256) + return nil, nil, fmt.Errorf("failed to verify sha256: genesis file \"%v\" hash \"%v\" does not match expected hash \"%v\"", app.cudosGenesisPath, actualGenesisSha256Hex, app.cudosGenesisSha256) } + manifest.GenesisFileSha256 = actualGenesisSha256Hex _, genDoc, err := genutiltypes.GenesisStateFromGenFile(app.cudosGenesisPath) if err != nil { - return fmt.Errorf("failed to unmarshal genesis state: %w", err) + return nil, nil, fmt.Errorf("cudos merge: failed to unmarshal genesis state: %w", err) } // unmarshal the app state var jsonData map[string]interface{} if err = json.Unmarshal(genDoc.AppState, &jsonData); err != nil { - return fmt.Errorf("failed to unmarshal app state: %w", err) + return nil, nil, fmt.Errorf("cudos merge: failed to unmarshal app state: %w", err) } - genesisData, err := parseGenesisData(jsonData, cudosCfg, manifest) - if err != nil { - return err + /* + genesisData, err := parseGenesisData(jsonData, cudosCfg, manifest) + if err != nil { + return fmt.Errorf("cudos merge: failed to parse genesis data: %w", err) + } + */ + + //genDoc.AppState = nil + + return &jsonData, genDoc, nil + +} + +func CudosMergeUpgradeHandler(app *App, ctx sdk.Context, cudosCfg *CudosMergeConfig, genesisData *GenesisData, manifest *UpgradeManifest) error { + if cudosCfg == nil { + return fmt.Errorf("cudos merge: cudos CudosMergeConfig not provided (null pointer passed in)") + } + + if app.cudosGenesisPath == "" { + return fmt.Errorf("cudos merge: cudos path not set") } - err = genesisUpgradeWithdrawIBCChannelsBalances(genesisData, cudosCfg, manifest) + err := genesisUpgradeWithdrawIBCChannelsBalances(genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to withdraw IBC channels balances: %w", err) + return fmt.Errorf("cudos merge: failed to withdraw IBC channels balances: %w", err) } err = withdrawGenesisContractBalances(genesisData, manifest, cudosCfg) if err != nil { - return fmt.Errorf("failed to withdraw genesis contracts balances: %w", err) + return fmt.Errorf("cudos merge: failed to withdraw genesis contracts balances: %w", err) } - err = withdrawGenesisStakingDelegations(genesisData, cudosCfg, manifest) + err = withdrawGenesisStakingDelegations(app, genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to withdraw genesis staked tokens: %w", err) + return fmt.Errorf("cudos merge: failed to withdraw genesis staked tokens: %w", err) } - err = withdrawGenesisDistributionRewards(genesisData, cudosCfg, manifest) + err = withdrawGenesisDistributionRewards(app, genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to withdraw genesis rewards: %w", err) + return fmt.Errorf("cudos merge: failed to withdraw genesis rewards: %w", err) } err = withdrawGenesisGravity(genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to withdraw gravity: %w", err) + return fmt.Errorf("cudos merge: failed to withdraw gravity: %w", err) } err = DoGenesisAccountMovements(genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to move funds: %w", err) + return fmt.Errorf("cudos merge: failed to move funds: %w", err) } err = MigrateGenesisAccounts(genesisData, ctx, app, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed process accounts: %w", err) + return fmt.Errorf("cudos merge: failed process accounts: %w", err) } err = createGenesisDelegations(ctx, app, genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed process delegations: %w", err) + return fmt.Errorf("cudos merge: failed process delegations: %w", err) } err = fundCommunityPool(ctx, app, genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to fund community pool: %w", err) + return fmt.Errorf("cudos merge: failed to fund community pool: %w", err) } err = verifySupply(genesisData, cudosCfg, manifest) if err != nil { - return fmt.Errorf("failed to verify supply: %w", err) + return fmt.Errorf("cudos merge: failed to verify supply: %w", err) } return nil @@ -693,7 +709,7 @@ func parseGenesisValidators(jsonData map[string]interface{}) (*OrderedMap[string return validatorInfoMap, nil } -func withdrawGenesisStakingDelegations(genesisData *GenesisData, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) error { +func withdrawGenesisStakingDelegations(app *App, genesisData *GenesisData, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) error { // Handle delegations for _, validatorOperatorAddress := range genesisData.validators.Keys() { validator := genesisData.validators.MustGet(validatorOperatorAddress) @@ -767,7 +783,7 @@ func withdrawGenesisStakingDelegations(genesisData *GenesisData, cudosCfg *Cudos return fmt.Errorf("remaining bonded pool balance %s is too high", bondedPool.balance.String()) } - println("remaining bonded pool balance: ", bondedPool.balance.String()) + app.Logger().Info("cudos merge: remaining bonded pool balance", "amount", bondedPool.balance.String()) err = moveGenesisBalance(genesisData, genesisData.bondedPoolAddress, cudosCfg.config.RemainingStakingBalanceAddr, bondedPool.balance, "remaining_bonded_pool_balance", manifest, cudosCfg) if err != nil { return err @@ -782,7 +798,7 @@ func withdrawGenesisStakingDelegations(genesisData *GenesisData, cudosCfg *Cudos return fmt.Errorf("remaining not-bonded pool balance %s is too high", notBondedPool.balance.String()) } - println("Remaining not-bonded pool balance: ", notBondedPool.balance.String()) + app.Logger().Info("cudos merge: remaining not-bonded pool balance", "amount", notBondedPool.balance.String()) err = moveGenesisBalance(genesisData, genesisData.notBondedPoolAddress, cudosCfg.config.RemainingStakingBalanceAddr, notBondedPool.balance, "remaining_not_bonded_pool_balance", manifest, cudosCfg) if err != nil { return err @@ -1042,22 +1058,8 @@ func convertBalance(balance sdk.Coins, cudosCfg *CudosMergeConfig) (sdk.Coins, e newAmount := coin.Amount.ToDec().Quo(conversionConstant).TruncateInt() sdkCoin := sdk.NewCoin(cudosCfg.config.ConvertedDenom, newAmount) resBalance = resBalance.Add(sdkCoin) - } else { - //println("Unknown denom: ", coin.Denom) - // Ignore unlisted tokens - continue - /* - // Just add without conversion - newAmount, ok := sdk.NewIntFromString(amount) - if !ok { - panic("failed to convert amount to big.Int") - } - - sdkCoin := sdk.NewCoin(denom, newAmount) - - resBalance = resBalance.Add(sdkCoin) - */ } + // Denominations that are not in conversion constant map are ignored } return resBalance, nil diff --git a/app/upgrade_cudos_distribution.go b/app/upgrade_cudos_distribution.go index e8f0981b..c54b4fb0 100644 --- a/app/upgrade_cudos_distribution.go +++ b/app/upgrade_cudos_distribution.go @@ -355,7 +355,7 @@ func verifyOutstandingBalances(genesisData *GenesisData) error { return nil } -func withdrawGenesisDistributionRewards(genesisData *GenesisData, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) error { +func withdrawGenesisDistributionRewards(app *App, genesisData *GenesisData, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) error { // block height is used only to early stop rewards calculation //blockHeight := getMaxBlockHeight(genesisData) + 1 blockHeight := uint64(math.MaxUint64) @@ -370,7 +370,7 @@ func withdrawGenesisDistributionRewards(genesisData *GenesisData, cudosCfg *Cudo for _, delegatorAddr := range delegatorStartInfo.Keys() { delegation := validator.delegations.MustGet(delegatorAddr) - _, err := withdrawDelegationRewards(genesisData, validator, delegation, endingPeriod, blockHeight, cudosCfg, manifest) + _, err := withdrawDelegationRewards(app, genesisData, validator, delegation, endingPeriod, blockHeight, cudosCfg, manifest) if err != nil { return err } @@ -396,12 +396,12 @@ func withdrawGenesisDistributionRewards(genesisData *GenesisData, cudosCfg *Cudo communityBalance, _ := genesisData.distributionInfo.feePool.communityPool.TruncateDecimal() remainingBalance := distributionModuleAccount.balance.Sub(communityBalance) - println("Remaining dist balance: ", remainingBalance.String()) + app.Logger().Info("cudos merge: remaining dist balance", "amount", remainingBalance.String()) // TODO: Write to manifest? err = checkTolerance(remainingBalance, maxToleratedRemainingDistributionBalance) if err != nil { - return fmt.Errorf("Remaining distribution balance %s is too high", remainingBalance.String()) + return fmt.Errorf("remaining distribution balance %s is too high", remainingBalance.String()) } err = moveGenesisBalance(genesisData, genesisData.distributionInfo.distributionModuleAccountAddress, cudosCfg.config.RemainingDistributionBalanceAddr, distributionModuleAccount.balance, "remaining_distribution_module_balance", manifest, cudosCfg) @@ -620,7 +620,7 @@ func (d DistributionInfo) GetDelegatorWithdrawAddr(delAddr string) string { return b } -func withdrawDelegationRewards(genesisData *GenesisData, val *ValidatorInfo, del *DelegationInfo, endingPeriod uint64, blockHeight uint64, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) (sdk.Coins, error) { +func withdrawDelegationRewards(app *App, genesisData *GenesisData, val *ValidatorInfo, del *DelegationInfo, endingPeriod uint64, blockHeight uint64, cudosCfg *CudosMergeConfig, manifest *UpgradeManifest) (sdk.Coins, error) { // check existence of delegator starting info genesisData.distributionInfo.delegatorStartingInfos.Has(val.operatorAddress) @@ -641,7 +641,7 @@ func withdrawDelegationRewards(genesisData *GenesisData, val *ValidatorInfo, del // of the decCoins due to operation order of the distribution mechanism. rewards := rewardsRaw.Intersect(outstanding) if !rewards.IsEqual(rewardsRaw) { - println( + app.Logger().Error( "rounding error withdrawing rewards from validator", "delegator", del.delegatorAddress, "validator", val.operatorAddress, diff --git a/app/upgrade_v_11_4_manifest.go b/app/upgrade_v_11_4_manifest.go index 136159f6..732f0bdc 100644 --- a/app/upgrade_v_11_4_manifest.go +++ b/app/upgrade_v_11_4_manifest.go @@ -13,16 +13,21 @@ import ( const manifestFilenameBase = "upgrade_manifest.json" type UpgradeManifest struct { - Reconciliation *UpgradeReconciliation `json:"reconciliation,omitempty"` - Contracts *Contracts `json:"contracts,omitempty"` - IBC *UpgradeIBCTransfers `json:"ibc,omitempty"` - Migration *UpgradeMigation `json:"migration,omitempty"` - MoveGenesisBalance *UpgradeMoveGenesisBalance `json:"move_genesis_balance,omitempty"` - Delegate *UpgradeDelegate `json:"delegate,omitempty"` - MoveMintedBalance *UpgradeMoveMintedBalance `json:"move_minted_balance,omitempty"` - VestingCollision *UpgradeVestingCollision `json:"vesting_collision,omitempty"` - MoveDelegations *UpgradeMoveDelegations `json:"move_delegation,omitempty"` - CreatedAccounts *UpgradeCreatedAccounts `json:"created_accounts,omitempty"` + // Following 2 hash data members are intentionally without `omitempty` parameter in `json:...` decorator + GenesisFileSha256 string `json:"genesis_file_sha256"` + NetworkConfigFileSha256 string `json:"network_config_file_sha256"` + MergeSourceChainID string `json:"merge_source_chain_id"` + DestinationChainID string `json:"destination_chain_id"` + Reconciliation *UpgradeReconciliation `json:"reconciliation,omitempty"` + Contracts *Contracts `json:"contracts,omitempty"` + IBC *UpgradeIBCTransfers `json:"ibc,omitempty"` + Migration *UpgradeMigation `json:"migration,omitempty"` + MoveGenesisBalance *UpgradeMoveGenesisBalance `json:"move_genesis_balance,omitempty"` + Delegate *UpgradeDelegate `json:"delegate,omitempty"` + MoveMintedBalance *UpgradeMoveMintedBalance `json:"move_minted_balance,omitempty"` + VestingCollision *UpgradeVestingCollision `json:"vesting_collision,omitempty"` + MoveDelegations *UpgradeMoveDelegations `json:"move_delegation,omitempty"` + CreatedAccounts *UpgradeCreatedAccounts `json:"created_accounts,omitempty"` } func NewUpgradeManifest() *UpgradeManifest { diff --git a/app/upgrade_v_11_4_network_config.go b/app/upgrade_v_11_4_network_config.go index e5b2c3fe..c6455760 100644 --- a/app/upgrade_v_11_4_network_config.go +++ b/app/upgrade_v_11_4_network_config.go @@ -179,7 +179,10 @@ var NetworkInfos = map[string]NetworkConfig{ //cudos15jpukx39rtkt8w3u3gzwwvyptdeyejcjade6he MovedAccounts: []Pair[string, string]{ - //{"cudos1dslwarknhfsw3pfjzxxf5mn28q3ewfectw0gta", "cudos15jpukx39rtkt8w3u3gzwwvyptdeyejcjade6he"}, // Replace this + //{"cudos196nrmandtwz67d8h4h0ux7amlcluecglx00wlw", "cudos1nj49l56x7sss5hqyvfmctxr3mq64whg273g3x5"}, // Replace this + //{"cudos1xcwjdw09cc9dyshr4gt5520sgsh582mjj03jge", "cudos1dslwarknhfsw3pfjzxxf5mn28q3ewfectw0gta"}, // Replace this + //{"cudos1ejmf96efvjp6pmsaj8djv3gpmnsvmpnctger4v", "fetch15p3rl5aavw9rtu86tna5lgxfkz67zzr6ed4yhw"}, // Replace this + }, BackupValidators: []string{"fetchvaloper1m9cjw6xgt04f9ddw25fff3cfe2exgwk07eu46u", "fetchvaloper122j02czdt5ca8cf576wy2hassyxyx67wdsecml"}, @@ -265,6 +268,9 @@ var NetworkInfos = map[string]NetworkConfig{ } type NetworkConfig struct { + MergeSourceChainID string `json:"merge_source_chain_id"` + DestinationChainID string `json:"destination_chain_id"` + ReconciliationInfo *ReconciliationInfo `json:"reconciliation_info,omitempty"` Contracts *ContractSet `json:"contracts,omitempty"` CudosMerge *CudosMergeConfigJSON `json:"cudos_merge,omitempty"` @@ -287,7 +293,7 @@ func LoadNetworkConfigFromFile(configFilePath string, expectedSha256Hex *string) if isVerified, actualHashHex, err := VerifySha256(byteValue, expectedSha256Hex); err != nil { return nil, err } else if !isVerified { - return nil, fmt.Errorf("provided expected sha256 \"%v\" for NetworkConf file does NOT match actual sha256 hash %v of the file content", expectedSha256Hex, actualHashHex) + return nil, fmt.Errorf("failed to verify sha256: NetworkConfig file \"%s\" hash \"%s\" does not match expected hash \"%s\"", configFilePath, actualHashHex, *expectedSha256Hex) } // Initialize an empty struct to hold the JSON data diff --git a/cmd/fetchd/cmd/cudos_merge.go b/cmd/fetchd/cmd/cudos_merge.go index 4e183e87..dca5c7e0 100644 --- a/cmd/fetchd/cmd/cudos_merge.go +++ b/cmd/fetchd/cmd/cudos_merge.go @@ -18,4 +18,25 @@ func AddCudosFlags(startCmd *cobra.Command) { startCmd.Flags().String(FlagCudosMigrationConfigPath, "", "Upgrade config file path. Required to be provided *exclusively* during cudos migration upgrade node start, *ignored* on all subsequent node starts.") startCmd.Flags().String(FlagCudosGenesisSha256, "", "Sha256 of the cudos genesis file. Optional to be provided *exclusively* during cudos migration upgrade node start, *ignored* on all subsequent node starts.") startCmd.Flags().String(FlagCudosMigrationConfigSha256, "", fmt.Sprintf("Sha256 of the upgrade config file. Required if to be provided *exclusively* during cudos migration upgrade node start and *only IF* \"%v\" flag has been provided, *ignored* on all subsequent node starts.", FlagCudosMigrationConfigPath)) + + // Capture the existing PreRunE function + existingPreRunE := startCmd.PreRunE + + // Set a new PreRunE function that includes the old one + startCmd.PreRunE = func(cmd *cobra.Command, args []string) error { + // Check for positional arguments + if len(args) > 0 { + return fmt.Errorf("no positional arguments are allowed") + } + + // Call the existing PreRunE function if it exists + if existingPreRunE != nil { + if err := existingPreRunE(cmd, args); err != nil { + return err + } + } + + return nil + } + }