Skip to content

Commit

Permalink
[FAB-3561] Increase test coverage for VSCC
Browse files Browse the repository at this point in the history
Output of test coverage for core/scc/vscc now is

coverage: 85.1% of statements
ok		github.com/hyperledger/fabric/core/scc/vscc	0.078s

Change-Id: Ic2882cfccdee02f0b3f680585097d4ea26b69099
Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net>
  • Loading branch information
ale-linux authored and yacovm committed May 6, 2017
1 parent 3d169cc commit 420a6a5
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 25 deletions.
10 changes: 6 additions & 4 deletions common/mocks/scc/sccprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@ import (
)

type MocksccProviderFactory struct {
Qe *lm.MockQueryExecutor
Qe *lm.MockQueryExecutor
QErr error
}

func (c *MocksccProviderFactory) NewSystemChaincodeProvider() sysccprovider.SystemChaincodeProvider {
return &mocksccProviderImpl{Qe: c.Qe}
return &mocksccProviderImpl{Qe: c.Qe, QErr: c.QErr}
}

type mocksccProviderImpl struct {
Qe *lm.MockQueryExecutor
Qe *lm.MockQueryExecutor
QErr error
}

func (c *mocksccProviderImpl) IsSysCC(name string) bool {
Expand All @@ -47,5 +49,5 @@ func (c *mocksccProviderImpl) IsSysCCAndNotInvokableExternal(name string) bool {
}

func (c *mocksccProviderImpl) GetQueryExecutorForLedger(cid string) (ledger.QueryExecutor, error) {
return c.Qe, nil
return c.Qe, c.QErr
}
17 changes: 5 additions & 12 deletions core/scc/vscc/validator_onevalidsignature.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface)
if hdrExt.ChaincodeId.Name == "lscc" {
logger.Debugf("VSCC info: doing special validation for LSCC")

err = vscc.ValidateLSCCInvocation(stub, chdr.ChannelId, env, cap)
err = vscc.ValidateLSCCInvocation(stub, chdr.ChannelId, env, cap, payl)
if err != nil {
logger.Errorf("VSCC error: ValidateLSCCInvocation failed, err %s", err)
return shim.Error(err.Error())
Expand All @@ -182,7 +182,7 @@ func (vscc *ValidatorOneValidSignature) Invoke(stub shim.ChaincodeStubInterface)
}

// checkInstantiationPolicy evaluates an instantiation policy against a signed proposal
func (vscc *ValidatorOneValidSignature) checkInstantiationPolicy(chainName string, env *common.Envelope, instantiationPolicy []byte) error {
func (vscc *ValidatorOneValidSignature) checkInstantiationPolicy(chainName string, env *common.Envelope, instantiationPolicy []byte, payl *common.Payload) error {
// create a policy object from the policy bytes
mgr := mspmgmt.GetManagerForChain(chainName)
if mgr == nil {
Expand All @@ -197,13 +197,6 @@ func (vscc *ValidatorOneValidSignature) checkInstantiationPolicy(chainName strin

logger.Debugf("VSCC info: checkInstantiationPolicy starts, policy is %#v", instPol)

// get the payload
payl, err := utils.GetPayload(env)
if err != nil {
logger.Errorf("VSCC error: GetPayload failed, err %s", err)
return err
}

// get the signature header
shdr, err := utils.GetSignatureHeader(payl.Header.SignatureHeader)
if err != nil {
Expand All @@ -223,7 +216,7 @@ func (vscc *ValidatorOneValidSignature) checkInstantiationPolicy(chainName strin
return nil
}

func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(stub shim.ChaincodeStubInterface, chid string, env *common.Envelope, cap *pb.ChaincodeActionPayload) error {
func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(stub shim.ChaincodeStubInterface, chid string, env *common.Envelope, cap *pb.ChaincodeActionPayload, payl *common.Payload) error {
cpp, err := utils.GetChaincodeProposalPayload(cap.ChaincodeProposalPayload)
if err != nil {
logger.Errorf("VSCC error: GetChaincodeProposalPayload failed, err %s", err)
Expand Down Expand Up @@ -352,7 +345,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(stub shim.Chainco
// here is the same as the one on disk?
// PROS: we prevent attacks where the policy is replaced
// CONS: this would be a point of non-determinism
err = vscc.checkInstantiationPolicy(chid, env, pol)
err = vscc.checkInstantiationPolicy(chid, env, pol, payl)
if err != nil {
return err
}
Expand Down Expand Up @@ -384,7 +377,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(stub shim.Chainco
// here is the same as the one on disk?
// PROS: we prevent attacks where the policy is replaced
// CONS: this would be a point of non-determinism
err = vscc.checkInstantiationPolicy(chid, env, pol)
err = vscc.checkInstantiationPolicy(chid, env, pol, payl)
if err != nil {
return err
}
Expand Down
225 changes: 216 additions & 9 deletions core/scc/vscc/validator_onevalidsignature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ func createCCDataRWset(nameK, nameV, version string, policy []byte) ([]byte, err
}

func createLSCCTx(ccname, ccver, f string, res []byte) (*common.Envelope, error) {
return createLSCCTxPutCds(ccname, ccver, f, res, nil, true)
}

func createLSCCTxPutCds(ccname, ccver, f string, res, cdsbytes []byte, putcds bool) (*common.Envelope, error) {
cds := &peer.ChaincodeDeploymentSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{
Expand All @@ -151,14 +155,30 @@ func createLSCCTx(ccname, ccver, f string, res []byte) (*common.Envelope, error)
return nil, err
}

cis := &peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
Input: &peer.ChaincodeInput{
Args: [][]byte{[]byte(f), []byte("barf"), cdsBytes},
var cis *peer.ChaincodeInvocationSpec
if putcds {
if cdsbytes != nil {
cdsBytes = cdsbytes
}
cis = &peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
Input: &peer.ChaincodeInput{
Args: [][]byte{[]byte(f), []byte("barf"), cdsBytes},
},
Type: peer.ChaincodeSpec_GOLANG,
},
Type: peer.ChaincodeSpec_GOLANG,
},
}
} else {
cis = &peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
Input: &peer.ChaincodeInput{
Args: [][]byte{[]byte(f), []byte("barf")},
},
Type: peer.ChaincodeSpec_GOLANG,
},
}
}

prop, _, err := utils.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, util.GetTestChainID(), cis, sid)
Expand Down Expand Up @@ -217,12 +237,44 @@ func TestInvoke(t *testing.T) {
t.Fatalf("vscc invoke should have failed")
}

// not enough args
args = [][]byte{[]byte("dv"), []byte("tx")}
args[1] = nil
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// nil args
args = [][]byte{nil, nil, nil}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// nil args
args = [][]byte{[]byte("a"), []byte("a"), nil}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// broken Envelope
args = [][]byte{[]byte("a"), []byte("a"), []byte("a")}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// (still) broken Envelope
args = [][]byte{[]byte("a"), utils.MarshalOrPanic(&common.Envelope{Payload: []byte("barf")}), []byte("a")}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// (still) broken Envelope
b := utils.MarshalOrPanic(&common.Envelope{Payload: utils.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: []byte("barf")}})})
args = [][]byte{[]byte("a"), b, []byte("a")}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

tx, _, err := createTx()
if err != nil {
t.Fatalf("createTx returned err %s", err)
Expand All @@ -233,12 +285,32 @@ func TestInvoke(t *testing.T) {
t.Fatalf("GetBytesEnvelope returned err %s", err)
}

// good path: signed by the right MSP
// broken policy
args = [][]byte{[]byte("dv"), envBytes, []byte("barf")}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

policy, err := getSignedByMSPMemberPolicy(mspid)
if err != nil {
t.Fatalf("failed getting policy, err %s", err)
}

// broken type
b = utils.MarshalOrPanic(&common.Envelope{Payload: utils.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: utils.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_ORDERER_TRANSACTION)})}})})
args = [][]byte{[]byte("dv"), b, policy}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// broken tx payload
b = utils.MarshalOrPanic(&common.Envelope{Payload: utils.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: utils.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_ORDERER_TRANSACTION)})}})})
args = [][]byte{[]byte("dv"), b, policy}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

