Skip to content

Commit a491bbe

Browse files
committed
[FAB-6651] check instantiation policy upon upgrade
When a chaincode is being upgrade, there might be 2 instantiation policies worth checking: that of the current chaincode and that of the upgraded chaincode. The existing code checks that the request complies with the existing instantiation policy (i.e. the one on the ledger). The new code also checks whether the request complies with the new instantiation policy (i.e. the one on the rwset). This code change affects the behaviour of the committer and is therefore enclosed in a capability block. Change-Id: I6dbdba3ee13a48f165e07c4cee802042a76ab92d Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net>
1 parent f7f9a2f commit a491bbe

File tree

2 files changed

+132
-2
lines changed

2 files changed

+132
-2
lines changed

core/scc/vscc/validator_onevalidsignature.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
459459
/*****************************************************/
460460
pol := cdRWSet.InstantiationPolicy
461461
if pol == nil {
462-
return fmt.Errorf("No installation policy was specified")
462+
return fmt.Errorf("No instantiation policy was specified")
463463
}
464464
// FIXME: could we actually pull the cds package from the
465465
// file system to verify whether the policy that is specified
@@ -499,7 +499,7 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
499499
/*****************************************************/
500500
pol := cdLedger.InstantiationPolicy
501501
if pol == nil {
502-
return fmt.Errorf("No installation policy was specified")
502+
return fmt.Errorf("No instantiation policy was specified")
503503
}
504504
// FIXME: could we actually pull the cds package from the
505505
// file system to verify whether the policy that is specified
@@ -517,6 +517,24 @@ func (vscc *ValidatorOneValidSignature) ValidateLSCCInvocation(
517517
if cdLedger.Version == cdsArgs.ChaincodeSpec.ChaincodeId.Version {
518518
return fmt.Errorf("Existing version of the cc on the ledger (%s) should be different from the upgraded one", cdsArgs.ChaincodeSpec.ChaincodeId.Version)
519519
}
520+
521+
/******************************************************************/
522+
/* security check 4 - check the instantiation policy in the rwset */
523+
/******************************************************************/
524+
if ac.V1_1Validation() {
525+
polNew := cdRWSet.InstantiationPolicy
526+
if polNew == nil {
527+
return errors.New("No instantiation policy was specified")
528+
}
529+
530+
// no point in checking it again if they are the same policy
531+
if !bytes.Equal(polNew, pol) {
532+
err = vscc.checkInstantiationPolicy(chid, env, polNew, payl)
533+
if err != nil {
534+
return errors.WithMessage(err, "a failure occurred during the verfication of the upgraded instantiation policy")
535+
}
536+
}
537+
}
520538
}
521539

522540
// all is good!

core/scc/vscc/validator_onevalidsignature_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,118 @@ func TestValidateUpgradeWithPoliciesOK(t *testing.T) {
13731373
}
13741374
}
13751375

