Skip to content

Commit 24cc0ac

Browse files
committed
[FAB-5284] Add ProcessConfigMsg to Process
This patch adds a new method `ProcessConfigMsg` to `Process` interface. This is going to be used by consenter to re-validate config messages if config seq advanced. Potentially, this could also be used by `broadcast` to process ingress config messages, which are currently rejected. Change-Id: I8bfa375dd8354b621f05fae8534f562ca795fc0a Signed-off-by: Jay Guo <guojiannan1101@gmail.com>
1 parent 36d37c4 commit 24cc0ac

File tree

7 files changed

+327
-2
lines changed

7 files changed

+327
-2
lines changed

orderer/common/broadcast/broadcast_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ func (ms *mockSupport) ProcessConfigUpdateMsg(msg *cb.Envelope) (*cb.Envelope, u
136136
return ms.ProcessConfigEnv, ms.ProcessConfigSeq, ms.ProcessErr
137137
}
138138

139+
func (ms *mockSupport) ProcessConfigMsg(msg *cb.Envelope) (*cb.Envelope, uint64, error) {
140+
return ms.ProcessConfigEnv, ms.ProcessConfigSeq, ms.ProcessErr
141+
}
142+
139143
func getMockSupportManager() *mockSupportManager {
140144
return &mockSupportManager{
141145
MsgProcessorVal: &mockSupport{},

orderer/common/msgprocessor/msgprocessor.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,9 @@ type Processor interface {
5858
// return the resulting config message and the configSeq the config was computed from. If the config update message
5959
// is invalid, an error is returned.
6060
ProcessConfigUpdateMsg(env *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error)
61+
62+
// ProcessConfigMsg takes message of type `ORDERER_TX` or `CONFIG`, unpack the ConfigUpdate envelope embedded
63+
// in it, and call `ProcessConfigUpdateMsg` to produce new Config message of the same type as original message.
64+
// This method is used to re-validate and reproduce config message, if it's deemed not to be valid anymore.
65+
ProcessConfigMsg(env *cb.Envelope) (*cb.Envelope, uint64, error)
6166
}

orderer/common/msgprocessor/standardchannel.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,17 @@ func (s *StandardChannel) ProcessConfigUpdateMsg(env *cb.Envelope) (config *cb.E
115115

116116
return config, seq, nil
117117
}
118+
119+
// ProcessConfigMsg takes an envelope of type `HeaderType_CONFIG`, unpacks the `ConfigEnvelope` from it
120+
// extracts the `ConfigUpdate` from `LastUpdate` field, and calls `ProcessConfigUpdateMsg` on it.
121+
func (s *StandardChannel) ProcessConfigMsg(env *cb.Envelope) (config *cb.Envelope, configSeq uint64, err error) {
122+
logger.Debugf("Processing config message for channel %s", s.support.ChainID())
123+
124+
configEnvelope := &cb.ConfigEnvelope{}
125+
_, err = utils.UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, configEnvelope)
126+
if err != nil {
127+
return
128+
}
129+
130+
return s.ProcessConfigUpdateMsg(configEnvelope.LastUpdate)
131+
}

orderer/common/msgprocessor/standardchannel_test.go

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
"github.com/hyperledger/fabric/common/crypto"
1414
cb "github.com/hyperledger/fabric/protos/common"
15-
15+
"github.com/hyperledger/fabric/protos/utils"
1616
"github.com/stretchr/testify/assert"
1717
)
1818

@@ -98,3 +98,49 @@ func TestConfigUpdateMsg(t *testing.T) {
9898
assert.Nil(t, err)
9999
})
100100
}
101+
102+
func TestProcessConfigMsg(t *testing.T) {
103+
t.Run("WrongType", func(t *testing.T) {
104+
ms := &mockSystemChannelFilterSupport{
105+
SequenceVal: 7,
106+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
107+
}
108+
_, _, err := NewStandardChannel(ms, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
109+
Payload: utils.MarshalOrPanic(&cb.Payload{
110+
Header: &cb.Header{
111+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
112+
ChannelId: testChannelID,
113+
Type: int32(cb.HeaderType_ORDERER_TRANSACTION),
114+
}),
115+
},
116+
}),
117+
})
118+
assert.Error(t, err)
119+
})
120+
121+
t.Run("Success", func(t *testing.T) {
122+
ms := &mockSystemChannelFilterSupport{
123+
SequenceVal: 7,
124+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
125+
}
126+
config, cs, err := NewStandardChannel(ms, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
127+
Payload: utils.MarshalOrPanic(&cb.Payload{
128+
Header: &cb.Header{
129+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
130+
ChannelId: testChannelID,
131+
Type: int32(cb.HeaderType_CONFIG),
132+
}),
133+
},
134+
}),
135+
})
136+
assert.NotNil(t, config)
137+
assert.Equal(t, cs, ms.SequenceVal)
138+
assert.Nil(t, err)
139+
hdr, err := utils.ChannelHeader(config)
140+
assert.Equal(
141+
t,
142+
int32(cb.HeaderType_CONFIG),
143+
hdr.Type,
144+
"Expect type of returned envelope to be %d, but got %d", cb.HeaderType_CONFIG, hdr.Type)
145+
})
146+
}

