Skip to content

Commit 0d25786

Browse files
author
Jason Yellick
committed
[FAB-9473] Always enforce validation on initial cc
Currently, if a tx does not modify any data, all validation of that tx is skipped. This is usually not the application writer's intent, and instead, the initially called chaincode should always have its EP enforced, regardless of whether writes are made. This also fixes the issue of enforcing endorsments for chaincode events. Currently, only the initially invoked chaincode may include events in the proposal results. Therefore any chaincode events will be verified using this EP. Change-Id: I3c98e54be2ba4a53d26c8c13c0e243c6871aad34 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent e507d74 commit 0d25786

File tree

2 files changed

+76
-19
lines changed

2 files changed

+76
-19
lines changed

core/committer/txvalidator/validator_test.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ func signedByAnyMember(ids []string) []byte {
5757
}
5858

5959
func setupLedgerAndValidator(t *testing.T) (ledger.PeerLedger, Validator) {
60+
return setupLedgerAndValidatorExplicit(t, &mockconfig.MockApplicationCapabilities{})
61+
}
62+
63+
func setupLedgerAndValidatorExplicit(t *testing.T, cpb *mockconfig.MockApplicationCapabilities) (ledger.PeerLedger, Validator) {
6064
viper.Set("peer.fileSystemPath", "/tmp/fabric/validatortest")
6165
ledgermgmt.InitializeTestEnv()
6266
gb, err := ctxt.MakeGenesisBlock("TestLedger")
@@ -66,7 +70,7 @@ func setupLedgerAndValidator(t *testing.T) (ledger.PeerLedger, Validator) {
6670
vcs := struct {
6771
*mocktxvalidator.Support
6872
*semaphore.Weighted
69-
}{&mocktxvalidator.Support{LedgerVal: theLedger, ACVal: &mockconfig.MockApplicationCapabilities{}}, semaphore.NewWeighted(10)}
73+
}{&mocktxvalidator.Support{LedgerVal: theLedger, ACVal: cpb}, semaphore.NewWeighted(10)}
7074
theValidator := NewTxValidator(vcs)
7175

7276
return theLedger, theValidator
@@ -209,6 +213,46 @@ func TestInvokeOK(t *testing.T) {
209213
assertValid(b, t)
210214
}
211215

216+
func TestInvokeNoRWSet(t *testing.T) {
217+
t.Run("Pre-1.2Capability", func(t *testing.T) {
218+
l, v := setupLedgerAndValidator(t)
219+
defer ledgermgmt.CleanupTestEnv()
220+
defer l.Close()
221+
222+
ccID := "mycc"
223+
224+
putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t)
225+
226+
tx := getEnv(ccID, createRWset(t), t)
227+
b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}}
228+
229+
v.(*txValidator).vscc.(*vsccValidatorImpl).ccprovider.(*ccprovider.MockCcProviderImpl).ExecuteResultProvider = nil
230+
v.(*txValidator).vscc.(*vsccValidatorImpl).ccprovider.(*ccprovider.MockCcProviderImpl).ExecuteChaincodeResponse = &peer.Response{Status: shim.ERROR}
231+
err := v.Validate(b)
232+
assert.NoError(t, err)
233+
assertValid(b, t)
234+
})
235+
236+
t.Run("Post-1.2Capability", func(t *testing.T) {
237+
l, v := setupLedgerAndValidatorExplicit(t, &mockconfig.MockApplicationCapabilities{V1_2ValidationRv: true})
238+
defer ledgermgmt.CleanupTestEnv()
239+
defer l.Close()
240+
241+
ccID := "mycc"
242+
243+
putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t)
244+
245+
tx := getEnv(ccID, createRWset(t), t)
246+
b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}}
247+
248+
v.(*txValidator).vscc.(*vsccValidatorImpl).ccprovider.(*ccprovider.MockCcProviderImpl).ExecuteResultProvider = nil
249+
v.(*txValidator).vscc.(*vsccValidatorImpl).ccprovider.(*ccprovider.MockCcProviderImpl).ExecuteChaincodeResponse = &peer.Response{Status: shim.ERROR}
250+
err := v.Validate(b)
251+
assert.NoError(t, err)
252+
assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
253+
})
254+
}
255+
212256
func TestInvokeOKPvtDataOnly(t *testing.T) {
213257
l, v := setupLedgerAndValidator(t)
214258
defer ledgermgmt.CleanupTestEnv()

core/committer/txvalidator/vscc_validator.go

+31-18
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
7373
1) which namespaces does it write to?
7474
2) does it write to LSCC's namespace?
7575
3) does it write to any cc that cannot be invoked? */
76-
wrNamespace := []string{}
7776
writesToLSCC := false
7877
writesToNonInvokableSCC := false
7978
respPayload, err := utils.GetActionFromEnvelope(envBytes)
@@ -84,23 +83,6 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
8483
if err = txRWSet.FromProtoBytes(respPayload.Results); err != nil {
8584
return errors.WithMessage(err, "txRWSet.FromProtoBytes failed"), peer.TxValidationCode_BAD_RWSET
8685
}
87-
for _, ns := range txRWSet.NsRwSets {
88-
if v.txWritesToNamespace(ns) {
89-
wrNamespace = append(wrNamespace, ns.NameSpace)
90-
91-
if !writesToLSCC && ns.NameSpace == "lscc" {
92-
writesToLSCC = true
93-
}
94-
95-
if !writesToNonInvokableSCC && v.sccprovider.IsSysCCAndNotInvokableCC2CC(ns.NameSpace) {
96-
writesToNonInvokableSCC = true
97-
}
98-
99-
if !writesToNonInvokableSCC && v.sccprovider.IsSysCCAndNotInvokableExternal(ns.NameSpace) {
100-
writesToNonInvokableSCC = true
101-
}
102-
}
103-
}
10486

