diff --git a/common/configtx/tool/configtxgen/main.go b/common/configtx/tool/configtxgen/main.go index aac401b3f35..3fffcc6811d 100644 --- a/common/configtx/tool/configtxgen/main.go +++ b/common/configtx/tool/configtxgen/main.go @@ -20,24 +20,23 @@ import ( "flag" "io/ioutil" + "github.com/hyperledger/fabric/common/configtx" genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig" "github.com/hyperledger/fabric/common/configtx/tool/provisional" + "github.com/hyperledger/fabric/msp" "github.com/hyperledger/fabric/protos/utils" logging "github.com/op/go-logging" ) -const ( - DefaultGenesisFileLocation = "genesis.block" -) - var logger = logging.MustGetLogger("common/configtx/tool") func main() { - var writePath, profile string + var outputBlock, outputChannelCreateTx, profile, channelID string - dryRun := flag.Bool("dryRun", false, "Whether to only generate but not write the genesis block file.") - flag.StringVar(&writePath, "path", DefaultGenesisFileLocation, "The path to write the genesis block to.") + flag.StringVar(&outputBlock, "outputBlock", "", "The path to write the genesis block to (if set)") + flag.StringVar(&channelID, "channelID", provisional.TestChainID, "The channel ID to use in the configtx") + flag.StringVar(&outputChannelCreateTx, "outputCreateChannelTx", "", "The path to write a channel creation configtx to (if set)") flag.StringVar(&profile, "profile", genesisconfig.SampleInsecureProfile, "The profile from configtx.yaml to use for generation.") flag.Parse() @@ -45,12 +44,33 @@ func main() { logger.Info("Loading configuration") config := genesisconfig.Load(profile) + pgen := provisional.New(config) - logger.Info("Generating genesis block") - genesisBlock := provisional.New(config).GenesisBlock() - - if !*dryRun { + if outputBlock != "" { + logger.Info("Generating genesis block") + genesisBlock := pgen.GenesisBlock() logger.Info("Writing genesis block") - ioutil.WriteFile(writePath, utils.MarshalOrPanic(genesisBlock), 0644) + err := ioutil.WriteFile(outputBlock, utils.MarshalOrPanic(genesisBlock), 0644) + if err != nil { + logger.Errorf("Error writing genesis block: %s", err) + } + } + + if outputChannelCreateTx != "" { + logger.Info("Generating new channel configtx") + // TODO, use actual MSP eventually + signer, err := msp.NewNoopMsp().GetDefaultSigningIdentity() + if err != nil { + logger.Fatalf("Error getting signing identity: %s", err) + } + configtx, err := configtx.MakeChainCreationTransaction(provisional.AcceptAllPolicyKey, channelID, signer, pgen.ChannelTemplate()) + if err != nil { + logger.Fatalf("Error generating configtx: %s", err) + } + logger.Info("Writing new channel tx") + err = ioutil.WriteFile(outputChannelCreateTx, utils.MarshalOrPanic(configtx), 0644) + if err != nil { + logger.Errorf("Error writing channel create tx: %s", err) + } } } diff --git a/common/configtx/tool/provisional/provisional.go b/common/configtx/tool/provisional/provisional.go index 429ef54eed9..466cf2dc6cd 100644 --- a/common/configtx/tool/provisional/provisional.go +++ b/common/configtx/tool/provisional/provisional.go @@ -163,6 +163,7 @@ func (bs *bootstrapper) ChannelTemplate() configtx.Template { ) } +// XXX deprecate and remove func (bs *bootstrapper) GenesisBlock() *cb.Block { block, err := genesis.NewFactoryImpl( configtx.NewCompositeTemplate( @@ -176,3 +177,17 @@ func (bs *bootstrapper) GenesisBlock() *cb.Block { } return block } + +func (bs *bootstrapper) GenesisBlockForChannel(channelID string) *cb.Block { + block, err := genesis.NewFactoryImpl( + configtx.NewCompositeTemplate( + configtx.NewSimpleTemplate(bs.ordererSystemChannelGroups...), + bs.ChannelTemplate(), + ), + ).Block(channelID) + + if err != nil { + panic(err) + } + return block +} diff --git a/docs/configtxgen.md b/docs/configtxgen.md index cc3358ff670..4a0f2dca0f8 100644 --- a/docs/configtxgen.md +++ b/docs/configtxgen.md @@ -23,8 +23,18 @@ This configuration file may be edited, or, individual properties may be overridd ## Bootstrapping the orderer After creating a configuration profile as desired, simply invoke ``` -configtxgen -profile <profile_name> +configtxgen -profile <profile_name> -outputBlock <genesis.blockname> ``` -This will produce a `genesis.block` file in the current directory. You may optionally specify another filename by passing in the `-path` parameter, or, you may skip the writing of the file by passing the `dryRun` parameter if you simply wish to test parsing of the file. +This will produce a `genesis.block` file in the current directory. If you wish to skip writing the file simply do not pass `outputBlock` Then, to utilize this genesis block, before starting the orderer, simply specify `ORDERER_GENERAL_GENESISMETHOD=file` and `ORDERER_GENERAL_GENESISFILE=$PWD/genesis.block` or modify the `orderer.yaml` file to encode these values. + +## Creating a channel + +The tool can also output a channel creation tx by executing + +``` +configtxgen -profile <profile_name> -outputCreateChannelTx <output.txname> +``` + +This will output a marshaled `Envelope` message which may be sent to broadcast to create a channel.