orderer/common/msgprocessor/systemchannel.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,58 @@ func (s *SystemChannel) ProcessConfigUpdateMsg(envConfigUpdate *cb.Envelope) (co
128128
return wrappedOrdererTransaction, s.support.Sequence(), nil
129129
}
130130

131+
// ProcessConfigMsg takes envelope of following two types:
132+
// - `HeaderType_CONFIG`: system channel itself is the target of config, we simply unpack `ConfigUpdate`
133+
// envelope from `LastUpdate` field and call `ProcessConfigUpdateMsg` on the underlying standard channel
134+
// - `HeaderType_ORDERER_TRANSACTION`: it's a channel creation message, we unpack `ConfigUpdate` envelope
135+
// and run `ProcessConfigUpdateMsg` on it
136+
func (s *SystemChannel) ProcessConfigMsg(env *cb.Envelope) (*cb.Envelope, uint64, error) {
137+
payload, err := utils.UnmarshalPayload(env.Payload)
138+
if err != nil {
139+
return nil, 0, err
140+
}
141+
142+
if payload.Header == nil {
143+
return nil, 0, fmt.Errorf("Abort processing config msg because no head was set")
144+
}
145+
146+
if payload.Header.ChannelHeader == nil {
147+
return nil, 0, fmt.Errorf("Abort processing config msg because no channel header was set")
148+
}
149+
150+
chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
151+
if err != nil {
152+
return nil, 0, fmt.Errorf("Abort processing config msg because channel header unmarshalling error: %s", err)
153+
}
154+
155+
switch chdr.Type {
156+
case int32(cb.HeaderType_CONFIG):
157+
configEnvelope := &cb.ConfigEnvelope{}
158+
if err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {
159+
return nil, 0, err
160+
}
161+
162+
return s.StandardChannel.ProcessConfigUpdateMsg(configEnvelope.LastUpdate)
163+
164+
case int32(cb.HeaderType_ORDERER_TRANSACTION):
165+
env, err := utils.UnmarshalEnvelope(payload.Data)
166+
if err != nil {
167+
return nil, 0, fmt.Errorf("Abort processing config msg because payload data unmarshalling error: %s", err)
168+
}
169+
170+
configEnvelope := &cb.ConfigEnvelope{}
171+
_, err = utils.UnmarshalEnvelopeOfType(env, cb.HeaderType_CONFIG, configEnvelope)
172+
if err != nil {
173+
return nil, 0, fmt.Errorf("Abort processing config msg because payload data unmarshalling error: %s", err)
174+
}
175+
176+
return s.ProcessConfigUpdateMsg(configEnvelope.LastUpdate)
177+
178+
default:
179+
return nil, 0, fmt.Errorf("Panic processing config msg due to unexpected envelope type %s", cb.HeaderType_name[chdr.Type])
180+
}
181+
}
182+
131183
// DefaultTemplatorSupport is the subset of the channel config required by the DefaultTemplator.
132184
type DefaultTemplatorSupport interface {
133185
// ConsortiumsConfig returns the ordering system channel's Consortiums config.

orderer/common/msgprocessor/systemchannel_test.go

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/hyperledger/fabric/common/tools/configtxgen/provisional"
2020
cb "github.com/hyperledger/fabric/protos/common"
2121
"github.com/hyperledger/fabric/protos/utils"
22-
2322
"github.com/stretchr/testify/assert"
2423
)
2524

@@ -203,6 +202,200 @@ func TestSystemChannelConfigUpdateMsg(t *testing.T) {
203202
})
204203
}
205204

