github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/cmd/configtxgen/main.go (about) 1 /* 2 Copyright hechain. 2017 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package main 8 9 import ( 10 "flag" 11 "fmt" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "strings" 16 17 "github.com/golang/protobuf/proto" 18 "github.com/hechain20/hechain/bccsp/factory" 19 "github.com/hechain20/hechain/common/channelconfig" 20 "github.com/hechain20/hechain/common/flogging" 21 "github.com/hechain20/hechain/internal/configtxgen/encoder" 22 "github.com/hechain20/hechain/internal/configtxgen/genesisconfig" 23 "github.com/hechain20/hechain/internal/configtxgen/metadata" 24 "github.com/hechain20/hechain/internal/configtxlator/update" 25 "github.com/hechain20/hechain/protoutil" 26 "github.com/hyperledger/fabric-config/protolator" 27 "github.com/hyperledger/fabric-config/protolator/protoext/ordererext" 28 cb "github.com/hyperledger/fabric-protos-go/common" 29 "github.com/pkg/errors" 30 ) 31 32 var logger = flogging.MustGetLogger("common.tools.configtxgen") 33 34 func doOutputBlock(config *genesisconfig.Profile, channelID string, outputBlock string) error { 35 pgen, err := encoder.NewBootstrapper(config) 36 if err != nil { 37 return errors.WithMessage(err, "could not create bootstrapper") 38 } 39 logger.Info("Generating genesis block") 40 if config.Orderer == nil { 41 return errors.New("refusing to generate block which is missing orderer section") 42 } 43 if config.Consortiums != nil { 44 logger.Info("Creating system channel genesis block") 45 } else { 46 if config.Application == nil { 47 return errors.New("refusing to generate application channel block which is missing application section") 48 } 49 logger.Info("Creating application channel genesis block") 50 } 51 genesisBlock := pgen.GenesisBlockForChannel(channelID) 52 logger.Info("Writing genesis block") 53 err = writeFile(outputBlock, protoutil.MarshalOrPanic(genesisBlock), 0o640) 54 if err != nil { 55 return fmt.Errorf("error writing genesis block: %s", err) 56 } 57 return nil 58 } 59 60 func doOutputChannelCreateTx(conf, baseProfile *genesisconfig.Profile, channelID string, outputChannelCreateTx string) error { 61 logger.Info("Generating new channel configtx") 62 63 var configtx *cb.Envelope 64 var err error 65 if baseProfile == nil { 66 configtx, err = encoder.MakeChannelCreationTransaction(channelID, nil, conf) 67 } else { 68 configtx, err = encoder.MakeChannelCreationTransactionWithSystemChannelContext(channelID, nil, conf, baseProfile) 69 } 70 if err != nil { 71 return err 72 } 73 74 logger.Info("Writing new channel tx") 75 err = writeFile(outputChannelCreateTx, protoutil.MarshalOrPanic(configtx), 0o640) 76 if err != nil { 77 return fmt.Errorf("error writing channel create tx: %s", err) 78 } 79 return nil 80 } 81 82 func doOutputAnchorPeersUpdate(conf *genesisconfig.Profile, channelID string, outputAnchorPeersUpdate string, asOrg string) error { 83 logger.Info("Generating anchor peer update") 84 if asOrg == "" { 85 return fmt.Errorf("must specify an organization to update the anchor peer for") 86 } 87 88 if conf.Application == nil { 89 return fmt.Errorf("cannot update anchor peers without an application section") 90 } 91 92 original, err := encoder.NewChannelGroup(conf) 93 if err != nil { 94 return errors.WithMessage(err, "error parsing profile as channel group") 95 } 96 original.Groups[channelconfig.ApplicationGroupKey].Version = 1 97 98 updated := proto.Clone(original).(*cb.ConfigGroup) 99 100 originalOrg, ok := original.Groups[channelconfig.ApplicationGroupKey].Groups[asOrg] 101 if !ok { 102 return errors.Errorf("org with name '%s' does not exist in config", asOrg) 103 } 104 105 if _, ok = originalOrg.Values[channelconfig.AnchorPeersKey]; !ok { 106 return errors.Errorf("org '%s' does not have any anchor peers defined", asOrg) 107 } 108 109 delete(originalOrg.Values, channelconfig.AnchorPeersKey) 110 111 updt, err := update.Compute(&cb.Config{ChannelGroup: original}, &cb.Config{ChannelGroup: updated}) 112 if err != nil { 113 return errors.WithMessage(err, "could not compute update") 114 } 115 updt.ChannelId = channelID 116 117 newConfigUpdateEnv := &cb.ConfigUpdateEnvelope{ 118 ConfigUpdate: protoutil.MarshalOrPanic(updt), 119 } 120 121 updateTx, err := protoutil.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, channelID, nil, newConfigUpdateEnv, 0, 0) 122 if err != nil { 123 return errors.WithMessage(err, "could not create signed envelope") 124 } 125 126 logger.Info("Writing anchor peer update") 127 err = writeFile(outputAnchorPeersUpdate, protoutil.MarshalOrPanic(updateTx), 0o640) 128 if err != nil { 129 return fmt.Errorf("Error writing channel anchor peer update: %s", err) 130 } 131 return nil 132 } 133 134 func doInspectBlock(inspectBlock string) error { 135 logger.Info("Inspecting block") 136 data, err := ioutil.ReadFile(inspectBlock) 137 if err != nil { 138 return fmt.Errorf("could not read block %s", inspectBlock) 139 } 140 141 logger.Info("Parsing genesis block") 142 block, err := protoutil.UnmarshalBlock(data) 143 if err != nil { 144 return fmt.Errorf("error unmarshalling to block: %s", err) 145 } 146 err = protolator.DeepMarshalJSON(os.Stdout, block) 147 if err != nil { 148 return fmt.Errorf("malformed block contents: %s", err) 149 } 150 return nil 151 } 152 153 func doInspectChannelCreateTx(inspectChannelCreateTx string) error { 154 logger.Info("Inspecting transaction") 155 data, err := ioutil.ReadFile(inspectChannelCreateTx) 156 if err != nil { 157 return fmt.Errorf("could not read channel create tx: %s", err) 158 } 159 160 logger.Info("Parsing transaction") 161 env, err := protoutil.UnmarshalEnvelope(data) 162 if err != nil { 163 return fmt.Errorf("Error unmarshalling envelope: %s", err) 164 } 165 166 err = protolator.DeepMarshalJSON(os.Stdout, env) 167 if err != nil { 168 return fmt.Errorf("malformed transaction contents: %s", err) 169 } 170 171 return nil 172 } 173 174 func doPrintOrg(t *genesisconfig.TopLevel, printOrg string) error { 175 for _, org := range t.Organizations { 176 if org.Name == printOrg { 177 og, err := encoder.NewOrdererOrgGroup(org) 178 if err != nil { 179 return errors.Wrapf(err, "bad org definition for org %s", org.Name) 180 } 181 182 if err := protolator.DeepMarshalJSON(os.Stdout, &ordererext.DynamicOrdererOrgGroup{ConfigGroup: og}); err != nil { 183 return errors.Wrapf(err, "malformed org definition for org: %s", org.Name) 184 } 185 return nil 186 } 187 } 188 return errors.Errorf("organization %s not found", printOrg) 189 } 190 191 func writeFile(filename string, data []byte, perm os.FileMode) error { 192 dirPath := filepath.Dir(filename) 193 exists, err := dirExists(dirPath) 194 if err != nil { 195 return err 196 } 197 if !exists { 198 err = os.MkdirAll(dirPath, 0o750) 199 if err != nil { 200 return err 201 } 202 } 203 return ioutil.WriteFile(filename, data, perm) 204 } 205 206 func dirExists(path string) (bool, error) { 207 _, err := os.Stat(path) 208 if err == nil { 209 return true, nil 210 } 211 if os.IsNotExist(err) { 212 return false, nil 213 } 214 return false, err 215 } 216 217 func main() { 218 var outputBlock, outputChannelCreateTx, channelCreateTxBaseProfile, profile, configPath, channelID, inspectBlock, inspectChannelCreateTx, outputAnchorPeersUpdate, asOrg, printOrg string 219 220 flag.StringVar(&outputBlock, "outputBlock", "", "The path to write the genesis block to (if set)") 221 flag.StringVar(&channelID, "channelID", "", "The channel ID to use in the configtx") 222 flag.StringVar(&outputChannelCreateTx, "outputCreateChannelTx", "", "The path to write a channel creation configtx to (if set)") 223 flag.StringVar(&channelCreateTxBaseProfile, "channelCreateTxBaseProfile", "", "Specifies a profile to consider as the orderer system channel current state to allow modification of non-application parameters during channel create tx generation. Only valid in conjunction with 'outputCreateChannelTx'.") 224 flag.StringVar(&profile, "profile", "", "The profile from configtx.yaml to use for generation.") 225 flag.StringVar(&configPath, "configPath", "", "The path containing the configuration to use (if set)") 226 flag.StringVar(&inspectBlock, "inspectBlock", "", "Prints the configuration contained in the block at the specified path") 227 flag.StringVar(&inspectChannelCreateTx, "inspectChannelCreateTx", "", "Prints the configuration contained in the transaction at the specified path") 228 flag.StringVar(&outputAnchorPeersUpdate, "outputAnchorPeersUpdate", "", "[DEPRECATED] Creates a config update to update an anchor peer (works only with the default channel creation, and only for the first update)") 229 flag.StringVar(&asOrg, "asOrg", "", "Performs the config generation as a particular organization (by name), only including values in the write set that org (likely) has privilege to set") 230 flag.StringVar(&printOrg, "printOrg", "", "Prints the definition of an organization as JSON. (useful for adding an org to a channel manually)") 231 232 version := flag.Bool("version", false, "Show version information") 233 234 flag.Parse() 235 236 if channelID == "" && (outputBlock != "" || outputChannelCreateTx != "" || outputAnchorPeersUpdate != "") { 237 logger.Fatalf("Missing channelID, please specify it with '-channelID'") 238 } 239 240 // show version 241 if *version { 242 printVersion() 243 os.Exit(0) 244 } 245 246 // don't need to panic when running via command line 247 defer func() { 248 if err := recover(); err != nil { 249 if strings.Contains(fmt.Sprint(err), "Error reading configuration: Unsupported Config Type") { 250 logger.Error("Could not find configtx.yaml. " + 251 "Please make sure that FABRIC_CFG_PATH or -configPath is set to a path " + 252 "which contains configtx.yaml") 253 os.Exit(1) 254 } 255 if strings.Contains(fmt.Sprint(err), "Could not find profile") { 256 logger.Error(fmt.Sprint(err) + ". " + 257 "Please make sure that FABRIC_CFG_PATH or -configPath is set to a path " + 258 "which contains configtx.yaml with the specified profile") 259 os.Exit(1) 260 } 261 logger.Panic(err) 262 } 263 }() 264 265 logger.Info("Loading configuration") 266 err := factory.InitFactories(nil) 267 if err != nil { 268 logger.Fatalf("Error on initFactories: %s", err) 269 } 270 var profileConfig *genesisconfig.Profile 271 if outputBlock != "" || outputChannelCreateTx != "" || outputAnchorPeersUpdate != "" { 272 if profile == "" { 273 logger.Fatalf("The '-profile' is required when '-outputBlock', '-outputChannelCreateTx', or '-outputAnchorPeersUpdate' is specified") 274 } 275 276 if configPath != "" { 277 profileConfig = genesisconfig.Load(profile, configPath) 278 } else { 279 profileConfig = genesisconfig.Load(profile) 280 } 281 } 282 283 var baseProfile *genesisconfig.Profile 284 if channelCreateTxBaseProfile != "" { 285 if outputChannelCreateTx == "" { 286 logger.Warning("Specified 'channelCreateTxBaseProfile', but did not specify 'outputChannelCreateTx', 'channelCreateTxBaseProfile' will not affect output.") 287 } 288 if configPath != "" { 289 baseProfile = genesisconfig.Load(channelCreateTxBaseProfile, configPath) 290 } else { 291 baseProfile = genesisconfig.Load(channelCreateTxBaseProfile) 292 } 293 } 294 295 if outputBlock != "" { 296 if err := doOutputBlock(profileConfig, channelID, outputBlock); err != nil { 297 logger.Fatalf("Error on outputBlock: %s", err) 298 } 299 } 300 301 if outputChannelCreateTx != "" { 302 if err := doOutputChannelCreateTx(profileConfig, baseProfile, channelID, outputChannelCreateTx); err != nil { 303 logger.Fatalf("Error on outputChannelCreateTx: %s", err) 304 } 305 } 306 307 if inspectBlock != "" { 308 if err := doInspectBlock(inspectBlock); err != nil { 309 logger.Fatalf("Error on inspectBlock: %s", err) 310 } 311 } 312 313 if inspectChannelCreateTx != "" { 314 if err := doInspectChannelCreateTx(inspectChannelCreateTx); err != nil { 315 logger.Fatalf("Error on inspectChannelCreateTx: %s", err) 316 } 317 } 318 319 if outputAnchorPeersUpdate != "" { 320 if err := doOutputAnchorPeersUpdate(profileConfig, channelID, outputAnchorPeersUpdate, asOrg); err != nil { 321 logger.Fatalf("Error on inspectChannelCreateTx: %s", err) 322 } 323 } 324 325 if printOrg != "" { 326 var topLevelConfig *genesisconfig.TopLevel 327 if configPath != "" { 328 topLevelConfig = genesisconfig.LoadTopLevel(configPath) 329 } else { 330 topLevelConfig = genesisconfig.LoadTopLevel() 331 } 332 333 if err := doPrintOrg(topLevelConfig, printOrg); err != nil { 334 logger.Fatalf("Error on printOrg: %s", err) 335 } 336 } 337 } 338 339 func printVersion() { 340 fmt.Println(metadata.GetVersionInfo()) 341 }