github.com/true-sqn/fabric@v2.1.1+incompatible/internal/peer/channel/channel.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package channel
     8  
     9  import (
    10  	"strings"
    11  	"time"
    12  
    13  	cb "github.com/hyperledger/fabric-protos-go/common"
    14  	pb "github.com/hyperledger/fabric-protos-go/peer"
    15  	"github.com/hyperledger/fabric/common/flogging"
    16  	"github.com/hyperledger/fabric/internal/peer/common"
    17  	"github.com/hyperledger/fabric/msp"
    18  	"github.com/pkg/errors"
    19  	"github.com/spf13/cobra"
    20  	"github.com/spf13/pflag"
    21  )
    22  
    23  var logger = flogging.MustGetLogger("channelCmd")
    24  
    25  const (
    26  	EndorserRequired       bool = true
    27  	EndorserNotRequired    bool = false
    28  	OrdererRequired        bool = true
    29  	OrdererNotRequired     bool = false
    30  	PeerDeliverRequired    bool = true
    31  	PeerDeliverNotRequired bool = false
    32  )
    33  
    34  var (
    35  	// join related variables.
    36  	genesisBlockPath string
    37  
    38  	// create related variables
    39  	channelID     string
    40  	channelTxFile string
    41  	outputBlock   string
    42  	timeout       time.Duration
    43  
    44  	// fetch related variables
    45  	bestEffort bool
    46  )
    47  
    48  // Cmd returns the cobra command for Node
    49  func Cmd(cf *ChannelCmdFactory) *cobra.Command {
    50  	AddFlags(channelCmd)
    51  
    52  	channelCmd.AddCommand(createCmd(cf))
    53  	channelCmd.AddCommand(fetchCmd(cf))
    54  	channelCmd.AddCommand(joinCmd(cf))
    55  	channelCmd.AddCommand(listCmd(cf))
    56  	channelCmd.AddCommand(updateCmd(cf))
    57  	channelCmd.AddCommand(signconfigtxCmd(cf))
    58  	channelCmd.AddCommand(getinfoCmd(cf))
    59  
    60  	return channelCmd
    61  }
    62  
    63  // AddFlags adds flags for create and join
    64  func AddFlags(cmd *cobra.Command) {
    65  	common.AddOrdererFlags(cmd)
    66  }
    67  
    68  var flags *pflag.FlagSet
    69  
    70  func init() {
    71  	resetFlags()
    72  }
    73  
    74  // Explicitly define a method to facilitate tests
    75  func resetFlags() {
    76  	flags = &pflag.FlagSet{}
    77  
    78  	flags.StringVarP(&genesisBlockPath, "blockpath", "b", common.UndefinedParamValue, "Path to file containing genesis block")
    79  	flags.StringVarP(&channelID, "channelID", "c", common.UndefinedParamValue, "In case of a newChain command, the channel ID to create. It must be all lower case, less than 250 characters long and match the regular expression: [a-z][a-z0-9.-]*")
    80  	flags.StringVarP(&channelTxFile, "file", "f", "", "Configuration transaction file generated by a tool such as configtxgen for submitting to orderer")
    81  	flags.StringVarP(&outputBlock, "outputBlock", "", common.UndefinedParamValue, `The path to write the genesis block for the channel. (default ./<channelID>.block)`)
    82  	flags.DurationVarP(&timeout, "timeout", "t", 10*time.Second, "Channel creation timeout")
    83  	flags.BoolVarP(&bestEffort, "bestEffort", "", false, "Whether fetch requests should ignore errors and return blocks on a best effort basis")
    84  }
    85  
    86  func attachFlags(cmd *cobra.Command, names []string) {
    87  	cmdFlags := cmd.Flags()
    88  	for _, name := range names {
    89  		if flag := flags.Lookup(name); flag != nil {
    90  			cmdFlags.AddFlag(flag)
    91  		} else {
    92  			logger.Fatalf("Could not find flag '%s' to attach to commond '%s'", name, cmd.Name())
    93  		}
    94  	}
    95  }
    96  
    97  var channelCmd = &cobra.Command{
    98  	Use:   "channel",
    99  	Short: "Operate a channel: create|fetch|join|list|update|signconfigtx|getinfo.",
   100  	Long:  "Operate a channel: create|fetch|join|list|update|signconfigtx|getinfo.",
   101  	PersistentPreRun: func(cmd *cobra.Command, args []string) {
   102  		common.InitCmd(cmd, args)
   103  		common.SetOrdererEnv(cmd, args)
   104  	},
   105  }
   106  
   107  type BroadcastClientFactory func() (common.BroadcastClient, error)
   108  
   109  type deliverClientIntf interface {
   110  	GetSpecifiedBlock(num uint64) (*cb.Block, error)
   111  	GetOldestBlock() (*cb.Block, error)
   112  	GetNewestBlock() (*cb.Block, error)
   113  	Close() error
   114  }
   115  
   116  // ChannelCmdFactory holds the clients used by ChannelCmdFactory
   117  type ChannelCmdFactory struct {
   118  	EndorserClient   pb.EndorserClient
   119  	Signer           msp.SigningIdentity
   120  	BroadcastClient  common.BroadcastClient
   121  	DeliverClient    deliverClientIntf
   122  	BroadcastFactory BroadcastClientFactory
   123  }
   124  
   125  // InitCmdFactory init the ChannelCmdFactory with clients to endorser and orderer according to params
   126  func InitCmdFactory(isEndorserRequired, isPeerDeliverRequired, isOrdererRequired bool) (*ChannelCmdFactory, error) {
   127  	if isPeerDeliverRequired && isOrdererRequired {
   128  		// this is likely a bug during development caused by adding a new cmd
   129  		return nil, errors.New("ERROR - only a single deliver source is currently supported")
   130  	}
   131  
   132  	var err error
   133  	cf := &ChannelCmdFactory{}
   134  
   135  	cf.Signer, err = common.GetDefaultSignerFnc()
   136  	if err != nil {
   137  		return nil, errors.WithMessage(err, "error getting default signer")
   138  	}
   139  
   140  	cf.BroadcastFactory = func() (common.BroadcastClient, error) {
   141  		return common.GetBroadcastClientFnc()
   142  	}
   143  
   144  	// for join and list, we need the endorser as well
   145  	if isEndorserRequired {
   146  		// creating an EndorserClient with these empty parameters will create a
   147  		// connection using the values of "peer.address" and
   148  		// "peer.tls.rootcert.file"
   149  		cf.EndorserClient, err = common.GetEndorserClientFnc(common.UndefinedParamValue, common.UndefinedParamValue)
   150  		if err != nil {
   151  			return nil, errors.WithMessage(err, "error getting endorser client for channel")
   152  		}
   153  	}
   154  
   155  	// for fetching blocks from a peer
   156  	if isPeerDeliverRequired {
   157  		cf.DeliverClient, err = common.NewDeliverClientForPeer(channelID, cf.Signer, bestEffort)
   158  		if err != nil {
   159  			return nil, errors.WithMessage(err, "error getting deliver client for channel")
   160  		}
   161  	}
   162  
   163  	// for create and fetch, we need the orderer as well
   164  	if isOrdererRequired {
   165  		if len(strings.Split(common.OrderingEndpoint, ":")) != 2 {
   166  			return nil, errors.Errorf("ordering service endpoint %s is not valid or missing", common.OrderingEndpoint)
   167  		}
   168  		cf.DeliverClient, err = common.NewDeliverClientForOrderer(channelID, cf.Signer, bestEffort)
   169  		if err != nil {
   170  			return nil, err
   171  		}
   172  	}
   173  
   174  	logger.Infof("Endorser and orderer connections initialized")
   175  	return cf, nil
   176  }