@@ -27,12 +27,13 @@ import (
27
27
"github.com/hyperledger/fabric/core/ledger"
28
28
"github.com/hyperledger/fabric/core/ledger/kvledger"
29
29
"github.com/hyperledger/fabric/core/peer"
30
+ "github.com/hyperledger/fabric/msp"
30
31
"github.com/hyperledger/fabric/protos/common"
31
32
pb "github.com/hyperledger/fabric/protos/peer"
32
33
putils "github.com/hyperledger/fabric/protos/utils"
33
34
)
34
35
35
- var devopsLogger = logging .MustGetLogger ("endorser" )
36
+ var endorserLogger = logging .MustGetLogger ("endorser" )
36
37
37
38
// The Jira issue that documents Endorser flow along with its relationship to
38
39
// the lifecycle chaincode - https://jira.hyperledger.org/browse/FAB-181
@@ -175,7 +176,7 @@ func (e *Endorser) getCDSFromLCCC(ctx context.Context, chaincodeID string, txsim
175
176
176
177
//endorse the proposal by calling the ESCC
177
178
func (e * Endorser ) endorseProposal (ctx context.Context , proposal * pb.Proposal , simRes []byte , event * pb.ChaincodeEvent , visibility []byte , ccid * pb.ChaincodeID , txsim ledger.TxSimulator ) ([]byte , error ) {
178
- devopsLogger .Infof ("endorseProposal starts for proposal %p, simRes %p event %p, visibility %p, ccid %s" , proposal , simRes , event , visibility , ccid )
179
+ endorserLogger .Infof ("endorseProposal starts for proposal %p, simRes %p event %p, visibility %p, ccid %s" , proposal , simRes , event , visibility , ccid )
179
180
180
181
// 1) extract the chaincodeDeploymentSpec for the chaincode we are invoking; we need it to get the escc
181
182
var escc string
@@ -197,7 +198,7 @@ func (e *Endorser) endorseProposal(ctx context.Context, proposal *pb.Proposal, s
197
198
escc = "escc"
198
199
}
199
200
200
- devopsLogger .Infof ("endorseProposal info: escc for cid %s is %s" , ccid , escc )
201
+ endorserLogger .Infof ("endorseProposal info: escc for cid %s is %s" , ccid , escc )
201
202
202
203
// marshalling event bytes
203
204
var err error
@@ -239,15 +240,15 @@ func (e *Endorser) endorseProposal(ctx context.Context, proposal *pb.Proposal, s
239
240
// FIXME: this method might be of general interest, should we package it somewhere else?
240
241
// validateChaincodeProposalMessage checks the validity of a CHAINCODE Proposal message
241
242
func (e * Endorser ) validateChaincodeProposalMessage (prop * pb.Proposal , hdr * common.Header ) (* pb.ChaincodeHeaderExtension , error ) {
242
- devopsLogger .Infof ("validateChaincodeProposalMessage starts for proposal %p, header %p" , prop , hdr )
243
+ endorserLogger .Infof ("validateChaincodeProposalMessage starts for proposal %p, header %p" , prop , hdr )
243
244
244
245
// 4) based on the header type (assuming it's CHAINCODE), look at the extensions
245
246
chaincodeHdrExt , err := putils .GetChaincodeHeaderExtension (hdr )
246
247
if err != nil {
247
248
return nil , fmt .Errorf ("Invalid header extension for type CHAINCODE" )
248
249
}
249
250
250
- devopsLogger .Infof ("validateChaincodeProposalMessage info: header extension references chaincode %s" , chaincodeHdrExt .ChaincodeID )
251
+ endorserLogger .Infof ("validateChaincodeProposalMessage info: header extension references chaincode %s" , chaincodeHdrExt .ChaincodeID )
251
252
252
253
// - ensure that the chaincodeID is correct (?)
253
254
// TODO: should we even do this? If so, using which interface?
@@ -264,65 +265,88 @@ func (e *Endorser) validateChaincodeProposalMessage(prop *pb.Proposal, hdr *comm
264
265
// validateProposalMessage checks the validity of a generic Proposal message
265
266
// this function returns Header and ChaincodeHeaderExtension messages since they
266
267
// have been unmarshalled and validated
267
- func (e * Endorser ) validateProposalMessage (prop * pb.Proposal ) (* common.Header , * pb.ChaincodeHeaderExtension , error ) {
268
- devopsLogger .Infof ("validateProposalMessage starts for proposal %p" , prop )
268
+ func (e * Endorser ) validateProposalMessage (signedProp * pb.SignedProposal ) (* pb.Proposal , * common.Header , * pb.ChaincodeHeaderExtension , error ) {
269
+ endorserLogger .Infof ("validateProposalMessage starts for signed proposal %p" , signedProp )
270
+
271
+ // extract the Proposal message from signedProp
272
+ prop , err := putils .GetProposal (signedProp .ProposalBytes )
273
+ if err != nil {
274
+ return nil , nil , nil , err
275
+ }
269
276
270
277
// 1) look at the ProposalHeader
271
278
hdr , err := putils .GetHeader (prop )
272
279
if err != nil {
273
- return nil , nil , err
280
+ return nil , nil , nil , err
274
281
}
275
282
276
- // - validate the type
277
- if hdr .ChainHeader .Type != int32 (common .HeaderType_ENDORSER_TRANSACTION ) {
278
- return nil , nil , fmt .Errorf ("Invalid proposal type %d" , hdr .ChainHeader .Type )
279
- }
283
+ // TODO: validate the type
284
+
285
+ endorserLogger .Infof ("validateProposalMessage info: proposal type %d" , hdr .ChainHeader .Type )
280
286
281
- devopsLogger .Infof ("validateProposalMessage info: proposal type %d" , hdr .ChainHeader .Type )
287
+ // - ensure that the version is what we expect
288
+ // TODO: Which is the right version?
289
+
290
+ // - ensure that the chainID is valid
291
+ // TODO: which set of APIs is supposed to give us this info?
282
292
283
- // - ensure that there is a nonce and a creator
293
+ // ensure that there is a nonce and a creator
284
294
if hdr .SignatureHeader .Nonce == nil || len (hdr .SignatureHeader .Nonce ) == 0 {
285
- return nil , nil , fmt .Errorf ("Invalid nonce specified in the header" )
295
+ return nil , nil , nil , fmt .Errorf ("Invalid nonce specified in the header" )
286
296
}
287
297
if hdr .SignatureHeader .Creator == nil || len (hdr .SignatureHeader .Creator ) == 0 {
288
- return nil , nil , fmt .Errorf ("Invalid creator specified in the header" )
298
+ return nil , nil , nil , fmt .Errorf ("Invalid creator specified in the header" )
289
299
}
290
300
291
- // - ensure that creator is a valid certificate (depends on membership svc)
292
- // TODO: We need MSP APIs for this
301
+ // get the identity of the creator
302
+ creator , err := msp .GetManager ().DeserializeIdentity (hdr .SignatureHeader .Creator )
303
+ if err != nil {
304
+ return nil , nil , nil , fmt .Errorf ("Failed to deserialize creator identity, err %s" , err )
305
+ }
306
+
307
+ // ensure that creator is a valid certificate
308
+ valid , err := creator .Validate ()
309
+ if err != nil {
310
+ return nil , nil , nil , fmt .Errorf ("Could not determine whether the identity is valid, err %s" , err )
311
+ } else if ! valid {
312
+ return nil , nil , nil , fmt .Errorf ("The creator certificate is not valid, aborting" )
313
+ }
314
+
315
+ // get the identifier and log info on the creator
316
+ identifier := creator .Identifier ()
317
+ endorserLogger .Infof ("validateProposalMessage info: creator identity is %s" , identifier )
293
318
294
319
// - ensure that creator is trusted (signed by a trusted CA)
295
320
// TODO: We need MSP APIs for this
296
321
297
322
// - ensure that creator can transact with us (some ACLs?)
298
323
// TODO: which set of APIs is supposed to give us this info?
299
324
300
- // - ensure that the version is what we expect
301
- // TODO: Which is the right version?
302
-
303
- // - ensure that the chainID is valid
304
- // TODO: which set of APIs is supposed to give us this info?
325
+ // 2) validate the signature of creator on header and payload
326
+ verified , err := creator .Verify (signedProp .ProposalBytes , signedProp .Signature )
327
+ if err != nil {
328
+ return nil , nil , nil , fmt .Errorf ("Could not determine whether the signature is valid, err %s" , err )
329
+ } else if ! verified {
330
+ return nil , nil , nil , fmt .Errorf ("The creator's signature over the proposal is not valid, aborting" )
331
+ }
305
332
306
- // 2 ) perform a check against replay attacks
333
+ // 3 ) perform a check against replay attacks
307
334
// TODO
308
335
309
- // 3) validate the signature of creator on header and payload
310
- // TODO: We need MSP APIs for this
311
-
312
336
// validation of the proposal message knowing it's of type CHAINCODE
313
337
chaincodeHdrExt , err := e .validateChaincodeProposalMessage (prop , hdr )
314
338
if err != nil {
315
- return nil , nil , err
339
+ return nil , nil , nil , err
316
340
}
317
341
318
- return hdr , chaincodeHdrExt , err
342
+ return prop , hdr , chaincodeHdrExt , err
319
343
}
320
344
321
345
// ProcessProposal process the Proposal
322
- func (e * Endorser ) ProcessProposal (ctx context.Context , prop * pb.Proposal ) (* pb.ProposalResponse , error ) {
346
+ func (e * Endorser ) ProcessProposal (ctx context.Context , signedProp * pb.SignedProposal ) (* pb.ProposalResponse , error ) {
323
347
// at first, we check whether the message is valid
324
348
// TODO: Do the checks performed by this function belong here or in the ESCC? From a security standpoint they should be performed as early as possible so here seems to be a good place
325
- _ , hdrExt , err := e .validateProposalMessage (prop )
349
+ prop , _ , hdrExt , err := e .validateProposalMessage (signedProp )
326
350
if err != nil {
327
351
return & pb.ProposalResponse {Response : & pb.Response2 {Status : 500 , Message : err .Error ()}}, err
328
352
}
0 commit comments