github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/genutil/collect.go (about) 1 package genutil 2 3 // DONTCOVER 4 5 import ( 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "sort" 13 "strings" 14 15 stakingtypes "github.com/fibonacci-chain/fbc/x/staking/types" 16 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 18 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 19 authexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported" 20 authtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types" 21 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/genutil/types" 22 cfg "github.com/fibonacci-chain/fbc/libs/tendermint/config" 23 tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types" 24 ) 25 26 // GenAppStateFromConfig gets the genesis app state from the config 27 func GenAppStateFromConfig(cdc *codec.Codec, config *cfg.Config, 28 initCfg InitConfig, genDoc tmtypes.GenesisDoc, 29 genAccIterator types.GenesisAccountsIterator, 30 ) (appState json.RawMessage, err error) { 31 32 // process genesis transactions, else create default genesis.json 33 appGenTxs, persistentPeers, err := CollectStdTxs( 34 cdc, config.Moniker, initCfg.GenTxsDir, genDoc, genAccIterator) 35 if err != nil { 36 return appState, err 37 } 38 39 config.P2P.PersistentPeers = persistentPeers 40 41 var nodeKeyWhiteList []string 42 for _, nodeAddr := range strings.Split(persistentPeers, ",") { 43 nodeKey := strings.Split(nodeAddr, "@")[0] 44 nodeKeyWhiteList = append(nodeKeyWhiteList, nodeKey) 45 } 46 config.Mempool.NodeKeyWhitelist = nodeKeyWhiteList 47 cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) 48 49 // if there are no gen txs to be processed, return the default empty state 50 if len(appGenTxs) == 0 { 51 return appState, errors.New("there must be at least one genesis tx") 52 } 53 54 // create the app state 55 appGenesisState, err := GenesisStateFromGenDoc(cdc, genDoc) 56 if err != nil { 57 return appState, err 58 } 59 60 appGenesisState, err = SetGenTxsInAppGenesisState(cdc, appGenesisState, appGenTxs) 61 if err != nil { 62 return appState, err 63 } 64 appState, err = codec.MarshalJSONIndent(cdc, appGenesisState) 65 if err != nil { 66 return appState, err 67 } 68 69 genDoc.AppState = appState 70 err = ExportGenesisFile(&genDoc, config.GenesisFile()) 71 return appState, err 72 } 73 74 // CollectStdTxs processes and validates application's genesis StdTxs and returns 75 // the list of appGenTxs, and persistent peers required to generate genesis.json. 76 func CollectStdTxs(cdc *codec.Codec, moniker, genTxsDir string, 77 genDoc tmtypes.GenesisDoc, genAccIterator types.GenesisAccountsIterator, 78 ) (appGenTxs []authtypes.StdTx, persistentPeers string, err error) { 79 80 var fos []os.FileInfo 81 fos, err = ioutil.ReadDir(genTxsDir) 82 if err != nil { 83 return appGenTxs, persistentPeers, err 84 } 85 86 // prepare a map of all accounts in genesis state to then validate 87 // against the validators addresses 88 var appState map[string]json.RawMessage 89 if err := cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil { 90 return appGenTxs, persistentPeers, err 91 } 92 93 addrMap := make(map[string]authexported.Account) 94 genAccIterator.IterateGenesisAccounts(cdc, appState, 95 func(acc authexported.Account) (stop bool) { 96 addrMap[acc.GetAddress().String()] = acc 97 return false 98 }, 99 ) 100 101 // addresses and IPs (and port) validator server info 102 var addressesIPs []string 103 104 for _, fo := range fos { 105 if fo == nil { 106 continue 107 } 108 filename := filepath.Join(genTxsDir, fo.Name()) 109 if !fo.IsDir() && (filepath.Ext(filename) != ".json") { 110 continue 111 } 112 113 // get the genStdTx 114 var jsonRawTx []byte 115 if jsonRawTx, err = ioutil.ReadFile(filename); err != nil { 116 return appGenTxs, persistentPeers, err 117 } 118 var genStdTx authtypes.StdTx 119 if err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx); err != nil { 120 return appGenTxs, persistentPeers, err 121 } 122 appGenTxs = append(appGenTxs, genStdTx) 123 124 // genesis transactions must be single-message 125 msgs := genStdTx.GetMsgs() 126 if len(msgs) != 1 { 127 return appGenTxs, persistentPeers, errors.New( 128 "each genesis transaction must provide a single genesis message") 129 } 130 131 //ignore not create validator tx 132 msg, ok := msgs[0].(stakingtypes.MsgCreateValidator) 133 if !ok { 134 continue 135 } 136 137 // the memo flag is used to store 138 // the ip and node-id, for example this may be: 139 // "528fd3df22b31f4969b05652bfe8f0fe921321d5@192.168.2.37:26656" 140 nodeAddrIP := genStdTx.GetMemo() 141 if len(nodeAddrIP) == 0 { 142 return appGenTxs, persistentPeers, fmt.Errorf( 143 "couldn't find node's address and IP in %s", fo.Name()) 144 } 145 146 // TODO abstract out staking message validation back to staking 147 // validate delegator and validator addresses and funds against the accounts in the state 148 delAddr := msg.DelegatorAddress.String() 149 valAddr := sdk.AccAddress(msg.ValidatorAddress).String() 150 151 delAcc, delOk := addrMap[delAddr] 152 if !delOk { 153 return appGenTxs, persistentPeers, fmt.Errorf( 154 "account %v not in genesis.json: %+v", delAddr, addrMap) 155 } 156 157 _, valOk := addrMap[valAddr] 158 if !valOk { 159 return appGenTxs, persistentPeers, fmt.Errorf( 160 "account %v not in genesis.json: %+v", valAddr, addrMap) 161 } 162 163 if delAcc.GetCoins().AmountOf(msg.MinSelfDelegation.Denom).LT(msg.MinSelfDelegation.Amount) { 164 return appGenTxs, persistentPeers, fmt.Errorf( 165 "insufficient fund for delegation %v: %v < %v", 166 delAcc.GetAddress(), delAcc.GetCoins().AmountOf(msg.MinSelfDelegation.Denom), msg.MinSelfDelegation.Amount, 167 ) 168 } 169 170 // exclude itself from persistent peers 171 if msg.Description.Moniker != moniker { 172 addressesIPs = append(addressesIPs, nodeAddrIP) 173 } 174 } 175 176 sort.Strings(addressesIPs) 177 persistentPeers = strings.Join(addressesIPs, ",") 178 179 return appGenTxs, persistentPeers, nil 180 }