hperledger fabric 1.0 源码分析之peer node start

前言:

      一、fabric所涉及方面比较多,建议先了解下相关的内容。

              1、Cobra

                          Cobra既是用于创建强大的现代CLI应用程序的库,也是用于生成应用程序和命令文件的程序。

                         示例:

                                 github.com/spf13/cobra go cobra包介绍

                                 go cobra包基础示例

               2、Viper

                           Viper可以被认为是所有应用程序配置需求的注册表,读取应用程序中的配置信息。

                           示例:

                                   github.com/spf13/viper go viper包介绍

         二、针对源码进行解释,来了解整个过程。

源码分析:

  一、定义peer命令并添加子命令

//github.com/hyperledger/fabric/peer/main.go
//peer命令的定义
var mainCmd = &cobra.Command{
	Use: "peer",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		// check for CORE_LOGGING_LEVEL environment variable, which should override
		// all other log settings
		loggingSpec := viper.GetString("logging_level")

		if loggingSpec == "" {
			// if CORE_LOGGING_LEVEL not set, use the value for 'peer' from core.yaml
			loggingSpec = viper.GetString("logging.peer")
		}
		flogging.InitFromSpec(loggingSpec)

		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		if versionFlag {
			fmt.Print(version.GetInfo())
		} else {
			cmd.HelpFunc()(cmd, args)
		}
	},
}

//在main方法mainCmd.Execute注册运行
//通过mainCmd.AddCommand添加子命令version、node、chaincode、clilogging、channel
func main(){
    ...
    //初始化配置文件core.yaml
    err := common.InitConfig(cmdRoot)
    ...
    mainCmd.AddCommand(version.Cmd())
    mainCmd.AddCommand(node.Cmd())
    mainCmd.AddCommand(chaincode.Cmd(nil))
    mainCmd.AddCommand(clilogging.Cmd(nil))
    mainCmd.AddCommand(channel.Cmd(nil))
    ...
    if mainCmd.Execute() != nil {
        os.Exit(1)
    }
    ...
}

二、定义peer node命令并添加子命令

#github.com/hyperledger/fabric/peer/node/node.go
#peer node命令下添加了两个子命令start和status
const (
	nodeFuncName = "node"
	shortDes     = "Operate a peer node: start|status."
	longDes      = "Operate a peer node: start|status."
)

var logger = flogging.MustGetLogger("nodeCmd")

// Cmd returns the cobra command for Node
func Cmd() *cobra.Command {
	nodeCmd.AddCommand(startCmd())
	nodeCmd.AddCommand(statusCmd())

	return nodeCmd
}

var nodeCmd = &cobra.Command{
	Use:   nodeFuncName,
	Short: fmt.Sprint(shortDes),
	Long:  fmt.Sprint(longDes),
}

三、start命令定义

 该命令执行时返回serve方法

