Skip to content

Commit 0991d53

Browse files
committed
[FAB-3613] JoinChan gossip broken if no anchorPeers
Since https://gerrit.hyperledger.org/r/#/c/7105/ is merged, when a channel is created- no anchor peers are supplied inside. There is a bug in gossip_service.go that if a config with an empty set of anchor peers for each org is given, the channel's membership (list of orgs) is considered empty, and then each peer considers itself alone in the channel. It "recovers" when the update config that does contain the anchor peers comes, but until then - it doesn't consider even peers of its own org as members of the channel because of the bug. I fixed it and added a test that simulates the flow that caused the bug. Change-Id: Ibc71747f2fd56add1361e996c1af89c8c3db479b Signed-off-by: Yacov Manevich <[email protected]>
1 parent 052b81b commit 0991d53

File tree

3 files changed

+58
-12
lines changed

3 files changed

+58
-12
lines changed

gossip/gossip/channel/channel.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ func (gc *gossipChannel) HandleMessage(msg proto.ReceivedMessage) {
384384
return
385385
}
386386
if !gc.IsOrgInChannel(orgID) {
387-
gc.logger.Warning("Point to point message came from", msg.GetConnectionInfo().ID, "but it's not eligible for the channel", string(gc.chainID))
387+
gc.logger.Warning("Point to point message came from", msg.GetConnectionInfo().ID,
388+
", org(", string(orgID), ") but it's not eligible for the channel", string(gc.chainID))
388389
return
389390
}
390391

