@@ -33,12 +33,17 @@ import (
33
33
mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
34
34
"github.com/hyperledger/fabric/protos/common"
35
35
"github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset"
36
+ "github.com/hyperledger/fabric/protos/msp"
36
37
pb "github.com/hyperledger/fabric/protos/peer"
37
38
"github.com/hyperledger/fabric/protos/utils"
38
39
)
39
40
40
41
var logger = flogging .MustGetLogger ("vscc" )
41
42
43
+ const (
44
+ DUPLICATED_IDENTITY_ERROR = "Endorsement policy evaluation failure might be caused by duplicated identities"
45
+ )
46
+
42
47
// ValidatorOneValidSignature implements the default transaction validation policy,
43
48
// which is to check the correctness of the read-write set and the endorsement
44
49
// signatures
@@ -62,7 +67,7 @@ func (vscc *ValidatorOneValidSignature) Init(stub shim.ChaincodeStubInterface) p
62
67
// chaincodes to provide more sophisticated policy processing such as enabling
63
68
// policy specification to be coded as a transaction of the chaincode and the client
64
69
// selecting which policy to use for validation using parameter function
65
- // @return serialized Block of valid and invalid transactions indentified
70
+ // @return serialized Block of valid and invalid transactions identified
66
71
// Note that Peer calls this function with 3 arguments, where args[0] is the
67
72
// function name, args[1] is the Envelope and args[2] is the validation policy
68
73
func (vscc * ValidatorOneValidSignature ) Invoke (stub shim.ChaincodeStubInterface ) pb.Response {
@@ -134,27 +139,19 @@ func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface)
134
139
return shim .Error (err .Error ())
135
140
}
136
141
137
- // this is the first part of the signed message
138
- prespBytes := cap .Action .ProposalResponsePayload
139
-
140
- // build the signature set for the evaluation
141
- signatureSet := make ([]* common.SignedData , len (cap .Action .Endorsements ))
142
-
143
- // loop through each of the endorsements and build the signature set
144
- for i , endorsement := range cap .Action .Endorsements {
145
- signatureSet [i ] = & common.SignedData {
146
- // set the data that is signed; concatenation of proposal response bytes and endorser ID
147
- Data : append (prespBytes , endorsement .Endorser ... ),
148
- // set the identity that signs the message: it's the endorser
149
- Identity : endorsement .Endorser ,
150
- // set the signature
151
- Signature : endorsement .Signature ,
152
- }
142
+ signatureSet , err := vscc .deduplicateIdentity (cap )
143
+ if err != nil {
144
+ return shim .Error (err .Error ())
153
145
}
154
146
155
147
// evaluate the signature set against the policy
156
148
err = policy .Evaluate (signatureSet )
157
149
if err != nil {
150
+ logger .Warningf ("Endorsement policy failure for transaction txid=%s, err: %s" , chdr .GetTxId (), err .Error ())
151
+ if len (signatureSet ) < len (cap .Action .Endorsements ) {
152
+ // Warning: duplicated identities exist, endorsement failure might be cause by this reason
153
+ return shim .Error (DUPLICATED_IDENTITY_ERROR )
154
+ }
158
155
return shim .Error (fmt .Sprintf ("VSCC error: policy evaluation failed, err %s" , err ))
159
156
}
160
157
@@ -425,3 +422,38 @@ func (vscc *ValidatorOneValidSignature) getInstantiatedCC(chid, ccid string) (cd
425
422
exists = true
426
423
return
427
424
}
425
+
426
+ func (vscc * ValidatorOneValidSignature ) deduplicateIdentity (cap * pb.ChaincodeActionPayload ) ([]* common.SignedData , error ) {
427
+ // this is the first part of the signed message
428
+ prespBytes := cap .Action .ProposalResponsePayload
429
+
430
+ // build the signature set for the evaluation
431
+ signatureSet := []* common.SignedData {}
432
+ signatureMap := make (map [string ]struct {})
433
+ // loop through each of the endorsements and build the signature set
434
+ for _ , endorsement := range cap .Action .Endorsements {
435
+ //unmarshal endorser bytes
436
+ serializedIdentity := & msp.SerializedIdentity {}
437
+ if err := proto .Unmarshal (endorsement .Endorser , serializedIdentity ); err != nil {
438
+ logger .Errorf ("Unmarshal endorser error: %s" , err )
439
+ return nil , fmt .Errorf ("Unmarshal endorser error: %s" , err )
440
+ }
441
+ identity := serializedIdentity .Mspid + string (serializedIdentity .IdBytes )
442
+ if _ , ok := signatureMap [identity ]; ok {
443
+ // Endorsement with the same identity has already been added
444
+ logger .Warningf ("Ignoring duplicated identity, Mspid: %s, pem:\n %s" , serializedIdentity .Mspid , serializedIdentity .IdBytes )
445
+ continue
446
+ }
447
+ signatureSet = append (signatureSet , & common.SignedData {
448
+ // set the data that is signed; concatenation of proposal response bytes and endorser ID
449
+ Data : append (prespBytes , endorsement .Endorser ... ),
450
+ // set the identity that signs the message: it's the endorser
451
+ Identity : endorsement .Endorser ,
452
+ // set the signature
453
+ Signature : endorsement .Signature })
454
+ signatureMap [identity ] = struct {}{}
455
+ }
456
+
457
+ logger .Debugf ("Signature set is of size %d out of %d endorsement(s)" , len (signatureSet ), len (cap .Action .Endorsements ))
458
+ return signatureSet , nil
459
+ }
0 commit comments