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