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