github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/peer/channel/create.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package channel
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"time"
    23  
    24  	"errors"
    25  
    26  	"github.com/golang/protobuf/proto"
    27  	"github.com/hyperledger/fabric/common/configtx"
    28  	genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig"
    29  	localsigner "github.com/hyperledger/fabric/common/localmsp"
    30  	"github.com/hyperledger/fabric/common/util"
    31  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    32  	"github.com/hyperledger/fabric/peer/common"
    33  	cb "github.com/hyperledger/fabric/protos/common"
    34  	"github.com/hyperledger/fabric/protos/utils"
    35  	"github.com/spf13/cobra"
    36  )
    37  
    38  //ConfigTxFileNotFound channel create configuration tx file not found
    39  type ConfigTxFileNotFound string
    40  
    41  const createCmdDescription = "Create a channel"
    42  
    43  func (e ConfigTxFileNotFound) Error() string {
    44  	return fmt.Sprintf("channel create configuration tx file not found %s", string(e))
    45  }
    46  
    47  //InvalidCreateTx invalid channel create transaction
    48  type InvalidCreateTx string
    49  
    50  func (e InvalidCreateTx) Error() string {
    51  	return fmt.Sprintf("Invalid channel create transaction : %s", string(e))
    52  }
    53  
    54  func createCmd(cf *ChannelCmdFactory) *cobra.Command {
    55  	createCmd := &cobra.Command{
    56  		Use:   "create",
    57  		Short: createCmdDescription,
    58  		Long:  createCmdDescription,
    59  		RunE: func(cmd *cobra.Command, args []string) error {
    60  			return create(cmd, args, cf)
    61  		},
    62  	}
    63  
    64  	return createCmd
    65  }
    66  
    67  func createChannelFromDefaults(cf *ChannelCmdFactory) (*cb.Envelope, error) {
    68  	signer, err := mspmgmt.GetLocalMSP().GetDefaultSigningIdentity()
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	chCrtEnv, err := configtx.MakeChainCreationTransaction(chainID, genesisconfig.SampleConsortiumName, signer)
    74  
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	return chCrtEnv, nil
    80  }
    81  
    82  func createChannelFromConfigTx(configTxFileName string) (*cb.Envelope, error) {
    83  	cftx, err := ioutil.ReadFile(configTxFileName)
    84  	if err != nil {
    85  		return nil, ConfigTxFileNotFound(err.Error())
    86  	}
    87  
    88  	return utils.UnmarshalEnvelope(cftx)
    89  }
    90  
    91  func sanityCheckAndSignChannelCreateTx(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) {
    92  	payload, err := utils.ExtractPayload(envConfigUpdate)
    93  	if err != nil {
    94  		return nil, InvalidCreateTx("bad payload")
    95  	}
    96  
    97  	if payload.Header == nil || payload.Header.ChannelHeader == nil {
    98  		return nil, InvalidCreateTx("bad header")
    99  	}
   100  
   101  	ch, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   102  	if err != nil {
   103  		return nil, InvalidCreateTx("could not unmarshall channel header")
   104  	}
   105  
   106  	if ch.Type != int32(cb.HeaderType_CONFIG_UPDATE) {
   107  		return nil, InvalidCreateTx("bad type")
   108  	}
   109  
   110  	if ch.ChannelId == "" {
   111  		return nil, InvalidCreateTx("empty channel id")
   112  	}
   113  
   114  	if ch.ChannelId != chainID {
   115  		return nil, InvalidCreateTx(fmt.Sprintf("mismatched channel ID %s != %s", ch.ChannelId, chainID))
   116  	}
   117  
   118  	configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(payload.Data)
   119  	if err != nil {
   120  		return nil, InvalidCreateTx("Bad config update env")
   121  	}
   122  
   123  	signer := localsigner.NewSigner()
   124  	sigHeader, err := signer.NewSignatureHeader()
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	configSig := &cb.ConfigSignature{
   130  		SignatureHeader: utils.MarshalOrPanic(sigHeader),
   131  	}
   132  
   133  	configSig.Signature, err = signer.Sign(util.ConcatenateBytes(configSig.SignatureHeader, configUpdateEnv.ConfigUpdate))
   134  
   135  	configUpdateEnv.Signatures = append(configUpdateEnv.Signatures, configSig)
   136  
   137  	return utils.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, chainID, signer, configUpdateEnv, 0, 0)
   138  }
   139  
   140  func sendCreateChainTransaction(cf *ChannelCmdFactory) error {
   141  	var err error
   142  	var chCrtEnv *cb.Envelope
   143  
   144  	if channelTxFile != "" {
   145  		if chCrtEnv, err = createChannelFromConfigTx(channelTxFile); err != nil {
   146  			return err
   147  		}
   148  	} else {
   149  		if chCrtEnv, err = createChannelFromDefaults(cf); err != nil {
   150  			return err
   151  		}
   152  	}
   153  
   154  	if chCrtEnv, err = sanityCheckAndSignChannelCreateTx(chCrtEnv); err != nil {
   155  		return err
   156  	}
   157  
   158  	var broadcastClient common.BroadcastClient
   159  	broadcastClient, err = cf.BroadcastFactory()
   160  	if err != nil {
   161  		return err
   162  	}
   163  
   164  	defer broadcastClient.Close()
   165  	err = broadcastClient.Send(chCrtEnv)
   166  
   167  	return err
   168  }
   169  
   170  func executeCreate(cf *ChannelCmdFactory) error {
   171  	var err error
   172  
   173  	if err = sendCreateChainTransaction(cf); err != nil {
   174  		return err
   175  	}
   176  
   177  	time.Sleep(2 * time.Second)
   178  
   179  	var block *cb.Block
   180  	if block, err = cf.DeliverClient.getBlock(); err != nil {
   181  		return err
   182  	}
   183  
   184  	b, err := proto.Marshal(block)
   185  	if err != nil {
   186  		return err
   187  	}
   188  
   189  	file := chainID + ".block"
   190  	if err = ioutil.WriteFile(file, b, 0644); err != nil {
   191  		return err
   192  	}
   193  
   194  	return nil
   195  }
   196  
   197  func create(cmd *cobra.Command, args []string, cf *ChannelCmdFactory) error {
   198  	//the global chainID filled by the "-c" command
   199  	if chainID == common.UndefinedParamValue {
   200  		return errors.New("Must supply channel ID")
   201  	}
   202  
   203  	var err error
   204  	if cf == nil {
   205  		cf, err = InitCmdFactory(false)
   206  		if err != nil {
   207  			return err
   208  		}
   209  	}
   210  	return executeCreate(cf)
   211  }