Skip to content

Commit a56549b

Browse files
committed
Gossip- warn and abort on invalid join channel event
When the MSP-ID of the peer isn't among any of the names of the organizations that are members of a channel, the gossip layer of the peer doesn't see any members of its own org as members of the channel. It doesn't make any sense to have a peer join a channel it isn't a member of, and this scenario confuses the gossip layer of the peer. Therefore, I am adding a check that prevents the gossip layer from joining a channel in such a case, and logs an error. Signed-off-by: Yacov Manevich <[email protected]> Change-Id: Ida456f72b1ab6813fbdcfdb0393b8f0eb7b516e7
1 parent bb5a53f commit a56549b

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

gossip/service/gossip_service.go

+25
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ type gossipServiceImpl struct {
7979
lock sync.RWMutex
8080
msgCrypto identity.Mapper
8181
peerIdentity []byte
82+
secAdv api.SecurityAdvisor
8283
}
8384

8485
// This is an implementation of api.JoinChannelMessage.
@@ -136,6 +137,7 @@ func InitGossipServiceCustomDeliveryFactory(peerIdentity []byte, endpoint string
136137
deliveryFactory: factory,
137138
msgCrypto: idMapper,
138139
peerIdentity: peerIdentity,
140+
secAdv: secAdv,
139141
}
140142
})
141143
}
@@ -176,6 +178,12 @@ func (g *gossipServiceImpl) InitializeChannel(chainID string, committer committe
176178

177179
// configUpdated constructs a joinChannelMessage and sends it to the gossipSvc
178180
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+
}
179187
jcm := &joinChannelMessage{seqNum: config.Sequence(), anchorPeers: []api.AnchorPeer{}}
180188
for orgID, appOrg := range config.Organizations() {
181189
for _, ap := range appOrg.AnchorPeers() {
@@ -221,6 +229,23 @@ func (g *gossipServiceImpl) Stop() {
221229
}
222230
}
223231

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+
224249
type secImpl struct {
225250
identity []byte
226251
}

gossip/service/join_test.go

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
Copyright IBM Corp. 2017 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+
"testing"
21+
"time"
22+
23+
api2 "github.com/hyperledger/fabric/common/configvalues"
24+
"github.com/hyperledger/fabric/gossip/api"
25+
"github.com/hyperledger/fabric/gossip/comm"
26+
"github.com/hyperledger/fabric/gossip/common"
27+
"github.com/hyperledger/fabric/gossip/discovery"
28+
"github.com/hyperledger/fabric/protos/gossip"
29+
"github.com/hyperledger/fabric/protos/peer"
30+
"github.com/stretchr/testify/assert"
31+
"github.com/stretchr/testify/mock"
32+
)
33+
34+
type secAdvMock struct {
35+
}
36+
37+
func (s *secAdvMock) OrgByPeerIdentity(identity api.PeerIdentityType) api.OrgIdentityType {
38+
return api.OrgIdentityType(identity)
39+
}
40+
41+
type gossipMock struct {
42+
mock.Mock
43+
}
44+
45+
func (*gossipMock) Send(msg *gossip.GossipMessage, peers ...*comm.RemotePeer) {
46+
panic("implement me")
47+
}
48+
49+
func (*gossipMock) Peers() []discovery.NetworkMember {
50+
panic("implement me")
51+
}
52+
53+
func (*gossipMock) PeersOfChannel(common.ChainID) []discovery.NetworkMember {
54+
panic("implement me")
55+
}
56+
57+
func (*gossipMock) UpdateMetadata(metadata []byte) {
58+
panic("implement me")
59+
}
60+
61+
func (*gossipMock) UpdateChannelMetadata(metadata []byte, chainID common.ChainID) {
62+
panic("implement me")
63+
}
64+
65+
func (*gossipMock) Gossip(msg *gossip.GossipMessage) {
66+
panic("implement me")
67+
}
68+
69+
func (*gossipMock) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-chan *gossip.GossipMessage, <-chan gossip.ReceivedMessage) {
70+
panic("implement me")
71+
}
72+
73+
func (g *gossipMock) JoinChan(joinMsg api.JoinChannelMessage, chainID common.ChainID) {
74+
g.Called()
75+
}
76+
77+
func (*gossipMock) Stop() {
78+
panic("implement me")
79+
}
80+
81+
type appOrgMock struct {
82+
}
83+
84+
func (*appOrgMock) Name() string {
85+
panic("implement me")
86+
}
87+
88+
func (*appOrgMock) MSPID() string {
89+
panic("implement me")
90+
}
91+
92+
func (*appOrgMock) AnchorPeers() []*peer.AnchorPeer {
93+
return []*peer.AnchorPeer{{Host: "1.2.3.4", Port: 5611}}
94+
}
95+
96+
type configMock struct {
97+
}
98+
99+
func (*configMock) ChainID() string {
100+
return "A"
101+
}
102+
103+
func (*configMock) Organizations() map[string]api2.ApplicationOrg {
104+
return map[string]api2.ApplicationOrg{
105+
"Org0": &appOrgMock{},
106+
}
107+
}
108+
109+
func (*configMock) Sequence() uint64 {
110+
return 0
111+
}
112+
113+
func TestJoinChannelConfig(t *testing.T) {
114+
// Scenarios: The channel we're joining has a single org - Org0
115+
// but our org ID is actually Org0MSP in the negative path
116+
// and Org0 in the positive path
117+
118+
failChan := make(chan struct{}, 1)
119+
g1SvcMock := &gossipMock{}
120+
g1SvcMock.On("JoinChan", mock.Anything).Run(func(_ mock.Arguments) {
121+
failChan <- struct{}{}
122+
})
123+
g1 := &gossipServiceImpl{secAdv: &secAdvMock{}, peerIdentity: api.PeerIdentityType("OrgMSP0"), gossipSvc: g1SvcMock}
124+
g1.configUpdated(&configMock{})
125+
select {
126+
case <-time.After(time.Second):
127+
case <-failChan:
128+
assert.Fail(t, "Joined a badly configured channel")
129+
}
130+
131+
succChan := make(chan struct{}, 1)
132+
g2SvcMock := &gossipMock{}
133+
g2SvcMock.On("JoinChan", mock.Anything).Run(func(_ mock.Arguments) {
134+
succChan <- struct{}{}
135+
})
136+
g2 := &gossipServiceImpl{secAdv: &secAdvMock{}, peerIdentity: api.PeerIdentityType("Org0"), gossipSvc: g2SvcMock}
137+
g2.configUpdated(&configMock{})
138+
select {
139+
case <-time.After(time.Second):
140+
assert.Fail(t, "Didn't join a channel (should have done so within the time period)")
141+
case <-succChan:
142+
143+
}
144+
}

0 commit comments

Comments
 (0)