github.com/ewagmig/fabric@v2.1.1+incompatible/core/committer/txvalidator/v14/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 "io/ioutil" 13 "os" 14 "strconv" 15 "testing" 16 "time" 17 18 "github.com/hyperledger/fabric-protos-go/common" 19 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 20 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 21 mb "github.com/hyperledger/fabric-protos-go/msp" 22 "github.com/hyperledger/fabric-protos-go/peer" 23 pb "github.com/hyperledger/fabric-protos-go/peer" 24 "github.com/hyperledger/fabric/bccsp/sw" 25 ctxt "github.com/hyperledger/fabric/common/configtx/test" 26 commonerrors "github.com/hyperledger/fabric/common/errors" 27 ledger2 "github.com/hyperledger/fabric/common/ledger" 28 "github.com/hyperledger/fabric/common/ledger/testutil" 29 "github.com/hyperledger/fabric/common/policydsl" 30 "github.com/hyperledger/fabric/common/semaphore" 31 "github.com/hyperledger/fabric/common/util" 32 "github.com/hyperledger/fabric/core/committer/txvalidator" 33 tmocks "github.com/hyperledger/fabric/core/committer/txvalidator/mocks" 34 vp "github.com/hyperledger/fabric/core/committer/txvalidator/plugin" 35 txvalidatorv14 "github.com/hyperledger/fabric/core/committer/txvalidator/v14" 36 "github.com/hyperledger/fabric/core/committer/txvalidator/v14/mocks" 37 "github.com/hyperledger/fabric/core/committer/txvalidator/v14/testdata" 38 ccp "github.com/hyperledger/fabric/core/common/ccprovider" 39 validation "github.com/hyperledger/fabric/core/handlers/validation/api" 40 "github.com/hyperledger/fabric/core/handlers/validation/builtin" 41 "github.com/hyperledger/fabric/core/ledger" 42 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 43 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 44 "github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledgermgmttest" 45 lutils "github.com/hyperledger/fabric/core/ledger/util" 46 mocktxvalidator "github.com/hyperledger/fabric/core/mocks/txvalidator" 47 mocks2 "github.com/hyperledger/fabric/discovery/support/mocks" 48 "github.com/hyperledger/fabric/msp" 49 "github.com/hyperledger/fabric/msp/mgmt" 50 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 51 "github.com/hyperledger/fabric/protoutil" 52 "github.com/stretchr/testify/assert" 53 "github.com/stretchr/testify/mock" 54 ) 55 56 func signedByAnyMember(ids []string) []byte { 57 p := policydsl.SignedByAnyMember(ids) 58 return protoutil.MarshalOrPanic(p) 59 } 60 61 func preV12Capabilities() *tmocks.ApplicationCapabilities { 62 ac := &tmocks.ApplicationCapabilities{} 63 ac.On("V1_2Validation").Return(false) 64 ac.On("V1_3Validation").Return(false) 65 ac.On("V2_0Validation").Return(false) 66 ac.On("PrivateChannelData").Return(false) 67 ac.On("ForbidDuplicateTXIdInBlock").Return(false) 68 ac.On("KeyLevelEndorsement").Return(false) 69 return ac 70 } 71 72 func v12Capabilities() *tmocks.ApplicationCapabilities { 73 ac := &tmocks.ApplicationCapabilities{} 74 ac.On("V1_2Validation").Return(true) 75 ac.On("V1_3Validation").Return(false) 76 ac.On("V2_0Validation").Return(false) 77 ac.On("PrivateChannelData").Return(true) 78 ac.On("ForbidDuplicateTXIdInBlock").Return(false) 79 ac.On("KeyLevelEndorsement").Return(false) 80 return ac 81 } 82 83 func v13Capabilities() *tmocks.ApplicationCapabilities { 84 ac := &tmocks.ApplicationCapabilities{} 85 ac.On("V1_2Validation").Return(true) 86 ac.On("V1_3Validation").Return(true) 87 ac.On("V2_0Validation").Return(false) 88 ac.On("PrivateChannelData").Return(true) 89 ac.On("ForbidDuplicateTXIdInBlock").Return(true) 90 ac.On("KeyLevelEndorsement").Return(true) 91 return ac 92 } 93 94 func setupLedgerAndValidatorExplicit(t *testing.T, cpb *tmocks.ApplicationCapabilities, plugin validation.Plugin) (ledger.PeerLedger, txvalidator.Validator, func()) { 95 return setupLedgerAndValidatorExplicitWithMSP(t, cpb, plugin, nil) 96 } 97 98 func setupLedgerAndValidatorWithPreV12Capabilities(t *testing.T) (ledger.PeerLedger, txvalidator.Validator, func()) { 99 return setupLedgerAndValidatorWithCapabilities(t, preV12Capabilities()) 100 } 101 102 func setupLedgerAndValidatorWithV12Capabilities(t *testing.T) (ledger.PeerLedger, txvalidator.Validator, func()) { 103 return setupLedgerAndValidatorWithCapabilities(t, v12Capabilities()) 104 } 105 106 func setupLedgerAndValidatorWithV13Capabilities(t *testing.T) (ledger.PeerLedger, txvalidator.Validator, func()) { 107 return setupLedgerAndValidatorWithCapabilities(t, v13Capabilities()) 108 } 109 110 func setupLedgerAndValidatorWithCapabilities(t *testing.T, c *tmocks.ApplicationCapabilities) (ledger.PeerLedger, txvalidator.Validator, func()) { 111 mspmgr := &mocks2.MSPManager{} 112 idThatSatisfiesPrincipal := &mocks2.Identity{} 113 idThatSatisfiesPrincipal.SatisfiesPrincipalReturns(nil) 114 idThatSatisfiesPrincipal.GetIdentifierReturns(&msp.IdentityIdentifier{}) 115 mspmgr.DeserializeIdentityReturns(idThatSatisfiesPrincipal, nil) 116 117 return setupLedgerAndValidatorExplicitWithMSP(t, c, &builtin.DefaultValidation{}, mspmgr) 118 } 119 120 func setupLedgerAndValidatorExplicitWithMSP(t *testing.T, cpb *tmocks.ApplicationCapabilities, plugin validation.Plugin, mspMgr msp.MSPManager) (ledger.PeerLedger, txvalidator.Validator, func()) { 121 ledgerMgr, cleanup := constructLedgerMgrWithTestDefaults(t, "txvalidator") 122 gb, err := ctxt.MakeGenesisBlock("TestLedger") 123 assert.NoError(t, err) 124 theLedger, err := ledgerMgr.CreateLedger("TestLedger", gb) 125 assert.NoError(t, err) 126 pm := &mocks.Mapper{} 127 factory := &mocks.PluginFactory{} 128 pm.On("FactoryByName", vp.Name("vscc")).Return(factory) 129 factory.On("New").Return(plugin) 130 131 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 132 assert.NoError(t, err) 133 theValidator := txvalidatorv14.NewTxValidator( 134 "", 135 semaphore.New(10), 136 &mocktxvalidator.Support{LedgerVal: theLedger, ACVal: cpb, MSPManagerVal: mspMgr}, 137 pm, 138 cryptoProvider, 139 ) 140 141 return theLedger, 142 theValidator, 143 func() { 144 theLedger.Close() 145 cleanup() 146 } 147 } 148 149 func createRWset(t *testing.T, ccnames ...string) []byte { 150 rwsetBuilder := rwsetutil.NewRWSetBuilder() 151 for _, ccname := range ccnames { 152 rwsetBuilder.AddToWriteSet(ccname, "key", []byte("value")) 153 } 154 rwset, err := rwsetBuilder.GetTxSimulationResults() 155 assert.NoError(t, err) 156 rwsetBytes, err := rwset.GetPubSimulationBytes() 157 return rwsetBytes 158 } 159 160 func getProposalWithType(ccID string, pType common.HeaderType) (*peer.Proposal, error) { 161 cis := &peer.ChaincodeInvocationSpec{ 162 ChaincodeSpec: &peer.ChaincodeSpec{ 163 ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion}, 164 Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}}, 165 Type: peer.ChaincodeSpec_GOLANG}} 166 167 proposal, _, err := protoutil.CreateProposalFromCIS(pType, "testchannelid", cis, signerSerialized) 168 return proposal, err 169 } 170 171 const ccVersion = "1.0" 172 173 func getEnvWithType(ccID string, event []byte, res []byte, pType common.HeaderType, t *testing.T) *common.Envelope { 174 // get a toy proposal 175 prop, err := getProposalWithType(ccID, pType) 176 assert.NoError(t, err) 177 178 response := &peer.Response{Status: 200} 179 180 // endorse it to get a proposal response 181 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, res, event, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, signer) 182 assert.NoError(t, err) 183 184 // assemble a transaction from that proposal and endorsement 185 tx, err := protoutil.CreateSignedTx(prop, signer, presp) 186 assert.NoError(t, err) 187 188 return tx 189 } 190 191 func getEnv(ccID string, event []byte, res []byte, t *testing.T) *common.Envelope { 192 return getEnvWithType(ccID, event, res, common.HeaderType_ENDORSER_TRANSACTION, t) 193 } 194 195 func getEnvWithSigner(ccID string, event []byte, res []byte, sig msp.SigningIdentity, t *testing.T) *common.Envelope { 196 // get a toy proposal 197 pType := common.HeaderType_ENDORSER_TRANSACTION 198 cis := &peer.ChaincodeInvocationSpec{ 199 ChaincodeSpec: &peer.ChaincodeSpec{ 200 ChaincodeId: &peer.ChaincodeID{Name: ccID, Version: ccVersion}, 201 Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("func")}}, 202 Type: peer.ChaincodeSpec_GOLANG, 203 }, 204 } 205 206 sID, err := sig.Serialize() 207 assert.NoError(t, err) 208 prop, _, err := protoutil.CreateProposalFromCIS(pType, "foochain", cis, sID) 209 assert.NoError(t, err) 210 211 response := &peer.Response{Status: 200} 212 213 // endorse it to get a proposal response 214 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, response, res, event, &peer.ChaincodeID{Name: ccID, Version: ccVersion}, sig) 215 assert.NoError(t, err) 216 217 // assemble a transaction from that proposal and endorsement 218 tx, err := protoutil.CreateSignedTx(prop, sig, presp) 219 assert.NoError(t, err) 220 221 return tx 222 } 223 224 func putCCInfoWithVSCCAndVer(theLedger ledger.PeerLedger, ccname, vscc, ver string, policy []byte, t *testing.T) { 225 cd := &ccp.ChaincodeData{ 226 Name: ccname, 227 Version: ver, 228 Vscc: vscc, 229 Policy: policy, 230 } 231 232 cdbytes := protoutil.MarshalOrPanic(cd) 233 234 txid := util.GenerateUUID() 235 simulator, err := theLedger.NewTxSimulator(txid) 236 assert.NoError(t, err) 237 simulator.SetState("lscc", ccname, cdbytes) 238 simulator.Done() 239 240 simRes, err := simulator.GetTxSimulationResults() 241 assert.NoError(t, err) 242 pubSimulationBytes, err := simRes.GetPubSimulationBytes() 243 assert.NoError(t, err) 244 bcInfo, err := theLedger.GetBlockchainInfo() 245 assert.NoError(t, err) 246 block0 := testutil.ConstructBlock(t, 1, bcInfo.CurrentBlockHash, [][]byte{pubSimulationBytes}, true) 247 err = theLedger.CommitLegacy(&ledger.BlockAndPvtData{Block: block0}, &ledger.CommitOptions{}) 248 assert.NoError(t, err) 249 } 250 251 func putSBEP(theLedger ledger.PeerLedger, cc, key string, policy []byte, t *testing.T) { 252 vpMetadataKey := peer.MetaDataKeys_VALIDATION_PARAMETER.String() 253 txid := util.GenerateUUID() 254 simulator, err := theLedger.NewTxSimulator(txid) 255 assert.NoError(t, err) 256 simulator.SetStateMetadata(cc, key, map[string][]byte{vpMetadataKey: policy}) 257 simulator.SetState(cc, key, []byte("I am a man who walks alone")) 258 simulator.Done() 259 260 simRes, err := simulator.GetTxSimulationResults() 261 assert.NoError(t, err) 262 pubSimulationBytes, err := simRes.GetPubSimulationBytes() 263 assert.NoError(t, err) 264 bcInfo, err := theLedger.GetBlockchainInfo() 265 assert.NoError(t, err) 266 block0 := testutil.ConstructBlock(t, 2, bcInfo.CurrentBlockHash, [][]byte{pubSimulationBytes}, true) 267 err = theLedger.CommitLegacy(&ledger.BlockAndPvtData{Block: block0}, &ledger.CommitOptions{}) 268 assert.NoError(t, err) 269 } 270 271 func putCCInfo(theLedger ledger.PeerLedger, ccname string, policy []byte, t *testing.T) { 272 putCCInfoWithVSCCAndVer(theLedger, ccname, "vscc", ccVersion, policy, t) 273 } 274 275 func assertInvalid(block *common.Block, t *testing.T, code peer.TxValidationCode) { 276 txsFilter := lutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 277 assert.True(t, txsFilter.IsInvalid(0)) 278 assert.True(t, txsFilter.IsSetTo(0, code)) 279 } 280 281 func assertValid(block *common.Block, t *testing.T) { 282 txsFilter := lutils.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 283 assert.False(t, txsFilter.IsInvalid(0)) 284 } 285 286 func TestInvokeBadRWSet(t *testing.T) { 287 t.Run("1.2Capability", func(t *testing.T) { 288 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 289 defer cleanup() 290 291 testInvokeBadRWSet(t, l, v) 292 }) 293 294 t.Run("1.3Capability", func(t *testing.T) { 295 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 296 defer cleanup() 297 298 testInvokeBadRWSet(t, l, v) 299 }) 300 } 301 302 func testInvokeBadRWSet(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 303 ccID := "mycc" 304 305 tx := getEnv(ccID, nil, []byte("barf"), t) 306 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 1}} 307 308 err := v.Validate(b) 309 assert.NoError(t, err) 310 assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET) 311 } 312 313 func TestInvokeNoPolicy(t *testing.T) { 314 t.Run("1.2Capability", func(t *testing.T) { 315 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 316 defer cleanup() 317 318 testInvokeNoPolicy(t, l, v) 319 }) 320 321 t.Run("1.3Capability", func(t *testing.T) { 322 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 323 defer cleanup() 324 325 testInvokeNoPolicy(t, l, v) 326 }) 327 } 328 329 func testInvokeNoPolicy(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 330 ccID := "mycc" 331 332 putCCInfo(l, ccID, nil, t) 333 334 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 335 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 336 337 err := v.Validate(b) 338 assert.NoError(t, err) 339 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 340 } 341 342 func TestInvokeOK(t *testing.T) { 343 t.Run("1.2Capability", func(t *testing.T) { 344 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 345 defer cleanup() 346 347 testInvokeOK(t, l, v) 348 }) 349 350 t.Run("1.3Capability", func(t *testing.T) { 351 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 352 defer cleanup() 353 354 testInvokeOK(t, l, v) 355 }) 356 } 357 358 func testInvokeOK(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 359 ccID := "mycc" 360 361 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 362 363 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 364 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 365 366 err := v.Validate(b) 367 assert.NoError(t, err) 368 assertValid(b, t) 369 } 370 371 func TestInvokeNOKDuplicateNs(t *testing.T) { 372 t.Run("1.2Capability", func(t *testing.T) { 373 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 374 defer cleanup() 375 376 testInvokeNOKDuplicateNs(t, l, v) 377 }) 378 379 t.Run("1.3Capability", func(t *testing.T) { 380 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 381 defer cleanup() 382 383 testInvokeNOKDuplicateNs(t, l, v) 384 }) 385 } 386 387 func testInvokeNOKDuplicateNs(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 388 ccID := "mycc" 389 390 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 391 392 // note that this read-write set has two read-write sets for the same namespace and key 393 txrws := &rwset.TxReadWriteSet{ 394 DataModel: rwset.TxReadWriteSet_KV, 395 NsRwset: []*rwset.NsReadWriteSet{ 396 { 397 Namespace: "mycc", 398 Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{ 399 Writes: []*kvrwset.KVWrite{ 400 { 401 Key: "foo", 402 Value: []byte("bar1"), 403 }, 404 }, 405 }), 406 }, 407 { 408 Namespace: "mycc", 409 Rwset: protoutil.MarshalOrPanic(&kvrwset.KVRWSet{ 410 Writes: []*kvrwset.KVWrite{ 411 { 412 Key: "foo", 413 Value: []byte("bar2"), 414 }, 415 }, 416 }), 417 }, 418 }, 419 } 420 421 tx := getEnv(ccID, nil, protoutil.MarshalOrPanic(txrws), t) 422 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 423 424 err := v.Validate(b) 425 assert.NoError(t, err) 426 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 427 } 428 429 func TestInvokeNoRWSet(t *testing.T) { 430 plugin := &mocks.Plugin{} 431 plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) 432 433 t.Run("Pre-1.2Capability", func(t *testing.T) { 434 l, v, cleanup := setupLedgerAndValidatorExplicit(t, preV12Capabilities(), plugin) 435 defer cleanup() 436 437 ccID := "mycc" 438 439 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 440 441 tx := getEnv(ccID, nil, createRWset(t), t) 442 b := &common.Block{ 443 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 444 Header: &common.BlockHeader{}, 445 } 446 447 err := v.Validate(b) 448 assert.NoError(t, err) 449 assertValid(b, t) 450 }) 451 452 mspmgr := &mocks2.MSPManager{} 453 idThatSatisfiesPrincipal := &mocks2.Identity{} 454 idThatSatisfiesPrincipal.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 455 idThatSatisfiesPrincipal.GetIdentifierReturns(&msp.IdentityIdentifier{}) 456 mspmgr.DeserializeIdentityReturns(idThatSatisfiesPrincipal, nil) 457 458 // No need to define validation behavior for the previous test case because pre 1.2 we don't validate transactions 459 // that have no write set. 460 t.Run("Post-1.2Capability", func(t *testing.T) { 461 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v12Capabilities(), &builtin.DefaultValidation{}, mspmgr) 462 defer cleanup() 463 464 testInvokeNoRWSet(t, l, v) 465 }) 466 467 // Here we test that if we have the 1.3 capability, we still reject a transaction that only contains 468 // reads if it doesn't comply with the endorsement policy 469 t.Run("Post-1.3Capability", func(t *testing.T) { 470 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v13Capabilities(), &builtin.DefaultValidation{}, mspmgr) 471 defer cleanup() 472 473 testInvokeNoRWSet(t, l, v) 474 }) 475 } 476 477 func testInvokeNoRWSet(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 478 ccID := "mycc" 479 480 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 481 482 tx := getEnv(ccID, nil, createRWset(t), t) 483 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 484 485 err := v.Validate(b) 486 assert.NoError(t, err) 487 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 488 } 489 490 // SerializedIdentity mock for the parallel validation test 491 type mockSI struct { 492 SerializedID []byte 493 MspID string 494 SatPrinError error 495 } 496 497 func (msi *mockSI) ExpiresAt() time.Time { 498 return time.Now() 499 } 500 501 func (msi *mockSI) GetIdentifier() *msp.IdentityIdentifier { 502 return &msp.IdentityIdentifier{ 503 Mspid: msi.MspID, 504 Id: "", 505 } 506 } 507 508 func (msi *mockSI) GetMSPIdentifier() string { 509 return msi.MspID 510 } 511 512 func (msi *mockSI) Validate() error { 513 return nil 514 } 515 516 func (msi *mockSI) GetOrganizationalUnits() []*msp.OUIdentifier { 517 return nil 518 } 519 520 func (msi *mockSI) Anonymous() bool { 521 return false 522 } 523 524 func (msi *mockSI) Verify(msg []byte, sig []byte) error { 525 return nil 526 } 527 528 func (msi *mockSI) Serialize() ([]byte, error) { 529 sid := &mb.SerializedIdentity{ 530 Mspid: msi.MspID, 531 IdBytes: msi.SerializedID, 532 } 533 sidBytes := protoutil.MarshalOrPanic(sid) 534 return sidBytes, nil 535 } 536 537 func (msi *mockSI) SatisfiesPrincipal(principal *mb.MSPPrincipal) error { 538 return msi.SatPrinError 539 } 540 541 func (msi *mockSI) Sign(msg []byte) ([]byte, error) { 542 return msg, nil 543 } 544 545 func (msi *mockSI) GetPublicVersion() msp.Identity { 546 return msi 547 } 548 549 // MSP mock for the parallel validation test 550 type mockMSP struct { 551 ID msp.Identity 552 SatPrinError error 553 MspID string 554 } 555 556 func (fake *mockMSP) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) { 557 return fake.ID, nil 558 } 559 560 func (fake *mockMSP) IsWellFormed(identity *mb.SerializedIdentity) error { 561 return nil 562 } 563 func (fake *mockMSP) Setup(config *mb.MSPConfig) error { 564 return nil 565 } 566 567 func (fake *mockMSP) GetVersion() msp.MSPVersion { 568 return msp.MSPv1_3 569 } 570 571 func (fake *mockMSP) GetType() msp.ProviderType { 572 return msp.FABRIC 573 } 574 575 func (fake *mockMSP) GetIdentifier() (string, error) { 576 return fake.MspID, nil 577 } 578 579 func (fake *mockMSP) GetSigningIdentity(identifier *msp.IdentityIdentifier) (msp.SigningIdentity, error) { 580 return nil, nil 581 } 582 583 func (fake *mockMSP) GetDefaultSigningIdentity() (msp.SigningIdentity, error) { 584 return nil, nil 585 } 586 587 func (fake *mockMSP) GetTLSRootCerts() [][]byte { 588 return nil 589 } 590 591 func (fake *mockMSP) GetTLSIntermediateCerts() [][]byte { 592 return nil 593 } 594 595 func (fake *mockMSP) Validate(id msp.Identity) error { 596 return nil 597 } 598 599 func (fake *mockMSP) SatisfiesPrincipal(id msp.Identity, principal *mb.MSPPrincipal) error { 600 return fake.SatPrinError 601 } 602 603 // parallel validation on a block with a high number of transactions and sbe dependencies among those 604 func TestParallelValidation(t *testing.T) { 605 // number of transactions in the block 606 txCnt := 100 607 608 // create two MSPs to control the policy evaluation result, one of them returning an error on SatisfiesPrincipal() 609 msp1 := &mockMSP{ 610 ID: &mockSI{ 611 MspID: "Org1", 612 SerializedID: []byte("signer0"), 613 SatPrinError: nil, 614 }, 615 SatPrinError: nil, 616 MspID: "Org1", 617 } 618 msp2 := &mockMSP{ 619 ID: &mockSI{ 620 MspID: "Org2", 621 SerializedID: []byte("signer1"), 622 SatPrinError: errors.New("nope"), 623 }, 624 SatPrinError: errors.New("nope"), 625 MspID: "Org2", 626 } 627 mgmt.GetManagerForChain("foochain") 628 mgr := mgmt.GetManagerForChain("foochain") 629 mgr.Setup([]msp.MSP{msp1, msp2}) 630 631 vpKey := pb.MetaDataKeys_VALIDATION_PARAMETER.String() 632 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP( 633 t, 634 v13Capabilities(), 635 &builtin.DefaultValidation{}, 636 mgr, 637 ) 638 defer cleanup() 639 640 ccID := "mycc" 641 642 policy := policydsl.SignedByMspPeer("Org1") 643 polBytes := protoutil.MarshalOrPanic(policy) 644 putCCInfo(l, ccID, polBytes, t) 645 646 // create a number of txes 647 blockData := make([][]byte, 0, txCnt) 648 col := "col1" 649 sigID0 := &mockSI{ 650 SerializedID: []byte("signer0"), 651 MspID: "Org1", 652 } 653 sigID1 := &mockSI{ 654 SerializedID: []byte("signer1"), 655 MspID: "Org2", 656 } 657 for txNum := 0; txNum < txCnt; txNum++ { 658 var sig msp.SigningIdentity 659 // create rwset for the tx - KVS key depends on the txnum 660 key := strconv.Itoa(txNum % 10) 661 rwsetBuilder := rwsetutil.NewRWSetBuilder() 662 // pick action that we want to do: read / modify the value or the ep 663 switch uint(txNum / 10) { 664 case 0: 665 // set the value of the key (valid) 666 rwsetBuilder.AddToWriteSet(ccID, key, []byte("value1")) 667 sig = sigID0 668 case 1: 669 // set the ep of the key (invalid, because Org2's MSP returns principal not satisfied) 670 metadata := make(map[string][]byte) 671 metadata[vpKey] = signedByAnyMember([]string{"SampleOrg"}) 672 rwsetBuilder.AddToMetadataWriteSet(ccID, key, metadata) 673 sig = sigID1 674 case 2: 675 // set the value of the key (valid, because the ep change before was invalid) 676 rwsetBuilder.AddToWriteSet(ccID, key, []byte("value2")) 677 sig = sigID0 678 case 3: 679 // set the ep of the key (valid) 680 metadata := make(map[string][]byte) 681 metadata[vpKey] = signedByAnyMember([]string{"Org2"}) 682 rwsetBuilder.AddToMetadataWriteSet(ccID, key, metadata) 683 sig = sigID0 684 case 4: 685 // set the value of the key (invalid, because the ep change before was valid) 686 rwsetBuilder.AddToWriteSet(ccID, key, []byte("value3")) 687 sig = &mockSI{ 688 SerializedID: []byte("signer0"), 689 MspID: "Org1", 690 } 691 // do the same txes for private data 692 case 5: 693 // set the value of the key (valid) 694 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value1")) 695 sig = sigID0 696 case 6: 697 // set the ep of the key (invalid, because Org2's MSP returns principal not satisfied) 698 metadata := make(map[string][]byte) 699 metadata[vpKey] = signedByAnyMember([]string{"SampleOrg"}) 700 rwsetBuilder.AddToHashedMetadataWriteSet(ccID, col, key, metadata) 701 sig = sigID1 702 case 7: 703 // set the value of the key (valid, because the ep change before was invalid) 704 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value2")) 705 sig = sigID0 706 case 8: 707 // set the ep of the key (valid) 708 metadata := make(map[string][]byte) 709 metadata[vpKey] = signedByAnyMember([]string{"Org2"}) 710 rwsetBuilder.AddToHashedMetadataWriteSet(ccID, col, key, metadata) 711 sig = sigID0 712 case 9: 713 // set the value of the key (invalid, because the ep change before was valid) 714 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, col, key, []byte("value3")) 715 sig = sigID0 716 } 717 rwset, err := rwsetBuilder.GetTxSimulationResults() 718 assert.NoError(t, err) 719 rwsetBytes, err := rwset.GetPubSimulationBytes() 720 tx := getEnvWithSigner(ccID, nil, rwsetBytes, sig, t) 721 blockData = append(blockData, protoutil.MarshalOrPanic(tx)) 722 } 723 724 // assemble block from all those txes 725 b := &common.Block{Data: &common.BlockData{Data: blockData}, Header: &common.BlockHeader{Number: uint64(txCnt)}} 726 727 // validate the block 728 err := v.Validate(b) 729 assert.NoError(t, err) 730 731 // Block metadata array position to store serialized bit array filter of invalid transactions 732 txsFilter := lutils.TxValidationFlags(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 733 // tx validity 734 for txNum := 0; txNum < txCnt; txNum += 1 { 735 switch uint(txNum / 10) { 736 case 1: 737 fallthrough 738 case 4: 739 fallthrough 740 case 6: 741 fallthrough 742 case 9: 743 assert.True(t, txsFilter.IsInvalid(txNum)) 744 default: 745 assert.False(t, txsFilter.IsInvalid(txNum)) 746 } 747 } 748 } 749 750 func TestChaincodeEvent(t *testing.T) { 751 t.Run("PreV1.2", func(t *testing.T) { 752 t.Run("MisMatchedName", func(t *testing.T) { 753 l, v, cleanup := setupLedgerAndValidatorWithPreV12Capabilities(t) 754 defer cleanup() 755 756 ccID := "mycc" 757 758 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 759 760 tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: "wrong"}), createRWset(t), t) 761 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 762 763 err := v.Validate(b) 764 assert.NoError(t, err) 765 assertValid(b, t) 766 }) 767 768 t.Run("BadBytes", func(t *testing.T) { 769 l, v, cleanup := setupLedgerAndValidatorWithPreV12Capabilities(t) 770 defer cleanup() 771 772 ccID := "mycc" 773 774 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 775 776 tx := getEnv(ccID, []byte("garbage"), createRWset(t), t) 777 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 778 779 err := v.Validate(b) 780 assert.NoError(t, err) 781 assertValid(b, t) 782 }) 783 784 t.Run("GoodPath", func(t *testing.T) { 785 l, v, cleanup := setupLedgerAndValidatorWithPreV12Capabilities(t) 786 defer cleanup() 787 788 ccID := "mycc" 789 790 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 791 792 tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: ccID}), createRWset(t), t) 793 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 794 795 err := v.Validate(b) 796 assert.NoError(t, err) 797 assertValid(b, t) 798 }) 799 }) 800 801 t.Run("PostV1.2", func(t *testing.T) { 802 t.Run("MisMatchedName", func(t *testing.T) { 803 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 804 defer cleanup() 805 806 testCCEventMismatchedName(t, l, v) 807 }) 808 809 t.Run("BadBytes", func(t *testing.T) { 810 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 811 defer cleanup() 812 813 testCCEventBadBytes(t, l, v) 814 }) 815 816 t.Run("GoodPath", func(t *testing.T) { 817 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 818 defer cleanup() 819 820 testCCEventGoodPath(t, l, v) 821 }) 822 }) 823 824 t.Run("V1.3", func(t *testing.T) { 825 t.Run("MisMatchedName", func(t *testing.T) { 826 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 827 defer cleanup() 828 829 testCCEventMismatchedName(t, l, v) 830 }) 831 832 t.Run("BadBytes", func(t *testing.T) { 833 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 834 defer cleanup() 835 836 testCCEventBadBytes(t, l, v) 837 }) 838 839 t.Run("GoodPath", func(t *testing.T) { 840 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 841 defer cleanup() 842 843 testCCEventGoodPath(t, l, v) 844 }) 845 }) 846 } 847 848 func testCCEventMismatchedName(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 849 ccID := "mycc" 850 851 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 852 853 tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: "wrong"}), createRWset(t), t) 854 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 855 856 err := v.Validate(b) 857 assert.NoError(t, err) // TODO, convert test so it can check the error text for INVALID_OTHER_REASON 858 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 859 } 860 861 func testCCEventBadBytes(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 862 ccID := "mycc" 863 864 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 865 866 tx := getEnv(ccID, []byte("garbage"), createRWset(t), t) 867 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 868 869 err := v.Validate(b) 870 assert.NoError(t, err) // TODO, convert test so it can check the error text for INVALID_OTHER_REASON 871 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 872 } 873 874 func testCCEventGoodPath(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 875 ccID := "mycc" 876 877 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 878 879 tx := getEnv(ccID, protoutil.MarshalOrPanic(&peer.ChaincodeEvent{ChaincodeId: ccID}), createRWset(t), t) 880 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 881 882 err := v.Validate(b) 883 assert.NoError(t, err) 884 assertValid(b, t) 885 } 886 887 func TestInvokeOKPvtDataOnly(t *testing.T) { 888 mspmgr := &mocks2.MSPManager{} 889 idThatSatisfiesPrincipal := &mocks2.Identity{} 890 idThatSatisfiesPrincipal.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 891 idThatSatisfiesPrincipal.GetIdentifierReturns(&msp.IdentityIdentifier{}) 892 mspmgr.DeserializeIdentityReturns(idThatSatisfiesPrincipal, nil) 893 894 t.Run("V1.2", func(t *testing.T) { 895 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v12Capabilities(), &builtin.DefaultValidation{}, mspmgr) 896 defer cleanup() 897 898 testInvokeOKPvtDataOnly(t, l, v) 899 }) 900 901 t.Run("V1.3", func(t *testing.T) { 902 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v13Capabilities(), &builtin.DefaultValidation{}, mspmgr) 903 defer cleanup() 904 905 testInvokeOKPvtDataOnly(t, l, v) 906 }) 907 } 908 909 func testInvokeOKPvtDataOnly(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 910 ccID := "mycc" 911 912 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 913 914 rwsetBuilder := rwsetutil.NewRWSetBuilder() 915 rwsetBuilder.AddToPvtAndHashedWriteSet(ccID, "mycollection", "somekey", nil) 916 rwset, err := rwsetBuilder.GetTxSimulationResults() 917 assert.NoError(t, err) 918 rwsetBytes, err := rwset.GetPubSimulationBytes() 919 assert.NoError(t, err) 920 921 tx := getEnv(ccID, nil, rwsetBytes, t) 922 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 923 924 err = v.Validate(b) 925 assert.NoError(t, err) 926 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 927 } 928 929 func TestInvokeOKMetaUpdateOnly(t *testing.T) { 930 mspmgr := &mocks2.MSPManager{} 931 idThatSatisfiesPrincipal := &mocks2.Identity{} 932 idThatSatisfiesPrincipal.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 933 idThatSatisfiesPrincipal.GetIdentifierReturns(&msp.IdentityIdentifier{}) 934 mspmgr.DeserializeIdentityReturns(idThatSatisfiesPrincipal, nil) 935 936 t.Run("V1.2", func(t *testing.T) { 937 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v12Capabilities(), &builtin.DefaultValidation{}, mspmgr) 938 defer cleanup() 939 940 testInvokeOKMetaUpdateOnly(t, l, v) 941 }) 942 943 t.Run("V1.3", func(t *testing.T) { 944 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v13Capabilities(), &builtin.DefaultValidation{}, mspmgr) 945 defer cleanup() 946 947 testInvokeOKMetaUpdateOnly(t, l, v) 948 }) 949 } 950 951 func testInvokeOKMetaUpdateOnly(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 952 ccID := "mycc" 953 954 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 955 956 rwsetBuilder := rwsetutil.NewRWSetBuilder() 957 rwsetBuilder.AddToMetadataWriteSet(ccID, "somekey", map[string][]byte{}) 958 rwset, err := rwsetBuilder.GetTxSimulationResults() 959 assert.NoError(t, err) 960 rwsetBytes, err := rwset.GetPubSimulationBytes() 961 assert.NoError(t, err) 962 963 tx := getEnv(ccID, nil, rwsetBytes, t) 964 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 965 966 err = v.Validate(b) 967 assert.NoError(t, err) 968 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 969 } 970 971 func TestInvokeOKPvtMetaUpdateOnly(t *testing.T) { 972 mspmgr := &mocks2.MSPManager{} 973 idThatSatisfiesPrincipal := &mocks2.Identity{} 974 idThatSatisfiesPrincipal.SatisfiesPrincipalReturns(errors.New("principal not satisfied")) 975 idThatSatisfiesPrincipal.GetIdentifierReturns(&msp.IdentityIdentifier{}) 976 mspmgr.DeserializeIdentityReturns(idThatSatisfiesPrincipal, nil) 977 978 t.Run("V1.2", func(t *testing.T) { 979 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v12Capabilities(), &builtin.DefaultValidation{}, mspmgr) 980 defer cleanup() 981 982 testInvokeOKPvtMetaUpdateOnly(t, l, v) 983 }) 984 985 t.Run("V1.3", func(t *testing.T) { 986 l, v, cleanup := setupLedgerAndValidatorExplicitWithMSP(t, v13Capabilities(), &builtin.DefaultValidation{}, mspmgr) 987 defer cleanup() 988 989 testInvokeOKPvtMetaUpdateOnly(t, l, v) 990 }) 991 } 992 993 func testInvokeOKPvtMetaUpdateOnly(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 994 ccID := "mycc" 995 996 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 997 998 rwsetBuilder := rwsetutil.NewRWSetBuilder() 999 rwsetBuilder.AddToHashedMetadataWriteSet(ccID, "mycollection", "somekey", map[string][]byte{}) 1000 rwset, err := rwsetBuilder.GetTxSimulationResults() 1001 assert.NoError(t, err) 1002 rwsetBytes, err := rwset.GetPubSimulationBytes() 1003 assert.NoError(t, err) 1004 1005 tx := getEnv(ccID, nil, rwsetBytes, t) 1006 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 1007 1008 err = v.Validate(b) 1009 assert.NoError(t, err) 1010 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 1011 } 1012 1013 func TestInvokeOKSCC(t *testing.T) { 1014 t.Run("1.2Capability", func(t *testing.T) { 1015 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1016 defer cleanup() 1017 1018 testInvokeOKSCC(t, l, v) 1019 }) 1020 1021 t.Run("1.3Capability", func(t *testing.T) { 1022 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1023 defer cleanup() 1024 1025 testInvokeOKSCC(t, l, v) 1026 }) 1027 } 1028 1029 func testInvokeOKSCC(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1030 cds := protoutil.MarshalOrPanic(&peer.ChaincodeDeploymentSpec{ 1031 ChaincodeSpec: &peer.ChaincodeSpec{ 1032 Type: peer.ChaincodeSpec_GOLANG, 1033 ChaincodeId: &peer.ChaincodeID{Name: "cc", Version: "ver"}, 1034 Input: &peer.ChaincodeInput{}, 1035 }, 1036 }) 1037 cis := &peer.ChaincodeInvocationSpec{ 1038 ChaincodeSpec: &peer.ChaincodeSpec{ 1039 ChaincodeId: &peer.ChaincodeID{Name: "lscc", Version: ccVersion}, 1040 Input: &peer.ChaincodeInput{Args: [][]byte{[]byte("deploy"), []byte("testchannelid"), cds}}, 1041 Type: peer.ChaincodeSpec_GOLANG}} 1042 1043 prop, _, err := protoutil.CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "testchannelid", cis, signerSerialized) 1044 assert.NoError(t, err) 1045 rwsetBuilder := rwsetutil.NewRWSetBuilder() 1046 rwsetBuilder.AddToWriteSet("lscc", "cc", protoutil.MarshalOrPanic(&ccp.ChaincodeData{Name: "cc", Version: "ver", InstantiationPolicy: policydsl.MarshaledAcceptAllPolicy})) 1047 rwset, err := rwsetBuilder.GetTxSimulationResults() 1048 assert.NoError(t, err) 1049 rwsetBytes, err := rwset.GetPubSimulationBytes() 1050 assert.NoError(t, err) 1051 presp, err := protoutil.CreateProposalResponse(prop.Header, prop.Payload, &peer.Response{Status: 200}, rwsetBytes, nil, &peer.ChaincodeID{Name: "lscc", Version: ccVersion}, signer) 1052 assert.NoError(t, err) 1053 tx, err := protoutil.CreateSignedTx(prop, signer, presp) 1054 assert.NoError(t, err) 1055 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 1}} 1056 1057 err = v.Validate(b) 1058 assert.NoError(t, err) 1059 assertValid(b, t) 1060 } 1061 1062 func TestInvokeNOKWritesToLSCC(t *testing.T) { 1063 t.Run("1.2Capability", func(t *testing.T) { 1064 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1065 defer cleanup() 1066 1067 testInvokeNOKWritesToLSCC(t, l, v) 1068 }) 1069 1070 t.Run("1.3Capability", func(t *testing.T) { 1071 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1072 defer cleanup() 1073 1074 testInvokeNOKWritesToLSCC(t, l, v) 1075 }) 1076 } 1077 1078 func testInvokeNOKWritesToLSCC(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1079 ccID := "mycc" 1080 1081 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1082 1083 tx := getEnv(ccID, nil, createRWset(t, ccID, "lscc"), t) 1084 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 2}} 1085 1086 err := v.Validate(b) 1087 assert.NoError(t, err) 1088 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 1089 } 1090 1091 func TestInvokeNOKWritesToESCC(t *testing.T) { 1092 t.Run("1.2Capability", func(t *testing.T) { 1093 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1094 defer cleanup() 1095 1096 testInvokeNOKWritesToESCC(t, l, v) 1097 }) 1098 1099 t.Run("1.3Capability", func(t *testing.T) { 1100 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1101 defer cleanup() 1102 1103 testInvokeNOKWritesToESCC(t, l, v) 1104 }) 1105 } 1106 1107 func testInvokeNOKWritesToESCC(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1108 ccID := "mycc" 1109 1110 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1111 1112 tx := getEnv(ccID, nil, createRWset(t, ccID, "escc"), t) 1113 b := &common.Block{ 1114 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1115 Header: &common.BlockHeader{}, 1116 } 1117 1118 err := v.Validate(b) 1119 assert.NoError(t, err) 1120 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 1121 } 1122 1123 func TestInvokeNOKWritesToNotExt(t *testing.T) { 1124 t.Run("1.2Capability", func(t *testing.T) { 1125 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1126 defer cleanup() 1127 1128 testInvokeNOKWritesToNotExt(t, l, v) 1129 }) 1130 1131 t.Run("1.3Capability", func(t *testing.T) { 1132 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1133 defer cleanup() 1134 1135 testInvokeNOKWritesToNotExt(t, l, v) 1136 }) 1137 } 1138 1139 func testInvokeNOKWritesToNotExt(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1140 ccID := "mycc" 1141 1142 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1143 1144 tx := getEnv(ccID, nil, createRWset(t, ccID, "escc"), t) 1145 b := &common.Block{ 1146 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1147 Header: &common.BlockHeader{}, 1148 } 1149 1150 err := v.Validate(b) 1151 assert.NoError(t, err) 1152 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 1153 } 1154 1155 func TestInvokeNOKInvokesNotExt(t *testing.T) { 1156 t.Run("1.2Capability", func(t *testing.T) { 1157 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1158 defer cleanup() 1159 1160 testInvokeNOKInvokesNotExt(t, l, v) 1161 }) 1162 1163 t.Run("1.3Capability", func(t *testing.T) { 1164 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1165 defer cleanup() 1166 1167 testInvokeNOKInvokesNotExt(t, l, v) 1168 }) 1169 } 1170 1171 func testInvokeNOKInvokesNotExt(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1172 ccID := "escc" 1173 1174 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 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 assert.NoError(t, err) 1184 assertInvalid(b, t, peer.TxValidationCode_ILLEGAL_WRITESET) 1185 } 1186 1187 func TestInvokeNOKInvokesEmptyCCName(t *testing.T) { 1188 t.Run("1.2Capability", func(t *testing.T) { 1189 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1190 defer cleanup() 1191 1192 testInvokeNOKInvokesEmptyCCName(t, l, v) 1193 }) 1194 1195 t.Run("1.3Capability", func(t *testing.T) { 1196 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1197 defer cleanup() 1198 1199 testInvokeNOKInvokesEmptyCCName(t, l, v) 1200 }) 1201 } 1202 1203 func testInvokeNOKInvokesEmptyCCName(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1204 ccID := "" 1205 1206 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1207 1208 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1209 b := &common.Block{ 1210 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1211 Header: &common.BlockHeader{}, 1212 } 1213 1214 err := v.Validate(b) 1215 assert.NoError(t, err) 1216 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 1217 } 1218 1219 func TestInvokeNOKExpiredCC(t *testing.T) { 1220 t.Run("1.2Capability", func(t *testing.T) { 1221 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1222 defer cleanup() 1223 1224 testInvokeNOKExpiredCC(t, l, v) 1225 }) 1226 1227 t.Run("1.3Capability", func(t *testing.T) { 1228 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1229 defer cleanup() 1230 1231 testInvokeNOKExpiredCC(t, l, v) 1232 }) 1233 } 1234 1235 func testInvokeNOKExpiredCC(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1236 ccID := "mycc" 1237 1238 putCCInfoWithVSCCAndVer(l, ccID, "vscc", "badversion", signedByAnyMember([]string{"SampleOrg"}), t) 1239 1240 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1241 b := &common.Block{ 1242 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1243 Header: &common.BlockHeader{}, 1244 } 1245 1246 err := v.Validate(b) 1247 assert.NoError(t, err) 1248 assertInvalid(b, t, peer.TxValidationCode_EXPIRED_CHAINCODE) 1249 } 1250 1251 func TestInvokeNOKBogusActions(t *testing.T) { 1252 t.Run("1.2Capability", func(t *testing.T) { 1253 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1254 defer cleanup() 1255 1256 testInvokeNOKBogusActions(t, l, v) 1257 }) 1258 1259 t.Run("1.3Capability", func(t *testing.T) { 1260 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1261 defer cleanup() 1262 1263 testInvokeNOKBogusActions(t, l, v) 1264 }) 1265 } 1266 1267 func testInvokeNOKBogusActions(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1268 ccID := "mycc" 1269 1270 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1271 1272 tx := getEnv(ccID, nil, []byte("barf"), t) 1273 b := &common.Block{ 1274 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1275 Header: &common.BlockHeader{}, 1276 } 1277 1278 err := v.Validate(b) 1279 assert.NoError(t, err) 1280 assertInvalid(b, t, peer.TxValidationCode_BAD_RWSET) 1281 } 1282 1283 func TestInvokeNOKCCDoesntExist(t *testing.T) { 1284 t.Run("1.2Capability", func(t *testing.T) { 1285 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1286 defer cleanup() 1287 1288 testInvokeNOKCCDoesntExist(t, l, v) 1289 }) 1290 1291 t.Run("1.3Capability", func(t *testing.T) { 1292 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1293 defer cleanup() 1294 1295 testInvokeNOKCCDoesntExist(t, l, v) 1296 }) 1297 } 1298 1299 func testInvokeNOKCCDoesntExist(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1300 ccID := "mycc" 1301 1302 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1303 b := &common.Block{ 1304 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1305 Header: &common.BlockHeader{}, 1306 } 1307 1308 err := v.Validate(b) 1309 assert.NoError(t, err) 1310 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 1311 } 1312 1313 func TestInvokeNOKVSCCUnspecified(t *testing.T) { 1314 t.Run("1.2Capability", func(t *testing.T) { 1315 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1316 defer cleanup() 1317 1318 testInvokeNOKVSCCUnspecified(t, l, v) 1319 }) 1320 1321 t.Run("1.3Capability", func(t *testing.T) { 1322 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1323 defer cleanup() 1324 1325 testInvokeNOKVSCCUnspecified(t, l, v) 1326 }) 1327 } 1328 1329 func testInvokeNOKVSCCUnspecified(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1330 ccID := "mycc" 1331 1332 putCCInfoWithVSCCAndVer(l, ccID, "", ccVersion, signedByAnyMember([]string{"SampleOrg"}), t) 1333 1334 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1335 b := &common.Block{ 1336 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1337 Header: &common.BlockHeader{}, 1338 } 1339 1340 err := v.Validate(b) 1341 assert.NoError(t, err) 1342 assertInvalid(b, t, peer.TxValidationCode_INVALID_OTHER_REASON) 1343 } 1344 1345 func TestInvokeNoBlock(t *testing.T) { 1346 t.Run("1.2Capability", func(t *testing.T) { 1347 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1348 defer cleanup() 1349 1350 testInvokeNoBlock(t, l, v) 1351 }) 1352 1353 t.Run("1.3Capability", func(t *testing.T) { 1354 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1355 defer cleanup() 1356 1357 testInvokeNoBlock(t, l, v) 1358 }) 1359 } 1360 1361 func testInvokeNoBlock(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) { 1362 err := v.Validate(&common.Block{ 1363 Data: &common.BlockData{Data: [][]byte{}}, 1364 Header: &common.BlockHeader{}, 1365 }) 1366 assert.NoError(t, err) 1367 } 1368 1369 func TestValidateTxWithStateBasedEndorsement(t *testing.T) { 1370 1371 // SCENARIO: we validate a transaction that writes to key "key". This key 1372 // has a state-based endorsement policy that cannot be satisfied, while 1373 // the chaincode endorseemnt policy is satisfied by this transaction. 1374 // When we run with the 1.2 capability we expect the transaction to be 1375 // successfully validated, while when we run with the 1.3 capability, 1376 // validation is expected to fail owing to the unsatisfiable SBEP. 1377 // Notice that this corner case should never occur in practice, since 1378 // capabilities also determine whether honest peers will endorse 1379 // chaincodes that set state-based endorsement policies. Still, the test 1380 // is valuable as it shows how transactions that are affected by state-based 1381 // endorsement policies are handled by the 1.3 validation, and simply 1382 // ignored by 1.2. 1383 1384 t.Run("1.2Capability", func(t *testing.T) { 1385 l, v, cleanup := setupLedgerAndValidatorWithV12Capabilities(t) 1386 defer cleanup() 1387 1388 err, b := validateTxWithStateBasedEndorsement(t, l, v) 1389 1390 assert.NoError(t, err) 1391 assertValid(b, t) 1392 }) 1393 1394 t.Run("1.3Capability", func(t *testing.T) { 1395 l, v, cleanup := setupLedgerAndValidatorWithV13Capabilities(t) 1396 defer cleanup() 1397 1398 err, b := validateTxWithStateBasedEndorsement(t, l, v) 1399 1400 assert.NoError(t, err) 1401 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 1402 }) 1403 } 1404 1405 func validateTxWithStateBasedEndorsement(t *testing.T, l ledger.PeerLedger, v txvalidator.Validator) (error, *common.Block) { 1406 ccID := "mycc" 1407 1408 putCCInfoWithVSCCAndVer(l, ccID, "vscc", ccVersion, signedByAnyMember([]string{"SampleOrg"}), t) 1409 putSBEP(l, ccID, "key", policydsl.MarshaledRejectAllPolicy, t) 1410 1411 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1412 b := &common.Block{Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, Header: &common.BlockHeader{Number: 3}} 1413 1414 err := v.Validate(b) 1415 1416 return err, b 1417 } 1418 1419 // mockLedger structure used to test ledger 1420 // failure, therefore leveraging mocking 1421 // library as need to simulate ledger which not 1422 // able to get access to state db 1423 type mockLedger struct { 1424 mock.Mock 1425 } 1426 1427 // GetTransactionByID returns transaction by ud 1428 func (m *mockLedger) GetTransactionByID(txID string) (*peer.ProcessedTransaction, error) { 1429 args := m.Called(txID) 1430 return args.Get(0).(*peer.ProcessedTransaction), args.Error(1) 1431 } 1432 1433 // GetBlockByHash returns block using its hash value 1434 func (m *mockLedger) GetBlockByHash(blockHash []byte) (*common.Block, error) { 1435 args := m.Called(blockHash) 1436 return args.Get(0).(*common.Block), nil 1437 } 1438 1439 // GetBlockByTxID given transaction id return block transaction was committed with 1440 func (m *mockLedger) GetBlockByTxID(txID string) (*common.Block, error) { 1441 args := m.Called(txID) 1442 return args.Get(0).(*common.Block), nil 1443 } 1444 1445 // GetTxValidationCodeByTxID returns validation code of give tx 1446 func (m *mockLedger) GetTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) { 1447 args := m.Called(txID) 1448 return args.Get(0).(peer.TxValidationCode), nil 1449 } 1450 1451 // NewTxSimulator creates new transaction simulator 1452 func (m *mockLedger) NewTxSimulator(txid string) (ledger.TxSimulator, error) { 1453 args := m.Called() 1454 return args.Get(0).(ledger.TxSimulator), nil 1455 } 1456 1457 // NewQueryExecutor creates query executor 1458 func (m *mockLedger) NewQueryExecutor() (ledger.QueryExecutor, error) { 1459 args := m.Called() 1460 return args.Get(0).(ledger.QueryExecutor), nil 1461 } 1462 1463 // NewHistoryQueryExecutor history query executor 1464 func (m *mockLedger) NewHistoryQueryExecutor() (ledger.HistoryQueryExecutor, error) { 1465 args := m.Called() 1466 return args.Get(0).(ledger.HistoryQueryExecutor), nil 1467 } 1468 1469 // GetPvtDataAndBlockByNum retrieves pvt data and block 1470 func (m *mockLedger) GetPvtDataAndBlockByNum(blockNum uint64, filter ledger.PvtNsCollFilter) (*ledger.BlockAndPvtData, error) { 1471 args := m.Called() 1472 return args.Get(0).(*ledger.BlockAndPvtData), nil 1473 } 1474 1475 // GetPvtDataByNum retrieves the pvt data 1476 func (m *mockLedger) GetPvtDataByNum(blockNum uint64, filter ledger.PvtNsCollFilter) ([]*ledger.TxPvtData, error) { 1477 args := m.Called() 1478 return args.Get(0).([]*ledger.TxPvtData), nil 1479 } 1480 1481 // CommitLegacy commits the block and the corresponding pvt data in an atomic operation 1482 func (m *mockLedger) CommitLegacy(pvtDataAndBlock *ledger.BlockAndPvtData, commitOpts *ledger.CommitOptions) error { 1483 return nil 1484 } 1485 1486 func (m *mockLedger) GetBlockchainInfo() (*common.BlockchainInfo, error) { 1487 args := m.Called() 1488 return args.Get(0).(*common.BlockchainInfo), nil 1489 } 1490 1491 func (m *mockLedger) GetBlockByNumber(blockNumber uint64) (*common.Block, error) { 1492 args := m.Called(blockNumber) 1493 return args.Get(0).(*common.Block), nil 1494 } 1495 1496 func (m *mockLedger) GetBlocksIterator(startBlockNumber uint64) (ledger2.ResultsIterator, error) { 1497 args := m.Called(startBlockNumber) 1498 return args.Get(0).(ledger2.ResultsIterator), nil 1499 } 1500 1501 func (m *mockLedger) DoesPvtDataInfoExist(blkNum uint64) (bool, error) { 1502 args := m.Called() 1503 return args.Get(0).(bool), args.Error(1) 1504 } 1505 1506 func (m *mockLedger) Close() { 1507 1508 } 1509 1510 func (m *mockLedger) Commit(block *common.Block) error { 1511 return nil 1512 } 1513 1514 // GetConfigHistoryRetriever returns the ConfigHistoryRetriever 1515 func (m *mockLedger) GetConfigHistoryRetriever() (ledger.ConfigHistoryRetriever, error) { 1516 args := m.Called() 1517 return args.Get(0).(ledger.ConfigHistoryRetriever), nil 1518 } 1519 1520 func (m *mockLedger) CommitPvtDataOfOldBlocks(reconciledPvtdata []*ledger.ReconciledPvtdata) ([]*ledger.PvtdataHashMismatch, error) { 1521 return nil, nil 1522 } 1523 1524 func (m *mockLedger) GetMissingPvtDataTracker() (ledger.MissingPvtDataTracker, error) { 1525 args := m.Called() 1526 return args.Get(0).(ledger.MissingPvtDataTracker), nil 1527 } 1528 1529 // mockQueryExecutor mock of the query executor, 1530 // needed to simulate inability to access state db, e.g. 1531 // the case where due to db failure it's not possible to 1532 // query for state, for example if we would like to query 1533 // the lccc for VSCC info and db is not avaible we expect 1534 // to stop validating block and fail commit procedure with 1535 // an error. 1536 type mockQueryExecutor struct { 1537 mock.Mock 1538 } 1539 1540 func (exec *mockQueryExecutor) GetState(namespace string, key string) ([]byte, error) { 1541 args := exec.Called(namespace, key) 1542 return args.Get(0).([]byte), args.Error(1) 1543 } 1544 1545 func (exec *mockQueryExecutor) GetStateMultipleKeys(namespace string, keys []string) ([][]byte, error) { 1546 args := exec.Called(namespace, keys) 1547 return args.Get(0).([][]byte), args.Error(1) 1548 } 1549 1550 func (exec *mockQueryExecutor) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (ledger2.ResultsIterator, error) { 1551 args := exec.Called(namespace, startKey, endKey) 1552 return args.Get(0).(ledger2.ResultsIterator), args.Error(1) 1553 } 1554 1555 func (exec *mockQueryExecutor) GetStateRangeScanIteratorWithMetadata(namespace, startKey, endKey string, metadata map[string]interface{}) (ledger.QueryResultsIterator, error) { 1556 args := exec.Called(namespace, startKey, endKey, metadata) 1557 return args.Get(0).(ledger.QueryResultsIterator), args.Error(1) 1558 } 1559 1560 func (exec *mockQueryExecutor) ExecuteQuery(namespace, query string) (ledger2.ResultsIterator, error) { 1561 args := exec.Called(namespace) 1562 return args.Get(0).(ledger2.ResultsIterator), args.Error(1) 1563 } 1564 1565 func (exec *mockQueryExecutor) ExecuteQueryWithMetadata(namespace, query string, metadata map[string]interface{}) (ledger.QueryResultsIterator, error) { 1566 args := exec.Called(namespace, query, metadata) 1567 return args.Get(0).(ledger.QueryResultsIterator), args.Error(1) 1568 } 1569 1570 func (exec *mockQueryExecutor) GetPrivateData(namespace, collection, key string) ([]byte, error) { 1571 args := exec.Called(namespace, collection, key) 1572 return args.Get(0).([]byte), args.Error(1) 1573 } 1574 1575 func (exec *mockQueryExecutor) GetPrivateDataHash(namespace, collection, key string) ([]byte, error) { 1576 args := exec.Called(namespace, collection, key) 1577 return args.Get(0).([]byte), args.Error(1) 1578 } 1579 1580 func (exec *mockQueryExecutor) GetPrivateDataMetadataByHash(namespace, collection string, keyhash []byte) (map[string][]byte, error) { 1581 args := exec.Called(namespace, collection, keyhash) 1582 return args.Get(0).(map[string][]byte), args.Error(1) 1583 } 1584 1585 func (exec *mockQueryExecutor) GetPrivateDataMultipleKeys(namespace, collection string, keys []string) ([][]byte, error) { 1586 args := exec.Called(namespace, collection, keys) 1587 return args.Get(0).([][]byte), args.Error(1) 1588 } 1589 1590 func (exec *mockQueryExecutor) GetPrivateDataRangeScanIterator(namespace, collection, startKey, endKey string) (ledger2.ResultsIterator, error) { 1591 args := exec.Called(namespace, collection, startKey, endKey) 1592 return args.Get(0).(ledger2.ResultsIterator), args.Error(1) 1593 } 1594 1595 func (exec *mockQueryExecutor) ExecuteQueryOnPrivateData(namespace, collection, query string) (ledger2.ResultsIterator, error) { 1596 args := exec.Called(namespace, collection, query) 1597 return args.Get(0).(ledger2.ResultsIterator), args.Error(1) 1598 } 1599 1600 func (exec *mockQueryExecutor) Done() { 1601 } 1602 1603 func (exec *mockQueryExecutor) GetStateMetadata(namespace, key string) (map[string][]byte, error) { 1604 return nil, nil 1605 } 1606 1607 func (exec *mockQueryExecutor) GetPrivateDataMetadata(namespace, collection, key string) (map[string][]byte, error) { 1608 return nil, nil 1609 } 1610 1611 func createCustomSupportAndLedger(t *testing.T) (*mocktxvalidator.Support, ledger.PeerLedger, func()) { 1612 ledgerMgr, cleanup := constructLedgerMgrWithTestDefaults(t, "txvalidator") 1613 gb, err := ctxt.MakeGenesisBlock("TestLedger") 1614 assert.NoError(t, err) 1615 l, err := ledgerMgr.CreateLedger("TestLedger", gb) 1616 assert.NoError(t, err) 1617 1618 identity := &mocks2.Identity{} 1619 identity.GetIdentifierReturns(&msp.IdentityIdentifier{ 1620 Mspid: "SampleOrg", 1621 Id: "foo", 1622 }) 1623 mspManager := &mocks2.MSPManager{} 1624 mspManager.DeserializeIdentityReturns(identity, nil) 1625 support := &mocktxvalidator.Support{LedgerVal: l, ACVal: preV12Capabilities(), MSPManagerVal: mspManager} 1626 return support, l, cleanup 1627 } 1628 1629 func TestDynamicCapabilitiesAndMSP(t *testing.T) { 1630 factory := &mocks.PluginFactory{} 1631 factory.On("New").Return(testdata.NewSampleValidationPlugin(t)) 1632 pm := &mocks.Mapper{} 1633 pm.On("FactoryByName", vp.Name("vscc")).Return(factory) 1634 1635 support, l, cleanup := createCustomSupportAndLedger(t) 1636 defer cleanup() 1637 1638 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1639 assert.NoError(t, err) 1640 v := txvalidatorv14.NewTxValidator("", semaphore.New(10), support, pm, cryptoProvider) 1641 1642 ccID := "mycc" 1643 1644 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1645 1646 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1647 b := &common.Block{ 1648 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1649 Header: &common.BlockHeader{}, 1650 } 1651 1652 // Perform a validation of a block 1653 err = v.Validate(b) 1654 assert.NoError(t, err) 1655 assertValid(b, t) 1656 // Record the number of times the capabilities and the MSP Manager were invoked 1657 capabilityInvokeCount := support.CapabilitiesInvokeCount() 1658 mspManagerInvokeCount := support.MSPManagerInvokeCount() 1659 1660 // Perform another validation pass, and ensure it is valid 1661 err = v.Validate(b) 1662 assert.NoError(t, err) 1663 assertValid(b, t) 1664 1665 // Ensure that the capabilities were retrieved from the support twice, 1666 // which proves that the capabilities are dynamically retrieved from the support each time 1667 assert.Equal(t, 2*capabilityInvokeCount, support.CapabilitiesInvokeCount()) 1668 // Ensure that the MSP Manager was retrieved from the support twice, 1669 // which proves that the MSP Manager is dynamically retrieved from the support each time 1670 assert.Equal(t, 2*mspManagerInvokeCount, support.MSPManagerInvokeCount()) 1671 } 1672 1673 // TestLedgerIsNoAvailable simulates and provides a test for following scenario, 1674 // which is based on FAB-535. Test checks the validation path which expects that 1675 // DB won't available while trying to lookup for VSCC from LCCC and therefore 1676 // transaction validation will have to fail. In such case the outcome should be 1677 // the error return from validate block method and processing of transactions 1678 // has to stop. There is suppose to be clear indication of the failure with error 1679 // returned from the function call. 1680 func TestLedgerIsNoAvailable(t *testing.T) { 1681 theLedger := new(mockLedger) 1682 pm := &mocks.Mapper{} 1683 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1684 assert.NoError(t, err) 1685 validator := txvalidatorv14.NewTxValidator( 1686 "", 1687 semaphore.New(10), 1688 &mocktxvalidator.Support{LedgerVal: theLedger, ACVal: preV12Capabilities()}, 1689 pm, 1690 cryptoProvider, 1691 ) 1692 1693 ccID := "mycc" 1694 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1695 1696 theLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, ledger.NotFoundInIndexErr("")) 1697 1698 queryExecutor := new(mockQueryExecutor) 1699 queryExecutor.On("GetState", mock.Anything, mock.Anything).Return([]byte{}, errors.New("Unable to connect to DB")) 1700 theLedger.On("NewQueryExecutor", mock.Anything).Return(queryExecutor, nil) 1701 1702 b := &common.Block{ 1703 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1704 Header: &common.BlockHeader{}, 1705 } 1706 1707 err = validator.Validate(b) 1708 1709 assertion := assert.New(t) 1710 // We suppose to get the error which indicates we cannot commit the block 1711 assertion.Error(err) 1712 // The error exptected to be of type VSCCInfoLookupFailureError 1713 assertion.NotNil(err.(*commonerrors.VSCCInfoLookupFailureError)) 1714 } 1715 1716 func TestLedgerIsNotAvailableForCheckingTxidDuplicate(t *testing.T) { 1717 theLedger := new(mockLedger) 1718 pm := &mocks.Mapper{} 1719 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1720 assert.NoError(t, err) 1721 validator := txvalidatorv14.NewTxValidator( 1722 "", 1723 semaphore.New(10), 1724 &mocktxvalidator.Support{LedgerVal: theLedger, ACVal: preV12Capabilities()}, 1725 pm, 1726 cryptoProvider, 1727 ) 1728 1729 ccID := "mycc" 1730 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1731 1732 theLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, errors.New("Unable to connect to DB")) 1733 1734 b := &common.Block{ 1735 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1736 Header: &common.BlockHeader{}, 1737 } 1738 1739 err = validator.Validate(b) 1740 1741 assertion := assert.New(t) 1742 // We expect a validation error because the ledger wasn't ready to tell us whether there was a tx with that ID or not 1743 assertion.Error(err) 1744 } 1745 1746 func TestDuplicateTxId(t *testing.T) { 1747 theLedger := new(mockLedger) 1748 pm := &mocks.Mapper{} 1749 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1750 assert.NoError(t, err) 1751 validator := txvalidatorv14.NewTxValidator( 1752 "", 1753 semaphore.New(10), 1754 &mocktxvalidator.Support{LedgerVal: theLedger, ACVal: preV12Capabilities()}, 1755 pm, 1756 cryptoProvider, 1757 ) 1758 1759 ccID := "mycc" 1760 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1761 1762 theLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, nil) 1763 1764 b := &common.Block{ 1765 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1766 Header: &common.BlockHeader{}, 1767 } 1768 1769 err = validator.Validate(b) 1770 1771 assertion := assert.New(t) 1772 // We expect no validation error because we simply mark the tx as invalid 1773 assertion.NoError(err) 1774 1775 // We expect the tx to be invalid because of a duplicate txid 1776 txsfltr := lutils.TxValidationFlags(b.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 1777 assertion.True(txsfltr.IsInvalid(0)) 1778 assertion.True(txsfltr.Flag(0) == peer.TxValidationCode_DUPLICATE_TXID) 1779 } 1780 1781 func TestValidationInvalidEndorsing(t *testing.T) { 1782 theLedger := new(mockLedger) 1783 pm := &mocks.Mapper{} 1784 factory := &mocks.PluginFactory{} 1785 plugin := &mocks.Plugin{} 1786 factory.On("New").Return(plugin) 1787 plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) 1788 plugin.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("invalid tx")) 1789 pm.On("FactoryByName", vp.Name("vscc")).Return(factory) 1790 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1791 assert.NoError(t, err) 1792 validator := txvalidatorv14.NewTxValidator( 1793 "", 1794 semaphore.New(10), 1795 &mocktxvalidator.Support{LedgerVal: theLedger, ACVal: preV12Capabilities()}, 1796 pm, 1797 cryptoProvider, 1798 ) 1799 1800 ccID := "mycc" 1801 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1802 1803 theLedger.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, ledger.NotFoundInIndexErr("")) 1804 1805 cd := &ccp.ChaincodeData{ 1806 Name: ccID, 1807 Version: ccVersion, 1808 Vscc: "vscc", 1809 Policy: signedByAnyMember([]string{"SampleOrg"}), 1810 } 1811 1812 cdbytes := protoutil.MarshalOrPanic(cd) 1813 1814 queryExecutor := new(mockQueryExecutor) 1815 queryExecutor.On("GetState", "lscc", ccID).Return(cdbytes, nil) 1816 theLedger.On("NewQueryExecutor", mock.Anything).Return(queryExecutor, nil) 1817 1818 b := &common.Block{ 1819 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1820 Header: &common.BlockHeader{}, 1821 } 1822 1823 // Keep default callback 1824 err = validator.Validate(b) 1825 // Restore default callback 1826 assert.NoError(t, err) 1827 assertInvalid(b, t, peer.TxValidationCode_ENDORSEMENT_POLICY_FAILURE) 1828 } 1829 1830 func createMockLedger(t *testing.T, ccID string) *mockLedger { 1831 l := new(mockLedger) 1832 l.On("GetTransactionByID", mock.Anything).Return(&peer.ProcessedTransaction{}, ledger.NotFoundInIndexErr("")) 1833 cd := &ccp.ChaincodeData{ 1834 Name: ccID, 1835 Version: ccVersion, 1836 Vscc: "vscc", 1837 Policy: signedByAnyMember([]string{"SampleOrg"}), 1838 } 1839 1840 cdbytes := protoutil.MarshalOrPanic(cd) 1841 queryExecutor := new(mockQueryExecutor) 1842 queryExecutor.On("GetState", "lscc", ccID).Return(cdbytes, nil) 1843 l.On("NewQueryExecutor", mock.Anything).Return(queryExecutor, nil) 1844 return l 1845 } 1846 1847 func TestValidationPluginExecutionError(t *testing.T) { 1848 plugin := &mocks.Plugin{} 1849 plugin.On("Init", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) 1850 1851 l, v, cleanup := setupLedgerAndValidatorExplicit(t, preV12Capabilities(), plugin) 1852 defer cleanup() 1853 1854 ccID := "mycc" 1855 putCCInfo(l, ccID, signedByAnyMember([]string{"SampleOrg"}), t) 1856 1857 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1858 b := &common.Block{ 1859 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1860 Header: &common.BlockHeader{}, 1861 } 1862 1863 plugin.On("Validate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&validation.ExecutionFailureError{ 1864 Reason: "I/O error", 1865 }) 1866 1867 err := v.Validate(b) 1868 executionErr := err.(*commonerrors.VSCCExecutionFailureError) 1869 assert.Contains(t, executionErr.Error(), "I/O error") 1870 } 1871 1872 func TestValidationPluginNotFound(t *testing.T) { 1873 ccID := "mycc" 1874 tx := getEnv(ccID, nil, createRWset(t, ccID), t) 1875 l := createMockLedger(t, ccID) 1876 1877 b := &common.Block{ 1878 Data: &common.BlockData{Data: [][]byte{protoutil.MarshalOrPanic(tx)}}, 1879 Header: &common.BlockHeader{}, 1880 } 1881 1882 pm := &mocks.Mapper{} 1883 pm.On("FactoryByName", vp.Name("vscc")).Return(nil) 1884 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1885 assert.NoError(t, err) 1886 validator := txvalidatorv14.NewTxValidator( 1887 "", 1888 semaphore.New(10), 1889 &mocktxvalidator.Support{LedgerVal: l, ACVal: preV12Capabilities()}, 1890 pm, 1891 cryptoProvider, 1892 ) 1893 err = validator.Validate(b) 1894 executionErr := err.(*commonerrors.VSCCExecutionFailureError) 1895 assert.Contains(t, executionErr.Error(), "plugin with name vscc wasn't found") 1896 } 1897 1898 var signer msp.SigningIdentity 1899 1900 var signerSerialized []byte 1901 1902 func TestMain(m *testing.M) { 1903 msptesttools.LoadMSPSetupForTesting() 1904 1905 var err error 1906 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 1907 if err != nil { 1908 fmt.Printf("Initialize cryptoProvider bccsp failed: %s", err) 1909 os.Exit(-1) 1910 return 1911 } 1912 1913 signer, err = mgmt.GetLocalMSP(cryptoProvider).GetDefaultSigningIdentity() 1914 if err != nil { 1915 fmt.Println("Could not get signer") 1916 os.Exit(-1) 1917 return 1918 } 1919 1920 signerSerialized, err = signer.Serialize() 1921 if err != nil { 1922 fmt.Println("Could not serialize identity") 1923 os.Exit(-1) 1924 return 1925 } 1926 1927 os.Exit(m.Run()) 1928 } 1929 1930 func ToHex(q uint64) string { 1931 return "0x" + strconv.FormatUint(q, 16) 1932 } 1933 1934 func constructLedgerMgrWithTestDefaults(t *testing.T, testDir string) (*ledgermgmt.LedgerMgr, func()) { 1935 testDir, err := ioutil.TempDir("", testDir) 1936 if err != nil { 1937 t.Fatalf("Failed to create ledger directory: %s", err) 1938 } 1939 initializer := ledgermgmttest.NewInitializer(testDir) 1940 ledgerMgr := ledgermgmt.NewLedgerMgr(initializer) 1941 cleanup := func() { 1942 ledgerMgr.Close() 1943 os.RemoveAll(testDir) 1944 } 1945 return ledgerMgr, cleanup 1946 }