diff --git a/Makefile b/Makefile index 0c1d2e1576..a887e1c2e5 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ THIRDPARTY_FABRIC_COMMIT ?= v1.1.0-alpha FIXTURE_DOCKER_REMOVE_FORCE ?= false # Options for exercising unit tests (overridable) -FABRIC_DEPRECATED_UNITTEST ?= false +FABRIC_SDK_DEPRECATED_UNITTEST ?= false # Code levels to exercise integration/e2e tests against (overridable) FABRIC_STABLE_INTTEST ?= true @@ -132,12 +132,12 @@ GO_DEP_COMMIT := v0.4.1 ifdef JENKINS_URL export FABRIC_SDKGO_DEPEND_INSTALL=true -FABRIC_DEPRECATED_UNITTEST := true -FABRIC_STABLE_INTTEST := true -FABRIC_STABLE_PKCS11_INTTEST := true -FABRIC_PREV_INTTEST := true -FABRIC_PRERELEASE_INTTEST := true -FABRIC_DEVSTABLE_INTTEST := false +FABRIC_SDK_DEPRECATED_UNITTEST := true +FABRIC_STABLE_INTTEST := true +FABRIC_STABLE_PKCS11_INTTEST := true +FABRIC_PREV_INTTEST := true +FABRIC_PRERELEASE_INTTEST := true +FABRIC_DEVSTABLE_INTTEST := false endif # Setup Go Tags @@ -206,7 +206,7 @@ build-softhsm2-image: .PHONY: unit-test unit-test: checks depend populate @FABRIC_SDKGO_CODELEVEL=$(FABRIC_CODELEVEL_UNITTEST_TAG) FABRIC_SDKGO_CODELEVEL_VER=$(FABRIC_CODELEVEL_UNITTEST_VER) $(TEST_SCRIPTS_PATH)/unit.sh -ifeq ($(FABRIC_DEPRECATED_UNITTEST),true) +ifeq ($(FABRIC_SDK_DEPRECATED_UNITTEST),true) @GO_TAGS="$(GO_TAGS) deprecated" GO_TESTFLAGS="$(GO_TESTFLAGS) -count=1" FABRIC_SDKGO_CODELEVEL=$(FABRIC_CODELEVEL_UNITTEST_TAG) FABRIC_SDKGO_CODELEVEL_VER=$(FABRIC_CODELEVEL_UNITTEST_VER) $(TEST_SCRIPTS_PATH)/unit.sh endif @@ -325,7 +325,7 @@ dockerenv-latest-up: clean mock-gen: mockgen -build_flags '$(GO_LDFLAGS_ARG)' github.com/hyperledger/fabric-sdk-go/pkg/context/api IdentityManager | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" | goimports > pkg/context/api/mocks/mockidmgr.gen.go mockgen -build_flags '$(GO_LDFLAGS_ARG)' github.com/hyperledger/fabric-sdk-go/pkg/context/api/core Config | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" | goimports > pkg/context/api/core/mocks/mockconfig.gen.go - mockgen -build_flags '$(GO_LDFLAGS_ARG)' github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab ProposalProcessor | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" | goimports > pkg/context/api/fab/mocks/mockcontextapi.gen.go + mockgen -build_flags '$(GO_LDFLAGS_ARG)' github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab ProposalProcessor | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" | goimports > pkg/context/api/fab/mocks/mockcontextapi.gen.go mockgen -build_flags '$(GO_LDFLAGS_ARG)' github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api CoreProviders,SvcProviders,Providers,CoreProviderFactory,ServiceProviderFactory,SessionClientFactory | sed "s/github.com\/hyperledger\/fabric-sdk-go\/vendor\///g" | goimports > pkg/fabsdk/mocks/mockfabsdkapi.gen.go @@ -403,4 +403,3 @@ temp-clean: clean: temp-clean -$(GO_CMD) clean -FIXTURE_PROJECT_NAME=$(FIXTURE_PROJECT_NAME) DOCKER_REMOVE_FORCE=$(FIXTURE_DOCKER_REMOVE_FORCE) $(TEST_SCRIPTS_PATH)/clean_integration.sh - diff --git a/pkg/fab/channel/lscc.go b/pkg/client/resmgmt/lscc.go similarity index 81% rename from pkg/fab/channel/lscc.go rename to pkg/client/resmgmt/lscc.go index c0d74c0984..59c0ac8437 100644 --- a/pkg/fab/channel/lscc.go +++ b/pkg/client/resmgmt/lscc.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package channel +package resmgmt import ( "github.com/golang/protobuf/proto" @@ -26,17 +26,17 @@ const ( vscc = "vscc" ) -// ChaincodeProposalType reflects transitions in the chaincode lifecycle -type ChaincodeProposalType int +// chaincodeProposalType reflects transitions in the chaincode lifecycle +type chaincodeProposalType int // Define chaincode proposal types const ( - InstantiateChaincode ChaincodeProposalType = iota + InstantiateChaincode chaincodeProposalType = iota UpgradeChaincode ) -// ChaincodeDeployRequest holds parameters for creating an instantiate or upgrade chaincode proposal. -type ChaincodeDeployRequest struct { +// chaincodeDeployRequest holds parameters for creating an instantiate or upgrade chaincode proposal. +type chaincodeDeployRequest struct { Name string Path string Version string @@ -45,8 +45,8 @@ type ChaincodeDeployRequest struct { CollConfig []*common.CollectionConfig } -// CreateChaincodeDeployProposal creates an instantiate or upgrade chaincode proposal. -func CreateChaincodeDeployProposal(txh fab.TransactionHeader, deploy ChaincodeProposalType, channelID string, chaincode ChaincodeDeployRequest) (*fab.TransactionProposal, error) { +// createChaincodeDeployProposal creates an instantiate or upgrade chaincode proposal. +func createChaincodeDeployProposal(txh fab.TransactionHeader, deploy chaincodeProposalType, channelID string, chaincode chaincodeDeployRequest) (*fab.TransactionProposal, error) { // Generate arguments for deploy (channel, marshaled CCDS, marshaled chaincode policy, marshaled collection policy) args := [][]byte{} @@ -98,11 +98,3 @@ func CreateChaincodeDeployProposal(txh fab.TransactionHeader, deploy ChaincodePr return txn.CreateChaincodeInvokeProposal(txh, cir) } - -func createChaincodesInvokeRequest() fab.ChaincodeInvokeRequest { - cir := fab.ChaincodeInvokeRequest{ - ChaincodeID: lscc, - Fcn: lsccChaincodes, - } - return cir -} diff --git a/pkg/client/resmgmt/resmgmt.go b/pkg/client/resmgmt/resmgmt.go index 7e63327262..48085d913b 100644 --- a/pkg/client/resmgmt/resmgmt.go +++ b/pkg/client/resmgmt/resmgmt.go @@ -17,7 +17,6 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/context" "github.com/hyperledger/fabric-sdk-go/pkg/errors/multi" - "github.com/hyperledger/fabric-sdk-go/pkg/fab/channel" "github.com/hyperledger/fabric-sdk-go/pkg/fab/orderer" "github.com/hyperledger/fabric-sdk-go/pkg/fab/peer" "github.com/hyperledger/fabric-sdk-go/pkg/fab/resource" @@ -400,12 +399,12 @@ func checkRequiredInstallCCParams(req InstallCCRequest) error { // InstantiateCC instantiates chaincode using default settings func (rc *Client) InstantiateCC(channelID string, req InstantiateCCRequest, options ...RequestOption) error { - return rc.sendCCProposal(channel.InstantiateChaincode, channelID, req, options...) + return rc.sendCCProposal(InstantiateChaincode, channelID, req, options...) } // UpgradeCC upgrades chaincode with optional custom options (specific peers, filtered peers, timeout) func (rc *Client) UpgradeCC(channelID string, req UpgradeCCRequest, options ...RequestOption) error { - return rc.sendCCProposal(channel.UpgradeChaincode, channelID, InstantiateCCRequest(req), options...) + return rc.sendCCProposal(UpgradeChaincode, channelID, InstantiateCCRequest(req), options...) } // QueryInstalledChaincodes queries the installed chaincodes on a peer. @@ -421,7 +420,7 @@ func (rc *Client) QueryChannels(proposalProcessor fab.ProposalProcessor) (*pb.Ch } // sendCCProposal sends proposal for type Instantiate, Upgrade -func (rc *Client) sendCCProposal(ccProposalType channel.ChaincodeProposalType, channelID string, req InstantiateCCRequest, options ...RequestOption) error { +func (rc *Client) sendCCProposal(ccProposalType chaincodeProposalType, channelID string, req InstantiateCCRequest, options ...RequestOption) error { if err := checkRequiredCCProposalParams(channelID, req); err != nil { return err @@ -466,7 +465,7 @@ func (rc *Client) sendCCProposal(ccProposalType channel.ChaincodeProposalType, c } // create a transaction proposal for chaincode deployment - deployProposal := channel.ChaincodeDeployRequest(req) + deployProposal := chaincodeDeployRequest(req) deployCtx := fabContext{ ProviderContext: rc.provider, IdentityContext: rc.identity, @@ -476,7 +475,7 @@ func (rc *Client) sendCCProposal(ccProposalType channel.ChaincodeProposalType, c if err != nil { return errors.WithMessage(err, "create transaction ID failed") } - tp, err := channel.CreateChaincodeDeployProposal(txid, ccProposalType, channelID, deployProposal) + tp, err := createChaincodeDeployProposal(txid, ccProposalType, channelID, deployProposal) if err != nil { return errors.WithMessage(err, "creating chaincode deploy transaction proposal failed") } diff --git a/pkg/client/resmgmt/resmgmt_test.go b/pkg/client/resmgmt/resmgmt_test.go index 83a9f9ce62..beed2a6b89 100644 --- a/pkg/client/resmgmt/resmgmt_test.go +++ b/pkg/client/resmgmt/resmgmt_test.go @@ -27,7 +27,6 @@ import ( txnmocks "github.com/hyperledger/fabric-sdk-go/pkg/client/common/mocks" "github.com/hyperledger/fabric-sdk-go/pkg/core/config" - "github.com/hyperledger/fabric-sdk-go/pkg/fab/channel" fcmocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" ) @@ -67,23 +66,13 @@ func TestJoinChannel(t *testing.T) { orderer.(fcmocks.MockOrderer).EnqueueForSendDeliver(fcmocks.NewSimpleMockBlock()) rc := setupResMgmtClient(ctx, nil, t) - channel, err := channel.New(ctx, fcmocks.NewMockChannelCfg("mychannel")) - if err != nil { - t.Fatalf("Error setting up channel: %v", err) - } - err = channel.AddOrderer(orderer) - if err != nil { - t.Fatalf("Error adding orderer: %v", err) - } - rc.channelProvider.(*fcmocks.MockChannelProvider).SetChannel("mychannel", channel) - // Setup target peers var peers []fab.Peer peer1, _ := peer.New(fcmocks.NewMockConfig(), peer.WithURL("example.com")) peers = append(peers, peer1) // Test valid join channel request (success) - err = rc.JoinChannel("mychannel", WithTargets(peer1)) + err := rc.JoinChannel("mychannel", WithTargets(peer1)) if err != nil { t.Fatal(err) } @@ -109,23 +98,13 @@ func TestJoinChannelWithFilter(t *testing.T) { //the target filter ( client option) will be set rc := setupResMgmtClient(ctx, nil, t) - channel, err := channel.New(ctx, fcmocks.NewMockChannelCfg("mychannel")) - if err != nil { - t.Fatalf("Error setting up channel: %v", err) - } - err = channel.AddOrderer(orderer) - if err != nil { - t.Fatalf("Error adding orderer: %v", err) - } - rc.channelProvider.(*fcmocks.MockChannelProvider).SetChannel("mychannel", channel) - // Setup target peers var peers []fab.Peer peer1, _ := peer.New(fcmocks.NewMockConfig(), peer.WithURL("example.com")) peers = append(peers, peer1) // Test valid join channel request (success) - err = rc.JoinChannel("mychannel", WithTargets(peer1)) + err := rc.JoinChannel("mychannel", WithTargets(peer1)) if err != nil { t.Fatal(err) } @@ -1037,15 +1016,6 @@ func TestCCProposal(t *testing.T) { orderer := fcmocks.NewMockOrderer("", nil) rc := setupResMgmtClient(ctx, nil, t) - channel, err := channel.New(ctx, fcmocks.NewMockChannelCfg("mychannel")) - if err != nil { - t.Fatalf("Error setting up channel: %v", err) - } - err = channel.AddOrderer(orderer) - if err != nil { - t.Fatalf("Error adding orderer: %v", err) - } - rc.channelProvider.(*fcmocks.MockChannelProvider).SetChannel("mychannel", channel) transactor := txnmocks.MockTransactor{ Ctx: ctx, ChannelID: "mychannel", diff --git a/pkg/context/api/fab/channel.go b/pkg/context/api/fab/channel.go index aad9c58175..b5aa16270a 100644 --- a/pkg/context/api/fab/channel.go +++ b/pkg/context/api/fab/channel.go @@ -7,56 +7,11 @@ SPDX-License-Identifier: Apache-2.0 package fab import ( - "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" mspCfg "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/msp" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" ) -// Channel ... -/** - * Channel representing a Channel with which the client SDK interacts. - * - * The Channel object captures settings for a channel, which is created by - * the orderers to isolate transactions delivery to peers participating on channel. - * A channel must be initialized after it has been configured with the list of peers - * and orderers. The initialization sends a get configuration block request to the - * primary orderer to retrieve the configuration settings for this channel. - */ -type Channel interface { - Name() string - ChannelConfig() (*common.ConfigEnvelope, error) - - SendInstantiateProposal(chaincodeName string, args [][]byte, chaincodePath string, chaincodeVersion string, chaincodePolicy *common.SignaturePolicyEnvelope, - collConfig []*common.CollectionConfig, targets []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error) - SendUpgradeProposal(chaincodeName string, args [][]byte, chaincodePath string, chaincodeVersion string, chaincodePolicy *common.SignaturePolicyEnvelope, targets []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error) - - // Network - // Deprecated: getters/setters are deprecated from interface. - AddPeer(peer Peer) error - RemovePeer(peer Peer) - Peers() []Peer - AnchorPeers() []OrgAnchorPeer - SetPrimaryPeer(peer Peer) error - PrimaryPeer() Peer - AddOrderer(orderer Orderer) error - RemoveOrderer(orderer Orderer) - Orderers() []Orderer - SetMSPManager(mspManager msp.MSPManager) - MSPManager() msp.MSPManager - OrganizationUnits() ([]string, error) - - // Query - QueryInfo() (*common.BlockchainInfo, error) - QueryBlock(blockNumber int) (*common.Block, error) - QueryBlockByHash(blockHash []byte) (*common.Block, error) - QueryTransaction(transactionID TransactionID) (*pb.ProcessedTransaction, error) - QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error) - QueryByChaincode(request ChaincodeInvokeRequest) ([][]byte, error) - QueryBySystemChaincode(request ChaincodeInvokeRequest) ([][]byte, error) - QueryConfigBlock(targets []ProposalProcessor, minResponses int) (*common.ConfigEnvelope, error) -} - // ChannelLedger provides access to the underlying ledger for a channel. type ChannelLedger interface { QueryInfo(targets []ProposalProcessor) ([]*BlockchainInfoResponse, error) diff --git a/pkg/context/api/fab/deprecated.go b/pkg/context/api/fab/deprecated.go new file mode 100644 index 0000000000..b5f2ff5d12 --- /dev/null +++ b/pkg/context/api/fab/deprecated.go @@ -0,0 +1,59 @@ +// +build deprecated + +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package fab + +import ( + "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp" + "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" + pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" +) + +// Channel ... +/** + * Channel representing a Channel with which the client SDK interacts. + * + * The Channel object captures settings for a channel, which is created by + * the orderers to isolate transactions delivery to peers participating on channel. + * A channel must be initialized after it has been configured with the list of peers + * and orderers. The initialization sends a get configuration block request to the + * primary orderer to retrieve the configuration settings for this channel. + */ +type Channel interface { + Name() string + ChannelConfig() (*common.ConfigEnvelope, error) + + SendInstantiateProposal(chaincodeName string, args [][]byte, chaincodePath string, chaincodeVersion string, chaincodePolicy *common.SignaturePolicyEnvelope, + collConfig []*common.CollectionConfig, targets []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error) + SendUpgradeProposal(chaincodeName string, args [][]byte, chaincodePath string, chaincodeVersion string, chaincodePolicy *common.SignaturePolicyEnvelope, targets []ProposalProcessor) ([]*TransactionProposalResponse, TransactionID, error) + + // Network + // Deprecated: getters/setters are deprecated from interface. + AddPeer(peer Peer) error + RemovePeer(peer Peer) + Peers() []Peer + AnchorPeers() []OrgAnchorPeer + SetPrimaryPeer(peer Peer) error + PrimaryPeer() Peer + AddOrderer(orderer Orderer) error + RemoveOrderer(orderer Orderer) + Orderers() []Orderer + SetMSPManager(mspManager msp.MSPManager) + MSPManager() msp.MSPManager + OrganizationUnits() ([]string, error) + + // Query + QueryInfo() (*common.BlockchainInfo, error) + QueryBlock(blockNumber int) (*common.Block, error) + QueryBlockByHash(blockHash []byte) (*common.Block, error) + QueryTransaction(transactionID TransactionID) (*pb.ProcessedTransaction, error) + QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error) + QueryByChaincode(request ChaincodeInvokeRequest) ([][]byte, error) + QueryBySystemChaincode(request ChaincodeInvokeRequest) ([][]byte, error) + QueryConfigBlock(targets []ProposalProcessor, minResponses int) (*common.ConfigEnvelope, error) +} diff --git a/pkg/fab/channel/block.go b/pkg/fab/channel/block.go deleted file mode 100644 index 6303f35eab..0000000000 --- a/pkg/fab/channel/block.go +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package channel - -import ( - "github.com/golang/protobuf/proto" - - ab "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/protos/orderer" - "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" - - ccomm "github.com/hyperledger/fabric-sdk-go/pkg/core/config/comm" - "github.com/hyperledger/fabric-sdk-go/pkg/fab/txn" - "github.com/pkg/errors" -) - -// block retrieves the block at the given position -func (c *Channel) block(pos *ab.SeekPosition) (*common.Block, error) { - - th, err := txn.NewHeader(c.clientContext, c.name) - if err != nil { - return nil, errors.Wrap(err, "generating TX ID failed") - } - - channelHeaderOpts := txn.ChannelHeaderOpts{ - TxnHeader: th, - TLSCertHash: ccomm.TLSCertHash(c.clientContext.Config()), - } - seekInfoHeader, err := txn.CreateChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, channelHeaderOpts) - if err != nil { - return nil, errors.Wrap(err, "CreateChannelHeader failed") - } - - seekInfoHeaderBytes, err := proto.Marshal(seekInfoHeader) - if err != nil { - return nil, errors.Wrap(err, "marshal seek info failed") - } - - signatureHeader, err := txn.CreateSignatureHeader(th) - if err != nil { - return nil, errors.Wrap(err, "CreateSignatureHeader failed") - } - - signatureHeaderBytes, err := proto.Marshal(signatureHeader) - if err != nil { - return nil, errors.Wrap(err, "marshal signature header failed") - } - - seekHeader := &common.Header{ - ChannelHeader: seekInfoHeaderBytes, - SignatureHeader: signatureHeaderBytes, - } - - seekInfo := &ab.SeekInfo{ - Start: pos, - Stop: pos, - Behavior: ab.SeekInfo_BLOCK_UNTIL_READY, - } - - seekInfoBytes, err := proto.Marshal(seekInfo) - if err != nil { - return nil, errors.Wrap(err, "marshal seek info failed") - } - - payload := common.Payload{ - Header: seekHeader, - Data: seekInfoBytes, - } - - return txn.SendPayload(c.clientContext, &payload, c.Orderers()) -} - -// newNewestSeekPosition returns a SeekPosition that requests the newest block -func newNewestSeekPosition() *ab.SeekPosition { - return &ab.SeekPosition{Type: &ab.SeekPosition_Newest{Newest: &ab.SeekNewest{}}} -} - -// newSpecificSeekPosition returns a SeekPosition that requests the block at the given index -func newSpecificSeekPosition(index uint64) *ab.SeekPosition { - return &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: index}}} -} diff --git a/pkg/fab/channel/channel_test.go b/pkg/fab/channel/channel_test.go deleted file mode 100644 index c717c2ba5d..0000000000 --- a/pkg/fab/channel/channel_test.go +++ /dev/null @@ -1,255 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ -package channel - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab" - mocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" - "github.com/pkg/errors" -) - -var testAddress = "127.0.0.1:0" - -var validRootCA = `-----BEGIN CERTIFICATE----- -MIICYjCCAgmgAwIBAgIUB3CTDOU47sUC5K4kn/Caqnh114YwCgYIKoZIzj0EAwIw -fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh -biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK -BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTYxMDEyMTkzMTAw -WhcNMjExMDExMTkzMTAwWjB/MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv -cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEfMB0GA1UEChMWSW50ZXJuZXQg -V2lkZ2V0cywgSW5jLjEMMAoGA1UECxMDV1dXMRQwEgYDVQQDEwtleGFtcGxlLmNv -bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKIH5b2JaSmqiQXHyqC+cmknICcF -i5AddVjsQizDV6uZ4v6s+PWiJyzfA/rTtMvYAPq/yeEHpBUB1j053mxnpMujYzBh -MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQXZ0I9 -qp6CP8TFHZ9bw5nRtZxIEDAfBgNVHSMEGDAWgBQXZ0I9qp6CP8TFHZ9bw5nRtZxI -EDAKBggqhkjOPQQDAgNHADBEAiAHp5Rbp9Em1G/UmKn8WsCbqDfWecVbZPQj3RK4 -oG5kQQIgQAe4OOKYhJdh3f7URaKfGTf492/nmRmtK+ySKjpHSrU= ------END CERTIFICATE----- -` - -func TestChannelMethods(t *testing.T) { - user := mocks.NewMockUser("test") - ctx := mocks.NewMockContext(user) - channel, err := New(ctx, mocks.NewMockChannelCfg("testChannel")) - if err != nil { - t.Fatalf("New return error[%s]", err) - } - if channel.Name() != "testChannel" { - t.Fatalf("New create wrong channel") - } - - _, err = New(ctx, mocks.NewMockChannelCfg("")) - if err != nil { - t.Fatalf("Got error creating channel with empty channel ID: %s", err) - } - - _, err = New(nil, mocks.NewMockChannelCfg("testChannel")) - if err == nil { - t.Fatalf("NewChannel didn't return error") - } - if err.Error() != "client is required" { - t.Fatalf("NewChannel didn't return right error") - } - -} - -func TestAddRemoveOrderer(t *testing.T) { - - //Setup channel - channel, _ := setupTestChannel() - - //Create mock orderer - orderer := mocks.NewMockOrderer("", nil) - - //Add an orderer - channel.AddOrderer(orderer) - - //Check if orderer is being added successfully - if len(channel.Orderers()) != 1 { - t.Fatal("Adding orderers to channel failed") - } - - //Remove the orderer now - channel.RemoveOrderer(orderer) - - //Check if list of orderers is empty now - if len(channel.Orderers()) != 0 { - t.Fatal("Removing orderers from channel failed") - } -} - -func TestAddAndRemovePeers(t *testing.T) { - //Setup channel - channel, _ := setupTestChannel() - - //Add a Peer - peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} - channel.AddPeer(&peer) - - //Remove and Test - channel.RemovePeer(&peer) - if len(channel.Peers()) != 0 { - t.Fatal("Remove Peer failed") - } - - //Add the Peer again - channel.AddPeer(&peer) - if len(channel.Peers()) != 1 { - t.Fatal("Add Peer failed") - } - -} - -func TestPrimaryPeer(t *testing.T) { - channel, _ := setupTestChannel() - - if channel.PrimaryPeer() != nil { - t.Fatal("Call to Primary peer on empty channel should always return nil") - } - - // Channel had one peer - peer1 := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} - err := channel.AddPeer(&peer1) - if err != nil { - t.Fatalf("Error adding peer: %v", err) - } - - // Test primary defaults to channel peer - primary := channel.PrimaryPeer() - if primary.URL() != peer1.URL() { - t.Fatalf("Primary Peer failed to default") - } - - // Channel has two peers - peer2 := mocks.MockPeer{MockName: "Peer2", MockURL: "http://peer2.com", MockRoles: []string{}, MockCert: nil} - err = channel.AddPeer(&peer2) - if err != nil { - t.Fatalf("Error adding peer: %v", err) - } - - // Set primary to invalid URL - invalidChoice := mocks.MockPeer{MockName: "", MockURL: "http://xyz.com", MockRoles: []string{}, MockCert: nil} - err = channel.SetPrimaryPeer(&invalidChoice) - if err == nil { - t.Fatalf("Primary Peer was set to an invalid peer") - } - - // Set primary to valid peer 2 URL - choice := mocks.MockPeer{MockName: "", MockURL: "http://peer2.com", MockRoles: []string{}, MockCert: nil} - err = channel.SetPrimaryPeer(&choice) - if err != nil { - t.Fatalf("Failed to set valid primary peer") - } - - // Test primary equals our choice - primary = channel.PrimaryPeer() - if primary.URL() != peer2.URL() { - t.Fatalf("Primary and our choice are not equal") - } - -} - -func TestQueryOnSystemChannel(t *testing.T) { - channel, _ := setupChannel(fab.SystemChannel) - peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, Status: 200} - err := channel.AddPeer(&peer) - if err != nil { - t.Fatalf("Error adding peer to channel: %s", err) - } - - request := fab.ChaincodeInvokeRequest{ - ChaincodeID: "ccID", - Fcn: "method", - Args: [][]byte{[]byte("arg")}, - } - if _, err := channel.QueryByChaincode(request); err != nil { - t.Fatalf("Error invoking chaincode on system channel: %s", err) - } -} - -func TestQueryBySystemChaincode(t *testing.T) { - channel, _ := setupTestChannel() - - peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, Payload: []byte("A"), Status: 200} - channel.AddPeer(&peer) - - request := fab.ChaincodeInvokeRequest{ - ChaincodeID: "cc", - Fcn: "Hello", - } - resp, err := channel.QueryBySystemChaincode(request) - if err != nil { - t.Fatalf("Failed to query: %s", err) - } - expectedResp := []byte("A") - - if !reflect.DeepEqual(resp[0], expectedResp) { - t.Fatalf("Unexpected transaction proposal response: %v", resp) - } -} - -func isValueInList(value string, list []string) bool { - for _, v := range list { - if v == value { - return true - } - } - return false -} - -func setupTestChannel() (*Channel, error) { - return setupChannel("testChannel") -} - -func setupChannel(channelID string) (*Channel, error) { - user := mocks.NewMockUser("test") - ctx := mocks.NewMockContext(user) - return New(ctx, mocks.NewMockChannelCfg(channelID)) -} - -func setupMassiveTestChannel(numberOfPeers int, numberOfOrderers int) (*Channel, error) { - channel, error := setupTestChannel() - if error != nil { - return channel, error - } - - for i := 0; i < numberOfPeers; i++ { - peer := mocks.MockPeer{MockName: fmt.Sprintf("MockPeer%d", i), MockURL: fmt.Sprintf("http://mock%d.peers.r.us", i), - MockRoles: []string{}, MockCert: nil} - err := channel.AddPeer(&peer) - if err != nil { - return nil, errors.WithMessage(err, "failed to add peer") - } - } - - for i := 0; i < numberOfOrderers; i++ { - orderer := mocks.NewMockOrderer(fmt.Sprintf("http://mock%d.orderers.r.us", i), nil) - err := channel.AddOrderer(orderer) - if err != nil { - return nil, errors.WithMessage(err, "failed to add orderer") - } - } - - return channel, error -} - -func TestAddPeerDuplicateCheck(t *testing.T) { - channel, _ := setupTestChannel() - - peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} - channel.AddPeer(&peer) - - err := channel.AddPeer(&peer) - - if err == nil || !strings.Contains(err.Error(), "http://peer1.com already exists") { - t.Fatal("Duplicate Peer check is not working as expected") - } -} diff --git a/pkg/fab/channel/config.go b/pkg/fab/channel/config.go deleted file mode 100644 index ba2f3c6653..0000000000 --- a/pkg/fab/channel/config.go +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package channel - -import ( - "github.com/golang/protobuf/proto" - - "github.com/hyperledger/fabric-sdk-go/pkg/context/api/core" - "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" - mb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/msp" - - "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp" - "github.com/pkg/errors" -) - -// ChannelConfig queries for the current config block for this channel. -// This transaction will be made to the orderer. -// @returns {ConfigEnvelope} Object containing the configuration items. -// @see /protos/orderer/ab.proto -// @see /protos/common/configtx.proto -func (c *Channel) ChannelConfig() (*common.ConfigEnvelope, error) { - logger.Debugf("channelConfig - start for channel %s", c.name) - - // Get the newest block - block, err := c.block(newNewestSeekPosition()) - if err != nil { - return nil, err - } - logger.Debugf("channelConfig - Retrieved newest block number: %d\n", block.Header.Number) - - // Get the index of the last config block - lastConfig, err := getLastConfigFromBlock(block) - if err != nil { - return nil, errors.Wrap(err, "GetLastConfigFromBlock failed") - } - logger.Debugf("channelConfig - Last config index: %d\n", lastConfig.Index) - - // Get the last config block - block, err = c.block(newSpecificSeekPosition(lastConfig.Index)) - - if err != nil { - return nil, errors.WithMessage(err, "retrieve block failed") - } - logger.Debugf("channelConfig - Last config block number %d, Number of tx: %d", block.Header.Number, len(block.Data.Data)) - - if len(block.Data.Data) != 1 { - return nil, errors.New("apiconfig block must contain one transaction") - } - - return createConfigEnvelope(block.Data.Data[0]) - -} - -func createConfigEnvelope(data []byte) (*common.ConfigEnvelope, error) { - - envelope := &common.Envelope{} - if err := proto.Unmarshal(data, envelope); err != nil { - return nil, errors.Wrap(err, "unmarshal envelope from config block failed") - } - payload := &common.Payload{} - if err := proto.Unmarshal(envelope.Payload, payload); err != nil { - return nil, errors.Wrap(err, "unmarshal payload from envelope failed") - } - channelHeader := &common.ChannelHeader{} - if err := proto.Unmarshal(payload.Header.ChannelHeader, channelHeader); err != nil { - return nil, errors.Wrap(err, "unmarshal payload from envelope failed") - } - if common.HeaderType(channelHeader.Type) != common.HeaderType_CONFIG { - return nil, errors.New("block must be of type 'CONFIG'") - } - configEnvelope := &common.ConfigEnvelope{} - if err := proto.Unmarshal(payload.Data, configEnvelope); err != nil { - return nil, errors.Wrap(err, "unmarshal config envelope failed") - } - - return configEnvelope, nil -} - -func loadMSPs(mspConfigs []*mb.MSPConfig, cs core.CryptoSuite) ([]msp.MSP, error) { - logger.Debugf("loadMSPs - start number of msps=%d", len(mspConfigs)) - - msps := []msp.MSP{} - for _, config := range mspConfigs { - mspType := msp.ProviderType(config.Type) - if mspType != msp.FABRIC { - return nil, errors.Errorf("MSP type not supported: %v", mspType) - } - if len(config.Config) == 0 { - return nil, errors.Errorf("MSP configuration missing the payload in the 'Config' property") - } - - fabricConfig := &mb.FabricMSPConfig{} - err := proto.Unmarshal(config.Config, fabricConfig) - if err != nil { - return nil, errors.Wrap(err, "unmarshal FabricMSPConfig from config failed") - } - - if fabricConfig.Name == "" { - return nil, errors.New("MSP Configuration missing name") - } - - // with this method we are only dealing with verifying MSPs, not local MSPs. Local MSPs are instantiated - // from user enrollment materials (see User class). For verifying MSPs the root certificates are always - // required - if len(fabricConfig.RootCerts) == 0 { - return nil, errors.New("MSP Configuration missing root certificates required for validating signing certificates") - } - - // get the application org names - var orgs []string - orgUnits := fabricConfig.OrganizationalUnitIdentifiers - for _, orgUnit := range orgUnits { - logger.Debugf("loadMSPs - found org of :: %s", orgUnit.OrganizationalUnitIdentifier) - orgs = append(orgs, orgUnit.OrganizationalUnitIdentifier) - } - - // TODO: Do something with orgs - // TODO: Configure MSP version (rather than MSP 1.0) - newMSP, err := msp.NewBccspMsp(msp.MSPv1_0, cs) - if err != nil { - return nil, errors.Wrap(err, "instantiate MSP failed") - } - - if err := newMSP.Setup(config); err != nil { - return nil, errors.Wrap(err, "configure MSP failed") - } - - mspID, _ := newMSP.GetIdentifier() - logger.Debugf("loadMSPs - adding msp=%s", mspID) - - msps = append(msps, newMSP) - } - - logger.Debugf("loadMSPs - loaded %d MSPs", len(msps)) - return msps, nil -} - -// getLastConfigFromBlock returns the LastConfig data from the given block -func getLastConfigFromBlock(block *common.Block) (*common.LastConfig, error) { - if block.Metadata == nil { - return nil, errors.New("block metadata is nil") - } - metadata := &common.Metadata{} - err := proto.Unmarshal(block.Metadata.Metadata[common.BlockMetadataIndex_LAST_CONFIG], metadata) - if err != nil { - return nil, errors.Wrap(err, "unmarshal block metadata failed") - } - - lastConfig := &common.LastConfig{} - err = proto.Unmarshal(metadata.Value, lastConfig) - if err != nil { - return nil, errors.Wrap(err, "unmarshal last config from metadata failed") - } - - return lastConfig, err -} diff --git a/pkg/fab/channel/config_test.go b/pkg/fab/channel/config_test.go deleted file mode 100644 index da17acce19..0000000000 --- a/pkg/fab/channel/config_test.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ -package channel - -import ( - "testing" - - "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" -) - -func TestChannelConfigs(t *testing.T) { - - user := mocks.NewMockUser("test") - ctx := mocks.NewMockContext(user) - - channel, _ := New(ctx, mocks.NewMockChannelCfg("testChannel")) - - if channel.IsReadonly() { - //TODO: Rightnow it is returning false always, need to revisit test once actual implementation is provided - t.Fatal("Is Readonly test failed") - } - - if channel.UpdateChannel() { - //TODO: Rightnow it is returning false always, need to revisit test once actual implementation is provided - t.Fatal("UpdateChannel test failed") - } - - channel.SetMSPManager(nil) - -} diff --git a/pkg/fab/channel/channel.go b/pkg/fab/channel/deprecated.go similarity index 67% rename from pkg/fab/channel/channel.go rename to pkg/fab/channel/deprecated.go index 2f72d4205c..156b609a48 100644 --- a/pkg/fab/channel/channel.go +++ b/pkg/fab/channel/deprecated.go @@ -1,3 +1,5 @@ +// +build deprecated + /* Copyright SecureKey Technologies Inc. All Rights Reserved. @@ -11,21 +13,46 @@ import ( "encoding/pem" "strings" + "github.com/golang/protobuf/proto" "github.com/pkg/errors" "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp" + ab "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/protos/orderer" "github.com/hyperledger/fabric-sdk-go/pkg/context" "github.com/hyperledger/fabric-sdk-go/pkg/context/api/core" "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab" + ccomm "github.com/hyperledger/fabric-sdk-go/pkg/core/config/comm" "github.com/hyperledger/fabric-sdk-go/pkg/errors/status" "github.com/hyperledger/fabric-sdk-go/pkg/fab/orderer" "github.com/hyperledger/fabric-sdk-go/pkg/fab/txn" - "github.com/hyperledger/fabric-sdk-go/pkg/logging" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" + mb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/msp" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" + protos_utils "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/utils" +) + +const ( + lsccDeploy = "deploy" + lsccUpgrade = "upgrade" + escc = "escc" + vscc = "vscc" + + InstantiateChaincode ChaincodeProposalType = iota + UpgradeChaincode ) -var logger = logging.NewLogger("fabric_sdk_go") +// ChaincodeProposalType reflects transitions in the chaincode lifecycle +type ChaincodeProposalType int + +// ChaincodeDeployRequest holds parameters for creating an instantiate or upgrade chaincode proposal. +type ChaincodeDeployRequest struct { + Name string + Path string + Version string + Args [][]byte + Policy *common.SignaturePolicyEnvelope + CollConfig []*common.CollectionConfig +} // Channel captures settings for a channel, which is created by // the orderers to isolate transactions delivery to peers participating on channel. @@ -561,6 +588,189 @@ func (c *Channel) chaincodeInvokeRequestAddDefaultPeers(targets []fab.ProposalPr return targets, nil } +// block retrieves the block at the given position +func (c *Channel) block(pos *ab.SeekPosition) (*common.Block, error) { + + th, err := txn.NewHeader(c.clientContext, c.name) + if err != nil { + return nil, errors.Wrap(err, "generating TX ID failed") + } + + channelHeaderOpts := txn.ChannelHeaderOpts{ + TxnHeader: th, + TLSCertHash: ccomm.TLSCertHash(c.clientContext.Config()), + } + seekInfoHeader, err := txn.CreateChannelHeader(common.HeaderType_DELIVER_SEEK_INFO, channelHeaderOpts) + if err != nil { + return nil, errors.Wrap(err, "CreateChannelHeader failed") + } + + seekInfoHeaderBytes, err := proto.Marshal(seekInfoHeader) + if err != nil { + return nil, errors.Wrap(err, "marshal seek info failed") + } + + signatureHeader, err := txn.CreateSignatureHeader(th) + if err != nil { + return nil, errors.Wrap(err, "CreateSignatureHeader failed") + } + + signatureHeaderBytes, err := proto.Marshal(signatureHeader) + if err != nil { + return nil, errors.Wrap(err, "marshal signature header failed") + } + + seekHeader := &common.Header{ + ChannelHeader: seekInfoHeaderBytes, + SignatureHeader: signatureHeaderBytes, + } + + seekInfo := &ab.SeekInfo{ + Start: pos, + Stop: pos, + Behavior: ab.SeekInfo_BLOCK_UNTIL_READY, + } + + seekInfoBytes, err := proto.Marshal(seekInfo) + if err != nil { + return nil, errors.Wrap(err, "marshal seek info failed") + } + + payload := common.Payload{ + Header: seekHeader, + Data: seekInfoBytes, + } + + return txn.SendPayload(c.clientContext, &payload, c.Orderers()) +} + +// newNewestSeekPosition returns a SeekPosition that requests the newest block +func newNewestSeekPosition() *ab.SeekPosition { + return &ab.SeekPosition{Type: &ab.SeekPosition_Newest{Newest: &ab.SeekNewest{}}} +} + +// newSpecificSeekPosition returns a SeekPosition that requests the block at the given index +func newSpecificSeekPosition(index uint64) *ab.SeekPosition { + return &ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: index}}} +} + +// ChannelConfig queries for the current config block for this channel. +// This transaction will be made to the orderer. +// @returns {ConfigEnvelope} Object containing the configuration items. +// @see /protos/orderer/ab.proto +// @see /protos/common/configtx.proto +func (c *Channel) ChannelConfig() (*common.ConfigEnvelope, error) { + logger.Debugf("channelConfig - start for channel %s", c.name) + + // Get the newest block + block, err := c.block(newNewestSeekPosition()) + if err != nil { + return nil, err + } + logger.Debugf("channelConfig - Retrieved newest block number: %d\n", block.Header.Number) + + // Get the index of the last config block + lastConfig, err := getLastConfigFromBlock(block) + if err != nil { + return nil, errors.Wrap(err, "GetLastConfigFromBlock failed") + } + logger.Debugf("channelConfig - Last config index: %d\n", lastConfig.Index) + + // Get the last config block + block, err = c.block(newSpecificSeekPosition(lastConfig.Index)) + + if err != nil { + return nil, errors.WithMessage(err, "retrieve block failed") + } + logger.Debugf("channelConfig - Last config block number %d, Number of tx: %d", block.Header.Number, len(block.Data.Data)) + + if len(block.Data.Data) != 1 { + return nil, errors.New("apiconfig block must contain one transaction") + } + + return createConfigEnvelope(block.Data.Data[0]) + +} + +func loadMSPs(mspConfigs []*mb.MSPConfig, cs core.CryptoSuite) ([]msp.MSP, error) { + logger.Debugf("loadMSPs - start number of msps=%d", len(mspConfigs)) + + msps := []msp.MSP{} + for _, config := range mspConfigs { + mspType := msp.ProviderType(config.Type) + if mspType != msp.FABRIC { + return nil, errors.Errorf("MSP type not supported: %v", mspType) + } + if len(config.Config) == 0 { + return nil, errors.Errorf("MSP configuration missing the payload in the 'Config' property") + } + + fabricConfig := &mb.FabricMSPConfig{} + err := proto.Unmarshal(config.Config, fabricConfig) + if err != nil { + return nil, errors.Wrap(err, "unmarshal FabricMSPConfig from config failed") + } + + if fabricConfig.Name == "" { + return nil, errors.New("MSP Configuration missing name") + } + + // with this method we are only dealing with verifying MSPs, not local MSPs. Local MSPs are instantiated + // from user enrollment materials (see User class). For verifying MSPs the root certificates are always + // required + if len(fabricConfig.RootCerts) == 0 { + return nil, errors.New("MSP Configuration missing root certificates required for validating signing certificates") + } + + // get the application org names + var orgs []string + orgUnits := fabricConfig.OrganizationalUnitIdentifiers + for _, orgUnit := range orgUnits { + logger.Debugf("loadMSPs - found org of :: %s", orgUnit.OrganizationalUnitIdentifier) + orgs = append(orgs, orgUnit.OrganizationalUnitIdentifier) + } + + // TODO: Do something with orgs + // TODO: Configure MSP version (rather than MSP 1.0) + newMSP, err := msp.NewBccspMsp(msp.MSPv1_0, cs) + if err != nil { + return nil, errors.Wrap(err, "instantiate MSP failed") + } + + if err := newMSP.Setup(config); err != nil { + return nil, errors.Wrap(err, "configure MSP failed") + } + + mspID, _ := newMSP.GetIdentifier() + logger.Debugf("loadMSPs - adding msp=%s", mspID) + + msps = append(msps, newMSP) + } + + logger.Debugf("loadMSPs - loaded %d MSPs", len(msps)) + return msps, nil +} + +// getLastConfigFromBlock returns the LastConfig data from the given block +func getLastConfigFromBlock(block *common.Block) (*common.LastConfig, error) { + if block.Metadata == nil { + return nil, errors.New("block metadata is nil") + } + metadata := &common.Metadata{} + err := proto.Unmarshal(block.Metadata.Metadata[common.BlockMetadataIndex_LAST_CONFIG], metadata) + if err != nil { + return nil, errors.Wrap(err, "unmarshal block metadata failed") + } + + lastConfig := &common.LastConfig{} + err = proto.Unmarshal(metadata.Value, lastConfig) + if err != nil { + return nil, errors.Wrap(err, "unmarshal last config from metadata failed") + } + + return lastConfig, err +} + // peersToTxnProcessors converts a slice of Peers to a slice of ProposalProcessors func peersToTxnProcessors(peers []fab.Peer) []fab.ProposalProcessor { tpp := make([]fab.ProposalProcessor, len(peers)) @@ -570,3 +780,57 @@ func peersToTxnProcessors(peers []fab.Peer) []fab.ProposalProcessor { } return tpp } + +// CreateChaincodeDeployProposal creates an instantiate or upgrade chaincode proposal. +func CreateChaincodeDeployProposal(txh fab.TransactionHeader, deploy ChaincodeProposalType, channelID string, chaincode ChaincodeDeployRequest) (*fab.TransactionProposal, error) { + + // Generate arguments for deploy (channel, marshaled CCDS, marshaled chaincode policy, marshaled collection policy) + args := [][]byte{} + args = append(args, []byte(channelID)) + + ccds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ + Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: chaincode.Name, Path: chaincode.Path, Version: chaincode.Version}, + Input: &pb.ChaincodeInput{Args: chaincode.Args}}} + ccdsBytes, err := protos_utils.Marshal(ccds) + if err != nil { + return nil, errors.WithMessage(err, "marshal of chaincode deployment spec failed") + } + args = append(args, ccdsBytes) + + chaincodePolicyBytes, err := protos_utils.Marshal(chaincode.Policy) + if err != nil { + return nil, errors.WithMessage(err, "marshal of chaincode policy failed") + } + args = append(args, chaincodePolicyBytes) + + args = append(args, []byte(escc)) + args = append(args, []byte(vscc)) + + if chaincode.CollConfig != nil { + var err error + collConfigBytes, err := proto.Marshal(&common.CollectionConfigPackage{Config: chaincode.CollConfig}) + if err != nil { + return nil, errors.WithMessage(err, "marshal of collection policy failed") + } + args = append(args, collConfigBytes) + } + + // Fcn is deploy or upgrade + fcn := "" + switch deploy { + case InstantiateChaincode: + fcn = lsccDeploy + case UpgradeChaincode: + fcn = lsccUpgrade + default: + return nil, errors.WithMessage(err, "chaincode deployment type unknown") + } + + cir := fab.ChaincodeInvokeRequest{ + ChaincodeID: lscc, + Fcn: fcn, + Args: args, + } + + return txn.CreateChaincodeInvokeProposal(txh, cir) +} diff --git a/pkg/fab/channel/lscc_test.go b/pkg/fab/channel/deprecated_test.go similarity index 51% rename from pkg/fab/channel/lscc_test.go rename to pkg/fab/channel/deprecated_test.go index 9e319234e8..365b414546 100644 --- a/pkg/fab/channel/lscc_test.go +++ b/pkg/fab/channel/deprecated_test.go @@ -1,3 +1,5 @@ +// +build deprecated + /* Copyright SecureKey Technologies Inc. All Rights Reserved. @@ -6,21 +8,265 @@ SPDX-License-Identifier: Apache-2.0 package channel import ( + "fmt" "net" + "reflect" + "strings" "testing" - "google.golang.org/grpc" - "github.com/golang/mock/gomock" "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab" mock_fab "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab/mocks" + mocks "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/cauthdsl" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" - - "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" + "github.com/pkg/errors" + "google.golang.org/grpc" ) +var testAddress = "127.0.0.1:0" + +func TestChannelMethods(t *testing.T) { + user := mocks.NewMockUser("test") + ctx := mocks.NewMockContext(user) + channel, err := New(ctx, mocks.NewMockChannelCfg("testChannel")) + if err != nil { + t.Fatalf("New return error[%s]", err) + } + if channel.Name() != "testChannel" { + t.Fatalf("New create wrong channel") + } + + _, err = New(ctx, mocks.NewMockChannelCfg("")) + if err != nil { + t.Fatalf("Got error creating channel with empty channel ID: %s", err) + } + + _, err = New(nil, mocks.NewMockChannelCfg("testChannel")) + if err == nil { + t.Fatalf("NewChannel didn't return error") + } + if err.Error() != "client is required" { + t.Fatalf("NewChannel didn't return right error") + } + +} + +func TestAddRemoveOrderer(t *testing.T) { + + //Setup channel + channel, _ := setupTestChannel() + + //Create mock orderer + orderer := mocks.NewMockOrderer("", nil) + + //Add an orderer + channel.AddOrderer(orderer) + + //Check if orderer is being added successfully + if len(channel.Orderers()) != 1 { + t.Fatal("Adding orderers to channel failed") + } + + //Remove the orderer now + channel.RemoveOrderer(orderer) + + //Check if list of orderers is empty now + if len(channel.Orderers()) != 0 { + t.Fatal("Removing orderers from channel failed") + } +} + +func TestAddAndRemovePeers(t *testing.T) { + //Setup channel + channel, _ := setupTestChannel() + + //Add a Peer + peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} + channel.AddPeer(&peer) + + //Remove and Test + channel.RemovePeer(&peer) + if len(channel.Peers()) != 0 { + t.Fatal("Remove Peer failed") + } + + //Add the Peer again + channel.AddPeer(&peer) + if len(channel.Peers()) != 1 { + t.Fatal("Add Peer failed") + } + +} + +func TestPrimaryPeer(t *testing.T) { + channel, _ := setupTestChannel() + + if channel.PrimaryPeer() != nil { + t.Fatal("Call to Primary peer on empty channel should always return nil") + } + + // Channel had one peer + peer1 := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} + err := channel.AddPeer(&peer1) + if err != nil { + t.Fatalf("Error adding peer: %v", err) + } + + // Test primary defaults to channel peer + primary := channel.PrimaryPeer() + if primary.URL() != peer1.URL() { + t.Fatalf("Primary Peer failed to default") + } + + // Channel has two peers + peer2 := mocks.MockPeer{MockName: "Peer2", MockURL: "http://peer2.com", MockRoles: []string{}, MockCert: nil} + err = channel.AddPeer(&peer2) + if err != nil { + t.Fatalf("Error adding peer: %v", err) + } + + // Set primary to invalid URL + invalidChoice := mocks.MockPeer{MockName: "", MockURL: "http://xyz.com", MockRoles: []string{}, MockCert: nil} + err = channel.SetPrimaryPeer(&invalidChoice) + if err == nil { + t.Fatalf("Primary Peer was set to an invalid peer") + } + + // Set primary to valid peer 2 URL + choice := mocks.MockPeer{MockName: "", MockURL: "http://peer2.com", MockRoles: []string{}, MockCert: nil} + err = channel.SetPrimaryPeer(&choice) + if err != nil { + t.Fatalf("Failed to set valid primary peer") + } + + // Test primary equals our choice + primary = channel.PrimaryPeer() + if primary.URL() != peer2.URL() { + t.Fatalf("Primary and our choice are not equal") + } + +} + +func TestQueryOnSystemChannel(t *testing.T) { + channel, _ := setupChannel(fab.SystemChannel) + peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, Status: 200} + err := channel.AddPeer(&peer) + if err != nil { + t.Fatalf("Error adding peer to channel: %s", err) + } + + request := fab.ChaincodeInvokeRequest{ + ChaincodeID: "ccID", + Fcn: "method", + Args: [][]byte{[]byte("arg")}, + } + if _, err := channel.QueryByChaincode(request); err != nil { + t.Fatalf("Error invoking chaincode on system channel: %s", err) + } +} + +func TestQueryBySystemChaincode(t *testing.T) { + channel, _ := setupTestChannel() + + peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, Payload: []byte("A"), Status: 200} + channel.AddPeer(&peer) + + request := fab.ChaincodeInvokeRequest{ + ChaincodeID: "cc", + Fcn: "Hello", + } + resp, err := channel.QueryBySystemChaincode(request) + if err != nil { + t.Fatalf("Failed to query: %s", err) + } + expectedResp := []byte("A") + + if !reflect.DeepEqual(resp[0], expectedResp) { + t.Fatalf("Unexpected transaction proposal response: %v", resp) + } +} + +func isValueInList(value string, list []string) bool { + for _, v := range list { + if v == value { + return true + } + } + return false +} + +func setupTestChannel() (*Channel, error) { + return setupChannel("testChannel") +} + +func setupChannel(channelID string) (*Channel, error) { + user := mocks.NewMockUser("test") + ctx := mocks.NewMockContext(user) + return New(ctx, mocks.NewMockChannelCfg(channelID)) +} + +func setupMassiveTestChannel(numberOfPeers int, numberOfOrderers int) (*Channel, error) { + channel, error := setupTestChannel() + if error != nil { + return channel, error + } + + for i := 0; i < numberOfPeers; i++ { + peer := mocks.MockPeer{MockName: fmt.Sprintf("MockPeer%d", i), MockURL: fmt.Sprintf("http://mock%d.peers.r.us", i), + MockRoles: []string{}, MockCert: nil} + err := channel.AddPeer(&peer) + if err != nil { + return nil, errors.WithMessage(err, "failed to add peer") + } + } + + for i := 0; i < numberOfOrderers; i++ { + orderer := mocks.NewMockOrderer(fmt.Sprintf("http://mock%d.orderers.r.us", i), nil) + err := channel.AddOrderer(orderer) + if err != nil { + return nil, errors.WithMessage(err, "failed to add orderer") + } + } + + return channel, error +} + +func TestAddPeerDuplicateCheck(t *testing.T) { + channel, _ := setupTestChannel() + + peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} + channel.AddPeer(&peer) + + err := channel.AddPeer(&peer) + + if err == nil || !strings.Contains(err.Error(), "http://peer1.com already exists") { + t.Fatal("Duplicate Peer check is not working as expected") + } +} + +func TestChannelConfigs(t *testing.T) { + + user := mocks.NewMockUser("test") + ctx := mocks.NewMockContext(user) + + channel, _ := New(ctx, mocks.NewMockChannelCfg("testChannel")) + + if channel.IsReadonly() { + //TODO: Rightnow it is returning false always, need to revisit test once actual implementation is provided + t.Fatal("Is Readonly test failed") + } + + if channel.UpdateChannel() { + //TODO: Rightnow it is returning false always, need to revisit test once actual implementation is provided + t.Fatal("UpdateChannel test failed") + } + + channel.SetMSPManager(nil) + +} + func TestSendInstantiateProposal(t *testing.T) { //Setup channel user := mocks.NewMockUserWithMSPID("test", "1234") diff --git a/pkg/fab/channel/ledger.go b/pkg/fab/channel/ledger.go index 3631900c19..7117c72852 100644 --- a/pkg/fab/channel/ledger.go +++ b/pkg/fab/channel/ledger.go @@ -16,10 +16,18 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab" "github.com/hyperledger/fabric-sdk-go/pkg/errors/multi" "github.com/hyperledger/fabric-sdk-go/pkg/fab/txn" + "github.com/hyperledger/fabric-sdk-go/pkg/logging" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" ) +var logger = logging.NewLogger("fabric_sdk_go") + +const ( + lscc = "lscc" + lsccChaincodes = "getchaincodes" +) + // Ledger is a client that provides access to the underlying ledger of a channel. type Ledger struct { ctx context.Context @@ -155,7 +163,7 @@ func createProcessedTransaction(tpr *fab.TransactionProposalResponse) (*pb.Proce // QueryInstantiatedChaincodes queries the instantiated chaincodes on this channel. // This query will be made to specified targets. func (c *Ledger) QueryInstantiatedChaincodes(targets []fab.ProposalProcessor) ([]*pb.ChaincodeQueryResponse, error) { - cir := createChaincodesInvokeRequest() + cir := createChaincodeInvokeRequest() tprs, errs := queryChaincode(c.ctx, c.chName, cir, targets) responses := []*pb.ChaincodeQueryResponse{} @@ -266,3 +274,36 @@ func filterResponses(responses []*fab.TransactionProposalResponse, errs error) ( return filteredResponses, errs } + +func createChaincodeInvokeRequest() fab.ChaincodeInvokeRequest { + cir := fab.ChaincodeInvokeRequest{ + ChaincodeID: lscc, + Fcn: lsccChaincodes, + } + return cir +} + +func createConfigEnvelope(data []byte) (*common.ConfigEnvelope, error) { + + envelope := &common.Envelope{} + if err := proto.Unmarshal(data, envelope); err != nil { + return nil, errors.Wrap(err, "unmarshal envelope from config block failed") + } + payload := &common.Payload{} + if err := proto.Unmarshal(envelope.Payload, payload); err != nil { + return nil, errors.Wrap(err, "unmarshal payload from envelope failed") + } + channelHeader := &common.ChannelHeader{} + if err := proto.Unmarshal(payload.Header.ChannelHeader, channelHeader); err != nil { + return nil, errors.Wrap(err, "unmarshal payload from envelope failed") + } + if common.HeaderType(channelHeader.Type) != common.HeaderType_CONFIG { + return nil, errors.New("block must be of type 'CONFIG'") + } + configEnvelope := &common.ConfigEnvelope{} + if err := proto.Unmarshal(payload.Data, configEnvelope); err != nil { + return nil, errors.Wrap(err, "unmarshal config envelope failed") + } + + return configEnvelope, nil +} diff --git a/pkg/fab/channel/ledger_test.go b/pkg/fab/channel/ledger_test.go index c44d6a3c3f..5310ae22ad 100644 --- a/pkg/fab/channel/ledger_test.go +++ b/pkg/fab/channel/ledger_test.go @@ -17,6 +17,23 @@ import ( "github.com/stretchr/testify/assert" ) +var validRootCA = `-----BEGIN CERTIFICATE----- +MIICYjCCAgmgAwIBAgIUB3CTDOU47sUC5K4kn/Caqnh114YwCgYIKoZIzj0EAwIw +fzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh +biBGcmFuY2lzY28xHzAdBgNVBAoTFkludGVybmV0IFdpZGdldHMsIEluYy4xDDAK +BgNVBAsTA1dXVzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMTYxMDEyMTkzMTAw +WhcNMjExMDExMTkzMTAwWjB/MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv +cm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEfMB0GA1UEChMWSW50ZXJuZXQg +V2lkZ2V0cywgSW5jLjEMMAoGA1UECxMDV1dXMRQwEgYDVQQDEwtleGFtcGxlLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKIH5b2JaSmqiQXHyqC+cmknICcF +i5AddVjsQizDV6uZ4v6s+PWiJyzfA/rTtMvYAPq/yeEHpBUB1j053mxnpMujYzBh +MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQXZ0I9 +qp6CP8TFHZ9bw5nRtZxIEDAfBgNVHSMEGDAWgBQXZ0I9qp6CP8TFHZ9bw5nRtZxI +EDAKBggqhkjOPQQDAgNHADBEAiAHp5Rbp9Em1G/UmKn8WsCbqDfWecVbZPQj3RK4 +oG5kQQIgQAe4OOKYhJdh3f7URaKfGTf492/nmRmtK+ySKjpHSrU= +-----END CERTIFICATE----- +` + func TestQueryMethods(t *testing.T) { channel, _ := setupTestLedger() peer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} diff --git a/pkg/fab/mocks/mockchprovider.go b/pkg/fab/mocks/mockchprovider.go index 13e9db8ca1..760c8ec56a 100644 --- a/pkg/fab/mocks/mockchprovider.go +++ b/pkg/fab/mocks/mockchprovider.go @@ -9,13 +9,11 @@ package mocks import ( "github.com/hyperledger/fabric-sdk-go/pkg/context" "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab" - "github.com/pkg/errors" ) // MockChannelProvider holds a mock channel provider. type MockChannelProvider struct { ctx context.ProviderContext - channels map[string]fab.Channel transactor fab.Transactor } @@ -28,21 +26,13 @@ type MockChannelService struct { // NewMockChannelProvider returns a mock ChannelProvider func NewMockChannelProvider(ctx context.Context) (*MockChannelProvider, error) { - channels := make(map[string]fab.Channel) - // Create a mock client with the mock channel cp := MockChannelProvider{ - ctx: ctx, - channels: channels, + ctx: ctx, } return &cp, nil } -// SetChannel convenience method to set channel -func (cp *MockChannelProvider) SetChannel(id string, channel fab.Channel) { - cp.channels[id] = channel -} - // SetTransactor sets the default transactor for all mock channel services func (cp *MockChannelProvider) SetTransactor(transactor fab.Transactor) { cp.transactor = transactor @@ -63,16 +53,6 @@ func (cs *MockChannelService) EventHub() (fab.EventHub, error) { return NewMockEventHub(), nil } -// Channel ... -func (cs *MockChannelService) Channel() (fab.Channel, error) { - ch, ok := cs.provider.channels[cs.channelID] - if !ok { - return nil, errors.New("No channel") - } - - return ch, nil -} - // Transactor ... func (cs *MockChannelService) Transactor() (fab.Transactor, error) { return cs.transactor, nil diff --git a/pkg/fab/resource/config.go b/pkg/fab/resource/config.go index 1820a8449e..c2a9905206 100644 --- a/pkg/fab/resource/config.go +++ b/pkg/fab/resource/config.go @@ -80,6 +80,7 @@ func ExtractChannelConfig(configEnvelope []byte) ([]byte, error) { return configUpdateEnvelope.ConfigUpdate, nil } +// CreateConfigEnvelope creates configuration envelope proto func CreateConfigEnvelope(data []byte) (*common.ConfigEnvelope, error) { envelope := &common.Envelope{} diff --git a/pkg/fabsdk/factory/defclient/sessfactory_test.go b/pkg/fabsdk/factory/defclient/sessfactory_test.go index 848c3861eb..75fd2d07cb 100644 --- a/pkg/fabsdk/factory/defclient/sessfactory_test.go +++ b/pkg/fabsdk/factory/defclient/sessfactory_test.go @@ -158,13 +158,6 @@ func newMockSessionWithUser(username, mspID string) *mockSession { return &session } -func (s *mockSession) Channel(channelID string) (fab.Channel, error) { - if s.IsChError { - return nil, errors.New("error") - } - return nil, nil -} - func (s *mockSession) EventHub(channelID string) (fab.EventHub, error) { if s.IsEHError { return nil, errors.New("error") diff --git a/pkg/fabsdk/provider/chpvdr/chprovider_test.go b/pkg/fabsdk/provider/chpvdr/chprovider_test.go index abb4ac08a7..59cc04fbdb 100644 --- a/pkg/fabsdk/provider/chpvdr/chprovider_test.go +++ b/pkg/fabsdk/provider/chpvdr/chprovider_test.go @@ -11,13 +11,11 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/context" "github.com/hyperledger/fabric-sdk-go/pkg/context/api/fab" - channelImpl "github.com/hyperledger/fabric-sdk-go/pkg/fab/channel" "github.com/hyperledger/fabric-sdk-go/pkg/fab/chconfig" "github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/factory/defcore" "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/provider/fabpvdr" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) @@ -76,20 +74,6 @@ func (f *MockFabricProvider) CreateChannelConfig(ic context.IdentityContext, cha } -// CreateChannelClient overrides the default. -func (f *MockFabricProvider) CreateChannelClient(ic context.IdentityContext, cfg fab.ChannelCfg) (fab.Channel, error) { - ctx := chconfig.Context{ - ProviderContext: f.providerContext, - IdentityContext: ic, - } - channel, err := channelImpl.New(ctx, cfg) - if err != nil { - return nil, errors.WithMessage(err, "NewChannel failed") - } - - return channel, nil -} - // CreateFabricProvider mocks new default implementation of fabric primitives func (f *MockProviderFactory) CreateFabricProvider(context context.ProviderContext) (api.FabricProvider, error) { fabProvider := fabpvdr.New(context)