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