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