Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 39fafe9

Browse files
committed
[FAB-8944] Refresh membership only on config update
Change-Id: Ia919caf72c247ed0df25a658c4575befb119bf09 Signed-off-by: Divyank Katira <Divyank.Katira@securekey.com>
1 parent 4d29ac5 commit 39fafe9

File tree

6 files changed

+46
-45
lines changed

6 files changed

+46
-45
lines changed

pkg/common/providers/fab/channel.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type ChannelConfig interface {
3030
// ChannelCfg contains channel configuration
3131
type ChannelCfg interface {
3232
ID() string
33+
BlockNumber() uint64
3334
MSPs() []*mspCfg.MSPConfig
3435
AnchorPeers() []*OrgAnchorPeer
3536
Orderers() []string

pkg/fab/channel/ledger.go

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,7 @@ func createChaincodeQueryResponse(tpr *fab.TransactionProposalResponse) (*pb.Cha
209209

210210
// QueryConfigBlock returns the current configuration block for the specified channel. If the
211211
// peer doesn't belong to the channel, return error
212-
func (c *Ledger) QueryConfigBlock(reqCtx reqContext.Context, targets []fab.ProposalProcessor, verifier ResponseVerifier) (*common.ConfigEnvelope, error) {
213-
212+
func (c *Ledger) QueryConfigBlock(reqCtx reqContext.Context, targets []fab.ProposalProcessor, verifier ResponseVerifier) (*common.Block, error) {
214213
if len(targets) == 0 {
215214
return nil, errors.New("target(s) required")
216215
}
@@ -226,10 +225,7 @@ func (c *Ledger) QueryConfigBlock(reqCtx reqContext.Context, targets []fab.Propo
226225
return nil, matchErr
227226
}
228227

229-
block, _ := createCommonBlock(tprs[0])
230-
231-
return createConfigEnvelope(block.Data.Data[0])
232-
228+
return createCommonBlock(tprs[0])
233229
}
234230

235231
func collectProposalResponses(tprs []*fab.TransactionProposalResponse) [][]byte {
@@ -286,28 +282,3 @@ func createChaincodeInvokeRequest() fab.ChaincodeInvokeRequest {
286282
}
287283
return cir
288284
}
289-
290-
func createConfigEnvelope(data []byte) (*common.ConfigEnvelope, error) {
291-
292-
envelope := &common.Envelope{}
293-
if err := proto.Unmarshal(data, envelope); err != nil {
294-
return nil, errors.Wrap(err, "unmarshal envelope from config block failed")
295-
}
296-
payload := &common.Payload{}
297-
if err := proto.Unmarshal(envelope.Payload, payload); err != nil {
298-
return nil, errors.Wrap(err, "unmarshal payload from envelope failed")
299-
}
300-
channelHeader := &common.ChannelHeader{}
301-
if err := proto.Unmarshal(payload.Header.ChannelHeader, channelHeader); err != nil {
302-
return nil, errors.Wrap(err, "unmarshal payload from envelope failed")
303-
}
304-
if common.HeaderType(channelHeader.Type) != common.HeaderType_CONFIG {
305-
return nil, errors.New("block must be of type 'CONFIG'")
306-
}
307-
configEnvelope := &common.ConfigEnvelope{}
308-
if err := proto.Unmarshal(payload.Data, configEnvelope); err != nil {
309-
return nil, errors.Wrap(err, "unmarshal config envelope failed")
310-
}
311-
312-
return configEnvelope, nil
313-
}

pkg/fab/channel/membership/reference.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ type Ref struct {
1919
*lazyref.Reference
2020
chConfigRef *lazyref.Reference
2121
context Context
22+
// Note: the following variables are only accessed from Ref.initializer which is synchronized
23+
configBlockNumber uint64
24+
mem fab.ChannelMembership
2225
}
2326

2427
// NewRef returns a new membership reference
@@ -64,7 +67,7 @@ func (ref *Ref) get() (fab.ChannelMembership, error) {
6467

6568
func (ref *Ref) initializer() lazyref.Initializer {
6669
return func() (interface{}, error) {
67-
logger.Debugf("Creating membership...")
70+
logger.Debugf("Initializing membership reference...")
6871

6972
channelCfg, err := ref.chConfigRef.Get()
7073
if err != nil {
@@ -75,12 +78,17 @@ func (ref *Ref) initializer() lazyref.Initializer {
7578
return nil, errors.New("chConfigRef.Get() returned unexpected value ")
7679
}
7780

78-
//TODO: create new membership only if config block number has changed
79-
membership, err := New(ref.context, cfg)
80-
if err != nil {
81-
return nil, err
81+
logger.Debugf("Got config block with number %d have %d", cfg.BlockNumber(), ref.configBlockNumber)
82+
83+
// Membership is refreshed only if we have a newer config block
84+
if ref.mem == nil || cfg.BlockNumber() > ref.configBlockNumber {
85+
logger.Debugf("Creating membership...")
86+
ref.mem, err = New(ref.context, cfg)
87+
if err != nil {
88+
return nil, err
89+
}
8290
}
8391

84-
return membership, nil
92+
return ref.mem, nil
8593
}
8694
}

pkg/fab/chconfig/chconfig.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type ChannelConfig struct {
6363
// ChannelCfg contains channel configuration
6464
type ChannelCfg struct {
6565
id string
66+
blockNumber uint64
6667
msps []*mb.MSPConfig
6768
anchorPeers []*fab.OrgAnchorPeer
6869
orderers []string
@@ -80,6 +81,11 @@ func (cfg *ChannelCfg) ID() string {
8081
return cfg.id
8182
}
8283

84+
// BlockNumber returns the channel config block number
85+
func (cfg *ChannelCfg) BlockNumber() uint64 {
86+
return cfg.blockNumber
87+
}
88+
8389
// MSPs returns msps
8490
func (cfg *ChannelCfg) MSPs() []*mb.MSPConfig {
8591
return cfg.msps
@@ -157,22 +163,22 @@ func (c *ChannelConfig) queryPeers(reqCtx reqContext.Context) (*ChannelCfg, erro
157163
targets = peersToTxnProcessors(c.opts.Targets)
158164
}
159165

160-
configEnvelope, err := l.QueryConfigBlock(reqCtx, targets, &channel.TransactionProposalResponseVerifier{MinResponses: minResponses})
166+
block, err := l.QueryConfigBlock(reqCtx, targets, &channel.TransactionProposalResponseVerifier{MinResponses: minResponses})
161167
if err != nil {
162168
return nil, errors.WithMessage(err, "QueryBlockConfig failed")
163169
}
164170

165-
return extractConfig(c.channelID, configEnvelope)
171+
return extractConfig(c.channelID, block)
166172
}
167173

168174
func (c *ChannelConfig) queryOrderer(reqCtx reqContext.Context) (*ChannelCfg, error) {
169175

170-
configEnvelope, err := resource.LastConfigFromOrderer(reqCtx, c.channelID, c.opts.Orderer)
176+
block, err := resource.LastConfigFromOrderer(reqCtx, c.channelID, c.opts.Orderer)
171177
if err != nil {
172178
return nil, errors.WithMessage(err, "LastConfigFromOrderer failed")
173179
}
174180

175-
return extractConfig(c.channelID, configEnvelope)
181+
return extractConfig(c.channelID, block)
176182
}
177183

178184
func (c *ChannelConfig) getLimitOpts(ctx context.Client) (int, int) {
@@ -251,7 +257,15 @@ func prepareOpts(options ...Option) (Opts, error) {
251257
return opts, nil
252258
}
253259

254-
func extractConfig(channelID string, configEnvelope *common.ConfigEnvelope) (*ChannelCfg, error) {
260+
func extractConfig(channelID string, block *common.Block) (*ChannelCfg, error) {
261+
if block.Header == nil {
262+
return nil, errors.New("expected header in block")
263+
}
264+
265+
configEnvelope, err := resource.CreateConfigEnvelope(block.Data.Data[0])
266+
if err != nil {
267+
return nil, err
268+
}
255269

256270
group := configEnvelope.Config.ChannelGroup
257271

@@ -261,13 +275,14 @@ func extractConfig(channelID string, configEnvelope *common.ConfigEnvelope) (*Ch
261275

262276
config := &ChannelCfg{
263277
id: channelID,
278+
blockNumber: block.Header.Number,
264279
msps: []*mb.MSPConfig{},
265280
anchorPeers: []*fab.OrgAnchorPeer{},
266281
orderers: []string{},
267282
versions: versions,
268283
}
269284

270-
err := loadConfig(config, config.versions.Channel, group, "base", "", true)
285+
err = loadConfig(config, config.versions.Channel, group, "base", "", true)
271286
if err != nil {
272287
return nil, errors.WithMessage(err, "load config items from config group failed")
273288
}

pkg/fab/mocks/mockchconfig.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
// MockChannelCfg contains mock channel configuration
1818
type MockChannelCfg struct {
1919
MockID string
20+
MockBlockNumber uint64
2021
MockMSPs []*msp.MSPConfig
2122
MockAnchorPeers []*fab.OrgAnchorPeer
2223
MockOrderers []string
@@ -34,6 +35,11 @@ func (cfg *MockChannelCfg) ID() string {
3435
return cfg.MockID
3536
}
3637

38+
// BlockNumber returns block number
39+
func (cfg *MockChannelCfg) BlockNumber() uint64 {
40+
return cfg.MockBlockNumber
41+
}
42+
3743
// MSPs returns msps
3844
func (cfg *MockChannelCfg) MSPs() []*msp.MSPConfig {
3945
return cfg.MockMSPs

pkg/fab/resource/resource.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func GenesisBlockFromOrderer(reqCtx reqContext.Context, channelName string, orde
116116

117117
// LastConfigFromOrderer fetches the current configuration block for the specified channel
118118
// from the given orderer
119-
func LastConfigFromOrderer(reqCtx reqContext.Context, channelName string, orderer fab.Orderer) (*common.ConfigEnvelope, error) {
119+
func LastConfigFromOrderer(reqCtx reqContext.Context, channelName string, orderer fab.Orderer) (*common.Block, error) {
120120
logger.Debugf("channelConfig - start for channel %s", channelName)
121121

122122
// Get the newest block
@@ -144,7 +144,7 @@ func LastConfigFromOrderer(reqCtx reqContext.Context, channelName string, ordere
144144
return nil, errors.New("apiconfig block must contain one transaction")
145145
}
146146

147-
return CreateConfigEnvelope(block.Data.Data[0])
147+
return block, nil
148148
}
149149

150150
// JoinChannel sends a join channel proposal to the target peer.

0 commit comments

Comments
 (0)