205+
func TestSystemChannelConfigMsg(t *testing.T) {
206+
t.Run("ConfigMsg", func(t *testing.T) {
207+
t.Run("BadPayloadData", func(t *testing.T) {
208+
mscs := &mockSystemChannelSupport{
209+
NewChannelConfigVal: &mockconfigtx.Manager{
210+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
211+
},
212+
}
213+
ms := &mockSystemChannelFilterSupport{
214+
SequenceVal: 7,
215+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
216+
}
217+
_, _, err := NewSystemChannel(ms, mscs, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
218+
Payload: utils.MarshalOrPanic(&cb.Payload{
219+
Header: &cb.Header{
220+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
221+
ChannelId: testChannelID,
222+
Type: int32(cb.HeaderType_CONFIG),
223+
}),
224+
},
225+
Data: []byte("hello"),
226+
}),
227+
})
228+
assert.Error(t, err)
229+
})
230+
231+
t.Run("Good", func(t *testing.T) {
232+
mscs := &mockSystemChannelSupport{
233+
NewChannelConfigVal: &mockconfigtx.Manager{
234+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
235+
},
236+
}
237+
ms := &mockSystemChannelFilterSupport{
238+
SequenceVal: 7,
239+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
240+
}
241+
config, seq, err := NewSystemChannel(ms, mscs, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
242+
Payload: utils.MarshalOrPanic(&cb.Payload{
243+
Header: &cb.Header{
244+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
245+
ChannelId: testChannelID,
246+
Type: int32(cb.HeaderType_CONFIG),
247+
}),
248+
},
249+
}),
250+
})
251+
assert.Equal(t, seq, ms.SequenceVal)
252+
assert.NotNil(t, config)
253+
assert.Nil(t, err)
254+
hdr, err := utils.ChannelHeader(config)
255+
assert.Equal(
256+
t,
257+
int32(cb.HeaderType_CONFIG),
258+
hdr.Type,
259+
"Expect type of returned envelope to be %d, but got %d", cb.HeaderType_CONFIG, hdr.Type)
260+
})
261+
})
262+
263+
t.Run("OrdererTxMsg", func(t *testing.T) {
264+
t.Run("BadPayloadData", func(t *testing.T) {
265+
mscs := &mockSystemChannelSupport{
266+
NewChannelConfigVal: &mockconfigtx.Manager{
267+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
268+
},
269+
}
270+
ms := &mockSystemChannelFilterSupport{
271+
SequenceVal: 7,
272+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
273+
}
274+
_, _, err := NewSystemChannel(ms, mscs, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
275+
Payload: utils.MarshalOrPanic(&cb.Payload{
276+
Header: &cb.Header{
277+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
278+
ChannelId: testChannelID,
279+
Type: int32(cb.HeaderType_ORDERER_TRANSACTION),
280+
}),
281+
},
282+
Data: []byte("hello"),
283+
}),
284+
})
285+
assert.Error(t, err)
286+
})
287+
288+
t.Run("WrongEnvelopeType", func(t *testing.T) {
289+
mscs := &mockSystemChannelSupport{
290+
NewChannelConfigVal: &mockconfigtx.Manager{
291+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
292+
},
293+
}
294+
ms := &mockSystemChannelFilterSupport{
295+
SequenceVal: 7,
296+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
297+
}
298+
_, _, err := NewSystemChannel(ms, mscs, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
299+
Payload: utils.MarshalOrPanic(&cb.Payload{
300+
Header: &cb.Header{
301+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
302+
ChannelId: testChannelID,
303+
Type: int32(cb.HeaderType_ORDERER_TRANSACTION),
304+
}),
305+
},
306+
Data: utils.MarshalOrPanic(&cb.Envelope{
307+
Payload: utils.MarshalOrPanic(&cb.Payload{
308+
Header: &cb.Header{
309+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
310+
ChannelId: testChannelID,
311+
Type: int32(cb.HeaderType_MESSAGE),
312+
}),
313+
},
314+
}),
315+
}),
316+
}),
317+
})
318+
assert.Error(t, err)
319+
})
320+
321+
t.Run("GoodConfigMsg", func(t *testing.T) {
322+
mscs := &mockSystemChannelSupport{
323+
NewChannelConfigVal: &mockconfigtx.Manager{
324+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
325+
},
326+
}
327+
ms := &mockSystemChannelFilterSupport{
328+
SequenceVal: 7,
329+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
330+
}
331+
config, seq, err := NewSystemChannel(ms, mscs, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
332+
Payload: utils.MarshalOrPanic(&cb.Payload{
333+
Header: &cb.Header{
334+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
335+
ChannelId: testChannelID,
336+
Type: int32(cb.HeaderType_ORDERER_TRANSACTION),
337+
}),
338+
},
339+
Data: utils.MarshalOrPanic(&cb.Envelope{
340+
Payload: utils.MarshalOrPanic(&cb.Payload{
341+
Header: &cb.Header{
342+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
343+
ChannelId: testChannelID,
344+
Type: int32(cb.HeaderType_CONFIG),
345+
}),
346+
},
347+
Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{
348+
LastUpdate: &cb.Envelope{
349+
Payload: utils.MarshalOrPanic(&cb.Payload{
350+
Header: &cb.Header{
351+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
352+
ChannelId: testChannelID + "different",
353+
Type: int32(cb.HeaderType_CONFIG_UPDATE),
354+
}),
355+
},
356+
}),
357+
},
358+
}),
359+
}),
360+
}),
361+
}),
362+
})
363+
assert.Equal(t, seq, ms.SequenceVal)
364+
assert.NotNil(t, config)
365+
assert.Nil(t, err)
366+
hdr, err := utils.ChannelHeader(config)
367+
assert.Equal(
368+
t,
369+
int32(cb.HeaderType_ORDERER_TRANSACTION),
370+
hdr.Type,
371+
"Expect type of returned envelope to be %d, but got %d", cb.HeaderType_ORDERER_TRANSACTION, hdr.Type)
372+
})
373+
})
374+
375+
t.Run("OtherMsgType", func(t *testing.T) {
376+
mscs := &mockSystemChannelSupport{
377+
NewChannelConfigVal: &mockconfigtx.Manager{
378+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
379+
},
380+
}
381+
ms := &mockSystemChannelFilterSupport{
382+
SequenceVal: 7,
383+
ProposeConfigUpdateVal: &cb.ConfigEnvelope{},
384+
}
385+
_, _, err := NewSystemChannel(ms, mscs, NewRuleSet([]Rule{AcceptRule})).ProcessConfigMsg(&cb.Envelope{
386+
Payload: utils.MarshalOrPanic(&cb.Payload{
387+
Header: &cb.Header{
388+
ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
389+
ChannelId: testChannelID,
390+
Type: int32(cb.HeaderType_MESSAGE),
391+
}),
392+
},
393+
}),
394+
})
395+
assert.Error(t, err)
396+
})
397+
}
398+
206399
type mockDefaultTemplatorSupport struct {
207400
channelconfig.Resources
208401
}

