github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/core/committer/txvalidator/v20/validator_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package txvalidator_test 8 9 import ( 10 "errors" 11 "fmt" 12 "os" 13 "strconv" 14 "testing" 15 "time" 16 17 "github.com/hyperledger/fabric-protos-go/common" 18 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 19 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 20 protosmsp "github.com/hyperledger/fabric-protos-go/msp" 21 "github.com/hyperledger/fabric-protos-go/peer" 22 protospeer "github.com/hyperledger/fabric-protos-go/peer" 23 "github.com/hyperledger/fabric/bccsp/sw" 24 commonerrors "github.com/hyperledger/fabric/common/errors" 25 "github.com/hyperledger/fabric/common/policydsl" 26 "github.com/hyperledger/fabric/common/semaphore" 27 "github.com/hyperledger/fabric/core/committer/txvalidator" 28 tmocks "github.com/hyperledger/fabric/core/committer/txvalidator/mocks" 29 txvalidatorplugin "github.com/hyperledger/fabric/core/committer/txvalidator/plugin" 30 txvalidatorv20 "github.com/hyperledger/fabric/core/committer/txvalidator/v20" 31 txvalidatormocks "github.com/hyperledger/fabric/core/committer/txvalidator/v20/mocks" 32 plugindispatchermocks "github.com/hyperledger/fabric/core/committer/txvalidator/v20/plugindispatcher/mocks" 33 ccp "github.com/hyperledger/fabric/core/common/ccprovider" 34 validation "github.com/hyperledger/fabric/core/handlers/validation/api" 35 "github.com/hyperledger/fabric/core/handlers/validation/builtin" 36 "github.com/hyperledger/fabric/core/ledger" 37 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 38 ledgerutils "github.com/hyperledger/fabric/core/ledger/util" 39 mocktxvalidator "github.com/hyperledger/fabric/core/mocks/txvalidator" 40 "github.com/hyperledger/fabric/core/scc/lscc" 41 supportmocks "github.com/hyperledger/fabric/discovery/support/mocks" 42 "github.com/hyperledger/fabric/msp" 43 "github.com/hyperledger/fabric/msp/mgmt" 44 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 45 "github.com/hyperledger/fabric/protoutil" 46 "github.com/stretchr/testify/assert" 47 "github.com/stretchr/testify/mock" 48 ) 49 50 func signedByAnyMember(ids []string) []byte { 51 p := policydsl.SignedByAnyMember(ids) 52 return protoutil.MarshalOrPanic(&protospeer.ApplicationPolicy{Type: &protospeer.ApplicationPolicy_SignaturePolicy{SignaturePolicy: p}}) 53 } 54 55 func v20Capabilities() *tmocks.ApplicationCapabilities { 56 ac := &tmocks.ApplicationCapabilities{} 57 ac.On("V1_2Validation").Return(true) 58 ac.On("V1_3Validation").Return(true) 59 ac.On("V2_0Validation").Return(true) 60 ac.On("PrivateChannelData").Return(true) 61 ac.On("KeyLevelEndorsement").Return(true) 62 return ac 63 } 64 65 func createRWset(t *testing.T, ccnames ...string) []byte { 66 rwsetBuilder := rwsetutil.NewRWSetBuilder() 67 for _, ccname := range ccnames { 68 rwsetBuilder.AddToWriteSet(ccname, "key", []byte("value")) 69 } 70 rwset, err := rwsetBuilder.GetTxSimulationResults() 71 assert.NoError(t, err) 72 rwsetBytes, err := rwset.GetPubSimulationBytes() 73 return rwsetBytes 74 } 75 76 func getProposalWithType(ccID string, pType common.HeaderType) (*peer.Proposal, error) { 77 cis := &peer.ChaincodeInvocationSpec{ 78 ChaincodeSpec: &peer.ChaincodeSpec{ 79 ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion}, 80 Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}}, 81 Type: peer.ChaincodeSpec_GOLANG}} 82 83 proposal, _, err := protoutil.CreateProposalFromCIS(pType, "testchannelid", cis, signerSerialized) 84 return proposal, err 85 } 86 87 const ccVersion = "1.0" 88 89 func getEnvWithType(ccID string, event []byte, res []byte, pType common.HeaderType, t *testing.T) *common.Envelope { 90 // get a toy proposal 91 prop, err := getProposalWithType(ccID, pType) 92 assert.NoError(t, err) 93 94 response := &peer.Response{Status: 200} 95 96 // endorse it to get a proposal response 97 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, res, event, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, signer) 98 assert.NoError(t, err) 99 100 // assemble a transaction from that proposal and endorsement 101 tx, err := protoutil.CreateSignedTx(prop, signer, presp) 102 assert.NoError(t, err) 103 104 return tx 105 } 106 107 func getEnv(ccID string, event []byte, res []byte, t *testing.T) *common.Envelope { 108 return getEnvWithType(ccID, event, res, common.HeaderType_ENDORSER_TRANSACTION, t) 109 } 110 111 func getEnvWithSigner(ccID string, event []byte, res []byte, sig msp.SigningIdentity, t *testing.T) *common.Envelope { 112 // get a toy proposal 113 pType := common.HeaderType_ENDORSER_TRANSACTION 114 cis := &peer.ChaincodeInvocationSpec{ 115 ChaincodeSpec: &peer.ChaincodeSpec{ 116 ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion}, 117 Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}}, 118 Type: peer.ChaincodeSpec_GOLANG, 119 }, 120 } 121 122 sID, err := sig.Serialize() 123 assert.NoError(t, err) 124 prop, _, err := protoutil.CreateProposalFromCIS(pType, "foochain", cis, sID) 125 assert.NoError(t, err) 126 127 response := &peer.Response{Status: 200} 128 129 // endorse it to get a proposal response 130 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, res, event, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, sig) 131 assert.NoError(t, err) 132 133 // assemble a transaction from that proposal and endorsement 134 tx, err := protoutil.CreateSignedTx(prop, sig, presp) 135 assert.NoError(t, err) 136 137 return tx 138 } 139 140 func assertInvalid(block *common.Block, t *testing.T, code peer.TxValidationCode) { 141 txsFilter := ledgerutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 142 assert.True(t, txsFilter.IsInvalid(0)) 143 assert.True(t, txsFilter.IsSetTo(0, code)) 144 } 145 146 func assertValid(block *common.Block, t *testing.T) { 147 txsFilter := ledgerutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 148 assert.False(t, txsFilter.IsInvalid(0)) 149 } 150 151 func setupValidator() (*txvalidatorv20.TxValidator, *txvalidatormocks.QueryExecutor, *supportmocks.Identity, *txvalidatormocks.CollectionResources) { 152 mspmgr := &supportmocks.MSPManager{} 153 mockID := &supportmocks.Identity{} 154 mockID.SatisfiesPrincipalReturns(nil) 155 mockID.GetIdentifierReturns(&msp.IdentityIdentifier{}) 156 mspmgr.DeserializeIdentityReturns(mockID, nil) 157 158 return setupValidatorWithMspMgr(mspmgr, mockID) 159 } 160 161 func setupValidatorWithMspMgr(mspmgr msp.MSPManager, mockID *supportmocks.Identity) (*txvalidatorv20.TxValidator, *txvalidatormocks.QueryExecutor, *supportmocks.Identity, *txvalidatormocks.CollectionResources) { 162 pm := &plugindispatchermocks.Mapper{} 163 factory := &plugindispatchermocks.PluginFactory{} 164 pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(factory) 165 factory.On("New").Return(&builtin.DefaultValidation{}) 166 167 mockQE := &txvalidatormocks.QueryExecutor{} 168 mockQE.On("Done").Return(nil) 169 mockQE.On("GetState", "lscc", "lscc").Return(nil, nil) 170 mockQE.On("GetState", "lscc", "escc").Return(nil, nil) 171 172 mockLedger := &txvalidatormocks.LedgerResources{} 173 mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean")) 174 mockLedger.On("NewQueryExecutor").Return(mockQE, nil) 175 176 mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{} 177 mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{}) 178 179 mockCR := &txvalidatormocks.CollectionResources{} 180 181 cryptoProvider, _ := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 182 v := txvalidatorv20.NewTxValidator( 183 "", 184 semaphore.New(10), 185 &mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr}, 186 mockLedger, 187 &lscc.SCC{BCCSP: cryptoProvider}, 188 mockCR, 189 pm, 190 mockCpmg, 191 cryptoProvider, 192 ) 193 194 return v, mockQE, mockID, mockCR 195 } 196 197 func TestInvokeBadRWSet(t *testing.T) { 198 ccID := "mycc" 199 200 v, _, _, _ := setupValidator() 201 202 tx := getEnv(ccID, nil, []byte("barf"), t) 203 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 1}} 204 205 err := v.Validate(b) 206 assert.NoError(t, err) 207 assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET) 208 } 209 210 func TestInvokeNoPolicy(t *testing.T) { 211 ccID := "mycc" 212 213 v, mockQE, _, _ := setupValidator() 214 215 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 216 Name: ccID, 217 Version: ccVersion, 218 Vscc: "vscc", 219 Policy: nil, 220 }), nil) 221 222 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 223 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 224 225 err := v.Validate(b) 226 assert.NoError(t, err) 227 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 228 } 229 230 func TestInvokeOK(t *testing.T) { 231 ccID := "mycc" 232 233 v, mockQE, _, _ := setupValidator() 234 235 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 236 Name: ccID, 237 Version: ccVersion, 238 Vscc: "vscc", 239 Policy: signedByAnyMember([]string{"SampleOrg"}), 240 }), nil) 241 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 242 243 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 244 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 245 246 err := v.Validate(b) 247 assert.NoError(t, err) 248 assertValid(b, t) 249 } 250 251 func TestInvokeNOKDuplicateNs(t *testing.T) { 252 ccID := "mycc" 253 254 v, mockQE, _, _ := setupValidator() 255 256 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 257 Name: ccID, 258 Version: ccVersion, 259 Vscc: "vscc", 260 Policy: signedByAnyMember([]string{"SampleOrg"}), 261 }), nil) 262 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 263 264 // note that this read-write set has two read-write sets for the same namespace and key 265 txrws := &rwset.TxReadWriteSet{ 266 DataModel: rwset.TxReadWriteSet_KV, 267 NsRwset: []*rwset.NsReadWriteSet{ 268 { 269 Namespace: "mycc", 270 Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{ 271 Writes: []*kvrwset.KVWrite{ 272 { 273 Key: "foo", 274 Value: []byte("bar1"), 275 }, 276 }, 277 }), 278 }, 279 { 280 Namespace: "mycc", 281 Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{ 282 Writes: []*kvrwset.KVWrite{ 283 { 284 Key: "foo", 285 Value: []byte("bar2"), 286 }, 287 }, 288 }), 289 }, 290 }, 291 } 292 293 tx := getEnv(ccID, nil, protoutil.MarshalOrPanic(txrws), t) 294 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 295 296 err := v.Validate(b) 297 assert.NoError(t, err) 298 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 299 } 300 301 func TestInvokeNoRWSet(t *testing.T) { 302 ccID := "mycc" 303 304 v, mockQE, mockID, _ := setupValidator() 305 mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 306 307 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 308 Name: ccID, 309 Version: ccVersion, 310 Vscc: "vscc", 311 Policy: signedByAnyMember([]string{"SampleOrg"}), 312 }), nil) 313 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 314 315 tx := getEnv(ccID, nil, createRWset(t), t) 316 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 317 318 err := v.Validate(b) 319 assert.NoError(t, err) 320 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 321 } 322 323 // SerializedIdentity mock for the parallel validation test 324 type mockSI struct { 325 SerializedID []byte 326 MspID string 327 SatPrinError error 328 } 329 330 func (msi *mockSI) ExpiresAt() time.Time { 331 return time.Now() 332 } 333 334 func (msi *mockSI) GetIdentifier() *msp.IdentityIdentifier { 335 return &msp.IdentityIdentifier{ 336 Mspid: msi.MspID, 337 Id: "", 338 } 339 } 340 341 func (msi *mockSI) GetMSPIdentifier() string { 342 return msi.MspID 343 } 344 345 func (msi *mockSI) Validate() error { 346 return nil 347 } 348 349 func (msi *mockSI) GetOrganizationalUnits() []*msp.OUIdentifier { 350 return nil 351 } 352 353 func (msi *mockSI) Anonymous() bool { 354 return false 355 } 356 357 func (msi *mockSI) Verify(msg []byte, sig []byte) error { 358 return nil 359 } 360 361 func (msi *mockSI) Serialize() ([]byte, error) { 362 sid := &protosmsp.SerializedIdentity{ 363 Mspid: msi.MspID, 364 IdBytes: msi.SerializedID, 365 } 366 sidBytes := protoutil.MarshalOrPanic(sid) 367 return sidBytes, nil 368 } 369 370 func (msi *mockSI) SatisfiesPrincipal(principal *protosmsp.MSPPrincipal) error { 371 return msi.SatPrinError 372 } 373 374 func (msi *mockSI) Sign(msg []byte) ([]byte, error) { 375 return msg, nil 376 } 377 378 func (msi *mockSI) GetPublicVersion() msp.Identity { 379 return msi 380 } 381 382 // MSP mock for the parallel validation test 383 type mockMSP struct { 384 ID msp.Identity 385 SatPrinError error 386 MspID string 387 } 388 389 func (fake *mockMSP) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) { 390 return fake.ID, nil 391 } 392 393 func (fake *mockMSP) IsWellFormed(identity *protosmsp.SerializedIdentity) error { 394 return nil 395 } 396 func (fake *mockMSP) Setup(config *protosmsp.MSPConfig) error { 397 return nil 398 } 399 400 func (fake *mockMSP) GetVersion() msp.MSPVersion { 401 return msp.MSPv1_3 402 } 403 404 func (fake *mockMSP) GetType() msp.ProviderType { 405 return msp.FABRIC 406 } 407 408 func (fake *mockMSP) GetIdentifier() (string, error) { 409 return fake.MspID, nil 410 } 411 412 func (fake *mockMSP) GetSigningIdentity(identifier *msp.IdentityIdentifier) (msp.SigningIdentity, error) { 413 return nil, nil 414 } 415 416 func (fake *mockMSP) GetDefaultSigningIdentity() (msp.SigningIdentity, error) { 417 return nil, nil 418 } 419 420 func (fake *mockMSP) GetTLSRootCerts() [][]byte { 421 return nil 422 } 423 424 func (fake *mockMSP) GetTLSIntermediateCerts() [][]byte { 425 return nil 426 } 427 428 func (fake *mockMSP) Validate(id msp.Identity) error { 429 return nil 430 } 431 432 func (fake *mockMSP) SatisfiesPrincipal(id msp.Identity, principal *protosmsp.MSPPrincipal) error { 433 return fake.SatPrinError 434 } 435 436 // parallel validation on a block with a high number of transactions and sbe dependencies among those 437 func TestParallelValidation(t *testing.T) { 438 // number of transactions in the block 439 txCnt := 100 440 441 // create two MSPs to control the policy evaluation result, one of them returning an error on SatisfiesPrincipal() 442 msp1 := &mockMSP{ 443 ID: &mockSI{ 444 MspID: "Org1", 445 SerializedID: []byte("signer0"), 446 SatPrinError: nil, 447 }, 448 SatPrinError: nil, 449 MspID: "Org1", 450 } 451 msp2 := &mockMSP{ 452 ID: &mockSI{ 453 MspID: "Org2", 454 SerializedID: []byte("signer1"), 455 SatPrinError: errors.New("nope"), 456 }, 457 SatPrinError: errors.New("nope"), 458 MspID: "Org2", 459 } 460 mgmt.GetManagerForChain("foochain") 461 mgr := mgmt.GetManagerForChain("foochain") 462 mgr.Setup([]msp.MSP{msp1, msp2}) 463 464 vpKey := protospeer.MetaDataKeys_VALIDATION_PARAMETER.String() 465 ccID := "mycc" 466 467 v, mockQE, _, mockCR := setupValidatorWithMspMgr(mgr, nil) 468 469 mockCR.On("CollectionValidationInfo", ccID, "col1", mock.Anything).Return(nil, nil, nil) 470 471 policy := policydsl.SignedByMspPeer("Org1") 472 polBytes := protoutil.MarshalOrPanic(&protospeer.ApplicationPolicy{Type: &protospeer.ApplicationPolicy_SignaturePolicy{SignaturePolicy: policy}}) 473 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 474 Name: ccID, 475 Version: ccVersion, 476 Vscc: "vscc", 477 Policy: polBytes, 478 }), nil) 479 mockQE.On("GetStateMetadata", "mycc", mock.Anything).Return(nil, nil) 480 mockQE.On("GetPrivateDataMetadataByHash", "mycc", "col1", mock.Anything).Return(nil, nil) 481 482 // create a number of txes 483 blockData := make([][]byte, 0, txCnt) 484 col := "col1" 485 sigID0 := &mockSI{ 486 SerializedID: []byte("signer0"), 487 MspID: "Org1", 488 } 489 sigID1 := &mockSI{ 490 SerializedID: []byte("signer1"), 491 MspID: "Org2", 492 } 493 for txNum := 0; txNum < txCnt; txNum++ { 494 var sig msp.SigningIdentity 495 // create rwset for the tx - KVS key depends on the txnum 496 key := strconv.Itoa(txNum % 10) 497 rwsetBuilder := rwsetutil.NewRWSetBuilder() 498 // pick action that we want to do: read / modify the value or the ep 499 switch uint(txNum / 10) { 500 case 0: 501 // set the value of the key (valid) 502 rwsetBuilder.AddToWriteSet(ccID, key, []byte("value1")) 503 sig = sigID0 504 case 1: 505 // set the ep of the key (invalid, because Org2's MSP returns principal not satisfied) 506 metadata := make(map[string][]byte) 507 metadata[vpKey] = signedByAnyMember([]string{"SampleOrg"}) 508 rwsetBuilder.AddToMetadataWriteSet(ccID, key, metadata) 509 sig = sigID1 510 case 2: 511 // set the value of the key (valid, because the ep change before was invalid) 512 rwsetBuilder.AddToWriteSet(ccID, key, []byte("value2")) 513 sig = sigID0 514 case 3: 515 // set the ep of the key (valid) 516 metadata := make(map[string][]byte) 517 metadata[vpKey] = signedByAnyMember([]string{"Org2"}) 518 rwsetBuilder.AddToMetadataWriteSet(ccID, key, metadata) 519 sig = sigID0 520 case 4: 521 // set the value of the key (invalid, because the ep change before was valid) 522 rwsetBuilder.AddToWriteSet(ccID, key, []byte("value3")) 523 sig = &mockSI{ 524 SerializedID: []byte("signer0"), 525 MspID: "Org1", 526 } 527 // do the same txes for private data 528 case 5: 529 // set the value of the key (valid) 530 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value1")) 531 sig = sigID0 532 case 6: 533 // set the ep of the key (invalid, because Org2's MSP returns principal not satisfied) 534 metadata := make(map[string][]byte) 535 metadata[vpKey] = signedByAnyMember([]string{"SampleOrg"}) 536 rwsetBuilder.AddToHashedMetadataWriteSet(ccID, col, key, metadata) 537 sig = sigID1 538 case 7: 539 // set the value of the key (valid, because the ep change before was invalid) 540 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value2")) 541 sig = sigID0 542 case 8: 543 // set the ep of the key (valid) 544 metadata := make(map[string][]byte) 545 metadata[vpKey] = signedByAnyMember([]string{"Org2"}) 546 rwsetBuilder.AddToHashedMetadataWriteSet(ccID, col, key, metadata) 547 sig = sigID0 548 case 9: 549 // set the value of the key (invalid, because the ep change before was valid) 550 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value3")) 551 sig = sigID0 552 } 553 rwset, err := rwsetBuilder.GetTxSimulationResults() 554 assert.NoError(t, err) 555 rwsetBytes, err := rwset.GetPubSimulationBytes() 556 tx := getEnvWithSigner(ccID, nil, rwsetBytes, sig, t) 557 blockData = append(blockData, protoutil.MarshalOrPanic(tx)) 558 } 559 560 // assemble block from all those txes 561 b := &common.Block{Data: &common.BlockData{Data: blockData}, Header: &common.BlockHeader{Number: uint64(txCnt)}} 562 563 // validate the block 564 err := v.Validate(b) 565 assert.NoError(t, err) 566 567 // Block metadata array position to store serialized bit array filter of invalid transactions 568 txsFilter := ledgerutils.TxValidationFlags(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 569 // tx validity 570 for txNum := 0; txNum < txCnt; txNum += 1 { 571 switch uint(txNum / 10) { 572 case 1: 573 fallthrough 574 case 4: 575 fallthrough 576 case 6: 577 fallthrough 578 case 9: 579 assert.True(t, txsFilter.IsInvalid(txNum)) 580 default: 581 assert.False(t, txsFilter.IsInvalid(txNum)) 582 } 583 } 584 } 585 586 func TestChaincodeEvent(t *testing.T) { 587 ccID := "mycc" 588 589 t.Run("MisMatchedName", func(t *testing.T) { 590 v, mockQE, _, _ := setupValidator() 591 592 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 593 Name: ccID, 594 Version: ccVersion, 595 Vscc: "vscc", 596 Policy: signedByAnyMember([]string{"SampleOrg"}), 597 }), nil) 598 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 599 600 testCCEventMismatchedName(t, v, ccID) 601 }) 602 603 t.Run("BadBytes", func(t *testing.T) { 604 v, mockQE, _, _ := setupValidator() 605 606 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 607 Name: ccID, 608 Version: ccVersion, 609 Vscc: "vscc", 610 Policy: signedByAnyMember([]string{"SampleOrg"}), 611 }), nil) 612 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 613 614 testCCEventBadBytes(t, v, ccID) 615 }) 616 617 t.Run("GoodPath", func(t *testing.T) { 618 v, mockQE, _, _ := setupValidator() 619 620 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 621 Name: ccID, 622 Version: ccVersion, 623 Vscc: "vscc", 624 Policy: signedByAnyMember([]string{"SampleOrg"}), 625 }), nil) 626 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 627 628 testCCEventGoodPath(t, v, ccID) 629 }) 630 } 631 632 func testCCEventMismatchedName(t *testing.T, v txvalidator.Validator, ccID string) { 633 tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: "wrong"}), createRWset(t), t) 634 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 635 636 err := v.Validate(b) 637 assert.NoError(t, err) // TODO, convert test so it can check the error text for INVALID_OTHER_REASON 638 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 639 } 640 641 func testCCEventBadBytes(t *testing.T, v txvalidator.Validator, ccID string) { 642 tx := getEnv(ccID, []byte("garbage"), createRWset(t), t) 643 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 644 645 err := v.Validate(b) 646 assert.NoError(t, err) // TODO, convert test so it can check the error text for INVALID_OTHER_REASON 647 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 648 } 649 650 func testCCEventGoodPath(t *testing.T, v txvalidator.Validator, ccID string) { 651 tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: ccID}), createRWset(t), t) 652 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 653 654 err := v.Validate(b) 655 assert.NoError(t, err) 656 assertValid(b, t) 657 } 658 659 func TestInvokeOKPvtDataOnly(t *testing.T) { 660 ccID := "mycc" 661 662 v, mockQE, mockID, mockCR := setupValidator() 663 mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 664 665 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 666 Name: ccID, 667 Version: ccVersion, 668 Vscc: "vscc", 669 Policy: signedByAnyMember([]string{"SampleOrg"}), 670 }), nil) 671 mockQE.On("GetPrivateDataMetadataByHash", ccID, "mycollection", mock.Anything).Return(nil, nil) 672 673 mockCR.On("CollectionValidationInfo", ccID, "mycollection", mock.Anything).Return(nil, nil, nil) 674 675 rwsetBuilder := rwsetutil.NewRWSetBuilder() 676 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, "mycollection", "somekey", nil) 677 rwset, err := rwsetBuilder.GetTxSimulationResults() 678 assert.NoError(t, err) 679 rwsetBytes, err := rwset.GetPubSimulationBytes() 680 assert.NoError(t, err) 681 682 tx := getEnv(ccID, nil, rwsetBytes, t) 683 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 684 685 err = v.Validate(b) 686 assert.NoError(t, err) 687 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 688 } 689 690 func TestInvokeOKMetaUpdateOnly(t *testing.T) { 691 ccID := "mycc" 692 693 v, mockQE, mockID, _ := setupValidator() 694 mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 695 696 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 697 Name: ccID, 698 Version: ccVersion, 699 Vscc: "vscc", 700 Policy: signedByAnyMember([]string{"SampleOrg"}), 701 }), nil) 702 mockQE.On("GetStateMetadata", ccID, "somekey").Return(nil, nil) 703 704 rwsetBuilder := rwsetutil.NewRWSetBuilder() 705 rwsetBuilder.AddToMetadataWriteSet(ccID, "somekey", map[string][]byte{}) 706 rwset, err := rwsetBuilder.GetTxSimulationResults() 707 assert.NoError(t, err) 708 rwsetBytes, err := rwset.GetPubSimulationBytes() 709 assert.NoError(t, err) 710 711 tx := getEnv(ccID, nil, rwsetBytes, t) 712 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 713 714 err = v.Validate(b) 715 assert.NoError(t, err) 716 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 717 } 718 719 func TestInvokeOKPvtMetaUpdateOnly(t *testing.T) { 720 ccID := "mycc" 721 722 v, mockQE, mockID, mockCR := setupValidator() 723 mockID.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 724 725 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 726 Name: ccID, 727 Version: ccVersion, 728 Vscc: "vscc", 729 Policy: signedByAnyMember([]string{"SampleOrg"}), 730 }), nil) 731 mockQE.On("GetPrivateDataMetadataByHash", ccID, "mycollection", mock.Anything).Return(nil, nil) 732 733 mockCR.On("CollectionValidationInfo", ccID, "mycollection", mock.Anything).Return(nil, nil, nil) 734 735 rwsetBuilder := rwsetutil.NewRWSetBuilder() 736 rwsetBuilder.AddToHashedMetadataWriteSet(ccID, "mycollection", "somekey", map[string][]byte{}) 737 rwset, err := rwsetBuilder.GetTxSimulationResults() 738 assert.NoError(t, err) 739 rwsetBytes, err := rwset.GetPubSimulationBytes() 740 assert.NoError(t, err) 741 742 tx := getEnv(ccID, nil, rwsetBytes, t) 743 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 744 745 err = v.Validate(b) 746 assert.NoError(t, err) 747 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 748 } 749 750 func TestInvokeNOKWritesToLSCC(t *testing.T) { 751 ccID := "mycc" 752 753 v, mockQE, _, _ := setupValidator() 754 755 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 756 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 757 Name: ccID, 758 Version: ccVersion, 759 Vscc: "vscc", 760 Policy: signedByAnyMember([]string{"SampleOrg"}), 761 }), nil) 762 763 tx := getEnv(ccID, nil, createRWset(t, ccID, "lscc"), t) 764 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 765 766 err := v.Validate(b) 767 assert.NoError(t, err) 768 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 769 } 770 771 func TestInvokeNOKWritesToESCC(t *testing.T) { 772 ccID := "mycc" 773 774 v, mockQE, _, _ := setupValidator() 775 776 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 777 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 778 Name: ccID, 779 Version: ccVersion, 780 Vscc: "vscc", 781 Policy: signedByAnyMember([]string{"SampleOrg"}), 782 }), nil) 783 784 tx := getEnv(ccID, nil, createRWset(t, ccID, "escc"), t) 785 b := &common.Block{ 786 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 787 Header: &common.BlockHeader{Number: 35}, 788 } 789 790 err := v.Validate(b) 791 assert.NoError(t, err) 792 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 793 } 794 795 func TestInvokeNOKWritesToNotExt(t *testing.T) { 796 ccID := "mycc" 797 798 v, mockQE, _, _ := setupValidator() 799 800 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 801 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 802 Name: ccID, 803 Version: ccVersion, 804 Vscc: "vscc", 805 Policy: signedByAnyMember([]string{"SampleOrg"}), 806 }), nil) 807 mockQE.On("GetState", "lscc", "notext").Return(nil, nil) 808 809 tx := getEnv(ccID, nil, createRWset(t, ccID, "notext"), t) 810 b := &common.Block{ 811 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 812 Header: &common.BlockHeader{Number: 35}, 813 } 814 815 err := v.Validate(b) 816 assert.NoError(t, err) 817 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 818 } 819 820 func TestInvokeNOKInvokesNotExt(t *testing.T) { 821 ccID := "notext" 822 823 v, mockQE, _, _ := setupValidator() 824 825 mockQE.On("GetState", "lscc", "notext").Return(nil, nil) 826 827 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 828 b := &common.Block{ 829 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 830 Header: &common.BlockHeader{}, 831 } 832 833 err := v.Validate(b) 834 assert.NoError(t, err) 835 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 836 } 837 838 func TestInvokeNOKInvokesEmptyCCName(t *testing.T) { 839 ccID := "" 840 841 v, _, _, _ := setupValidator() 842 843 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 844 b := &common.Block{ 845 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 846 Header: &common.BlockHeader{}, 847 } 848 849 err := v.Validate(b) 850 assert.NoError(t, err) 851 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 852 } 853 854 func TestInvokeNOKBogusActions(t *testing.T) { 855 ccID := "ccid" 856 857 v, _, _, _ := setupValidator() 858 859 tx := getEnv(ccID, nil, []byte("barf"), t) 860 b := &common.Block{ 861 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 862 Header: &common.BlockHeader{}, 863 } 864 865 err := v.Validate(b) 866 assert.NoError(t, err) 867 assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET) 868 } 869 870 func TestInvokeNOKCCDoesntExist(t *testing.T) { 871 ccID := "mycc" 872 873 v, mockQE, _, _ := setupValidator() 874 mockQE.On("GetState", "lscc", ccID).Return(nil, nil) 875 876 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 877 b := &common.Block{ 878 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 879 Header: &common.BlockHeader{}, 880 } 881 882 err := v.Validate(b) 883 assert.NoError(t, err) 884 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 885 } 886 887 func TestInvokeNOKVSCCUnspecified(t *testing.T) { 888 ccID := "mycc" 889 890 v, mockQE, _, _ := setupValidator() 891 892 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 893 Name: ccID, 894 Version: ccVersion, 895 Vscc: "", 896 Policy: signedByAnyMember([]string{"SampleOrg"}), 897 }), nil) 898 899 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 900 b := &common.Block{ 901 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 902 Header: &common.BlockHeader{}, 903 } 904 905 err := v.Validate(b) 906 assert.NoError(t, err) 907 assertInvalid(b, t, peer.TxValidationCode_INVALID_CHAINCODE) 908 } 909 910 func TestInvokeNoBlock(t *testing.T) { 911 v, _, _, _ := setupValidator() 912 err := v.Validate(&common.Block{ 913 Data: &common.BlockData{Data: [][]byte{}}, 914 Header: &common.BlockHeader{}, 915 }) 916 assert.NoError(t, err) 917 } 918 919 func TestValidateTxWithStateBasedEndorsement(t *testing.T) { 920 ccID := "mycc" 921 922 v, mockQE, _, _ := setupValidator() 923 924 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 925 Name: ccID, 926 Version: ccVersion, 927 Vscc: "vscc", 928 Policy: signedByAnyMember([]string{"SampleOrg"}), 929 }), nil) 930 mockQE.On("GetStateMetadata", ccID, "key").Return(map[string][]byte{peer.MetaDataKeys_VALIDATION_PARAMETER.String(): protoutil.MarshalOrPanic(&protospeer.ApplicationPolicy{Type: &protospeer.ApplicationPolicy_SignaturePolicy{SignaturePolicy: policydsl.RejectAllPolicy}})}, nil) 931 932 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 933 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 3}} 934 935 err := v.Validate(b) 936 assert.NoError(t, err) 937 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 938 } 939 940 func TestDynamicCapabilitiesAndMSP(t *testing.T) { 941 ccID := "mycc" 942 943 v, mockQE, _, _ := setupValidator() 944 945 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 946 Name: ccID, 947 Version: ccVersion, 948 Vscc: "vscc", 949 Policy: signedByAnyMember([]string{"SampleOrg"}), 950 }), nil) 951 mockQE.On("GetStateMetadata", ccID, "key").Return(nil, nil) 952 953 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 954 b := &common.Block{ 955 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 956 Header: &common.BlockHeader{Number: 1}, 957 } 958 959 // Perform a validation of a block 960 err := v.Validate(b) 961 assert.NoError(t, err) 962 assertValid(b, t) 963 // Record the number of times the capabilities and the MSP Manager were invoked 964 capabilityInvokeCount := v.ChannelResources.(*mocktxvalidator.Support).CapabilitiesInvokeCount() 965 mspManagerInvokeCount := v.ChannelResources.(*mocktxvalidator.Support).MSPManagerInvokeCount() 966 967 // Perform another validation pass, and ensure it is valid 968 err = v.Validate(b) 969 assert.NoError(t, err) 970 assertValid(b, t) 971 972 // Ensure that the capabilities were retrieved from the support twice, 973 // which proves that the capabilities are dynamically retrieved from the support each time 974 assert.Equal(t, 2*capabilityInvokeCount, v.ChannelResources.(*mocktxvalidator.Support).CapabilitiesInvokeCount()) 975 // Ensure that the MSP Manager was retrieved from the support twice, 976 // which proves that the MSP Manager is dynamically retrieved from the support each time 977 assert.Equal(t, 2*mspManagerInvokeCount, v.ChannelResources.(*mocktxvalidator.Support).MSPManagerInvokeCount()) 978 } 979 980 // TestLedgerIsNoAvailable simulates and provides a test for following scenario, 981 // which is based on FAB-535. Test checks the validation path which expects that 982 // DB won't available while trying to lookup for VSCC from LCCC and therefore 983 // transaction validation will have to fail. In such case the outcome should be 984 // the error return from validate block method and processing of transactions 985 // has to stop. There is suppose to be clear indication of the failure with error 986 // returned from the function call. 987 func TestLedgerIsNotAvailable(t *testing.T) { 988 ccID := "mycc" 989 990 v, mockQE, _, _ := setupValidator() 991 mockQE.On("GetState", "lscc", ccID).Return(nil, errors.New("Detroit rock city")) 992 993 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 994 995 b := &common.Block{ 996 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 997 Header: &common.BlockHeader{}, 998 } 999 1000 err := v.Validate(b) 1001 1002 assertion := assert.New(t) 1003 // We suppose to get the error which indicates we cannot commit the block 1004 assertion.Error(err) 1005 // The error exptected to be of type VSCCInfoLookupFailureError 1006 assertion.NotNil(err.(*commonerrors.VSCCInfoLookupFailureError)) 1007 } 1008 1009 func TestLedgerIsNotAvailableForCheckingTxidDuplicate(t *testing.T) { 1010 ccID := "mycc" 1011 1012 v, _, _, _ := setupValidator() 1013 1014 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1015 1016 mockLedger := &txvalidatormocks.LedgerResources{} 1017 v.LedgerResources = mockLedger 1018 mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, errors.New("uh, oh")) 1019 1020 b := &common.Block{ 1021 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1022 Header: &common.BlockHeader{Number: 1}, 1023 } 1024 1025 err := v.Validate(b) 1026 1027 assertion := assert.New(t) 1028 // We expect a validation error because the ledger wasn't ready to tell us whether there was a tx with that ID or not 1029 assertion.Error(err) 1030 } 1031 1032 func TestDuplicateTxId(t *testing.T) { 1033 ccID := "mycc" 1034 1035 v, _, _, _ := setupValidator() 1036 1037 mockLedger := &txvalidatormocks.LedgerResources{} 1038 v.LedgerResources = mockLedger 1039 mockLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, nil) 1040 1041 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1042 1043 b := &common.Block{ 1044 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1045 Header: &common.BlockHeader{}, 1046 } 1047 1048 err := v.Validate(b) 1049 1050 assertion := assert.New(t) 1051 // We expect no validation error because we simply mark the tx as invalid 1052 assertion.NoError(err) 1053 1054 // We expect the tx to be invalid because of a duplicate txid 1055 txsfltr := ledgerutils.TxValidationFlags(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 1056 assertion.True(txsfltr.IsInvalid(0)) 1057 assertion.True(txsfltr.Flag(0) == peer.TxValidationCode_DUPLICATE_TXID) 1058 } 1059 1060 func TestValidationInvalidEndorsing(t *testing.T) { 1061 ccID := "mycc" 1062 1063 mspmgr := &supportmocks.MSPManager{} 1064 mockID := &supportmocks.Identity{} 1065 mockID.SatisfiesPrincipalReturns(nil) 1066 mockID.GetIdentifierReturns(&msp.IdentityIdentifier{}) 1067 mspmgr.DeserializeIdentityReturns(mockID, nil) 1068 1069 pm := &plugindispatchermocks.Mapper{} 1070 factory := &plugindispatchermocks.PluginFactory{} 1071 pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(factory) 1072 plugin := &plugindispatchermocks.Plugin{} 1073 factory.On("New").Return(plugin) 1074 plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) 1075 plugin.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("invalid tx")) 1076 1077 mockQE := &txvalidatormocks.QueryExecutor{} 1078 mockQE.On("Done").Return(nil) 1079 1080 mockLedger := &txvalidatormocks.LedgerResources{} 1081 mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean")) 1082 mockLedger.On("NewQueryExecutor").Return(mockQE, nil) 1083 1084 mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{} 1085 mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{}) 1086 1087 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1088 assert.NoError(t, err) 1089 1090 v := txvalidatorv20.NewTxValidator( 1091 "", 1092 semaphore.New(10), 1093 &mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr}, 1094 mockLedger, 1095 &lscc.SCC{BCCSP: cryptoProvider}, 1096 &txvalidatormocks.CollectionResources{}, 1097 pm, 1098 mockCpmg, 1099 cryptoProvider, 1100 ) 1101 1102 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1103 1104 cd := &ccp.ChaincodeData{ 1105 Name: ccID, 1106 Version: ccVersion, 1107 Vscc: "vscc", 1108 Policy: signedByAnyMember([]string{"SampleOrg"}), 1109 } 1110 1111 cdbytes := protoutil.MarshalOrPanic(cd) 1112 1113 mockQE.On("GetState", "lscc", ccID).Return(cdbytes, nil) 1114 1115 b := &common.Block{ 1116 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1117 Header: &common.BlockHeader{}, 1118 } 1119 1120 // Keep default callback 1121 err = v.Validate(b) 1122 // Restore default callback 1123 assert.NoError(t, err) 1124 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 1125 } 1126 1127 func TestValidationPluginExecutionError(t *testing.T) { 1128 ccID := "mycc" 1129 1130 mspmgr := &supportmocks.MSPManager{} 1131 mockID := &supportmocks.Identity{} 1132 mockID.SatisfiesPrincipalReturns(nil) 1133 mockID.GetIdentifierReturns(&msp.IdentityIdentifier{}) 1134 mspmgr.DeserializeIdentityReturns(mockID, nil) 1135 1136 pm := &plugindispatchermocks.Mapper{} 1137 factory := &plugindispatchermocks.PluginFactory{} 1138 pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(factory) 1139 plugin := &plugindispatchermocks.Plugin{} 1140 factory.On("New").Return(plugin) 1141 plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) 1142 plugin.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&validation.ExecutionFailureError{ 1143 Reason: "I/O error", 1144 }) 1145 1146 mockQE := &txvalidatormocks.QueryExecutor{} 1147 mockQE.On("Done").Return(nil) 1148 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 1149 Name: ccID, 1150 Version: ccVersion, 1151 Vscc: "vscc", 1152 Policy: signedByAnyMember([]string{"SampleOrg"}), 1153 }), nil) 1154 1155 mockLedger := &txvalidatormocks.LedgerResources{} 1156 mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean")) 1157 mockLedger.On("NewQueryExecutor").Return(mockQE, nil) 1158 1159 mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{} 1160 mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{}) 1161 1162 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1163 assert.NoError(t, err) 1164 v := txvalidatorv20.NewTxValidator( 1165 "", 1166 semaphore.New(10), 1167 &mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr}, 1168 mockLedger, 1169 &lscc.SCC{BCCSP: cryptoProvider}, 1170 &txvalidatormocks.CollectionResources{}, 1171 pm, 1172 mockCpmg, 1173 cryptoProvider, 1174 ) 1175 1176 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1177 b := &common.Block{ 1178 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1179 Header: &common.BlockHeader{}, 1180 } 1181 1182 err = v.Validate(b) 1183 executionErr := err.(*commonerrors.VSCCExecutionFailureError) 1184 assert.Contains(t, executionErr.Error(), "I/O error") 1185 } 1186 1187 func TestValidationPluginNotFound(t *testing.T) { 1188 ccID := "mycc" 1189 1190 mspmgr := &supportmocks.MSPManager{} 1191 mockID := &supportmocks.Identity{} 1192 mockID.SatisfiesPrincipalReturns(nil) 1193 mockID.GetIdentifierReturns(&msp.IdentityIdentifier{}) 1194 mspmgr.DeserializeIdentityReturns(mockID, nil) 1195 1196 pm := &plugindispatchermocks.Mapper{} 1197 pm.On("FactoryByName", txvalidatorplugin.Name("vscc")).Return(nil) 1198 1199 mockQE := &txvalidatormocks.QueryExecutor{} 1200 mockQE.On("Done").Return(nil) 1201 mockQE.On("GetState", "lscc", ccID).Return(protoutil.MarshalOrPanic(&ccp.ChaincodeData{ 1202 Name: ccID, 1203 Version: ccVersion, 1204 Vscc: "vscc", 1205 Policy: signedByAnyMember([]string{"SampleOrg"}), 1206 }), nil) 1207 1208 mockLedger := &txvalidatormocks.LedgerResources{} 1209 mockLedger.On("GetTransactionByID", mock.Anything).Return(nil, ledger.NotFoundInIndexErr("As idle as a painted ship upon a painted ocean")) 1210 mockLedger.On("NewQueryExecutor").Return(mockQE, nil) 1211 1212 mockCpmg := &plugindispatchermocks.ChannelPolicyManagerGetter{} 1213 mockCpmg.On("Manager", mock.Anything).Return(&txvalidatormocks.PolicyManager{}) 1214 1215 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1216 assert.NoError(t, err) 1217 v := txvalidatorv20.NewTxValidator( 1218 "", 1219 semaphore.New(10), 1220 &mocktxvalidator.Support{ACVal: v20Capabilities(), MSPManagerVal: mspmgr}, 1221 mockLedger, 1222 &lscc.SCC{BCCSP: cryptoProvider}, 1223 &txvalidatormocks.CollectionResources{}, 1224 pm, 1225 mockCpmg, 1226 cryptoProvider, 1227 ) 1228 1229 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1230 b := &common.Block{ 1231 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1232 Header: &common.BlockHeader{}, 1233 } 1234 1235 err = v.Validate(b) 1236 executionErr := err.(*commonerrors.VSCCExecutionFailureError) 1237 assert.Contains(t, executionErr.Error(), "plugin with name vscc wasn't found") 1238 } 1239 1240 var signer msp.SigningIdentity 1241 1242 var signerSerialized []byte 1243 1244 func TestMain(m *testing.M) { 1245 msptesttools.LoadMSPSetupForTesting() 1246 1247 var err error 1248 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1249 if err != nil { 1250 fmt.Printf("Initialize cryptoProvider bccsp failed: %s", err) 1251 os.Exit(-1) 1252 return 1253 } 1254 1255 signer, err = mgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 1256 if err != nil { 1257 fmt.Println("Could not get signer") 1258 os.Exit(-1) 1259 return 1260 } 1261 1262 signerSerialized, err = signer.Serialize() 1263 if err != nil { 1264 fmt.Println("Could not serialize identity") 1265 os.Exit(-1) 1266 return 1267 } 1268 1269 os.Exit(m.Run()) 1270 } 1271 1272 func ToHex(q uint64) string { 1273 return "0x" + strconv.FormatUint(q, 16) 1274 }