//github.com/hyperledger/fabric/peer/node/start.go
func startCmd() *cobra.Command {
	// Set the flags on the node start command.
	flags := nodeStartCmd.Flags()
	flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false,
		"Whether peer in chaincode development mode")
	flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", false,
		"Whether to start peer with chain testchainid")
	flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint")

	return nodeStartCmd
}
var nodeStartCmd = &cobra.Command{
	Use:   "start",
	Short: "Starts the node.",
	Long:  `Starts a node that interacts with the network.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		return serve(args)
	},
}

四、serve方法

由于内容过多,所以先整体进行说明,具体的内容可向下查看,根据需要查看相关部分。

func serve(args []string) error {
	logger.Infof("Starting %s", version.GetInfo())
    //初始化账本,并构造账本数据提供者ledgerProvider
	ledgermgmt.Initialize()
	// Parameter overrides must be processed before any parameters are
	// cached. Failures to cache cause the server to terminate immediately.
    //判断是否为开发模式
	if chaincodeDevMode {	
		logger.Info("Running in chaincode development mode")
		logger.Info("Disable loading validity system chaincode")

		viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode)

	}
    //peer.CacheConfiguration设置并缓存全局变量localAddress和PeerEndpoint
    //默认localAddress=0.0.0.0:7051
    //默认peerEndpoint是一个结构体,包含peer.id、peer.address
	if err := peer.CacheConfiguration(); err != nil {
		return err
	}
    //获取由peer.CacheConfiguration设置的PeerEndpoint
	peerEndpoint, err := peer.GetPeerEndpoint()
	if err != nil {
		err = fmt.Errorf("Failed to get Peer Endpoint: %s", err)
		return err
	}

	//创建GRPCserver套接字所需的监听地址
	listenAddr := viper.GetString("peer.listenAddress")

	//获取PeerServer安全配置,是否启用TLS、公钥、私钥、根证书等信息
	secureConfig, err := peer.GetSecureConfig()
	if err != nil {
		logger.Fatalf("Error loading secure config for peer (%s)", err)
	}
	//创建PeerServer其内部返回一个GRPCServer
	peerServer, err := peer.CreatePeerServer(listenAddr, secureConfig)
	if err != nil {
		logger.Fatalf("Failed to create peer server (%s)", err)
	}
    //如果启用TLS,提供CA支持
	if secureConfig.UseTLS {
		logger.Info("Starting peer with TLS enabled")
		// set up CA support
		caSupport := comm.GetCASupport()
		caSupport.ServerRootCAs = secureConfig.ServerRootCAs
	}

	//TODO - do we need different SSL material for events ?
	//创建EventHubServer(事件中心服务器)
    //默认监听地址为0.0.0.0:7053
    //同时EventHubServer也是一个GRPCserver
	ehubGrpcServer, err := createEventHubServer(secureConfig)
	if err != nil {
		grpclog.Fatalf("Failed to create ehub server: %v", err)
	}

	// enable the cache of chaincode info
    //启用链码缓存
	ccprovider.EnableCCInfoCache()
    
    //创建ChaincodeServer
    //ChaincodeServer监听peer.chaincodeListenAddress地址
    //peer.chaincodeListenAddress默认未配置,监听listenAddr,即0.0.0.0:7051
    //所以默认启的链码服务即peer服务,但配置peer.chaincodeListenAddress后将分开启两个服务
	ccSrv, ccEpFunc := createChaincodeServer(peerServer, listenAddr)
    //注册服务(将ChaincodeServer注册到创建的peer grpc server)
	registerChaincodeSupport(ccSrv.Server(), ccEpFunc)
    //启动服务
	go ccSrv.Start()

	logger.Debugf("Running peer")

	// Register the Admin server
    //注册Admin server
    //Admin server用于peer node status命令
	pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer())

	// Register the Endorser server
    //注册Endorser server
	serverEndorser := endorser.NewEndorserServer()
	pb.RegisterEndorserServer(peerServer.Server(), serverEndorser)

	// Initialize gossip component
    //注册GOSSIP组件
    //bootstrap=127.0.0.1:7051
    //启动peer后gossip连接的初始节点
	bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")
	//serializedIdentity获取签名身份
	serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
	if err != nil {
		logger.Panicf("Failed serializing self identity: %v", err)
	}
	//构造mspMessageCryptoService(消息加密服务)
	messageCryptoService := peergossip.NewMCS(
		peer.NewChannelPolicyManagerGetter(), //它通过Manager方法提供对给定通道的策略管理器的访问/type channelPolicyManagerGetter struct{}
		localmsp.NewSigner(),                 //一个加密实例/type mspSigner struct {}
		mgmt.NewDeserializersManager())       //身份解串器管理器/构造type mspDeserializersManager struct{}
	//创建实例mspSecurityAdvisor
	secAdv := peergossip.NewSecurityAdvisor(mgmt.NewDeserializersManager())

	// callback function for secure dial options for gossip service
    //用于gossip服务secure dial回调
	secureDialOpts := func() []grpc.DialOption {
		var dialOpts []grpc.DialOption
		// set max send/recv msg sizes
		dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize()),
			grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize())))
		// set the keepalive options
		dialOpts = append(dialOpts, comm.ClientKeepaliveOptions()...)

		if comm.TLSEnabled() {
			tlsCert := peerServer.ServerCertificate()
			dialOpts = append(dialOpts, grpc.WithTransportCredentials(comm.GetCASupport().GetPeerCredentials(tlsCert)))
		} else {
			dialOpts = append(dialOpts, grpc.WithInsecure())
		}
		return dialOpts
	}
    //初始化gossip服务
	err = service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(),
		messageCryptoService, secAdv, secureDialOpts, bootstrap...)
	if err != nil {
		return err
	}
	defer service.GetGossipService().Stop()

	//initialize system chaincodes
    //初始化系统链码
	initSysCCs()

	//this brings up all the chains (including testchainid)
    //对peer上的所有链进行初始化并部署
	peer.Initialize(func(cid string) {
		logger.Debugf("Deploying system CC, for chain <%s>", cid)
        //系统链码部署
		scc.DeploySysCCs(cid)
	})

	logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]",
		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)

	// Start the grpc server. Done in a goroutine so we can deploy the
	// genesis block if needed.
	serve := make(chan error)

	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	go func() {
        //接收系统消息
		sig := <-sigs
		logger.Debugf("sig: %s", sig)
		serve <- nil
	}()

	go func() {
		var grpcErr error
        //启动peer服务
		if grpcErr = peerServer.Start(); grpcErr != nil {
			grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
		} else {
			logger.Info("peer server exited")
		}
		serve <- grpcErr
	}()

	if err := writePid(config.GetPath("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil {
		return err
	}

	// Start the event hub server
    //启动事件中心处理服务
	if ehubGrpcServer != nil {
		go ehubGrpcServer.Start()
	}

	// Start profiling http endpoint if enabled
	if viper.GetBool("peer.profile.enabled") {
		go func() {
            //启动Go自带的profiling支持进行调试
			profileListenAddress := viper.GetString("peer.profile.listenAddress")
			logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress)
			if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil {
				logger.Errorf("Error starting profiler: %s", profileErr)
			}
		}()
	}

	logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]",
		peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address)

	// set the logging level for specific modules defined via environment
	// variables or core.yaml
    //按配置文件重新更新模块日志级别
	overrideLogModules := []string{"msp", "gossip", "ledger", "cauthdsl", "policies", "grpc"}
	for _, module := range overrideLogModules {
		err = common.SetLogLevelFromViper(module)
		if err != nil {
			logger.Warningf("Error setting log level for module '%s': %s", module, err.Error())
		}
	}

	flogging.SetPeerStartupModulesMap()

	// Block until grpc server exits
	return <-serve
}

 五、详细说明

  账本初始化

//github.com/hyperledger/fabric/peer/node/start.go
ledgermgmt.Initialize()
//github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledger_mgmt.go
//Initialize方法
//Initialize方法只执行一次
func Initialize() {
	once.Do(func() {
		initialize()
	})
}

func initialize() {
	logger.Info("Initializing ledger mgmt")
	lock.Lock()
	defer lock.Unlock()
	initialized = true
        //用于保存peer上的账本
	openedLedgers = make(map[string]ledger.PeerLedger)
        //provider接收账本数据(账本提供者)
	provider, err := kvledger.NewProvider()
	if err != nil {
		panic(fmt.Errorf("Error in instantiating ledger provider: %s", err))
	}
        //ledgerProvider是全局变量
	ledgerProvider = provider
	logger.Info("ledger mgmt initialized")
}
//kvledger.NewProvider()详情
//github.com/hyperledger/fabric/core/ledger/kvledger/kv_ledger_provider.go
func NewProvider() (ledger.PeerLedgerProvider, error) {

	logger.Info("Initializing ledger provider")

	// Initialize the ID store (inventory of chainIds/ledgerIds)
    //初始化ID store 
	idStore := openIDStore(ledgerconfig.GetLedgerProviderPath())

	// Initialize the block storage
    //初始化块存储,定义块的信息
        attrsToIndex := []blkstorage.IndexableAttr{
	    blkstorage.IndexableAttrBlockHash,
	    blkstorage.IndexableAttrBlockNum,
	    blkstorage.IndexableAttrTxID,
	    blkstorage.IndexableAttrBlockNumTranNum,
	    blkstorage.IndexableAttrBlockTxID,
	    blkstorage.IndexableAttrTxValidationCode,
	}
	indexConfig := &blkstorage.IndexConfig{AttrsToIndex: attrsToIndex}
	blockStoreProvider := fsblkstorage.NewProvider(
		fsblkstorage.NewConf(ledgerconfig.GetBlockStorePath(), ledgerconfig.GetMaxBlockfileSize()),
		indexConfig)

	// Initialize the versioned database (state database)
    //初始化version db
	var vdbProvider statedb.VersionedDBProvider
	if !ledgerconfig.IsCouchDBEnabled() {
		logger.Debug("Constructing leveldb VersionedDBProvider")
		vdbProvider = stateleveldb.NewVersionedDBProvider()
	} else {
		logger.Debug("Constructing CouchDB VersionedDBProvider")
		var err error
		vdbProvider, err = statecouchdb.NewVersionedDBProvider()
		if err != nil {
			return nil, err
		}
	}

	// Initialize the history database (index for history of values by key)
    //初始化history db
	var historydbProvider historydb.HistoryDBProvider
	historydbProvider = historyleveldb.NewHistoryDBProvider()

	logger.Info("ledger provider Initialized")
	provider := &Provider{idStore, blockStoreProvider, vdbProvider, historydbProvider}
	provider.recoverUnderConstructionLedger()
    //返回账本提供者对象
	return provider, nil
}

localAddress和peerEndpoint

if err := peer.CacheConfiguration(); err != nil {
    return err
}
//github.com/hyperledger/fabric/core/peer/config.go
//CacheConfiguration方法具体实现
//最终CacheConfiguration方法设置全局变量configurationCached=true,下次直接读取缓存数据,返回错误信息或nil

func CacheConfiguration() (err error) {
    //getLocalAddress匿名函数获取本地ip地址及端口,如果环境变量peer.addressAutoDetect=true则自动获取。返回一个ipv4地址,地址由GetLocalIP()方法返回(),端口则获取配置文件core.yaml中的peer.address端口(7051),最终返回:192.168.x.x:7051
    //环境变量peer.addressAutoDetect默认等于false,取配置文件care.yaml中的peer.address,最终返回0.0.0.0:7051

	getLocalAddress := func() (peerAddress string, err error) {
		if viper.GetBool("peer.addressAutoDetect") {
			_, port, err := net.SplitHostPort(viper.GetString("peer.address"))
			if err != nil {
				err = fmt.Errorf("Error auto detecting Peer's address: %s", err)
				return "", err
			}
			peerAddress = net.JoinHostPort(GetLocalIP(), port)
			peerLogger.Infof("Auto detected peer address: %s", peerAddress)
		} else {
			peerAddress = viper.GetString("peer.address")
		}
		return
	}

   //getPeerEndpoint匿名函数获取环境变量CORE_PEER_ID及上述getLocalAddress方法返回的本地ipv4地址给PeerEndpoint,PeerEndpoint具体实现在下面。

	getPeerEndpoint := func() (*pb.PeerEndpoint, error) {
		var peerAddress string
		peerAddress, err := getLocalAddress()
		if err != nil {
			return nil, err
		}
		return &pb.PeerEndpoint{Id: &pb.PeerID{Name: viper.GetString("peer.id")}, Address: peerAddress}, nil
	}

	localAddress, localAddressError = getLocalAddress()
	peerEndpoint, _ = getPeerEndpoint()

	configurationCached = true

	if localAddressError != nil {
		return localAddressError
	}
	return
}
//返回本地ip地址
//github.com/hyperledger/fabric/core/peer/peer.go
func GetLocalIP() string {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return ""
	}
	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}
	return ""
}
//github.com/hyperledger/fabric/core/peer/peer.pb.go
//PeerEndpoint定义
type PeerEndpoint struct {
	Id      *PeerID `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
	Address string  `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
}

GetSecureConfig获取安全配置信息

secureConfig, err := peer.GetSecureConfig()
//github.com/hyperledger/fabric/core/peer/config.go
func GetSecureConfig() (comm.SecureServerConfig, error) {
        //获取环境变量CORE_PEER_TLS_ENABLED,是否启用tls安全协议
	secureConfig := comm.SecureServerConfig{
		UseTLS: viper.GetBool("peer.tls.enabled"),
	}
	if secureConfig.UseTLS {
		// get the certs from the file system
                //启用TLS,获取证书文件,文件位于容器"/etc/hyperledger/fabric"目录下
		serverKey, err := ioutil.ReadFile(config.GetPath("peer.tls.key.file"))
		serverCert, err := ioutil.ReadFile(config.GetPath("peer.tls.cert.file"))
		// must have both key and cert file
		if err != nil {
			return secureConfig, fmt.Errorf("Error loading TLS key and/or certificate (%s)", err)
		}
        //将获取的信息存入secureConfig
		secureConfig.ServerCertificate = serverCert
		secureConfig.ServerKey = serverKey
		// check for root cert
		if config.GetPath("peer.tls.rootcert.file") != "" {
			rootCert, err := ioutil.ReadFile(config.GetPath("peer.tls.rootcert.file"))
			if err != nil {
				return secureConfig, fmt.Errorf("Error loading TLS root certificate (%s)", err)
			}
			secureConfig.ServerRootCAs = [][]byte{rootCert}
		}
		return secureConfig, nil
	}
	return secureConfig, nil
}
func GetPath(key string) string {
	p := viper.GetString(key)
	if p == "" {
		return ""
	}
    #viper.ConfigFileUsed()获取文件配置路径,返回/etc/hyperledger/fabric
    #github.com/hyperledger/fabric/peer/main.go中err := common.InitConfig(cmdRoot)实现
	return TranslatePath(filepath.Dir(viper.ConfigFileUsed()), p)
}

func TranslatePath(base, p string) string {
	if filepath.IsAbs(p) {
		return p
	}

	return filepath.Join(base, p)
}
//secureConfig结构定义
//github.com/hyperledger/fabric/core/comm/server.go
type SecureServerConfig struct {
	//PEM-encoded X509 public key to be used by the server for TLS communication
	ServerCertificate []byte
	//PEM-encoded private key to be used by the server for TLS communication
	ServerKey []byte
	//Set of PEM-encoded X509 certificate authorities to optionally send
	//as part of the server handshake
	ServerRootCAs [][]byte
	//Set of PEM-encoded X509 certificate authorities to use when verifying
	//client certificates
	ClientRootCAs [][]byte
	//Whether or not to use TLS for communication
	UseTLS bool
	//Whether or not TLS client must present certificates for authentication
	RequireClientCert bool
}

创建CreatePeerServer

peerServer, err := peer.CreatePeerServer(listenAddr, secureConfig)
//github.com/hyperledger/fabric/core/peer/peer.go
func CreatePeerServer(listenAddress string,secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
	var err error
	peerServer, err = comm.NewGRPCServer(listenAddress, secureConfig)
	if err != nil {
		peerLogger.Errorf("Failed to create peer server (%s)", err)
		return nil, err
	}
	return peerServer, nil
}
//comm.NewGRPCServer创建grpc服务
//github.com/hyperledger/fabric/core/comm/server.go

func NewGRPCServer(address string, secureConfig SecureServerConfig) (GRPCServer, error) {

	if address == "" {
		return nil, errors.New("Missing address parameter")
	}
	//create our listener
	lis, err := net.Listen("tcp", address)

	if err != nil {
		return nil, err
	}

	return NewGRPCServerFromListener(lis, secureConfig)

}
func NewGRPCServerFromListener(listener net.Listener, secureConfig SecureServerConfig) (GRPCServer, error) {
    //将地址,tcp.listen存入grpcServerImpl
	grpcServer := &grpcServerImpl{
		address:  listener.Addr().String(),
		listener: listener,
		lock:     &sync.Mutex{},
	}

	//set up our server options
	var serverOpts []grpc.ServerOption
	//check secureConfig
	if secureConfig.UseTLS {
        //如果安全配置中启用了TLS,获取私钥和证书
		if secureConfig.ServerKey != nil && secureConfig.ServerCertificate != nil {
			//加载私钥和证书,并将数据存入grpcServerImpl
            grpcServer.tlsEnabled = true
			cert, err := tls.X509KeyPair(secureConfig.ServerCertificate, secureConfig.ServerKey)
			if err != nil {
				return nil, err
			}
			grpcServer.serverCertificate = cert

			//更新tls配置
			certificates := []tls.Certificate{grpcServer.serverCertificate}
            //默认启用SessionTickets,可提高服务器性能
			grpcServer.tlsConfig = &tls.Config{
				Certificates:           certificates,
				SessionTicketsDisabled: true,
			}
			grpcServer.tlsConfig.ClientAuth = tls.RequestClientCert
			//判断是否获取到证书
			if secureConfig.RequireClientCert {
				//完成证书验证
				grpcServer.tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
				//如果有多个根证书,则创建根证书库
				if len(secureConfig.ClientRootCAs) > 0 {
					grpcServer.clientRootCAs = make(map[string]*x509.Certificate)
					grpcServer.tlsConfig.ClientCAs = x509.NewCertPool()
					for _, clientRootCA := range secureConfig.ClientRootCAs {
						err = grpcServer.appendClientRootCA(clientRootCA)
						if err != nil {
							return nil, err
						}
					}
				}
			}

			//创建凭证(将信息写入serverConfig)
			creds := NewServerTransportCredentials(grpcServer.tlsConfig)
			serverOpts = append(serverOpts, grpc.Creds(creds))
		} else {
			return nil, errors.New("secureConfig must contain both ServerKey and " +
				"ServerCertificate when UseTLS is true")
		}
	}
    //设置服务发送和接收的最大消息数
	serverOpts = append(serverOpts, grpc.MaxSendMsgSize(MaxSendMsgSize()))
	serverOpts = append(serverOpts, grpc.MaxRecvMsgSize(MaxRecvMsgSize()))
    //设置服务保持时间
	serverOpts = append(serverOpts, ServerKeepaliveOptions()...)
	grpcServer.server = grpc.NewServer(serverOpts...)

	return grpcServer, nil
}
//ClientAuthType定义
type ClientAuthType int{}
const (
        NoClientCert ClientAuthType = iota       #0
        RequestClientCert                        #1
        RequireAnyClientCert                     #2
        VerifyClientCertIfGiven                  #3
        RequireAndVerifyClientCert               #4
)

//grpcServerImpl定义
//github.com/hyperledger/fabric/core/comm/server.go
type grpcServerImpl struct {
	//Listen address for the server specified as hostname:port
	address string
	//Listener for handling network requests
	listener net.Listener
	//GRPC server
	server *grpc.Server
	//Certificate presented by the server for TLS communication
	serverCertificate tls.Certificate
	//Key used by the server for TLS communication
	serverKeyPEM []byte
	//List of certificate authorities to optionally pass to the client during
	//the TLS handshake
	serverRootCAs []tls.Certificate
	//lock to protect concurrent access to append / remove
	lock *sync.Mutex
	//Set of PEM-encoded X509 certificate authorities used to populate
	//the tlsConfig.ClientCAs indexed by subject
	clientRootCAs map[string]*x509.Certificate
	//TLS configuration used by the grpc server
	tlsConfig *tls.Config
	//Is TLS enabled?
	tlsEnabled bool
}

创建事件中心服务createEventHubServer

ehubGrpcServer, err := createEventHubServer(secureConfig)
//github.com/hyperledger/fabric/peer/node/start.go
func createEventHubServer(secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
	var lis net.Listener
	var err error
	lis, err = net.Listen("tcp", viper.GetString("peer.events.address"))
	if err != nil {
		return nil, fmt.Errorf("failed to listen: %v", err)
	}

	grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig)
	if err != nil {
		logger.Errorf("Failed to return new GRPC server: %s", err)
		return nil, err
	}
	ehServer := producer.NewEventsServer(
		uint(viper.GetInt("peer.events.buffersize")),    //最大进行缓冲的消息数
		viper.GetDuration("peer.events.timeout"))        //缓冲已满的情况下,往缓冲中发送消息的超时
    //将事件服务注册到GRPCserver
	pb.RegisterEventsServer(grpcServer.Server(), ehServer)
	return grpcServer, nil
}

//github.com/hyperledger/fabric/events/producer/producer.go
//全局变量globalEventsServer判断是否创建过EventsServer,如果我们想创建多个服务器,需要将events.gEventConsumers包含到EventsServer中

var globalEventsServer *EventsServer
func NewEventsServer(bufferSize uint, timeout time.Duration) *EventsServer {
	if globalEventsServer != nil {
		panic("Cannot create multiple event hub servers")
	}
	globalEventsServer = new(EventsServer)
    //事件服务初始化
	initializeEvents(bufferSize, timeout)
	//initializeCCEventProcessor(bufferSize, timeout)
	return globalEventsServer
}

//初始化事件服务
func initializeEvents(bufferSize uint, tout time.Duration) {
	if gEventProcessor != nil {
		panic("should not be called twice")
	}

	gEventProcessor = &eventProcessor{eventConsumers: make(map[pb.EventType]handlerList), eventChannel: make(chan *pb.Event, bufferSize), timeout: tout}

	addInternalEventTypes()

	//start the event processor
	go gEventProcessor.start()
}

//github.com/hyperledger/fabric/events/producer/register_internal_events.go
func addInternalEventTypes() {
    //添加事件服务所支持的事件类型
	AddEventType(pb.EventType_BLOCK)
	AddEventType(pb.EventType_CHAINCODE)
	AddEventType(pb.EventType_REJECTION)
	AddEventType(pb.EventType_REGISTER)
}

//github.com/hyperledger/fabric/events/producer/events.go
func AddEventType(eventType pb.EventType) error {
	gEventProcessor.Lock()
	logger.Debugf("Registering %s", pb.EventType_name[int32(eventType)])
	if _, ok := gEventProcessor.eventConsumers[eventType]; ok {
		gEventProcessor.Unlock()
		return fmt.Errorf("event type exists %s", pb.EventType_name[int32(eventType)])
	}

	switch eventType {
	case pb.EventType_BLOCK:
		gEventProcessor.eventConsumers[eventType] = &genericHandlerList{handlers: make(map[*handler]bool)}
	case pb.EventType_CHAINCODE:
		gEventProcessor.eventConsumers[eventType] = &chaincodeHandlerList{handlers: make(map[string]map[string]map[*handler]bool)}
	case pb.EventType_REJECTION:
		gEventProcessor.eventConsumers[eventType] = &genericHandlerList{handlers: make(map[*handler]bool)}
	}
	gEventProcessor.Unlock()

	return nil
}

//github.com/hyperledger/fabric/protos/peer/events.pb.go
type EventType int32

const (
	EventType_REGISTER  EventType = 0
	EventType_BLOCK     EventType = 1
	EventType_CHAINCODE EventType = 2
	EventType_REJECTION EventType = 3
)

创建并启动链码服务ChaincodeServer

ccSrv, ccEpFunc := createChaincodeServer(peerServer, listenAddr)
registerChaincodeSupport(ccSrv.Server(), ccEpFunc)
go ccSrv.Start()
//createChaincodeServer判断peer.chaincodeListenAddress是否设置
//如果未设置则直接返回之前的peerServer和pb.PeerEndpoint对象,如果设置并且等于配置中的peer.address则返回相同的内容,否则根据配置的peer.chaincodeListenAddress重新创建GRPCserver和pb.PeerEndpoint

func createChaincodeServer(peerServer comm.GRPCServer, peerListenAddress string) (comm.GRPCServer, ccEndpointFunc) {
    //默认没有定义peer.chaincodeListenAddress,所以cclistenAddress是空
	cclistenAddress := viper.GetString("peer.chaincodeListenAddress")

	var srv comm.GRPCServer
	var ccEpFunc ccEndpointFunc

	//use the chaincode address endpoint function..
	//three cases
	// -  peer.chaincodeListenAddress not specied (use peer's server)
	// -  peer.chaincodeListenAddress identical to peer.listenAddress (use peer's server)
	// -  peer.chaincodeListenAddress different and specified (create chaincode server)
	if cclistenAddress == "" {
		//...but log a warning
		logger.Warningf("peer.chaincodeListenAddress is not set, use peer.listenAddress %s", peerListenAddress)

		//we are using peer address, use peer endpoint
		ccEpFunc = peer.GetPeerEndpoint
		srv = peerServer
	} else if cclistenAddress == peerListenAddress {
		//using peer's endpoint...log a  warning
		logger.Warningf("peer.chaincodeListenAddress is identical to peer.listenAddress %s", cclistenAddress)

		//we are using peer address, use peer endpoint
		ccEpFunc = peer.GetPeerEndpoint
		srv = peerServer
	} else {
		config, err := peer.GetSecureConfig()
		if err != nil {
			panic(err)
		}

		srv, err = comm.NewGRPCServer(cclistenAddress, config)
		if err != nil {
			panic(err)
		}
		ccEpFunc = getChaincodeAddressEndpoint
	}

	return srv, ccEpFunc
}
//将链码服务注册到grpcserver,同时注册系统链码
func registerChaincodeSupport(grpcServer *grpc.Server, ccEpFunc ccEndpointFunc) {
	//get user mode
    //判断是否开发模式
	userRunsCC := chaincode.IsDevMode()

	//get chaincode startup timeout
    //core.yaml中默认值为300s
	ccStartupTimeout := viper.GetDuration("chaincode.startuptimeout")
    //如果定义值小于5s,则设置为5s
	if ccStartupTimeout < time.Duration(5)*time.Second {
		logger.Warningf("Invalid chaincode startup timeout value %s (should be at least 5s); defaulting to 5s", ccStartupTimeout)
		ccStartupTimeout = time.Duration(5) * time.Second
	} else {
		logger.Debugf("Chaincode startup timeout value set to %s", ccStartupTimeout)
	}
    //构造ChaincodeSupport
	ccSrv := chaincode.NewChaincodeSupport(ccEpFunc, userRunsCC, ccStartupTimeout)

	//Now that chaincode is initialized, register all system chaincodes.
	scc.RegisterSysCCs()

	pb.RegisterChaincodeSupportServer(grpcServer, ccSrv)
}

//获取配置文件core.yaml中chaincode.mode的值为net(dev/net)
func IsDevMode() bool {
	mode := viper.GetString("chaincode.mode")

	return mode == DevModeUserRunsChaincode
}

注册系统链码 

//循环遍历系统链码systemChaincodes
func RegisterSysCCs() {
	for _, sysCC := range systemChaincodes {
		RegisterSysCC(sysCC)
	}
}
//系统链码定义
var systemChaincodes = []*SystemChaincode{
	{
		Enabled:           true,
		Name:              "cscc",
		Path:              "github.com/hyperledger/fabric/core/scc/cscc",
		InitArgs:          [][]byte{[]byte("")},
		Chaincode:         &cscc.PeerConfiger{},
		InvokableExternal: true, // cscc is invoked to join a channel
	},
	{
		Enabled:           true,
		Name:              "lscc",
		Path:              "github.com/hyperledger/fabric/core/scc/lscc",
		InitArgs:          [][]byte{[]byte("")},
		Chaincode:         &lscc.LifeCycleSysCC{},
		InvokableExternal: true, // lscc is invoked to deploy new chaincodes
		InvokableCC2CC:    true, // lscc can be invoked by other chaincodes
	},
	{
		Enabled:   true,
		Name:      "escc",
		Path:      "github.com/hyperledger/fabric/core/scc/escc",
		InitArgs:  [][]byte{[]byte("")},
		Chaincode: &escc.EndorserOneValidSignature{},
	},
	{
		Enabled:   true,
		Name:      "vscc",
		Path:      "github.com/hyperledger/fabric/core/scc/vscc",
		InitArgs:  [][]byte{[]byte("")},
		Chaincode: &vscc.ValidatorOneValidSignature{},
	},
	{
		Enabled:           true,
		Name:              "qscc",
		Path:              "github.com/hyperledger/fabric/core/chaincode/qscc",
		InitArgs:          [][]byte{[]byte("")},
		Chaincode:         &qscc.LedgerQuerier{},
		InvokableExternal: true, // qscc can be invoked to retrieve blocks
		InvokableCC2CC:    true, // qscc can be invoked to retrieve blocks also by a cc
	},
}

//RegisterSysCC逐个注册
func RegisterSysCC(syscc *SystemChaincode) error {
    //判断是否启用
	if !syscc.Enabled || !isWhitelisted(syscc) {
		sysccLogger.Info(fmt.Sprintf("system chaincode (%s,%s,%t) disabled", syscc.Name, syscc.Path, syscc.Enabled))
		return nil
	}
	//Register将链码存到数据结构inprocContainer,并赋与typeRegistry map对象
	err := inproccontroller.Register(syscc.Path, syscc.Chaincode)
	if err != nil {
		//if the type is registered, the instance may not be... keep going
		if _, ok := err.(inproccontroller.SysCCRegisteredErr); !ok {
			errStr := fmt.Sprintf("could not register (%s,%v): %s", syscc.Path, syscc, err)
			sysccLogger.Error(errStr)
			return fmt.Errorf(errStr)
		}
	}

	sysccLogger.Infof("system chaincode %s(%s) registered", syscc.Name, syscc.Path)
	return err
}

//根据路径进行注册
func Register(path string, cc shim.Chaincode) error {
	tmp := typeRegistry[path]
	if tmp != nil {
		return SysCCRegisteredErr(path)
	}

	typeRegistry[path] = &inprocContainer{chaincode: cc}
	return nil
}

//typeRegistry定义
typeRegistry = make(map[string]*inprocContainer)

//inprocContainer定义
type inprocContainer struct {
	chaincode shim.Chaincode
	running   bool
	args      []string
	env       []string
	stopChan  chan struct{}
}
//github.com/hyperledger/fabric/core/chaincode/chaincode_support.go
func NewChaincodeSupport(getCCEndpoint func() (*pb.PeerEndpoint, error), userrunsCC bool, ccstartuptimeout time.Duration) *ChaincodeSupport {
    //获取环境变量和配置参数    
    //SetChaincodesPath=/var/hyperledger/production/chaincodes
	ccprovider.SetChaincodesPath(config.GetPath("peer.fileSystemPath") + string(filepath.Separator) + "chaincodes")
	pnid := viper.GetString("peer.networkId")
	pid := viper.GetString("peer.id")
    
	theChaincodeSupport = &ChaincodeSupport{runningChaincodes: &runningChaincodes{chaincodeMap: make(map[string]*chaincodeRTEnv)}, peerNetworkID: pnid, peerID: pid}

	//initialize global chain
    //获取pb.PeerEndpoint对象,如果获取失败则使用配置文件中的chaincode.peerAddress(默认设置为空)
    //否则为之前设置的peer.address值0.0.0.0:7051
    //如果未成功获取到则默认设置为0.0.0.0:7051
	ccEndpoint, err := getCCEndpoint()
	if err != nil {
		chaincodeLogger.Errorf("Error getting chaincode endpoint, using chaincode.peerAddress: %s", err)
		theChaincodeSupport.peerAddress = viper.GetString("chaincode.peerAddress")
	} else {
		theChaincodeSupport.peerAddress = ccEndpoint.Address
	}
	chaincodeLogger.Infof("Chaincode support using peerAddress: %s\n", theChaincodeSupport.peerAddress)
	//peerAddress = viper.GetString("peer.address")
	if theChaincodeSupport.peerAddress == "" {
		theChaincodeSupport.peerAddress = peerAddressDefault
	}

	theChaincodeSupport.userRunsCC = userrunsCC

	theChaincodeSupport.ccStartupTimeout = ccstartuptimeout

	theChaincodeSupport.peerTLS = viper.GetBool("peer.tls.enabled")
	if theChaincodeSupport.peerTLS {
		theChaincodeSupport.peerTLSCertFile = config.GetPath("peer.tls.cert.file")
		theChaincodeSupport.peerTLSKeyFile = config.GetPath("peer.tls.key.file")
		theChaincodeSupport.peerTLSSvrHostOrd = viper.GetString("peer.tls.serverhostoverride")
	}
    //默认不开启tcp keepalive
    //Peer和链码之间的心跳超时,小于或等于0意味着关闭
	kadef := 0
	if ka := viper.GetString("chaincode.keepalive"); ka == "" {
		theChaincodeSupport.keepalive = time.Duration(kadef) * time.Second
	} else {
		t, terr := strconv.Atoi(ka)
		if terr != nil {
			chaincodeLogger.Errorf("Invalid keepalive value %s (%s) defaulting to %d", ka, terr, kadef)
			t = kadef
		} else if t <= 0 {
			chaincodeLogger.Debugf("Turn off keepalive(value %s)", ka)
			t = kadef
		}
		theChaincodeSupport.keepalive = time.Duration(t) * time.Second
	}

	//default chaincode execute timeout is 30 secs
    //默认链码运行超时时间为30s(invoke和initialize命令)
	execto := time.Duration(30) * time.Second
	if eto := viper.GetDuration("chaincode.executetimeout"); eto <= time.Duration(1)*time.Second {
		chaincodeLogger.Errorf("Invalid execute timeout value %s (should be at least 1s); defaulting to %s", eto, execto)
	} else {
		chaincodeLogger.Debugf("Setting execute timeout value to %s", eto)
		execto = eto
	}

	theChaincodeSupport.executetimeout = execto

	viper.SetEnvPrefix("CORE")
	viper.AutomaticEnv()
	replacer := strings.NewReplacer(".", "_")
	viper.SetEnvKeyReplacer(replacer)

	theChaincodeSupport.chaincodeLogLevel = getLogLevelFromViper("level")
	theChaincodeSupport.shimLogLevel = getLogLevelFromViper("shim")
	theChaincodeSupport.logFormat = viper.GetString("chaincode.logging.format")

	return theChaincodeSupport
}

//ChaincodeSupport负责提供与Peer的链代码的接口。
type ChaincodeSupport struct {
	runningChaincodes *runningChaincodes
	peerAddress       string
	ccStartupTimeout  time.Duration
	peerNetworkID     string
	peerID            string
	peerTLSCertFile   string
	peerTLSKeyFile    string
	peerTLSSvrHostOrd string
	keepalive         time.Duration
	chaincodeLogLevel string
	shimLogLevel      string
	logFormat         string
	executetimeout    time.Duration
	userRunsCC        bool
	peerTLS           bool
}

注册Admin server

Admin server接口如下:

扫描二维码关注公众号,回复: 3155523 查看本文章

 1、GetStatus():获取peer服务的状态,即执行peer node status命令

 2、StartServer()

 3、GetModuleLogLevel()

 4、SetModuleLogLevel()

 5、RevertLogLevels()

pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer())
func RegisterAdminServer(s *grpc.Server, srv AdminServer) {
	s.RegisterService(&_Admin_serviceDesc, srv)
}
var _Admin_serviceDesc = grpc.ServiceDesc{
	ServiceName: "protos.Admin",
	HandlerType: (*AdminServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "GetStatus",
			Handler:    _Admin_GetStatus_Handler,
		},
		{
			MethodName: "StartServer",
			Handler:    _Admin_StartServer_Handler,
		},
		{
			MethodName: "GetModuleLogLevel",
			Handler:    _Admin_GetModuleLogLevel_Handler,
		},
		{
			MethodName: "SetModuleLogLevel",
			Handler:    _Admin_SetModuleLogLevel_Handler,
		},
		{
			MethodName: "RevertLogLevels",
			Handler:    _Admin_RevertLogLevels_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "peer/admin.proto",
}

注册Endorser server

serverEndorser := endorser.NewEndorserServer()
pb.RegisterEndorserServer(peerServer.Server(), serverEndorser)
func NewEndorserServer() pb.EndorserServer {
	e := new(Endorser)
	e.policyChecker = policy.NewPolicyChecker(
		peer.NewChannelPolicyManagerGetter(),
		mgmt.GetLocalMSP(),
		mgmt.NewLocalMSPPrincipalGetter(),
	)

	return e
}
func RegisterEndorserServer(s *grpc.Server, srv EndorserServer) {
	s.RegisterService(&_Endorser_serviceDesc, srv)
}
var _Endorser_serviceDesc = grpc.ServiceDesc{
	ServiceName: "protos.Endorser",
	HandlerType: (*EndorserServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "ProcessProposal",
			Handler:    _Endorser_ProcessProposal_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "peer/peer.proto",
}

初始化gossip

//bootstrap = 127.0.0.1:7051
bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")

//获取签名身份/得到字节数组
serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize()
//GetLocalSigningIdentityOrPanic
//github.com/hyperledger/fabric/msp/mgmt/mgmt.go
func GetLocalSigningIdentityOrPanic() msp.SigningIdentity {
	id, err := GetLocalMSP().GetDefaultSigningIdentity()
	if err != nil {
		mspLogger.Panicf("Failed getting local signing identity [%s]", err)
	}
	return id
}

//GetLocalMSP 返回localMSP,否则执行msp.NewBccspMsp()返回localMSP
//localMSP 是实现的最小成员资格服务提供程序接口
func GetLocalMSP() msp.MSP {
	var lclMsp msp.MSP
	var created bool = false
	{
		m.Lock()
		defer m.Unlock()

		lclMsp = localMsp
		if lclMsp == nil {
			var err error
			created = true
			lclMsp, err = msp.NewBccspMsp()
			if err != nil {
				mspLogger.Fatalf("Failed to initialize local MSP, received err %s", err)
			}
			localMsp = lclMsp
		}
	}

	if created {
		mspLogger.Debugf("Created new local MSP")
	} else {
		mspLogger.Debugf("Returning existing local MSP")
	}

	return lclMsp
}

//GetDefaultSigningIdentity返回该localMSP默认签名身份
//github.com/hyperledger/fabric/msp/mspimpl.go
func (msp *bccspmsp) GetDefaultSigningIdentity() (SigningIdentity, error) {
	mspLogger.Debugf("Obtaining default signing identity")

	if msp.signer == nil {
		return nil, fmt.Errorf("This MSP does not possess a valid default signing identity")
	}

	return msp.signer, nil
}
//Serialize返回此标识的字节数组表示形式
func (id *identity) Serialize() ([]byte, error) {
	// mspIdentityLogger.Infof("Serializing identity %s", id.id)

	pb := &pem.Block{Bytes: id.cert.Raw}
	pemBytes := pem.EncodeToMemory(pb)
	if pemBytes == nil {
		return nil, fmt.Errorf("Encoding of identitiy failed")
	}

	// We serialize identities by prepending the MSPID and appending the ASN.1 DER content of the cert
	sId := &msp.SerializedIdentity{Mspid: id.id.Mspid, IdBytes: pemBytes}
	idBytes, err := proto.Marshal(sId)
	if err != nil {
		return nil, fmt.Errorf("Could not marshal a SerializedIdentity structure for identity %s, err %s", id.id, err)
	}

	return idBytes, nil
}

消息加密服务

messageCryptoService := peergossip.NewMCS(
    //它通过Manager方法提供对给定通道的策略管理器的访问/type channelPolicyManagerGetter struct{}
    peer.NewChannelPolicyManagerGetter(),
    //一个加密实例/type mspSigner struct {}
    localmsp.NewSigner(), 
   //身份解串器管理器/构造type mspDeserializersManager struct{}
    mgmt.NewDeserializersManager()
)
//为gossip服务创建一个安全会话回调函数
secureDialOpts := func() []grpc.DialOption {
		var dialOpts []grpc.DialOption
		// set max send/recv msg sizes
		dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize()),
			grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize())))
		// set the keepalive options
		dialOpts = append(dialOpts, comm.ClientKeepaliveOptions()...)

		if comm.TLSEnabled() {
			tlsCert := peerServer.ServerCertificate()
			dialOpts = append(dialOpts, grpc.WithTransportCredentials(comm.GetCASupport().GetPeerCredentials(tlsCert)))
		} else {
			dialOpts = append(dialOpts, grpc.WithInsecure())
		}
		return dialOpts
	}

初始化GOSSIP

//初始化GOSSIP服务
err = service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(),
messageCryptoService, secAdv, secureDialOpts, bootstrap...)

初始化系统链码

initSysCCs()
//在peer中初始化所有链,部署所有链码
peer.Initialize(func(cid string) {
    scc.DeploySysCCs(cid) //按chain id部署并运行系统链码
})
func initSysCCs() {
	//deploy system chaincodes
	scc.DeploySysCCs("")
	logger.Infof("Deployed system chaincodess")
}

//部署系统链码
//systemChaincodes是链码对象集合
func DeploySysCCs(chainID string) {
	for _, sysCC := range systemChaincodes {
		deploySysCC(chainID, sysCC)
	}
}

//peer.Initialize设置peer有关的任何链。 当帐本和gossip准备好时,在启动时调用此函数
func Initialize(init func(string)) {
	chainInitializer = init

	var cb *common.Block
	var ledger ledger.PeerLedger
	ledgermgmt.Initialize()
	ledgerIds, err := ledgermgmt.GetLedgerIDs()
	if err != nil {
		panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err))
	}
	for _, cid := range ledgerIds {
		peerLogger.Infof("Loading chain %s", cid)
		if ledger, err = ledgermgmt.OpenLedger(cid); err != nil {
			peerLogger.Warningf("Failed to load ledger %s(%s)", cid, err)
			peerLogger.Debugf("Error while loading ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
			continue
		}
		if cb, err = getCurrConfigBlockFromLedger(ledger); err != nil {
			peerLogger.Warningf("Failed to find config block on ledger %s(%s)", cid, err)
			peerLogger.Debugf("Error while looking for config block on ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
			continue
		}
		//如果获取到一个有效的配置块和有效的账本创建一个链
		if err = createChain(cid, ledger, cb); err != nil {
			peerLogger.Warningf("Failed to load chain %s(%s)", cid, err)
			peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err)
			continue
		}

		InitChain(cid)
	}
}

 

猜你喜欢

转载自blog.csdn.net/cs380637384/article/details/81666480