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 }