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  }