Skip to content

Commit 9f87f84

Browse files
committed
Fix peer panic at initiate proposal with no MSPs
This change ensures the peer doesn't panic when a proposal is initiated and no MSPs are defined. This is due to the code checking the outer MSPConfigHandler structure for nil instead of the MSPManager interface inside it. It also updates protos/utils/proputils_test.go to a blackbox test to avoid an import cycle. https://jira.hyperledger.org/browse/FAB-2536 Change-Id: I61b0366a127b4d90e2b187d2dc0e91a5541a243c Signed-off-by: Will Lahti <[email protected]>
1 parent b3544b3 commit 9f87f84

File tree

3 files changed

+115
-38
lines changed

3 files changed

+115
-38
lines changed

msp/mgmt/mgmt.go

+22-2
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ limitations under the License.
1717
package mgmt
1818

1919
import (
20+
"reflect"
2021
"sync"
2122

2223
"errors"
2324

2425
"github.com/hyperledger/fabric/bccsp/factory"
26+
configvaluesmsp "github.com/hyperledger/fabric/common/configvalues/msp"
2527
"github.com/hyperledger/fabric/msp"
2628
"github.com/op/go-logging"
2729
)
@@ -62,9 +64,27 @@ func GetManagerForChain(chainID string) msp.MSPManager {
6264
mspMgr = msp.NewMSPManager()
6365
mspMap[chainID] = mspMgr
6466
} else {
65-
mspLogger.Debugf("Returning existing manager for chain %s", chainID)
67+
switch mgr := mspMgr.(type) {
68+
case *configvaluesmsp.MSPConfigHandler:
69+
// check for nil MSPManager interface as it can exist but not be
70+
// instantiated
71+
if mgr.MSPManager == nil {
72+
mspLogger.Debugf("MSPManager is not instantiated; no MSPs are defined for this channel.")
73+
// return nil so the MSPManager methods cannot be accidentally called,
74+
// which would result in a panic
75+
return nil
76+
}
77+
default:
78+
// check for internal mspManagerImpl type. if a different type is found,
79+
// it's because a developer has added a new type that implements the
80+
// MSPManager interface and should add a case to the logic above to handle
81+
// it.
82+
if reflect.TypeOf(mgr).Elem().Name() != "mspManagerImpl" {
83+
panic("Found unexpected MSPManager type.")
84+
}
85+
}
86+
mspLogger.Debugf("Returning existing manager for channel '%s'", chainID)
6687
}
67-
6888
return mspMgr
6989
}
7090

msp/mgmt/mgmt_test.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package mgmt
18+
19+
import (
20+
"testing"
21+
22+
configvaluesmsp "github.com/hyperledger/fabric/common/configvalues/msp"
23+
"github.com/hyperledger/fabric/msp"
24+
)
25+
26+
func TestGetManagerForChains(t *testing.T) {
27+
// MSPManager for channel does not exist prior to this call
28+
mspMgr1 := GetManagerForChain("test")
29+
// ensure MSPManager is set
30+
if mspMgr1 == nil {
31+
t.FailNow()
32+
}
33+
34+
// MSPManager for channel now exists
35+
mspMgr2 := GetManagerForChain("test")
36+
// ensure MSPManager returned matches the first result
37+
if mspMgr2 != mspMgr1 {
38+
t.FailNow()
39+
}
40+
}
41+
42+
func TestGetManagerForChains_usingMSPConfigHandlers(t *testing.T) {
43+
XXXSetMSPManager("test", &configvaluesmsp.MSPConfigHandler{MSPManager: nil})
44+
msp1 := GetManagerForChain("test")
45+
// return value should be nil because the MSPManager was not initialized
46+
if msp1 != nil {
47+
t.Fatalf("MSPManager should have been nil")
48+
}
49+
50+
XXXSetMSPManager("foo", &configvaluesmsp.MSPConfigHandler{MSPManager: msp.NewMSPManager()})
51+
msp2 := GetManagerForChain("foo")
52+
// return value should be set because the MSPManager was initialized
53+
if msp2 == nil {
54+
t.FailNow()
55+
}
56+
}

protos/utils/proputils_test.go

+37-36
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package utils
17+
package utils_test
1818

