github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/peer/channel/channel.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  	"strings"
    22  
    23  	"github.com/inklabsfoundation/inkchain/common/flogging"
    24  	"github.com/inklabsfoundation/inkchain/msp"
    25  	"github.com/inklabsfoundation/inkchain/peer/common"
    26  	ab "github.com/inklabsfoundation/inkchain/protos/orderer"
    27  	pb "github.com/inklabsfoundation/inkchain/protos/peer"
    28  	"github.com/spf13/cobra"
    29  	"github.com/spf13/pflag"
    30  	"golang.org/x/net/context"
    31  	"google.golang.org/grpc"
    32  	"google.golang.org/grpc/credentials"
    33  )
    34  
    35  const (
    36  	channelFuncName = "channel"
    37  	shortDes        = "Operate a channel: create|fetch|join|list|update."
    38  	longDes         = "Operate a channel: create|fetch|join|list|update."
    39  )
    40  
    41  var logger = flogging.MustGetLogger("channelCmd")
    42  
    43  type OrdererRequirement bool
    44  type EndorserRequirement bool
    45  
    46  const (
    47  	EndorserRequired    EndorserRequirement = true
    48  	EndorserNotRequired EndorserRequirement = false
    49  	OrdererRequired     OrdererRequirement  = true
    50  	OrdererNotRequired  OrdererRequirement  = false
    51  )
    52  
    53  var (
    54  	// join related variables.
    55  	genesisBlockPath string
    56  
    57  	// create related variables
    58  	chainID          string
    59  	channelTxFile    string
    60  	orderingEndpoint string
    61  	tls              bool
    62  	caFile           string
    63  	timeout          int
    64  )
    65  
    66  // Cmd returns the cobra command for Node
    67  func Cmd(cf *ChannelCmdFactory) *cobra.Command {
    68  	AddFlags(channelCmd)
    69  
    70  	channelCmd.AddCommand(createCmd(cf))
    71  	channelCmd.AddCommand(fetchCmd(cf))
    72  	channelCmd.AddCommand(joinCmd(cf))
    73  	channelCmd.AddCommand(listCmd(cf))
    74  	channelCmd.AddCommand(updateCmd(cf))
    75  	channelCmd.AddCommand(signconfigtxCmd(cf))
    76  
    77  	return channelCmd
    78  }
    79  
    80  // AddFlags adds flags for create and join
    81  func AddFlags(cmd *cobra.Command) {
    82  	flags := cmd.PersistentFlags()
    83  
    84  	flags.StringVarP(&orderingEndpoint, "orderer", "o", "", "Ordering service endpoint")
    85  	flags.BoolVarP(&tls, "tls", "", false, "Use TLS when communicating with the orderer endpoint")
    86  	flags.StringVarP(&caFile, "cafile", "", "", "Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint")
    87  }
    88  
    89  var flags *pflag.FlagSet
    90  
    91  func init() {
    92  	resetFlags()
    93  }
    94  
    95  // Explicitly define a method to facilitate tests
    96  func resetFlags() {
    97  	flags = &pflag.FlagSet{}
    98  
    99  	flags.StringVarP(&genesisBlockPath, "blockpath", "b", common.UndefinedParamValue, "Path to file containing genesis block")
   100  	flags.StringVarP(&chainID, "channelID", "c", common.UndefinedParamValue, "In case of a newChain command, the channel ID to create.")
   101  	flags.StringVarP(&channelTxFile, "file", "f", "", "Configuration transaction file generated by a tool such as configtxgen for submitting to orderer")
   102  	flags.IntVarP(&timeout, "timeout", "t", 5, "Channel creation timeout")
   103  }
   104  
   105  func attachFlags(cmd *cobra.Command, names []string) {
   106  	cmdFlags := cmd.Flags()
   107  	for _, name := range names {
   108  		if flag := flags.Lookup(name); flag != nil {
   109  			cmdFlags.AddFlag(flag)
   110  		} else {
   111  			logger.Fatalf("Could not find flag '%s' to attach to commond '%s'", name, cmd.Name())
   112  		}
   113  	}
   114  }
   115  
   116  var channelCmd = &cobra.Command{
   117  	Use:   channelFuncName,
   118  	Short: fmt.Sprint(shortDes),
   119  	Long:  fmt.Sprint(longDes),
   120  }
   121  
   122  type BroadcastClientFactory func() (common.BroadcastClient, error)
   123  
   124  // ChannelCmdFactory holds the clients used by ChannelCmdFactory
   125  type ChannelCmdFactory struct {
   126  	EndorserClient   pb.EndorserClient
   127  	Signer           msp.SigningIdentity
   128  	BroadcastClient  common.BroadcastClient
   129  	DeliverClient    deliverClientIntf
   130  	BroadcastFactory BroadcastClientFactory
   131  }
   132  
   133  // InitCmdFactory init the ChannelCmdFactory with clients to endorser and orderer according to params
   134  func InitCmdFactory(isEndorserRequired EndorserRequirement, isOrdererRequired OrdererRequirement) (*ChannelCmdFactory, error) {
   135  	var err error
   136  
   137  	cmdFact := &ChannelCmdFactory{}
   138  
   139  	cmdFact.Signer, err = common.GetDefaultSignerFnc()
   140  	if err != nil {
   141  		return nil, fmt.Errorf("Error getting default signer: %s", err)
   142  	}
   143  
   144  	cmdFact.BroadcastFactory = func() (common.BroadcastClient, error) {
   145  		return common.GetBroadcastClientFnc(orderingEndpoint, tls, caFile)
   146  	}
   147  
   148  	//for join and list, we need the endorser as well
   149  	if isEndorserRequired {
   150  		cmdFact.EndorserClient, err = common.GetEndorserClientFnc()
   151  		if err != nil {
   152  			return nil, fmt.Errorf("Error getting endorser client %s: %s", channelFuncName, err)
   153  		}
   154  	}
   155  
   156  	//for create and fetch, we need the orderer as well
   157  	if isOrdererRequired {
   158  		if len(strings.Split(orderingEndpoint, ":")) != 2 {
   159  			return nil, fmt.Errorf("Ordering service endpoint %s is not valid or missing", orderingEndpoint)
   160  		}
   161  
   162  		var opts []grpc.DialOption
   163  		// check for TLS
   164  		if tls {
   165  			if caFile != "" {
   166  				creds, err := credentials.NewClientTLSFromFile(caFile, "")
   167  				if err != nil {
   168  					return nil, fmt.Errorf("Error connecting to %s due to %s", orderingEndpoint, err)
   169  				}
   170  				opts = append(opts, grpc.WithTransportCredentials(creds))
   171  			}
   172  		} else {
   173  			opts = append(opts, grpc.WithInsecure())
   174  		}
   175  		conn, err := grpc.Dial(orderingEndpoint, opts...)
   176  		if err != nil {
   177  			return nil, err
   178  		}
   179  
   180  		client, err := ab.NewAtomicBroadcastClient(conn).Deliver(context.TODO())
   181  		if err != nil {
   182  			return nil, fmt.Errorf("Error connecting due to  %s", err)
   183  		}
   184  
   185  		cmdFact.DeliverClient = newDeliverClient(conn, client, chainID)
   186  	}
   187  	logger.Infof("Endorser and orderer connections initialized")
   188  	return cmdFact, nil
   189  }