github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/peer/node/start.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package node 18 19 import ( 20 "fmt" 21 "net" 22 "net/http" 23 "os" 24 "os/signal" 25 "path/filepath" 26 "strconv" 27 "strings" 28 "syscall" 29 "time" 30 31 genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig" 32 "github.com/hyperledger/fabric/common/configtx/tool/provisional" 33 "github.com/hyperledger/fabric/common/flogging" 34 "github.com/hyperledger/fabric/common/localmsp" 35 "github.com/hyperledger/fabric/common/util" 36 "github.com/hyperledger/fabric/core" 37 "github.com/hyperledger/fabric/core/chaincode" 38 "github.com/hyperledger/fabric/core/comm" 39 "github.com/hyperledger/fabric/core/config" 40 "github.com/hyperledger/fabric/core/endorser" 41 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 42 "github.com/hyperledger/fabric/core/peer" 43 "github.com/hyperledger/fabric/core/scc" 44 "github.com/hyperledger/fabric/events/producer" 45 "github.com/hyperledger/fabric/gossip/service" 46 "github.com/hyperledger/fabric/msp/mgmt" 47 "github.com/hyperledger/fabric/peer/common" 48 "github.com/hyperledger/fabric/peer/gossip/mcs" 49 cb "github.com/hyperledger/fabric/protos/common" 50 pb "github.com/hyperledger/fabric/protos/peer" 51 "github.com/spf13/cobra" 52 "github.com/spf13/viper" 53 "google.golang.org/grpc" 54 "google.golang.org/grpc/grpclog" 55 ) 56 57 var chaincodeDevMode bool 58 var peerDefaultChain bool 59 var orderingEndpoint string 60 61 // XXXDefaultChannelMSPID should not be defined in production code 62 // It should only be referenced in tests. However, it is necessary 63 // to support the 'default chain' setup so temporarilly adding until 64 // this concept can be removed to testing scenarios only 65 const XXXDefaultChannelMSPID = "DEFAULT" 66 67 func startCmd() *cobra.Command { 68 // Set the flags on the node start command. 69 flags := nodeStartCmd.Flags() 70 flags.BoolVarP(&chaincodeDevMode, "peer-chaincodedev", "", false, 71 "Whether peer in chaincode development mode") 72 flags.BoolVarP(&peerDefaultChain, "peer-defaultchain", "", true, 73 "Whether to start peer with chain testchainid") 74 flags.StringVarP(&orderingEndpoint, "orderer", "o", "orderer:7050", "Ordering service endpoint") 75 76 return nodeStartCmd 77 } 78 79 var nodeStartCmd = &cobra.Command{ 80 Use: "start", 81 Short: "Starts the node.", 82 Long: `Starts a node that interacts with the network.`, 83 RunE: func(cmd *cobra.Command, args []string) error { 84 return serve(args) 85 }, 86 } 87 88 //start chaincodes 89 func initSysCCs() { 90 //deploy system chaincodes 91 scc.DeploySysCCs("") 92 logger.Infof("Deployed system chaincodess") 93 } 94 95 func serve(args []string) error { 96 ledgermgmt.Initialize() 97 // Parameter overrides must be processed before any paramaters are 98 // cached. Failures to cache cause the server to terminate immediately. 99 if chaincodeDevMode { 100 logger.Info("Running in chaincode development mode") 101 logger.Info("Disable loading validity system chaincode") 102 103 viper.Set("chaincode.mode", chaincode.DevModeUserRunsChaincode) 104 105 } 106 107 if err := peer.CacheConfiguration(); err != nil { 108 return err 109 } 110 111 peerEndpoint, err := peer.GetPeerEndpoint() 112 if err != nil { 113 err = fmt.Errorf("Failed to get Peer Endpoint: %s", err) 114 return err 115 } 116 117 listenAddr := viper.GetString("peer.listenAddress") 118 119 secureConfig, err := peer.GetSecureConfig() 120 if err != nil { 121 logger.Fatalf("Error loading secure config for peer (%s)", err) 122 } 123 peerServer, err := peer.CreatePeerServer(listenAddr, secureConfig) 124 if err != nil { 125 logger.Fatalf("Failed to create peer server (%s)", err) 126 } 127 128 if secureConfig.UseTLS { 129 logger.Info("Starting peer with TLS enabled") 130 // set up CA support 131 caSupport := comm.GetCASupport() 132 caSupport.ServerRootCAs = secureConfig.ServerRootCAs 133 } 134 135 //TODO - do we need different SSL material for events ? 136 ehubGrpcServer, err := createEventHubServer(secureConfig) 137 if err != nil { 138 grpclog.Fatalf("Failed to create ehub server: %v", err) 139 } 140 141 registerChaincodeSupport(peerServer.Server()) 142 143 logger.Debugf("Running peer") 144 145 // Register the Admin server 146 pb.RegisterAdminServer(peerServer.Server(), core.NewAdminServer()) 147 148 // Register the Endorser server 149 serverEndorser := endorser.NewEndorserServer() 150 pb.RegisterEndorserServer(peerServer.Server(), serverEndorser) 151 152 // Initialize gossip component 153 bootstrap := viper.GetStringSlice("peer.gossip.bootstrap") 154 155 serializedIdentity, err := mgmt.GetLocalSigningIdentityOrPanic().Serialize() 156 if err != nil { 157 logger.Panicf("Failed serializing self identity: %v", err) 158 } 159 160 messageCryptoService := mcs.New( 161 peer.NewChannelPolicyManagerGetter(), 162 localmsp.NewSigner(), 163 mgmt.NewDeserializersManager()) 164 service.InitGossipService(serializedIdentity, peerEndpoint.Address, peerServer.Server(), messageCryptoService, bootstrap...) 165 defer service.GetGossipService().Stop() 166 167 //initialize system chaincodes 168 initSysCCs() 169 170 // Begin startup of default chain 171 if peerDefaultChain { 172 if orderingEndpoint == "" { 173 logger.Panic("No ordering service endpoint provided, please use -o option.") 174 } 175 176 if len(strings.Split(orderingEndpoint, ":")) != 2 { 177 logger.Panicf("Invalid format of ordering service endpoint, %s.", orderingEndpoint) 178 } 179 180 chainID := util.GetTestChainID() 181 182 var block *cb.Block 183 184 func() { 185 defer func() { 186 if err := recover(); err != nil { 187 logger.Fatalf("Peer configured to start with the default test chain, but supporting configuration files did not match. Please ensure that configtx.yaml contains the unmodified SampleSingleMSPSolo profile and that sampleconfig/msp is present.\n%s", err) 188 } 189 }() 190 191 genConf := genesisconfig.Load(genesisconfig.SampleSingleMSPSoloProfile) 192 genConf.Orderer.Addresses = []string{orderingEndpoint} 193 genConf.Application.Organizations[0].Name = XXXDefaultChannelMSPID 194 genConf.Application.Organizations[0].ID = XXXDefaultChannelMSPID 195 block = provisional.New(genConf).GenesisBlockForChannel(chainID) 196 }() 197 198 //this creates testchainid and sets up gossip 199 if err = peer.CreateChainFromBlock(block); err == nil { 200 logger.Infof("create chain [%s]", chainID) 201 scc.DeploySysCCs(chainID) 202 logger.Infof("Deployed system chaincodes on %s", chainID) 203 } else { 204 logger.Errorf("create default chain [%s] failed with %s", chainID, err) 205 } 206 } 207 208 //this brings up all the chains (including testchainid) 209 peer.Initialize(func(cid string) { 210 logger.Debugf("Deploying system CC, for chain <%s>", cid) 211 scc.DeploySysCCs(cid) 212 }) 213 214 logger.Infof("Starting peer with ID=[%s], network ID=[%s], address=[%s]", 215 peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address) 216 217 // Start the grpc server. Done in a goroutine so we can deploy the 218 // genesis block if needed. 219 serve := make(chan error) 220 221 sigs := make(chan os.Signal, 1) 222 signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 223 go func() { 224 sig := <-sigs 225 logger.Debugf("sig: %s", sig) 226 serve <- nil 227 }() 228 229 go func() { 230 var grpcErr error 231 if grpcErr = peerServer.Start(); grpcErr != nil { 232 grpcErr = fmt.Errorf("grpc server exited with error: %s", grpcErr) 233 } else { 234 logger.Info("peer server exited") 235 } 236 serve <- grpcErr 237 }() 238 239 if err := writePid(config.GetPath("peer.fileSystemPath")+"/peer.pid", os.Getpid()); err != nil { 240 return err 241 } 242 243 // Start the event hub server 244 if ehubGrpcServer != nil { 245 go ehubGrpcServer.Start() 246 } 247 248 // Start profiling http endpoint if enabled 249 if viper.GetBool("peer.profile.enabled") { 250 go func() { 251 profileListenAddress := viper.GetString("peer.profile.listenAddress") 252 logger.Infof("Starting profiling server with listenAddress = %s", profileListenAddress) 253 if profileErr := http.ListenAndServe(profileListenAddress, nil); profileErr != nil { 254 logger.Errorf("Error starting profiler: %s", profileErr) 255 } 256 }() 257 } 258 259 logger.Infof("Started peer with ID=[%s], network ID=[%s], address=[%s]", 260 peerEndpoint.Id, viper.GetString("peer.networkId"), peerEndpoint.Address) 261 262 // set the logging level for specific modules defined in core.yaml. 263 // TODO Add calls to set 'ledger' module loggers 264 overrideLogModules := []string{"msp", "gossip"} 265 for _, module := range overrideLogModules { 266 err = common.SetLogLevelFromViper(module) 267 if err != nil { 268 logger.Warningf("Error setting log level for module '%s': %s", module, err.Error()) 269 } 270 } 271 272 flogging.SetPeerStartupModulesMap() 273 274 // Block until grpc server exits 275 return <-serve 276 } 277 278 //NOTE - when we implment JOIN we will no longer pass the chainID as param 279 //The chaincode support will come up without registering system chaincodes 280 //which will be registered only during join phase. 281 func registerChaincodeSupport(grpcServer *grpc.Server) { 282 //get user mode 283 userRunsCC := chaincode.IsDevMode() 284 285 //get chaincode startup timeout 286 tOut, err := strconv.Atoi(viper.GetString("chaincode.startuptimeout")) 287 if err != nil { //what went wrong ? 288 logger.Warning("could not retrieve timeout var...setting to 5secs") 289 tOut = 5000 290 } 291 ccStartupTimeout := time.Duration(tOut) * time.Millisecond 292 293 ccSrv := chaincode.NewChaincodeSupport(peer.GetPeerEndpoint, userRunsCC, ccStartupTimeout) 294 295 //Now that chaincode is initialized, register all system chaincodes. 296 scc.RegisterSysCCs() 297 298 pb.RegisterChaincodeSupportServer(grpcServer, ccSrv) 299 } 300 301 func createEventHubServer(secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) { 302 var lis net.Listener 303 var err error 304 lis, err = net.Listen("tcp", viper.GetString("peer.events.address")) 305 if err != nil { 306 return nil, fmt.Errorf("failed to listen: %v", err) 307 } 308 309 grpcServer, err := comm.NewGRPCServerFromListener(lis, secureConfig) 310 if err != nil { 311 logger.Errorf("Failed to return new GRPC server: %s", err) 312 return nil, err 313 } 314 ehServer := producer.NewEventsServer( 315 uint(viper.GetInt("peer.events.buffersize")), 316 viper.GetInt("peer.events.timeout")) 317 318 pb.RegisterEventsServer(grpcServer.Server(), ehServer) 319 return grpcServer, nil 320 } 321 322 func writePid(fileName string, pid int) error { 323 err := os.MkdirAll(filepath.Dir(fileName), 0755) 324 if err != nil { 325 return err 326 } 327 328 fd, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0644) 329 if err != nil { 330 return err 331 } 332 defer fd.Close() 333 if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil { 334 return fmt.Errorf("can't lock '%s', lock is held", fd.Name()) 335 } 336 337 if _, err := fd.Seek(0, 0); err != nil { 338 return err 339 } 340 341 if err := fd.Truncate(0); err != nil { 342 return err 343 } 344 345 if _, err := fmt.Fprintf(fd, "%d", pid); err != nil { 346 return err 347 } 348 349 if err := fd.Sync(); err != nil { 350 return err 351 } 352 353 if err := syscall.Flock(int(fd.Fd()), syscall.LOCK_UN); err != nil { 354 return fmt.Errorf("can't release lock '%s', lock is held", fd.Name()) 355 } 356 return nil 357 }