gossip/service/gossip_service.go

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ func (g *gossipServiceImpl) configUpdated(config Config) {
221221
jcm := &joinChannelMessage{seqNum: config.Sequence(), members2AnchorPeers: map[string][]api.AnchorPeer{}}
222222
for _, appOrg := range config.Organizations() {
223223
logger.Debug(appOrg.MSPID(), "anchor peers:", appOrg.AnchorPeers())
224+
jcm.members2AnchorPeers[appOrg.MSPID()] = []api.AnchorPeer{}
224225
for _, ap := range appOrg.AnchorPeers() {
225226
anchorPeer := api.AnchorPeer{
226227
Host: ap.Host,

gossip/service/join_test.go

+55-11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package service
1818

1919
import (
20+
"sync"
2021
"testing"
2122
"time"
2223

@@ -80,7 +81,7 @@ func (*gossipMock) Accept(acceptor common.MessageAcceptor, passThrough bool) (<-
8081
}
8182

8283
func (g *gossipMock) JoinChan(joinMsg api.JoinChannelMessage, chainID common.ChainID) {
83-
g.Called()
84+
g.Called(joinMsg, chainID)
8485
}
8586

8687
func (*gossipMock) Stop() {
@@ -99,21 +100,20 @@ func (ao *appOrgMock) MSPID() string {
99100
return ao.id
100101
}
101102

102-
func (*appOrgMock) AnchorPeers() []*peer.AnchorPeer {
103-
return []*peer.AnchorPeer{{Host: "1.2.3.4", Port: 5611}}
103+
func (ao *appOrgMock) AnchorPeers() []*peer.AnchorPeer {
104+
return []*peer.AnchorPeer{}
104105
}
105106

106107
type configMock struct {
108+
orgs2AppOrgs map[string]config.ApplicationOrg
107109
}
108110

109111
func (*configMock) ChainID() string {
110112
return "A"
111113
}
112114

113-
func (*configMock) Organizations() map[string]config.ApplicationOrg {
114-
return map[string]config.ApplicationOrg{
115-
"Org0": &appOrgMock{"Org0"},
116-
}
115+
func (c *configMock) Organizations() map[string]config.ApplicationOrg {
116+
return c.orgs2AppOrgs
117117
}
118118

119119
func (*configMock) Sequence() uint64 {
@@ -127,11 +127,15 @@ func TestJoinChannelConfig(t *testing.T) {
127127

128128
failChan := make(chan struct{}, 1)
129129
g1SvcMock := &gossipMock{}
130-
g1SvcMock.On("JoinChan", mock.Anything).Run(func(_ mock.Arguments) {
130+
g1SvcMock.On("JoinChan", mock.Anything, mock.Anything).Run(func(_ mock.Arguments) {
131131
failChan <- struct{}{}
132132
})
133133
g1 := &gossipServiceImpl{secAdv: &secAdvMock{}, peerIdentity: api.PeerIdentityType("OrgMSP0"), gossipSvc: g1SvcMock}
134-
g1.configUpdated(&configMock{})
134+
g1.configUpdated(&configMock{
135+
orgs2AppOrgs: map[string]config.ApplicationOrg{
136+
"Org0": &appOrgMock{id: "Org0"},
137+
},
138+
})
135139
select {
136140
case <-time.After(time.Second):
137141
case <-failChan:
@@ -140,15 +144,55 @@ func TestJoinChannelConfig(t *testing.T) {
140144

141145
succChan := make(chan struct{}, 1)
142146
g2SvcMock := &gossipMock{}
143-
g2SvcMock.On("JoinChan", mock.Anything).Run(func(_ mock.Arguments) {
147+
g2SvcMock.On("JoinChan", mock.Anything, mock.Anything).Run(func(_ mock.Arguments) {
144148
succChan <- struct{}{}
145149
})
146150
g2 := &gossipServiceImpl{secAdv: &secAdvMock{}, peerIdentity: api.PeerIdentityType("Org0"), gossipSvc: g2SvcMock}
147-
g2.configUpdated(&configMock{})
151+
g2.configUpdated(&configMock{
152+
orgs2AppOrgs: map[string]config.ApplicationOrg{
153+
"Org0": &appOrgMock{id: "Org0"},
154+
},
155+
})
148156
select {
149157
case <-time.After(time.Second):
150158
assert.Fail(t, "Didn't join a channel (should have done so within the time period)")
151159
case <-succChan:
152160

153161
}
154162
}
163+
164+
func TestJoinChannelNoAnchorPeers(t *testing.T) {
165+
// Scenario: The channel we're joining has 2 orgs but no anchor peers
166+
// The test ensures that JoinChan is called with a JoinChannelMessage with Members
167+
// that consist of the organizations of the configuration given.
168+
169+
var joinChanCalled sync.WaitGroup
170+
joinChanCalled.Add(1)
171+
gMock := &gossipMock{}
172+
gMock.On("JoinChan", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
173+
defer joinChanCalled.Done()
174+
jcm := args.Get(0).(api.JoinChannelMessage)
175+
channel := args.Get(1).(common.ChainID)
176+
assert.Len(t, jcm.Members(), 2)
177+
assert.Contains(t, jcm.Members(), api.OrgIdentityType("Org0"))
178+
assert.Contains(t, jcm.Members(), api.OrgIdentityType("Org1"))
179+
assert.Equal(t, "A", string(channel))
180+
})
181+
182+
g := &gossipServiceImpl{secAdv: &secAdvMock{}, peerIdentity: api.PeerIdentityType("Org0"), gossipSvc: gMock}
183+
184+
appOrg0 := &appOrgMock{id: "Org0"}
185+
appOrg1 := &appOrgMock{id: "Org1"}
186+
187+
// Make sure the ApplicationOrgs really have no anchor peers
188+
assert.Empty(t, appOrg0.AnchorPeers())
189+
assert.Empty(t, appOrg1.AnchorPeers())
190+
191+
g.configUpdated(&configMock{
192+
orgs2AppOrgs: map[string]config.ApplicationOrg{
193+
"Org0": appOrg0,
194+
"Org1": appOrg1,
195+
},
196+
})
197+
joinChanCalled.Wait()
198+
}

0 commit comments

Comments
 (0)