github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/node/start.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package node
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"io"
    13  	"io/ioutil"
    14  	"net"
    15  	"net/http"
    16  	"os"
    17  	"os/signal"
    18  	"path/filepath"
    19  	"sync"
    20  	"syscall"
    21  	"time"
    22  
    23  	docker "github.com/fsouza/go-dockerclient"
    24  	"github.com/golang/protobuf/proto"
    25  	"github.com/hechain20/hechain/bccsp/factory"
    26  	"github.com/hechain20/hechain/common/cauthdsl"
    27  	ccdef "github.com/hechain20/hechain/common/chaincode"
    28  	"github.com/hechain20/hechain/common/crypto"
    29  	"github.com/hechain20/hechain/common/crypto/tlsgen"
    30  	"github.com/hechain20/hechain/common/deliver"
    31  	"github.com/hechain20/hechain/common/fabhttp"
    32  	"github.com/hechain20/hechain/common/flogging"
    33  	floggingmetrics "github.com/hechain20/hechain/common/flogging/metrics"
    34  	"github.com/hechain20/hechain/common/grpclogging"
    35  	"github.com/hechain20/hechain/common/grpcmetrics"
    36  	"github.com/hechain20/hechain/common/metadata"
    37  	"github.com/hechain20/hechain/common/metrics"
    38  	"github.com/hechain20/hechain/common/policies"
    39  	"github.com/hechain20/hechain/common/policydsl"
    40  	"github.com/hechain20/hechain/core/aclmgmt"
    41  	"github.com/hechain20/hechain/core/cclifecycle"
    42  	"github.com/hechain20/hechain/core/chaincode"
    43  	"github.com/hechain20/hechain/core/chaincode/accesscontrol"
    44  	"github.com/hechain20/hechain/core/chaincode/extcc"
    45  	"github.com/hechain20/hechain/core/chaincode/lifecycle"
    46  	"github.com/hechain20/hechain/core/chaincode/persistence"
    47  	"github.com/hechain20/hechain/core/chaincode/platforms"
    48  	"github.com/hechain20/hechain/core/committer/txvalidator/plugin"
    49  	"github.com/hechain20/hechain/core/common/ccprovider"
    50  	"github.com/hechain20/hechain/core/common/privdata"
    51  	coreconfig "github.com/hechain20/hechain/core/config"
    52  	"github.com/hechain20/hechain/core/container"
    53  	"github.com/hechain20/hechain/core/container/dockercontroller"
    54  	"github.com/hechain20/hechain/core/container/externalbuilder"
    55  	"github.com/hechain20/hechain/core/deliverservice"
    56  	"github.com/hechain20/hechain/core/dispatcher"
    57  	"github.com/hechain20/hechain/core/endorser"
    58  	authHandler "github.com/hechain20/hechain/core/handlers/auth"
    59  	endorsement2 "github.com/hechain20/hechain/core/handlers/endorsement/api"
    60  	endorsement3 "github.com/hechain20/hechain/core/handlers/endorsement/api/identities"
    61  	"github.com/hechain20/hechain/core/handlers/library"
    62  	validation "github.com/hechain20/hechain/core/handlers/validation/api"
    63  	"github.com/hechain20/hechain/core/ledger"
    64  	"github.com/hechain20/hechain/core/ledger/cceventmgmt"
    65  	"github.com/hechain20/hechain/core/ledger/kvledger"
    66  	"github.com/hechain20/hechain/core/ledger/ledgermgmt"
    67  	"github.com/hechain20/hechain/core/ledger/snapshotgrpc"
    68  	"github.com/hechain20/hechain/core/operations"
    69  	"github.com/hechain20/hechain/core/peer"
    70  	"github.com/hechain20/hechain/core/policy"
    71  	"github.com/hechain20/hechain/core/scc"
    72  	"github.com/hechain20/hechain/core/scc/cscc"
    73  	"github.com/hechain20/hechain/core/scc/lscc"
    74  	"github.com/hechain20/hechain/core/scc/qscc"
    75  	"github.com/hechain20/hechain/core/transientstore"
    76  	"github.com/hechain20/hechain/discovery"
    77  	"github.com/hechain20/hechain/discovery/endorsement"
    78  	discsupport "github.com/hechain20/hechain/discovery/support"
    79  	discacl "github.com/hechain20/hechain/discovery/support/acl"
    80  	ccsupport "github.com/hechain20/hechain/discovery/support/chaincode"
    81  	"github.com/hechain20/hechain/discovery/support/config"
    82  	"github.com/hechain20/hechain/discovery/support/gossip"
    83  	gossipcommon "github.com/hechain20/hechain/gossip/common"
    84  	gossipgossip "github.com/hechain20/hechain/gossip/gossip"
    85  	gossipmetrics "github.com/hechain20/hechain/gossip/metrics"
    86  	gossipprivdata "github.com/hechain20/hechain/gossip/privdata"
    87  	gossipservice "github.com/hechain20/hechain/gossip/service"
    88  	peergossip "github.com/hechain20/hechain/internal/peer/gossip"
    89  	"github.com/hechain20/hechain/internal/peer/version"
    90  	"github.com/hechain20/hechain/internal/pkg/comm"
    91  	"github.com/hechain20/hechain/internal/pkg/gateway"
    92  	"github.com/hechain20/hechain/msp"
    93  	"github.com/hechain20/hechain/msp/mgmt"
    94  	"github.com/hechain20/hechain/protoutil"
    95  	cb "github.com/hyperledger/fabric-protos-go/common"
    96  	discprotos "github.com/hyperledger/fabric-protos-go/discovery"
    97  	gatewayprotos "github.com/hyperledger/fabric-protos-go/gateway"
    98  	pb "github.com/hyperledger/fabric-protos-go/peer"
    99  	"github.com/pkg/errors"
   100  	"github.com/spf13/cobra"
   101  	"github.com/spf13/viper"
   102  	"google.golang.org/grpc"
   103  )
   104  
   105  const (
   106  	chaincodeListenAddrKey = "peer.chaincodeListenAddress"
   107  	defaultChaincodePort   = 7052
   108  )
   109  
   110  var chaincodeDevMode bool
   111  
   112  func startCmd() *cobra.Command {
   113  	// Set the flags on the node start command.
   114  	flags := nodeStartCmd.Flags()
   115  	flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, "start peer in chaincode development mode")
   116  	return nodeStartCmd
   117  }
   118  
   119  var nodeStartCmd = &cobra.Command{
   120  	Use:   "start",
   121  	Short: "Starts the node.",
   122  	Long:  `Starts a node that interacts with the network.`,
   123  	RunE: func(cmd *cobra.Command, args []string) error {
   124  		if len(args) != 0 {
   125  			return fmt.Errorf("trailing args detected")
   126  		}
   127  		// Parsing of the command line is done so silence cmd usage
   128  		cmd.SilenceUsage = true
   129  		return serve(args)
   130  	},
   131  }
   132  
   133  // externalVMAdapter adapts coerces the result of Build to the
   134  // container.Interface type expected by the VM interface.
   135  type externalVMAdapter struct {
   136  	detector *externalbuilder.Detector
   137  }
   138  
   139  func (e externalVMAdapter) Build(
   140  	ccid string,
   141  	mdBytes []byte,
   142  	codePackage io.Reader,
   143  ) (container.Instance, error) {
   144  	i, err := e.detector.Build(ccid, mdBytes, codePackage)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	// ensure <nil> is returned instead of (*externalbuilder.Instance)(nil)
   150  	if i == nil {
   151  		return nil, nil
   152  	}
   153  	return i, err
   154  }
   155  
   156  type disabledDockerBuilder struct{}
   157  
   158  func (disabledDockerBuilder) Build(string, *persistence.ChaincodePackageMetadata, io.Reader) (container.Instance, error) {
   159  	return nil, errors.New("docker build is disabled")
   160  }
   161  
   162  type endorserChannelAdapter struct {
   163  	peer *peer.Peer
   164  }
   165  
   166  func (e endorserChannelAdapter) Channel(channelID string) *endorser.Channel {
   167  	if peerChannel := e.peer.Channel(channelID); peerChannel != nil {
   168  		return &endorser.Channel{
   169  			IdentityDeserializer: peerChannel.MSPManager(),
   170  		}
   171  	}
   172  
   173  	return nil
   174  }
   175  
   176  type custodianLauncherAdapter struct {
   177  	launcher      chaincode.Launcher
   178  	streamHandler extcc.StreamHandler
   179  }
   180  
   181  func (c custodianLauncherAdapter) Launch(ccid string) error {
   182  	return c.launcher.Launch(ccid, c.streamHandler)
   183  }
   184  
   185  func (c custodianLauncherAdapter) Stop(ccid string) error {
   186  	return c.launcher.Stop(ccid)
   187  }
   188  
   189  func serve(args []string) error {
   190  	// currently the peer only works with the standard MSP
   191  	// because in certain scenarios the MSP has to make sure
   192  	// that from a single credential you only have a single 'identity'.
   193  	// Idemix does not support this *YET* but it can be easily
   194  	// fixed to support it. For now, we just make sure that
   195  	// the peer only comes up with the standard MSP
   196  	mspType := mgmt.GetLocalMSP(factory.GetDefault()).GetType()
   197  	if mspType != msp.FABRIC {
   198  		panic("Unsupported msp type " + msp.ProviderTypeToString(mspType))
   199  	}
   200  
   201  	// Trace RPCs with the golang.org/x/net/trace package. This was moved out of
   202  	// the deliver service connection factory as it has process wide implications
   203  	// and was racy with respect to initialization of gRPC clients and servers.
   204  	grpc.EnableTracing = true
   205  
   206  	logger.Infof("Starting %s", version.GetInfo())
   207  
   208  	// obtain coreConfiguration
   209  	coreConfig, err := peer.GlobalConfig()
   210  	if err != nil {
   211  		return err
   212  	}
   213  
   214  	platformRegistry := platforms.NewRegistry(platforms.SupportedPlatforms...)
   215  
   216  	opsSystem := newOperationsSystem(coreConfig)
   217  	err = opsSystem.Start()
   218  	if err != nil {
   219  		return errors.WithMessage(err, "failed to initialize operations subsystem")
   220  	}
   221  	defer opsSystem.Stop()
   222  
   223  	metricsProvider := opsSystem.Provider
   224  	logObserver := floggingmetrics.NewObserver(metricsProvider)
   225  	flogging.SetObserver(logObserver)
   226  
   227  	chaincodeInstallPath := filepath.Join(coreconfig.GetPath("peer.fileSystemPath"), "lifecycle", "chaincodes")
   228  	ccStore := persistence.NewStore(chaincodeInstallPath)
   229  	ccPackageParser := &persistence.ChaincodePackageParser{
   230  		MetadataProvider: ccprovider.PersistenceAdapter(ccprovider.MetadataAsTarEntries),
   231  	}
   232  
   233  	peerHost, _, err := net.SplitHostPort(coreConfig.PeerAddress)
   234  	if err != nil {
   235  		return fmt.Errorf("peer address is not in the format of host:port: %v", err)
   236  	}
   237  
   238  	listenAddr := coreConfig.ListenAddress
   239  	serverConfig, err := peer.GetServerConfig()
   240  	if err != nil {
   241  		logger.Fatalf("Error loading secure config for peer (%s)", err)
   242  	}
   243  
   244  	serverConfig.Logger = flogging.MustGetLogger("core.comm").With("server", "PeerServer")
   245  	serverConfig.ServerStatsHandler = comm.NewServerStatsHandler(metricsProvider)
   246  	serverConfig.UnaryInterceptors = append(
   247  		serverConfig.UnaryInterceptors,
   248  		grpcmetrics.UnaryServerInterceptor(grpcmetrics.NewUnaryMetrics(metricsProvider)),
   249  		grpclogging.UnaryServerInterceptor(flogging.MustGetLogger("comm.grpc.server").Zap()),
   250  	)
   251  	serverConfig.StreamInterceptors = append(
   252  		serverConfig.StreamInterceptors,
   253  		grpcmetrics.StreamServerInterceptor(grpcmetrics.NewStreamMetrics(metricsProvider)),
   254  		grpclogging.StreamServerInterceptor(flogging.MustGetLogger("comm.grpc.server").Zap()),
   255  	)
   256  
   257  	semaphores := initGrpcSemaphores(coreConfig)
   258  	if len(semaphores) != 0 {
   259  		serverConfig.UnaryInterceptors = append(serverConfig.UnaryInterceptors, unaryGrpcLimiter(semaphores))
   260  		serverConfig.StreamInterceptors = append(serverConfig.StreamInterceptors, streamGrpcLimiter(semaphores))
   261  	}
   262  
   263  	cs := comm.NewCredentialSupport()
   264  	if serverConfig.SecOpts.UseTLS {
   265  		logger.Info("Starting peer with TLS enabled")
   266  		cs = comm.NewCredentialSupport(serverConfig.SecOpts.ServerRootCAs...)
   267  
   268  		// set the cert to use if client auth is requested by remote endpoints
   269  		clientCert, err := peer.GetClientCertificate()
   270  		if err != nil {
   271  			logger.Fatalf("Failed to set TLS client certificate (%s)", err)
   272  		}
   273  		cs.SetClientCertificate(clientCert)
   274  	}
   275  
   276  	transientStoreProvider, err := transientstore.NewStoreProvider(
   277  		filepath.Join(coreconfig.GetPath("peer.fileSystemPath"), "transientstore"),
   278  	)
   279  	if err != nil {
   280  		return errors.WithMessage(err, "failed to open transient store")
   281  	}
   282  
   283  	deliverServiceConfig := deliverservice.GlobalConfig()
   284  
   285  	peerInstance := &peer.Peer{
   286  		ServerConfig:             serverConfig,
   287  		CredentialSupport:        cs,
   288  		StoreProvider:            transientStoreProvider,
   289  		CryptoProvider:           factory.GetDefault(),
   290  		OrdererEndpointOverrides: deliverServiceConfig.OrdererEndpointOverrides,
   291  	}
   292  
   293  	identityDeserializerFactory := func(channelName string) msp.IdentityDeserializer {
   294  		if channel := peerInstance.Channel(channelName); channel != nil {
   295  			return channel.MSPManager()
   296  		}
   297  		return nil
   298  	}
   299  
   300  	mspID := coreConfig.LocalMSPID
   301  	localMSP := mgmt.GetLocalMSP(factory.GetDefault())
   302  
   303  	signingIdentity, err := localMSP.GetDefaultSigningIdentity()
   304  	if err != nil {
   305  		logger.Panicf("Could not get the default signing identity from the local MSP: [%+v]", err)
   306  	}
   307  	signingIdentityBytes, err := signingIdentity.Serialize()
   308  	if err != nil {
   309  		logger.Panicf("Failed to serialize the signing identity: %v", err)
   310  	}
   311  
   312  	membershipInfoProvider := privdata.NewMembershipInfoProvider(
   313  		mspID,
   314  		createSelfSignedData(signingIdentity),
   315  		identityDeserializerFactory,
   316  	)
   317  
   318  	expirationLogger := flogging.MustGetLogger("certmonitor")
   319  	crypto.TrackExpiration(
   320  		serverConfig.SecOpts.UseTLS,
   321  		serverConfig.SecOpts.Certificate,
   322  		cs.GetClientCertificate().Certificate,
   323  		signingIdentityBytes,
   324  		expirationLogger.Infof,
   325  		expirationLogger.Warnf, // This can be used to piggyback a metric event in the future
   326  		time.Now(),
   327  		time.AfterFunc,
   328  	)
   329  
   330  	policyMgr := policies.PolicyManagerGetterFunc(peerInstance.GetPolicyManager)
   331  
   332  	policyChecker := policy.NewPolicyChecker(
   333  		policies.PolicyManagerGetterFunc(peerInstance.GetPolicyManager),
   334  		mgmt.GetLocalMSP(factory.GetDefault()),
   335  	)
   336  
   337  	// startup aclmgmt with default ACL providers (resource based and default 1.0 policies based).
   338  	// Users can pass in their own ACLProvider to RegisterACLProvider (currently unit tests do this)
   339  	aclProvider := aclmgmt.NewACLProvider(
   340  		aclmgmt.ResourceGetter(peerInstance.GetStableChannelConfig),
   341  		policyChecker,
   342  	)
   343  
   344  	// TODO, unfortunately, the lifecycle initialization is very unclean at the
   345  	// moment. This is because ccprovider.SetChaincodePath only works after
   346  	// ledgermgmt.Initialize, but ledgermgmt.Initialize requires a reference to
   347  	// lifecycle.  Finally, lscc requires a reference to the system chaincode
   348  	// provider in order to be created, which requires chaincode support to be
   349  	// up, which also requires, you guessed it, lifecycle. Once we remove the
   350  	// v1.0 lifecycle, we should be good to collapse all of the init of lifecycle
   351  	// to this point.
   352  	lifecycleResources := &lifecycle.Resources{
   353  		Serializer:          &lifecycle.Serializer{},
   354  		ChannelConfigSource: peerInstance,
   355  		ChaincodeStore:      ccStore,
   356  		PackageParser:       ccPackageParser,
   357  	}
   358  
   359  	privdataConfig := gossipprivdata.GlobalConfig()
   360  	lifecycleValidatorCommitter := &lifecycle.ValidatorCommitter{
   361  		CoreConfig:                   coreConfig,
   362  		PrivdataConfig:               privdataConfig,
   363  		Resources:                    lifecycleResources,
   364  		LegacyDeployedCCInfoProvider: &lscc.DeployedCCInfoProvider{},
   365  	}
   366  
   367  	// Configure CC package storage before ccInfoFSImpl.ListInstalledChaincodes() gets called
   368  	lsccInstallPath := filepath.Join(coreconfig.GetPath("peer.fileSystemPath"), "chaincodes")
   369  	ccprovider.SetChaincodesPath(lsccInstallPath)
   370  
   371  	ccInfoFSImpl := &ccprovider.CCInfoFSImpl{GetHasher: factory.GetDefault()}
   372  
   373  	// legacyMetadataManager collects metadata information from the legacy
   374  	// lifecycle (lscc). This is expected to disappear with FAB-15061.
   375  	legacyMetadataManager, err := cclifecycle.NewMetadataManager(
   376  		cclifecycle.EnumerateFunc(
   377  			func() ([]ccdef.InstalledChaincode, error) {
   378  				return ccInfoFSImpl.ListInstalledChaincodes(ccInfoFSImpl.GetChaincodeInstallPath(), ioutil.ReadDir, ccprovider.LoadPackage)
   379  			},
   380  		),
   381  	)
   382  	if err != nil {
   383  		logger.Panicf("Failed creating LegacyMetadataManager: +%v", err)
   384  	}
   385  
   386  	// metadataManager aggregates metadata information from _lifecycle and
   387  	// the legacy lifecycle (lscc).
   388  	metadataManager := lifecycle.NewMetadataManager()
   389  
   390  	// the purpose of these two managers is to feed per-channel chaincode data
   391  	// into gossip owing to the fact that we are transitioning from lscc to
   392  	// _lifecycle, we still have two providers of such information until v2.1,
   393  	// in which we will remove the legacy.
   394  	//
   395  	// the flow of information is the following
   396  	//
   397  	// gossip <-- metadataManager <-- lifecycleCache  (for _lifecycle)
   398  	//                             \
   399  	//                              - legacyMetadataManager (for lscc)
   400  	//
   401  	// FAB-15061 tracks the work necessary to remove LSCC, at which point we
   402  	// will be able to simplify the flow to simply be
   403  	//
   404  	// gossip <-- lifecycleCache
   405  
   406  	chaincodeCustodian := lifecycle.NewChaincodeCustodian()
   407  
   408  	externalBuilderOutput := filepath.Join(coreconfig.GetPath("peer.fileSystemPath"), "externalbuilder", "builds")
   409  	if err := os.MkdirAll(externalBuilderOutput, 0o700); err != nil {
   410  		logger.Panicf("could not create externalbuilder build output dir: %s", err)
   411  	}
   412  
   413  	ebMetadataProvider := &externalbuilder.MetadataProvider{
   414  		DurablePath: externalBuilderOutput,
   415  	}
   416  
   417  	lifecycleCache := lifecycle.NewCache(
   418  		lifecycleResources,
   419  		mspID,
   420  		metadataManager,
   421  		chaincodeCustodian,
   422  		ebMetadataProvider,
   423  	)
   424  
   425  	txProcessors := map[cb.HeaderType]ledger.CustomTxProcessor{
   426  		cb.HeaderType_CONFIG: &peer.ConfigTxProcessor{},
   427  	}
   428  
   429  	peerInstance.LedgerMgr = ledgermgmt.NewLedgerMgr(
   430  		&ledgermgmt.Initializer{
   431  			CustomTxProcessors:              txProcessors,
   432  			DeployedChaincodeInfoProvider:   lifecycleValidatorCommitter,
   433  			MembershipInfoProvider:          membershipInfoProvider,
   434  			ChaincodeLifecycleEventProvider: lifecycleCache,
   435  			MetricsProvider:                 metricsProvider,
   436  			HealthCheckRegistry:             opsSystem,
   437  			StateListeners:                  []ledger.StateListener{lifecycleCache},
   438  			Config:                          ledgerConfig(),
   439  			HashProvider:                    factory.GetDefault(),
   440  			EbMetadataProvider:              ebMetadataProvider,
   441  		},
   442  	)
   443  
   444  	peerServer, err := comm.NewGRPCServer(listenAddr, serverConfig)
   445  	if err != nil {
   446  		logger.Fatalf("Failed to create peer server (%s)", err)
   447  	}
   448  
   449  	// FIXME: Creating the gossip service has the side effect of starting a bunch
   450  	// of go routines and registration with the grpc server.
   451  	gossipService, err := initGossipService(
   452  		policyMgr,
   453  		metricsProvider,
   454  		peerServer,
   455  		signingIdentity,
   456  		cs,
   457  		coreConfig.PeerAddress,
   458  		deliverServiceConfig,
   459  		privdataConfig,
   460  	)
   461  	if err != nil {
   462  		return errors.WithMessage(err, "failed to initialize gossip service")
   463  	}
   464  	defer gossipService.Stop()
   465  
   466  	peerInstance.GossipService = gossipService
   467  
   468  	if err := lifecycleCache.InitializeLocalChaincodes(); err != nil {
   469  		return errors.WithMessage(err, "could not initialize local chaincodes")
   470  	}
   471  
   472  	// Parameter overrides must be processed before any parameters are
   473  	// cached. Failures to cache cause the server to terminate immediately.
   474  	if chaincodeDevMode {
   475  		logger.Info("Running in chaincode development mode")
   476  		logger.Info("Disable loading validity system chaincode")
   477  
   478  		viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode)
   479  	}
   480  
   481  	mutualTLS := serverConfig.SecOpts.UseTLS && serverConfig.SecOpts.RequireClientCert
   482  	policyCheckerProvider := func(resourceName string) deliver.PolicyCheckerFunc {
   483  		return func(env *cb.Envelope, channelID string) error {
   484  			return aclProvider.CheckACL(resourceName, channelID, env)
   485  		}
   486  	}
   487  
   488  	metrics := deliver.NewMetrics(metricsProvider)
   489  	abServer := &peer.DeliverServer{
   490  		DeliverHandler: deliver.NewHandler(
   491  			&peer.DeliverChainManager{Peer: peerInstance},
   492  			coreConfig.AuthenticationTimeWindow,
   493  			mutualTLS,
   494  			metrics,
   495  			false,
   496  		),
   497  		PolicyCheckerProvider: policyCheckerProvider,
   498  	}
   499  	pb.RegisterDeliverServer(peerServer.Server(), abServer)
   500  
   501  	// Create a self-signed CA for chaincode service
   502  	ca, err := tlsgen.NewCA()
   503  	if err != nil {
   504  		logger.Panic("Failed creating authentication layer:", err)
   505  	}
   506  	ccSrv, ccEndpoint, err := createChaincodeServer(coreConfig, ca, peerHost)
   507  	if err != nil {
   508  		logger.Panicf("Failed to create chaincode server: %s", err)
   509  	}
   510  
   511  	// get user mode
   512  	userRunsCC := chaincode.IsDevMode()
   513  	tlsEnabled := coreConfig.PeerTLSEnabled
   514  
   515  	// create chaincode specific tls CA
   516  	authenticator := accesscontrol.NewAuthenticator(ca)
   517  
   518  	chaincodeHandlerRegistry := chaincode.NewHandlerRegistry(userRunsCC)
   519  	lifecycleTxQueryExecutorGetter := &chaincode.TxQueryExecutorGetter{
   520  		CCID:            scc.ChaincodeID(lifecycle.LifecycleNamespace),
   521  		HandlerRegistry: chaincodeHandlerRegistry,
   522  	}
   523  
   524  	if coreConfig.VMEndpoint == "" && len(coreConfig.ExternalBuilders) == 0 {
   525  		logger.Panic("VMEndpoint not set and no ExternalBuilders defined")
   526  	}
   527  
   528  	chaincodeConfig := chaincode.GlobalConfig()
   529  
   530  	var dockerBuilder container.DockerBuilder
   531  	if coreConfig.VMEndpoint != "" {
   532  		client, err := createDockerClient(coreConfig)
   533  		if err != nil {
   534  			logger.Panicf("cannot create docker client: %s", err)
   535  		}
   536  
   537  		dockerVM := &dockercontroller.DockerVM{
   538  			PeerID:        coreConfig.PeerID,
   539  			NetworkID:     coreConfig.NetworkID,
   540  			BuildMetrics:  dockercontroller.NewBuildMetrics(opsSystem.Provider),
   541  			Client:        client,
   542  			AttachStdOut:  coreConfig.VMDockerAttachStdout,
   543  			HostConfig:    getDockerHostConfig(),
   544  			ChaincodePull: coreConfig.ChaincodePull,
   545  			NetworkMode:   coreConfig.VMNetworkMode,
   546  			PlatformBuilder: &platforms.Builder{
   547  				Registry: platformRegistry,
   548  				Client:   client,
   549  			},
   550  			// This field is superfluous for chaincodes built with v2.0+ binaries
   551  			// however, to prevent users from being forced to rebuild leaving for now
   552  			// but it should be removed in the future.
   553  			LoggingEnv: []string{
   554  				"CORE_CHAINCODE_LOGGING_LEVEL=" + chaincodeConfig.LogLevel,
   555  				"CORE_CHAINCODE_LOGGING_SHIM=" + chaincodeConfig.ShimLogLevel,
   556  				"CORE_CHAINCODE_LOGGING_FORMAT=" + chaincodeConfig.LogFormat,
   557  			},
   558  			MSPID: mspID,
   559  		}
   560  		if err := opsSystem.RegisterChecker("docker", dockerVM); err != nil {
   561  			logger.Panicf("failed to register docker health check: %s", err)
   562  		}
   563  		dockerBuilder = dockerVM
   564  	}
   565  
   566  	// docker is disabled when we're missing the docker config
   567  	if dockerBuilder == nil {
   568  		dockerBuilder = &disabledDockerBuilder{}
   569  	}
   570  
   571  	externalVM := &externalbuilder.Detector{
   572  		Builders:    externalbuilder.CreateBuilders(coreConfig.ExternalBuilders, mspID),
   573  		DurablePath: externalBuilderOutput,
   574  	}
   575  
   576  	buildRegistry := &container.BuildRegistry{}
   577  
   578  	containerRouter := &container.Router{
   579  		DockerBuilder:   dockerBuilder,
   580  		ExternalBuilder: externalVMAdapter{externalVM},
   581  		PackageProvider: &persistence.FallbackPackageLocator{
   582  			ChaincodePackageLocator: &persistence.ChaincodePackageLocator{
   583  				ChaincodeDir: chaincodeInstallPath,
   584  			},
   585  			LegacyCCPackageLocator: &ccprovider.CCInfoFSImpl{GetHasher: factory.GetDefault()},
   586  		},
   587  	}
   588  
   589  	builtinSCCs := map[string]struct{}{
   590  		"lscc":       {},
   591  		"qscc":       {},
   592  		"cscc":       {},
   593  		"_lifecycle": {},
   594  	}
   595  
   596  	lsccInst := &lscc.SCC{
   597  		BuiltinSCCs: builtinSCCs,
   598  		Support: &lscc.SupportImpl{
   599  			GetMSPIDs:               peerInstance.GetMSPIDs,
   600  			GetIdentityDeserializer: identityDeserializerFactory,
   601  		},
   602  		SCCProvider: &lscc.PeerShim{Peer: peerInstance},
   603  		ACLProvider: aclProvider,
   604  		GetMSPIDs:   peerInstance.GetMSPIDs,
   605  		GetMSPManager: func(channelName string) msp.MSPManager {
   606  			return peerInstance.Channel(channelName).MSPManager()
   607  		},
   608  		BCCSP:              factory.GetDefault(),
   609  		BuildRegistry:      buildRegistry,
   610  		ChaincodeBuilder:   containerRouter,
   611  		EbMetadataProvider: ebMetadataProvider,
   612  	}
   613  
   614  	chaincodeEndorsementInfo := &lifecycle.ChaincodeEndorsementInfoSource{
   615  		LegacyImpl:  lsccInst,
   616  		Resources:   lifecycleResources,
   617  		Cache:       lifecycleCache,
   618  		BuiltinSCCs: builtinSCCs,
   619  		UserRunsCC:  userRunsCC,
   620  	}
   621  
   622  	containerRuntime := &chaincode.ContainerRuntime{
   623  		BuildRegistry:   buildRegistry,
   624  		ContainerRouter: containerRouter,
   625  	}
   626  
   627  	lifecycleFunctions := &lifecycle.ExternalFunctions{
   628  		Resources:                 lifecycleResources,
   629  		InstallListener:           lifecycleCache,
   630  		InstalledChaincodesLister: lifecycleCache,
   631  		ChaincodeBuilder:          containerRouter,
   632  		BuildRegistry:             buildRegistry,
   633  	}
   634  
   635  	lifecycleSCC := &lifecycle.SCC{
   636  		Dispatcher: &dispatcher.Dispatcher{
   637  			Protobuf: &dispatcher.ProtobufImpl{},
   638  		},
   639  		DeployedCCInfoProvider: lifecycleValidatorCommitter,
   640  		QueryExecutorProvider:  lifecycleTxQueryExecutorGetter,
   641  		Functions:              lifecycleFunctions,
   642  		OrgMSPID:               mspID,
   643  		ChannelConfigSource:    peerInstance,
   644  		ACLProvider:            aclProvider,
   645  	}
   646  
   647  	chaincodeLauncher := &chaincode.RuntimeLauncher{
   648  		Metrics:           chaincode.NewLaunchMetrics(opsSystem.Provider),
   649  		Registry:          chaincodeHandlerRegistry,
   650  		Runtime:           containerRuntime,
   651  		StartupTimeout:    chaincodeConfig.StartupTimeout,
   652  		CertGenerator:     authenticator,
   653  		CACert:            ca.CertBytes(),
   654  		PeerAddress:       ccEndpoint,
   655  		ConnectionHandler: &extcc.ExternalChaincodeRuntime{},
   656  	}
   657  
   658  	// Keep TestQueries working
   659  	if !chaincodeConfig.TLSEnabled {
   660  		chaincodeLauncher.CertGenerator = nil
   661  	}
   662  
   663  	chaincodeSupport := &chaincode.ChaincodeSupport{
   664  		ACLProvider:            aclProvider,
   665  		AppConfig:              peerInstance,
   666  		DeployedCCInfoProvider: lifecycleValidatorCommitter,
   667  		ExecuteTimeout:         chaincodeConfig.ExecuteTimeout,
   668  		InstallTimeout:         chaincodeConfig.InstallTimeout,
   669  		HandlerRegistry:        chaincodeHandlerRegistry,
   670  		HandlerMetrics:         chaincode.NewHandlerMetrics(opsSystem.Provider),
   671  		Keepalive:              chaincodeConfig.Keepalive,
   672  		Launcher:               chaincodeLauncher,
   673  		Lifecycle:              chaincodeEndorsementInfo,
   674  		Peer:                   peerInstance,
   675  		Runtime:                containerRuntime,
   676  		BuiltinSCCs:            builtinSCCs,
   677  		TotalQueryLimit:        chaincodeConfig.TotalQueryLimit,
   678  		UserRunsCC:             userRunsCC,
   679  	}
   680  
   681  	custodianLauncher := custodianLauncherAdapter{
   682  		launcher:      chaincodeLauncher,
   683  		streamHandler: chaincodeSupport,
   684  	}
   685  	go chaincodeCustodian.Work(buildRegistry, containerRouter, custodianLauncher)
   686  
   687  	ccSupSrv := pb.ChaincodeSupportServer(chaincodeSupport)
   688  	if tlsEnabled {
   689  		ccSupSrv = authenticator.Wrap(ccSupSrv)
   690  	}
   691  
   692  	csccInst := cscc.New(
   693  		aclProvider,
   694  		lifecycleValidatorCommitter,
   695  		lsccInst,
   696  		lifecycleValidatorCommitter,
   697  		peerInstance,
   698  		factory.GetDefault(),
   699  	)
   700  	qsccInst := scc.SelfDescribingSysCC(qscc.New(aclProvider, peerInstance))
   701  
   702  	pb.RegisterChaincodeSupportServer(ccSrv.Server(), ccSupSrv)
   703  
   704  	// start the chaincode specific gRPC listening service
   705  	go ccSrv.Start()
   706  
   707  	logger.Debugf("Running peer")
   708  
   709  	libConf, err := library.LoadConfig()
   710  	if err != nil {
   711  		return errors.WithMessage(err, "could not decode peer handlers configuration")
   712  	}
   713  
   714  	reg := library.InitRegistry(libConf)
   715  
   716  	authFilters := reg.Lookup(library.Auth).([]authHandler.Filter)
   717  	endorserSupport := &endorser.SupportImpl{
   718  		SignerSerializer: signingIdentity,
   719  		Peer:             peerInstance,
   720  		ChaincodeSupport: chaincodeSupport,
   721  		ACLProvider:      aclProvider,
   722  		BuiltinSCCs:      builtinSCCs,
   723  	}
   724  	endorsementPluginsByName := reg.Lookup(library.Endorsement).(map[string]endorsement2.PluginFactory)
   725  	validationPluginsByName := reg.Lookup(library.Validation).(map[string]validation.PluginFactory)
   726  	signingIdentityFetcher := (endorsement3.SigningIdentityFetcher)(endorserSupport)
   727  	channelStateRetriever := endorser.ChannelStateRetriever(endorserSupport)
   728  	pluginMapper := endorser.MapBasedPluginMapper(endorsementPluginsByName)
   729  	pluginEndorser := endorser.NewPluginEndorser(&endorser.PluginSupport{
   730  		ChannelStateRetriever:   channelStateRetriever,
   731  		TransientStoreRetriever: peerInstance,
   732  		PluginMapper:            pluginMapper,
   733  		SigningIdentityFetcher:  signingIdentityFetcher,
   734  	})
   735  	endorserSupport.PluginEndorser = pluginEndorser
   736  	channelFetcher := endorserChannelAdapter{
   737  		peer: peerInstance,
   738  	}
   739  	serverEndorser := &endorser.Endorser{
   740  		PrivateDataDistributor: gossipService,
   741  		ChannelFetcher:         channelFetcher,
   742  		LocalMSP:               localMSP,
   743  		Support:                endorserSupport,
   744  		Metrics:                endorser.NewMetrics(metricsProvider),
   745  	}
   746  
   747  	// deploy system chaincodes
   748  	for _, cc := range []scc.SelfDescribingSysCC{lsccInst, csccInst, qsccInst, lifecycleSCC} {
   749  		if enabled, ok := chaincodeConfig.SCCAllowlist[cc.Name()]; !ok || !enabled {
   750  			logger.Infof("not deploying chaincode %s as it is not enabled", cc.Name())
   751  			continue
   752  		}
   753  		scc.DeploySysCC(cc, chaincodeSupport)
   754  	}
   755  
   756  	logger.Infof("Deployed system chaincodes")
   757  
   758  	// register the lifecycleMetadataManager to get updates from the legacy
   759  	// chaincode; lifecycleMetadataManager will aggregate these updates with
   760  	// the ones from the new lifecycle and deliver both
   761  	// this is expected to disappear with FAB-15061
   762  	legacyMetadataManager.AddListener(metadataManager)
   763  
   764  	// register gossip as a listener for updates from lifecycleMetadataManager
   765  	metadataManager.AddListener(lifecycle.HandleMetadataUpdateFunc(func(channel string, chaincodes ccdef.MetadataSet) {
   766  		gossipService.UpdateChaincodes(chaincodes.AsChaincodes(), gossipcommon.ChannelID(channel))
   767  	}))
   768  
   769  	// this brings up all the channels
   770  	peerInstance.Initialize(
   771  		func(cid string) {
   772  			// initialize the metadata for this channel.
   773  			// This call will pre-populate chaincode information for this
   774  			// channel but it won't fire any updates to its listeners
   775  			lifecycleCache.InitializeMetadata(cid)
   776  
   777  			// initialize the legacyMetadataManager for this channel.
   778  			// This call will pre-populate chaincode information from
   779  			// the legacy lifecycle for this channel; it will also fire
   780  			// the listener, which will cascade to metadataManager
   781  			// and eventually to gossip to pre-populate data structures.
   782  			// this is expected to disappear with FAB-15061
   783  			sub, err := legacyMetadataManager.NewChannelSubscription(cid, cclifecycle.QueryCreatorFunc(func() (cclifecycle.Query, error) {
   784  				return peerInstance.GetLedger(cid).NewQueryExecutor()
   785  			}))
   786  			if err != nil {
   787  				logger.Panicf("Failed subscribing to chaincode lifecycle updates")
   788  			}
   789  
   790  			// register this channel's legacyMetadataManager (sub) to get ledger updates
   791  			// this is expected to disappear with FAB-15061
   792  			cceventmgmt.GetMgr().Register(cid, sub)
   793  		},
   794  		peerServer,
   795  		plugin.MapBasedMapper(validationPluginsByName),
   796  		lifecycleValidatorCommitter,
   797  		lsccInst,
   798  		lifecycleValidatorCommitter,
   799  		coreConfig.ValidatorPoolSize,
   800  	)
   801  
   802  	var discoveryService *discovery.Service
   803  	if coreConfig.DiscoveryEnabled {
   804  		discoveryService = createDiscoveryService(
   805  			coreConfig,
   806  			peerInstance,
   807  			peerServer,
   808  			policyMgr,
   809  			lifecycle.NewMetadataProvider(
   810  				lifecycleCache,
   811  				legacyMetadataManager,
   812  				peerInstance,
   813  			),
   814  			gossipService,
   815  		)
   816  		logger.Info("Discovery service activated")
   817  		discprotos.RegisterDiscoveryServer(peerServer.Server(), discoveryService)
   818  	}
   819  
   820  	if coreConfig.GatewayOptions.Enabled {
   821  		if coreConfig.DiscoveryEnabled {
   822  			logger.Info("Starting peer with Gateway enabled")
   823  
   824  			gatewayServer := gateway.CreateServer(
   825  				serverEndorser,
   826  				discoveryService,
   827  				peerInstance,
   828  				&serverConfig.SecOpts,
   829  				aclProvider,
   830  				coreConfig.LocalMSPID,
   831  				coreConfig.GatewayOptions,
   832  			)
   833  			gatewayprotos.RegisterGatewayServer(peerServer.Server(), gatewayServer)
   834  		} else {
   835  			logger.Warning("Discovery service must be enabled for embedded gateway")
   836  		}
   837  	}
   838  
   839  	logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]", coreConfig.PeerID, coreConfig.NetworkID, coreConfig.PeerAddress)
   840  
   841  	// Get configuration before starting go routines to avoid
   842  	// racing in tests
   843  	profileEnabled := coreConfig.ProfileEnabled
   844  	profileListenAddress := coreConfig.ProfileListenAddress
   845  
   846  	// Start the grpc server. Done in a goroutine so we can deploy the
   847  	// genesis block if needed.
   848  	serve := make(chan error)
   849  
   850  	// Start profiling http endpoint if enabled
   851  	if profileEnabled {
   852  		go func() {
   853  			logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress)
   854  			if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil {
   855  				logger.Errorf("Error starting profiler: %s", profileErr)
   856  			}
   857  		}()
   858  	}
   859  
   860  	handleSignals(addPlatformSignals(map[os.Signal]func(){
   861  		syscall.SIGINT:  func() { containerRouter.Shutdown(5 * time.Second); serve <- nil },
   862  		syscall.SIGTERM: func() { containerRouter.Shutdown(5 * time.Second); serve <- nil },
   863  	}))
   864  
   865  	logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]", coreConfig.PeerID, coreConfig.NetworkID, coreConfig.PeerAddress)
   866  
   867  	// get a list of ledger IDs and load preResetHeight files for these ledger IDs
   868  	ledgerIDs, err := peerInstance.LedgerMgr.GetLedgerIDs()
   869  	if err != nil {
   870  		return errors.WithMessage(err, "failed to get ledger IDs")
   871  	}
   872  
   873  	// check to see if the peer ledgers have been reset
   874  	rootFSPath := filepath.Join(coreconfig.GetPath("peer.fileSystemPath"), "ledgersData")
   875  	preResetHeights, err := kvledger.LoadPreResetHeight(rootFSPath, ledgerIDs)
   876  	if err != nil {
   877  		return fmt.Errorf("error loading prereset height: %s", err)
   878  	}
   879  
   880  	for cid, height := range preResetHeights {
   881  		logger.Infof("Ledger rebuild: channel [%s]: preresetHeight: [%d]", cid, height)
   882  	}
   883  
   884  	if len(preResetHeights) > 0 {
   885  		logger.Info("Ledger rebuild: Entering loop to check if current ledger heights surpass prereset ledger heights. Endorsement request processing will be disabled.")
   886  		resetFilter := &reset{
   887  			reject: true,
   888  		}
   889  		authFilters = append(authFilters, resetFilter)
   890  		go resetLoop(resetFilter, preResetHeights, ledgerIDs, peerInstance.GetLedger, 10*time.Second)
   891  	}
   892  
   893  	// start the peer server
   894  	auth := authHandler.ChainFilters(serverEndorser, authFilters...)
   895  	// Register the Endorser server
   896  	pb.RegisterEndorserServer(peerServer.Server(), auth)
   897  
   898  	// register the snapshot server
   899  	snapshotSvc := &snapshotgrpc.SnapshotService{LedgerGetter: peerInstance, ACLProvider: aclProvider}
   900  	pb.RegisterSnapshotServer(peerServer.Server(), snapshotSvc)
   901  
   902  	go func() {
   903  		var grpcErr error
   904  		if grpcErr = peerServer.Start(); grpcErr != nil {
   905  			grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr)
   906  		}
   907  		serve <- grpcErr
   908  	}()
   909  
   910  	// Block until grpc server exits
   911  	return <-serve
   912  }
   913  
   914  func handleSignals(handlers map[os.Signal]func()) {
   915  	var signals []os.Signal
   916  	for sig := range handlers {
   917  		signals = append(signals, sig)
   918  	}
   919  
   920  	signalChan := make(chan os.Signal, 1)
   921  	signal.Notify(signalChan, signals...)
   922  
   923  	go func() {
   924  		for sig := range signalChan {
   925  			logger.Infof("Received signal: %d (%s)", sig, sig)
   926  			handlers[sig]()
   927  		}
   928  	}()
   929  }
   930  
   931  func localPolicy(policyObject proto.Message) policies.Policy {
   932  	localMSP := mgmt.GetLocalMSP(factory.GetDefault())
   933  	pp := cauthdsl.NewPolicyProvider(localMSP)
   934  	policy, _, err := pp.NewPolicy(protoutil.MarshalOrPanic(policyObject))
   935  	if err != nil {
   936  		logger.Panicf("Failed creating local policy: +%v", err)
   937  	}
   938  	return policy
   939  }
   940  
   941  func createSelfSignedData(sID msp.SigningIdentity) protoutil.SignedData {
   942  	msg := make([]byte, 32)
   943  	sig, err := sID.Sign(msg)
   944  	if err != nil {
   945  		logger.Panicf("Failed creating self signed data because message signing failed: %v", err)
   946  	}
   947  	peerIdentity, err := sID.Serialize()
   948  	if err != nil {
   949  		logger.Panicf("Failed creating self signed data because peer identity couldn't be serialized: %v", err)
   950  	}
   951  	return protoutil.SignedData{
   952  		Data:      msg,
   953  		Signature: sig,
   954  		Identity:  peerIdentity,
   955  	}
   956  }
   957  
   958  func createDiscoveryService(
   959  	coreConfig *peer.Config,
   960  	peerInstance *peer.Peer,
   961  	peerServer *comm.GRPCServer,
   962  	polMgr policies.ChannelPolicyManagerGetter,
   963  	metadataProvider *lifecycle.MetadataProvider,
   964  	gossipService *gossipservice.GossipService,
   965  ) *discovery.Service {
   966  	mspID := coreConfig.LocalMSPID
   967  	localAccessPolicy := localPolicy(policydsl.SignedByAnyAdmin([]string{mspID}))
   968  	if coreConfig.DiscoveryOrgMembersAllowed {
   969  		localAccessPolicy = localPolicy(policydsl.SignedByAnyMember([]string{mspID}))
   970  	}
   971  	channelVerifier := discacl.NewChannelVerifier(policies.ChannelApplicationWriters, polMgr)
   972  	acl := discacl.NewDiscoverySupport(channelVerifier, localAccessPolicy, discacl.ChannelConfigGetterFunc(peerInstance.GetStableChannelConfig))
   973  	gSup := gossip.NewDiscoverySupport(gossipService)
   974  	ccSup := ccsupport.NewDiscoverySupport(metadataProvider)
   975  	ea := endorsement.NewEndorsementAnalyzer(gSup, ccSup, acl, metadataProvider)
   976  	confSup := config.NewDiscoverySupport(config.CurrentConfigGetterFunc(func(channelID string) *cb.Config {
   977  		channel := peerInstance.Channel(channelID)
   978  		if channel == nil {
   979  			return nil
   980  		}
   981  		config, err := peer.RetrievePersistedChannelConfig(channel.Ledger())
   982  		if err != nil {
   983  			logger.Errorw("failed to get channel config", "error", err)
   984  			return nil
   985  		}
   986  		return config
   987  	}))
   988  	support := discsupport.NewDiscoverySupport(acl, gSup, ea, confSup, acl)
   989  	return discovery.NewService(discovery.Config{
   990  		TLS:                          peerServer.TLSEnabled(),
   991  		AuthCacheEnabled:             coreConfig.DiscoveryAuthCacheEnabled,
   992  		AuthCacheMaxSize:             coreConfig.DiscoveryAuthCacheMaxSize,
   993  		AuthCachePurgeRetentionRatio: coreConfig.DiscoveryAuthCachePurgeRetentionRatio,
   994  	}, support)
   995  }
   996  
   997  // create a CC listener using peer.chaincodeListenAddress (and if that's not set use peer.peerAddress)
   998  func createChaincodeServer(coreConfig *peer.Config, ca tlsgen.CA, peerHostname string) (srv *comm.GRPCServer, ccEndpoint string, err error) {
   999  	// before potentially setting chaincodeListenAddress, compute chaincode endpoint at first
  1000  	ccEndpoint, err = computeChaincodeEndpoint(coreConfig.ChaincodeAddress, coreConfig.ChaincodeListenAddress, peerHostname)
  1001  	if err != nil {
  1002  		if chaincode.IsDevMode() {
  1003  			// if any error for dev mode, we use 0.0.0.0:7052
  1004  			ccEndpoint = fmt.Sprintf("%s:%d", "0.0.0.0", defaultChaincodePort)
  1005  			logger.Warningf("use %s as chaincode endpoint because of error in computeChaincodeEndpoint: %s", ccEndpoint, err)
  1006  		} else {
  1007  			// for non-dev mode, we have to return error
  1008  			logger.Errorf("Error computing chaincode endpoint: %s", err)
  1009  			return nil, "", err
  1010  		}
  1011  	}
  1012  
  1013  	host, _, err := net.SplitHostPort(ccEndpoint)
  1014  	if err != nil {
  1015  		logger.Panic("Chaincode service host", ccEndpoint, "isn't a valid hostname:", err)
  1016  	}
  1017  
  1018  	cclistenAddress := coreConfig.ChaincodeListenAddress
  1019  	if cclistenAddress == "" {
  1020  		cclistenAddress = fmt.Sprintf("%s:%d", peerHostname, defaultChaincodePort)
  1021  		logger.Warningf("%s is not set, using %s", chaincodeListenAddrKey, cclistenAddress)
  1022  		coreConfig.ChaincodeListenAddress = cclistenAddress
  1023  	}
  1024  
  1025  	config, err := peer.GetServerConfig()
  1026  	if err != nil {
  1027  		logger.Errorf("Error getting server config: %s", err)
  1028  		return nil, "", err
  1029  	}
  1030  
  1031  	// set the logger for the server
  1032  	config.Logger = flogging.MustGetLogger("core.comm").With("server", "ChaincodeServer")
  1033  
  1034  	// Override TLS configuration if TLS is applicable
  1035  	if config.SecOpts.UseTLS {
  1036  		// Create a self-signed TLS certificate with a SAN that matches the computed chaincode endpoint
  1037  		certKeyPair, err := ca.NewServerCertKeyPair(host)
  1038  		if err != nil {
  1039  			logger.Panicf("Failed generating TLS certificate for chaincode service: +%v", err)
  1040  		}
  1041  		config.SecOpts = comm.SecureOptions{
  1042  			UseTLS: true,
  1043  			// Require chaincode shim to authenticate itself
  1044  			RequireClientCert: true,
  1045  			// Trust only client certificates signed by ourselves
  1046  			ClientRootCAs: [][]byte{ca.CertBytes()},
  1047  			// Use our own self-signed TLS certificate and key
  1048  			Certificate: certKeyPair.Cert,
  1049  			Key:         certKeyPair.Key,
  1050  			// No point in specifying server root CAs since this TLS config is only used for
  1051  			// a gRPC server and not a client
  1052  			ServerRootCAs: nil,
  1053  		}
  1054  	}
  1055  
  1056  	// Chaincode keepalive options - static for now
  1057  	chaincodeKeepaliveOptions := comm.KeepaliveOptions{
  1058  		ServerInterval:    time.Duration(2) * time.Hour,    // 2 hours - gRPC default
  1059  		ServerTimeout:     time.Duration(20) * time.Second, // 20 sec - gRPC default
  1060  		ServerMinInterval: time.Duration(1) * time.Minute,  // match ClientInterval
  1061  	}
  1062  	config.KaOpts = chaincodeKeepaliveOptions
  1063  	config.HealthCheckEnabled = true
  1064  
  1065  	srv, err = comm.NewGRPCServer(cclistenAddress, config)
  1066  	if err != nil {
  1067  		logger.Errorf("Error creating GRPC server: %s", err)
  1068  		return nil, "", err
  1069  	}
  1070  
  1071  	return srv, ccEndpoint, nil
  1072  }
  1073  
  1074  // computeChaincodeEndpoint will utilize chaincode address, chaincode listen
  1075  // address (these two are from viper) and peer address to compute chaincode endpoint.
  1076  // There could be following cases of computing chaincode endpoint:
  1077  // Case A: if chaincodeAddrKey is set, use it if not "0.0.0.0" (or "::")
  1078  // Case B: else if chaincodeListenAddressKey is set and not "0.0.0.0" or ("::"), use it
  1079  // Case C: else use peer address if not "0.0.0.0" (or "::")
  1080  // Case D: else return error
  1081  func computeChaincodeEndpoint(chaincodeAddress string, chaincodeListenAddress string, peerHostname string) (ccEndpoint string, err error) {
  1082  	logger.Infof("Entering computeChaincodeEndpoint with peerHostname: %s", peerHostname)
  1083  	// Case A: the chaincodeAddrKey is set
  1084  	if chaincodeAddress != "" {
  1085  		host, _, err := net.SplitHostPort(chaincodeAddress)
  1086  		if err != nil {
  1087  			logger.Errorf("Fail to split chaincodeAddress: %s", err)
  1088  			return "", err
  1089  		}
  1090  		ccIP := net.ParseIP(host)
  1091  		if ccIP != nil && ccIP.IsUnspecified() {
  1092  			logger.Errorf("ChaincodeAddress' IP cannot be %s in non-dev mode", ccIP)
  1093  			return "", errors.New("invalid endpoint for chaincode to connect")
  1094  		}
  1095  		logger.Infof("Exit with ccEndpoint: %s", chaincodeAddress)
  1096  		return chaincodeAddress, nil
  1097  	}
  1098  
  1099  	// Case B: chaincodeListenAddrKey is set
  1100  	if chaincodeListenAddress != "" {
  1101  		ccEndpoint = chaincodeListenAddress
  1102  		host, port, err := net.SplitHostPort(ccEndpoint)
  1103  		if err != nil {
  1104  			logger.Errorf("ChaincodeAddress is nil and fail to split chaincodeListenAddress: %s", err)
  1105  			return "", err
  1106  		}
  1107  
  1108  		ccListenerIP := net.ParseIP(host)
  1109  		// ignoring other values such as Multicast address etc ...as the server
  1110  		// wouldn't start up with this address anyway
  1111  		if ccListenerIP != nil && ccListenerIP.IsUnspecified() {
  1112  			// Case C: if "0.0.0.0" or "::", we have to use peer address with the listen port
  1113  			peerIP := net.ParseIP(peerHostname)
  1114  			if peerIP != nil && peerIP.IsUnspecified() {
  1115  				// Case D: all we have is "0.0.0.0" or "::" which chaincode cannot connect to
  1116  				logger.Error("ChaincodeAddress is nil while both chaincodeListenAddressIP and peerIP are 0.0.0.0")
  1117  				return "", errors.New("invalid endpoint for chaincode to connect")
  1118  			}
  1119  			ccEndpoint = fmt.Sprintf("%s:%s", peerHostname, port)
  1120  		}
  1121  		logger.Infof("Exit with ccEndpoint: %s", ccEndpoint)
  1122  		return ccEndpoint, nil
  1123  	}
  1124  
  1125  	// Case C: chaincodeListenAddrKey is not set, use peer address
  1126  	peerIP := net.ParseIP(peerHostname)
  1127  	if peerIP != nil && peerIP.IsUnspecified() {
  1128  		// Case D: all we have is "0.0.0.0" or "::" which chaincode cannot connect to
  1129  		logger.Errorf("ChaincodeAddress and chaincodeListenAddress are nil and peerIP is %s", peerIP)
  1130  		return "", errors.New("invalid endpoint for chaincode to connect")
  1131  	}
  1132  
  1133  	// use peerAddress:defaultChaincodePort
  1134  	ccEndpoint = fmt.Sprintf("%s:%d", peerHostname, defaultChaincodePort)
  1135  
  1136  	logger.Infof("Exit with ccEndpoint: %s", ccEndpoint)
  1137  	return ccEndpoint, nil
  1138  }
  1139  
  1140  func createDockerClient(coreConfig *peer.Config) (*docker.Client, error) {
  1141  	if coreConfig.VMDockerTLSEnabled {
  1142  		return docker.NewTLSClient(coreConfig.VMEndpoint, coreConfig.DockerCert, coreConfig.DockerKey, coreConfig.DockerCA)
  1143  	}
  1144  	return docker.NewClient(coreConfig.VMEndpoint)
  1145  }
  1146  
  1147  // secureDialOpts is the callback function for secure dial options for gossip service
  1148  func secureDialOpts(credSupport *comm.CredentialSupport) func() []grpc.DialOption {
  1149  	return func() []grpc.DialOption {
  1150  		var dialOpts []grpc.DialOption
  1151  		// set max send/recv msg sizes
  1152  		maxRecvMsgSize := comm.DefaultMaxRecvMsgSize
  1153  		if viper.IsSet("peer.maxRecvMsgSize") {
  1154  			maxRecvMsgSize = int(viper.GetInt32("peer.maxRecvMsgSize"))
  1155  		}
  1156  		maxSendMsgSize := comm.DefaultMaxSendMsgSize
  1157  		if viper.IsSet("peer.maxSendMsgSize") {
  1158  			maxSendMsgSize = int(viper.GetInt32("peer.maxSendMsgSize"))
  1159  		}
  1160  		dialOpts = append(
  1161  			dialOpts,
  1162  			grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxRecvMsgSize), grpc.MaxCallSendMsgSize(maxSendMsgSize)),
  1163  		)
  1164  		// set the keepalive options
  1165  		kaOpts := comm.DefaultKeepaliveOptions
  1166  		if viper.IsSet("peer.keepalive.client.interval") {
  1167  			kaOpts.ClientInterval = viper.GetDuration("peer.keepalive.client.interval")
  1168  		}
  1169  		if viper.IsSet("peer.keepalive.client.timeout") {
  1170  			kaOpts.ClientTimeout = viper.GetDuration("peer.keepalive.client.timeout")
  1171  		}
  1172  		dialOpts = append(dialOpts, kaOpts.ClientKeepaliveOptions()...)
  1173  
  1174  		if viper.GetBool("peer.tls.enabled") {
  1175  			dialOpts = append(dialOpts, grpc.WithTransportCredentials(credSupport.GetPeerCredentials()))
  1176  		} else {
  1177  			dialOpts = append(dialOpts, grpc.WithInsecure())
  1178  		}
  1179  		return dialOpts
  1180  	}
  1181  }
  1182  
  1183  // initGossipService will initialize the gossip service by:
  1184  // 1. Enable TLS if configured;
  1185  // 2. Init the message crypto service;
  1186  // 3. Init the security advisor;
  1187  // 4. Init gossip related struct.
  1188  func initGossipService(
  1189  	policyMgr policies.ChannelPolicyManagerGetter,
  1190  	metricsProvider metrics.Provider,
  1191  	peerServer *comm.GRPCServer,
  1192  	signer msp.SigningIdentity,
  1193  	credSupport *comm.CredentialSupport,
  1194  	peerAddress string,
  1195  	deliverServiceConfig *deliverservice.DeliverServiceConfig,
  1196  	privdataConfig *gossipprivdata.PrivdataConfig,
  1197  ) (*gossipservice.GossipService, error) {
  1198  	var certs *gossipcommon.TLSCertificates
  1199  	if peerServer.TLSEnabled() {
  1200  		serverCert := peerServer.ServerCertificate()
  1201  		clientCert, err := peer.GetClientCertificate()
  1202  		if err != nil {
  1203  			return nil, errors.Wrap(err, "failed obtaining client certificates")
  1204  		}
  1205  		certs = &gossipcommon.TLSCertificates{}
  1206  		certs.TLSServerCert.Store(&serverCert)
  1207  		certs.TLSClientCert.Store(&clientCert)
  1208  	}
  1209  
  1210  	localMSP := mgmt.GetLocalMSP(factory.GetDefault())
  1211  	deserManager := peergossip.NewDeserializersManager(localMSP)
  1212  	messageCryptoService := peergossip.NewMCS(
  1213  		policyMgr,
  1214  		signer,
  1215  		deserManager,
  1216  		factory.GetDefault(),
  1217  	)
  1218  	secAdv := peergossip.NewSecurityAdvisor(deserManager)
  1219  	bootstrap := viper.GetStringSlice("peer.gossip.bootstrap")
  1220  
  1221  	serviceConfig := gossipservice.GlobalConfig()
  1222  	if serviceConfig.Endpoint != "" {
  1223  		peerAddress = serviceConfig.Endpoint
  1224  	}
  1225  	gossipConfig, err := gossipgossip.GlobalConfig(peerAddress, certs, bootstrap...)
  1226  	if err != nil {
  1227  		return nil, errors.Wrap(err, "failed obtaining gossip config")
  1228  	}
  1229  
  1230  	return gossipservice.New(
  1231  		signer,
  1232  		gossipmetrics.NewGossipMetrics(metricsProvider),
  1233  		peerAddress,
  1234  		peerServer.Server(),
  1235  		messageCryptoService,
  1236  		secAdv,
  1237  		secureDialOpts(credSupport),
  1238  		credSupport,
  1239  		gossipConfig,
  1240  		serviceConfig,
  1241  		privdataConfig,
  1242  		deliverServiceConfig,
  1243  	)
  1244  }
  1245  
  1246  func newOperationsSystem(coreConfig *peer.Config) *operations.System {
  1247  	return operations.NewSystem(operations.Options{
  1248  		Options: fabhttp.Options{
  1249  			Logger:        flogging.MustGetLogger("peer.operations"),
  1250  			ListenAddress: coreConfig.OperationsListenAddress,
  1251  			TLS: fabhttp.TLS{
  1252  				Enabled:            coreConfig.OperationsTLSEnabled,
  1253  				CertFile:           coreConfig.OperationsTLSCertFile,
  1254  				KeyFile:            coreConfig.OperationsTLSKeyFile,
  1255  				ClientCertRequired: coreConfig.OperationsTLSClientAuthRequired,
  1256  				ClientCACertFiles:  coreConfig.OperationsTLSClientRootCAs,
  1257  			},
  1258  		},
  1259  		Metrics: operations.MetricsOptions{
  1260  			Provider: coreConfig.MetricsProvider,
  1261  			Statsd: &operations.Statsd{
  1262  				Network:       coreConfig.StatsdNetwork,
  1263  				Address:       coreConfig.StatsdAaddress,
  1264  				WriteInterval: coreConfig.StatsdWriteInterval,
  1265  				Prefix:        coreConfig.StatsdPrefix,
  1266  			},
  1267  		},
  1268  		Version: metadata.Version,
  1269  	})
  1270  }
  1271  
  1272  func getDockerHostConfig() *docker.HostConfig {
  1273  	dockerKey := func(key string) string { return "vm.docker.hostConfig." + key }
  1274  	getInt64 := func(key string) int64 { return int64(viper.GetInt(dockerKey(key))) }
  1275  
  1276  	var logConfig docker.LogConfig
  1277  	err := viper.UnmarshalKey(dockerKey("LogConfig"), &logConfig)
  1278  	if err != nil {
  1279  		logger.Panicf("unable to parse Docker LogConfig: %s", err)
  1280  	}
  1281  
  1282  	networkMode := viper.GetString(dockerKey("NetworkMode"))
  1283  	if networkMode == "" {
  1284  		networkMode = "host"
  1285  	}
  1286  
  1287  	memorySwappiness := getInt64("MemorySwappiness")
  1288  	oomKillDisable := viper.GetBool(dockerKey("OomKillDisable"))
  1289  
  1290  	return &docker.HostConfig{
  1291  		CapAdd:  viper.GetStringSlice(dockerKey("CapAdd")),
  1292  		CapDrop: viper.GetStringSlice(dockerKey("CapDrop")),
  1293  
  1294  		DNS:         viper.GetStringSlice(dockerKey("Dns")),
  1295  		DNSSearch:   viper.GetStringSlice(dockerKey("DnsSearch")),
  1296  		ExtraHosts:  viper.GetStringSlice(dockerKey("ExtraHosts")),
  1297  		NetworkMode: networkMode,
  1298  		IpcMode:     viper.GetString(dockerKey("IpcMode")),
  1299  		PidMode:     viper.GetString(dockerKey("PidMode")),
  1300  		UTSMode:     viper.GetString(dockerKey("UTSMode")),
  1301  		LogConfig:   logConfig,
  1302  
  1303  		ReadonlyRootfs:   viper.GetBool(dockerKey("ReadonlyRootfs")),
  1304  		SecurityOpt:      viper.GetStringSlice(dockerKey("SecurityOpt")),
  1305  		CgroupParent:     viper.GetString(dockerKey("CgroupParent")),
  1306  		Memory:           getInt64("Memory"),
  1307  		MemorySwap:       getInt64("MemorySwap"),
  1308  		MemorySwappiness: &memorySwappiness,
  1309  		OOMKillDisable:   &oomKillDisable,
  1310  		CPUShares:        getInt64("CpuShares"),
  1311  		CPUSet:           viper.GetString(dockerKey("Cpuset")),
  1312  		CPUSetCPUs:       viper.GetString(dockerKey("CpusetCPUs")),
  1313  		CPUSetMEMs:       viper.GetString(dockerKey("CpusetMEMs")),
  1314  		CPUQuota:         getInt64("CpuQuota"),
  1315  		CPUPeriod:        getInt64("CpuPeriod"),
  1316  		BlkioWeight:      getInt64("BlkioWeight"),
  1317  	}
  1318  }
  1319  
  1320  //go:generate counterfeiter -o mock/get_ledger.go -fake-name GetLedger . getLedger
  1321  //go:generate counterfeiter -o mock/peer_ledger.go -fake-name PeerLedger . peerLedger
  1322  
  1323  type peerLedger interface {
  1324  	ledger.PeerLedger
  1325  }
  1326  
  1327  type getLedger func(string) ledger.PeerLedger
  1328  
  1329  func resetLoop(
  1330  	resetFilter *reset,
  1331  	preResetHeights map[string]uint64,
  1332  	ledgerIDs []string,
  1333  	pLedger getLedger,
  1334  	interval time.Duration,
  1335  ) {
  1336  	ledgerDataPath := filepath.Join(coreconfig.GetPath("peer.fileSystemPath"), "ledgersData")
  1337  
  1338  	// periodically check to see if current ledger height(s) surpass prereset height(s)
  1339  	ticker := time.NewTicker(interval)
  1340  	defer ticker.Stop()
  1341  
  1342  	for range ticker.C {
  1343  		logger.Info("Ledger rebuild: Checking if current ledger heights surpass prereset ledger heights")
  1344  		logger.Debugf("Ledger rebuild: Number of ledgers still rebuilding before check: %d", len(preResetHeights))
  1345  
  1346  		for cid, height := range preResetHeights {
  1347  			l := pLedger(cid)
  1348  			if l == nil {
  1349  				logger.Warningf("No ledger found for channel [%s]", cid)
  1350  				continue
  1351  			}
  1352  
  1353  			bcInfo, err := l.GetBlockchainInfo()
  1354  			if err != nil {
  1355  				logger.Warningf("Ledger rebuild: could not retrieve info for channel [%s]: %s", cid, err.Error())
  1356  				continue
  1357  			}
  1358  			if bcInfo == nil {
  1359  				continue
  1360  			}
  1361  
  1362  			logger.Debugf("Ledger rebuild: channel [%s]: currentHeight [%d] : preresetHeight [%d]", cid, bcInfo.GetHeight(), height)
  1363  			if bcInfo.GetHeight() >= height {
  1364  				delete(preResetHeights, cid)
  1365  			}
  1366  		}
  1367  
  1368  		logger.Debugf("Ledger rebuild: Number of ledgers still rebuilding after check: %d", len(preResetHeights))
  1369  		if len(preResetHeights) == 0 {
  1370  			logger.Infof("Ledger rebuild: Complete, all ledgers surpass prereset heights. Endorsement request processing will be enabled.")
  1371  
  1372  			err := kvledger.ClearPreResetHeight(ledgerDataPath, ledgerIDs)
  1373  			if err != nil {
  1374  				logger.Warningf("Ledger rebuild: could not clear off prerest files: error=%s", err)
  1375  			}
  1376  			resetFilter.setReject(false)
  1377  			return
  1378  		}
  1379  	}
  1380  }
  1381  
  1382  // reset implements the auth.Filter interface.
  1383  type reset struct {
  1384  	lock   sync.RWMutex
  1385  	next   pb.EndorserServer
  1386  	reject bool
  1387  }
  1388  
  1389  func (r *reset) setReject(reject bool) {
  1390  	r.lock.Lock()
  1391  	defer r.lock.Unlock()
  1392  	r.reject = reject
  1393  }
  1394  
  1395  // Init initializes Reset with the next EndorserServer.
  1396  func (r *reset) Init(next pb.EndorserServer) {
  1397  	r.next = next
  1398  }
  1399  
  1400  // ProcessProposal processes a signed proposal.
  1401  func (r *reset) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal) (*pb.ProposalResponse, error) {
  1402  	r.lock.RLock()
  1403  	defer r.lock.RUnlock()
  1404  	if r.reject {
  1405  		return nil, errors.New("endorse requests are blocked while ledgers are being rebuilt")
  1406  	}
  1407  	return r.next.ProcessProposal(ctx, signedProp)
  1408  }