1376+
func TestValidateUpgradeWithNewFailAllIP(t *testing.T) {
1377+
// we're testing upgrade.
1378+
// In particular, we want to test the scenario where the upgrader
1379+
// complies with the instantiation policy of the current version
1380+
// BUT NOT the instantiation policy of the new version. For this
1381+
// reason we first deploy a cc with IP whic is equal to the AcceptAllPolicy
1382+
// and then try to upgrade with a cc with the RejectAllPolicy.
1383+
// We run this test twice, once with the V11 capability (and expect
1384+
// a failure) and once without (and we expect success).
1385+
1386+
validateUpgradeWithNewFailAllIP(t, true, true)
1387+
validateUpgradeWithNewFailAllIP(t, false, false)
1388+
}
1389+
1390+
func validateUpgradeWithNewFailAllIP(t *testing.T, v11capability, expecterr bool) {
1391+
// create the validator
1392+
v := new(ValidatorOneValidSignature)
1393+
stub := shim.NewMockStub("validatoronevalidsignature", v)
1394+
1395+
lccc := lscc.NewLifeCycleSysCC()
1396+
stublccc := shim.NewMockStub("lscc", lccc)
1397+
1398+
State := make(map[string]map[string][]byte)
1399+
State["lscc"] = stublccc.State
1400+
sysccprovider.RegisterSystemChaincodeProviderFactory(&scc.MocksccProviderFactory{
1401+
Qe: lm.NewMockQueryExecutor(State),
1402+
ApplicationConfigBool: true,
1403+
ApplicationConfigRv: &mc.MockApplication{&mc.MockApplicationCapabilities{V1_1ValidationRv: v11capability}},
1404+
})
1405+
stub.MockPeerChaincode("lscc", stublccc)
1406+
1407+
// init both chaincodes
1408+
r1 := stub.MockInit("1", [][]byte{})
1409+
if r1.Status != shim.OK {
1410+
fmt.Println("Init failed", string(r1.Message))
1411+
t.FailNow()
1412+
}
1413+
1414+
r := stublccc.MockInit("1", [][]byte{})
1415+
if r.Status != shim.OK {
1416+
fmt.Println("Init failed", string(r.Message))
1417+
t.FailNow()
1418+
}
1419+
1420+
// deploy the chaincode with an accept all policy
1421+
1422+
ccname := "mycc"
1423+
ccver := "1"
1424+
path := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
1425+
ppath := lccctestpath + "/" + ccname + "." + ccver
1426+
1427+
os.Remove(ppath)
1428+
1429+
cds, err := constructDeploymentSpec(ccname, path, ccver, [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}, false)
1430+
if err != nil {
1431+
fmt.Printf("%s\n", err)
1432+
t.FailNow()
1433+
}
1434+
_, err = processSignedCDS(cds, cauthdsl.AcceptAllPolicy)
1435+
assert.NoError(t, err)
1436+
defer os.Remove(ppath)
1437+
var b []byte
1438+
if b, err = proto.Marshal(cds); err != nil || b == nil {
1439+
t.FailNow()
1440+
}
1441+
1442+
sProp2, _ := utils.MockSignedEndorserProposal2OrPanic(chainId, &peer.ChaincodeSpec{}, id)
1443+
args := [][]byte{[]byte("deploy"), []byte(ccname), b}
1444+
if res := stublccc.MockInvokeWithSignedProposal("1", args, sProp2); res.Status != shim.OK {
1445+
fmt.Printf("%#v\n", res)
1446+
t.FailNow()
1447+
}
1448+
1449+
// if we're here, we have a cc deployed with an accept all IP
1450+
1451+
// now we upgrade, with v 2 of the same cc, with the crucial difference that it has a reject all IP
1452+
1453+
ccver = "2"
1454+
1455+
simresres, err := createCCDataRWset(ccname, ccname, ccver,
1456+
cauthdsl.MarshaledRejectAllPolicy, // here's where we specify the IP of the upgraded cc
1457+
)
1458+
assert.NoError(t, err)
1459+
1460+
tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres)
1461+
if err != nil {
1462+
t.Fatalf("createTx returned err %s", err)
1463+
}
1464+
1465+
envBytes, err := utils.GetBytesEnvelope(tx)
1466+
if err != nil {
1467+
t.Fatalf("GetBytesEnvelope returned err %s", err)
1468+
}
1469+
1470+
policy, err := getSignedByMSPMemberPolicy(mspid)
1471+
if err != nil {
1472+
t.Fatalf("failed getting policy, err %s", err)
1473+
}
1474+
1475+
// execute the upgrade tx
1476+
args = [][]byte{[]byte("dv"), envBytes, policy}
1477+
if expecterr {
1478+
if res := stub.MockInvoke("1", args); res.Status == shim.OK {
1479+
t.Fatalf("vscc invoke should have failed")
1480+
}
1481+
} else {
1482+
if res := stub.MockInvoke("1", args); res.Status != shim.OK {
1483+
t.Fatalf("vscc invoke failed with %s", res.Message)
1484+
}
1485+
}
1486+
}
1487+
13761488
func TestValidateUpgradeWithPoliciesFail(t *testing.T) {
13771489
v := new(ValidatorOneValidSignature)
13781490
stub := shim.NewMockStub("validatoronevalidsignature", v)

0 commit comments

Comments
 (0)