// good path: signed by the right MSP
args = [][]byte{[]byte("dv"), envBytes, policy}
res := stub.MockInvoke("1", args)
if res.Status != shim.OK {
Expand Down Expand Up @@ -456,11 +528,67 @@ func TestValidateDeployFail(t *testing.T) {
t.Fatalf("vscc invoke should have failed")
}

/**********************/
/* test bad LSCC args */
/**********************/

res, err := createCCDataRWset(ccname, ccname, ccver, nil)
assert.NoError(t, err)

tx, err = createLSCCTxPutCds(ccname, ccver, lscc.DEPLOY, res, nil, false)
if err != nil {
t.Fatalf("createTx returned err %s", err)
}

envBytes, err = utils.GetBytesEnvelope(tx)
if err != nil {
t.Fatalf("GetBytesEnvelope returned err %s", err)
}

// good path: signed by the right MSP
policy, err = getSignedByMSPMemberPolicy(mspid)
if err != nil {
t.Fatalf("failed getting policy, err %s", err)
}

args = [][]byte{[]byte("dv"), envBytes, policy}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

/**********************/
/* test bad LSCC args */
/**********************/

res, err = createCCDataRWset(ccname, ccname, ccver, nil)
assert.NoError(t, err)

tx, err = createLSCCTxPutCds(ccname, ccver, lscc.DEPLOY, res, []byte("barf"), true)
if err != nil {
t.Fatalf("createTx returned err %s", err)
}

envBytes, err = utils.GetBytesEnvelope(tx)
if err != nil {
t.Fatalf("GetBytesEnvelope returned err %s", err)
}

// good path: signed by the right MSP
policy, err = getSignedByMSPMemberPolicy(mspid)
if err != nil {
t.Fatalf("failed getting policy, err %s", err)
}

args = [][]byte{[]byte("dv"), envBytes, policy}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

/***********************/
/* test bad cc version */
/***********************/

res, err := createCCDataRWset(ccname, ccname, ccver+".1", nil)
res, err = createCCDataRWset(ccname, ccname, ccver+".1", nil)
assert.NoError(t, err)

tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
Expand All @@ -484,6 +612,31 @@ func TestValidateDeployFail(t *testing.T) {
t.Fatalf("vscc invoke should have failed")
}

/*************/
/* bad rwset */
/*************/

tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, []byte("barf"))
if err != nil {
t.Fatalf("createTx returned err %s", err)
}

