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