diff --git a/gossip/gossip/channel/channel.go b/gossip/gossip/channel/channel.go index 85fe8b5039b..eb0d9515633 100644 --- a/gossip/gossip/channel/channel.go +++ b/gossip/gossip/channel/channel.go @@ -414,6 +414,11 @@ func (gc *gossipChannel) publishStateInfo() { return } + gc.publishSignedStateInfoMessage() + atomic.StoreInt32(&gc.shouldGossipStateInfo, int32(0)) +} + +func (gc *gossipChannel) publishSignedStateInfoMessage() { stateInfoMsg, err := gc.setupSignedStateInfoMessage() if err != nil { gc.logger.Errorf("Failed creating signed state info message: %v", err) @@ -421,7 +426,6 @@ func (gc *gossipChannel) publishStateInfo() { } gc.stateInfoMsgStore.Add(stateInfoMsg) gc.Gossip(stateInfoMsg) - atomic.StoreInt32(&gc.shouldGossipStateInfo, int32(0)) } func (gc *gossipChannel) setupSignedStateInfoMessage() (*protoext.SignedGossipMessage, error) { @@ -928,6 +932,14 @@ func (gc *gossipChannel) UpdateLedgerHeight(height uint64) { // UpdateChaincodes updates the chaincodes the peer publishes // to other peers in the channel func (gc *gossipChannel) UpdateChaincodes(chaincodes []*proto.Chaincode) { + // Always publish the signed state info message regardless. + // We do this because we have to update our data structures + // with the new chaincodes installed/instantiated, to be able to + // respond to discovery requests, no matter if we see other peers + // in the membership, or do not see them. + + defer gc.publishSignedStateInfoMessage() + gc.Lock() defer gc.Unlock() diff --git a/gossip/gossip/channel/channel_test.go b/gossip/gossip/channel/channel_test.go index a2a2e719310..c8fdb38a5e4 100644 --- a/gossip/gossip/channel/channel_test.go +++ b/gossip/gossip/channel/channel_test.go @@ -1132,6 +1132,14 @@ func TestNoGossipOrSigningWhenEmptyMembership(t *testing.T) { time.Sleep(conf.PublishStateInfoInterval * 3) // We haven't signed anything assert.Equal(t, uint32(2), atomic.LoadUint32(&adapter.signCallCount)) + + assert.Empty(t, gc.Self().GetStateInfo().Properties.Chaincodes) + gossipedWG.Add(1) + // Now, update chaincodes and check our chaincode information was indeed updated + gc.UpdateChaincodes([]*proto.Chaincode{{Name: "mycc"}}) + // We should have signed regardless! + assert.Equal(t, uint32(3), atomic.LoadUint32(&adapter.signCallCount)) + assert.Equal(t, "mycc", gc.Self().GetStateInfo().Properties.Chaincodes[0].Name) } func TestChannelPulledBadBlocks(t *testing.T) { diff --git a/integration/discovery/discovery_test.go b/integration/discovery/discovery_test.go index 8523762fb25..932cd86b3eb 100644 --- a/integration/discovery/discovery_test.go +++ b/integration/discovery/discovery_test.go @@ -84,7 +84,6 @@ var _ = Describe("DiscoveryService", func() { orderer = network.Orderer("orderer") network.CreateAndJoinChannel(orderer, "testchannel") - network.UpdateChannelAnchors(orderer, "testchannel") org1Peer0 = network.Peer("Org1", "peer0") org2Peer0 = network.Peer("Org2", "peer0") @@ -102,10 +101,46 @@ var _ = Describe("DiscoveryService", func() { os.RemoveAll(testDir) }) + It("discovers network configuration even without anchor peers present", func() { + chaincodeWhenNoAnchorPeers := nwo.Chaincode{ + Name: "noanchorpeersjustyet", + Version: "1.0", + Path: "github.com/hyperledger/fabric/integration/chaincode/simple/cmd", + Ctor: `{"Args":["init","a","100","b","200"]}`, + Policy: `OR ('Org1MSP.member')`, + } + By("Deploying chaincode before anchor peers are defined in the channel") + nwo.DeployChaincodeLegacy(network, "testchannel", orderer, chaincodeWhenNoAnchorPeers, org1Peer0) + + endorsersForChaincodeBeforeAnchorPeersExist := commands.Endorsers{ + UserCert: network.PeerUserCert(org1Peer0, "User1"), + UserKey: network.PeerUserKey(org1Peer0, "User1"), + MSPID: network.Organization(org1Peer0.Organization).MSPID, + Server: network.PeerAddress(org1Peer0, nwo.ListenPort), + Channel: "testchannel", + Chaincode: chaincodeWhenNoAnchorPeers.Name, + } + discoveryQuery := discoverEndorsers(network, endorsersForChaincodeBeforeAnchorPeersExist) + Eventually(discoveryQuery, network.EventuallyTimeout).Should(BeEquivalentTo( + []ChaincodeEndorsers{ + { + Chaincode: chaincodeWhenNoAnchorPeers.Name, + EndorsersByGroups: map[string][]nwo.DiscoveredPeer{ + "G0": {network.DiscoveredPeer(org1Peer0)}, + }, + Layouts: []*discovery.Layout{ + { + QuantitiesByGroup: map[string]uint32{"G0": 1}, + }, + }, + }, + }, + )) + }) + It("discovers network configuration, endorsers, and peer membership", func() { - // - // discovering network configuration information - // + By("Updating anchor peers") + network.UpdateChannelAnchors(orderer, "testchannel") By("retrieving the configuration") config := commands.Config{