orderer/mocks/common/multichannel/multichannel.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ type ConsenterSupport struct {
5656
// ProcessConfigUpdateMsgErr is returned as the error for ProcessConfigUpdateMsg
5757
ProcessConfigUpdateMsgErr error
5858

59+
// ProcessConfigMsgVal is returned as the error for ProcessConfigMsg
60+
ProcessConfigMsgVal *cb.Envelope
61+
62+
// ProcessConfigMsgErr is returned by ProcessConfigMsg
63+
ProcessConfigMsgErr error
64+
5965
// SequenceVal is returned by Sequence
6066
SequenceVal uint64
6167
}
@@ -131,6 +137,11 @@ func (mcs *ConsenterSupport) ProcessConfigUpdateMsg(env *cb.Envelope) (config *c
131137
return mcs.ProcessConfigUpdateMsgVal, mcs.ConfigSeqVal, mcs.ProcessConfigUpdateMsgErr
132138
}
133139

140+
// ProcessConfigMsg returns ProcessConfigMsgVal, ConfigSeqVal, ProcessConfigMsgErr
141+
func (mcs *ConsenterSupport) ProcessConfigMsg(env *cb.Envelope) (*cb.Envelope, uint64, error) {
142+
return mcs.ProcessConfigMsgVal, mcs.ConfigSeqVal, mcs.ProcessConfigMsgErr
143+
}
144+
134145
// Sequence returns SequenceVal
135146
func (mcs *ConsenterSupport) Sequence() uint64 {
136147
return mcs.SequenceVal

0 commit comments

Comments
 (0)