github.com/yimialmonte/fabric@v2.1.1+incompatible/gossip/gossip/chanstate.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package gossip
     8  
     9  import (
    10  	"bytes"
    11  	"sync"
    12  	"sync/atomic"
    13  
    14  	proto "github.com/hyperledger/fabric-protos-go/gossip"
    15  	"github.com/hyperledger/fabric/gossip/api"
    16  	"github.com/hyperledger/fabric/gossip/comm"
    17  	"github.com/hyperledger/fabric/gossip/common"
    18  	"github.com/hyperledger/fabric/gossip/discovery"
    19  	"github.com/hyperledger/fabric/gossip/gossip/channel"
    20  	"github.com/hyperledger/fabric/gossip/metrics"
    21  	"github.com/hyperledger/fabric/gossip/protoext"
    22  )
    23  
    24  type channelState struct {
    25  	stopping int32
    26  	sync.RWMutex
    27  	channels map[string]channel.GossipChannel
    28  	g        *Node
    29  }
    30  
    31  func (cs *channelState) stop() {
    32  	if cs.isStopping() {
    33  		return
    34  	}
    35  	atomic.StoreInt32(&cs.stopping, int32(1))
    36  	cs.Lock()
    37  	defer cs.Unlock()
    38  	for _, gc := range cs.channels {
    39  		gc.Stop()
    40  	}
    41  }
    42  
    43  func (cs *channelState) isStopping() bool {
    44  	return atomic.LoadInt32(&cs.stopping) == int32(1)
    45  }
    46  
    47  func (cs *channelState) lookupChannelForMsg(msg protoext.ReceivedMessage) channel.GossipChannel {
    48  	if protoext.IsStateInfoPullRequestMsg(msg.GetGossipMessage().GossipMessage) {
    49  		sipr := msg.GetGossipMessage().GetStateInfoPullReq()
    50  		mac := sipr.Channel_MAC
    51  		pkiID := msg.GetConnectionInfo().ID
    52  		return cs.getGossipChannelByMAC(mac, pkiID)
    53  	}
    54  	return cs.lookupChannelForGossipMsg(msg.GetGossipMessage().GossipMessage)
    55  }
    56  
    57  func (cs *channelState) lookupChannelForGossipMsg(msg *proto.GossipMessage) channel.GossipChannel {
    58  	if !protoext.IsStateInfoMsg(msg) {
    59  		// If we reached here then the message isn't:
    60  		// 1) StateInfoPullRequest
    61  		// 2) StateInfo
    62  		// Hence, it was already sent to a peer (us) that has proved it knows the channel name, by
    63  		// sending StateInfo messages in the past.
    64  		// Therefore- we use the channel name from the message itself.
    65  		return cs.getGossipChannelByChainID(msg.Channel)
    66  	}
    67  
    68  	// Else, it's a StateInfo message.
    69  	stateInfMsg := msg.GetStateInfo()
    70  	return cs.getGossipChannelByMAC(stateInfMsg.Channel_MAC, stateInfMsg.PkiId)
    71  }
    72  
    73  func (cs *channelState) getGossipChannelByMAC(receivedMAC []byte, pkiID common.PKIidType) channel.GossipChannel {
    74  	// Iterate over the channels, and try to find a channel that the computation
    75  	// of the MAC is equal to the MAC on the message.
    76  	// If it is, then the peer that signed the message knows the name of the channel
    77  	// because its PKI-ID was checked when the message was verified.
    78  	cs.RLock()
    79  	defer cs.RUnlock()
    80  	for chanName, gc := range cs.channels {
    81  		mac := channel.GenerateMAC(pkiID, common.ChannelID(chanName))
    82  		if bytes.Equal(mac, receivedMAC) {
    83  			return gc
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  func (cs *channelState) getGossipChannelByChainID(channelID common.ChannelID) channel.GossipChannel {
    90  	if cs.isStopping() {
    91  		return nil
    92  	}
    93  	cs.RLock()
    94  	defer cs.RUnlock()
    95  	return cs.channels[string(channelID)]
    96  }
    97  
    98  func (cs *channelState) joinChannel(joinMsg api.JoinChannelMessage, channelID common.ChannelID,
    99  	metrics *metrics.MembershipMetrics) {
   100  	if cs.isStopping() {
   101  		return
   102  	}
   103  	cs.Lock()
   104  	defer cs.Unlock()
   105  	if gc, exists := cs.channels[string(channelID)]; !exists {
   106  		pkiID := cs.g.comm.GetPKIid()
   107  		ga := &gossipAdapterImpl{Node: cs.g, Discovery: cs.g.disc}
   108  		gc := channel.NewGossipChannel(pkiID, cs.g.selfOrg, cs.g.mcs, channelID, ga, joinMsg, metrics, nil)
   109  		cs.channels[string(channelID)] = gc
   110  	} else {
   111  		gc.ConfigureChannel(joinMsg)
   112  	}
   113  }
   114  
   115  type gossipAdapterImpl struct {
   116  	*Node
   117  	discovery.Discovery
   118  }
   119  
   120  func (ga *gossipAdapterImpl) GetConf() channel.Config {
   121  	return channel.Config{
   122  		ID:                          ga.conf.ID,
   123  		MaxBlockCountToStore:        ga.conf.MaxBlockCountToStore,
   124  		PublishStateInfoInterval:    ga.conf.PublishStateInfoInterval,
   125  		PullInterval:                ga.conf.PullInterval,
   126  		PullPeerNum:                 ga.conf.PullPeerNum,
   127  		RequestStateInfoInterval:    ga.conf.RequestStateInfoInterval,
   128  		BlockExpirationInterval:     ga.conf.PullInterval * 100,
   129  		StateInfoCacheSweepInterval: ga.conf.PullInterval * 5,
   130  		TimeForMembershipTracker:    ga.conf.TimeForMembershipTracker,
   131  		DigestWaitTime:              ga.conf.DigestWaitTime,
   132  		RequestWaitTime:             ga.conf.RequestWaitTime,
   133  		ResponseWaitTime:            ga.conf.ResponseWaitTime,
   134  		MsgExpirationTimeout:        ga.conf.MsgExpirationTimeout,
   135  	}
   136  }
   137  
   138  func (ga *gossipAdapterImpl) Sign(msg *proto.GossipMessage) (*protoext.SignedGossipMessage, error) {
   139  	signer := func(msg []byte) ([]byte, error) {
   140  		return ga.mcs.Sign(msg)
   141  	}
   142  	sMsg := &protoext.SignedGossipMessage{
   143  		GossipMessage: msg,
   144  	}
   145  	e, err := sMsg.Sign(signer)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	return &protoext.SignedGossipMessage{
   150  		Envelope:      e,
   151  		GossipMessage: msg,
   152  	}, nil
   153  }
   154  
   155  // Gossip gossips a message
   156  func (ga *gossipAdapterImpl) Gossip(msg *protoext.SignedGossipMessage) {
   157  	ga.Node.emitter.Add(&emittedGossipMessage{
   158  		SignedGossipMessage: msg,
   159  		filter: func(_ common.PKIidType) bool {
   160  			return true
   161  		},
   162  	})
   163  }
   164  
   165  // Forward sends message to the next hops
   166  func (ga *gossipAdapterImpl) Forward(msg protoext.ReceivedMessage) {
   167  	ga.Node.emitter.Add(&emittedGossipMessage{
   168  		SignedGossipMessage: msg.GetGossipMessage(),
   169  		filter:              msg.GetConnectionInfo().ID.IsNotSameFilter,
   170  	})
   171  }
   172  
   173  func (ga *gossipAdapterImpl) Send(msg *protoext.SignedGossipMessage, peers ...*comm.RemotePeer) {
   174  	ga.Node.comm.Send(msg, peers...)
   175  }
   176  
   177  // ValidateStateInfoMessage returns error if a message isn't valid
   178  // nil otherwise
   179  func (ga *gossipAdapterImpl) ValidateStateInfoMessage(msg *protoext.SignedGossipMessage) error {
   180  	return ga.Node.validateStateInfoMsg(msg)
   181  }
   182  
   183  // GetOrgOfPeer returns the organization identifier of a certain peer
   184  func (ga *gossipAdapterImpl) GetOrgOfPeer(PKIID common.PKIidType) api.OrgIdentityType {
   185  	return ga.Node.getOrgOfPeer(PKIID)
   186  }
   187  
   188  // GetIdentityByPKIID returns an identity of a peer with a certain
   189  // pkiID, or nil if not found
   190  func (ga *gossipAdapterImpl) GetIdentityByPKIID(pkiID common.PKIidType) api.PeerIdentityType {
   191  	identity, err := ga.idMapper.Get(pkiID)
   192  	if err != nil {
   193  		return nil
   194  	}
   195  	return identity
   196  }