1919
import (
2020
"bytes"
@@ -34,6 +34,7 @@ import (
3434
"github.com/hyperledger/fabric/msp/mgmt/testtools"
3535
"github.com/hyperledger/fabric/protos/common"
3636
pb "github.com/hyperledger/fabric/protos/peer"
37+
"github.com/hyperledger/fabric/protos/utils"
3738
"github.com/stretchr/testify/assert"
3839
)
3940

@@ -47,7 +48,7 @@ func createCIS() *pb.ChaincodeInvocationSpec {
4748

4849
func TestProposal(t *testing.T) {
4950
// create a proposal from a ChaincodeInvocationSpec
50-
prop, _, err := CreateChaincodeProposalWithTransient(
51+
prop, _, err := utils.CreateChaincodeProposalWithTransient(
5152
common.HeaderType_ENDORSER_TRANSACTION,
5253
util.GetTestChainID(), createCIS(),
5354
[]byte("creator"),
@@ -58,14 +59,14 @@ func TestProposal(t *testing.T) {
5859
}
5960

6061
// serialize the proposal
61-
pBytes, err := GetBytesProposal(prop)
62+
pBytes, err := utils.GetBytesProposal(prop)
6263
if err != nil {
6364
t.Fatalf("Could not serialize the chaincode proposal, err %s\n", err)
6465
return
6566
}
6667

6768
// deserialize it and expect it to be the same
68-
propBack, err := GetProposal(pBytes)
69+
propBack, err := utils.GetProposal(pBytes)
6970
if err != nil {
7071
t.Fatalf("Could not deserialize the chaincode proposal, err %s\n", err)
7172
return
@@ -76,27 +77,27 @@ func TestProposal(t *testing.T) {
7677
}
7778

7879
// get back the header
79-
hdr, err := GetHeader(prop.Header)
80+
hdr, err := utils.GetHeader(prop.Header)
8081
if err != nil {
8182
t.Fatalf("Could not extract the header from the proposal, err %s\n", err)
8283
}
8384

84-
hdrBytes, err := GetBytesHeader(hdr)
85+
hdrBytes, err := utils.GetBytesHeader(hdr)
8586
if err != nil {
8687
t.Fatalf("Could not marshal the header, err %s\n", err)
8788
}
8889

89-
hdr, err = GetHeader(hdrBytes)
90+
hdr, err = utils.GetHeader(hdrBytes)
9091
if err != nil {
9192
t.Fatalf("Could not unmarshal the header, err %s\n", err)
9293
}
9394

94-
chdr, err := UnmarshalChannelHeader(hdr.ChannelHeader)
95+
chdr, err := utils.UnmarshalChannelHeader(hdr.ChannelHeader)
9596
if err != nil {
9697
t.Fatalf("Could not unmarshal channel header, err %s", err)
9798
}
9899

99-
shdr, err := GetSignatureHeader(hdr.SignatureHeader)
100+
shdr, err := utils.GetSignatureHeader(hdr.SignatureHeader)
100101
if err != nil {
101102
t.Fatalf("Could not unmarshal signature header, err %s", err)
102103
}
@@ -110,7 +111,7 @@ func TestProposal(t *testing.T) {
110111
}
111112

112113
// get back the header extension
113-
hdrExt, err := GetChaincodeHeaderExtension(hdr)
114+
hdrExt, err := utils.GetChaincodeHeaderExtension(hdr)
114115
if err != nil {
115116
t.Fatalf("Could not extract the header extensions from the proposal, err %s\n", err)
116117
return
@@ -123,7 +124,7 @@ func TestProposal(t *testing.T) {
123124
}
124125

125126
// get back the ChaincodeInvocationSpec
126-
cis, err := GetChaincodeInvocationSpec(prop)
127+
cis, err := utils.GetChaincodeInvocationSpec(prop)
127128
if err != nil {
128129
t.Fatalf("Could not extract chaincode invocation spec from header, err %s\n", err)
129130
return
@@ -139,7 +140,7 @@ func TestProposal(t *testing.T) {
139140
return
140141
}
141142

142-
creator, transient, err := GetChaincodeProposalContext(prop)
143+
creator, transient, err := utils.GetChaincodeProposalContext(prop)
143144
if err != nil {
144145
t.Fatalf("Failed getting chaincode proposal context [%s]", err)
145146
}
@@ -164,28 +165,28 @@ func TestProposalResponse(t *testing.T) {
164165
pHashBytes := []byte("proposal_hash")
165166
pResponse := &pb.Response{Status: 200}
166167
results := []byte("results")
167-
eventBytes, err := GetBytesChaincodeEvent(events)
168+
eventBytes, err := utils.GetBytesChaincodeEvent(events)
168169
if err != nil {
169170
t.Fatalf("Failure while marshalling the ProposalResponsePayload")
170171
return
171172
}
172173

173174
// get the bytes of the ProposalResponsePayload
174-
prpBytes, err := GetBytesProposalResponsePayload(pHashBytes, pResponse, results, eventBytes)
175+
prpBytes, err := utils.GetBytesProposalResponsePayload(pHashBytes, pResponse, results, eventBytes)
175176
if err != nil {
176177
t.Fatalf("Failure while marshalling the ProposalResponsePayload")
177178
return
178179
}
179180

180181
// get the ProposalResponsePayload message
181-
prp, err := GetProposalResponsePayload(prpBytes)
182+
prp, err := utils.GetProposalResponsePayload(prpBytes)
182183
if err != nil {
183184
t.Fatalf("Failure while unmarshalling the ProposalResponsePayload")
184185
return
185186
}
186187

187188
// get the ChaincodeAction message
188-
act, err := GetChaincodeAction(prp.Extension)
189+
act, err := utils.GetChaincodeAction(prp.Extension)
189190
if err != nil {
190191
t.Fatalf("Failure while unmarshalling the ChaincodeAction")
191192
return
@@ -197,7 +198,7 @@ func TestProposalResponse(t *testing.T) {
197198
return
198199
}
199200

200-
event, err := GetChaincodeEvents(act.Events)
201+
event, err := utils.GetChaincodeEvents(act.Events)
201202
if err != nil {
202203
t.Fatalf("Failure while unmarshalling the ChainCodeEvents")
203204
return
@@ -216,14 +217,14 @@ func TestProposalResponse(t *testing.T) {
216217
Response: &pb.Response{Status: 200, Message: "OK"}}
217218

218219
// create a proposal response
219-
prBytes, err := GetBytesProposalResponse(pr)
220+
prBytes, err := utils.GetBytesProposalResponse(pr)
220221
if err != nil {
221222
t.Fatalf("Failure while marshalling the ProposalResponse")
222223
return
223224
}
224225

225226
// get the proposal response message back
226-
prBack, err := GetProposalResponse(prBytes)
227+
prBack, err := utils.GetProposalResponse(prBytes)
227228
if err != nil {
228229
t.Fatalf("Failure while unmarshalling the ProposalResponse")
229230
return
@@ -241,7 +242,7 @@ func TestProposalResponse(t *testing.T) {
241242

242243
func TestEnvelope(t *testing.T) {
243244
// create a proposal from a ChaincodeInvocationSpec
244-
prop, _, err := CreateChaincodeProposal(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), createCIS(), signerSerialized)
245+
prop, _, err := utils.CreateChaincodeProposal(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), createCIS(), signerSerialized)
245246
if err != nil {
246247
t.Fatalf("Could not create chaincode proposal, err %s\n", err)
247248
return
@@ -250,31 +251,31 @@ func TestEnvelope(t *testing.T) {
250251
response := &pb.Response{Status: 200, Payload: []byte("payload")}
251252
result := []byte("res")
252253

253-
presp, err := CreateProposalResponse(prop.Header, prop.Payload, response, result, nil, nil, signer)
254+
presp, err := utils.CreateProposalResponse(prop.Header, prop.Payload, response, result, nil, nil, signer)
254255
if err != nil {
255256
t.Fatalf("Could not create proposal response, err %s\n", err)
256257
return
257258
}
258259

259-
tx, err := CreateSignedTx(prop, signer, presp)
260+
tx, err := utils.CreateSignedTx(prop, signer, presp)
260261
if err != nil {
261262
t.Fatalf("Could not create signed tx, err %s\n", err)
262263
return
263264
}
264265

265-
envBytes, err := GetBytesEnvelope(tx)
266+
envBytes, err := utils.GetBytesEnvelope(tx)
266267
if err != nil {
267268
t.Fatalf("Could not marshal envelope, err %s\n", err)
268269
return
269270
}
270271

271-
tx, err = GetEnvelopeFromBlock(envBytes)
272+
tx, err = utils.GetEnvelopeFromBlock(envBytes)
272273
if err != nil {
273274
t.Fatalf("Could not unmarshal envelope, err %s\n", err)
274275
return
275276
}
276277

277-
act2, err := GetActionFromEnvelope(envBytes)
278+
act2, err := utils.GetActionFromEnvelope(envBytes)
278279
if err != nil {
279280
t.Fatalf("Could not extract actions from envelop, err %s\n", err)
280281
return
@@ -294,19 +295,19 @@ func TestEnvelope(t *testing.T) {
294295
return
295296
}
296297

297-
txpayl, err := GetPayload(tx)
298+
txpayl, err := utils.GetPayload(tx)
298299
if err != nil {
299300
t.Fatalf("Could not unmarshal payload, err %s\n", err)
300301
return
301302
}
302303

303-
tx2, err := GetTransaction(txpayl.Data)
304+
tx2, err := utils.GetTransaction(txpayl.Data)
304305
if err != nil {
305306
t.Fatalf("Could not unmarshal Transaction, err %s\n", err)
306307
return
307308
}
308309

309-
sh, err := GetSignatureHeader(tx2.Actions[0].Header)
310+
sh, err := utils.GetSignatureHeader(tx2.Actions[0].Header)
310311
if err != nil {
311312
t.Fatalf("Could not unmarshal SignatureHeader, err %s\n", err)
312313
return
@@ -317,20 +318,20 @@ func TestEnvelope(t *testing.T) {
317318
return
318319
}
319320

320-
cap, err := GetChaincodeActionPayload(tx2.Actions[0].Payload)
321+
cap, err := utils.GetChaincodeActionPayload(tx2.Actions[0].Payload)
321322
if err != nil {
322323
t.Fatalf("Could not unmarshal ChaincodeActionPayload, err %s\n", err)
323324
return
324325
}
325326
assert.NotNil(t, cap)
326327

327-
prp, err := GetProposalResponsePayload(cap.Action.ProposalResponsePayload)
328+
prp, err := utils.GetProposalResponsePayload(cap.Action.ProposalResponsePayload)
328329
if err != nil {
329330
t.Fatalf("Could not unmarshal ProposalResponsePayload, err %s\n", err)
330331
return
331332
}
332333

333-
ca, err := GetChaincodeAction(prp.Extension)
334+
ca, err := utils.GetChaincodeAction(prp.Extension)
334335
if err != nil {
335336
t.Fatalf("Could not unmarshal ChaincodeAction, err %s\n", err)
336337
return
@@ -355,19 +356,19 @@ func TestProposalTxID(t *testing.T) {
355356
nonce := []byte{1}
356357
creator := []byte{2}
357358

358-
txid, err := ComputeProposalTxID(nonce, creator)
359+
txid, err := utils.ComputeProposalTxID(nonce, creator)
359360
assert.NotEmpty(t, txid, "TxID cannot be empty.")
360361
assert.NoError(t, err, "Failed computing txID")
361-
assert.Nil(t, CheckProposalTxID(txid, nonce, creator))
362-
assert.Error(t, CheckProposalTxID("", nonce, creator))
362+
assert.Nil(t, utils.CheckProposalTxID(txid, nonce, creator))
363+
assert.Error(t, utils.CheckProposalTxID("", nonce, creator))
363364

364-
txid, err = ComputeProposalTxID(nil, nil)
365+
txid, err = utils.ComputeProposalTxID(nil, nil)
365366
assert.NotEmpty(t, txid, "TxID cannot be empty.")
366367
assert.NoError(t, err, "Failed computing txID")
367368
}
368369

369370
func TestComputeProposalTxID(t *testing.T) {
370-
txid, err := ComputeProposalTxID([]byte{1}, []byte{1})
371+
txid, err := utils.ComputeProposalTxID([]byte{1}, []byte{1})
371372
assert.NoError(t, err, "Failed computing TxID")
372373

373374
// Compute the function computed by ComputeProposalTxID,

0 commit comments

Comments
 (0)