10587
// Verify the header extension and response payload contain the ChaincodeId
10688
if hdrExt.ChaincodeId == nil {
@@ -133,6 +115,36 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
133115
return err, peer.TxValidationCode_INVALID_OTHER_REASON
134116
}
135117

118+
var wrNamespace []string
119+
alwaysEnforceOriginalNamespace := v.support.Capabilities().V1_2Validation()
120+
if alwaysEnforceOriginalNamespace {
121+
wrNamespace = append(wrNamespace, ccID)
122+
}
123+
124+
for _, ns := range txRWSet.NsRwSets {
125+
if !v.txWritesToNamespace(ns) {
126+
continue
127+
}
128+
129+
// Check to make sure we did not already populate this chaincode
130+
// name to avoid checking the same namespace twice
131+
if ns.NameSpace != ccID || !alwaysEnforceOriginalNamespace {
132+
wrNamespace = append(wrNamespace, ns.NameSpace)
133+
}
134+
135+
if !writesToLSCC && ns.NameSpace == "lscc" {
136+
writesToLSCC = true
137+
}
138+
139+
if !writesToNonInvokableSCC && v.sccprovider.IsSysCCAndNotInvokableCC2CC(ns.NameSpace) {
140+
writesToNonInvokableSCC = true
141+
}
142+
143+
if !writesToNonInvokableSCC && v.sccprovider.IsSysCCAndNotInvokableExternal(ns.NameSpace) {
144+
writesToNonInvokableSCC = true
145+
}
146+
}
147+
136148
// we've gathered all the info required to proceed to validation;
137149
// validation will behave differently depending on the type of
138150
// chaincode (system vs. application)
@@ -252,6 +264,7 @@ func (v *vsccValidatorImpl) VSCCValidateTxForCC(envBytes []byte, txid, chid, vsc
252264
msg := fmt.Sprintf("Invoke VSCC failed for transaction txid=%s, error: %s", txid, err)
253265
return &commonerrors.VSCCExecutionFailureError{msg}
254266
}
267+
255268
if res.Status != shim.OK {
256269
return &commonerrors.VSCCEndorsementPolicyError{fmt.Sprintf("%s", res.Message)}
257270
}

0 commit comments

Comments
 (0)