github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/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/osdi23p228/fabric/bccsp/sw" 23 configtxtest "github.com/osdi23p228/fabric/common/configtx/test" 24 "github.com/osdi23p228/fabric/common/genesis" 25 "github.com/osdi23p228/fabric/common/metrics/disabled" 26 "github.com/osdi23p228/fabric/common/policies" 27 "github.com/osdi23p228/fabric/core/aclmgmt" 28 "github.com/osdi23p228/fabric/core/chaincode" 29 "github.com/osdi23p228/fabric/core/config/configtest" 30 "github.com/osdi23p228/fabric/core/deliverservice" 31 "github.com/osdi23p228/fabric/core/ledger" 32 "github.com/osdi23p228/fabric/core/ledger/ledgermgmt" 33 "github.com/osdi23p228/fabric/core/ledger/ledgermgmt/ledgermgmttest" 34 "github.com/osdi23p228/fabric/core/peer" 35 "github.com/osdi23p228/fabric/core/policy" 36 "github.com/osdi23p228/fabric/core/scc/cscc/mocks" 37 "github.com/osdi23p228/fabric/core/transientstore" 38 "github.com/osdi23p228/fabric/gossip/gossip" 39 gossipmetrics "github.com/osdi23p228/fabric/gossip/metrics" 40 "github.com/osdi23p228/fabric/gossip/privdata" 41 "github.com/osdi23p228/fabric/gossip/service" 42 "github.com/osdi23p228/fabric/internal/configtxgen/encoder" 43 "github.com/osdi23p228/fabric/internal/configtxgen/genesisconfig" 44 peergossip "github.com/osdi23p228/fabric/internal/peer/gossip" 45 "github.com/osdi23p228/fabric/internal/pkg/comm" 46 "github.com/osdi23p228/fabric/msp/mgmt" 47 msptesttools "github.com/osdi23p228/fabric/msp/mgmt/testtools" 48 "github.com/osdi23p228/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("testChannelID")} 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("testChannelID")} 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("testChannelID")} 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("testChannelID")} 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][testChannelID]: 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 return []grpc.DialOption{grpc.WithInsecure()} 285 } 286 var defaultDeliverClientDialOpts []grpc.DialOption 287 defaultDeliverClientDialOpts = append( 288 defaultDeliverClientDialOpts, 289 grpc.WithBlock(), 290 grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(comm.MaxRecvMsgSize), grpc.MaxCallSendMsgSize(comm.MaxSendMsgSize)), 291 ) 292 defaultDeliverClientDialOpts = append( 293 defaultDeliverClientDialOpts, 294 comm.ClientKeepaliveOptions(comm.DefaultKeepaliveOptions)..., 295 ) 296 gossipConfig, err := gossip.GlobalConfig(peerEndpoint, nil) 297 assert.NoError(t, err) 298 299 gossipService, err := service.New( 300 signer, 301 gossipmetrics.NewGossipMetrics(&disabled.Provider{}), 302 peerEndpoint, 303 grpcServer, 304 messageCryptoService, 305 secAdv, 306 defaultSecureDialOpts, 307 nil, 308 nil, 309 gossipConfig, 310 &service.ServiceConfig{}, 311 &privdata.PrivdataConfig{}, 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][mytestchannelid]") 386 sProp.Signature = sProp.ProposalBytes 387 388 // Query the configuration block 389 //channelID := []byte{143, 222, 22, 192, 73, 145, 76, 110, 167, 154, 118, 66, 132, 204, 113, 168} 390 channelID, err := protoutil.GetChannelIDFromBlockBytes(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(channelID)} 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("mytestchannelid") 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("mytestchannelid") 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 }