From 1f1922b06a8ffda7020d2669a41d7c5eebdc1655 Mon Sep 17 00:00:00 2001 From: jonathansumner Date: Thu, 18 Apr 2024 12:35:03 +0100 Subject: [PATCH 1/2] feat: withdraw ibc balances to hardcoded withdrawal address --- cmd/fetchd/cmd/genasiupgrade.go | 121 +++++++++++++++++++++++++++++++- go.mod | 2 + go.sum | 1 + 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/cmd/fetchd/cmd/genasiupgrade.go b/cmd/fetchd/cmd/genasiupgrade.go index 18016d71..3c1e65f2 100644 --- a/cmd/fetchd/cmd/genasiupgrade.go +++ b/cmd/fetchd/cmd/genasiupgrade.go @@ -1,17 +1,27 @@ package cmd import ( + "encoding/json" "fmt" + "github.com/btcsuite/btcutil/bech32" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" + ibc_core "github.com/cosmos/ibc-go/v3/modules/core/24-host" + ibctypes "github.com/cosmos/ibc-go/v3/modules/core/types" "github.com/spf13/cobra" "github.com/tendermint/tendermint/types" ) const ( + IbcWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x" /* "asi1rhrlzsx9z865dqen8t4v47r99dw6y4vaw76rd9" */ + flagNewDescription = "new-description" Bech32Chars = "023456789acdefghjklmnpqrstuvwxyz" AddrDataLength = 32 @@ -46,21 +56,26 @@ func ASIGenesisUpgradeCmd(defaultNodeHome string) *cobra.Command { Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { clientCtx := client.GetClientContextFromCmd(cmd) - serverCtx := server.GetServerContextFromCmd(cmd) config := serverCtx.Config + cdc := clientCtx.Codec config.SetRoot(clientCtx.HomeDir) genFile := config.GenesisFile() - _, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) + appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) if err != nil { return fmt.Errorf("failed to unmarshal genesis state: %w", err) } // replace chain-id ASIGenesisUpgradeReplaceChainID(genDoc) + + if err = ASIGenesisUpgradeWithdrawIBCChannelsBalances(&cdc, &appState); err != nil { + return fmt.Errorf("failed to withdraw IBC channels balances: %w", err) + } + return genutil.ExportGenesisFile(genDoc, genFile) }, } @@ -83,6 +98,106 @@ func ASIGenesisUpgradeReplaceDenom() {} func ASIGenesisUpgradeReplaceAddresses() {} -func ASIGenesisUpgradeWithdrawIBCChannelsBalances() {} +func ASIGenesisUpgradeWithdrawIBCChannelsBalances(cdc *codec.Codec, appState *map[string]json.RawMessage) error { + bankGenState := banktypes.GetGenesisStateFromAppState(*cdc, *appState) + balances := bankGenState.Balances + balanceMap, err := getGenesisBalancesMap(bankGenState) + if err != nil { + return err + } + + var ibcAppState ibctypes.GenesisState + if err := (*cdc).UnmarshalJSON((*appState)[ibc_core.ModuleName], &ibcAppState); err != nil { + return fmt.Errorf("failed to unmarshal IBC genesis state: %w", err) + } + + withdrawalBalanceIdx, ok := (*balanceMap)[IbcWithdrawAddress] + if !ok { + return fmt.Errorf("failed to find withdrawal address in genesis balances") + } + + for _, balance := range bankGenState.Balances { + if balance.Address == IbcWithdrawAddress { + fmt.Println("Withdrawal address balance:", balance.Coins.String()) + } + } + + for _, channel := range ibcAppState.ChannelGenesis.Channels { + rawAddr := ibctransfertypes.GetEscrowAddress(channel.PortId, channel.ChannelId) + addr, err := sdk.Bech32ifyAddressBytes(OldAddrPrefix+AccAddressPrefix, rawAddr) + if err != nil { + return fmt.Errorf("failed to bech32ify address: %w", err) + } + + // TODO: use this conversion when merging with address replacement branch + //addr, err := convertAddressToASI(oldAddr, AccAddressPrefix) + //if err != nil { + // return fmt.Errorf("failed to convert address: %w", err) + //} + //if _, err = sdk.AccAddressFromBech32(addr); err != nil { + // return fmt.Errorf("converted address is invalid: %w", err) + //} + + balanceIdx, ok := (*balanceMap)[addr] + if !ok { + fmt.Println("Channel address not found in genesis balances:", addr) + continue + } + + accBalance := balances[balanceIdx] + + // withdraw funds from the channel balance + balances[withdrawalBalanceIdx].Coins = balances[withdrawalBalanceIdx].Coins.Add(accBalance.Coins...) + + // zero out the channel balance + balances[balanceIdx].Coins = sdk.NewCoins() + } + + // update the bank genesis state + (*bankGenState).Balances = balances + + bankGenStateBytes, err := (*cdc).MarshalJSON(bankGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis state: %w", err) + } + + for _, balance := range bankGenState.Balances { + if balance.Address == IbcWithdrawAddress { + fmt.Println("Withdrawal address balance:", balance.Coins.String()) + } + } + + (*appState)[banktypes.ModuleName] = bankGenStateBytes + return nil +} func ASIGenesisUpgradeWithdrawReconciliationBalances() {} + +func getGenesisBalancesMap(bankGenState *banktypes.GenesisState) (*map[string]int, error) { + balanceMap := make(map[string]int) + + for i, balance := range bankGenState.Balances { + balanceMap[balance.Address] = i + } + + return &balanceMap, nil +} + +func convertAddressToASI(addr string, addressPrefix string) (string, error) { + _, decodedAddrData, err := bech32.Decode(addr) + if err != nil { + return "", err + } + + newAddress, err := bech32.Encode(NewAddrPrefix+addressPrefix, decodedAddrData) + if err != nil { + return "", err + } + + err = sdk.VerifyAddressFormat(decodedAddrData) + if err != nil { + return "", err + } + + return newAddress, nil +} diff --git a/go.mod b/go.mod index 32d3950a..b446d809 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,8 @@ require ( github.com/tendermint/tm-db v0.6.7 ) +require github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce + require ( filippo.io/edwards25519 v1.0.0-beta.2 // indirect github.com/99designs/keyring v1.1.6 // indirect diff --git a/go.sum b/go.sum index a83afb2d..6467bd8d 100644 --- a/go.sum +++ b/go.sum @@ -122,6 +122,7 @@ github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+q github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= From e57c066df2839ff1f18acb4a17c1545195f667ed Mon Sep 17 00:00:00 2001 From: jonathansumner Date: Thu, 18 Apr 2024 14:25:21 +0100 Subject: [PATCH 2/2] fix: reflect changes in genesis.json --- cmd/fetchd/cmd/genasiupgrade.go | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/cmd/fetchd/cmd/genasiupgrade.go b/cmd/fetchd/cmd/genasiupgrade.go index 3c1e65f2..f52ee1aa 100644 --- a/cmd/fetchd/cmd/genasiupgrade.go +++ b/cmd/fetchd/cmd/genasiupgrade.go @@ -76,6 +76,13 @@ func ASIGenesisUpgradeCmd(defaultNodeHome string) *cobra.Command { return fmt.Errorf("failed to withdraw IBC channels balances: %w", err) } + // reflect changes in the genesis file + var modifiedGenState json.RawMessage + if modifiedGenState, err = json.Marshal(appState); err != nil { + return fmt.Errorf("failed to marshal app state: %w", err) + } + + (*genDoc).AppState = modifiedGenState return genutil.ExportGenesisFile(genDoc, genFile) }, } @@ -116,12 +123,6 @@ func ASIGenesisUpgradeWithdrawIBCChannelsBalances(cdc *codec.Codec, appState *ma return fmt.Errorf("failed to find withdrawal address in genesis balances") } - for _, balance := range bankGenState.Balances { - if balance.Address == IbcWithdrawAddress { - fmt.Println("Withdrawal address balance:", balance.Coins.String()) - } - } - for _, channel := range ibcAppState.ChannelGenesis.Channels { rawAddr := ibctransfertypes.GetEscrowAddress(channel.PortId, channel.ChannelId) addr, err := sdk.Bech32ifyAddressBytes(OldAddrPrefix+AccAddressPrefix, rawAddr) @@ -140,7 +141,7 @@ func ASIGenesisUpgradeWithdrawIBCChannelsBalances(cdc *codec.Codec, appState *ma balanceIdx, ok := (*balanceMap)[addr] if !ok { - fmt.Println("Channel address not found in genesis balances:", addr) + // channel address not found in genesis balances continue } @@ -161,12 +162,6 @@ func ASIGenesisUpgradeWithdrawIBCChannelsBalances(cdc *codec.Codec, appState *ma return fmt.Errorf("failed to marshal auth genesis state: %w", err) } - for _, balance := range bankGenState.Balances { - if balance.Address == IbcWithdrawAddress { - fmt.Println("Withdrawal address balance:", balance.Coins.String()) - } - } - (*appState)[banktypes.ModuleName] = bankGenStateBytes return nil }