diff --git a/core/committer/txvalidator/validator.go b/core/committer/txvalidator/validator.go index 52ff0a06d3c..dd96565af38 100644 --- a/core/committer/txvalidator/validator.go +++ b/core/committer/txvalidator/validator.go @@ -557,7 +557,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b // do VSCC validation if err = v.VSCCValidateTxForCC(envBytes, chdr.TxId, chdr.ChannelId, vscc.ChaincodeName, vscc.ChaincodeVersion, policy); err != nil { switch err.(type) { - case VSCCEndorsementPolicyError: + case *VSCCEndorsementPolicyError: return err, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE default: return err, peer.TxValidationCode_INVALID_OTHER_REASON @@ -588,7 +588,7 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b // they have to modify VSCC to provide appropriate validation if err = v.VSCCValidateTxForCC(envBytes, chdr.TxId, vscc.ChainID, vscc.ChaincodeName, vscc.ChaincodeVersion, policy); err != nil { switch err.(type) { - case VSCCEndorsementPolicyError: + case *VSCCEndorsementPolicyError: return err, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE default: return err, peer.TxValidationCode_INVALID_OTHER_REASON diff --git a/core/committer/txvalidator/validator_test.go b/core/committer/txvalidator/validator_test.go index 86ce49216a4..9000f7d967b 100644 --- a/core/committer/txvalidator/validator_test.go +++ b/core/committer/txvalidator/validator_test.go @@ -28,6 +28,7 @@ import ( "github.com/hyperledger/fabric/common/ledger/testutil" "github.com/hyperledger/fabric/common/mocks/scc" "github.com/hyperledger/fabric/common/util" + "github.com/hyperledger/fabric/core/chaincode/shim" ccp "github.com/hyperledger/fabric/core/common/ccprovider" "github.com/hyperledger/fabric/core/common/sysccprovider" "github.com/hyperledger/fabric/core/ledger" @@ -531,12 +532,73 @@ func TestLedgerIsNoAvailable(t *testing.T) { assertion.NotNil(err.(*VSCCInfoLookupFailureError)) } +func TestValidationInvalidEndorsing(t *testing.T) { + theLedger := new(mockLedger) + validator := NewTxValidator(&mockSupport{l: theLedger}) + + ccID := "mycc" + tx := getEnv(ccID, createRWset(t, ccID), t) + + theLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, errors.New("Cannot find the transaction")) + + cd := &ccp.ChaincodeData{ + Name: ccID, + Version: ccVersion, + Vscc: "vscc", + Policy: signedByAnyMember([]string{"DEFAULT"}), + } + + cdbytes := utils.MarshalOrPanic(cd) + + queryExecutor := new(mockQueryExecutor) + queryExecutor.On("GetState", "lscc", ccID).Return(cdbytes, nil) + theLedger.On("NewQueryExecutor", mock.Anything).Return(queryExecutor, nil) + + b := &common.Block{Data: &common.BlockData{Data: [][]byte{utils.MarshalOrPanic(tx)}}} + + // Keep default callback + c := executeChaincodeProvider.getCallback() + executeChaincodeProvider.setCallback(func() (*peer.Response, *peer.ChaincodeEvent, error) { + return &peer.Response{Status: shim.ERROR}, nil, nil + }) + err := validator.Validate(b) + // Restore default callback + executeChaincodeProvider.setCallback(c) + assert.NoError(t, err) + assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) +} + +type ccResultCallback func() (*peer.Response, *peer.ChaincodeEvent, error) + +type ccExecuteChaincode struct { + executeChaincodeCalback ccResultCallback +} + +func (cc *ccExecuteChaincode) ExecuteChaincodeResult() (*peer.Response, *peer.ChaincodeEvent, error) { + return cc.executeChaincodeCalback() +} + +func (cc *ccExecuteChaincode) getCallback() ccResultCallback { + return cc.executeChaincodeCalback +} + +func (cc *ccExecuteChaincode) setCallback(calback ccResultCallback) { + cc.executeChaincodeCalback = calback +} + var signer msp.SigningIdentity + var signerSerialized []byte +var executeChaincodeProvider = &ccExecuteChaincode{ + executeChaincodeCalback: func() (*peer.Response, *peer.ChaincodeEvent, error) { + return &peer.Response{Status: shim.OK}, nil, nil + }, +} + func TestMain(m *testing.M) { sysccprovider.RegisterSystemChaincodeProviderFactory(&scc.MocksccProviderFactory{}) - ccp.RegisterChaincodeProviderFactory(&ccprovider.MockCcProviderFactory{}) + ccp.RegisterChaincodeProviderFactory(&ccprovider.MockCcProviderFactory{executeChaincodeProvider}) msptesttools.LoadMSPSetupForTesting() diff --git a/core/mocks/ccprovider/ccprovider.go b/core/mocks/ccprovider/ccprovider.go index 0ac8e948543..b532ee6987d 100644 --- a/core/mocks/ccprovider/ccprovider.go +++ b/core/mocks/ccprovider/ccprovider.go @@ -25,18 +25,24 @@ import ( "github.com/hyperledger/fabric/protos/peer" ) +type ExecuteChaincodeResultProvider interface { + ExecuteChaincodeResult() (*peer.Response, *peer.ChaincodeEvent, error) +} + // MockCcProviderFactory is a factory that returns // mock implementations of the ccprovider.ChaincodeProvider interface type MockCcProviderFactory struct { + ExecuteResultProvider ExecuteChaincodeResultProvider } // NewChaincodeProvider returns a mock implementation of the ccprovider.ChaincodeProvider interface func (c *MockCcProviderFactory) NewChaincodeProvider() ccprovider.ChaincodeProvider { - return &mockCcProviderImpl{} + return &mockCcProviderImpl{c.ExecuteResultProvider} } // mockCcProviderImpl is a mock implementation of the chaincode provider type mockCcProviderImpl struct { + executeResultProvider ExecuteChaincodeResultProvider } type mockCcProviderContextImpl struct { @@ -59,6 +65,9 @@ func (c *mockCcProviderImpl) GetCCValidationInfoFromLSCC(ctxt context.Context, t // ExecuteChaincode does nothing func (c *mockCcProviderImpl) ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][]byte) (*peer.Response, *peer.ChaincodeEvent, error) { + if c.executeResultProvider != nil { + return c.executeResultProvider.ExecuteChaincodeResult() + } return &peer.Response{Status: shim.OK}, nil, nil }