github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/gossip/service/gossip_service.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 service 18 19 import ( 20 "sync" 21 22 peerComm "github.com/hyperledger/fabric/core/comm" 23 "github.com/hyperledger/fabric/core/committer" 24 "github.com/hyperledger/fabric/core/deliverservice" 25 "github.com/hyperledger/fabric/gossip/api" 26 gossipCommon "github.com/hyperledger/fabric/gossip/common" 27 "github.com/hyperledger/fabric/gossip/gossip" 28 "github.com/hyperledger/fabric/gossip/identity" 29 "github.com/hyperledger/fabric/gossip/integration" 30 "github.com/hyperledger/fabric/gossip/state" 31 "github.com/hyperledger/fabric/gossip/util" 32 "github.com/hyperledger/fabric/peer/gossip/sa" 33 "github.com/hyperledger/fabric/protos/common" 34 proto "github.com/hyperledger/fabric/protos/gossip" 35 "github.com/spf13/viper" 36 "google.golang.org/grpc" 37 ) 38 39 var ( 40 gossipServiceInstance *gossipServiceImpl 41 once sync.Once 42 ) 43 44 type gossipSvc gossip.Gossip 45 46 // GossipService encapsulates gossip and state capabilities into single interface 47 type GossipService interface { 48 gossip.Gossip 49 50 // NewConfigEventer creates a ConfigProcessor which the configtx.Manager can ultimately route config updates to 51 NewConfigEventer() ConfigProcessor 52 // InitializeChannel allocates the state provider and should be invoked once per channel per execution 53 InitializeChannel(chainID string, committer committer.Committer) 54 // GetBlock returns block for given chain 55 GetBlock(chainID string, index uint64) *common.Block 56 // AddPayload appends message payload to for given chain 57 AddPayload(chainID string, payload *proto.Payload) error 58 } 59 60 // DeliveryServiceFactory factory to create and initialize delivery service instance 61 type DeliveryServiceFactory interface { 62 // Returns an instance of delivery client 63 Service(g GossipService) (deliverclient.DeliverService, error) 64 } 65 66 type deliveryFactoryImpl struct { 67 } 68 69 // Returns an instance of delivery client 70 func (*deliveryFactoryImpl) Service(g GossipService) (deliverclient.DeliverService, error) { 71 return deliverclient.NewDeliverService(g) 72 } 73 74 type gossipServiceImpl struct { 75 gossipSvc 76 chains map[string]state.GossipStateProvider 77 deliveryService deliverclient.DeliverService 78 deliveryFactory DeliveryServiceFactory 79 lock sync.RWMutex 80 msgCrypto identity.Mapper 81 peerIdentity []byte 82 secAdv api.SecurityAdvisor 83 } 84 85 // This is an implementation of api.JoinChannelMessage. 86 type joinChannelMessage struct { 87 seqNum uint64 88 anchorPeers []api.AnchorPeer 89 } 90 91 func (jcm *joinChannelMessage) SequenceNumber() uint64 { 92 return jcm.seqNum 93 } 94 95 func (jcm *joinChannelMessage) AnchorPeers() []api.AnchorPeer { 96 return jcm.anchorPeers 97 } 98 99 var logger = util.GetLogger(util.LoggingServiceModule, "") 100 101 // InitGossipService initialize gossip service 102 func InitGossipService(peerIdentity []byte, endpoint string, s *grpc.Server, mcs api.MessageCryptoService, bootPeers ...string) { 103 InitGossipServiceCustomDeliveryFactory(peerIdentity, endpoint, s, &deliveryFactoryImpl{}, mcs, bootPeers...) 104 } 105 106 // InitGossipService initialize gossip service with customize delivery factory 107 // implementation, might be useful for testing and mocking purposes 108 func InitGossipServiceCustomDeliveryFactory(peerIdentity []byte, endpoint string, s *grpc.Server, factory DeliveryServiceFactory, mcs api.MessageCryptoService, bootPeers ...string) { 109 once.Do(func() { 110 logger.Info("Initialize gossip with endpoint", endpoint, "and bootstrap set", bootPeers) 111 dialOpts := []grpc.DialOption{} 112 if peerComm.TLSEnabled() { 113 dialOpts = append(dialOpts, grpc.WithTransportCredentials(peerComm.InitTLSForPeer())) 114 } else { 115 dialOpts = append(dialOpts, grpc.WithInsecure()) 116 } 117 118 secAdv := sa.NewSecurityAdvisor() 119 120 if overrideEndpoint := viper.GetString("peer.gossip.endpoint"); overrideEndpoint != "" { 121 endpoint = overrideEndpoint 122 } 123 124 if viper.GetBool("peer.gossip.ignoreSecurity") { 125 sec := &secImpl{[]byte(endpoint)} 126 mcs = sec 127 secAdv = sec 128 peerIdentity = []byte(endpoint) 129 } 130 131 idMapper := identity.NewIdentityMapper(mcs) 132 133 gossip := integration.NewGossipComponent(peerIdentity, endpoint, s, secAdv, mcs, idMapper, dialOpts, bootPeers...) 134 gossipServiceInstance = &gossipServiceImpl{ 135 gossipSvc: gossip, 136 chains: make(map[string]state.GossipStateProvider), 137 deliveryFactory: factory, 138 msgCrypto: idMapper, 139 peerIdentity: peerIdentity, 140 secAdv: secAdv, 141 } 142 }) 143 } 144 145 // GetGossipService returns an instance of gossip service 146 func GetGossipService() GossipService { 147 return gossipServiceInstance 148 } 149 150 // NewConfigEventer creates a ConfigProcessor which the configtx.Manager can ultimately route config updates to 151 func (g *gossipServiceImpl) NewConfigEventer() ConfigProcessor { 152 return newConfigEventer(g) 153 } 154 155 // InitializeChannel allocates the state provider and should be invoked once per channel per execution 156 func (g *gossipServiceImpl) InitializeChannel(chainID string, committer committer.Committer) { 157 g.lock.Lock() 158 defer g.lock.Unlock() 159 // Initialize new state provider for given committer 160 logger.Debug("Creating state provider for chainID", chainID) 161 g.chains[chainID] = state.NewGossipStateProvider(chainID, g, committer) 162 if g.deliveryService == nil { 163 var err error 164 g.deliveryService, err = g.deliveryFactory.Service(gossipServiceInstance) 165 if err != nil { 166 logger.Warning("Cannot create delivery client, due to", err) 167 } 168 } 169 170 if g.deliveryService != nil { 171 if err := g.deliveryService.JoinChain(chainID, committer); err != nil { 172 logger.Error("Delivery service is not able to join the chain, due to", err) 173 } 174 } else { 175 logger.Warning("Delivery client is down won't be able to pull blocks for chain", chainID) 176 } 177 } 178 179 // configUpdated constructs a joinChannelMessage and sends it to the gossipSvc 180 func (g *gossipServiceImpl) configUpdated(config Config) { 181 myOrg := string(g.secAdv.OrgByPeerIdentity(api.PeerIdentityType(g.peerIdentity))) 182 if !g.amIinChannel(myOrg, config) { 183 logger.Error("Tried joining channel", config.ChainID(), "but our org(", myOrg, "), isn't "+ 184 "among the orgs of the channel:", orgListFromConfig(config), ", aborting.") 185 return 186 } 187 jcm := &joinChannelMessage{seqNum: config.Sequence(), anchorPeers: []api.AnchorPeer{}} 188 for orgID, appOrg := range config.Organizations() { 189 for _, ap := range appOrg.AnchorPeers() { 190 anchorPeer := api.AnchorPeer{ 191 Host: ap.Host, 192 Port: int(ap.Port), 193 OrgID: api.OrgIdentityType(orgID), 194 } 195 jcm.anchorPeers = append(jcm.anchorPeers, anchorPeer) 196 } 197 } 198 199 // Initialize new state provider for given committer 200 logger.Debug("Creating state provider for chainID", config.ChainID()) 201 g.JoinChan(jcm, gossipCommon.ChainID(config.ChainID())) 202 } 203 204 // GetBlock returns block for given chain 205 func (g *gossipServiceImpl) GetBlock(chainID string, index uint64) *common.Block { 206 g.lock.RLock() 207 defer g.lock.RUnlock() 208 return g.chains[chainID].GetBlock(index) 209 } 210 211 // AddPayload appends message payload to for given chain 212 func (g *gossipServiceImpl) AddPayload(chainID string, payload *proto.Payload) error { 213 g.lock.RLock() 214 defer g.lock.RUnlock() 215 return g.chains[chainID].AddPayload(payload) 216 } 217 218 // Stop stops the gossip component 219 func (g *gossipServiceImpl) Stop() { 220 g.lock.Lock() 221 defer g.lock.Unlock() 222 for _, ch := range g.chains { 223 logger.Info("Stopping chain", ch) 224 ch.Stop() 225 } 226 g.gossipSvc.Stop() 227 if g.deliveryService != nil { 228 g.deliveryService.Stop() 229 } 230 } 231 232 func (g *gossipServiceImpl) amIinChannel(myOrg string, config Config) bool { 233 for _, orgName := range orgListFromConfig(config) { 234 if orgName == myOrg { 235 return true 236 } 237 } 238 return false 239 } 240 241 func orgListFromConfig(config Config) []string { 242 var orgList []string 243 for orgName := range config.Organizations() { 244 orgList = append(orgList, orgName) 245 } 246 return orgList 247 } 248 249 type secImpl struct { 250 identity []byte 251 } 252 253 func (*secImpl) OrgByPeerIdentity(api.PeerIdentityType) api.OrgIdentityType { 254 return api.OrgIdentityType("DEFAULT") 255 } 256 257 func (s *secImpl) GetPKIidOfCert(peerIdentity api.PeerIdentityType) gossipCommon.PKIidType { 258 return gossipCommon.PKIidType(peerIdentity) 259 } 260 261 func (s *secImpl) VerifyBlock(chainID gossipCommon.ChainID, signedBlock api.SignedBlock) error { 262 return nil 263 } 264 265 func (s *secImpl) Sign(msg []byte) ([]byte, error) { 266 return msg, nil 267 } 268 269 func (s *secImpl) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error { 270 return nil 271 } 272 273 func (s *secImpl) VerifyByChannel(chainID gossipCommon.ChainID, peerIdentity api.PeerIdentityType, signature, message []byte) error { 274 return nil 275 } 276 277 func (s *secImpl) ValidateIdentity(peerIdentity api.PeerIdentityType) error { 278 return nil 279 }