github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/peer/peer.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 peer 18 19 import ( 20 "errors" 21 "fmt" 22 "net" 23 "sync" 24 25 "github.com/golang/protobuf/proto" 26 "github.com/hyperledger/fabric/common/config" 27 "github.com/hyperledger/fabric/common/configtx" 28 configtxapi "github.com/hyperledger/fabric/common/configtx/api" 29 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 30 "github.com/hyperledger/fabric/common/flogging" 31 mockconfigtx "github.com/hyperledger/fabric/common/mocks/configtx" 32 mockpolicies "github.com/hyperledger/fabric/common/mocks/policies" 33 "github.com/hyperledger/fabric/common/policies" 34 "github.com/hyperledger/fabric/core/comm" 35 "github.com/hyperledger/fabric/core/committer" 36 "github.com/hyperledger/fabric/core/committer/txvalidator" 37 "github.com/hyperledger/fabric/core/ledger" 38 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 39 "github.com/hyperledger/fabric/gossip/api" 40 "github.com/hyperledger/fabric/gossip/service" 41 "github.com/hyperledger/fabric/msp" 42 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 43 "github.com/hyperledger/fabric/protos/common" 44 mspprotos "github.com/hyperledger/fabric/protos/msp" 45 pb "github.com/hyperledger/fabric/protos/peer" 46 "github.com/hyperledger/fabric/protos/utils" 47 "github.com/spf13/viper" 48 "google.golang.org/grpc" 49 ) 50 51 var peerLogger = flogging.MustGetLogger("peer") 52 53 var peerServer comm.GRPCServer 54 55 // singleton instance to manage CAs for the peer across channel config changes 56 var rootCASupport = comm.GetCASupport() 57 58 type chainSupport struct { 59 configtxapi.Manager 60 config.Application 61 ledger ledger.PeerLedger 62 } 63 64 func (cs *chainSupport) Ledger() ledger.PeerLedger { 65 return cs.ledger 66 } 67 68 func (cs *chainSupport) GetMSPIDs(cid string) []string { 69 return GetMSPIDs(cid) 70 } 71 72 // chain is a local struct to manage objects in a chain 73 type chain struct { 74 cs *chainSupport 75 cb *common.Block 76 committer committer.Committer 77 } 78 79 // chains is a local map of chainID->chainObject 80 var chains = struct { 81 sync.RWMutex 82 list map[string]*chain 83 }{list: make(map[string]*chain)} 84 85 //MockInitialize resets chains for test env 86 func MockInitialize() { 87 ledgermgmt.InitializeTestEnv() 88 chains.list = nil 89 chains.list = make(map[string]*chain) 90 chainInitializer = func(string) { return } 91 } 92 93 var chainInitializer func(string) 94 95 var mockMSPIDGetter func(string) []string 96 97 func MockSetMSPIDGetter(mspIDGetter func(string) []string) { 98 mockMSPIDGetter = mspIDGetter 99 } 100 101 // Initialize sets up any chains that the peer has from the persistence. This 102 // function should be called at the start up when the ledger and gossip 103 // ready 104 func Initialize(init func(string)) { 105 chainInitializer = init 106 107 var cb *common.Block 108 var ledger ledger.PeerLedger 109 ledgermgmt.Initialize() 110 ledgerIds, err := ledgermgmt.GetLedgerIDs() 111 if err != nil { 112 panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err)) 113 } 114 for _, cid := range ledgerIds { 115 peerLogger.Infof("Loading chain %s", cid) 116 if ledger, err = ledgermgmt.OpenLedger(cid); err != nil { 117 peerLogger.Warningf("Failed to load ledger %s(%s)", cid, err) 118 peerLogger.Debugf("Error while loading ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err) 119 continue 120 } 121 if cb, err = getCurrConfigBlockFromLedger(ledger); err != nil { 122 peerLogger.Warningf("Failed to find config block on ledger %s(%s)", cid, err) 123 peerLogger.Debugf("Error while looking for config block on ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err) 124 continue 125 } 126 // Create a chain if we get a valid ledger with config block 127 if err = createChain(cid, ledger, cb); err != nil { 128 peerLogger.Warningf("Failed to load chain %s(%s)", cid, err) 129 peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err) 130 continue 131 } 132 133 InitChain(cid) 134 } 135 } 136 137 // Take care to initialize chain after peer joined, for example deploys system CCs 138 func InitChain(cid string) { 139 if chainInitializer != nil { 140 // Initialize chaincode, namely deploy system CC 141 peerLogger.Debugf("Init chain %s", cid) 142 chainInitializer(cid) 143 } 144 } 145 146 func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, error) { 147 peerLogger.Debugf("Getting config block") 148 149 // get last block. Last block number is Height-1 150 blockchainInfo, err := ledger.GetBlockchainInfo() 151 if err != nil { 152 return nil, err 153 } 154 lastBlock, err := ledger.GetBlockByNumber(blockchainInfo.Height - 1) 155 if err != nil { 156 return nil, err 157 } 158 159 // get most recent config block location from last block metadata 160 configBlockIndex, err := utils.GetLastConfigIndexFromBlock(lastBlock) 161 if err != nil { 162 return nil, err 163 } 164 165 // get most recent config block 166 configBlock, err := ledger.GetBlockByNumber(configBlockIndex) 167 if err != nil { 168 return nil, err 169 } 170 171 peerLogger.Debugf("Got config block[%d]", configBlockIndex) 172 return configBlock, nil 173 } 174 175 // createChain creates a new chain object and insert it into the chains 176 func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error { 177 178 envelopeConfig, err := utils.ExtractEnvelope(cb, 0) 179 if err != nil { 180 return err 181 } 182 183 configtxInitializer := configtx.NewInitializer() 184 185 gossipEventer := service.GetGossipService().NewConfigEventer() 186 187 gossipCallbackWrapper := func(cm configtxapi.Manager) { 188 ac, ok := configtxInitializer.ApplicationConfig() 189 if !ok { 190 // TODO, handle a missing ApplicationConfig more gracefully 191 ac = nil 192 } 193 gossipEventer.ProcessConfigUpdate(&chainSupport{ 194 Manager: cm, 195 Application: ac, 196 }) 197 service.GetGossipService().SuspectPeers(func(identity api.PeerIdentityType) bool { 198 // TODO: this is a place-holder that would somehow make the MSP layer suspect 199 // that a given certificate is revoked, or its intermediate CA is revoked. 200 // In the meantime, before we have such an ability, we return true in order 201 // to suspect ALL identities in order to validate all of them. 202 return true 203 }) 204 } 205 206 trustedRootsCallbackWrapper := func(cm configtxapi.Manager) { 207 updateTrustedRoots(cm) 208 } 209 210 configtxManager, err := configtx.NewManagerImpl( 211 envelopeConfig, 212 configtxInitializer, 213 []func(cm configtxapi.Manager){gossipCallbackWrapper, trustedRootsCallbackWrapper}, 214 ) 215 if err != nil { 216 return err 217 } 218 219 // TODO remove once all references to mspmgmt are gone from peer code 220 mspmgmt.XXXSetMSPManager(cid, configtxManager.MSPManager()) 221 222 ac, ok := configtxInitializer.ApplicationConfig() 223 if !ok { 224 ac = nil 225 } 226 cs := &chainSupport{ 227 Manager: configtxManager, 228 Application: ac, // TODO, refactor as this is accessible through Manager 229 ledger: ledger, 230 } 231 232 c := committer.NewLedgerCommitterReactive(ledger, txvalidator.NewTxValidator(cs), func(block *common.Block) error { 233 chainID, err := utils.GetChainIDFromBlock(block) 234 if err != nil { 235 return err 236 } 237 return SetCurrConfigBlock(block, chainID) 238 }) 239 240 ordererAddresses := configtxManager.ChannelConfig().OrdererAddresses() 241 if len(ordererAddresses) == 0 { 242 return errors.New("No ordering service endpoint provided in configuration block") 243 } 244 service.GetGossipService().InitializeChannel(cs.ChainID(), c, ordererAddresses) 245 246 chains.Lock() 247 defer chains.Unlock() 248 chains.list[cid] = &chain{ 249 cs: cs, 250 cb: cb, 251 committer: c, 252 } 253 return nil 254 } 255 256 // CreateChainFromBlock creates a new chain from config block 257 func CreateChainFromBlock(cb *common.Block) error { 258 cid, err := utils.GetChainIDFromBlock(cb) 259 if err != nil { 260 return err 261 } 262 263 var l ledger.PeerLedger 264 if l, err = ledgermgmt.CreateLedger(cb); err != nil { 265 return fmt.Errorf("Cannot create ledger from genesis block, due to %s", err) 266 } 267 268 return createChain(cid, l, cb) 269 } 270 271 // MockCreateChain used for creating a ledger for a chain for tests 272 // without havin to join 273 func MockCreateChain(cid string) error { 274 var ledger ledger.PeerLedger 275 var err error 276 277 if ledger = GetLedger(cid); ledger == nil { 278 gb, _ := configtxtest.MakeGenesisBlock(cid) 279 if ledger, err = ledgermgmt.CreateLedger(gb); err != nil { 280 return err 281 } 282 } 283 284 // Here we need to mock also the policy manager 285 // in order for the ACL to be checked 286 initializer := mockconfigtx.Initializer{ 287 Resources: mockconfigtx.Resources{ 288 PolicyManagerVal: &mockpolicies.Manager{ 289 Policy: &mockpolicies.Policy{}, 290 }, 291 }, 292 PolicyProposerVal: &mockconfigtx.PolicyProposer{ 293 Transactional: mockconfigtx.Transactional{}, 294 }, 295 ValueProposerVal: &mockconfigtx.ValueProposer{ 296 Transactional: mockconfigtx.Transactional{}, 297 }, 298 } 299 manager := &mockconfigtx.Manager{ 300 Initializer: initializer, 301 } 302 303 chains.Lock() 304 defer chains.Unlock() 305 306 chains.list[cid] = &chain{ 307 cs: &chainSupport{ 308 Manager: manager, 309 ledger: ledger}, 310 } 311 312 return nil 313 } 314 315 // GetLedger returns the ledger of the chain with chain ID. Note that this 316 // call returns nil if chain cid has not been created. 317 func GetLedger(cid string) ledger.PeerLedger { 318 chains.RLock() 319 defer chains.RUnlock() 320 if c, ok := chains.list[cid]; ok { 321 return c.cs.ledger 322 } 323 return nil 324 } 325 326 // GetPolicyManager returns the policy manager of the chain with chain ID. Note that this 327 // call returns nil if chain cid has not been created. 328 func GetPolicyManager(cid string) policies.Manager { 329 chains.RLock() 330 defer chains.RUnlock() 331 if c, ok := chains.list[cid]; ok { 332 return c.cs.PolicyManager() 333 } 334 return nil 335 } 336 337 // GetCurrConfigBlock returns the cached config block of the specified chain. 338 // Note that this call returns nil if chain cid has not been created. 339 func GetCurrConfigBlock(cid string) *common.Block { 340 chains.RLock() 341 defer chains.RUnlock() 342 if c, ok := chains.list[cid]; ok { 343 return c.cb 344 } 345 return nil 346 } 347 348 // updates the trusted roots for the peer based on updates to channels 349 func updateTrustedRoots(cm configtxapi.Manager) { 350 // this is triggered on per channel basis so first update the roots for the channel 351 peerLogger.Debugf("Updating trusted root authorities for channel %s", cm.ChainID()) 352 var secureConfig comm.SecureServerConfig 353 var err error 354 // only run is TLS is enabled 355 secureConfig, err = GetSecureConfig() 356 if err == nil && secureConfig.UseTLS { 357 buildTrustedRootsForChain(cm) 358 359 // now iterate over all roots for all app and orderer chains 360 trustedRoots := [][]byte{} 361 rootCASupport.RLock() 362 defer rootCASupport.RUnlock() 363 for _, roots := range rootCASupport.AppRootCAsByChain { 364 trustedRoots = append(trustedRoots, roots...) 365 } 366 // also need to append statically configured root certs 367 if len(secureConfig.ClientRootCAs) > 0 { 368 trustedRoots = append(trustedRoots, secureConfig.ClientRootCAs...) 369 } 370 if len(secureConfig.ServerRootCAs) > 0 { 371 trustedRoots = append(trustedRoots, secureConfig.ServerRootCAs...) 372 } 373 374 server := GetPeerServer() 375 // now update the client roots for the peerServer 376 if server != nil { 377 err := server.SetClientRootCAs(trustedRoots) 378 if err != nil { 379 msg := "Failed to update trusted roots for peer from latest config " + 380 "block. This peer may not be able to communicate " + 381 "with members of channel %s (%s)" 382 peerLogger.Warningf(msg, cm.ChainID(), err) 383 } 384 } 385 } 386 } 387 388 // populates the appRootCAs and orderRootCAs maps by getting the 389 // root and intermediate certs for all msps associated with the MSPManager 390 func buildTrustedRootsForChain(cm configtxapi.Manager) { 391 rootCASupport.Lock() 392 defer rootCASupport.Unlock() 393 394 appRootCAs := [][]byte{} 395 ordererRootCAs := [][]byte{} 396 appOrgMSPs := make(map[string]struct{}) 397 398 ac, ok := cm.ApplicationConfig() 399 if ok { 400 //loop through app orgs and build map of MSPIDs 401 for _, appOrg := range ac.Organizations() { 402 appOrgMSPs[appOrg.MSPID()] = struct{}{} 403 } 404 } 405 406 cid := cm.ChainID() 407 peerLogger.Debugf("updating root CAs for channel [%s]", cid) 408 msps, err := cm.MSPManager().GetMSPs() 409 if err != nil { 410 peerLogger.Errorf("Error getting root CAs for channel %s (%s)", cid, err) 411 } 412 if err == nil { 413 for k, v := range msps { 414 // check to see if this is a FABRIC MSP 415 if v.GetType() == msp.FABRIC { 416 for _, root := range v.GetRootCerts() { 417 sid, err := root.Serialize() 418 if err == nil { 419 id := &mspprotos.SerializedIdentity{} 420 err = proto.Unmarshal(sid, id) 421 if err == nil { 422 // check to see of this is an app org MSP 423 if _, ok := appOrgMSPs[k]; ok { 424 peerLogger.Debugf("adding app root CAs for MSP [%s]", k) 425 appRootCAs = append(appRootCAs, id.IdBytes) 426 } else { 427 peerLogger.Debugf("adding orderer root CAs for MSP [%s]", k) 428 ordererRootCAs = append(ordererRootCAs, id.IdBytes) 429 } 430 } 431 } 432 } 433 for _, intermediate := range v.GetIntermediateCerts() { 434 sid, err := intermediate.Serialize() 435 if err == nil { 436 id := &mspprotos.SerializedIdentity{} 437 err = proto.Unmarshal(sid, id) 438 if err == nil { 439 // check to see of this is an app org MSP 440 if _, ok := appOrgMSPs[k]; ok { 441 peerLogger.Debugf("adding app root CAs for MSP [%s]", k) 442 appRootCAs = append(appRootCAs, id.IdBytes) 443 } else { 444 peerLogger.Debugf("adding orderer root CAs for MSP [%s]", k) 445 ordererRootCAs = append(ordererRootCAs, id.IdBytes) 446 } 447 } 448 } 449 } 450 } 451 } 452 rootCASupport.AppRootCAsByChain[cid] = appRootCAs 453 rootCASupport.OrdererRootCAsByChain[cid] = ordererRootCAs 454 } 455 } 456 457 // GetMSPIDs returns the ID of each application MSP defined on this chain 458 func GetMSPIDs(cid string) []string { 459 chains.RLock() 460 defer chains.RUnlock() 461 462 //if mock is set, use it to return MSPIDs 463 //used for tests without a proper join 464 if mockMSPIDGetter != nil { 465 return mockMSPIDGetter(cid) 466 } 467 if c, ok := chains.list[cid]; ok { 468 if c == nil || c.cs == nil { 469 return nil 470 } 471 ac, ok := c.cs.ApplicationConfig() 472 if !ok || ac.Organizations() == nil { 473 return nil 474 } 475 476 orgs := ac.Organizations() 477 toret := make([]string, len(orgs)) 478 i := 0 479 for _, org := range orgs { 480 toret[i] = org.MSPID() 481 i++ 482 } 483 484 return toret 485 } 486 return nil 487 } 488 489 // SetCurrConfigBlock sets the current config block of the specified chain 490 func SetCurrConfigBlock(block *common.Block, cid string) error { 491 chains.Lock() 492 defer chains.Unlock() 493 if c, ok := chains.list[cid]; ok { 494 c.cb = block 495 return nil 496 } 497 return fmt.Errorf("Chain %s doesn't exist on the peer", cid) 498 } 499 500 // NewPeerClientConnection Returns a new grpc.ClientConn to the configured local PEER. 501 func NewPeerClientConnection() (*grpc.ClientConn, error) { 502 return NewPeerClientConnectionWithAddress(viper.GetString("peer.address")) 503 } 504 505 // GetLocalIP returns the non loopback local IP of the host 506 func GetLocalIP() string { 507 addrs, err := net.InterfaceAddrs() 508 if err != nil { 509 return "" 510 } 511 for _, address := range addrs { 512 // check the address type and if it is not a loopback then display it 513 if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 514 if ipnet.IP.To4() != nil { 515 return ipnet.IP.String() 516 } 517 } 518 } 519 return "" 520 } 521 522 // NewPeerClientConnectionWithAddress Returns a new grpc.ClientConn to the configured local PEER. 523 func NewPeerClientConnectionWithAddress(peerAddress string) (*grpc.ClientConn, error) { 524 if comm.TLSEnabled() { 525 return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer()) 526 } 527 return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil) 528 } 529 530 // GetChannelsInfo returns an array with information about all channels for 531 // this peer 532 func GetChannelsInfo() []*pb.ChannelInfo { 533 // array to store metadata for all channels 534 var channelInfoArray []*pb.ChannelInfo 535 536 chains.RLock() 537 defer chains.RUnlock() 538 for key := range chains.list { 539 channelInfo := &pb.ChannelInfo{ChannelId: key} 540 541 // add this specific chaincode's metadata to the array of all chaincodes 542 channelInfoArray = append(channelInfoArray, channelInfo) 543 } 544 545 return channelInfoArray 546 } 547 548 // NewChannelPolicyManagerGetter returns a new instance of ChannelPolicyManagerGetter 549 func NewChannelPolicyManagerGetter() policies.ChannelPolicyManagerGetter { 550 return &channelPolicyManagerGetter{} 551 } 552 553 type channelPolicyManagerGetter struct{} 554 555 func (c *channelPolicyManagerGetter) Manager(channelID string) (policies.Manager, bool) { 556 policyManager := GetPolicyManager(channelID) 557 return policyManager, policyManager != nil 558 } 559 560 // CreatePeerServer creates an instance of comm.GRPCServer 561 // This server is used for peer communications 562 func CreatePeerServer(listenAddress string, 563 secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) { 564 565 var err error 566 peerServer, err = comm.NewGRPCServer(listenAddress, secureConfig) 567 if err != nil { 568 peerLogger.Errorf("Failed to create peer server (%s)", err) 569 return nil, err 570 } 571 return peerServer, nil 572 } 573 574 // GetPeerServer returns the peer server instance 575 func GetPeerServer() comm.GRPCServer { 576 return peerServer 577 }