envBytes, err = utils.GetBytesEnvelope(tx)
if err != nil {
t.Fatalf("GetBytesEnvelope returned err %s", err)
}

// good path: signed by the right MSP
policy, err = getSignedByMSPMemberPolicy(mspid)
if err != nil {
t.Fatalf("failed getting policy, err %s", err)
}

args = [][]byte{[]byte("dv"), envBytes, policy}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}

/********************/
/* test bad cc name */
/********************/
Expand Down Expand Up @@ -652,6 +805,60 @@ func TestAlreadyDeployed(t *testing.T) {
}
}

func TestValidateDeployNoLedger(t *testing.T) {
v := new(ValidatorOneValidSignature)
stub := shim.NewMockStub("validatoronevalidsignature", v)

lccc := new(lscc.LifeCycleSysCC)
stublccc := shim.NewMockStub("lscc", lccc)

State := make(map[string]map[string][]byte)
State["lscc"] = stublccc.State
sysccprovider.RegisterSystemChaincodeProviderFactory(&scc.MocksccProviderFactory{QErr: fmt.Errorf("Simulated error")})
stub.MockPeerChaincode("lscc", stublccc)

r1 := stub.MockInit("1", [][]byte{})
if r1.Status != shim.OK {
fmt.Println("Init failed", string(r1.Message))
t.FailNow()
}

r := stublccc.MockInit("1", [][]byte{})
if r.Status != shim.OK {
fmt.Println("Init failed", string(r.Message))
t.FailNow()
}

ccname := "mycc"
ccver := "1"

defaultPolicy, err := getSignedByMSPAdminPolicy(mspid)
assert.NoError(t, err)
res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy)
assert.NoError(t, err)

tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res)
if err != nil {
t.Fatalf("createTx returned err %s", err)
}

envBytes, err := utils.GetBytesEnvelope(tx)
if err != nil {
t.Fatalf("GetBytesEnvelope returned err %s", err)
}

// good path: signed by the right MSP
policy, err := getSignedByMSPMemberPolicy(mspid)
if err != nil {
t.Fatalf("failed getting policy, err %s", err)
}

args := [][]byte{[]byte("dv"), envBytes, policy}
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
t.Fatalf("vscc invoke should have failed")
}
}

func TestValidateDeployOK(t *testing.T) {
v := new(ValidatorOneValidSignature)
stub := shim.NewMockStub("validatoronevalidsignature", v)
Expand Down

0 comments on commit 420a6a5

Please sign in to comment.