github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/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 "fmt" 11 "io/ioutil" 12 "net" 13 "net/http" 14 "os" 15 "os/signal" 16 "path/filepath" 17 "strconv" 18 "syscall" 19 "time" 20 21 "github.com/hyperledger/fabric/common/flogging" 22 "github.com/hyperledger/fabric/common/localmsp" 23 "github.com/hyperledger/fabric/core" 24 "github.com/hyperledger/fabric/core/chaincode" 25 "github.com/hyperledger/fabric/core/comm" 26 "github.com/hyperledger/fabric/core/common/ccprovider" 27 "github.com/hyperledger/fabric/core/config" 28 "github.com/hyperledger/fabric/core/endorser" 29 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 30 "github.com/hyperledger/fabric/core/peer" 31 "github.com/hyperledger/fabric/core/scc" 32 "github.com/hyperledger/fabric/events/producer" 33 "github.com/hyperledger/fabric/gossip/service" 34 "github.com/hyperledger/fabric/msp/mgmt" 35 "github.com/hyperledger/fabric/peer/common" 36 peergossip "github.com/hyperledger/fabric/peer/gossip" 37 "github.com/hyperledger/fabric/peer/version" 38 pb "github.com/hyperledger/fabric/protos/peer" 39 "github.com/spf13/cobra" 40 "github.com/spf13/viper" 41 "google.golang.org/grpc" 42 "google.golang.org/grpc/grpclog" 43 ) 44 45 //function used by chaincode support 46 type ccEndpointFunc func() (*pb.PeerEndpoint, error) 47 48 var chaincodeDevMode bool 49 var peerDefaultChain bool 50 var orderingEndpoint string 51 52 // XXXDefaultChannelMSPID should not be defined in production code 53 // It should only be referenced in tests. However, it is necessary 54 // to support the 'default chain' setup so temporarily adding until 55 // this concept can be removed to testing scenarios only 56 const XXXDefaultChannelMSPID = "DEFAULT" 57 58 func startCmd() *cobra.Command { 59 // Set the flags on the node start command. 60 flags := nodeStartCmd.Flags() 61 flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, 62 "Whether peer in chaincode development mode") 63 flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", false, 64 "Whether to start peer with chain testchainid") 65 flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint") 66 67 return nodeStartCmd 68 } 69 70 var nodeStartCmd = &cobra.Command{ 71 Use: "start", 72 Short: "Starts the node.", 73 Long: `Starts a node that interacts with the network.`, 74 RunE: func(cmd *cobra.Command, args []string) error { 75 return serve(args) 76 }, 77 } 78 79 //start chaincodes 80 func initSysCCs() { 81 //deploy system chaincodes 82 scc.DeploySysCCs("") 83 logger.Infof("Deployed system chaincodess") 84 } 85 86 func serve(args []string) error { 87 logger.Infof("Starting %s", version.GetInfo()) 88 ledgermgmt.Initialize() 89 // Parameter overrides must be processed before any parameters are 90 // cached. Failures to cache cause the server to terminate immediately. 91 if chaincodeDevMode { 92 logger.Info("Running in chaincode development mode") 93 logger.Info("Disable loading validity system chaincode") 94 95 viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode) 96 97 } 98 99 if err := peer.CacheConfiguration(); err != nil { 100 return err 101 } 102 103 peerEndpoint, err := peer.GetPeerEndpoint() 104 if err != nil { 105 err = fmt.Errorf("Failed to get Peer Endpoint: %s", err) 106 return err 107 } 108 109 listenAddr := viper.GetString("peer.listenAddress") 110 111 secureConfig, err := peer.GetSecureConfig() 112 if err != nil { 113 logger.Fatalf("Error loading secure config for peer (%s)", err) 114 } 115 peerServer, err := peer.CreatePeerServer(listenAddr, secureConfig) 116 if err != nil { 117 logger.Fatalf("Failed to create peer server (%s)", err) 118 } 119 120 if secureConfig.UseTLS { 121 logger.Info("Starting peer with TLS enabled") 122 // set up CA support 123 caSupport := comm.GetCASupport() 124 caSupport.ServerRootCAs = secureConfig.ServerRootCAs 125 } 126 127 //TODO - do we need different SSL material for events ? 128 ehubGrpcServer, err := createEventHubServer(secureConfig) 129 if err != nil { 130 grpclog.Fatalf("Failed to create ehub server: %v", err) 131 } 132 133 // enable the cache of chaincode info 134 ccprovider.EnableCCInfoCache() 135 136 ccSrv, ccEpFunc := createChaincodeServer(peerServer, listenAddr) 137 registerChaincodeSupport(ccSrv.Server(), ccEpFunc) 138 go ccSrv.Start() 139 140 logger.Debugf("Running peer") 141 142 // Register the Admin server 143 pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer()) 144 145 // Register the Endorser server 146 serverEndorser := endorser.NewEndorserServer() 147 pb.RegisterEndorserServer(peerServer.Server(), serverEndorser) 148 149 // Initialize gossip component 150 bootstrap := viper.GetStringSlice("peer.gossip.bootstrap") 151 152 serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize() 153 if err != nil { 154 logger.Panicf("Failed serializing self identity: %v", err) 155 } 156 157 messageCryptoService := peergossip.NewMCS( 158 peer.NewChannelPolicyManagerGetter(), 159 localmsp.NewSigner(), 160 mgmt.NewDeserializersManager()) 161 secAdv := peergossip.NewSecurityAdvisor(mgmt.NewDeserializersManager()) 162 163 // callback function for secure dial options for gossip service 164 secureDialOpts := func() []grpc.DialOption { 165 var dialOpts []grpc.DialOption 166 // set max send/recv msg sizes 167 dialOpts = append(dialOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize()), 168 grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize()))) 169 // set the keepalive options 170 dialOpts = append(dialOpts, comm.ClientKeepaliveOptions()...) 171 172 if comm.TLSEnabled() { 173 tlsCert := peerServer.ServerCertificate() 174 dialOpts = append(dialOpts, grpc.WithTransportCredentials(comm.GetCASupport().GetPeerCredentials(tlsCert))) 175 } else { 176 dialOpts = append(dialOpts, grpc.WithInsecure()) 177 } 178 return dialOpts 179 } 180 err = service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(), 181 messageCryptoService, secAdv, secureDialOpts, bootstrap...) 182 if err != nil { 183 return err 184 } 185 defer service.GetGossipService().Stop() 186 187 //initialize system chaincodes 188 initSysCCs() 189 190 //this brings up all the chains (including testchainid) 191 peer.Initialize(func(cid string) { 192 logger.Debugf("Deploying system CC, for chain <%s>", cid) 193 scc.DeploySysCCs(cid) 194 }) 195 196 logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]", 197 peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address) 198 199 // Start the grpc server. Done in a goroutine so we can deploy the 200 // genesis block if needed. 201 serve := make(chan error) 202 203 sigs := make(chan os.Signal, 1) 204 signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 205 go func() { 206 sig := <-sigs 207 logger.Debugf("sig: %s", sig) 208 serve <- nil 209 }() 210 211 go func() { 212 var grpcErr error 213 if grpcErr = peerServer.Start(); grpcErr != nil { 214 grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr) 215 } else { 216 logger.Info("peer server exited") 217 } 218 serve <- grpcErr 219 }() 220 221 if err := writePid(config.GetPath("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil { 222 return err 223 } 224 225 // Start the event hub server 226 if ehubGrpcServer != nil { 227 go ehubGrpcServer.Start() 228 } 229 230 // Start profiling http endpoint if enabled 231 if viper.GetBool("peer.profile.enabled") { 232 go func() { 233 profileListenAddress := viper.GetString("peer.profile.listenAddress") 234 logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress) 235 if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil { 236 logger.Errorf("Error starting profiler: %s", profileErr) 237 } 238 }() 239 } 240 241 logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]", 242 peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address) 243 244 // set the logging level for specific modules defined via environment 245 // variables or core.yaml 246 overrideLogModules := []string{"msp", "gossip", "ledger", "cauthdsl", "policies", "grpc"} 247 for _, module := range overrideLogModules { 248 err = common.SetLogLevelFromViper(module) 249 if err != nil { 250 logger.Warningf("Error setting log level for module '%s': %s", module, err.Error()) 251 } 252 } 253 254 flogging.SetPeerStartupModulesMap() 255 256 // Block until grpc server exits 257 return <-serve 258 } 259 260 //create a CC listener using peer.chaincodeListenAddress (and if that's not set use peer.peerAddress) 261 func createChaincodeServer(peerServer comm.GRPCServer, peerListenAddress string) (comm.GRPCServer, ccEndpointFunc) { 262 cclistenAddress := viper.GetString("peer.chaincodeListenAddress") 263 264 var srv comm.GRPCServer 265 var ccEpFunc ccEndpointFunc 266 267 //use the chaincode address endpoint function.. 268 //three cases 269 // - peer.chaincodeListenAddress not specied (use peer's server) 270 // - peer.chaincodeListenAddress identical to peer.listenAddress (use peer's server) 271 // - peer.chaincodeListenAddress different and specified (create chaincode server) 272 if cclistenAddress == "" { 273 //...but log a warning 274 logger.Warningf("peer.chaincodeListenAddress is not set, use peer.listenAddress %s", peerListenAddress) 275 276 //we are using peer address, use peer endpoint 277 ccEpFunc = peer.GetPeerEndpoint 278 srv = peerServer 279 } else if cclistenAddress == peerListenAddress { 280 //using peer's endpoint...log a warning 281 logger.Warningf("peer.chaincodeListenAddress is identical to peer.listenAddress %s", cclistenAddress) 282 283 //we are using peer address, use peer endpoint 284 ccEpFunc = peer.GetPeerEndpoint 285 srv = peerServer 286 } else { 287 config, err := peer.GetSecureConfig() 288 if err != nil { 289 panic(err) 290 } 291 292 srv, err = comm.NewGRPCServer(cclistenAddress, config) 293 if err != nil { 294 panic(err) 295 } 296 ccEpFunc = getChaincodeAddressEndpoint 297 } 298 299 return srv, ccEpFunc 300 } 301 302 //NOTE - when we implment JOIN we will no longer pass the chainID as param 303 //The chaincode support will come up without registering system chaincodes 304 //which will be registered only during join phase. 305 func registerChaincodeSupport(grpcServer *grpc.Server, ccEpFunc ccEndpointFunc) { 306 //get user mode 307 userRunsCC := chaincode.IsDevMode() 308 309 //get chaincode startup timeout 310 ccStartupTimeout := viper.GetDuration("chaincode.startuptimeout") 311 if ccStartupTimeout < time.Duration(5)*time.Second { 312 logger.Warningf("Invalid chaincode startup timeout value %s (should be at least 5s); defaulting to 5s", ccStartupTimeout) 313 ccStartupTimeout = time.Duration(5) * time.Second 314 } else { 315 logger.Debugf("Chaincode startup timeout value set to %s", ccStartupTimeout) 316 } 317 318 ccSrv := chaincode.NewChaincodeSupport(ccEpFunc, userRunsCC, ccStartupTimeout) 319 320 //Now that chaincode is initialized, register all system chaincodes. 321 scc.RegisterSysCCs() 322 323 pb.RegisterChaincodeSupportServer(grpcServer, ccSrv) 324 } 325 326 func getChaincodeAddressEndpoint() (*pb.PeerEndpoint, error) { 327 //need this for the ID to create chaincode endpoint 328 peerEndpoint, err := peer.GetPeerEndpoint() 329 if err != nil { 330 return nil, err 331 } 332 333 ccendpoint := viper.GetString("peer.chaincodeListenAddress") 334 if ccendpoint == "" { 335 return nil, fmt.Errorf("peer.chaincodeListenAddress not specified") 336 } 337 338 if _, _, err = net.SplitHostPort(ccendpoint); err != nil { 339 return nil, err 340 } 341 342 return &pb.PeerEndpoint{ 343 Id: peerEndpoint.Id, 344 Address: ccendpoint, 345 }, nil 346 } 347 348 func createEventHubServer(secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) { 349 var lis net.Listener 350 var err error 351 lis, err = net.Listen("tcp", viper.GetString("peer.events.address")) 352 if err != nil { 353 return nil, fmt.Errorf("failed to listen: %v", err) 354 } 355 356 grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig) 357 if err != nil { 358 logger.Errorf("Failed to return new GRPC server: %s", err) 359 return nil, err 360 } 361 ehServer := producer.NewEventsServer( 362 uint(viper.GetInt("peer.events.buffersize")), 363 viper.GetDuration("peer.events.timeout")) 364 365 pb.RegisterEventsServer(grpcServer.Server(), ehServer) 366 return grpcServer, nil 367 } 368 369 func writePid(fileName string, pid int) error { 370 err := os.MkdirAll(filepath.Dir(fileName), 0755) 371 if err != nil { 372 return err 373 } 374 375 buf := strconv.Itoa(pid) 376 if err = ioutil.WriteFile(fileName, []byte(buf), 0644); err != nil { 377 logger.Errorf("Cannot write pid to %s (err:%s)", fileName, err) 378 return err 379 } 380 381 return nil 382 }