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