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 }