github.com/lzy4123/fabric@v2.1.1+incompatible/core/scc/cscc/configure_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package cscc 8 9 import ( 10 "errors" 11 "io/ioutil" 12 "net" 13 "os" 14 "testing" 15 "time" 16 17 "github.com/golang/protobuf/proto" 18 "github.com/hyperledger/fabric-chaincode-go/shim" 19 "github.com/hyperledger/fabric-protos-go/common" 20 cb "github.com/hyperledger/fabric-protos-go/common" 21 pb "github.com/hyperledger/fabric-protos-go/peer" 22 "github.com/hyperledger/fabric/bccsp/sw" 23 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 24 "github.com/hyperledger/fabric/common/genesis" 25 "github.com/hyperledger/fabric/common/metrics/disabled" 26 "github.com/hyperledger/fabric/common/policies" 27 "github.com/hyperledger/fabric/core/aclmgmt" 28 "github.com/hyperledger/fabric/core/chaincode" 29 "github.com/hyperledger/fabric/core/config/configtest" 30 "github.com/hyperledger/fabric/core/deliverservice" 31 "github.com/hyperledger/fabric/core/ledger" 32 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 33 "github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledgermgmttest" 34 "github.com/hyperledger/fabric/core/peer" 35 "github.com/hyperledger/fabric/core/policy" 36 "github.com/hyperledger/fabric/core/scc/cscc/mocks" 37 "github.com/hyperledger/fabric/core/transientstore" 38 "github.com/hyperledger/fabric/gossip/gossip" 39 gossipmetrics "github.com/hyperledger/fabric/gossip/metrics" 40 "github.com/hyperledger/fabric/gossip/privdata" 41 "github.com/hyperledger/fabric/gossip/service" 42 "github.com/hyperledger/fabric/internal/configtxgen/encoder" 43 "github.com/hyperledger/fabric/internal/configtxgen/genesisconfig" 44 peergossip "github.com/hyperledger/fabric/internal/peer/gossip" 45 "github.com/hyperledger/fabric/internal/pkg/comm" 46 "github.com/hyperledger/fabric/msp/mgmt" 47 msptesttools "github.com/hyperledger/fabric/msp/mgmt/testtools" 48 "github.com/hyperledger/fabric/protoutil" 49 "github.com/spf13/viper" 50 "github.com/stretchr/testify/assert" 51 "github.com/stretchr/testify/require" 52 "google.golang.org/grpc" 53 ) 54 55 //go:generate counterfeiter -o mocks/acl_provider.go --fake-name ACLProvider . aclProvider 56 57 type aclProvider interface { 58 aclmgmt.ACLProvider 59 } 60 61 //go:generate counterfeiter -o mocks/chaincode_stub.go --fake-name ChaincodeStub . chaincodeStub 62 63 type chaincodeStub interface { 64 shim.ChaincodeStubInterface 65 } 66 67 //go:generate counterfeiter -o mocks/channel_policy_manager_getter.go --fake-name ChannelPolicyManagerGetter . channelPolicyManagerGetter 68 69 type channelPolicyManagerGetter interface { 70 policies.ChannelPolicyManagerGetter 71 } 72 73 //go:generate counterfeiter -o mocks/policy_checker.go --fake-name PolicyChecker . policyChecker 74 75 type policyChecker interface { 76 policy.PolicyChecker 77 } 78 79 //go:generate counterfeiter -o mocks/store_provider.go --fake-name StoreProvider . storeProvider 80 81 type storeProvider interface { 82 transientstore.StoreProvider 83 } 84 85 func TestMain(m *testing.M) { 86 msptesttools.LoadMSPSetupForTesting() 87 rc := m.Run() 88 os.Exit(rc) 89 90 } 91 92 func TestConfigerInit(t *testing.T) { 93 mockACLProvider := &mocks.ACLProvider{} 94 mockStub := &mocks.ChaincodeStub{} 95 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 96 assert.NoError(t, err) 97 cscc := &PeerConfiger{ 98 aclProvider: mockACLProvider, 99 bccsp: cryptoProvider, 100 } 101 res := cscc.Init(mockStub) 102 assert.Equal(t, int32(shim.OK), res.Status) 103 } 104 105 func TestConfigerInvokeInvalidParameters(t *testing.T) { 106 mockACLProvider := &mocks.ACLProvider{} 107 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 108 assert.NoError(t, err) 109 cscc := &PeerConfiger{ 110 aclProvider: mockACLProvider, 111 bccsp: cryptoProvider, 112 } 113 mockStub := &mocks.ChaincodeStub{} 114 115 mockStub.GetArgsReturns(nil) 116 mockStub.GetSignedProposalReturns(validSignedProposal(), nil) 117 res := cscc.Invoke(mockStub) 118 assert.NotEqual( 119 t, 120 int32(shim.OK), 121 res.Status, 122 "cscc invoke expected to fail having zero arguments", 123 ) 124 assert.Equal(t, "Incorrect number of arguments, 0", res.Message) 125 126 mockACLProvider.CheckACLReturns(errors.New("Failed authorization")) 127 args := [][]byte{[]byte("GetChannels")} 128 mockStub.GetArgsReturns(args) 129 res = cscc.Invoke(mockStub) 130 assert.NotEqual( 131 t, 132 int32(shim.OK), 133 res.Status, 134 "invoke expected to fail no signed proposal provided", 135 ) 136 assert.Equal(t, "access denied for [GetChannels]: Failed authorization", res.Message) 137 138 mockACLProvider.CheckACLReturns(nil) 139 args = [][]byte{[]byte("fooFunction"), []byte("testChainID")} 140 mockStub.GetArgsReturns(args) 141 res = cscc.Invoke(mockStub) 142 assert.NotEqual( 143 t, 144 int32(shim.OK), 145 res.Status, 146 "invoke invoke expected wrong function name provided", 147 ) 148 assert.Equal(t, "Requested function fooFunction not found.", res.Message) 149 150 mockACLProvider.CheckACLReturns(nil) 151 args = [][]byte{[]byte("GetConfigBlock"), []byte("testChainID")} 152 mockStub.GetArgsReturns(args) 153 mockStub.GetSignedProposalReturns(&pb.SignedProposal{ 154 ProposalBytes: []byte("garbage"), 155 }, nil) 156 res = cscc.Invoke(mockStub) 157 assert.NotEqual( 158 t, 159 int32(shim.OK), 160 res.Status, 161 "invoke expected to fail in ccc2cc context", 162 ) 163 assert.Equal( 164 t, 165 "Failed to identify the called chaincode: could not unmarshal proposal: proto: can't skip unknown wire type 7", 166 res.Message, 167 ) 168 169 mockACLProvider.CheckACLReturns(nil) 170 args = [][]byte{[]byte("GetConfigBlock"), []byte("testChainID")} 171 mockStub.GetArgsReturns(args) 172 mockStub.GetSignedProposalReturns(&pb.SignedProposal{ 173 ProposalBytes: protoutil.MarshalOrPanic(&pb.Proposal{ 174 Payload: protoutil.MarshalOrPanic(&pb.ChaincodeProposalPayload{ 175 Input: protoutil.MarshalOrPanic(&pb.ChaincodeInvocationSpec{ 176 ChaincodeSpec: &pb.ChaincodeSpec{ 177 ChaincodeId: &pb.ChaincodeID{ 178 Name: "fake-cc2cc", 179 }, 180 }, 181 }), 182 }), 183 }), 184 }, nil) 185 res = cscc.Invoke(mockStub) 186 assert.NotEqual( 187 t, 188 int32(shim.OK), 189 res.Status, 190 "invoke expected to fail in ccc2cc context", 191 ) 192 assert.Equal( 193 t, 194 "Rejecting invoke of CSCC from another chaincode, original invocation for 'fake-cc2cc'", 195 res.Message, 196 ) 197 198 mockACLProvider.CheckACLReturns(errors.New("Failed authorization")) 199 mockStub.GetSignedProposalReturns(validSignedProposal(), nil) 200 args = [][]byte{[]byte("GetConfigBlock"), []byte("testChainID")} 201 mockStub.GetArgsReturns(args) 202 res = cscc.Invoke(mockStub) 203 assert.NotEqual( 204 t, 205 int32(shim.OK), 206 res.Status, 207 "invoke expected to fail no signed proposal provided", 208 ) 209 assert.Equal( 210 t, 211 "access denied for [GetConfigBlock][testChainID]: Failed authorization", 212 res.Message, 213 ) 214 } 215 216 func TestConfigerInvokeJoinChainMissingParams(t *testing.T) { 217 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 218 assert.NoError(t, err) 219 cscc := &PeerConfiger{ 220 aclProvider: &mocks.ACLProvider{}, 221 bccsp: cryptoProvider, 222 } 223 mockStub := &mocks.ChaincodeStub{} 224 mockStub.GetArgsReturns([][]byte{[]byte("JoinChain")}) 225 res := cscc.Invoke(mockStub) 226 assert.NotEqual( 227 t, 228 int32(shim.OK), 229 res.Status, 230 "cscc invoke JoinChain should have failed with invalid number of args", 231 ) 232 } 233 234 func TestConfigerInvokeJoinChainWrongParams(t *testing.T) { 235 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 236 assert.NoError(t, err) 237 cscc := &PeerConfiger{ 238 aclProvider: &mocks.ACLProvider{}, 239 bccsp: cryptoProvider, 240 } 241 mockStub := &mocks.ChaincodeStub{} 242 mockStub.GetArgsReturns([][]byte{[]byte("JoinChain"), []byte("action")}) 243 mockStub.GetSignedProposalReturns(validSignedProposal(), nil) 244 res := cscc.Invoke(mockStub) 245 assert.NotEqual( 246 t, 247 int32(shim.OK), 248 res.Status, 249 "cscc invoke JoinChain should have failed with null genesis block", 250 ) 251 } 252 253 func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { 254 viper.Set("chaincode.executetimeout", "3s") 255 256 testDir, err := ioutil.TempDir("", "cscc_test") 257 require.NoError(t, err, "error in creating test dir") 258 defer os.RemoveAll(testDir) 259 260 ledgerInitializer := ledgermgmttest.NewInitializer(testDir) 261 ledgerInitializer.CustomTxProcessors = map[common.HeaderType]ledger.CustomTxProcessor{ 262 common.HeaderType_CONFIG: &peer.ConfigTxProcessor{}, 263 } 264 ledgerMgr := ledgermgmt.NewLedgerMgr(ledgerInitializer) 265 defer ledgerMgr.Close() 266 267 peerEndpoint := "127.0.0.1:13611" 268 269 config := chaincode.GlobalConfig() 270 config.StartupTimeout = 30 * time.Second 271 272 grpcServer := grpc.NewServer() 273 socket, err := net.Listen("tcp", peerEndpoint) 274 require.NoError(t, err) 275 276 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 277 assert.NoError(t, err) 278 279 signer := mgmt.GetLocalSigningIdentityOrPanic(cryptoProvider) 280 281 messageCryptoService := peergossip.NewMCS(&mocks.ChannelPolicyManagerGetter{}, signer, mgmt.NewDeserializersManager(cryptoProvider), cryptoProvider) 282 secAdv := peergossip.NewSecurityAdvisor(mgmt.NewDeserializersManager(cryptoProvider)) 283 var defaultSecureDialOpts = func() []grpc.DialOption { 284 var dialOpts []grpc.DialOption 285 dialOpts = append(dialOpts, grpc.WithInsecure()) 286 return dialOpts 287 } 288 defaultDeliverClientDialOpts := []grpc.DialOption{grpc.WithBlock()} 289 defaultDeliverClientDialOpts = append( 290 defaultDeliverClientDialOpts, 291 grpc.WithDefaultCallOptions( 292 grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize), 293 grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize))) 294 defaultDeliverClientDialOpts = append( 295 defaultDeliverClientDialOpts, 296 comm.ClientKeepaliveOptions(comm.DefaultKeepaliveOptions)..., 297 ) 298 gossipConfig, err := gossip.GlobalConfig(peerEndpoint, nil) 299 assert.NoError(t, err) 300 301 gossipService, err := service.New( 302 signer, 303 gossipmetrics.NewGossipMetrics(&disabled.Provider{}), 304 peerEndpoint, 305 grpcServer, 306 messageCryptoService, 307 secAdv, 308 defaultSecureDialOpts, 309 nil, 310 nil, 311 gossipConfig, 312 &service.ServiceConfig{}, 313 &privdata.PrivdataConfig{}, 314 &deliverservice.DeliverServiceConfig{ 315 ReConnectBackoffThreshold: deliverservice.DefaultReConnectBackoffThreshold, 316 ReconnectTotalTimeThreshold: deliverservice.DefaultReConnectTotalTimeThreshold, 317 }, 318 ) 319 assert.NoError(t, err) 320 321 go grpcServer.Serve(socket) 322 defer grpcServer.Stop() 323 324 assert.NoError(t, err) 325 326 // setup cscc instance 327 mockACLProvider := &mocks.ACLProvider{} 328 cscc := &PeerConfiger{ 329 policyChecker: &mocks.PolicyChecker{}, 330 aclProvider: mockACLProvider, 331 peer: &peer.Peer{ 332 StoreProvider: &mocks.StoreProvider{}, 333 GossipService: gossipService, 334 LedgerMgr: ledgerMgr, 335 CryptoProvider: cryptoProvider, 336 }, 337 bccsp: cryptoProvider, 338 } 339 mockStub := &mocks.ChaincodeStub{} 340 341 // Successful path for JoinChain 342 blockBytes := mockConfigBlock() 343 if blockBytes == nil { 344 t.Fatalf("cscc invoke JoinChain failed because invalid block") 345 } 346 args := [][]byte{[]byte("JoinChain"), blockBytes} 347 sProp := validSignedProposal() 348 sProp.Signature = sProp.ProposalBytes 349 350 // Try fail path with nil block 351 mockStub.GetArgsReturns([][]byte{[]byte("JoinChain"), nil}) 352 mockStub.GetSignedProposalReturns(sProp, nil) 353 res := cscc.Invoke(mockStub) 354 //res := stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), nil}, sProp) 355 assert.Equal(t, int32(shim.ERROR), res.Status) 356 357 // Try fail path with block and nil payload header 358 payload, _ := proto.Marshal(&cb.Payload{}) 359 env, _ := proto.Marshal(&cb.Envelope{ 360 Payload: payload, 361 }) 362 badBlock := &cb.Block{ 363 Data: &cb.BlockData{ 364 Data: [][]byte{env}, 365 }, 366 } 367 badBlockBytes := protoutil.MarshalOrPanic(badBlock) 368 mockStub.GetArgsReturns([][]byte{[]byte("JoinChain"), badBlockBytes}) 369 res = cscc.Invoke(mockStub) 370 //res = stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), badBlockBytes}, sProp) 371 assert.Equal(t, int32(shim.ERROR), res.Status) 372 373 // Now, continue with valid execution path 374 mockStub.GetArgsReturns(args) 375 mockStub.GetSignedProposalReturns(sProp, nil) 376 res = cscc.Invoke(mockStub) 377 assert.Equal(t, int32(shim.OK), res.Status, "invoke JoinChain failed with: %v", res.Message) 378 379 // This call must fail 380 sProp.Signature = nil 381 mockACLProvider.CheckACLReturns(errors.New("Failed authorization")) 382 mockStub.GetArgsReturns(args) 383 mockStub.GetSignedProposalReturns(sProp, nil) 384 385 res = cscc.Invoke(mockStub) 386 assert.Equal(t, int32(shim.ERROR), res.Status) 387 assert.Contains(t, res.Message, "access denied for [JoinChain][mytestchainid]") 388 sProp.Signature = sProp.ProposalBytes 389 390 // Query the configuration block 391 //chainID := []byte{143, 222, 22, 192, 73, 145, 76, 110, 167, 154, 118, 66, 132, 204, 113, 168} 392 chainID, err := protoutil.GetChainIDFromBlockBytes(blockBytes) 393 if err != nil { 394 t.Fatalf("cscc invoke JoinChain failed with: %v", err) 395 } 396 397 // Test an ACL failure on GetConfigBlock 398 mockACLProvider.CheckACLReturns(errors.New("Failed authorization")) 399 args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)} 400 mockStub.GetArgsReturns(args) 401 mockStub.GetSignedProposalReturns(sProp, nil) 402 res = cscc.Invoke(mockStub) 403 assert.Equal(t, int32(shim.ERROR), res.Status, "invoke GetConfigBlock should have failed: %v", res.Message) 404 assert.Contains(t, res.Message, "Failed authorization") 405 406 // Test with ACL okay 407 mockACLProvider.CheckACLReturns(nil) 408 res = cscc.Invoke(mockStub) 409 assert.Equal(t, int32(shim.OK), res.Status, "invoke GetConfigBlock failed with: %v", res.Message) 410 411 // get channels for the peer 412 mockACLProvider.CheckACLReturns(nil) 413 args = [][]byte{[]byte(GetChannels)} 414 mockStub.GetArgsReturns(args) 415 res = cscc.Invoke(mockStub) 416 if res.Status != shim.OK { 417 t.FailNow() 418 } 419 420 cqr := &pb.ChannelQueryResponse{} 421 err = proto.Unmarshal(res.Payload, cqr) 422 if err != nil { 423 t.FailNow() 424 } 425 426 // peer joined one channel so query should return an array with one channel 427 if len(cqr.GetChannels()) != 1 { 428 t.FailNow() 429 } 430 } 431 432 func TestPeerConfiger_SubmittingOrdererGenesis(t *testing.T) { 433 conf := genesisconfig.Load(genesisconfig.SampleSingleMSPSoloProfile, configtest.GetDevConfigDir()) 434 conf.Application = nil 435 cg, err := encoder.NewChannelGroup(conf) 436 assert.NoError(t, err) 437 block := genesis.NewFactoryImpl(cg).Block("mytestchainid") 438 blockBytes := protoutil.MarshalOrPanic(block) 439 440 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 441 assert.NoError(t, err) 442 mockACLProvider := &mocks.ACLProvider{} 443 cscc := &PeerConfiger{ 444 aclProvider: mockACLProvider, 445 bccsp: cryptoProvider, 446 } 447 mockStub := &mocks.ChaincodeStub{} 448 // Failed path: wrong parameter type 449 args := [][]byte{[]byte("JoinChain"), []byte(blockBytes)} 450 mockStub.GetArgsReturns(args) 451 mockStub.GetSignedProposalReturns(validSignedProposal(), nil) 452 res := cscc.Invoke(mockStub) 453 454 assert.NotEqual( 455 t, 456 int32(shim.OK), 457 res.Status, 458 "invoke JoinChain should have failed with wrong genesis block", 459 ) 460 assert.Contains(t, res.Message, "missing Application configuration group") 461 } 462 463 func mockConfigBlock() []byte { 464 var blockBytes []byte = nil 465 block, err := configtxtest.MakeGenesisBlock("mytestchainid") 466 if err == nil { 467 blockBytes = protoutil.MarshalOrPanic(block) 468 } 469 return blockBytes 470 } 471 472 func validSignedProposal() *pb.SignedProposal { 473 return &pb.SignedProposal{ 474 ProposalBytes: protoutil.MarshalOrPanic(&pb.Proposal{ 475 Payload: protoutil.MarshalOrPanic(&pb.ChaincodeProposalPayload{ 476 Input: protoutil.MarshalOrPanic(&pb.ChaincodeInvocationSpec{ 477 ChaincodeSpec: &pb.ChaincodeSpec{ 478 ChaincodeId: &pb.ChaincodeID{ 479 Name: "cscc", 480 }, 481 }, 482 }), 483 }), 484 }), 485 } 486 }