github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/handlers/validation/builtin/v12/validation_logic_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 package v12 7 8 import ( 9 "fmt" 10 "io/ioutil" 11 "os" 12 "testing" 13 14 "github.com/golang/protobuf/proto" 15 "github.com/hechain20/hechain/bccsp/sw" 16 "github.com/hechain20/hechain/common/capabilities" 17 "github.com/hechain20/hechain/common/channelconfig" 18 "github.com/hechain20/hechain/common/policydsl" 19 "github.com/hechain20/hechain/core/committer/txvalidator/v14" 20 "github.com/hechain20/hechain/core/common/ccprovider" 21 "github.com/hechain20/hechain/core/common/privdata" 22 validation "github.com/hechain20/hechain/core/handlers/validation/api/capabilities" 23 vs "github.com/hechain20/hechain/core/handlers/validation/api/state" 24 "github.com/hechain20/hechain/core/handlers/validation/builtin/v12/mocks" 25 "github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/rwsetutil" 26 "github.com/hechain20/hechain/core/scc/lscc" 27 "github.com/hechain20/hechain/msp" 28 mspmgmt "github.com/hechain20/hechain/msp/mgmt" 29 msptesttools "github.com/hechain20/hechain/msp/mgmt/testtools" 30 "github.com/hechain20/hechain/protoutil" 31 "github.com/hyperledger/fabric-protos-go/common" 32 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 33 mspproto "github.com/hyperledger/fabric-protos-go/msp" 34 "github.com/hyperledger/fabric-protos-go/peer" 35 "github.com/pkg/errors" 36 "github.com/stretchr/testify/require" 37 ) 38 39 //go:generate counterfeiter -o mocks/state.go -fake-name State . vsState 40 41 type vsState interface { 42 vs.State 43 } 44 45 func createTx(endorsedByDuplicatedIdentity bool) (*common.Envelope, error) { 46 ccid := &peer.ChaincodeID{Name: "foo", Version: "v1"} 47 cis := &peer.ChaincodeInvocationSpec{ChaincodeSpec: &peer.ChaincodeSpec{ChaincodeId: ccid}} 48 49 prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid) 50 if err != nil { 51 return nil, err 52 } 53 54 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, []byte("res"), nil, ccid, id) 55 if err != nil { 56 return nil, err 57 } 58 59 var env *common.Envelope 60 if endorsedByDuplicatedIdentity { 61 env, err = protoutil.CreateSignedTx(prop, id, presp, presp) 62 } else { 63 env, err = protoutil.CreateSignedTx(prop, id, presp) 64 } 65 if err != nil { 66 return nil, err 67 } 68 return env, err 69 } 70 71 func createCCDataRWsetWithCollection(nameK, nameV, version string, policy []byte, collectionConfigPackage []byte) ([]byte, error) { 72 cd := &ccprovider.ChaincodeData{ 73 Name: nameV, 74 Version: version, 75 InstantiationPolicy: policy, 76 } 77 78 cdbytes := protoutil.MarshalOrPanic(cd) 79 80 rwsetBuilder := rwsetutil.NewRWSetBuilder() 81 rwsetBuilder.AddToWriteSet("lscc", nameK, cdbytes) 82 rwsetBuilder.AddToWriteSet("lscc", privdata.BuildCollectionKVSKey(nameK), collectionConfigPackage) 83 sr, err := rwsetBuilder.GetTxSimulationResults() 84 if err != nil { 85 return nil, err 86 } 87 return sr.GetPubSimulationBytes() 88 } 89 90 func createCCDataRWset(nameK, nameV, version string, policy []byte) ([]byte, error) { 91 cd := &ccprovider.ChaincodeData{ 92 Name: nameV, 93 Version: version, 94 InstantiationPolicy: policy, 95 } 96 97 cdbytes := protoutil.MarshalOrPanic(cd) 98 99 rwsetBuilder := rwsetutil.NewRWSetBuilder() 100 rwsetBuilder.AddToWriteSet("lscc", nameK, cdbytes) 101 sr, err := rwsetBuilder.GetTxSimulationResults() 102 if err != nil { 103 return nil, err 104 } 105 return sr.GetPubSimulationBytes() 106 } 107 108 func createLSCCTxWithCollection(ccname, ccver, f string, res []byte, policy []byte, ccpBytes []byte) (*common.Envelope, error) { 109 return createLSCCTxPutCdsWithCollection(ccname, ccver, f, res, nil, true, policy, ccpBytes) 110 } 111 112 func createLSCCTx(ccname, ccver, f string, res []byte) (*common.Envelope, error) { 113 return createLSCCTxPutCds(ccname, ccver, f, res, nil, true) 114 } 115 116 func createLSCCTxPutCdsWithCollection(ccname, ccver, f string, res, cdsbytes []byte, putcds bool, policy []byte, ccpBytes []byte) (*common.Envelope, error) { 117 cds := &peer.ChaincodeDeploymentSpec{ 118 ChaincodeSpec: &peer.ChaincodeSpec{ 119 ChaincodeId: &peer.ChaincodeID{ 120 Name: ccname, 121 Version: ccver, 122 }, 123 Type: peer.ChaincodeSpec_GOLANG, 124 }, 125 } 126 127 cdsBytes, err := proto.Marshal(cds) 128 if err != nil { 129 return nil, err 130 } 131 132 var cis *peer.ChaincodeInvocationSpec 133 if putcds { 134 if cdsbytes != nil { 135 cdsBytes = cdsbytes 136 } 137 cis = &peer.ChaincodeInvocationSpec{ 138 ChaincodeSpec: &peer.ChaincodeSpec{ 139 ChaincodeId: &peer.ChaincodeID{Name: "lscc"}, 140 Input: &peer.ChaincodeInput{ 141 Args: [][]byte{[]byte(f), []byte("barf"), cdsBytes, []byte("escc"), []byte("vscc"), policy, ccpBytes}, 142 }, 143 Type: peer.ChaincodeSpec_GOLANG, 144 }, 145 } 146 } else { 147 cis = &peer.ChaincodeInvocationSpec{ 148 ChaincodeSpec: &peer.ChaincodeSpec{ 149 ChaincodeId: &peer.ChaincodeID{Name: "lscc"}, 150 Input: &peer.ChaincodeInput{ 151 Args: [][]byte{[]byte(f), []byte("barf")}, 152 }, 153 Type: peer.ChaincodeSpec_GOLANG, 154 }, 155 } 156 } 157 158 prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid) 159 if err != nil { 160 return nil, err 161 } 162 163 ccid := &peer.ChaincodeID{Name: ccname, Version: ccver} 164 165 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, res, nil, ccid, id) 166 if err != nil { 167 return nil, err 168 } 169 170 return protoutil.CreateSignedTx(prop, id, presp) 171 } 172 173 func createLSCCTxPutCds(ccname, ccver, f string, res, cdsbytes []byte, putcds bool) (*common.Envelope, error) { 174 cds := &peer.ChaincodeDeploymentSpec{ 175 ChaincodeSpec: &peer.ChaincodeSpec{ 176 ChaincodeId: &peer.ChaincodeID{ 177 Name: ccname, 178 Version: ccver, 179 }, 180 Type: peer.ChaincodeSpec_GOLANG, 181 }, 182 } 183 184 cdsBytes, err := proto.Marshal(cds) 185 if err != nil { 186 return nil, err 187 } 188 189 var cis *peer.ChaincodeInvocationSpec 190 if putcds { 191 if cdsbytes != nil { 192 cdsBytes = cdsbytes 193 } 194 cis = &peer.ChaincodeInvocationSpec{ 195 ChaincodeSpec: &peer.ChaincodeSpec{ 196 ChaincodeId: &peer.ChaincodeID{Name: "lscc"}, 197 Input: &peer.ChaincodeInput{ 198 Args: [][]byte{[]byte(f), []byte("barf"), cdsBytes}, 199 }, 200 Type: peer.ChaincodeSpec_GOLANG, 201 }, 202 } 203 } else { 204 cis = &peer.ChaincodeInvocationSpec{ 205 ChaincodeSpec: &peer.ChaincodeSpec{ 206 ChaincodeId: &peer.ChaincodeID{Name: "lscc"}, 207 Input: &peer.ChaincodeInput{ 208 Args: [][]byte{[]byte(f), []byte(ccname)}, 209 }, 210 Type: peer.ChaincodeSpec_GOLANG, 211 }, 212 } 213 } 214 215 prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid) 216 if err != nil { 217 return nil, err 218 } 219 220 ccid := &peer.ChaincodeID{Name: ccname, Version: ccver} 221 222 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, res, nil, ccid, id) 223 if err != nil { 224 return nil, err 225 } 226 227 return protoutil.CreateSignedTx(prop, id, presp) 228 } 229 230 func getSignedByMSPMemberPolicy(mspID string) ([]byte, error) { 231 p := policydsl.SignedByMspMember(mspID) 232 233 b, err := protoutil.Marshal(p) 234 if err != nil { 235 return nil, fmt.Errorf("Could not marshal policy, err %s", err) 236 } 237 238 return b, err 239 } 240 241 func getSignedByOneMemberTwicePolicy(mspID string) ([]byte, error) { 242 principal := &mspproto.MSPPrincipal{ 243 PrincipalClassification: mspproto.MSPPrincipal_ROLE, 244 Principal: protoutil.MarshalOrPanic(&mspproto.MSPRole{Role: mspproto.MSPRole_MEMBER, MspIdentifier: mspID}), 245 } 246 247 p := &common.SignaturePolicyEnvelope{ 248 Version: 0, 249 Rule: policydsl.NOutOf(2, []*common.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(0)}), 250 Identities: []*mspproto.MSPPrincipal{principal}, 251 } 252 b, err := protoutil.Marshal(p) 253 if err != nil { 254 return nil, fmt.Errorf("Could not marshal policy, err %s", err) 255 } 256 257 return b, err 258 } 259 260 func getSignedByMSPAdminPolicy(mspID string) ([]byte, error) { 261 p := policydsl.SignedByMspAdmin(mspID) 262 263 b, err := protoutil.Marshal(p) 264 if err != nil { 265 return nil, fmt.Errorf("Could not marshal policy, err %s", err) 266 } 267 268 return b, err 269 } 270 271 func newValidationInstance(state map[string]map[string][]byte) *Validator { 272 c := &mocks.Capabilities{} 273 c.On("PrivateChannelData").Return(false) 274 c.On("V1_1Validation").Return(false) 275 c.On("V1_2Validation").Return(false) 276 vs := &mocks.State{} 277 vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) { 278 if ns, ok := state[namespace]; ok { 279 return [][]byte{ns[keys[0]]}, nil 280 } else { 281 return nil, fmt.Errorf("could not retrieve namespace %s", namespace) 282 } 283 } 284 sf := &mocks.StateFetcher{} 285 sf.On("FetchState").Return(vs, nil) 286 return newCustomValidationInstance(sf, c) 287 } 288 289 func newCustomValidationInstance(sf StateFetcher, c validation.Capabilities) *Validator { 290 is := &mocks.IdentityDeserializer{} 291 pe := &txvalidator.PolicyEvaluator{ 292 IdentityDeserializer: mspmgmt.GetManagerForChain("testchannelid"), 293 } 294 return New(c, sf, is, pe) 295 } 296 297 func TestDeduplicateIdentity(t *testing.T) { 298 // We allocate a slice with capacity greater than the length 299 proposalResponsePayload := []byte{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3} 300 prpBuff := make([]byte, len(proposalResponsePayload), len(proposalResponsePayload)*2) 301 copy(prpBuff, proposalResponsePayload) 302 303 identity1 := protoutil.MarshalOrPanic(&mspproto.SerializedIdentity{ 304 IdBytes: []byte{1, 1, 1}, 305 }) 306 identity2 := protoutil.MarshalOrPanic(&mspproto.SerializedIdentity{ 307 IdBytes: []byte{2, 2, 2}, 308 }) 309 310 chaincodeActionPayload := &peer.ChaincodeActionPayload{ 311 Action: &peer.ChaincodeEndorsedAction{ 312 Endorsements: []*peer.Endorsement{ 313 { 314 Endorser: identity1, 315 }, 316 { 317 Endorser: identity2, 318 }, 319 }, 320 ProposalResponsePayload: prpBuff, 321 }, 322 } 323 324 signedData, err := (&Validator{}).deduplicateIdentity(chaincodeActionPayload) 325 require.NoError(t, err) 326 // The original bytes of proposalResponsePayload are preserved 327 require.Equal(t, proposalResponsePayload, signedData[0].Data[:len(proposalResponsePayload)]) 328 require.Equal(t, proposalResponsePayload, signedData[1].Data[:len(proposalResponsePayload)]) 329 // And are suffixed with the identity bytes 330 require.Equal(t, identity1, signedData[0].Data[len(proposalResponsePayload):]) 331 require.Equal(t, identity2, signedData[1].Data[len(proposalResponsePayload):]) 332 } 333 334 func TestInvoke(t *testing.T) { 335 v := newValidationInstance(make(map[string]map[string][]byte)) 336 337 // broken Envelope 338 var err error 339 b := &common.Block{Data: &common.BlockData{Data: [][]byte{[]byte("a")}}} 340 err = v.Validate(b, "foo", 0, 0, []byte("a")) 341 require.Error(t, err) 342 343 // (still) broken Envelope 344 b = &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(&common.Envelope{Payload: []byte("barf")})}}} 345 err = v.Validate(b, "foo", 0, 0, []byte("a")) 346 require.Error(t, err) 347 348 // (still) broken Envelope 349 e := protoutil.MarshalOrPanic(&common.Envelope{Payload: protoutil.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: []byte("barf")}})}) 350 b = &common.Block{Data: &common.BlockData{Data: [][]byte{e}}} 351 err = v.Validate(b, "foo", 0, 0, []byte("a")) 352 require.Error(t, err) 353 354 tx, err := createTx(false) 355 if err != nil { 356 t.Fatalf("createTx returned err %s", err) 357 } 358 359 envBytes, err := protoutil.GetBytesEnvelope(tx) 360 if err != nil { 361 t.Fatalf("GetBytesEnvelope returned err %s", err) 362 } 363 364 // broken policy 365 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 366 err = v.Validate(b, "foo", 0, 0, []byte("barf")) 367 require.Error(t, err) 368 369 policy, err := getSignedByMSPMemberPolicy(mspid) 370 if err != nil { 371 t.Fatalf("failed getting policy, err %s", err) 372 } 373 374 // broken type 375 e = protoutil.MarshalOrPanic(&common.Envelope{Payload: protoutil.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_ORDERER_TRANSACTION)})}})}) 376 b = &common.Block{Data: &common.BlockData{Data: [][]byte{e}}} 377 err = v.Validate(b, "foo", 0, 0, policy) 378 require.Error(t, err) 379 380 // broken tx payload 381 e = protoutil.MarshalOrPanic(&common.Envelope{Payload: protoutil.MarshalOrPanic(&common.Payload{Header: &common.Header{ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{Type: int32(common.HeaderType_ORDERER_TRANSACTION)})}})}) 382 b = &common.Block{Data: &common.BlockData{Data: [][]byte{e}}} 383 err = v.Validate(b, "foo", 0, 0, policy) 384 require.Error(t, err) 385 386 // good path: signed by the right MSP 387 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 388 err = v.Validate(b, "foo", 0, 0, policy) 389 require.NoError(t, err) 390 391 // bad path: signed by the wrong MSP 392 policy, err = getSignedByMSPMemberPolicy("barf") 393 if err != nil { 394 t.Fatalf("failed getting policy, err %s", err) 395 } 396 397 err = v.Validate(b, "foo", 0, 0, policy) 398 require.Error(t, err) 399 400 // bad path: signed by duplicated MSP identity 401 policy, err = getSignedByOneMemberTwicePolicy(mspid) 402 if err != nil { 403 t.Fatalf("failed getting policy, err %s", err) 404 } 405 tx, err = createTx(true) 406 if err != nil { 407 t.Fatalf("createTx returned err %s", err) 408 } 409 envBytes, err = protoutil.GetBytesEnvelope(tx) 410 if err != nil { 411 t.Fatalf("GetBytesEnvelope returned err %s", err) 412 } 413 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 414 err = v.Validate(b, "foo", 0, 0, policy) 415 require.Error(t, err) 416 } 417 418 func TestRWSetTooBig(t *testing.T) { 419 state := make(map[string]map[string][]byte) 420 state["lscc"] = make(map[string][]byte) 421 422 v := newValidationInstance(state) 423 424 ccname := "mycc" 425 ccver := "1" 426 427 cd := &ccprovider.ChaincodeData{ 428 Name: ccname, 429 Version: ccver, 430 InstantiationPolicy: nil, 431 } 432 433 cdbytes := protoutil.MarshalOrPanic(cd) 434 435 rwsetBuilder := rwsetutil.NewRWSetBuilder() 436 rwsetBuilder.AddToWriteSet("lscc", ccname, cdbytes) 437 rwsetBuilder.AddToWriteSet("lscc", "spurious", []byte("spurious")) 438 439 sr, err := rwsetBuilder.GetTxSimulationResults() 440 require.NoError(t, err) 441 srBytes, err := sr.GetPubSimulationBytes() 442 require.NoError(t, err) 443 tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, srBytes) 444 if err != nil { 445 t.Fatalf("createTx returned err %s", err) 446 } 447 448 envBytes, err := protoutil.GetBytesEnvelope(tx) 449 if err != nil { 450 t.Fatalf("GetBytesEnvelope returned err %s", err) 451 } 452 453 // good path: signed by the right MSP 454 policy, err := getSignedByMSPMemberPolicy(mspid) 455 if err != nil { 456 t.Fatalf("failed getting policy, err %s", err) 457 } 458 459 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 460 err = v.Validate(b, "lscc", 0, 0, policy) 461 require.EqualError(t, err, "LSCC can only issue a single putState upon deploy") 462 t.Logf("error: %s", err) 463 } 464 465 func TestValidateDeployFail(t *testing.T) { 466 state := make(map[string]map[string][]byte) 467 state["lscc"] = make(map[string][]byte) 468 469 v := newValidationInstance(state) 470 471 ccname := "mycc" 472 ccver := "1" 473 474 /*********************/ 475 /* test no write set */ 476 /*********************/ 477 478 tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, nil) 479 if err != nil { 480 t.Fatalf("createTx returned err %s", err) 481 } 482 483 envBytes, err := protoutil.GetBytesEnvelope(tx) 484 if err != nil { 485 t.Fatalf("GetBytesEnvelope returned err %s", err) 486 } 487 488 // good path: signed by the right MSP 489 policy, err := getSignedByMSPMemberPolicy(mspid) 490 if err != nil { 491 t.Fatalf("failed getting policy, err %s", err) 492 } 493 494 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 495 err = v.Validate(b, "lscc", 0, 0, policy) 496 require.EqualError(t, err, "No read write set for lscc was found") 497 498 /************************/ 499 /* test bogus write set */ 500 /************************/ 501 502 rwsetBuilder := rwsetutil.NewRWSetBuilder() 503 rwsetBuilder.AddToWriteSet("lscc", ccname, []byte("barf")) 504 sr, err := rwsetBuilder.GetTxSimulationResults() 505 require.NoError(t, err) 506 resBogusBytes, err := sr.GetPubSimulationBytes() 507 require.NoError(t, err) 508 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, resBogusBytes) 509 if err != nil { 510 t.Fatalf("createTx returned err %s", err) 511 } 512 513 envBytes, err = protoutil.GetBytesEnvelope(tx) 514 if err != nil { 515 t.Fatalf("GetBytesEnvelope returned err %s", err) 516 } 517 518 // good path: signed by the right MSP 519 policy, err = getSignedByMSPMemberPolicy(mspid) 520 if err != nil { 521 t.Fatalf("failed getting policy, err %s", err) 522 } 523 524 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 525 err = v.Validate(b, "lscc", 0, 0, policy) 526 require.EqualError(t, err, "unmarhsalling of ChaincodeData failed, error unexpected EOF") 527 528 /**********************/ 529 /* test bad LSCC args */ 530 /**********************/ 531 532 res, err := createCCDataRWset(ccname, ccname, ccver, nil) 533 require.NoError(t, err) 534 535 tx, err = createLSCCTxPutCds(ccname, ccver, lscc.DEPLOY, res, nil, false) 536 if err != nil { 537 t.Fatalf("createTx returned err %s", err) 538 } 539 540 envBytes, err = protoutil.GetBytesEnvelope(tx) 541 if err != nil { 542 t.Fatalf("GetBytesEnvelope returned err %s", err) 543 } 544 545 // good path: signed by the right MSP 546 policy, err = getSignedByMSPMemberPolicy(mspid) 547 if err != nil { 548 t.Fatalf("failed getting policy, err %s", err) 549 } 550 551 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 552 err = v.Validate(b, "lscc", 0, 0, policy) 553 require.EqualError(t, err, "Wrong number of arguments for invocation lscc(deploy): expected at least 2, received 1") 554 555 /**********************/ 556 /* test bad LSCC args */ 557 /**********************/ 558 559 res, err = createCCDataRWset(ccname, ccname, ccver, nil) 560 require.NoError(t, err) 561 562 tx, err = createLSCCTxPutCds(ccname, ccver, lscc.DEPLOY, res, []byte("barf"), true) 563 if err != nil { 564 t.Fatalf("createTx returned err %s", err) 565 } 566 567 envBytes, err = protoutil.GetBytesEnvelope(tx) 568 if err != nil { 569 t.Fatalf("GetBytesEnvelope returned err %s", err) 570 } 571 572 // good path: signed by the right MSP 573 policy, err = getSignedByMSPMemberPolicy(mspid) 574 if err != nil { 575 t.Fatalf("failed getting policy, err %s", err) 576 } 577 578 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 579 err = v.Validate(b, "lscc", 0, 0, policy) 580 require.EqualError(t, err, "GetChaincodeDeploymentSpec error error unmarshalling ChaincodeDeploymentSpec: unexpected EOF") 581 582 /***********************/ 583 /* test bad cc version */ 584 /***********************/ 585 586 res, err = createCCDataRWset(ccname, ccname, ccver+".1", nil) 587 require.NoError(t, err) 588 589 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 590 if err != nil { 591 t.Fatalf("createTx returned err %s", err) 592 } 593 594 envBytes, err = protoutil.GetBytesEnvelope(tx) 595 if err != nil { 596 t.Fatalf("GetBytesEnvelope returned err %s", err) 597 } 598 599 // good path: signed by the right MSP 600 policy, err = getSignedByMSPMemberPolicy(mspid) 601 if err != nil { 602 t.Fatalf("failed getting policy, err %s", err) 603 } 604 605 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 606 err = v.Validate(b, "lscc", 0, 0, policy) 607 require.EqualError(t, err, "expected cc version 1, found 1.1") 608 609 /*************/ 610 /* bad rwset */ 611 /*************/ 612 613 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, []byte("barf")) 614 if err != nil { 615 t.Fatalf("createTx returned err %s", err) 616 } 617 618 envBytes, err = protoutil.GetBytesEnvelope(tx) 619 if err != nil { 620 t.Fatalf("GetBytesEnvelope returned err %s", err) 621 } 622 623 // good path: signed by the right MSP 624 policy, err = getSignedByMSPMemberPolicy(mspid) 625 if err != nil { 626 t.Fatalf("failed getting policy, err %s", err) 627 } 628 629 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 630 err = v.Validate(b, "lscc", 0, 0, policy) 631 require.EqualError(t, err, "txRWSet.FromProtoBytes error unexpected EOF") 632 633 /********************/ 634 /* test bad cc name */ 635 /********************/ 636 637 res, err = createCCDataRWset(ccname+".badbad", ccname, ccver, nil) 638 require.NoError(t, err) 639 640 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 641 if err != nil { 642 t.Fatalf("createTx returned err %s", err) 643 } 644 645 envBytes, err = protoutil.GetBytesEnvelope(tx) 646 if err != nil { 647 t.Fatalf("GetBytesEnvelope returned err %s", err) 648 } 649 650 policy, err = getSignedByMSPMemberPolicy(mspid) 651 if err != nil { 652 t.Fatalf("failed getting policy, err %s", err) 653 } 654 655 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 656 err = v.Validate(b, "lscc", 0, 0, policy) 657 require.EqualError(t, err, "expected key mycc, found mycc.badbad") 658 659 /**********************/ 660 /* test bad cc name 2 */ 661 /**********************/ 662 663 res, err = createCCDataRWset(ccname, ccname+".badbad", ccver, nil) 664 require.NoError(t, err) 665 666 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 667 if err != nil { 668 t.Fatalf("createTx returned err %s", err) 669 } 670 671 envBytes, err = protoutil.GetBytesEnvelope(tx) 672 if err != nil { 673 t.Fatalf("GetBytesEnvelope returned err %s", err) 674 } 675 676 policy, err = getSignedByMSPMemberPolicy(mspid) 677 if err != nil { 678 t.Fatalf("failed getting policy, err %s", err) 679 } 680 681 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 682 err = v.Validate(b, "lscc", 0, 0, policy) 683 require.EqualError(t, err, "expected cc name mycc, found mycc.badbad") 684 685 /************************/ 686 /* test spurious writes */ 687 /************************/ 688 689 cd := &ccprovider.ChaincodeData{ 690 Name: ccname, 691 Version: ccver, 692 InstantiationPolicy: nil, 693 } 694 695 cdbytes := protoutil.MarshalOrPanic(cd) 696 rwsetBuilder = rwsetutil.NewRWSetBuilder() 697 rwsetBuilder.AddToWriteSet("lscc", ccname, cdbytes) 698 rwsetBuilder.AddToWriteSet("bogusbogus", "key", []byte("val")) 699 sr, err = rwsetBuilder.GetTxSimulationResults() 700 require.NoError(t, err) 701 srBytes, err := sr.GetPubSimulationBytes() 702 require.NoError(t, err) 703 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, srBytes) 704 if err != nil { 705 t.Fatalf("createTx returned err %s", err) 706 } 707 708 envBytes, err = protoutil.GetBytesEnvelope(tx) 709 if err != nil { 710 t.Fatalf("GetBytesEnvelope returned err %s", err) 711 } 712 713 policy, err = getSignedByMSPMemberPolicy(mspid) 714 if err != nil { 715 t.Fatalf("failed getting policy, err %s", err) 716 } 717 718 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 719 err = v.Validate(b, "lscc", 0, 0, policy) 720 require.EqualError(t, err, "LSCC invocation is attempting to write to namespace bogusbogus") 721 } 722 723 func TestAlreadyDeployed(t *testing.T) { 724 state := make(map[string]map[string][]byte) 725 state["lscc"] = make(map[string][]byte) 726 727 v := newValidationInstance(state) 728 729 ccname := "mycc" 730 ccver := "alreadydeployed" 731 732 // create state for ccname to simulate deployment 733 state["lscc"][ccname] = []byte{} 734 735 simresres, err := createCCDataRWset(ccname, ccname, ccver, nil) 736 require.NoError(t, err) 737 738 tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, simresres) 739 if err != nil { 740 t.Fatalf("createTx returned err %s", err) 741 } 742 743 envBytes, err := protoutil.GetBytesEnvelope(tx) 744 if err != nil { 745 t.Fatalf("GetBytesEnvelope returned err %s", err) 746 } 747 748 // good path: signed by the right MSP 749 policy, err := getSignedByMSPMemberPolicy(mspid) 750 if err != nil { 751 t.Fatalf("failed getting policy, err %s", err) 752 } 753 754 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 755 err = v.Validate(bl, "lscc", 0, 0, policy) 756 require.EqualError(t, err, "Chaincode mycc is already instantiated") 757 } 758 759 func TestValidateDeployNoLedger(t *testing.T) { 760 sf := &mocks.StateFetcher{} 761 sf.On("FetchState").Return(nil, errors.New("failed obtaining query executor")) 762 capabilities := &mocks.Capabilities{} 763 capabilities.On("PrivateChannelData").Return(false) 764 capabilities.On("V1_1Validation").Return(false) 765 capabilities.On("V1_2Validation").Return(false) 766 v := newCustomValidationInstance(sf, capabilities) 767 768 ccname := "mycc" 769 ccver := "1" 770 771 defaultPolicy, err := getSignedByMSPAdminPolicy(mspid) 772 require.NoError(t, err) 773 res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy) 774 require.NoError(t, err) 775 776 tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 777 if err != nil { 778 t.Fatalf("createTx returned err %s", err) 779 } 780 781 envBytes, err := protoutil.GetBytesEnvelope(tx) 782 if err != nil { 783 t.Fatalf("GetBytesEnvelope returned err %s", err) 784 } 785 786 // good path: signed by the right MSP 787 policy, err := getSignedByMSPMemberPolicy(mspid) 788 if err != nil { 789 t.Fatalf("failed getting policy, err %s", err) 790 } 791 792 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 793 err = v.Validate(b, "lscc", 0, 0, policy) 794 require.EqualError(t, err, "could not retrieve QueryExecutor for channel testchannelid, error failed obtaining query executor") 795 } 796 797 func TestValidateDeployNOKNilChaincodeSpec(t *testing.T) { 798 state := make(map[string]map[string][]byte) 799 state["lscc"] = make(map[string][]byte) 800 801 v := newValidationInstance(state) 802 803 ccname := "mycc" 804 ccver := "1" 805 806 defaultPolicy, err := getSignedByMSPAdminPolicy(mspid) 807 require.NoError(t, err) 808 res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy) 809 require.NoError(t, err) 810 811 // Create a ChaincodeDeploymentSpec with nil ChaincodeSpec for negative test 812 cdsBytes, err := proto.Marshal(&peer.ChaincodeDeploymentSpec{}) 813 require.NoError(t, err) 814 815 // ChaincodeDeploymentSpec/ChaincodeSpec are derived from cdsBytes (i.e., cis.ChaincodeSpec.Input.Args[2]) 816 cis := &peer.ChaincodeInvocationSpec{ 817 ChaincodeSpec: &peer.ChaincodeSpec{ 818 ChaincodeId: &peer.ChaincodeID{Name: "lscc"}, 819 Input: &peer.ChaincodeInput{ 820 Args: [][]byte{[]byte(lscc.DEPLOY), []byte("barf"), cdsBytes}, 821 }, 822 Type: peer.ChaincodeSpec_GOLANG, 823 }, 824 } 825 826 prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, sid) 827 require.NoError(t, err) 828 829 ccid := &peer.ChaincodeID{Name: ccname, Version: ccver} 830 831 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, res, nil, ccid, id) 832 require.NoError(t, err) 833 834 env, err := protoutil.CreateSignedTx(prop, id, presp) 835 require.NoError(t, err) 836 837 // good path: signed by the right MSP 838 policy, err := getSignedByMSPMemberPolicy(mspid) 839 if err != nil { 840 t.Fatalf("failed getting policy, err %s", err) 841 } 842 843 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(env)}}, Header: &common.BlockHeader{}} 844 err = v.Validate(b, "lscc", 0, 0, policy) 845 require.EqualError(t, err, "VSCC error: invocation of lscc(deploy) does not have appropriate arguments") 846 } 847 848 func TestValidateDeployOK(t *testing.T) { 849 state := make(map[string]map[string][]byte) 850 state["lscc"] = make(map[string][]byte) 851 852 v := newValidationInstance(state) 853 854 ccname := "mycc" 855 ccver := "1" 856 857 defaultPolicy, err := getSignedByMSPAdminPolicy(mspid) 858 require.NoError(t, err) 859 res, err := createCCDataRWset(ccname, ccname, ccver, defaultPolicy) 860 require.NoError(t, err) 861 862 tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 863 if err != nil { 864 t.Fatalf("createTx returned err %s", err) 865 } 866 867 envBytes, err := protoutil.GetBytesEnvelope(tx) 868 if err != nil { 869 t.Fatalf("GetBytesEnvelope returned err %s", err) 870 } 871 872 // good path: signed by the right MSP 873 policy, err := getSignedByMSPMemberPolicy(mspid) 874 if err != nil { 875 t.Fatalf("failed getting policy, err %s", err) 876 } 877 878 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 879 err = v.Validate(b, "lscc", 0, 0, policy) 880 require.NoError(t, err) 881 } 882 883 func TestValidateDeployNOK(t *testing.T) { 884 testCases := []struct { 885 description string 886 ccName string 887 ccVersion string 888 errMsg string 889 }{ 890 {description: "empty cc name", ccName: "", ccVersion: "1", errMsg: "invalid chaincode name ''"}, 891 {description: "bad first character in cc name", ccName: "_badname", ccVersion: "1.2", errMsg: "invalid chaincode name '_badname'"}, 892 {description: "bad character in cc name", ccName: "bad.name", ccVersion: "1-5", errMsg: "invalid chaincode name 'bad.name'"}, 893 {description: "empty cc version", ccName: "1good_name", ccVersion: "", errMsg: "invalid chaincode version ''"}, 894 {description: "bad cc version", ccName: "good-name", ccVersion: "$badversion", errMsg: "invalid chaincode version '$badversion'"}, 895 {description: "use system cc name", ccName: "qscc", ccVersion: "2.1", errMsg: "chaincode name 'qscc' is reserved for system chaincodes"}, 896 } 897 898 // create validator and policy 899 state := make(map[string]map[string][]byte) 900 state["lscc"] = make(map[string][]byte) 901 902 v := newValidationInstance(state) 903 904 policy, err := getSignedByMSPAdminPolicy(mspid) 905 require.NoError(t, err) 906 907 for _, tc := range testCases { 908 t.Run(tc.description, func(t *testing.T) { 909 testChaincodeDeployNOK(t, tc.ccName, tc.ccVersion, tc.errMsg, v, policy) 910 }) 911 } 912 } 913 914 func testChaincodeDeployNOK(t *testing.T, ccName, ccVersion, errMsg string, v *Validator, policy []byte) { 915 res, err := createCCDataRWset(ccName, ccName, ccVersion, policy) 916 require.NoError(t, err) 917 918 tx, err := createLSCCTx(ccName, ccVersion, lscc.DEPLOY, res) 919 if err != nil { 920 t.Fatalf("createTx returned err %s", err) 921 } 922 923 envBytes, err := protoutil.GetBytesEnvelope(tx) 924 if err != nil { 925 t.Fatalf("GetBytesEnvelope returned err %s", err) 926 } 927 928 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}, Header: &common.BlockHeader{}} 929 err = v.Validate(b, "lscc", 0, 0, policy) 930 require.EqualError(t, err, errMsg) 931 } 932 933 func TestValidateDeployWithCollection(t *testing.T) { 934 state := make(map[string]map[string][]byte) 935 state["lscc"] = make(map[string][]byte) 936 937 vs := &mocks.State{} 938 vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) { 939 if ns, ok := state[namespace]; ok { 940 return [][]byte{ns[keys[0]]}, nil 941 } else { 942 return nil, fmt.Errorf("could not retrieve namespace %s", namespace) 943 } 944 } 945 sf := &mocks.StateFetcher{} 946 sf.On("FetchState").Return(vs, nil) 947 capabilities := &mocks.Capabilities{} 948 capabilities.On("PrivateChannelData").Return(true) 949 capabilities.On("V1_1Validation").Return(true) 950 capabilities.On("V1_2Validation").Return(false) 951 v := newCustomValidationInstance(sf, capabilities) 952 953 ccname := "mycc" 954 ccver := "1" 955 956 collName1 := "mycollection1" 957 collName2 := "mycollection2" 958 signers := [][]byte{[]byte("signer0"), []byte("signer1")} 959 policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers) 960 var requiredPeerCount, maximumPeerCount int32 961 var blockToLive uint64 962 requiredPeerCount = 1 963 maximumPeerCount = 2 964 blockToLive = 1000 965 coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 966 coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 967 968 // Test 1: Deploy chaincode with a valid collection configs --> success 969 ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}} 970 ccpBytes, err := proto.Marshal(ccp) 971 require.NoError(t, err) 972 require.NotNil(t, ccpBytes) 973 974 defaultPolicy, err := getSignedByMSPAdminPolicy(mspid) 975 require.NoError(t, err) 976 res, err := createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes) 977 require.NoError(t, err) 978 979 tx, err := createLSCCTxWithCollection(ccname, ccver, lscc.DEPLOY, res, defaultPolicy, ccpBytes) 980 if err != nil { 981 t.Fatalf("createTx returned err %s", err) 982 } 983 984 envBytes, err := protoutil.GetBytesEnvelope(tx) 985 if err != nil { 986 t.Fatalf("GetBytesEnvelope returned err %s", err) 987 } 988 989 // good path: signed by the right MSP 990 policy, err := getSignedByMSPMemberPolicy(mspid) 991 if err != nil { 992 t.Fatalf("failed getting policy, err %s", err) 993 } 994 995 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 996 err = v.Validate(b, "lscc", 0, 0, policy) 997 require.NoError(t, err) 998 999 // Test 2: Deploy the chaincode with duplicate collection configs --> no error as the 1000 // peer is not in V1_2Validation mode 1001 ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2, coll1}} 1002 ccpBytes, err = proto.Marshal(ccp) 1003 require.NoError(t, err) 1004 require.NotNil(t, ccpBytes) 1005 1006 res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes) 1007 require.NoError(t, err) 1008 1009 tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.DEPLOY, res, defaultPolicy, ccpBytes) 1010 if err != nil { 1011 t.Fatalf("createTx returned err %s", err) 1012 } 1013 1014 envBytes, err = protoutil.GetBytesEnvelope(tx) 1015 if err != nil { 1016 t.Fatalf("GetBytesEnvelope returned err %s", err) 1017 } 1018 1019 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1020 err = v.Validate(b, "lscc", 0, 0, policy) 1021 require.NoError(t, err) 1022 1023 // Test 3: Once the V1_2Validation is enabled, validation should fail due to duplicate collection configs 1024 capabilities = &mocks.Capabilities{} 1025 capabilities.On("PrivateChannelData").Return(true) 1026 capabilities.On("V1_2Validation").Return(true) 1027 v = newCustomValidationInstance(sf, capabilities) 1028 1029 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1030 err = v.Validate(b, "lscc", 0, 0, policy) 1031 require.EqualError(t, err, "collection-name: mycollection1 -- found duplicate collection configuration") 1032 } 1033 1034 func TestValidateDeployWithPolicies(t *testing.T) { 1035 state := make(map[string]map[string][]byte) 1036 state["lscc"] = make(map[string][]byte) 1037 1038 v := newValidationInstance(state) 1039 1040 ccname := "mycc" 1041 ccver := "1" 1042 1043 /*********************************************/ 1044 /* test 1: success with an accept-all policy */ 1045 /*********************************************/ 1046 1047 res, err := createCCDataRWset(ccname, ccname, ccver, policydsl.MarshaledAcceptAllPolicy) 1048 require.NoError(t, err) 1049 1050 tx, err := createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 1051 if err != nil { 1052 t.Fatalf("createTx returned err %s", err) 1053 } 1054 1055 envBytes, err := protoutil.GetBytesEnvelope(tx) 1056 if err != nil { 1057 t.Fatalf("GetBytesEnvelope returned err %s", err) 1058 } 1059 1060 // good path: signed by the right MSP 1061 policy, err := getSignedByMSPMemberPolicy(mspid) 1062 if err != nil { 1063 t.Fatalf("failed getting policy, err %s", err) 1064 } 1065 1066 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1067 err = v.Validate(b, "lscc", 0, 0, policy) 1068 require.NoError(t, err) 1069 1070 /********************************************/ 1071 /* test 2: failure with a reject-all policy */ 1072 /********************************************/ 1073 1074 res, err = createCCDataRWset(ccname, ccname, ccver, policydsl.MarshaledRejectAllPolicy) 1075 require.NoError(t, err) 1076 1077 tx, err = createLSCCTx(ccname, ccver, lscc.DEPLOY, res) 1078 if err != nil { 1079 t.Fatalf("createTx returned err %s", err) 1080 } 1081 1082 envBytes, err = protoutil.GetBytesEnvelope(tx) 1083 if err != nil { 1084 t.Fatalf("GetBytesEnvelope returned err %s", err) 1085 } 1086 1087 // good path: signed by the right MSP 1088 policy, err = getSignedByMSPMemberPolicy(mspid) 1089 if err != nil { 1090 t.Fatalf("failed getting policy, err %s", err) 1091 } 1092 1093 b = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1094 err = v.Validate(b, "lscc", 0, 0, policy) 1095 require.EqualError(t, err, "chaincode instantiation policy violated, error signature set did not satisfy policy") 1096 } 1097 1098 func TestInvalidUpgrade(t *testing.T) { 1099 state := make(map[string]map[string][]byte) 1100 state["lscc"] = make(map[string][]byte) 1101 1102 v := newValidationInstance(state) 1103 1104 ccname := "mycc" 1105 ccver := "2" 1106 1107 simresres, err := createCCDataRWset(ccname, ccname, ccver, nil) 1108 require.NoError(t, err) 1109 1110 tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres) 1111 if err != nil { 1112 t.Fatalf("createTx returned err %s", err) 1113 } 1114 1115 envBytes, err := protoutil.GetBytesEnvelope(tx) 1116 if err != nil { 1117 t.Fatalf("GetBytesEnvelope returned err %s", err) 1118 } 1119 1120 // good path: signed by the right MSP 1121 policy, err := getSignedByMSPMemberPolicy(mspid) 1122 if err != nil { 1123 t.Fatalf("failed getting policy, err %s", err) 1124 } 1125 1126 b := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1127 err = v.Validate(b, "lscc", 0, 0, policy) 1128 require.EqualError(t, err, "Upgrading non-existent chaincode mycc") 1129 } 1130 1131 func TestValidateUpgradeOK(t *testing.T) { 1132 state := make(map[string]map[string][]byte) 1133 state["lscc"] = make(map[string][]byte) 1134 1135 v := newValidationInstance(state) 1136 1137 ccname := "mycc" 1138 ccver := "upgradeok" 1139 ccver = "2" 1140 1141 // policy signed by the right MSP 1142 policy, err := getSignedByMSPMemberPolicy(mspid) 1143 if err != nil { 1144 t.Fatalf("failed getting policy, err %s", err) 1145 } 1146 1147 // create lscc record 1148 cd := &ccprovider.ChaincodeData{ 1149 InstantiationPolicy: policy, 1150 } 1151 cdbytes, err := proto.Marshal(cd) 1152 if err != nil { 1153 t.Fatalf("Failed to marshal ChaincodeData: %s", err) 1154 } 1155 state["lscc"][ccname] = cdbytes 1156 1157 simresres, err := createCCDataRWset(ccname, ccname, ccver, nil) 1158 require.NoError(t, err) 1159 1160 tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres) 1161 if err != nil { 1162 t.Fatalf("createTx returned err %s", err) 1163 } 1164 1165 envBytes, err := protoutil.GetBytesEnvelope(tx) 1166 if err != nil { 1167 t.Fatalf("GetBytesEnvelope returned err %s", err) 1168 } 1169 1170 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1171 err = v.Validate(bl, "lscc", 0, 0, policy) 1172 require.NoError(t, err) 1173 } 1174 1175 func TestInvalidateUpgradeBadVersion(t *testing.T) { 1176 state := make(map[string]map[string][]byte) 1177 state["lscc"] = make(map[string][]byte) 1178 1179 v := newValidationInstance(state) 1180 1181 ccname := "mycc" 1182 ccver := "upgradebadversion" 1183 1184 // policy signed by the right MSP 1185 policy, err := getSignedByMSPMemberPolicy(mspid) 1186 if err != nil { 1187 t.Fatalf("failed getting policy, err %s", err) 1188 } 1189 1190 // create lscc record 1191 cd := &ccprovider.ChaincodeData{ 1192 InstantiationPolicy: policy, 1193 Version: ccver, 1194 } 1195 cdbytes, err := proto.Marshal(cd) 1196 if err != nil { 1197 t.Fatalf("Failed to marshal ChaincodeData: %s", err) 1198 } 1199 state["lscc"][ccname] = cdbytes 1200 1201 simresres, err := createCCDataRWset(ccname, ccname, ccver, nil) 1202 require.NoError(t, err) 1203 1204 tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres) 1205 if err != nil { 1206 t.Fatalf("createTx returned err %s", err) 1207 } 1208 1209 envBytes, err := protoutil.GetBytesEnvelope(tx) 1210 if err != nil { 1211 t.Fatalf("GetBytesEnvelope returned err %s", err) 1212 } 1213 1214 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1215 err = v.Validate(bl, "lscc", 0, 0, policy) 1216 require.EqualError(t, err, fmt.Sprintf("Existing version of the cc on the ledger (%s) should be different from the upgraded one", ccver)) 1217 } 1218 1219 func validateUpgradeWithCollection(t *testing.T, V1_2Validation bool) { 1220 state := make(map[string]map[string][]byte) 1221 state["lscc"] = make(map[string][]byte) 1222 1223 vs := &mocks.State{} 1224 vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) { 1225 if ns, ok := state[namespace]; ok { 1226 return [][]byte{ns[keys[0]]}, nil 1227 } else { 1228 return nil, fmt.Errorf("could not retrieve namespace %s", namespace) 1229 } 1230 } 1231 sf := &mocks.StateFetcher{} 1232 sf.On("FetchState").Return(vs, nil) 1233 capabilities := &mocks.Capabilities{} 1234 capabilities.On("PrivateChannelData").Return(true) 1235 capabilities.On("V1_1Validation").Return(true) 1236 capabilities.On("V1_2Validation").Return(V1_2Validation) 1237 v := newCustomValidationInstance(sf, capabilities) 1238 1239 ccname := "mycc" 1240 ccver := "2" 1241 1242 policy, err := getSignedByMSPMemberPolicy(mspid) 1243 if err != nil { 1244 t.Fatalf("failed getting policy, err %s", err) 1245 } 1246 1247 // create lscc record 1248 cd := &ccprovider.ChaincodeData{ 1249 InstantiationPolicy: policy, 1250 } 1251 cdbytes, err := proto.Marshal(cd) 1252 if err != nil { 1253 t.Fatalf("Failed to marshal ChaincodeData: %s", err) 1254 } 1255 state["lscc"][ccname] = cdbytes 1256 1257 collName1 := "mycollection1" 1258 collName2 := "mycollection2" 1259 signers := [][]byte{[]byte("signer0"), []byte("signer1")} 1260 policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers) 1261 var requiredPeerCount, maximumPeerCount int32 1262 var blockToLive uint64 1263 requiredPeerCount = 1 1264 maximumPeerCount = 2 1265 blockToLive = 1000 1266 coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1267 coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1268 1269 // Test 1: Valid Collection Config in the upgrade. 1270 // V1_2Validation enabled: success 1271 // V1_2Validation disable: fail (as no collection updates are allowed) 1272 // Note: We might change V1_2Validation with CollectionUpdate capability 1273 ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}} 1274 ccpBytes, err := proto.Marshal(ccp) 1275 require.NoError(t, err) 1276 require.NotNil(t, ccpBytes) 1277 1278 defaultPolicy, err := getSignedByMSPAdminPolicy(mspid) 1279 require.NoError(t, err) 1280 res, err := createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes) 1281 require.NoError(t, err) 1282 1283 tx, err := createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes) 1284 if err != nil { 1285 t.Fatalf("createTx returned err %s", err) 1286 } 1287 1288 envBytes, err := protoutil.GetBytesEnvelope(tx) 1289 if err != nil { 1290 t.Fatalf("GetBytesEnvelope returned err %s", err) 1291 } 1292 1293 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1294 err = v.Validate(bl, "lscc", 0, 0, policy) 1295 if V1_2Validation { 1296 require.NoError(t, err) 1297 } else { 1298 require.Error(t, err, "LSCC can only issue a single putState upon deploy/upgrade") 1299 } 1300 1301 state["lscc"][privdata.BuildCollectionKVSKey(ccname)] = ccpBytes 1302 1303 if V1_2Validation { 1304 ccver = "3" 1305 1306 collName3 := "mycollection3" 1307 coll3 := createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1308 1309 // Test 2: some existing collections are missing in the updated config and peer in 1310 // V1_2Validation mode --> error 1311 ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll3}} 1312 ccpBytes, err = proto.Marshal(ccp) 1313 require.NoError(t, err) 1314 require.NotNil(t, ccpBytes) 1315 1316 res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes) 1317 require.NoError(t, err) 1318 1319 tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes) 1320 if err != nil { 1321 t.Fatalf("createTx returned err %s", err) 1322 } 1323 1324 envBytes, err = protoutil.GetBytesEnvelope(tx) 1325 if err != nil { 1326 t.Fatalf("GetBytesEnvelope returned err %s", err) 1327 } 1328 1329 bl = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1330 err = v.Validate(bl, "lscc", 0, 0, policy) 1331 require.Error(t, err, "Some existing collection configurations are missing in the new collection configuration package") 1332 1333 ccver = "3" 1334 1335 // Test 3: some existing collections are missing in the updated config and peer in 1336 // V1_2Validation mode --> error 1337 ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll3}} 1338 ccpBytes, err = proto.Marshal(ccp) 1339 require.NoError(t, err) 1340 require.NotNil(t, ccpBytes) 1341 1342 res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes) 1343 require.NoError(t, err) 1344 1345 tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes) 1346 if err != nil { 1347 t.Fatalf("createTx returned err %s", err) 1348 } 1349 1350 envBytes, err = protoutil.GetBytesEnvelope(tx) 1351 if err != nil { 1352 t.Fatalf("GetBytesEnvelope returned err %s", err) 1353 } 1354 1355 bl = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1356 err = v.Validate(bl, "lscc", 0, 0, policy) 1357 require.Error(t, err, "existing collection named mycollection2 is missing in the new collection configuration package") 1358 1359 ccver = "3" 1360 1361 // Test 4: valid collection config config and peer in V1_2Validation mode --> success 1362 ccp = &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2, coll3}} 1363 ccpBytes, err = proto.Marshal(ccp) 1364 require.NoError(t, err) 1365 require.NotNil(t, ccpBytes) 1366 1367 res, err = createCCDataRWsetWithCollection(ccname, ccname, ccver, defaultPolicy, ccpBytes) 1368 require.NoError(t, err) 1369 1370 tx, err = createLSCCTxWithCollection(ccname, ccver, lscc.UPGRADE, res, defaultPolicy, ccpBytes) 1371 if err != nil { 1372 t.Fatalf("createTx returned err %s", err) 1373 } 1374 1375 envBytes, err = protoutil.GetBytesEnvelope(tx) 1376 if err != nil { 1377 t.Fatalf("GetBytesEnvelope returned err %s", err) 1378 } 1379 1380 bl = &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1381 err = v.Validate(bl, "lscc", 0, 0, policy) 1382 require.NoError(t, err) 1383 } 1384 } 1385 1386 func TestValidateUpgradeWithCollection(t *testing.T) { 1387 // with V1_2Validation enabled 1388 validateUpgradeWithCollection(t, true) 1389 // with V1_2Validation disabled 1390 validateUpgradeWithCollection(t, false) 1391 } 1392 1393 func TestValidateUpgradeWithPoliciesOK(t *testing.T) { 1394 state := make(map[string]map[string][]byte) 1395 state["lscc"] = make(map[string][]byte) 1396 1397 v := newValidationInstance(state) 1398 1399 ccname := "mycc" 1400 ccver := "upgradewithpoliciesok" 1401 1402 // policy signed by the right MSP 1403 policy, err := getSignedByMSPMemberPolicy(mspid) 1404 if err != nil { 1405 t.Fatalf("failed getting policy, err %s", err) 1406 } 1407 1408 // create lscc record 1409 cd := &ccprovider.ChaincodeData{ 1410 InstantiationPolicy: policy, 1411 } 1412 cdbytes, err := proto.Marshal(cd) 1413 if err != nil { 1414 t.Fatalf("Failed to marshal ChaincodeData: %s", err) 1415 } 1416 state["lscc"][ccname] = cdbytes 1417 1418 simresres, err := createCCDataRWset(ccname, ccname, ccver, nil) 1419 require.NoError(t, err) 1420 1421 tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres) 1422 if err != nil { 1423 t.Fatalf("createTx returned err %s", err) 1424 } 1425 1426 envBytes, err := protoutil.GetBytesEnvelope(tx) 1427 if err != nil { 1428 t.Fatalf("GetBytesEnvelope returned err %s", err) 1429 } 1430 1431 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1432 err = v.Validate(bl, "lscc", 0, 0, policy) 1433 require.NoError(t, err) 1434 } 1435 1436 func TestValidateUpgradeWithNewFailAllIP(t *testing.T) { 1437 // we're testing upgrade. 1438 // In particular, we want to test the scenario where the upgrade 1439 // complies with the instantiation policy of the current version 1440 // BUT NOT the instantiation policy of the new version. For this 1441 // reason we first deploy a cc with IP which is equal to the AcceptAllPolicy 1442 // and then try to upgrade with a cc with the RejectAllPolicy. 1443 // We run this test twice, once with the V11 capability (and expect 1444 // a failure) and once without (and we expect success). 1445 1446 validateUpgradeWithNewFailAllIP(t, true, true) 1447 validateUpgradeWithNewFailAllIP(t, false, false) 1448 } 1449 1450 func validateUpgradeWithNewFailAllIP(t *testing.T, v11capability, expecterr bool) { 1451 state := make(map[string]map[string][]byte) 1452 state["lscc"] = make(map[string][]byte) 1453 1454 vs := &mocks.State{} 1455 vs.GetStateMultipleKeysStub = func(namespace string, keys []string) ([][]byte, error) { 1456 if ns, ok := state[namespace]; ok { 1457 return [][]byte{ns[keys[0]]}, nil 1458 } else { 1459 return nil, fmt.Errorf("could not retrieve namespace %s", namespace) 1460 } 1461 } 1462 sf := &mocks.StateFetcher{} 1463 sf.On("FetchState").Return(vs, nil) 1464 capabilities := &mocks.Capabilities{} 1465 capabilities.On("PrivateChannelData").Return(true) 1466 capabilities.On("V1_1Validation").Return(v11capability) 1467 capabilities.On("V1_2Validation").Return(false) 1468 v := newCustomValidationInstance(sf, capabilities) 1469 1470 ccname := "mycc" 1471 ccver := "2" 1472 1473 // create lscc record with accept all instantiation policy 1474 ipbytes, err := proto.Marshal(policydsl.AcceptAllPolicy) 1475 if err != nil { 1476 t.Fatalf("Failed to marshal AcceptAllPolicy: %s", err) 1477 } 1478 cd := &ccprovider.ChaincodeData{ 1479 InstantiationPolicy: ipbytes, 1480 } 1481 cdbytes, err := proto.Marshal(cd) 1482 if err != nil { 1483 t.Fatalf("Failed to marshal ChaincodeData: %s", err) 1484 } 1485 state["lscc"][ccname] = cdbytes 1486 1487 // now we upgrade, with v 2 of the same cc, with the crucial difference that it has a reject all IP 1488 ccver = ccver + ".2" 1489 1490 simresres, err := createCCDataRWset(ccname, ccname, ccver, 1491 policydsl.MarshaledRejectAllPolicy, // here's where we specify the IP of the upgraded cc 1492 ) 1493 require.NoError(t, err) 1494 1495 tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres) 1496 if err != nil { 1497 t.Fatalf("createTx returned err %s", err) 1498 } 1499 1500 envBytes, err := protoutil.GetBytesEnvelope(tx) 1501 if err != nil { 1502 t.Fatalf("GetBytesEnvelope returned err %s", err) 1503 } 1504 1505 policy, err := getSignedByMSPMemberPolicy(mspid) 1506 if err != nil { 1507 t.Fatalf("failed getting policy, err %s", err) 1508 } 1509 1510 // execute the upgrade tx 1511 if expecterr { 1512 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1513 err = v.Validate(bl, "lscc", 0, 0, policy) 1514 require.Error(t, err) 1515 } else { 1516 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1517 err = v.Validate(bl, "lscc", 0, 0, policy) 1518 require.NoError(t, err) 1519 } 1520 } 1521 1522 func TestValidateUpgradeWithPoliciesFail(t *testing.T) { 1523 ccname := "mycc" 1524 ccver := "upgradewithpoliciesfail" 1525 1526 state := make(map[string]map[string][]byte) 1527 state["lscc"] = make(map[string][]byte) 1528 1529 v := newValidationInstance(state) 1530 1531 // create lscc record with reject all instantiation policy 1532 ipbytes, err := proto.Marshal(policydsl.RejectAllPolicy) 1533 if err != nil { 1534 t.Fatalf("Failed to marshal RejectAllPolicy: %s", err) 1535 } 1536 cd := &ccprovider.ChaincodeData{ 1537 InstantiationPolicy: ipbytes, 1538 Version: ccver, 1539 } 1540 cdbytes, err := proto.Marshal(cd) 1541 if err != nil { 1542 t.Fatalf("Failed to marshal ChaincodeData: %s", err) 1543 } 1544 state["lscc"][ccname] = cdbytes 1545 1546 ccver = "2" 1547 simresres, err := createCCDataRWset(ccname, ccname, ccver, nil) 1548 require.NoError(t, err) 1549 1550 tx, err := createLSCCTx(ccname, ccver, lscc.UPGRADE, simresres) 1551 if err != nil { 1552 t.Fatalf("createTx returned err %s", err) 1553 } 1554 1555 envBytes, err := protoutil.GetBytesEnvelope(tx) 1556 if err != nil { 1557 t.Fatalf("GetBytesEnvelope returned err %s", err) 1558 } 1559 1560 // good path: signed by the right MSP 1561 policy, err := getSignedByMSPMemberPolicy(mspid) 1562 if err != nil { 1563 t.Fatalf("failed getting policy, err %s", err) 1564 } 1565 1566 bl := &common.Block{Data: &common.BlockData{Data: [][]byte{envBytes}}} 1567 err = v.Validate(bl, "lscc", 0, 0, policy) 1568 require.EqualError(t, err, "chaincode instantiation policy violated, error signature set did not satisfy policy") 1569 } 1570 1571 var ( 1572 id msp.SigningIdentity 1573 sid []byte 1574 mspid string 1575 chainId string = "testchannelid" 1576 ) 1577 1578 func createCollectionConfig(collectionName string, signaturePolicyEnvelope *common.SignaturePolicyEnvelope, 1579 requiredPeerCount int32, maximumPeerCount int32, blockToLive uint64, 1580 ) *peer.CollectionConfig { 1581 signaturePolicy := &peer.CollectionPolicyConfig_SignaturePolicy{ 1582 SignaturePolicy: signaturePolicyEnvelope, 1583 } 1584 accessPolicy := &peer.CollectionPolicyConfig{ 1585 Payload: signaturePolicy, 1586 } 1587 1588 return &peer.CollectionConfig{ 1589 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 1590 StaticCollectionConfig: &peer.StaticCollectionConfig{ 1591 Name: collectionName, 1592 MemberOrgsPolicy: accessPolicy, 1593 RequiredPeerCount: requiredPeerCount, 1594 MaximumPeerCount: maximumPeerCount, 1595 BlockToLive: blockToLive, 1596 }, 1597 }, 1598 } 1599 } 1600 1601 func testValidateCollection(t *testing.T, v *Validator, collectionConfigs []*peer.CollectionConfig, cdRWSet *ccprovider.ChaincodeData, 1602 lsccFunc string, ac channelconfig.ApplicationCapabilities, chid string, 1603 ) error { 1604 ccp := &peer.CollectionConfigPackage{Config: collectionConfigs} 1605 ccpBytes, err := proto.Marshal(ccp) 1606 require.NoError(t, err) 1607 require.NotNil(t, ccpBytes) 1608 1609 lsccargs := [][]byte{nil, nil, nil, nil, nil, ccpBytes} 1610 rwset := &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: cdRWSet.Name}, {Key: privdata.BuildCollectionKVSKey(cdRWSet.Name), Value: ccpBytes}}} 1611 1612 err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid) 1613 return err 1614 } 1615 1616 func TestValidateRWSetAndCollectionForDeploy(t *testing.T) { 1617 var err error 1618 chid := "ch" 1619 ccid := "mycc" 1620 ccver := "1.0" 1621 cdRWSet := &ccprovider.ChaincodeData{Name: ccid, Version: ccver} 1622 1623 state := make(map[string]map[string][]byte) 1624 state["lscc"] = make(map[string][]byte) 1625 1626 v := newValidationInstance(state) 1627 1628 ac := capabilities.NewApplicationProvider(map[string]*common.Capability{ 1629 capabilities.ApplicationV1_1: {}, 1630 }) 1631 1632 lsccFunc := lscc.DEPLOY 1633 // Test 1: More than two entries in the rwset -> error 1634 rwset := &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: "b"}, {Key: "c"}}} 1635 err = v.validateRWSetAndCollection(rwset, cdRWSet, nil, lsccFunc, ac, chid) 1636 require.EqualError(t, err, "LSCC can only issue one or two putState upon deploy") 1637 1638 // Test 2: Invalid key for the collection config package -> error 1639 rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: "b"}}} 1640 err = v.validateRWSetAndCollection(rwset, cdRWSet, nil, lsccFunc, ac, chid) 1641 require.EqualError(t, err, "invalid key for the collection of chaincode mycc:1.0; expected 'mycc~collection', received 'b'") 1642 1643 // Test 3: No collection config package -> success 1644 rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}}} 1645 err = v.validateRWSetAndCollection(rwset, cdRWSet, nil, lsccFunc, ac, chid) 1646 require.NoError(t, err) 1647 1648 lsccargs := [][]byte{nil, nil, nil, nil, nil, nil} 1649 err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid) 1650 require.NoError(t, err) 1651 1652 // Test 4: Valid key for the collection config package -> success 1653 rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: privdata.BuildCollectionKVSKey(ccid)}}} 1654 err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid) 1655 require.NoError(t, err) 1656 1657 // Test 5: Collection configuration of the lscc args doesn't match the rwset 1658 lsccargs = [][]byte{nil, nil, nil, nil, nil, []byte("barf")} 1659 err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid) 1660 require.EqualError(t, err, "collection configuration arguments supplied for chaincode mycc:1.0 do not match the configuration in the lscc writeset") 1661 1662 // Test 6: Invalid collection config package -> error 1663 rwset = &kvrwset.KVRWSet{Writes: []*kvrwset.KVWrite{{Key: ccid}, {Key: privdata.BuildCollectionKVSKey("mycc"), Value: []byte("barf")}}} 1664 err = v.validateRWSetAndCollection(rwset, cdRWSet, lsccargs, lsccFunc, ac, chid) 1665 require.EqualError(t, err, "invalid collection configuration supplied for chaincode mycc:1.0") 1666 1667 // Test 7: Valid collection config package -> success 1668 collName1 := "mycollection1" 1669 collName2 := "mycollection2" 1670 signers := [][]byte{[]byte("signer0"), []byte("signer1")} 1671 policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers) 1672 var requiredPeerCount, maximumPeerCount int32 1673 var blockToLive uint64 1674 requiredPeerCount = 1 1675 maximumPeerCount = 2 1676 blockToLive = 10000 1677 coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1678 coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1679 1680 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2}, cdRWSet, lsccFunc, ac, chid) 1681 require.NoError(t, err) 1682 1683 // Test 8: Duplicate collections in the collection config package -> success as the peer is in v1.1 validation mode 1684 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll1}, cdRWSet, lsccFunc, ac, chid) 1685 require.NoError(t, err) 1686 1687 // Test 9: requiredPeerCount > maximumPeerCount -> success as the peer is in v1.1 validation mode 1688 collName3 := "mycollection3" 1689 requiredPeerCount = 2 1690 maximumPeerCount = 1 1691 blockToLive = 10000 1692 coll3 := createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1693 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid) 1694 require.NoError(t, err) 1695 1696 // Enable v1.2 validation mode 1697 ac = capabilities.NewApplicationProvider(map[string]*common.Capability{ 1698 capabilities.ApplicationV1_2: {}, 1699 }) 1700 1701 // Test 10: Duplicate collections in the collection config package -> error 1702 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll1}, cdRWSet, lsccFunc, ac, chid) 1703 require.EqualError(t, err, "collection-name: mycollection1 -- found duplicate collection configuration") 1704 1705 // Test 11: requiredPeerCount < 0 -> error 1706 requiredPeerCount = -2 1707 maximumPeerCount = 1 1708 blockToLive = 10000 1709 coll3 = createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1710 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid) 1711 require.EqualError(t, err, "collection-name: mycollection3 -- requiredPeerCount (-2) cannot be less than zero", 1712 collName3, maximumPeerCount, requiredPeerCount) 1713 1714 // Test 11: requiredPeerCount > maximumPeerCount -> error 1715 requiredPeerCount = 2 1716 maximumPeerCount = 1 1717 blockToLive = 10000 1718 coll3 = createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1719 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid) 1720 require.EqualError(t, err, "collection-name: mycollection3 -- maximum peer count (1) cannot be less than the required peer count (2)") 1721 1722 // Test 12: AND concatenation of orgs in access policy -> error 1723 requiredPeerCount = 1 1724 maximumPeerCount = 2 1725 policyEnvelope = policydsl.Envelope(policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers) 1726 coll3 = createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1727 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll3}, cdRWSet, lsccFunc, ac, chid) 1728 require.EqualError(t, err, "collection-name: mycollection3 -- error in member org policy: signature policy is not an OR concatenation, NOutOf 2") 1729 1730 // Test 13: deploy with existing collection config on the ledger -> error 1731 ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1}} 1732 ccpBytes, err := proto.Marshal(ccp) 1733 require.NoError(t, err) 1734 state["lscc"][privdata.BuildCollectionKVSKey(ccid)] = ccpBytes 1735 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1}, cdRWSet, lsccFunc, ac, chid) 1736 require.EqualError(t, err, "collection data should not exist for chaincode mycc:1.0") 1737 } 1738 1739 func TestValidateRWSetAndCollectionForUpgrade(t *testing.T) { 1740 chid := "ch" 1741 ccid := "mycc" 1742 ccver := "1.0" 1743 cdRWSet := &ccprovider.ChaincodeData{Name: ccid, Version: ccver} 1744 1745 state := make(map[string]map[string][]byte) 1746 state["lscc"] = make(map[string][]byte) 1747 1748 v := newValidationInstance(state) 1749 1750 ac := capabilities.NewApplicationProvider(map[string]*common.Capability{ 1751 capabilities.ApplicationV1_2: {}, 1752 }) 1753 1754 lsccFunc := lscc.UPGRADE 1755 1756 collName1 := "mycollection1" 1757 collName2 := "mycollection2" 1758 collName3 := "mycollection3" 1759 signers := [][]byte{[]byte("signer0"), []byte("signer1")} 1760 policyEnvelope := policydsl.Envelope(policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), signers) 1761 var requiredPeerCount, maximumPeerCount int32 1762 var blockToLive uint64 1763 requiredPeerCount = 1 1764 maximumPeerCount = 2 1765 blockToLive = 3 1766 coll1 := createCollectionConfig(collName1, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1767 coll2 := createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1768 coll3 := createCollectionConfig(collName3, policyEnvelope, requiredPeerCount, maximumPeerCount, blockToLive) 1769 1770 ccp := &peer.CollectionConfigPackage{Config: []*peer.CollectionConfig{coll1, coll2}} 1771 ccpBytes, err := proto.Marshal(ccp) 1772 require.NoError(t, err) 1773 1774 // Test 1: no existing collection config package -> success 1775 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1}, cdRWSet, lsccFunc, ac, chid) 1776 require.NoError(t, err) 1777 1778 state["lscc"][privdata.BuildCollectionKVSKey(ccid)] = ccpBytes 1779 1780 // Test 2: exactly same as the existing collection config package -> success 1781 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2}, cdRWSet, lsccFunc, ac, chid) 1782 require.NoError(t, err) 1783 1784 // Test 3: missing one existing collection (check based on the length) -> error 1785 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1}, cdRWSet, lsccFunc, ac, chid) 1786 require.EqualError(t, err, "the following existing collections are missing in the new collection configuration package: [mycollection2]") 1787 1788 // Test 4: missing one existing collection (check based on the collection names) -> error 1789 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll3}, cdRWSet, lsccFunc, ac, chid) 1790 require.EqualError(t, err, "the following existing collections are missing in the new collection configuration package: [mycollection2]") 1791 1792 // Test 5: adding a new collection along with the existing collections -> success 1793 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid) 1794 require.NoError(t, err) 1795 1796 newBlockToLive := blockToLive + 1 1797 coll2 = createCollectionConfig(collName2, policyEnvelope, requiredPeerCount, maximumPeerCount, newBlockToLive) 1798 1799 // Test 6: modify the BlockToLive in an existing collection -> error 1800 err = testValidateCollection(t, v, []*peer.CollectionConfig{coll1, coll2, coll3}, cdRWSet, lsccFunc, ac, chid) 1801 require.EqualError(t, err, "the BlockToLive in the following existing collections must not be modified: [mycollection2]") 1802 } 1803 1804 func TestMain(m *testing.M) { 1805 code := -1 1806 defer func() { 1807 os.Exit(code) 1808 }() 1809 testDir, err := ioutil.TempDir("", "v1.2-validation") 1810 if err != nil { 1811 fmt.Printf("Could not create temp dir: %s", err) 1812 return 1813 } 1814 defer os.RemoveAll(testDir) 1815 ccprovider.SetChaincodesPath(testDir) 1816 1817 // setup the MSP manager so that we can sign/verify 1818 msptesttools.LoadMSPSetupForTesting() 1819 1820 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1821 if err != nil { 1822 fmt.Printf("Initialize cryptoProvider bccsp failed: %s", cryptoProvider) 1823 return 1824 } 1825 1826 id, err = mspmgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 1827 if err != nil { 1828 fmt.Printf("GetDefaultSigningIdentity failed with err %s", err) 1829 return 1830 } 1831 1832 sid, err = id.Serialize() 1833 if err != nil { 1834 fmt.Printf("Serialize failed with err %s", err) 1835 return 1836 } 1837 1838 // determine the MSP identifier for the first MSP in the default chain 1839 var msp msp.MSP 1840 mspMgr := mspmgmt.GetManagerForChain(chainId) 1841 msps, err := mspMgr.GetMSPs() 1842 if err != nil { 1843 fmt.Printf("Could not retrieve the MSPs for the chain manager, err %s", err) 1844 return 1845 } 1846 if len(msps) == 0 { 1847 fmt.Printf("At least one MSP was expected") 1848 return 1849 } 1850 for _, m := range msps { 1851 msp = m 1852 break 1853 } 1854 mspid, err = msp.GetIdentifier() 1855 if err != nil { 1856 fmt.Printf("Failure getting the msp identifier, err %s", err) 1857 return 1858 } 1859 1860 // also set the MSP for the "test" chain 1861 mspmgmt.XXXSetMSPManager("mycc", mspmgmt.GetManagerForChain("testchannelid")) 1862 1863 code = m.Run() 1864 } 1865 1866 func TestInValidCollectionName(t *testing.T) { 1867 validNames := []string{"collection1", "collection_2"} 1868 inValidNames := []string{"collection.1", "collection%2", ""} 1869 1870 for _, name := range validNames { 1871 require.NoError(t, validateCollectionName(name), "Testing for name = "+name) 1872 } 1873 for _, name := range inValidNames { 1874 require.Error(t, validateCollectionName(name), "Testing for name = "+name) 1875 } 1876 }