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