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