11package cmd
22
33import (
4+ "bytes"
5+ _ "embed"
6+ "encoding/csv"
47 "encoding/json"
58 "fmt"
69 "github.com/btcsuite/btcutil/bech32"
710 "github.com/cosmos/cosmos-sdk/client"
811 "github.com/cosmos/cosmos-sdk/client/flags"
912 "github.com/cosmos/cosmos-sdk/server"
1013 sdk "github.com/cosmos/cosmos-sdk/types"
14+ authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
1115 banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
1216 "github.com/cosmos/cosmos-sdk/x/genutil"
1317 genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
1418 ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
15- ibc_core "github.com/cosmos/ibc-go/v3/modules/core/24-host"
19+ ibccore "github.com/cosmos/ibc-go/v3/modules/core/24-host"
1620 "github.com/spf13/cobra"
1721 "github.com/tendermint/tendermint/types"
22+ "log"
1823 "regexp"
24+ "strconv"
1925 "strings"
2026)
2127
2228const (
2329 BridgeContractAddress = "fetch1qxxlalvsdjd07p07y3rc5fu6ll8k4tmetpha8n"
2430 NewBridgeContractAdmin = "fetch15p3rl5aavw9rtu86tna5lgxfkz67zzr6ed4yhw"
2531
26- IbcWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x" /* "asi1rhrlzsx9z865dqen8t4v47r99dw6y4vaw76rd9" */
32+ IbcWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x" /* "asi1rhrlzsx9z865dqen8t4v47r99dw6y4vaw76rd9" */
33+ ReconciliationWithdrawAddress = "fetch1rhrlzsx9z865dqen8t4v47r99dw6y4va4uph0x"
2734
2835 flagNewDescription = "new-description"
2936 Bech32Chars = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
@@ -40,11 +47,13 @@ const (
4047 NewChainId = "asi-1"
4148 NewDescription = "ASI Token"
4249
43- OldBaseDenom = "fet"
4450 OldDenom = "afet"
4551 OldAddrPrefix = "fetch"
4652)
4753
54+ //go:embed reconciliation_data.csv
55+ var reconciliationData []byte
56+
4857// ASIGenesisUpgradeCmd returns replace-genesis-values cobra Command.
4958func ASIGenesisUpgradeCmd (defaultNodeHome string ) * cobra.Command {
5059 cmd := & cobra.Command {
@@ -87,6 +96,11 @@ func ASIGenesisUpgradeCmd(defaultNodeHome string) *cobra.Command {
8796 return err
8897 }
8998
99+ // withdraw balances from reconciliation addresses
100+ if err = ASIGenesisUpgradeWithdrawReconciliationBalances (jsonData ); err != nil {
101+ return err
102+ }
103+
90104 // replace denom across the genesis file
91105 ASIGenesisUpgradeReplaceDenom (jsonData )
92106
@@ -234,18 +248,15 @@ func replaceAddresses(addressTypePrefix string, jsonData map[string]interface{},
234248func ASIGenesisUpgradeWithdrawIBCChannelsBalances (jsonData map [string ]interface {}) error {
235249 bank := jsonData [banktypes .ModuleName ].(map [string ]interface {})
236250 balances := bank ["balances" ].([]interface {})
237- balanceMap , err := getGenesisBalancesMap (balances )
238- if err != nil {
239- return err
240- }
251+ balanceMap := getGenesisBalancesMap (balances )
241252
242253 withdrawalBalanceIdx , ok := (* balanceMap )[IbcWithdrawAddress ]
243254 if ! ok {
244255 fmt .Println ("failed to find Ibc withdrawal address in genesis balances - have addresses already been converted?" )
245256 return nil
246257 }
247258
248- ibc := jsonData [ibc_core .ModuleName ].(map [string ]interface {})
259+ ibc := jsonData [ibccore .ModuleName ].(map [string ]interface {})
249260 channelGenesis := ibc ["channel_genesis" ].(map [string ]interface {})
250261 ibcChannels := channelGenesis ["channels" ].([]interface {})
251262
@@ -273,13 +284,113 @@ func ASIGenesisUpgradeWithdrawIBCChannelsBalances(jsonData map[string]interface{
273284 balances [withdrawalBalanceIdx ].(map [string ]interface {})["coins" ] = getInterfaceSliceFromCoins (newWithdrawalBalanceCoins )
274285
275286 // zero out the channel balance
276- balances [balanceIdx ] = nil
287+ balances [balanceIdx ].( map [ string ] interface {})[ "coins" ] = [] interface {}{}
277288 }
278289
279290 return nil
280291}
281292
282- func ASIGenesisUpgradeWithdrawReconciliationBalances () {}
293+ func getGenesisAccountSequenceMap (accounts []interface {}) * map [string ]int {
294+ const ModuleAccount = "/cosmos.auth.v1beta1.ModuleAccount"
295+ accountMap := make (map [string ]int )
296+
297+ for _ , acc := range accounts {
298+ accType := acc .(map [string ]interface {})["@type" ]
299+
300+ accData := acc
301+ if accType == ModuleAccount {
302+ accData = acc .(map [string ]interface {})["base_account" ]
303+ }
304+
305+ addr := accData .(map [string ]interface {})["address" ].(string )
306+ sequence := accData .(map [string ]interface {})["sequence" ].(string )
307+
308+ sequenceInt , ok := strconv .Atoi (sequence )
309+ if ok != nil {
310+ panic ("getGenesisAccountSequenceMap: failed to convert sequence to int" )
311+ }
312+ accountMap [addr ] = sequenceInt
313+ }
314+
315+ return & accountMap
316+ }
317+
318+ func ASIGenesisUpgradeWithdrawReconciliationBalances (jsonData map [string ]interface {}) error {
319+ bank := jsonData [banktypes .ModuleName ].(map [string ]interface {})
320+ balances := bank ["balances" ].([]interface {})
321+
322+ balanceMap := getGenesisBalancesMap (balances )
323+
324+ auth := jsonData [authtypes .ModuleName ].(map [string ]interface {})
325+ accounts := auth ["accounts" ].([]interface {})
326+ accountSequenceMap := getGenesisAccountSequenceMap (accounts )
327+
328+ fileData := reconciliationData
329+ r := csv .NewReader (bytes .NewReader (fileData ))
330+ items , err := r .ReadAll ()
331+ if err != nil {
332+ log .Fatalf ("Error reading reconciliation data: %s" , err )
333+ }
334+
335+ reconciliationBalanceIdx , ok := (* balanceMap )[ReconciliationWithdrawAddress ]
336+ if ! ok {
337+ return fmt .Errorf ("no genesis match for reconciliation address: %s" , ReconciliationWithdrawAddress )
338+ }
339+
340+ for _ , row := range items {
341+ addr := row [2 ]
342+
343+ //_ = row[3] balance from CSV
344+
345+ accSequence , ok := (* accountSequenceMap )[addr ]
346+ if ! ok {
347+ return fmt .Errorf ("no genesis match for reconciliation address: %s" , addr )
348+ }
349+
350+ balanceIdx , ok := (* balanceMap )[addr ]
351+ if ! ok {
352+ continue
353+ }
354+
355+ accBalance := balances [balanceIdx ]
356+ accBalanceCoins := getCoinsFromInterfaceSlice (accBalance )
357+
358+ reconciliationBalance := balances [reconciliationBalanceIdx ]
359+ reconciliationBalanceCoins := getCoinsFromInterfaceSlice (reconciliationBalance )
360+
361+ // check if the reconciliation address is still dormant and contains funds
362+ if accSequence != 0 || ! accBalanceCoins .IsAllPositive () {
363+ continue
364+ }
365+
366+ // add reconciliation account balance to withdrawal balance
367+ newReconciliationBalanceCoins := reconciliationBalanceCoins .Add (accBalanceCoins ... )
368+ reconciliationBalance .(map [string ]interface {})["coins" ] = getInterfaceSliceFromCoins (newReconciliationBalanceCoins )
369+
370+ // zero out the reconciliation account balance
371+ balances [balanceIdx ].(map [string ]interface {})["coins" ] = []interface {}{}
372+ }
373+ return nil
374+ }
375+
376+ func convertAddressToASI (addr string , addressPrefix string ) (string , error ) {
377+ _ , decodedAddrData , err := bech32 .Decode (addr )
378+ if err != nil {
379+ return "" , err
380+ }
381+
382+ newAddress , err := bech32 .Encode (NewAddrPrefix + addressPrefix , decodedAddrData )
383+ if err != nil {
384+ return "" , err
385+ }
386+
387+ err = sdk .VerifyAddressFormat (decodedAddrData )
388+ if err != nil {
389+ return "" , err
390+ }
391+
392+ return newAddress , nil
393+ }
283394
284395func crawlJson (key string , value interface {}, idx int , strHandler func (string , interface {}, int ) interface {}) interface {} {
285396 switch val := value .(type ) {
@@ -299,34 +410,19 @@ func crawlJson(key string, value interface{}, idx int, strHandler func(string, i
299410 return value
300411}
301412
302- func getGenesisBalancesMap (balances []interface {}) ( * map [string ]int , error ) {
413+ func getGenesisBalancesMap (balances []interface {}) * map [string ]int {
303414 balanceMap := make (map [string ]int )
304415
305416 for i , balance := range balances {
306- addr := balance .(map [string ]interface {})["address" ].(string )
307- balanceMap [addr ] = i
308- }
309-
310- return & balanceMap , nil
311- }
312-
313- func convertAddressToASI (addr string , addressTypePrefix string ) (string , error ) {
314- _ , decodedAddrData , err := bech32 .Decode (addr )
315- if err != nil {
316- return "" , fmt .Errorf ("failed to decode address: %w" , err )
317- }
318-
319- err = sdk .VerifyAddressFormat (decodedAddrData )
320- if err != nil {
321- return "" , fmt .Errorf ("failed to verify address format: %w" , err )
322- }
323-
324- newAddress , err := bech32 .Encode (NewAddrPrefix + addressTypePrefix , decodedAddrData )
325- if err != nil {
326- return "" , fmt .Errorf ("failed to encode new address: %w" , err )
417+ addr := balance .(map [string ]interface {})["address" ]
418+ if addr == nil {
419+ fmt .Println (balance )
420+ }
421+ addrStr := addr .(string )
422+ balanceMap [addrStr ] = i
327423 }
328424
329- return newAddress , nil
425+ return & balanceMap
330426}
331427
332428func getCoinsFromInterfaceSlice (data interface {}) sdk.Coins {
0 commit comments