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  }