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