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