Skip to content

Commit d45004d

Browse files
ale-linuxyacovm
authored andcommittedDec 21, 2017
[FAB-6671] call VSCC for tx with pvt writes only
VSCC validation applies only if there are public writes in a transaction. This change set forces VSCC validation if there are only private writes in a transaction (hashed rwset). Change-Id: Ie3abc4e613a5c547fa8676d9aa390f17d167a9d9 Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net>
1 parent 8a705b7 commit d45004d

File tree

3 files changed

+78
-13
lines changed

3 files changed

+78
-13
lines changed
 

‎core/committer/txvalidator/validator.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,29 @@ func (v *vsccValidatorImpl) GetInfoForValidate(txid, chID, ccID string) (*sysccp
654654
return cc, vscc, policy, nil
655655
}
656656

657+
// txWritesToNamespace returns true if the supplied NsRwSet
658+
// performs a ledger write
659+
func (v *vsccValidatorImpl) txWritesToNamespace(ns *rwsetutil.NsRwSet) bool {
660+
// check for public writes first
661+
if ns.KvRwSet != nil && len(ns.KvRwSet.Writes) > 0 {
662+
return true
663+
}
664+
665+
// do not look at collection data if we don't support that capability
666+
if !v.support.Capabilities().PrivateChannelData() {
667+
return false
668+
}
669+
670+
// check for private writes for all collections
671+
for _, c := range ns.CollHashedRwSets {
672+
if c.HashedRwSet != nil && len(c.HashedRwSet.HashedWrites) > 0 {
673+
return true
674+
}
675+
}
676+
677+
return false
678+
}
679+
657680
func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []byte, env *common.Envelope) (error, peer.TxValidationCode) {
658681
logger.Debugf("VSCCValidateTx starts for env %p envbytes %p", env, envBytes)
659682
defer logger.Debugf("VSCCValidateTx completes for env %p envbytes %p", env, envBytes)
@@ -687,7 +710,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
687710
return fmt.Errorf("txRWSet.FromProtoBytes failed, error %s", err), peer.TxValidationCode_BAD_RWSET
688711
}
689712
for _, ns := range txRWSet.NsRwSets {
690-
if len(ns.KvRwSet.Writes) > 0 {
713+
if v.txWritesToNamespace(ns) {
691714
wrNamespace = append(wrNamespace, ns.NameSpace)
692715

693716
if !writesToLSCC && ns.NameSpace == "lscc" {

‎core/committer/txvalidator/validator_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,38 @@ func TestInvokeOK(t *testing.T) {
208208
assertValid(b, t)
209209
}
210210

211+
func TestInvokeOKPvtDataOnly(t *testing.T) {
212+
l, v := setupLedgerAndValidator(t)
213+
defer ledgermgmt.CleanupTestEnv()
214+
defer l.Close()
215+
216+
v.(*txValidator).support.(struct {
217+
*mocktxvalidator.Support
218+
*semaphore.Weighted
219+
}).ACVal = &mockconfig.MockApplicationCapabilities{PrivateChannelDataRv: true}
220+
221+
ccID := "mycc"
222+
223+
putCCInfo(l, ccID, signedByAnyMember([]string{"DEFAULT"}), t)
224+
225+
rwsetBuilder := rwsetutil.NewRWSetBuilder()
226+
rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, "mycollection", "somekey", nil)
227+
rwset, err := rwsetBuilder.GetTxSimulationResults()
228+
assert.NoError(t, err)
229+
rwsetBytes, err := rwset.GetPubSimulationBytes()
230+
assert.NoError(t, err)
231+
232+
tx := getEnv(ccID, rwsetBytes, t)
233+
b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}}
234+
235+
v.(*txValidator).vscc.(*vsccValidatorImpl).ccprovider.(*ccprovider.MockCcProviderImpl).ExecuteResultProvider = nil
236+
v.(*txValidator).vscc.(*vsccValidatorImpl).ccprovider.(*ccprovider.MockCcProviderImpl).ExecuteChaincodeResponse = &peer.Response{Status: shim.ERROR}
237+
238+
err = v.Validate(b)
239+
assert.NoError(t, err)
240+
assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE)
241+
}
242+
211243
func TestInvokeOKSCC(t *testing.T) {
212244
l, v := setupLedgerAndValidator(t)
213245
defer ledgermgmt.CleanupTestEnv()

‎core/mocks/ccprovider/ccprovider.go

+22-12
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ type MockCcProviderFactory struct {
3838

3939
// NewChaincodeProvider returns a mock implementation of the ccprovider.ChaincodeProvider interface
4040
func (c *MockCcProviderFactory) NewChaincodeProvider() ccprovider.ChaincodeProvider {
41-
return &mockCcProviderImpl{c.ExecuteResultProvider}
41+
return &MockCcProviderImpl{ExecuteResultProvider: c.ExecuteResultProvider}
4242
}
4343

4444
// mockCcProviderImpl is a mock implementation of the chaincode provider
45-
type mockCcProviderImpl struct {
46-
executeResultProvider ExecuteChaincodeResultProvider
45+
type MockCcProviderImpl struct {
46+
ExecuteResultProvider ExecuteChaincodeResultProvider
47+
ExecuteChaincodeResponse *peer.Response
4748
}
4849

4950
type mockCcProviderContextImpl struct {
@@ -121,34 +122,43 @@ func (m *MockTxSim) SetPrivateDataMultipleKeys(namespace, collection string, kvs
121122
}
122123

123124
// GetContext does nothing
124-
func (c *mockCcProviderImpl) GetContext(ledger ledger.PeerLedger, txid string) (context.Context, ledger.TxSimulator, error) {
125+
func (c *MockCcProviderImpl) GetContext(ledger ledger.PeerLedger, txid string) (context.Context, ledger.TxSimulator, error) {
125126
return nil, &MockTxSim{}, nil
126127
}
127128

128129
// GetCCContext does nothing
129-
func (c *mockCcProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *peer.SignedProposal, prop *peer.Proposal) interface{} {
130+
func (c *MockCcProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *peer.SignedProposal, prop *peer.Proposal) interface{} {
130131
return &mockCcProviderContextImpl{}
131132
}
132133

134+
// GetCCValidationInfoFromLSCC does nothing
135+
func (c *MockCcProviderImpl) GetCCValidationInfoFromLSCC(ctxt context.Context, txid string, signedProp *peer.SignedProposal, prop *peer.Proposal, chainID string, chaincodeID string) (string, []byte, error) {
136+
return "vscc", nil, nil
137+
}
138+
133139
// ExecuteChaincode does nothing
134-
func (c *mockCcProviderImpl) ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][]byte) (*peer.Response, *peer.ChaincodeEvent, error) {
135-
if c.executeResultProvider != nil {
136-
return c.executeResultProvider.ExecuteChaincodeResult()
140+
func (c *MockCcProviderImpl) ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][]byte) (*peer.Response, *peer.ChaincodeEvent, error) {
141+
if c.ExecuteResultProvider != nil {
142+
return c.ExecuteResultProvider.ExecuteChaincodeResult()
143+
}
144+
if c.ExecuteChaincodeResponse == nil {
145+
return &peer.Response{Status: shim.OK}, nil, nil
146+
} else {
147+
return c.ExecuteChaincodeResponse, nil, nil
137148
}
138-
return &peer.Response{Status: shim.OK}, nil, nil
139149
}
140150

141151
// Execute executes the chaincode given context and spec (invocation or deploy)
142-
func (c *mockCcProviderImpl) Execute(ctxt context.Context, cccid interface{}, spec interface{}) (*peer.Response, *peer.ChaincodeEvent, error) {
152+
func (c *MockCcProviderImpl) Execute(ctxt context.Context, cccid interface{}, spec interface{}) (*peer.Response, *peer.ChaincodeEvent, error) {
143153
return nil, nil, nil
144154
}
145155

146156
// ExecuteWithErrorFilter executes the chaincode given context and spec and returns payload
147-
func (c *mockCcProviderImpl) ExecuteWithErrorFilter(ctxt context.Context, cccid interface{}, spec interface{}) ([]byte, *peer.ChaincodeEvent, error) {
157+
func (c *MockCcProviderImpl) ExecuteWithErrorFilter(ctxt context.Context, cccid interface{}, spec interface{}) ([]byte, *peer.ChaincodeEvent, error) {
148158
return nil, nil, nil
149159
}
150160

151161
// Stop stops the chaincode given context and deployment spec
152-
func (c *mockCcProviderImpl) Stop(ctxt context.Context, cccid interface{}, spec *peer.ChaincodeDeploymentSpec) error {
162+
func (c *MockCcProviderImpl) Stop(ctxt context.Context, cccid interface{}, spec *peer.ChaincodeDeploymentSpec) error {
153163
return nil
154164
}

0 commit comments

Comments
 (0)