github.com/defanghe/fabric@v2.1.1+incompatible/internal/peer/channel/join.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package channel 8 9 import ( 10 "context" 11 "errors" 12 "fmt" 13 "io/ioutil" 14 15 pcommon "github.com/hyperledger/fabric-protos-go/common" 16 pb "github.com/hyperledger/fabric-protos-go/peer" 17 "github.com/hyperledger/fabric/core/scc/cscc" 18 "github.com/hyperledger/fabric/internal/peer/common" 19 "github.com/hyperledger/fabric/protoutil" 20 "github.com/spf13/cobra" 21 ) 22 23 const commandDescription = "Joins the peer to a channel." 24 25 func joinCmd(cf *ChannelCmdFactory) *cobra.Command { 26 // Set the flags on the channel start command. 27 joinCmd := &cobra.Command{ 28 Use: "join", 29 Short: commandDescription, 30 Long: commandDescription, 31 RunE: func(cmd *cobra.Command, args []string) error { 32 return join(cmd, args, cf) 33 }, 34 } 35 flagList := []string{ 36 "blockpath", 37 } 38 attachFlags(joinCmd, flagList) 39 40 return joinCmd 41 } 42 43 //GBFileNotFoundErr genesis block file not found 44 type GBFileNotFoundErr string 45 46 func (e GBFileNotFoundErr) Error() string { 47 return fmt.Sprintf("genesis block file not found %s", string(e)) 48 } 49 50 //ProposalFailedErr proposal failed 51 type ProposalFailedErr string 52 53 func (e ProposalFailedErr) Error() string { 54 return fmt.Sprintf("proposal failed (err: %s)", string(e)) 55 } 56 57 func getJoinCCSpec() (*pb.ChaincodeSpec, error) { 58 if genesisBlockPath == common.UndefinedParamValue { 59 return nil, errors.New("Must supply genesis block file") 60 } 61 62 gb, err := ioutil.ReadFile(genesisBlockPath) 63 if err != nil { 64 return nil, GBFileNotFoundErr(err.Error()) 65 } 66 // Build the spec 67 input := &pb.ChaincodeInput{Args: [][]byte{[]byte(cscc.JoinChain), gb}} 68 69 spec := &pb.ChaincodeSpec{ 70 Type: pb.ChaincodeSpec_Type(pb.ChaincodeSpec_Type_value["GOLANG"]), 71 ChaincodeId: &pb.ChaincodeID{Name: "cscc"}, 72 Input: input, 73 } 74 75 return spec, nil 76 } 77 78 func executeJoin(cf *ChannelCmdFactory) (err error) { 79 spec, err := getJoinCCSpec() 80 if err != nil { 81 return err 82 } 83 84 // Build the ChaincodeInvocationSpec message 85 invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} 86 87 creator, err := cf.Signer.Serialize() 88 if err != nil { 89 return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err) 90 } 91 92 var prop *pb.Proposal 93 prop, _, err = protoutil.CreateProposalFromCIS(pcommon.HeaderType_CONFIG, "", invocation, creator) 94 if err != nil { 95 return fmt.Errorf("Error creating proposal for join %s", err) 96 } 97 98 var signedProp *pb.SignedProposal 99 signedProp, err = protoutil.GetSignedProposal(prop, cf.Signer) 100 if err != nil { 101 return fmt.Errorf("Error creating signed proposal %s", err) 102 } 103 104 var proposalResp *pb.ProposalResponse 105 proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp) 106 if err != nil { 107 return ProposalFailedErr(err.Error()) 108 } 109 110 if proposalResp == nil { 111 return ProposalFailedErr("nil proposal response") 112 } 113 114 if proposalResp.Response.Status != 0 && proposalResp.Response.Status != 200 { 115 return ProposalFailedErr(fmt.Sprintf("bad proposal response %d: %s", proposalResp.Response.Status, proposalResp.Response.Message)) 116 } 117 logger.Info("Successfully submitted proposal to join channel") 118 return nil 119 } 120 121 func join(cmd *cobra.Command, args []string, cf *ChannelCmdFactory) error { 122 if genesisBlockPath == common.UndefinedParamValue { 123 return errors.New("Must supply genesis block path") 124 } 125 // Parsing of the command line is done so silence cmd usage 126 cmd.SilenceUsage = true 127 128 var err error 129 if cf == nil { 130 cf, err = InitCmdFactory(EndorserRequired, PeerDeliverNotRequired, OrdererNotRequired) 131 if err != nil { 132 return err 133 } 134 } 135 return executeJoin(cf) 136 }