Skip to content

Commit a4c510b

Browse files
committed
[FAB-1168]: Multichain support for gossip state trans.
Gossip state transfer mechanism should be aware of the relevant chainID, since it has to query for peers which part of given channel to be to initiate state replication of missing blocks. Also while doing peer-to-peer messaging state mechanism should indicate which chain runs required state replication of missing blocks. Current commit extends gossip state transfer to provide support for multi chain functionality. Change-Id: Ie3e3807c8efe8ee0acf323e220ddb14fc0211a33 Signed-off-by: Artem Barger <bartem@il.ibm.com>
1 parent edd6258 commit a4c510b

File tree

7 files changed

+113
-52
lines changed

7 files changed

+113
-52
lines changed

core/committer/noopssinglechain/client.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ import (
3939
var logger *logging.Logger // package-level logger
4040

4141
func init() {
42-
logger = logging.MustGetLogger("committer")
43-
logging.SetLevel(logging.DEBUG, logger.Module)
42+
logger = logging.MustGetLogger("noopssinglechain.client")
4443
}
4544

4645
// DeliverService used to communicate with orderers to obtain
@@ -200,7 +199,7 @@ func (d *DeliverService) readUntilClose() {
200199
// Create payload with a block received
201200
payload := createPayload(seqNum, t.Block)
202201
// Use payload to create gossip message
203-
gossipMsg := createGossipMsg(payload)
202+
gossipMsg := createGossipMsg(d.chainID, payload)
204203
logger.Debug("Creating gossip message", gossipMsg)
205204

206205
logger.Debugf("Adding payload locally, buffer seqNum = [%d], peers number [%d]", seqNum, numberOfPeers)
@@ -221,15 +220,16 @@ func (d *DeliverService) readUntilClose() {
221220
}
222221
}
223222

224-
func createGossipMsg(payload *gossip_proto.Payload) *gossip_proto.GossipMessage {
223+
func createGossipMsg(chainID string, payload *gossip_proto.Payload) *gossip_proto.GossipMessage {
225224
gossipMsg := &gossip_proto.GossipMessage{
226-
Nonce: 0,
225+
Nonce: 0,
226+
Tag: gossip_proto.GossipMessage_CHAN_AND_ORG,
227+
Channel: []byte(chainID),
227228
Content: &gossip_proto.GossipMessage_DataMsg{
228229
DataMsg: &gossip_proto.DataMessage{
229230
Payload: payload,
230231
},
231232
},
232-
Tag: gossip_proto.GossipMessage_EMPTY,
233233
}
234234
return gossipMsg
235235
}

core/util/utils.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ import (
2525
"strings"
2626
"time"
2727

28-
"github.com/hyperledger/fabric/common/metadata"
29-
3028
"github.com/golang/protobuf/ptypes/timestamp"
29+
"github.com/hyperledger/fabric/common/metadata"
3130
"golang.org/x/crypto/sha3"
3231
)
3332

@@ -38,7 +37,7 @@ type alg struct {
3837
const defaultAlg = "sha256"
3938

4039
var availableIDgenAlgs = map[string]alg{
41-
defaultAlg: alg{GenerateIDfromTxSHAHash},
40+
defaultAlg: {GenerateIDfromTxSHAHash},
4241
}
4342

4443
// ComputeCryptoHash should be used in openchain code so that we can change the actual algo used for crypto-hash at one place
@@ -146,12 +145,18 @@ func ArrayToChaincodeArgs(args []string) [][]byte {
146145
}
147146

148147
const testchainid = "**TEST_CHAINID**"
148+
const testorgid = "**TEST_ORGID**"
149149

150150
//GetTestChainID returns the CHAINID constant in use by orderer
151151
func GetTestChainID() string {
152152
return testchainid
153153
}
154154

155+
//GetTestOrgID returns the ORGID constant in use by gossip join message
156+
func GetTestOrgID() string {
157+
return testorgid
158+
}
159+
155160
//GetSysCCVersion returns the version of all system chaincodes
156161
//This needs to be revisited on policies around system chaincode
157162
//"upgrades" from user and relationship with "fabric" upgrade. For

gossip/gossip/gossip_impl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func NewGossipService(conf *Config, s *grpc.Server, secAdvisor api.SecurityAdvis
124124

125125
g.certStore = newCertStore(g.createCertStorePuller(), idMapper, selfIdentity, mcs)
126126

127-
g.logger.SetLevel(logging.WARNING)
127+
g.logger.SetLevel(logging.DEBUG)
128128

129129
go g.start()
130130

gossip/integration/integration.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,22 @@ func newConfig(selfEndpoint string, bootPeers ...string) *gossip.Config {
4141
if err != nil {
4242
panic(err)
4343
}
44+
4445
return &gossip.Config{
45-
BindPort: int(port),
46-
BootstrapPeers: bootPeers,
47-
ID: selfEndpoint,
48-
MaxBlockCountToStore: 100,
49-
MaxPropagationBurstLatency: time.Millisecond * 50,
50-
MaxPropagationBurstSize: 3,
46+
BindPort: int(port),
47+
BootstrapPeers: bootPeers,
48+
ID: selfEndpoint,
49+
MaxBlockCountToStore: 100,
50+
MaxPropagationBurstLatency: time.Duration(10) * time.Millisecond,
51+
MaxPropagationBurstSize: 10,
5152
PropagateIterations: 1,
5253
PropagatePeerNum: 3,
53-
PullInterval: time.Second * 5,
54+
PullInterval: time.Duration(4) * time.Second,
5455
PullPeerNum: 3,
5556
SelfEndpoint: selfEndpoint,
56-
PublishCertPeriod: time.Duration(4) * time.Second,
57-
RequestStateInfoInterval: time.Duration(4) * time.Second,
57+
PublishCertPeriod: 10 * time.Second,
58+
RequestStateInfoInterval: 4 * time.Second,
59+
PublishStateInfoInterval: 4 * time.Second,
5860
}
5961
}
6062

gossip/service/gossip_service.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ package service
1818

1919
import (
2020
"sync"
21+
"time"
2122

2223
peerComm "github.com/hyperledger/fabric/core/comm"
2324
"github.com/hyperledger/fabric/core/committer"
25+
"github.com/hyperledger/fabric/core/util"
2426
"github.com/hyperledger/fabric/gossip/api"
2527
gossipCommon "github.com/hyperledger/fabric/gossip/common"
2628
"github.com/hyperledger/fabric/gossip/gossip"
@@ -40,6 +42,23 @@ var (
4042

4143
type gossipSvc gossip.Gossip
4244

45+
// TODO: This is a temporary join channel struct, to be removed once
46+
// the structure of configuration block in terms of anchor peers will
47+
// be defined and coded. Currently need it to allow the end-to-end
48+
// skeleton to work, having gossip multi chain support.
49+
type joinChanMsg struct {
50+
}
51+
52+
// GetTimestamp returns the timestamp of the message's creation
53+
func (*joinChanMsg) GetTimestamp() time.Time {
54+
return time.Now()
55+
}
56+
57+
// AnchorPeers returns all the anchor peers that are in the channel
58+
func (*joinChanMsg) AnchorPeers() []api.AnchorPeer {
59+
return []api.AnchorPeer{{Cert: api.PeerIdentityType(util.GetTestOrgID())}}
60+
}
61+
4362
// GossipService encapsulates gossip and state capabilities into single interface
4463
type GossipService interface {
4564
gossip.Gossip
@@ -58,11 +77,6 @@ type gossipServiceImpl struct {
5877
lock sync.RWMutex
5978
}
6079

61-
// JoinChan makes the Gossip instance join a channel
62-
func (g *gossipServiceImpl) JoinChan(joinMsg api.JoinChannelMessage, chainID gossipCommon.ChainID) {
63-
// TODO: eventually we'll have only 1 JoinChannel method
64-
}
65-
6680
var logger = logging.MustGetLogger("gossipService")
6781

6882
// InitGossipService initialize gossip service
@@ -99,7 +113,8 @@ func (g *gossipServiceImpl) JoinChannel(commiter committer.Committer, block *com
99113
} else {
100114
// Initialize new state provider for given committer
101115
logger.Debug("Creating state provider for chainID", chainID)
102-
g.chains[chainID] = state.NewGossipStateProvider(g, commiter)
116+
g.chains[chainID] = state.NewGossipStateProvider(chainID, g, commiter)
117+
g.JoinChan(&joinChanMsg{}, gossipCommon.ChainID(chainID))
103118
}
104119

105120
return nil

gossip/state/state.go

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package state
1818

1919
import (
20+
"bytes"
2021
"math/rand"
2122
"sync"
2223
"sync/atomic"
@@ -25,6 +26,7 @@ import (
2526
pb "github.com/golang/protobuf/proto"
2627
"github.com/hyperledger/fabric/core/committer"
2728
"github.com/hyperledger/fabric/gossip/comm"
29+
common2 "github.com/hyperledger/fabric/gossip/common"
2830
"github.com/hyperledger/fabric/gossip/gossip"
2931
"github.com/hyperledger/fabric/gossip/proto"
3032
"github.com/hyperledger/fabric/protos/common"
@@ -58,6 +60,9 @@ const (
5860
// the struct to handle in memory sliding window of
5961
// new ledger block to be acquired by hyper ledger
6062
type GossipStateProviderImpl struct {
63+
// Chain id
64+
chainID string
65+
6166
// The gossiping service
6267
gossip gossip.Gossip
6368

@@ -82,18 +87,19 @@ type GossipStateProviderImpl struct {
8287
}
8388

8489
// NewGossipStateProvider creates initialized instance of gossip state provider
85-
func NewGossipStateProvider(g gossip.Gossip, committer committer.Committer) GossipStateProvider {
90+
func NewGossipStateProvider(chainID string, g gossip.Gossip, committer committer.Committer) GossipStateProvider {
8691
logger, _ := logging.GetLogger("GossipStateProvider")
92+
logging.SetLevel(logging.DEBUG, logger.Module)
8793

8894
gossipChan, _ := g.Accept(func(message interface{}) bool {
8995
// Get only data messages
90-
return message.(*proto.GossipMessage).GetDataMsg() != nil
96+
return message.(*proto.GossipMessage).IsDataMsg() &&
97+
bytes.Equal(message.(*proto.GossipMessage).Channel, []byte(chainID))
9198
}, false)
9299

93100
// Filter message which are only relevant for state transfer
94101
_, commChan := g.Accept(func(message interface{}) bool {
95-
return message.(comm.ReceivedMessage).GetGossipMessage().GetStateRequest() != nil ||
96-
message.(comm.ReceivedMessage).GetGossipMessage().GetStateResponse() != nil
102+
return message.(comm.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage()
97103
}, true)
98104

99105
height, err := committer.LedgerHeight()
@@ -106,6 +112,8 @@ func NewGossipStateProvider(g gossip.Gossip, committer committer.Committer) Goss
106112
}
107113

108114
s := &GossipStateProviderImpl{
115+
chainID: chainID,
116+
109117
// Instance of the gossip
110118
gossip: g,
111119

@@ -131,7 +139,8 @@ func NewGossipStateProvider(g gossip.Gossip, committer committer.Committer) Goss
131139
s.logger.Infof("Updating node metadata information, current ledger sequence is at = %d, next expected block is = %d", state.LedgerHeight, s.payloads.Next())
132140
bytes, err := state.Bytes()
133141
if err == nil {
134-
g.UpdateMetadata(bytes)
142+
s.logger.Debug("[VVV]: Updating gossip metadate state", state)
143+
g.UpdateChannelMetadata(bytes, common2.ChainID(s.chainID))
135144
} else {
136145
s.logger.Errorf("Unable to serialize node meta state, error = %s", err)
137146
}
@@ -182,6 +191,12 @@ func (s *GossipStateProviderImpl) directMessage(msg comm.ReceivedMessage) {
182191
return
183192
}
184193

194+
if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
195+
s.logger.Warning("Received state transfer request for channel",
196+
string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
197+
return
198+
}
199+
185200
incoming := msg.GetGossipMessage()
186201

187202
if incoming.GetStateRequest() != nil {
@@ -208,19 +223,17 @@ func (s *GossipStateProviderImpl) handleStateRequest(msg comm.ReceivedMessage) {
208223
s.logger.Errorf("Could not marshal block: %s", err)
209224
}
210225

211-
if err != nil {
212-
s.logger.Errorf("Could not calculate hash of block: %s", err)
213-
}
214-
215226
response.Payloads = append(response.Payloads, &proto.Payload{
216227
SeqNum: seqNum,
217228
Data: blockBytes,
218-
// TODO: Check hash generation for given block from the ledger
219-
Hash: "",
229+
Hash: string(blocks[0].Header.Hash()),
220230
})
221231
}
222232
// Sending back response with missing blocks
223233
msg.Respond(&proto.GossipMessage{
234+
Nonce: 0,
235+
Tag: proto.GossipMessage_CHAN_OR_ORG,
236+
Channel: []byte(s.chainID),
224237
Content: &proto.GossipMessage_StateResponse{response},
225238
})
226239
}
@@ -251,6 +264,12 @@ func (s *GossipStateProviderImpl) Stop() {
251264

252265
// New message notification/handler
253266
func (s *GossipStateProviderImpl) queueNewMessage(msg *proto.GossipMessage) {
267+
if !bytes.Equal(msg.Channel, []byte(s.chainID)) {
268+
s.logger.Warning("Received state transfer request for channel",
269+
string(msg.Channel), "while expecting channel", s.chainID, "skipping request...")
270+
return
271+
}
272+
254273
dataMsg := msg.GetDataMsg()
255274
if dataMsg != nil {
256275
// Add new payload to ordered set
@@ -302,7 +321,7 @@ func (s *GossipStateProviderImpl) antiEntropy() {
302321
current, _ := s.committer.LedgerHeight()
303322
max, _ := s.committer.LedgerHeight()
304323

305-
for _, p := range s.gossip.Peers() {
324+
for _, p := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) {
306325
if state, err := FromBytes(p.Metadata); err == nil {
307326
if max < state.LedgerHeight {
308327
max = state.LedgerHeight
@@ -328,7 +347,7 @@ func (s *GossipStateProviderImpl) antiEntropy() {
328347
func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) {
329348
var peers []*comm.RemotePeer
330349
// Filtering peers which might have relevant blocks
331-
for _, value := range s.gossip.Peers() {
350+
for _, value := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) {
332351
nodeMetadata, err := FromBytes(value.Metadata)
333352
if err == nil {
334353
if nodeMetadata.LedgerHeight >= end {
@@ -356,13 +375,15 @@ func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64)
356375
request.SeqNums = append(request.SeqNums, uint64(i))
357376
}
358377

359-
s.logger.Debug("[$$$$$$$$$$$$$$$$]: Sending direct request to complete missing blocks, ", request)
378+
s.logger.Debug("[$$$$$$$$$$$$$$$$]: Sending direct request to complete missing blocks, ", request, "for chain", s.chainID)
360379
s.gossip.Send(&proto.GossipMessage{
380+
Nonce: 0,
381+
Tag: proto.GossipMessage_CHAN_OR_ORG,
382+
Channel: []byte(s.chainID),
361383
Content: &proto.GossipMessage_StateRequest{request},
362384
}, peer)
363385
}
364386

365-
366387
// GetBlock return ledger block given its sequence number as a parameter
367388
func (s *GossipStateProviderImpl) GetBlock(index uint64) *common.Block {
368389
// Try to read missing block from the ledger, should return no nil with
@@ -376,6 +397,7 @@ func (s *GossipStateProviderImpl) GetBlock(index uint64) *common.Block {
376397

377398
// AddPayload add new payload into state
378399
func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error {
400+
s.logger.Debug("Adding new payload into the buffer, seqNum = ", payload.SeqNum)
379401
return s.payloads.Push(payload)
380402
}
381403

@@ -390,7 +412,7 @@ func (s *GossipStateProviderImpl) commitBlock(block *common.Block, seqNum uint64
390412
// Decode state to byte array
391413
bytes, err := state.Bytes()
392414
if err == nil {
393-
s.gossip.UpdateMetadata(bytes)
415+
s.gossip.UpdateChannelMetadata(bytes, common2.ChainID(s.chainID))
394416
} else {
395417
s.logger.Errorf("Unable to serialize node meta state, error = %s", err)
396418
}

0 commit comments

Comments
 (0)