diff --git a/api/channel.go b/api/channel.go new file mode 100644 index 0000000000..d7172f27ca --- /dev/null +++ b/api/channel.go @@ -0,0 +1,128 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "github.com/hyperledger/fabric/msp" + "github.com/hyperledger/fabric/protos/common" + pb "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 { + GetName() string + Initialize(data []byte) error + IsSecurityEnabled() bool + GetTCertBatchSize() int + SetTCertBatchSize(batchSize int) + AddPeer(peer Peer) error + RemovePeer(peer Peer) + GetPeers() []Peer + GetAnchorPeers() []OrgAnchorPeer + SetPrimaryPeer(peer Peer) error + GetPrimaryPeer() Peer + AddOrderer(orderer Orderer) error + RemoveOrderer(orderer Orderer) + GetOrderers() []Orderer + SetMSPManager(mspManager msp.MSPManager) + GetMSPManager() msp.MSPManager + GetGenesisBlock(request *GenesisBlockRequest) (*common.Block, error) + JoinChannel(request *JoinChannelRequest) ([]*TransactionProposalResponse, error) + UpdateChannel() bool + IsReadonly() bool + QueryInfo() (*common.BlockchainInfo, error) + QueryBlock(blockNumber int) (*common.Block, error) + QueryBlockByHash(blockHash []byte) (*common.Block, error) + QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error) + QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error) + QueryByChaincode(chaincodeName string, args []string, targets []Peer) ([][]byte, error) + CreateTransactionProposal(chaincodeName string, channelID string, args []string, sign bool, transientData map[string][]byte) (*TransactionProposal, error) + SendTransactionProposal(proposal *TransactionProposal, retry int, targets []Peer) ([]*TransactionProposalResponse, error) + CreateTransaction(resps []*TransactionProposalResponse) (*Transaction, error) + SendTransaction(tx *Transaction) ([]*TransactionResponse, error) + SendInstantiateProposal(chaincodeName string, channelID string, args []string, chaincodePath string, chaincodeVersion string, targets []Peer) ([]*TransactionProposalResponse, string, error) + GetOrganizationUnits() ([]string, error) + QueryExtensionInterface() ChannelExtension + LoadConfigUpdateEnvelope(data []byte) error +} + +// The ChannelExtension interface allows extensions of the SDK to add functionality to Channel overloads. +type ChannelExtension interface { + GetClientContext() FabricClient + + SignPayload(payload []byte) (*SignedEnvelope, error) + BroadcastEnvelope(envelope *SignedEnvelope) ([]*TransactionResponse, error) + + // TODO: This should go somewhere else - see TransactionProposal.GetBytes(). - deprecated + GetProposalBytes(tp *TransactionProposal) ([]byte, error) +} + +// OrgAnchorPeer contains information about an anchor peer on this channel +type OrgAnchorPeer struct { + Org string + Host string + Port int32 +} + +// GenesisBlockRequest ... +type GenesisBlockRequest struct { + TxID string + Nonce []byte +} + +// The TransactionProposal object to be send to the endorsers +type TransactionProposal struct { + TransactionID string + + SignedProposal *pb.SignedProposal + Proposal *pb.Proposal +} + +// TransactionProposalResponse ... +/** + * The TransactionProposalResponse result object returned from endorsers. + */ +type TransactionProposalResponse struct { + Endorser string + Err error + Status int32 + + Proposal *TransactionProposal + ProposalResponse *pb.ProposalResponse +} + +// JoinChannelRequest allows a set of peers to transact on a channel on the network +type JoinChannelRequest struct { + Targets []Peer + GenesisBlock *common.Block + TxID string + Nonce []byte +} + +// The Transaction object created from an endorsed proposal +type Transaction struct { + Proposal *TransactionProposal + Transaction *pb.Transaction +} + +// TransactionResponse ... +/** + * The TransactionProposalResponse result object returned from orderers. + */ +type TransactionResponse struct { + Orderer string + Err error +} diff --git a/api/config.go b/api/config.go new file mode 100644 index 0000000000..4f652ba308 --- /dev/null +++ b/api/config.go @@ -0,0 +1,56 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "crypto/x509" + + bccspFactory "github.com/hyperledger/fabric/bccsp/factory" + "github.com/spf13/viper" +) + +// Config ... +type Config interface { + GetServerURL() string + GetServerCertFiles() []string + GetFabricCAClientKeyFile() string + GetFabricCAClientCertFile() string + GetFabricCATLSEnabledFlag() bool + GetFabricClientViper() *viper.Viper + GetPeersConfig() ([]PeerConfig, error) + IsTLSEnabled() bool + GetTLSCACertPool(tlsCertificate string) (*x509.CertPool, error) + GetTLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) + IsSecurityEnabled() bool + TcertBatchSize() int + GetSecurityAlgorithm() string + GetSecurityLevel() int + GetOrdererHost() string + GetOrdererPort() string + GetOrdererTLSServerHostOverride() string + GetOrdererTLSCertificate() string + GetFabricCAID() string + GetFabricCAName() string + GetKeyStorePath() string + GetFabricCAHomeDir() string + GetFabricCAMspDir() string + GetCryptoConfigPath() string + GetCSPConfig() *bccspFactory.FactoryOpts +} + +// PeerConfig A set of configurations required to connect to a Fabric peer +type PeerConfig struct { + Host string + Port int + EventHost string + EventPort int + Primary bool + TLS struct { + Certificate string + ServerHostOverride string + } +} diff --git a/api/event.go b/api/event.go new file mode 100644 index 0000000000..3ae15a8229 --- /dev/null +++ b/api/event.go @@ -0,0 +1,65 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + common "github.com/hyperledger/fabric/protos/common" + ehpb "github.com/hyperledger/fabric/protos/peer" + pb "github.com/hyperledger/fabric/protos/peer" +) + +// EventHub ... +type EventHub interface { + SetPeerAddr(peerURL string, certificate string, serverHostOverride string) + IsConnected() bool + Connect() error + Disconnect() + RegisterChaincodeEvent(ccid string, eventname string, callback func(*ChaincodeEvent)) *ChainCodeCBE + UnregisterChaincodeEvent(cbe *ChainCodeCBE) + RegisterTxEvent(txID string, callback func(string, pb.TxValidationCode, error)) + UnregisterTxEvent(txID string) + RegisterBlockEvent(callback func(*common.Block)) + UnregisterBlockEvent(callback func(*common.Block)) +} + +//EventsClient holds the stream and adapter for consumer to work with +type EventsClient interface { + RegisterAsync(ies []*ehpb.Interest) error + UnregisterAsync(ies []*ehpb.Interest) error + Unregister(ies []*ehpb.Interest) error + Recv() (*ehpb.Event, error) + Start() error + Stop() error +} + +// The EventHubExt interface allows extensions of the SDK to add functionality to EventHub overloads. +type EventHubExt interface { + SetInterests(block bool) +} + +// ChainCodeCBE ... +/** + * The ChainCodeCBE is used internal to the EventHub to hold chaincode + * event registration callbacks. + */ +type ChainCodeCBE struct { + // chaincode id + CCID string + // event name regex filter + EventNameFilter string + // callback function to invoke on successful filter match + CallbackFunc func(*ChaincodeEvent) +} + +// ChaincodeEvent contains the current event data for the event handler +type ChaincodeEvent struct { + ChaincodeID string + TxID string + EventName string + Payload []byte + ChannelID string +} diff --git a/api/fabricclient.go b/api/fabricclient.go new file mode 100644 index 0000000000..b6182e181a --- /dev/null +++ b/api/fabricclient.go @@ -0,0 +1,78 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "github.com/hyperledger/fabric/bccsp" + "github.com/hyperledger/fabric/protos/common" + pb "github.com/hyperledger/fabric/protos/peer" +) + +// FabricClient ... +/* + * Main interaction handler with end user. A client instance provides a handler to interact + * with a network of peers, orderers and optionally member services. An application using the + * SDK may need to interact with multiple networks, each through a separate instance of the Client. + * + * Each client when initially created should be initialized with configuration data from the + * consensus service, which includes a list of trusted roots, orderer certificates and IP addresses, + * and a list of peer certificates and IP addresses that it can access. This must be done out of band + * as part of bootstrapping the application environment. It is also the responsibility of the application + * to maintain the configuration of a client as the SDK does not persist this object. + * + * Each Client instance can maintain several {@link Channel} instances representing channels and the associated + * private ledgers. + * + * + */ +type FabricClient interface { + NewChannel(name string) (Channel, error) + GetChannel(name string) Channel + ExtractChannelConfig(configEnvelope []byte) ([]byte, error) + SignChannelConfig(config []byte) (*common.ConfigSignature, error) + CreateChannel(request *CreateChannelRequest) error + QueryChannelInfo(name string, peers []Peer) (Channel, error) + SetStateStore(stateStore KeyValueStore) + GetStateStore() KeyValueStore + SetCryptoSuite(cryptoSuite bccsp.BCCSP) + GetCryptoSuite() bccsp.BCCSP + SaveUserToStateStore(user User, skipPersistence bool) error + LoadUserFromStateStore(name string) (User, error) + InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, chaincodePackage []byte, targets []Peer) ([]*TransactionProposalResponse, string, error) + QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error) + QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse, error) + GetIdentity() ([]byte, error) + GetUserContext() User + SetUserContext(user User) + GetConfig() Config +} + +// CreateChannelRequest requests channel creation on the network +type CreateChannelRequest struct { + // required - The name of the new channel + Name string + // required - The Orderer to send the update request + Orderer Orderer + // optional - the envelope object containing all + // required settings and signatures to initialize this channel. + // This envelope would have been created by the command + // line tool "configtx" + Envelope []byte + // optional - ConfigUpdate object built by the + // buildChannelConfig() method of this package + Config []byte + // optional - the list of collected signatures + // required by the channel create policy when using the `config` parameter. + // see signChannelConfig() method of this package + Signatures []*common.ConfigSignature + // optional - transaction ID + // required when using the `config` parameter + TxID string + // optional - nonce + // required when using the `config` parameter + Nonce []byte +} diff --git a/fabric-client/keyvaluestore/keyvaluestore.go b/api/keyvaluestore.go similarity index 96% rename from fabric-client/keyvaluestore/keyvaluestore.go rename to api/keyvaluestore.go index 6457c4dc5d..5a38c3c3b2 100644 --- a/fabric-client/keyvaluestore/keyvaluestore.go +++ b/api/keyvaluestore.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package keyvaluestore +package api // KeyValueStore ... /** diff --git a/api/msp.go b/api/msp.go new file mode 100644 index 0000000000..dd81a24d0b --- /dev/null +++ b/api/msp.go @@ -0,0 +1,65 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "github.com/hyperledger/fabric/bccsp" +) + +// Services ... +type Services interface { + GetCAName() string + Enroll(enrollmentID string, enrollmentSecret string) (bccsp.Key, []byte, error) + //reenroll to renew user's enrollment certificate + Reenroll(user User) (bccsp.Key, []byte, error) + Register(registrar User, request *RegistrationRequest) (string, error) + Revoke(registrar User, request *RevocationRequest) error +} + +// RegistrationRequest defines the attributes required to register a user with the CA +type RegistrationRequest struct { + // Name is the unique name of the identity + Name string + // Type of identity being registered (e.g. "peer, app, user") + Type string + // MaxEnrollments is the number of times the secret can be reused to enroll. + // if omitted, this defaults to max_enrollments configured on the server + MaxEnrollments int + // The identity's affiliation e.g. org1.department1 + Affiliation string + // Optional attributes associated with this identity + Attributes []Attribute + // CAName is the name of the CA to connect to + CAName string + // Secret is an optional password. If not specified, + // a random secret is generated. In both cases, the secret + // is returned from registration. + Secret string +} + +// RevocationRequest defines the attributes required to revoke credentials with the CA +type RevocationRequest struct { + // Name of the identity whose certificates should be revoked + // If this field is omitted, then Serial and AKI must be specified. + Name string + // Serial number of the certificate to be revoked + // If this is omitted, then Name must be specified + Serial string + // AKI (Authority Key Identifier) of the certificate to be revoked + AKI string + // Reason is the reason for revocation. See https://godoc.org/golang.org/x/crypto/ocsp + // for valid values. The default value is 0 (ocsp.Unspecified). + Reason string + // CAName is the name of the CA to connect to + CAName string +} + +// Attribute defines additional attributes that may be passed along during registration +type Attribute struct { + Key string + Value string +} diff --git a/api/orderer.go b/api/orderer.go new file mode 100644 index 0000000000..41ded5be49 --- /dev/null +++ b/api/orderer.go @@ -0,0 +1,25 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "github.com/hyperledger/fabric/protos/common" +) + +// Orderer The Orderer class represents a peer in the target blockchain network to which +// HFC sends a block of transactions of endorsed proposals requiring ordering. +type Orderer interface { + GetURL() string + SendBroadcast(envelope *SignedEnvelope) (*common.Status, error) + SendDeliver(envelope *SignedEnvelope) (chan *common.Block, chan error) +} + +// A SignedEnvelope can can be sent to an orderer for broadcasting +type SignedEnvelope struct { + Payload []byte + Signature []byte +} diff --git a/api/peer.go b/api/peer.go new file mode 100644 index 0000000000..ce64b1de10 --- /dev/null +++ b/api/peer.go @@ -0,0 +1,42 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "encoding/pem" +) + +// Peer ... +/** + * The Peer class represents a peer in the target blockchain network to which + * HFC sends endorsement proposals, transaction ordering or query requests. + * + * The Peer class represents the remote Peer node and its network membership materials, + * aka the ECert used to verify signatures. Peer membership represents organizations, + * unlike User membership which represents individuals. + * + * When constructed, a Peer instance can be designated as an event source, in which case + * a “eventSourceUrl” attribute should be configured. This allows the SDK to automatically + * attach transaction event listeners to the event stream. + * + * It should be noted that Peer event streams function at the Peer level and not at the + * channel and chaincode levels. + */ +type Peer interface { + ConnectEventSource() + IsEventListened(event string, channel Channel) (bool, error) + AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error) + RemoveListener(eventListenerRef string) (bool, error) + GetName() string + SetName(name string) + GetRoles() []string + SetRoles(roles []string) + GetEnrollmentCertificate() *pem.Block + SetEnrollmentCertificate(pem *pem.Block) + GetURL() string + SendProposal(proposal *TransactionProposal) (*TransactionProposalResponse, error) +} diff --git a/api/user.go b/api/user.go new file mode 100644 index 0000000000..ea5f442630 --- /dev/null +++ b/api/user.go @@ -0,0 +1,40 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package api + +import ( + "github.com/hyperledger/fabric/bccsp" +) + +// User ... +/** + * The User struct represents users that have been enrolled and represented by + * an enrollment certificate (ECert) and a signing key. The ECert must have + * been signed by one of the CAs the blockchain network has been configured to trust. + * An enrolled user (having a signing key and ECert) can conduct chaincode deployments, + * transactions and queries with the Chain. + * + * User ECerts can be obtained from a CA beforehand as part of deploying the application, + * or it can be obtained from the optional Fabric COP service via its enrollment process. + * + * Sometimes User identities are confused with Peer identities. User identities represent + * signing capability because it has access to the private key, while Peer identities in + * the context of the application/SDK only has the certificate for verifying signatures. + * An application cannot use the Peer identity to sign things because the application doesn’t + * have access to the Peer identity’s private key. + * + */ +type User interface { + GetName() string + GetRoles() []string + SetRoles([]string) + GetEnrollmentCertificate() []byte + SetEnrollmentCertificate(cert []byte) + SetPrivateKey(privateKey bccsp.Key) + GetPrivateKey() bccsp.Key + GenerateTcerts(count int, attributes []string) +} diff --git a/fabric-txn/transaction.go b/fabric-txn/transaction.go new file mode 100644 index 0000000000..4a779cb64e --- /dev/null +++ b/fabric-txn/transaction.go @@ -0,0 +1,5 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ diff --git a/fabric-txn/transactionconfig.go b/fabric-txn/transactionconfig.go new file mode 100644 index 0000000000..4a779cb64e --- /dev/null +++ b/fabric-txn/transactionconfig.go @@ -0,0 +1,5 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ diff --git a/config/config.go b/pkg/config/config.go similarity index 76% rename from config/config.go rename to pkg/config/config.go index 41fb2153db..aac39ff1c5 100644 --- a/config/config.go +++ b/pkg/config/config.go @@ -17,24 +17,13 @@ import ( "strconv" "strings" + api "github.com/hyperledger/fabric-sdk-go/api" + bccspFactory "github.com/hyperledger/fabric/bccsp/factory" "github.com/op/go-logging" "github.com/spf13/viper" ) -// PeerConfig A set of configurations required to connect to a Fabric peer -type PeerConfig struct { - Host string - Port int - EventHost string - EventPort int - Primary bool - TLS struct { - Certificate string - ServerHostOverride string - } -} - var myViper = viper.New() var log = logging.MustGetLogger("fabric_sdk_go") var format = logging.MustStringFormatter( @@ -43,15 +32,18 @@ var format = logging.MustStringFormatter( const cmdRoot = "fabric_sdk" +type config struct { +} + // InitConfig ... // initConfig reads in config file -func InitConfig(configFile string) error { +func InitConfig(configFile string) (api.Config, error) { return InitConfigWithCmdRoot(configFile, cmdRoot) } // InitConfigWithCmdRoot reads in a config file and allows the // environment variable prefixed to be specified -func InitConfigWithCmdRoot(configFile string, cmdRootPrefix string) error { +func InitConfigWithCmdRoot(configFile string, cmdRootPrefix string) (api.Config, error) { myViper.SetEnvPrefix(cmdRootPrefix) myViper.AutomaticEnv() replacer := strings.NewReplacer(".", "_") @@ -66,7 +58,7 @@ func InitConfigWithCmdRoot(configFile string, cmdRootPrefix string) error { if err == nil { log.Infof("Using config file: %s", myViper.ConfigFileUsed()) } else { - return fmt.Errorf("Fatal error config file: %v", err) + return nil, fmt.Errorf("Fatal error config file: %v", err) } } log.Debug(myViper.GetString("client.fabricCA.serverURL")) @@ -85,16 +77,17 @@ func InitConfigWithCmdRoot(configFile string, cmdRootPrefix string) error { } logging.SetBackend(backendFormatter).SetLevel(logging.Level(logLevel), "fabric_sdk_go") - return nil + return &config{}, nil + } //GetServerURL Read configuration option for the fabric CA server URL -func GetServerURL() string { +func (c *config) GetServerURL() string { return strings.Replace(myViper.GetString("client.fabricCA.serverURL"), "$GOPATH", os.Getenv("GOPATH"), -1) } //GetServerCertFiles Read configuration option for the server certificate files -func GetServerCertFiles() []string { +func (c *config) GetServerCertFiles() []string { certFiles := myViper.GetStringSlice("client.fabricCA.certfiles") certFileModPath := make([]string, len(certFiles)) for i, v := range certFiles { @@ -104,29 +97,29 @@ func GetServerCertFiles() []string { } //GetFabricCAClientKeyFile Read configuration option for the fabric CA client key file -func GetFabricCAClientKeyFile() string { +func (c *config) GetFabricCAClientKeyFile() string { return strings.Replace(myViper.GetString("client.fabricCA.client.keyfile"), "$GOPATH", os.Getenv("GOPATH"), -1) } //GetFabricCAClientCertFile Read configuration option for the fabric CA client cert file -func GetFabricCAClientCertFile() string { +func (c *config) GetFabricCAClientCertFile() string { return strings.Replace(myViper.GetString("client.fabricCA.client.certfile"), "$GOPATH", os.Getenv("GOPATH"), -1) } //GetFabricCATLSEnabledFlag Read configuration option for the fabric CA TLS flag -func GetFabricCATLSEnabledFlag() bool { +func (c *config) GetFabricCATLSEnabledFlag() bool { return myViper.GetBool("client.fabricCA.tlsEnabled") } // GetFabricClientViper returns the internal viper instance used by the // SDK to read configuration options -func GetFabricClientViper() *viper.Viper { +func (c *config) GetFabricClientViper() *viper.Viper { return myViper } // GetPeersConfig Retrieves the fabric peers from the config file provided -func GetPeersConfig() ([]PeerConfig, error) { - peersConfig := []PeerConfig{} +func (c *config) GetPeersConfig() ([]api.PeerConfig, error) { + peersConfig := []api.PeerConfig{} err := myViper.UnmarshalKey("client.peers", &peersConfig) if err != nil { return nil, err @@ -138,7 +131,7 @@ func GetPeersConfig() ([]PeerConfig, error) { if p.Port == 0 { return nil, fmt.Errorf("port key not exist or empty for peer %d", index) } - if IsTLSEnabled() && p.TLS.Certificate == "" { + if c.IsTLSEnabled() && p.TLS.Certificate == "" { return nil, fmt.Errorf("tls.certificate not exist or empty for peer %d", index) } peersConfig[index].TLS.Certificate = strings.Replace(p.TLS.Certificate, "$GOPATH", @@ -148,12 +141,12 @@ func GetPeersConfig() ([]PeerConfig, error) { } // IsTLSEnabled ... -func IsTLSEnabled() bool { +func (c *config) IsTLSEnabled() bool { return myViper.GetBool("client.tls.enabled") } // GetTLSCACertPool ... -func GetTLSCACertPool(tlsCertificate string) (*x509.CertPool, error) { +func (c *config) GetTLSCACertPool(tlsCertificate string) (*x509.CertPool, error) { certPool := x509.NewCertPool() if tlsCertificate != "" { rawData, err := ioutil.ReadFile(tlsCertificate) @@ -173,7 +166,7 @@ func GetTLSCACertPool(tlsCertificate string) (*x509.CertPool, error) { } // GetTLSCACertPoolFromRoots ... -func GetTLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) { +func (c *config) GetTLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) { certPool := x509.NewCertPool() for _, root := range ordererRootCAs { @@ -189,73 +182,73 @@ func GetTLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) } // IsSecurityEnabled ... -func IsSecurityEnabled() bool { +func (c *config) IsSecurityEnabled() bool { return myViper.GetBool("client.security.enabled") } // TcertBatchSize ... -func TcertBatchSize() int { +func (c *config) TcertBatchSize() int { return myViper.GetInt("client.tcert.batch.size") } // GetSecurityAlgorithm ... -func GetSecurityAlgorithm() string { +func (c *config) GetSecurityAlgorithm() string { return myViper.GetString("client.security.hashAlgorithm") } // GetSecurityLevel ... -func GetSecurityLevel() int { +func (c *config) GetSecurityLevel() int { return myViper.GetInt("client.security.level") } // GetOrdererHost ... -func GetOrdererHost() string { +func (c *config) GetOrdererHost() string { return myViper.GetString("client.orderer.host") } // GetOrdererPort ... -func GetOrdererPort() string { +func (c *config) GetOrdererPort() string { return strconv.Itoa(myViper.GetInt("client.orderer.port")) } // GetOrdererTLSServerHostOverride ... -func GetOrdererTLSServerHostOverride() string { +func (c *config) GetOrdererTLSServerHostOverride() string { return myViper.GetString("client.orderer.tls.serverhostoverride") } // GetOrdererTLSCertificate ... -func GetOrdererTLSCertificate() string { +func (c *config) GetOrdererTLSCertificate() string { return strings.Replace(myViper.GetString("client.orderer.tls.certificate"), "$GOPATH", os.Getenv("GOPATH"), -1) } // GetFabricCAID ... -func GetFabricCAID() string { +func (c *config) GetFabricCAID() string { return myViper.GetString("client.fabricCA.id") } //GetFabricCAName Read the fabric CA name -func GetFabricCAName() string { +func (c *config) GetFabricCAName() string { return myViper.GetString("client.fabricCA.name") } // GetKeyStorePath ... -func GetKeyStorePath() string { - return path.Join(GetFabricCAHomeDir(), GetFabricCAMspDir(), "keystore") +func (c *config) GetKeyStorePath() string { + return path.Join(c.GetFabricCAHomeDir(), c.GetFabricCAMspDir(), "keystore") } // GetFabricCAHomeDir ... -func GetFabricCAHomeDir() string { +func (c *config) GetFabricCAHomeDir() string { return myViper.GetString("client.fabricCA.homeDir") } // GetFabricCAMspDir ... -func GetFabricCAMspDir() string { +func (c *config) GetFabricCAMspDir() string { return myViper.GetString("client.fabricCA.mspDir") } // GetCryptoConfigPath ... -func GetCryptoConfigPath() string { +func (c *config) GetCryptoConfigPath() string { return strings.Replace(myViper.GetString("client.cryptoconfig.path"), "$GOPATH", os.Getenv("GOPATH"), -1) } @@ -275,14 +268,14 @@ func loadCAKey(rawData []byte) (*x509.Certificate, error) { } // GetCSPConfig ... -func GetCSPConfig() *bccspFactory.FactoryOpts { +func (c *config) GetCSPConfig() *bccspFactory.FactoryOpts { return &bccspFactory.FactoryOpts{ ProviderName: "SW", SwOpts: &bccspFactory.SwOpts{ - HashFamily: GetSecurityAlgorithm(), - SecLevel: GetSecurityLevel(), + HashFamily: c.GetSecurityAlgorithm(), + SecLevel: c.GetSecurityLevel(), FileKeystore: &bccspFactory.FileKeystoreOpts{ - KeyStorePath: GetKeyStorePath(), + KeyStorePath: c.GetKeyStorePath(), }, Ephemeral: false, }, diff --git a/config/config_test.go b/pkg/config/config_test.go similarity index 85% rename from config/config_test.go rename to pkg/config/config_test.go index 8913dd2d2d..aea7bbebc3 100644 --- a/config/config_test.go +++ b/pkg/config/config_test.go @@ -11,18 +11,21 @@ import ( "os" "testing" + api "github.com/hyperledger/fabric-sdk-go/api" "github.com/spf13/viper" ) +var configImpl api.Config + func TestCAConfig(t *testing.T) { - caname := GetFabricCAName() + caname := configImpl.GetFabricCAName() if caname != "ca-org1" { t.Fatalf("caname doesn't match") } } func TestGetPeersConfig(t *testing.T) { - pc, err := GetPeersConfig() + pc, err := configImpl.GetPeersConfig() if err != nil { t.Fatalf(err.Error()) } @@ -59,7 +62,7 @@ func TestMultipleVipers(t *testing.T) { t.Fatalf("Expected testValue before config initialization got: %s", testValue1) } // initialize go sdk - err = InitConfig("../test/fixtures/config/config_test.yaml") + _, err = InitConfig("../../test/fixtures/config/config_test.yaml") if err != nil { fmt.Println(err.Error()) } @@ -88,7 +91,7 @@ func TestEnvironmentVariablesDefaultCmdRoot(t *testing.T) { fmt.Println(err.Error()) } - err = InitConfig("../test/fixtures/config/config_test.yaml") + _, err = InitConfig("../../test/fixtures/config/config_test.yaml") if err != nil { fmt.Println(err.Error()) } @@ -112,7 +115,7 @@ func TestEnvironmentVariablesSpecificCmdRoot(t *testing.T) { fmt.Println(err.Error()) } - err = InitConfigWithCmdRoot("../test/fixtures/config/config_test.yaml", "test_root") + _, err = InitConfigWithCmdRoot("../../test/fixtures/config/config_test.yaml", "test_root") if err != nil { fmt.Println(err.Error()) } @@ -124,7 +127,8 @@ func TestEnvironmentVariablesSpecificCmdRoot(t *testing.T) { } func TestMain(m *testing.M) { - err := InitConfig("../test/fixtures/config/config_test.yaml") + var err error + configImpl, err = InitConfig("../../test/fixtures/config/config_test.yaml") if err != nil { fmt.Println(err.Error()) } diff --git a/config/test.yaml b/pkg/config/test.yaml similarity index 100% rename from config/test.yaml rename to pkg/config/test.yaml diff --git a/fabric-ca-client/fabricca.go b/pkg/fabric-ca-client/fabricca.go similarity index 69% rename from fabric-ca-client/fabricca.go rename to pkg/fabric-ca-client/fabricca.go index 36be87b1a3..747d833bb1 100644 --- a/fabric-ca-client/fabricca.go +++ b/pkg/fabric-ca-client/fabricca.go @@ -9,10 +9,9 @@ package fabricca import ( "fmt" - "github.com/hyperledger/fabric-ca/api" + api "github.com/hyperledger/fabric-ca/api" fabric_ca "github.com/hyperledger/fabric-ca/lib" - "github.com/hyperledger/fabric-sdk-go/config" - fabricclient "github.com/hyperledger/fabric-sdk-go/fabric-client" + sdkApi "github.com/hyperledger/fabric-sdk-go/api" "github.com/hyperledger/fabric/bccsp" "github.com/op/go-logging" @@ -20,69 +19,15 @@ import ( var logger = logging.MustGetLogger("fabric_sdk_go") -// Services ... -type Services interface { - GetCAName() string - Enroll(enrollmentID string, enrollmentSecret string) (bccsp.Key, []byte, error) - //reenroll to renew user's enrollment certificate - Reenroll(user fabricclient.User) (bccsp.Key, []byte, error) - Register(registrar fabricclient.User, request *RegistrationRequest) (string, error) - Revoke(registrar fabricclient.User, request *RevocationRequest) error -} - type services struct { fabricCAClient *fabric_ca.Client } -// RegistrationRequest defines the attributes required to register a user with the CA -type RegistrationRequest struct { - // Name is the unique name of the identity - Name string - // Type of identity being registered (e.g. "peer, app, user") - Type string - // MaxEnrollments is the number of times the secret can be reused to enroll. - // if omitted, this defaults to max_enrollments configured on the server - MaxEnrollments int - // The identity's affiliation e.g. org1.department1 - Affiliation string - // Optional attributes associated with this identity - Attributes []Attribute - // CAName is the name of the CA to connect to - CAName string - // Secret is an optional password. If not specified, - // a random secret is generated. In both cases, the secret - // is returned from registration. - Secret string -} - -// RevocationRequest defines the attributes required to revoke credentials with the CA -type RevocationRequest struct { - // Name of the identity whose certificates should be revoked - // If this field is omitted, then Serial and AKI must be specified. - Name string - // Serial number of the certificate to be revoked - // If this is omitted, then Name must be specified - Serial string - // AKI (Authority Key Identifier) of the certificate to be revoked - AKI string - // Reason is the reason for revocation. See https://godoc.org/golang.org/x/crypto/ocsp - // for valid values. The default value is 0 (ocsp.Unspecified). - Reason string - // CAName is the name of the CA to connect to - CAName string -} - -// Attribute defines additional attributes that may be passed along during registration -type Attribute struct { - Key string - Value string -} - // NewFabricCAClient ... /** * @param {string} clientConfigFile for fabric-ca services" */ -func NewFabricCAClient() (Services, error) { +func NewFabricCAClient(config sdkApi.Config) (sdkApi.Services, error) { // Create new Fabric-ca client without configs c := &fabric_ca.Client{ @@ -149,11 +94,11 @@ func (fabricCAServices *services) Enroll(enrollmentID string, enrollmentSecret s /** * ReEnroll an enrolled user in order to receive a signed X509 certificate - * @param {user} fabricclient.User to be reenrolled + * @param {user} User to be reenrolled * @returns {[]byte} X509 certificate * @returns {[]byte} private key */ -func (fabricCAServices *services) Reenroll(user fabricclient.User) (bccsp.Key, []byte, error) { +func (fabricCAServices *services) Reenroll(user sdkApi.User) (bccsp.Key, []byte, error) { if user == nil { return nil, nil, fmt.Errorf("User does not exist") } @@ -188,8 +133,8 @@ func (fabricCAServices *services) Reenroll(user fabricclient.User) (bccsp.Key, [ // @param {RegistrationRequest} request Registration Request // @returns {string} Enrolment Secret // @returns {error} Error -func (fabricCAServices *services) Register(registrar fabricclient.User, - request *RegistrationRequest) (string, error) { +func (fabricCAServices *services) Register(registrar sdkApi.User, + request *sdkApi.RegistrationRequest) (string, error) { // Validate registration request if request == nil { return "", fmt.Errorf("Registration request cannot be nil") @@ -226,8 +171,8 @@ func (fabricCAServices *services) Register(registrar fabricclient.User, // @param {User} registrar The User that is initiating the revocation // @param {RevocationRequest} request Revocation Request // @returns {error} Error -func (fabricCAServices *services) Revoke(registrar fabricclient.User, - request *RevocationRequest) error { +func (fabricCAServices *services) Revoke(registrar sdkApi.User, + request *sdkApi.RevocationRequest) error { // Validate revocation request if request == nil { return fmt.Errorf("Revocation request cannot be nil") @@ -248,7 +193,7 @@ func (fabricCAServices *services) Revoke(registrar fabricclient.User, } // createSigningIdentity creates an identity to sign Fabric CA requests with -func (fabricCAServices *services) createSigningIdentity(user fabricclient. +func (fabricCAServices *services) createSigningIdentity(user sdkApi. User) (*fabric_ca.Identity, error) { // Validate user if user == nil { diff --git a/fabric-ca-client/fabricca_test.go b/pkg/fabric-ca-client/fabricca_test.go similarity index 69% rename from fabric-ca-client/fabricca_test.go rename to pkg/fabric-ca-client/fabricca_test.go index 72d83cc25b..df400698ba 100644 --- a/fabric-ca-client/fabricca_test.go +++ b/pkg/fabric-ca-client/fabricca_test.go @@ -12,14 +12,17 @@ import ( "os" "testing" - "github.com/hyperledger/fabric-sdk-go/config" - "github.com/hyperledger/fabric-sdk-go/fabric-ca-client/mocks" - "github.com/hyperledger/fabric-sdk-go/fabric-client" + api "github.com/hyperledger/fabric-sdk-go/api" + + "github.com/hyperledger/fabric-sdk-go/pkg/fabric-ca-client/mocks" ) +var configImp api.Config + // Load testing config func TestMain(m *testing.M) { - err := config.InitConfig("../test/fixtures/config/config_test.yaml") + var err error + configImp = mocks.NewMockConfig() if err != nil { fmt.Println(err.Error()) } @@ -28,7 +31,7 @@ func TestMain(m *testing.M) { func TestEnrollWithMissingParameters(t *testing.T) { - fabricCAClient, err := NewFabricCAClient() + fabricCAClient, err := NewFabricCAClient(configImp) if err != nil { t.Fatalf("NewFabricCAClient return error: %v", err) } @@ -50,44 +53,44 @@ func TestEnrollWithMissingParameters(t *testing.T) { func TestRegister(t *testing.T) { - fabricCAClient, err := NewFabricCAClient() + fabricCAClient, err := NewFabricCAClient(configImp) if err != nil { t.Fatalf("NewFabricCAClient returned error: %v", err) } mockKey := &mocks.MockKey{} - user := fabricclient.NewUser("test") + user := mocks.NewMockUser("test") // Register with nil request _, err = fabricCAClient.Register(user, nil) if err == nil { t.Fatalf("Expected error with nil request") } //Register with nil user - _, err = fabricCAClient.Register(nil, &RegistrationRequest{}) + _, err = fabricCAClient.Register(nil, &api.RegistrationRequest{}) if err == nil { t.Fatalf("Expected error with nil user") } // Register with nil user cert and key - _, err = fabricCAClient.Register(user, &RegistrationRequest{}) + _, err = fabricCAClient.Register(user, &api.RegistrationRequest{}) if err == nil { t.Fatalf("Expected error without user enrolment information") } user.SetEnrollmentCertificate(readCert(t)) user.SetPrivateKey(mockKey) // Register without registration name parameter - _, err = fabricCAClient.Register(user, &RegistrationRequest{}) + _, err = fabricCAClient.Register(user, &api.RegistrationRequest{}) if err.Error() != "Error Registering User: Register was called without a Name set" { t.Fatalf("Expected error without registration information. Got: %s", err.Error()) } // Register without registration affiliation parameter - _, err = fabricCAClient.Register(user, &RegistrationRequest{Name: "test"}) + _, err = fabricCAClient.Register(user, &api.RegistrationRequest{Name: "test"}) if err.Error() != "Error Registering User: Registration request does not have an affiliation" { t.Fatalf("Expected error without registration information. Got: %s", err.Error()) } // Register with valid request - var attributes []Attribute - attributes = append(attributes, Attribute{Key: "test1", Value: "test2"}) - attributes = append(attributes, Attribute{Key: "test2", Value: "test3"}) - _, err = fabricCAClient.Register(user, &RegistrationRequest{Name: "test", + var attributes []api.Attribute + attributes = append(attributes, api.Attribute{Key: "test1", Value: "test2"}) + attributes = append(attributes, api.Attribute{Key: "test2", Value: "test3"}) + _, err = fabricCAClient.Register(user, &api.RegistrationRequest{Name: "test", Affiliation: "test", Attributes: attributes}) if err == nil { t.Fatalf("Expected PEM decoding error with test cert") @@ -96,25 +99,25 @@ func TestRegister(t *testing.T) { func TestRevoke(t *testing.T) { - fabricCAClient, err := NewFabricCAClient() + fabricCAClient, err := NewFabricCAClient(configImp) if err != nil { t.Fatalf("NewFabricCAClient returned error: %v", err) } mockKey := &mocks.MockKey{} - user := fabricclient.NewUser("test") + user := mocks.NewMockUser("test") // Revoke with nil request err = fabricCAClient.Revoke(user, nil) if err == nil { t.Fatalf("Expected error with nil request") } //Revoke with nil user - err = fabricCAClient.Revoke(nil, &RevocationRequest{}) + err = fabricCAClient.Revoke(nil, &api.RevocationRequest{}) if err == nil { t.Fatalf("Expected error with nil user") } user.SetEnrollmentCertificate(readCert(t)) user.SetPrivateKey(mockKey) - err = fabricCAClient.Revoke(user, &RevocationRequest{}) + err = fabricCAClient.Revoke(user, &api.RevocationRequest{}) if err == nil { t.Fatalf("Expected decoding error with test cert") } @@ -122,7 +125,7 @@ func TestRevoke(t *testing.T) { // Reads a random cert for testing func readCert(t *testing.T) []byte { - cert, err := ioutil.ReadFile("../test/fixtures/root.pem") + cert, err := ioutil.ReadFile("../../test/fixtures/root.pem") if err != nil { t.Fatalf("Error reading cert: %s", err.Error()) } diff --git a/pkg/fabric-ca-client/mocks/mockconfig.go b/pkg/fabric-ca-client/mocks/mockconfig.go new file mode 100644 index 0000000000..dc4548cb1f --- /dev/null +++ b/pkg/fabric-ca-client/mocks/mockconfig.go @@ -0,0 +1,152 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package mocks + +import ( + "crypto/x509" + + api "github.com/hyperledger/fabric-sdk-go/api" + + bccspFactory "github.com/hyperledger/fabric/bccsp/factory" + "github.com/spf13/viper" +) + +// MockConfig ... +type MockConfig struct { +} + +// NewMockConfig ... +func NewMockConfig() api.Config { + return &MockConfig{} +} + +//GetServerURL Read configuration option for the fabric CA server URL +func (c *MockConfig) GetServerURL() string { + return "" +} + +//GetServerCertFiles Read configuration option for the server certificate files +func (c *MockConfig) GetServerCertFiles() []string { + return nil +} + +//GetFabricCAClientKeyFile Read configuration option for the fabric CA client key file +func (c *MockConfig) GetFabricCAClientKeyFile() string { + return "" +} + +//GetFabricCAClientCertFile Read configuration option for the fabric CA client cert file +func (c *MockConfig) GetFabricCAClientCertFile() string { + return "" +} + +//GetFabricCATLSEnabledFlag Read configuration option for the fabric CA TLS flag +func (c *MockConfig) GetFabricCATLSEnabledFlag() bool { + return false +} + +// GetFabricClientViper returns the internal viper instance used by the +// SDK to read configuration options +func (c *MockConfig) GetFabricClientViper() *viper.Viper { + return nil +} + +// GetPeersConfig Retrieves the fabric peers from the config file provided +func (c *MockConfig) GetPeersConfig() ([]api.PeerConfig, error) { + return nil, nil +} + +// IsTLSEnabled ... +func (c *MockConfig) IsTLSEnabled() bool { + return false +} + +// GetTLSCACertPool ... +func (c *MockConfig) GetTLSCACertPool(tlsCertificate string) (*x509.CertPool, error) { + return nil, nil +} + +// GetTLSCACertPoolFromRoots ... +func (c *MockConfig) GetTLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) { + return nil, nil +} + +// IsSecurityEnabled ... +func (c *MockConfig) IsSecurityEnabled() bool { + return false +} + +// TcertBatchSize ... +func (c *MockConfig) TcertBatchSize() int { + return 0 +} + +// GetSecurityAlgorithm ... +func (c *MockConfig) GetSecurityAlgorithm() string { + return "" +} + +// GetSecurityLevel ... +func (c *MockConfig) GetSecurityLevel() int { + return 0 + +} + +// GetOrdererHost ... +func (c *MockConfig) GetOrdererHost() string { + return "" +} + +// GetOrdererPort ... +func (c *MockConfig) GetOrdererPort() string { + return "" +} + +// GetOrdererTLSServerHostOverride ... +func (c *MockConfig) GetOrdererTLSServerHostOverride() string { + return "" +} + +// GetOrdererTLSCertificate ... +func (c *MockConfig) GetOrdererTLSCertificate() string { + return "" +} + +// GetFabricCAID ... +func (c *MockConfig) GetFabricCAID() string { + return "" +} + +//GetFabricCAName Read the fabric CA name +func (c *MockConfig) GetFabricCAName() string { + return "" +} + +// GetKeyStorePath ... +func (c *MockConfig) GetKeyStorePath() string { + return "" +} + +// GetFabricCAHomeDir ... +func (c *MockConfig) GetFabricCAHomeDir() string { + return "" +} + +// GetFabricCAMspDir ... +func (c *MockConfig) GetFabricCAMspDir() string { + return "" +} + +// GetCryptoConfigPath ... +func (c *MockConfig) GetCryptoConfigPath() string { + return "" +} + +// GetCSPConfig ... +func (c *MockConfig) GetCSPConfig() *bccspFactory.FactoryOpts { + return nil +} diff --git a/fabric-ca-client/mocks/mockkey.go b/pkg/fabric-ca-client/mocks/mockkey.go similarity index 100% rename from fabric-ca-client/mocks/mockkey.go rename to pkg/fabric-ca-client/mocks/mockkey.go diff --git a/pkg/fabric-ca-client/mocks/mockuser.go b/pkg/fabric-ca-client/mocks/mockuser.go new file mode 100644 index 0000000000..5a41ddc793 --- /dev/null +++ b/pkg/fabric-ca-client/mocks/mockuser.go @@ -0,0 +1,101 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package mocks + +import ( + api "github.com/hyperledger/fabric-sdk-go/api" + "github.com/hyperledger/fabric/bccsp" +) + +// MockUser ... +type MockUser struct { + name string + roles []string + PrivateKey bccsp.Key // ****This key is temporary We use it to sign transaction until we have tcerts + enrollmentCertificate []byte +} + +// NewMockUser ... +/** + * Constructor for a user. + * + * @param {string} name - The user name + */ +func NewMockUser(name string) api.User { + return &MockUser{name: name} +} + +// GetName ... +/** + * Get the user name. + * @returns {string} The user name. + */ +func (u *MockUser) GetName() string { + return u.name +} + +// GetRoles ... +/** + * Get the roles. + * @returns {[]string} The roles. + */ +func (u *MockUser) GetRoles() []string { + return u.roles +} + +// SetRoles ... +/** + * Set the roles. + * @param roles {[]string} The roles. + */ +func (u *MockUser) SetRoles(roles []string) { + u.roles = roles +} + +// GetEnrollmentCertificate ... +/** + * Returns the underlying ECert representing this user’s identity. + */ +func (u *MockUser) GetEnrollmentCertificate() []byte { + return u.enrollmentCertificate +} + +// SetEnrollmentCertificate ... +/** + * Set the user’s Enrollment Certificate. + */ +func (u *MockUser) SetEnrollmentCertificate(cert []byte) { + u.enrollmentCertificate = cert +} + +// SetPrivateKey ... +/** + * deprecated. + */ +func (u *MockUser) SetPrivateKey(privateKey bccsp.Key) { + u.PrivateKey = privateKey +} + +// GetPrivateKey ... +/** + * deprecated. + */ +func (u *MockUser) GetPrivateKey() bccsp.Key { + return u.PrivateKey +} + +// GenerateTcerts ... +/** + * Gets a batch of TCerts to use for transaction. there is a 1-to-1 relationship between + * TCert and Transaction. The TCert can be generated locally by the SDK using the user’s crypto materials. + * @param {int} count how many in the batch to obtain + * @param {[]string} attributes list of attributes to include in the TCert + * @return {[]tcert} An array of TCerts + */ +func (u *MockUser) GenerateTcerts(count int, attributes []string) { + +} diff --git a/fabric-client/chain.go b/pkg/fabric-client/channel/channel.go similarity index 78% rename from fabric-client/chain.go rename to pkg/fabric-client/channel/channel.go index c414ee1c76..e8f4917df3 100644 --- a/fabric-client/chain.go +++ b/pkg/fabric-client/channel/channel.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package channel import ( "fmt" @@ -14,7 +14,9 @@ import ( "time" "github.com/golang/protobuf/proto" + api "github.com/hyperledger/fabric-sdk-go/api" "github.com/hyperledger/fabric/bccsp" + "github.com/hyperledger/fabric/msp" "github.com/hyperledger/fabric/protos/common" mspprotos "github.com/hyperledger/fabric/protos/msp" @@ -24,7 +26,8 @@ import ( "github.com/op/go-logging" proto_ts "github.com/golang/protobuf/ptypes/timestamp" - config "github.com/hyperledger/fabric-sdk-go/config" + fc "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal" + fabric_config "github.com/hyperledger/fabric/common/config" mb "github.com/hyperledger/fabric/protos/msp" ab "github.com/hyperledger/fabric/protos/orderer" @@ -32,151 +35,22 @@ import ( var logger = logging.MustGetLogger("fabric_sdk_go") -// Chain ... -/** - * Chain representing a chain with which the client SDK interacts. - * - * The “Chain” object captures settings for a channel, which is created by - * the orderers to isolate transactions delivery to peers participating on channel. - * A chain 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 Chain interface { - GetName() string - Initialize(data []byte) error - IsSecurityEnabled() bool - GetTCertBatchSize() int - SetTCertBatchSize(batchSize int) - AddPeer(peer Peer) error - RemovePeer(peer Peer) - GetPeers() []Peer - GetAnchorPeers() []OrgAnchorPeer - SetPrimaryPeer(peer Peer) error - GetPrimaryPeer() Peer - AddOrderer(orderer Orderer) error - RemoveOrderer(orderer Orderer) - GetOrderers() []Orderer - SetMSPManager(mspManager msp.MSPManager) - GetMSPManager() msp.MSPManager - GetGenesisBlock(request *GenesisBlockRequest) (*common.Block, error) - JoinChannel(request *JoinChannelRequest) ([]*TransactionProposalResponse, error) - UpdateChain() bool - IsReadonly() bool - QueryInfo() (*common.BlockchainInfo, error) - QueryBlock(blockNumber int) (*common.Block, error) - QueryBlockByHash(blockHash []byte) (*common.Block, error) - QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error) - QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error) - QueryByChaincode(chaincodeName string, args []string, targets []Peer) ([][]byte, error) - CreateTransactionProposal(chaincodeName string, chainID string, args []string, sign bool, transientData map[string][]byte) (*TransactionProposal, error) - SendTransactionProposal(proposal *TransactionProposal, retry int, targets []Peer) ([]*TransactionProposalResponse, error) - CreateTransaction(resps []*TransactionProposalResponse) (*Transaction, error) - SendTransaction(tx *Transaction) ([]*TransactionResponse, error) - SendInstantiateProposal(chaincodeName string, chainID string, args []string, chaincodePath string, chaincodeVersion string, targets []Peer) ([]*TransactionProposalResponse, string, error) - GetOrganizationUnits() ([]string, error) - QueryExtensionInterface() ChainExtension - LoadConfigUpdateEnvelope(data []byte) error -} - -// The ChainExtension interface allows extensions of the SDK to add functionality to Chain overloads. -type ChainExtension interface { - GetClientContext() Client - - SignPayload(payload []byte) (*SignedEnvelope, error) - BroadcastEnvelope(envelope *SignedEnvelope) ([]*TransactionResponse, error) - - // TODO: This should go somewhere else - see TransactionProposal.GetBytes(). - deprecated - GetProposalBytes(tp *TransactionProposal) ([]byte, error) -} - -type chain struct { - name string // Name of the chain is only meaningful to the client +type channel struct { + name string // Name of the channel is only meaningful to the client securityEnabled bool // Security enabled flag - peers map[string]Peer + peers map[string]api.Peer tcertBatchSize int // The number of tcerts to get in each batch - orderers map[string]Orderer - clientContext Client - primaryPeer Peer + orderers map[string]api.Orderer + clientContext api.FabricClient + primaryPeer api.Peer mspManager msp.MSPManager - anchorPeers []*OrgAnchorPeer -} - -// The TransactionProposal object to be send to the endorsers -type TransactionProposal struct { - TransactionID string - - SignedProposal *pb.SignedProposal - Proposal *pb.Proposal -} - -// GetBytes returns the serialized bytes of this proposal -func (tp *TransactionProposal) GetBytes() ([]byte, error) { - return proto.Marshal(tp.SignedProposal) -} - -// TransactionProposalResponse ... -/** - * The TransactionProposalResponse result object returned from endorsers. - */ -type TransactionProposalResponse struct { - Endorser string - Err error - Status int32 - - Proposal *TransactionProposal - ProposalResponse *pb.ProposalResponse -} - -// GetResponsePayload returns the response object payload -func (tpr *TransactionProposalResponse) GetResponsePayload() []byte { - if tpr == nil || tpr.ProposalResponse == nil { - return nil - } - return tpr.ProposalResponse.GetResponse().Payload -} - -// GetPayload returns the response payload -func (tpr *TransactionProposalResponse) GetPayload() []byte { - if tpr == nil || tpr.ProposalResponse == nil { - return nil - } - return tpr.ProposalResponse.Payload -} - -// The Transaction object created from an endorsed proposal -type Transaction struct { - proposal *TransactionProposal - transaction *pb.Transaction -} - -// TransactionResponse ... -/** - * The TransactionProposalResponse result object returned from orderers. - */ -type TransactionResponse struct { - Orderer string - Err error -} - -// GenesisBlockRequest ... -type GenesisBlockRequest struct { - TxID string - Nonce []byte -} - -// JoinChannelRequest allows a set of peers to transact on a channel on the network -type JoinChannelRequest struct { - Targets []Peer - GenesisBlock *common.Block - TxID string - Nonce []byte + anchorPeers []*api.OrgAnchorPeer } // configItems contains the configuration values retrieved from the Orderer Service type configItems struct { msps []*mb.MSPConfig - anchorPeers []*OrgAnchorPeer + anchorPeers []*api.OrgAnchorPeer orderers []string versions *versions } @@ -188,56 +62,49 @@ type versions struct { Channel *common.ConfigGroup } -// OrgAnchorPeer contains information about an anchor peer on this chain -type OrgAnchorPeer struct { - Org string - Host string - Port int32 -} - -// NewChain ... +// NewChannel ... /** -* @param {string} name to identify different chain instances. The naming of chain instances +* @param {string} name to identify different channel instances. The naming of channel instances * is enforced by the ordering service and must be unique within the blockchain network -* @param {Client} clientContext An instance of {@link Client} that provides operational context +* @param {FabricClient} clientContext An instance of {@link FabricClient} that provides operational context * such as submitting User etc. */ -func NewChain(name string, client Client) (Chain, error) { +func NewChannel(name string, client api.FabricClient) (api.Channel, error) { if name == "" { - return nil, fmt.Errorf("failed to create Chain. Missing required 'name' parameter") + return nil, fmt.Errorf("failed to create Channel. Missing required 'name' parameter") } if client == nil { - return nil, fmt.Errorf("failed to create Chain. Missing required 'clientContext' parameter") + return nil, fmt.Errorf("failed to create Channel. Missing required 'clientContext' parameter") } - p := make(map[string]Peer) - o := make(map[string]Orderer) - c := &chain{name: name, securityEnabled: config.IsSecurityEnabled(), peers: p, - tcertBatchSize: config.TcertBatchSize(), orderers: o, clientContext: client, mspManager: msp.NewMSPManager()} - logger.Infof("Constructed Chain instance: %v", c) + p := make(map[string]api.Peer) + o := make(map[string]api.Orderer) + c := &channel{name: name, securityEnabled: client.GetConfig().IsSecurityEnabled(), peers: p, + tcertBatchSize: client.GetConfig().TcertBatchSize(), orderers: o, clientContext: client, mspManager: msp.NewMSPManager()} + logger.Infof("Constructed channel instance: %v", c) return c, nil } -func (c *chain) QueryExtensionInterface() ChainExtension { +func (c *channel) QueryExtensionInterface() api.ChannelExtension { return c } -// GetClientContext returns the Client that was passed in to NewChain -func (c *chain) GetClientContext() Client { +// GetClientContext returns the Client that was passed in to NewChannel +func (c *channel) GetClientContext() api.FabricClient { return c.clientContext } // GetProposalBytes returns the serialized transaction. -func (c *chain) GetProposalBytes(tp *TransactionProposal) ([]byte, error) { +func (c *channel) GetProposalBytes(tp *api.TransactionProposal) ([]byte, error) { return proto.Marshal(tp.SignedProposal) } // GetName ... /** - * Get the chain name. - * @returns {string} The name of the chain. + * Get the channel name. + * @returns {string} The name of the channel. */ -func (c *chain) GetName() string { +func (c *channel) GetName() string { return c.name } @@ -245,7 +112,7 @@ func (c *chain) GetName() string { /** * Determine if security is enabled. */ -func (c *chain) IsSecurityEnabled() bool { +func (c *channel) IsSecurityEnabled() bool { return c.securityEnabled } @@ -253,7 +120,7 @@ func (c *chain) IsSecurityEnabled() bool { /** * Get the tcert batch size. */ -func (c *chain) GetTCertBatchSize() int { +func (c *channel) GetTCertBatchSize() int { return c.tcertBatchSize } @@ -261,18 +128,18 @@ func (c *chain) GetTCertBatchSize() int { /** * Set the tcert batch size. */ -func (c *chain) SetTCertBatchSize(batchSize int) { +func (c *channel) SetTCertBatchSize(batchSize int) { c.tcertBatchSize = batchSize } // AddPeer ... /** - * Add peer endpoint to chain. + * Add peer endpoint to channel. * @param {Peer} peer An instance of the Peer class that has been initialized with URL, * TLC certificate, and enrollment certificate. * @throws {Error} if the peer with that url already exists. */ -func (c *chain) AddPeer(peer Peer) error { +func (c *channel) AddPeer(peer api.Peer) error { url := peer.GetURL() if c.peers[url] != nil { return fmt.Errorf("Peer with URL %s already exists", url) @@ -283,10 +150,10 @@ func (c *chain) AddPeer(peer Peer) error { // RemovePeer ... /** - * Remove peer endpoint from chain. + * Remove peer endpoint from channel. * @param {Peer} peer An instance of the Peer. */ -func (c *chain) RemovePeer(peer Peer) { +func (c *channel) RemovePeer(peer api.Peer) { url := peer.GetURL() if c.peers[url] != nil { delete(c.peers, url) @@ -296,21 +163,21 @@ func (c *chain) RemovePeer(peer Peer) { // GetPeers ... /** - * Get peers of a chain from local information. - * @returns {[]Peer} The peer list on the chain. + * Get peers of a channel from local information. + * @returns {[]Peer} The peer list on the channel. */ -func (c *chain) GetPeers() []Peer { - var peersArray []Peer +func (c *channel) GetPeers() []api.Peer { + var peersArray []api.Peer for _, v := range c.peers { peersArray = append(peersArray, v) } return peersArray } -// GetAnchorPeers returns the anchor peers for this chain. -// Note: chain.Initialize() must be called first to retrieve anchor peers -func (c *chain) GetAnchorPeers() []OrgAnchorPeer { - anchors := []OrgAnchorPeer{} +// GetAnchorPeers returns the anchor peers for this channel. +// Note: channel.Initialize() must be called first to retrieve anchor peers +func (c *channel) GetAnchorPeers() []api.OrgAnchorPeer { + anchors := []api.OrgAnchorPeer{} for _, anchor := range c.anchorPeers { anchors = append(anchors, *anchor) } @@ -319,21 +186,21 @@ func (c *chain) GetAnchorPeers() []OrgAnchorPeer { } /** - * Utility function to get target peers (target peer is valid only if it belongs to chain's peer list). - * If targets is empty return chain's peer list + * Utility function to get target peers (target peer is valid only if it belongs to channel's peer list). + * If targets is empty return channel's peer list * @returns {[]Peer} The target peer list - * @returns {error} if target peer is not in chain's peer list + * @returns {error} if target peer is not in channel's peer list */ -func (c *chain) getTargetPeers(targets []Peer) ([]Peer, error) { +func (c *channel) getTargetPeers(targets []api.Peer) ([]api.Peer, error) { if targets == nil || len(targets) == 0 { return c.GetPeers(), nil } - var targetPeers []Peer + var targetPeers []api.Peer for _, target := range targets { if !c.isValidPeer(target) { - return nil, fmt.Errorf("The target peer must be on this chain peer list") + return nil, fmt.Errorf("The target peer must be on this channel peer list") } targetPeers = append(targetPeers, c.peers[target.GetURL()]) } @@ -342,10 +209,10 @@ func (c *chain) getTargetPeers(targets []Peer) ([]Peer, error) { } /** - * Utility function to ensure that a peer exists on this chain - * @returns {bool} true if peer exists on this chain + * Utility function to ensure that a peer exists on this channel + * @returns {bool} true if peer exists on this channel */ -func (c *chain) isValidPeer(peer Peer) bool { +func (c *channel) isValidPeer(peer api.Peer) bool { return peer != nil && c.peers[peer.GetURL()] != nil } @@ -353,16 +220,16 @@ func (c *chain) isValidPeer(peer Peer) bool { /** * Set the primary peer * The peer to use for doing queries. -* Peer must be a peer on this chain's peer list. +* Peer must be a peer on this channel's peer list. * Default: When no primary peer has been set the first peer * on the list will be used. * @param {Peer} peer An instance of the Peer class. * @returns error when peer is not on the existing peer list */ -func (c *chain) SetPrimaryPeer(peer Peer) error { +func (c *channel) SetPrimaryPeer(peer api.Peer) error { if !c.isValidPeer(peer) { - return fmt.Errorf("The primary peer must be on this chain peer list") + return fmt.Errorf("The primary peer must be on this channel peer list") } c.primaryPeer = c.peers[peer.GetURL()] @@ -377,7 +244,7 @@ func (c *chain) SetPrimaryPeer(peer Peer) error { * from map range will be used. * @returns {Peer} peer An instance of the Peer class. */ -func (c *chain) GetPrimaryPeer() Peer { +func (c *channel) GetPrimaryPeer() api.Peer { if c.primaryPeer != nil { return c.primaryPeer @@ -395,15 +262,15 @@ func (c *chain) GetPrimaryPeer() Peer { // AddOrderer ... /** - * Add orderer endpoint to a chain object, this is a local-only operation. - * A chain instance may choose to use a single orderer node, which will broadcast + * Add orderer endpoint to a channel object, this is a local-only operation. + * A channel instance may choose to use a single orderer node, which will broadcast * requests to the rest of the orderer network. Or if the application does not trust - * the orderer nodes, it can choose to use more than one by adding them to the chain instance. + * the orderer nodes, it can choose to use more than one by adding them to the channel instance. * All APIs concerning the orderer will broadcast to all orderers simultaneously. * @param {Orderer} orderer An instance of the Orderer class. * @throws {Error} if the orderer with that url already exists. */ -func (c *chain) AddOrderer(orderer Orderer) error { +func (c *channel) AddOrderer(orderer api.Orderer) error { url := orderer.GetURL() if c.orderers[url] != nil { return fmt.Errorf("Orderer with URL %s already exists", url) @@ -414,10 +281,10 @@ func (c *chain) AddOrderer(orderer Orderer) error { // RemoveOrderer ... /** - * Remove orderer endpoint from a chain object, this is a local-only operation. + * Remove orderer endpoint from a channel object, this is a local-only operation. * @param {Orderer} orderer An instance of the Orderer class. */ -func (c *chain) RemoveOrderer(orderer Orderer) { +func (c *channel) RemoveOrderer(orderer api.Orderer) { url := orderer.GetURL() if c.orderers[url] != nil { delete(c.orderers, url) @@ -427,10 +294,10 @@ func (c *chain) RemoveOrderer(orderer Orderer) { // GetOrderers ... /** - * Get orderers of a chain. + * Get orderers of a channel. */ -func (c *chain) GetOrderers() []Orderer { - var orderersArray []Orderer +func (c *channel) GetOrderers() []api.Orderer { + var orderersArray []api.Orderer for _, v := range c.orderers { orderersArray = append(orderersArray, v) } @@ -442,19 +309,19 @@ func (c *chain) GetOrderers() []Orderer { // "Initialize()" method will read this channel's // current configuration and reset the MSPManager with // the MSP's found. -func (c *chain) SetMSPManager(mspManager msp.MSPManager) { +func (c *channel) SetMSPManager(mspManager msp.MSPManager) { c.mspManager = mspManager } // GetMSPManager returns the MSP Manager for this channel -func (c *chain) GetMSPManager() msp.MSPManager { +func (c *channel) GetMSPManager() msp.MSPManager { return c.mspManager } // GetOrganizationUnits - to get identifier for the organization configured on the channel -func (c *chain) GetOrganizationUnits() ([]string, error) { - chainMSPManager := c.GetMSPManager() - msps, err := chainMSPManager.GetMSPs() +func (c *channel) GetOrganizationUnits() ([]string, error) { + channelMSPManager := c.GetMSPManager() + msps, err := channelMSPManager.GetMSPs() if err != nil { logger.Info("Cannot get channel manager") return nil, fmt.Errorf("Organization uits were not set: %v", err) @@ -481,7 +348,7 @@ func (c *chain) GetOrganizationUnits() ([]string, error) { * @returns A Genesis block * @see /protos/peer/proposal_response.proto */ -func (c *chain) GetGenesisBlock(request *GenesisBlockRequest) (*common.Block, error) { +func (c *channel) GetGenesisBlock(request *api.GenesisBlockRequest) (*common.Block, error) { logger.Debug("GetGenesisBlock - start") // verify that we have an orderer configured @@ -502,10 +369,10 @@ func (c *chain) GetGenesisBlock(request *GenesisBlockRequest) (*common.Block, er return nil, fmt.Errorf("Error getting creator: %v", err) } - // now build the seek info , will be used once the chain is created + // now build the seek info , will be used once the channel is created // to get the genesis block back - seekStart := NewSpecificSeekPosition(0) - seekStop := NewSpecificSeekPosition(0) + seekStart := fc.NewSpecificSeekPosition(0) + seekStop := fc.NewSpecificSeekPosition(0) seekInfo := &ab.SeekInfo{ Start: seekStart, Stop: seekStop, @@ -516,15 +383,15 @@ func (c *chain) GetGenesisBlock(request *GenesisBlockRequest) (*common.Block, er if err != nil { return nil, fmt.Errorf("Error building channel header: %v", err) } - seekHeader, err := BuildHeader(creator, seekInfoHeader, request.Nonce) + seekHeader, err := fc.BuildHeader(creator, seekInfoHeader, request.Nonce) if err != nil { return nil, fmt.Errorf("Error building header: %v", err) } seekPayload := &common.Payload{ Header: seekHeader, - Data: MarshalOrPanic(seekInfo), + Data: fc.MarshalOrPanic(seekInfo), } - seekPayloadBytes := MarshalOrPanic(seekPayload) + seekPayloadBytes := fc.MarshalOrPanic(seekPayload) signedEnvelope, err := c.SignPayload(seekPayloadBytes) if err != nil { @@ -553,7 +420,7 @@ func (c *chain) GetGenesisBlock(request *GenesisBlockRequest) (*common.Block, er * @returns {Promise} A Promise for a `ProposalResponse` * @see /protos/peer/proposal_response.proto */ -func (c *chain) JoinChannel(request *JoinChannelRequest) ([]*TransactionProposalResponse, error) { +func (c *channel) JoinChannel(request *api.JoinChannelRequest) ([]*api.TransactionProposalResponse, error) { logger.Debug("joinChannel - start") // verify that we have targets (Peers) to join this channel @@ -613,7 +480,7 @@ func (c *chain) JoinChannel(request *JoinChannelRequest) ([]*TransactionProposal if err != nil { return nil, fmt.Errorf("Error signing proposal: %v", err) } - transactionProposal := &TransactionProposal{ + transactionProposal := &api.TransactionProposal{ TransactionID: txID, SignedProposal: signedProposal, Proposal: proposal, @@ -628,24 +495,24 @@ func (c *chain) JoinChannel(request *JoinChannelRequest) ([]*TransactionProposal } /** - * Queries for the current config block for this chain(channel). + * 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 *chain) getChannelConfig() (*common.ConfigEnvelope, error) { +func (c *channel) getChannelConfig() (*common.ConfigEnvelope, error) { logger.Debugf("getChannelConfig - start for channel %s", c.name) // Get the newest block - block, err := c.getBlock(NewNewestSeekPosition()) + block, err := c.getBlock(fc.NewNewestSeekPosition()) if err != nil { return nil, err } logger.Debugf("GetChannelConfig - Retrieved newest block number: %d\n", block.Header.Number) // Get the index of the last config block - lastConfig, err := GetLastConfigFromBlock(block) + lastConfig, err := fc.GetLastConfigFromBlock(block) if err != nil { return nil, fmt.Errorf("Unable to get last config from block: %v", err) } @@ -653,7 +520,7 @@ func (c *chain) getChannelConfig() (*common.ConfigEnvelope, error) { // Get the last config block //block, err = c.getBlock(NewSpecificSeekPosition(lastConfig.Index)) - block, err = c.getBlock(NewSpecificSeekPosition(0)) //FIXME: temporary hack to workaround https://jira.hyperledger.org/browse/FAB-3493 + block, err = c.getBlock(fc.NewSpecificSeekPosition(0)) //FIXME: temporary hack to workaround https://jira.hyperledger.org/browse/FAB-3493 if err != nil { return nil, fmt.Errorf("Unable to retrieve block at index %d: %v", lastConfig.Index, err) } @@ -687,12 +554,12 @@ func (c *chain) getChannelConfig() (*common.ConfigEnvelope, error) { // LoadConfigUpdateEnvelope ... /* - * Utility method to load this chain with configuration information + * Utility method to load this channel with configuration information * from an Envelope that contains a Configuration * @param {byte[]} the envelope with the configuration update items * @see /protos/common/configtx.proto */ -func (c *chain) LoadConfigUpdateEnvelope(data []byte) error { +func (c *channel) LoadConfigUpdateEnvelope(data []byte) error { logger.Debugf("loadConfigUpdateEnvelope - start") envelope := &common.Envelope{} @@ -724,7 +591,7 @@ func (c *chain) LoadConfigUpdateEnvelope(data []byte) error { return err } -func (c *chain) loadConfigUpdate(configUpdateBytes []byte) (*configItems, error) { +func (c *channel) loadConfigUpdate(configUpdateBytes []byte) (*configItems, error) { configUpdate := &common.ConfigUpdate{} if err := proto.Unmarshal(configUpdateBytes, configUpdate); err != nil { @@ -742,7 +609,7 @@ func (c *chain) loadConfigUpdate(configUpdateBytes []byte) (*configItems, error) configItems := &configItems{ msps: []*mb.MSPConfig{}, - anchorPeers: []*OrgAnchorPeer{}, + anchorPeers: []*api.OrgAnchorPeer{}, orderers: []string{}, versions: versions, } @@ -758,14 +625,14 @@ func (c *chain) loadConfigUpdate(configUpdateBytes []byte) (*configItems, error) } err = c.initializeFromConfig(configItems) if err != nil { - return nil, fmt.Errorf("chain initialization errort: %v", err) + return nil, fmt.Errorf("channel initialization errort: %v", err) } //TODO should we create orderers and endorsing peers return configItems, nil } -func (c *chain) loadConfigEnvelope(configEnvelope *common.ConfigEnvelope) (*configItems, error) { +func (c *channel) loadConfigEnvelope(configEnvelope *common.ConfigEnvelope) (*configItems, error) { group := configEnvelope.Config.ChannelGroup @@ -775,7 +642,7 @@ func (c *chain) loadConfigEnvelope(configEnvelope *common.ConfigEnvelope) (*conf configItems := &configItems{ msps: []*mb.MSPConfig{}, - anchorPeers: []*OrgAnchorPeer{}, + anchorPeers: []*api.OrgAnchorPeer{}, orderers: []string{}, versions: versions, } @@ -787,41 +654,41 @@ func (c *chain) loadConfigEnvelope(configEnvelope *common.ConfigEnvelope) (*conf err = c.initializeFromConfig(configItems) - logger.Debugf("Chain config: %v", configItems) + logger.Debugf("channel config: %v", configItems) return configItems, err } -// UpdateChain ... +// UpdateChannel ... /** - * Calls the orderer(s) to update an existing chain. This allows the addition and - * deletion of Peer nodes to an existing chain, as well as the update of Peer + * Calls the orderer(s) to update an existing channel. This allows the addition and + * deletion of Peer nodes to an existing channel, as well as the update of Peer * certificate information upon certificate renewals. - * @returns {bool} Whether the chain update process was successful. + * @returns {bool} Whether the channel update process was successful. */ -func (c *chain) UpdateChain() bool { +func (c *channel) UpdateChannel() bool { return false } // IsReadonly ... /** - * Get chain status to see if the underlying channel has been terminated, - * making it a read-only chain, where information (transactions and states) + * Get channel status to see if the underlying channel has been terminated, + * making it a read-only channel, where information (transactions and states) * can be queried but no new transactions can be submitted. * @returns {bool} Is read-only, true or not. */ -func (c *chain) IsReadonly() bool { +func (c *channel) IsReadonly() bool { return false //to do } // QueryInfo ... /** - * Queries for various useful information on the state of the Chain + * Queries for various useful information on the state of the channel * (height, known peers). * This query will be made to the primary peer. * @returns {object} With height, currently the only useful info. */ -func (c *chain) QueryInfo() (*common.BlockchainInfo, error) { +func (c *channel) QueryInfo() (*common.BlockchainInfo, error) { logger.Debug("queryInfo - start") // prepare arguments to call qscc GetChainInfo function @@ -850,7 +717,7 @@ func (c *chain) QueryInfo() (*common.BlockchainInfo, error) { * @param {byte[]} block hash of the Block. * @returns {object} Object containing the block. */ -func (c *chain) QueryBlockByHash(blockHash []byte) (*common.Block, error) { +func (c *channel) QueryBlockByHash(blockHash []byte) (*common.Block, error) { if blockHash == nil { return nil, fmt.Errorf("Blockhash bytes are required") @@ -883,7 +750,7 @@ func (c *chain) QueryBlockByHash(blockHash []byte) (*common.Block, error) { * @param {int} blockNumber The number which is the ID of the Block. * @returns {object} Object containing the block. */ -func (c *chain) QueryBlock(blockNumber int) (*common.Block, error) { +func (c *channel) QueryBlock(blockNumber int) (*common.Block, error) { if blockNumber < 0 { return nil, fmt.Errorf("Block number must be positive integer") @@ -909,14 +776,14 @@ func (c *chain) QueryBlock(blockNumber int) (*common.Block, error) { return block, nil } -// Initialize initializes the chain +// Initialize initializes the channel /** - * Retrieve the configuration from the primary orderer and initializes this chain (channel) + * Retrieve the configuration from the primary orderer and initializes this channel * with those values. Optionally a configuration may be passed in to initialize this channel * without making the call to the orderer. * @param {byte[]} config_update- Optional - A serialized form of the protobuf configuration update */ -func (c *chain) Initialize(configUpdate []byte) error { +func (c *channel) Initialize(configUpdate []byte) error { if len(configUpdate) > 0 { var err error @@ -945,7 +812,7 @@ func (c *chain) Initialize(configUpdate []byte) error { * @param {int} transactionID * @returns {object} ProcessedTransaction information containing the transaction. */ -func (c *chain) QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error) { +func (c *channel) QueryTransaction(transactionID string) (*pb.ProcessedTransaction, error) { // prepare arguments to call qscc GetTransactionByID function var args []string @@ -973,7 +840,7 @@ func (c *chain) QueryTransaction(transactionID string) (*pb.ProcessedTransaction * This query will be made to the primary peer. * @returns {object} ChaincodeQueryResponse proto */ -func (c *chain) QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error) { +func (c *channel) QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error) { payload, err := c.queryByChaincodeByTarget("lscc", []string{"getchaincodes"}, c.GetPrimaryPeer()) if err != nil { @@ -997,9 +864,9 @@ func (c *chain) QueryInstantiatedChaincodes() (*pb.ChaincodeQueryResponse, error * @param {Peer} target peer * @returns {[]byte} payload */ -func (c *chain) queryByChaincodeByTarget(chaincodeName string, args []string, target Peer) ([]byte, error) { +func (c *channel) queryByChaincodeByTarget(chaincodeName string, args []string, target api.Peer) ([]byte, error) { - queryResponses, err := c.QueryByChaincode(chaincodeName, args, []Peer{target}) + queryResponses, err := c.QueryByChaincode(chaincodeName, args, []api.Peer{target}) if err != nil { return nil, fmt.Errorf("QueryByChaincode return error: %v", err) } @@ -1023,9 +890,10 @@ func (c *chain) queryByChaincodeByTarget(chaincodeName string, args []string, ta * @parame {string} chaincode name * @param {[]string} invoke arguments * @param {[]Peer} target peers + * @param {FabricClient} fabric client * @returns {[][]byte} an array of payloads */ -func QueryByChaincode(chaincodeName string, args []string, targets []Peer, clientContext Client) ([][]byte, error) { +func QueryByChaincode(chaincodeName string, args []string, targets []api.Peer, clientContext api.FabricClient) ([][]byte, error) { if chaincodeName == "" { return nil, fmt.Errorf("Missing chaincode name") } @@ -1056,7 +924,7 @@ func QueryByChaincode(chaincodeName string, args []string, targets []Peer, clien if response.Err != nil { errMsg = errMsg + response.Err.Error() + "\n" } else { - responses = append(responses, response.GetResponsePayload()) + responses = append(responses, response.ProposalResponse.GetResponse().Payload) } } @@ -1067,7 +935,7 @@ func QueryByChaincode(chaincodeName string, args []string, targets []Peer, clien return responses, nil } -func (c *chain) QueryByChaincode(chaincodeName string, args []string, targets []Peer) ([][]byte, error) { +func (c *channel) QueryByChaincode(chaincodeName string, args []string, targets []api.Peer) ([][]byte, error) { return QueryByChaincode(chaincodeName, args, targets, c.clientContext) } @@ -1077,14 +945,14 @@ func (c *chain) QueryByChaincode(chaincodeName string, args []string, targets [] * with the data (chaincodeName, function to call, arguments, transient data, etc.) and signing it using the private key corresponding to the * ECert to sign. */ -func (c *chain) CreateTransactionProposal(chaincodeName string, chainID string, - args []string, sign bool, transientData map[string][]byte) (*TransactionProposal, error) { - return CreateTransactionProposal(chaincodeName, chainID, args, sign, transientData, c.clientContext) +func (c *channel) CreateTransactionProposal(chaincodeName string, channelID string, + args []string, sign bool, transientData map[string][]byte) (*api.TransactionProposal, error) { + return CreateTransactionProposal(chaincodeName, channelID, args, sign, transientData, c.clientContext) } //CreateTransactionProposal ... -func CreateTransactionProposal(chaincodeName string, chainID string, - args []string, sign bool, transientData map[string][]byte, clientContext Client) (*TransactionProposal, error) { +func CreateTransactionProposal(chaincodeName string, channelID string, + args []string, sign bool, transientData map[string][]byte, clientContext api.FabricClient) (*api.TransactionProposal, error) { argsArray := make([][]byte, len(args)) for i, arg := range args { @@ -1100,7 +968,7 @@ func CreateTransactionProposal(chaincodeName string, chainID string, } // create a proposal from a ChaincodeInvocationSpec - proposal, txID, err := protos_utils.CreateChaincodeProposalWithTransient(common.HeaderType_ENDORSER_TRANSACTION, chainID, ccis, creator, transientData) + proposal, txID, err := protos_utils.CreateChaincodeProposalWithTransient(common.HeaderType_ENDORSER_TRANSACTION, channelID, ccis, creator, transientData) if err != nil { return nil, fmt.Errorf("Could not create chaincode proposal, err %s", err) } @@ -1115,13 +983,13 @@ func CreateTransactionProposal(chaincodeName string, chainID string, return nil, fmt.Errorf("Error loading user from store: %s", err) } - signature, err := SignObjectWithKey(proposalBytes, user.GetPrivateKey(), + signature, err := fc.SignObjectWithKey(proposalBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, clientContext.GetCryptoSuite()) if err != nil { return nil, err } signedProposal := &pb.SignedProposal{ProposalBytes: proposalBytes, Signature: signature} - return &TransactionProposal{ + return &api.TransactionProposal{ TransactionID: txID, SignedProposal: signedProposal, Proposal: proposal, @@ -1131,7 +999,7 @@ func CreateTransactionProposal(chaincodeName string, chainID string, // SendTransactionProposal ... // Send the created proposal to peer for endorsement. -func (c *chain) SendTransactionProposal(proposal *TransactionProposal, retry int, targets []Peer) ([]*TransactionProposalResponse, error) { +func (c *channel) SendTransactionProposal(proposal *api.TransactionProposal, retry int, targets []api.Peer) ([]*api.TransactionProposalResponse, error) { if c.peers == nil || len(c.peers) == 0 { return nil, fmt.Errorf("peers is nil") } @@ -1152,7 +1020,7 @@ func (c *chain) SendTransactionProposal(proposal *TransactionProposal, retry int } //SendTransactionProposal ... -func SendTransactionProposal(proposal *TransactionProposal, retry int, targetPeers []Peer) ([]*TransactionProposalResponse, error) { +func SendTransactionProposal(proposal *api.TransactionProposal, retry int, targetPeers []api.Peer) ([]*api.TransactionProposalResponse, error) { if proposal == nil || proposal.SignedProposal == nil { return nil, fmt.Errorf("signedProposal is nil") @@ -1163,19 +1031,19 @@ func SendTransactionProposal(proposal *TransactionProposal, retry int, targetPee } var responseMtx sync.Mutex - var transactionProposalResponses []*TransactionProposalResponse + var transactionProposalResponses []*api.TransactionProposalResponse var wg sync.WaitGroup for _, p := range targetPeers { wg.Add(1) - go func(peer Peer) { + go func(peer api.Peer) { defer wg.Done() var err error - var proposalResponse *TransactionProposalResponse + var proposalResponse *api.TransactionProposalResponse logger.Debugf("Send ProposalRequest to peer :%s", peer.GetURL()) if proposalResponse, err = peer.SendProposal(proposal); err != nil { logger.Debugf("Receive Error Response :%v", proposalResponse) - proposalResponse = &TransactionProposalResponse{ + proposalResponse = &api.TransactionProposalResponse{ Endorser: peer.GetURL(), Err: fmt.Errorf("Error calling endorser '%s': %s", peer.GetURL(), err), Proposal: proposal, @@ -1197,7 +1065,7 @@ func SendTransactionProposal(proposal *TransactionProposal, retry int, targetPee /** * Create a transaction with proposal response, following the endorsement policy. */ -func (c *chain) CreateTransaction(resps []*TransactionProposalResponse) (*Transaction, error) { +func (c *channel) CreateTransaction(resps []*api.TransactionProposalResponse) (*api.Transaction, error) { if len(resps) == 0 { return nil, fmt.Errorf("At least one proposal response is necessary") } @@ -1272,9 +1140,9 @@ func (c *chain) CreateTransaction(resps []*TransactionProposalResponse) (*Transa taas := make([]*pb.TransactionAction, 1) taas[0] = taa - return &Transaction{ - transaction: &pb.Transaction{Actions: taas}, - proposal: proposal, + return &api.Transaction{ + Transaction: &pb.Transaction{Actions: taas}, + Proposal: proposal, }, nil } @@ -1291,23 +1159,23 @@ func (c *chain) CreateTransaction(resps []*TransactionProposalResponse) (*Transa * internal event hub mechanism in order to support the fabric events “BLOCK”, “CHAINCODE” and “TRANSACTION”. * These events should cause the method to emit “complete” or “error” events to the application. */ -func (c *chain) SendTransaction(tx *Transaction) ([]*TransactionResponse, error) { +func (c *channel) SendTransaction(tx *api.Transaction) ([]*api.TransactionResponse, error) { if c.orderers == nil || len(c.orderers) == 0 { return nil, fmt.Errorf("orderers is nil") } - if tx == nil || tx.proposal == nil || tx.proposal.Proposal == nil { + if tx == nil || tx.Proposal == nil || tx.Proposal.Proposal == nil { return nil, fmt.Errorf("proposal is nil") } if tx == nil { return nil, fmt.Errorf("Transaction is nil") } // the original header - hdr, err := protos_utils.GetHeader(tx.proposal.Proposal.Header) + hdr, err := protos_utils.GetHeader(tx.Proposal.Proposal.Header) if err != nil { return nil, fmt.Errorf("Could not unmarshal the proposal header") } // serialize the tx - txBytes, err := protos_utils.GetBytesTransaction(tx.transaction) + txBytes, err := protos_utils.GetBytesTransaction(tx.Transaction) if err != nil { return nil, err } @@ -1337,19 +1205,19 @@ func (c *chain) SendTransaction(tx *Transaction) ([]*TransactionResponse, error) /** * Sends an instantiate proposal to one or more endorsing peers. * @param {string} chaincodeName: required - The name of the chain. -* @param {string} chainID: required - string of the name of the chain +* @param {string} channelID: required - string of the name of the channel * @param {[]string} args: optional - string Array arguments specific to the chaincode being instantiated * @param {[]string} chaincodePath: required - string of the path to the location of the source code of the chaincode * @param {[]string} chaincodeVersion: required - string of the version of the chaincode */ -func (c *chain) SendInstantiateProposal(chaincodeName string, chainID string, - args []string, chaincodePath string, chaincodeVersion string, targets []Peer) ([]*TransactionProposalResponse, string, error) { +func (c *channel) SendInstantiateProposal(chaincodeName string, channelID string, + args []string, chaincodePath string, chaincodeVersion string, targets []api.Peer) ([]*api.TransactionProposalResponse, string, error) { if chaincodeName == "" { return nil, "", fmt.Errorf("Missing 'chaincodeName' parameter") } - if chainID == "" { - return nil, "", fmt.Errorf("Missing 'chainID' parameter") + if channelID == "" { + return nil, "", fmt.Errorf("Missing 'channelID' parameter") } if chaincodePath == "" { return nil, "", fmt.Errorf("Missing 'chaincodePath' parameter") @@ -1381,7 +1249,7 @@ func (c *chain) SendInstantiateProposal(chaincodeName string, chainID string, if err != nil { return nil, "", fmt.Errorf("Error getting creator: %v", err) } - chaincodePolicy, err := buildChaincodePolicy(config.GetFabricCAID()) + chaincodePolicy, err := buildChaincodePolicy(c.GetClientContext().GetConfig().GetFabricCAID()) if err != nil { return nil, "", err } @@ -1390,7 +1258,7 @@ func (c *chain) SendInstantiateProposal(chaincodeName string, chainID string, return nil, "", err } // create a proposal from a chaincodeDeploymentSpec - proposal, txID, err := protos_utils.CreateDeployProposalFromCDS(chainID, ccds, creator, chaincodePolicyBytes, []byte("escc"), []byte("vscc")) + proposal, txID, err := protos_utils.CreateDeployProposalFromCDS(channelID, ccds, creator, chaincodePolicyBytes, []byte("escc"), []byte("vscc")) if err != nil { return nil, "", fmt.Errorf("Could not create chaincode Deploy proposal, err %s", err) } @@ -1400,7 +1268,7 @@ func (c *chain) SendInstantiateProposal(chaincodeName string, chainID string, return nil, "", err } - transactionProposalResponse, err := c.SendTransactionProposal(&TransactionProposal{ + transactionProposalResponse, err := c.SendTransactionProposal(&api.TransactionProposal{ SignedProposal: signedProposal, Proposal: proposal, TransactionID: txID, @@ -1409,47 +1277,47 @@ func (c *chain) SendInstantiateProposal(chaincodeName string, chainID string, return transactionProposalResponse, txID, err } -func (c *chain) SignPayload(payload []byte) (*SignedEnvelope, error) { +func (c *channel) SignPayload(payload []byte) (*api.SignedEnvelope, error) { //Get user info user, err := c.clientContext.LoadUserFromStateStore("") if err != nil { return nil, fmt.Errorf("LoadUserFromStateStore returned error: %s", err) } - signature, err := SignObjectWithKey(payload, user.GetPrivateKey(), + signature, err := fc.SignObjectWithKey(payload, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.clientContext.GetCryptoSuite()) if err != nil { return nil, err } // here's the envelope - return &SignedEnvelope{Payload: payload, Signature: signature}, nil + return &api.SignedEnvelope{Payload: payload, Signature: signature}, nil } //broadcastEnvelope will send the given envelope to each orderer -func (c *chain) BroadcastEnvelope(envelope *SignedEnvelope) ([]*TransactionResponse, error) { +func (c *channel) BroadcastEnvelope(envelope *api.SignedEnvelope) ([]*api.TransactionResponse, error) { // Check if orderers are defined if c.orderers == nil || len(c.orderers) == 0 { return nil, fmt.Errorf("orderers not set") } var responseMtx sync.Mutex - var transactionResponses []*TransactionResponse + var transactionResponses []*api.TransactionResponse var wg sync.WaitGroup for _, o := range c.orderers { wg.Add(1) - go func(orderer Orderer) { + go func(orderer api.Orderer) { defer wg.Done() - var transactionResponse *TransactionResponse + var transactionResponse *api.TransactionResponse logger.Debugf("Broadcasting envelope to orderer :%s\n", orderer.GetURL()) if _, err := orderer.SendBroadcast(envelope); err != nil { logger.Debugf("Receive Error Response from orderer :%v\n", err) - transactionResponse = &TransactionResponse{orderer.GetURL(), - fmt.Errorf("Error calling orderer '%s': %s", orderer.GetURL(), err)} + transactionResponse = &api.TransactionResponse{Orderer: orderer.GetURL(), + Err: fmt.Errorf("Error calling orderer '%s': %s", orderer.GetURL(), err)} } else { logger.Debugf("Receive Success Response from orderer\n") - transactionResponse = &TransactionResponse{orderer.GetURL(), nil} + transactionResponse = &api.TransactionResponse{Orderer: orderer.GetURL(), Err: nil} } responseMtx.Lock() @@ -1463,7 +1331,7 @@ func (c *chain) BroadcastEnvelope(envelope *SignedEnvelope) ([]*TransactionRespo } // SendEnvelope sends the given envelope to each orderer and returns a block response -func (c *chain) SendEnvelope(envelope *SignedEnvelope) (*common.Block, error) { +func (c *channel) SendEnvelope(envelope *api.SignedEnvelope) (*common.Block, error) { if c.orderers == nil || len(c.orderers) == 0 { return nil, fmt.Errorf("orderers not set") } @@ -1476,7 +1344,7 @@ func (c *chain) SendEnvelope(envelope *SignedEnvelope) (*common.Block, error) { // Send the request to all orderers and return as soon as one responds with a block. for _, o := range c.orderers { - go func(orderer Orderer) { + go func(orderer api.Orderer) { logger.Debugf("Broadcasting envelope to orderer :%s\n", orderer.GetURL()) blocks, errors := orderer.SendDeliver(envelope) select { @@ -1527,7 +1395,7 @@ func (c *chain) SendEnvelope(envelope *SignedEnvelope) (*common.Block, error) { return nil, fmt.Errorf("unexpected: didn't receive a block from any of the orderer servces and didn't receive any error") } -func (c *chain) signProposal(proposal *pb.Proposal) (*pb.SignedProposal, error) { +func (c *channel) signProposal(proposal *pb.Proposal) (*pb.SignedProposal, error) { user, err := c.clientContext.LoadUserFromStateStore("") if err != nil { return nil, fmt.Errorf("LoadUserFromStateStore return error: %s", err) @@ -1538,7 +1406,7 @@ func (c *chain) signProposal(proposal *pb.Proposal) (*pb.SignedProposal, error) return nil, fmt.Errorf("Error mashalling proposal: %s", err) } - signature, err := SignObjectWithKey(proposalBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.clientContext.GetCryptoSuite()) + signature, err := fc.SignObjectWithKey(proposalBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.clientContext.GetCryptoSuite()) if err != nil { return nil, fmt.Errorf("Error signing proposal: %s", err) } @@ -1547,14 +1415,14 @@ func (c *chain) signProposal(proposal *pb.Proposal) (*pb.SignedProposal, error) } // fetchGenesisBlock fetches the configuration block for this channel -func (c *chain) fetchGenesisBlock() (*common.Block, error) { +func (c *channel) fetchGenesisBlock() (*common.Block, error) { // Get user enrolment info and serialize for signing requests creator, err := c.clientContext.GetIdentity() if err != nil { return nil, fmt.Errorf("Error getting creator: %v", err) } // Seek block zero (the configuration tx for this channel) - payload := CreateSeekGenesisBlockRequest(c.name, creator) + payload := fc.CreateSeekGenesisBlockRequest(c.name, creator) blockRequest, err := c.SignPayload(payload) if err != nil { return nil, fmt.Errorf("Error signing payload: %s", err) @@ -1668,7 +1536,7 @@ func loadConfigValue(configItems *configItems, key string, versionsValue *common if len(anchorPeers.AnchorPeers) > 0 { for _, anchorPeer := range anchorPeers.AnchorPeers { - oap := &OrgAnchorPeer{Org: org, Host: anchorPeer.Host, Port: anchorPeer.Port} + oap := &api.OrgAnchorPeer{Org: org, Host: anchorPeer.Host, Port: anchorPeer.Port} configItems.anchorPeers = append(configItems.anchorPeers, oap) logger.Debugf("loadConfigValue - %s - AnchorPeer :: %s:%d:%s", groupName, oap.Host, oap.Port, oap.Org) } @@ -1832,8 +1700,8 @@ func loadPolicy(configItems *configItems, versionsPolicy *common.ConfigPolicy, k } // getBlock retrieves the block at the given position -func (c *chain) getBlock(pos *ab.SeekPosition) (*common.Block, error) { - nonce, err := GenerateRandomNonce() +func (c *channel) getBlock(pos *ab.SeekPosition) (*common.Block, error) { + nonce, err := fc.GenerateRandomNonce() if err != nil { return nil, fmt.Errorf("error when generating nonce: %v", err) } @@ -1902,7 +1770,7 @@ func (c *chain) getBlock(pos *ab.SeekPosition) (*common.Block, error) { return c.SendEnvelope(signedEnvelope) } -func (c *chain) initializeFromConfig(configItems *configItems) error { +func (c *channel) initializeFromConfig(configItems *configItems) error { // TODO revisit this if if len(configItems.msps) > 0 { msps, err := c.loadMSPs(configItems.msps) @@ -1920,7 +1788,7 @@ func (c *chain) initializeFromConfig(configItems *configItems) error { return nil } -func (c *chain) loadMSPs(mspConfigs []*mb.MSPConfig) ([]msp.MSP, error) { +func (c *channel) loadMSPs(mspConfigs []*mb.MSPConfig) ([]msp.MSP, error) { logger.Debugf("loadMSPs - start number of msps=%d", len(mspConfigs)) msps := []msp.MSP{} @@ -1980,12 +1848,12 @@ func (c *chain) loadMSPs(mspConfigs []*mb.MSPConfig) ([]msp.MSP, error) { } // BuildChannelHeader is a utility method to build a common chain header -func BuildChannelHeader(headerType common.HeaderType, chainID string, txID string, epoch uint64, chaincodeID string, timestamp time.Time) (*common.ChannelHeader, error) { - logger.Debugf("buildChannelHeader - headerType: %s chainID: %s txID: %d epoch: % chaincodeID: %s timestamp: %v", headerType, chainID, txID, epoch, chaincodeID, timestamp) +func BuildChannelHeader(headerType common.HeaderType, channelID string, txID string, epoch uint64, chaincodeID string, timestamp time.Time) (*common.ChannelHeader, error) { + logger.Debugf("buildChannelHeader - headerType: %s channelID: %s txID: %d epoch: % chaincodeID: %s timestamp: %v", headerType, channelID, txID, epoch, chaincodeID, timestamp) channelHeader := &common.ChannelHeader{ Type: int32(headerType), Version: 1, - ChannelId: chainID, + ChannelId: channelID, TxId: txID, Epoch: epoch, } diff --git a/fabric-client/chain_test.go b/pkg/fabric-client/channel/channel_test.go similarity index 54% rename from fabric-client/chain_test.go rename to pkg/fabric-client/channel/channel_test.go index 26284c4415..03b9a5cd89 100644 --- a/fabric-client/chain_test.go +++ b/pkg/fabric-client/channel/channel_test.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package channel import ( "fmt" @@ -13,6 +13,11 @@ import ( "google.golang.org/grpc" + api "github.com/hyperledger/fabric-sdk-go/api" + fc "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal" + mocks "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks" + peer "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/peer" + pb "github.com/hyperledger/fabric/protos/peer" ) @@ -35,97 +40,97 @@ oG5kQQIgQAe4OOKYhJdh3f7URaKfGTf492/nmRmtK+ySKjpHSrU= -----END CERTIFICATE----- ` -func TestChainMethods(t *testing.T) { - client := NewClient() - chain, err := NewChain("testChain", client) +func TestChannelMethods(t *testing.T) { + client := mocks.NewMockClient() + channel, err := NewChannel("testChannel", client) if err != nil { - t.Fatalf("NewChain return error[%s]", err) + t.Fatalf("NewChannel return error[%s]", err) } - if chain.GetName() != "testChain" { - t.Fatalf("NewChain create wrong chain") + if channel.GetName() != "testChannel" { + t.Fatalf("NewChannel create wrong channel") } - _, err = NewChain("", client) + _, err = NewChannel("", client) if err == nil { - t.Fatalf("NewChain didn't return error") + t.Fatalf("NewChannel didn't return error") } - if err.Error() != "failed to create Chain. Missing required 'name' parameter" { - t.Fatalf("NewChain didn't return right error") + if err.Error() != "failed to create Channel. Missing required 'name' parameter" { + t.Fatalf("NewChannel didn't return right error") } - _, err = NewChain("testChain", nil) + _, err = NewChannel("testChannel", nil) if err == nil { - t.Fatalf("NewChain didn't return error") + t.Fatalf("NewChannel didn't return error") } - if err.Error() != "failed to create Chain. Missing required 'clientContext' parameter" { - t.Fatalf("NewChain didn't return right error") + if err.Error() != "failed to create Channel. Missing required 'clientContext' parameter" { + t.Fatalf("NewChannel didn't return right error") } } func TestQueryMethods(t *testing.T) { - chain, _ := setupTestChain() + channel, _ := setupTestChannel() - _, err := chain.QueryBlock(-1) + _, err := channel.QueryBlock(-1) if err == nil { t.Fatalf("Query block cannot be negative number") } - _, err = chain.QueryBlockByHash(nil) + _, err = channel.QueryBlockByHash(nil) if err == nil { t.Fatalf("Query hash cannot be nil") } - _, err = chain.QueryByChaincode("", []string{"method"}, nil) + _, err = channel.QueryByChaincode("", []string{"method"}, nil) if err == nil { - t.Fatalf("QueryByChaincode: name cannot be empty") + t.Fatalf("QueryByChannelcode: name cannot be empty") } - _, err = chain.QueryByChaincode("qscc", nil, nil) + _, err = channel.QueryByChaincode("qscc", nil, nil) if err == nil { - t.Fatalf("QueryByChaincode: arguments cannot be empty") + t.Fatalf("QueryByChannelcode: arguments cannot be empty") } - _, err = chain.QueryByChaincode("qscc", []string{"method"}, nil) + _, err = channel.QueryByChaincode("qscc", []string{"method"}, nil) if err == nil { - t.Fatalf("QueryByChaincode: targets cannot be empty") + t.Fatalf("QueryByChannelcode: targets cannot be empty") } } func TestTargetPeers(t *testing.T) { - p := make(map[string]Peer) - chain := &chain{name: "targetChain", peers: p} + p := make(map[string]api.Peer) + channel := &channel{name: "targetChannel", peers: p} - // Chain has two peers - peer1 := mockPeer{"Peer1", "http://peer1.com", []string{}, nil} - err := chain.AddPeer(&peer1) + // Channel has two peers + 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) } - peer2 := mockPeer{"Peer2", "http://peer2.com", []string{}, nil} - err = chain.AddPeer(&peer2) + 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 target to invalid URL - invalidChoice := mockPeer{"", "http://xyz.com", []string{}, nil} - targetPeers, err := chain.getTargetPeers([]Peer{&invalidChoice}) + invalidChoice := mocks.MockPeer{MockName: "", MockURL: "http://xyz.com", MockRoles: []string{}, MockCert: nil} + targetPeers, err := channel.getTargetPeers([]api.Peer{&invalidChoice}) if err == nil { t.Fatalf("Target peer didn't fail for an invalid peer") } - // Test target peers default to chain peers if target peers are not provided - targetPeers, err = chain.getTargetPeers(nil) + // Test target peers default to channel peers if target peers are not provided + targetPeers, err = channel.getTargetPeers(nil) if err != nil || targetPeers == nil || len(targetPeers) != 2 { t.Fatalf("Target Peers failed to default") } // Set target to valid peer 2 URL - choice := mockPeer{"", "http://peer2.com", []string{}, nil} - targetPeers, err = chain.getTargetPeers([]Peer{&choice}) + choice := mocks.MockPeer{MockName: "", MockURL: "http://peer2.com", MockRoles: []string{}, MockCert: nil} + targetPeers, err = channel.getTargetPeers([]api.Peer{&choice}) if err != nil { t.Fatalf("Failed to get valid target peer") } @@ -138,44 +143,44 @@ func TestTargetPeers(t *testing.T) { } func TestPrimaryPeer(t *testing.T) { - chain, _ := setupTestChain() + channel, _ := setupTestChannel() - // Chain had one peer - peer1 := mockPeer{"Peer1", "http://peer1.com", []string{}, nil} - err := chain.AddPeer(&peer1) + // 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 chain peer - primary := chain.GetPrimaryPeer() + // Test primary defaults to channel peer + primary := channel.GetPrimaryPeer() if primary.GetURL() != peer1.GetURL() { t.Fatalf("Primary Peer failed to default") } - // Chain has two peers - peer2 := mockPeer{"Peer2", "http://peer2.com", []string{}, nil} - err = chain.AddPeer(&peer2) + // 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 := mockPeer{"", "http://xyz.com", []string{}, nil} - err = chain.SetPrimaryPeer(&invalidChoice) + 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 := mockPeer{"", "http://peer2.com", []string{}, nil} - err = chain.SetPrimaryPeer(&choice) + 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 = chain.GetPrimaryPeer() + primary = channel.GetPrimaryPeer() if primary.GetURL() != peer2.GetURL() || primary.GetName() != peer2.GetName() { t.Fatalf("Primary and our choice are not equal") } @@ -184,12 +189,12 @@ func TestPrimaryPeer(t *testing.T) { func TestConcurrentPeers(t *testing.T) { const numPeers = 10000 - chain, err := setupMassiveTestChain(numPeers, 0) + channel, err := setupMassiveTestChannel(numPeers, 0) if err != nil { - t.Fatalf("Failed to create massive chain: %s", err) + t.Fatalf("Failed to create massive channel: %s", err) } - result, err := chain.SendTransactionProposal(&TransactionProposal{ + result, err := channel.SendTransactionProposal(&api.TransactionProposal{ SignedProposal: &pb.SignedProposal{}, }, 1, nil) if err != nil { @@ -203,102 +208,102 @@ func TestConcurrentPeers(t *testing.T) { func TestConcurrentOrderers(t *testing.T) { const numOrderers = 10000 - chain, err := setupMassiveTestChain(0, numOrderers) + channel, err := setupMassiveTestChannel(0, numOrderers) if err != nil { - t.Fatalf("Failed to create massive chain: %s", err) + t.Fatalf("Failed to create massive channel: %s", err) } - txn := Transaction{ - proposal: &TransactionProposal{ + txn := api.Transaction{ + Proposal: &api.TransactionProposal{ Proposal: &pb.Proposal{}, }, - transaction: &pb.Transaction{}, + Transaction: &pb.Transaction{}, } - _, err = chain.SendTransaction(&txn) + _, err = channel.SendTransaction(&txn) if err != nil { t.Fatalf("SendTransaction returned error: %s", err) } } func TestJoinChannel(t *testing.T) { - var peers []Peer + var peers []api.Peer endorserServer := startEndorserServer(t) - chain, _ := setupTestChain() - peer, _ := NewPeer(testAddress, "", "") + channel, _ := setupTestChannel() + peer, _ := peer.NewPeer(testAddress, "", "", mocks.NewMockConfig()) peers = append(peers, peer) - orderer := NewMockOrderer("", nil) - orderer.(MockOrderer).EnqueueForSendDeliver(NewSimpleMockBlock()) - nonce, _ := GenerateRandomNonce() - txID, _ := ComputeTxID(nonce, []byte("testID")) + orderer := mocks.NewMockOrderer("", nil) + orderer.(mocks.MockOrderer).EnqueueForSendDeliver(mocks.NewSimpleMockBlock()) + nonce, _ := fc.GenerateRandomNonce() + txID, _ := fc.ComputeTxID(nonce, []byte("testID")) - genesisBlockReqeust := &GenesisBlockRequest{ + genesisBlockReqeust := &api.GenesisBlockRequest{ TxID: txID, Nonce: nonce, } - genesisBlock, err := chain.GetGenesisBlock(genesisBlockReqeust) + genesisBlock, err := channel.GetGenesisBlock(genesisBlockReqeust) if err == nil { t.Fatalf("Should not have been able to get genesis block because of orderer missing") } - err = chain.AddOrderer(orderer) + err = channel.AddOrderer(orderer) if err != nil { t.Fatalf("Error adding orderer: %v", err) } - genesisBlock, err = chain.GetGenesisBlock(genesisBlockReqeust) + genesisBlock, err = channel.GetGenesisBlock(genesisBlockReqeust) if err != nil { t.Fatalf("Error getting genesis block: %v", err) } - _, err = chain.JoinChannel(nil) + _, err = channel.JoinChannel(nil) if err == nil { t.Fatalf("Should not have been able to join channel because of missing request parameter") } - request := &JoinChannelRequest{ + request := &api.JoinChannelRequest{ Targets: peers, GenesisBlock: genesisBlock, Nonce: nonce, //TxID: txID, } - _, err = chain.JoinChannel(request) + _, err = channel.JoinChannel(request) if err == nil { t.Fatalf("Should not have been able to join channel because of missing TxID parameter") } - request = &JoinChannelRequest{ + request = &api.JoinChannelRequest{ Targets: peers, GenesisBlock: genesisBlock, //Nonce: nonce, TxID: txID, } - _, err = chain.JoinChannel(request) + _, err = channel.JoinChannel(request) if err == nil { t.Fatalf("Should not have been able to join channel because of missing Nonce parameter") } - request = &JoinChannelRequest{ + request = &api.JoinChannelRequest{ Targets: peers, //GenesisBlock: genesisBlock, Nonce: nonce, TxID: txID, } - _, err = chain.JoinChannel(request) + _, err = channel.JoinChannel(request) if err == nil { t.Fatalf("Should not have been able to join channel because of missing GenesisBlock parameter") } - request = &JoinChannelRequest{ + request = &api.JoinChannelRequest{ //Targets: peers, GenesisBlock: genesisBlock, Nonce: nonce, TxID: txID, } - _, err = chain.JoinChannel(request) + _, err = channel.JoinChannel(request) if err == nil { t.Fatalf("Should not have been able to join channel because of missing Targets parameter") } - request = &JoinChannelRequest{ + request = &api.JoinChannelRequest{ Targets: peers, GenesisBlock: genesisBlock, Nonce: nonce, @@ -308,12 +313,12 @@ func TestJoinChannel(t *testing.T) { t.Fatalf("Should not have been able to join channel because of invalid targets") } - err = chain.AddPeer(peer) + err = channel.AddPeer(peer) if err != nil { t.Fatalf("Error adding peer: %v", err) } // Test join channel with valid arguments - response, err := chain.JoinChannel(request) + response, err := channel.JoinChannel(request) if err != nil { t.Fatalf("Did not expect error from join channel. Got: %s", err) } @@ -323,20 +328,20 @@ func TestJoinChannel(t *testing.T) { // Test failed proposal error handling endorserServer.ProposalError = fmt.Errorf("Test Error") - request = &JoinChannelRequest{Targets: peers, Nonce: nonce, TxID: txID} - _, err = chain.JoinChannel(request) + request = &api.JoinChannelRequest{Targets: peers, Nonce: nonce, TxID: txID} + _, err = channel.JoinChannel(request) if err == nil { t.Fatalf("Expected error") } } -func TestChainInitializeFromOrderer(t *testing.T) { +func TestChannelInitializeFromOrderer(t *testing.T) { org1MSPID := "ORG1MSP" org2MSPID := "ORG2MSP" - chain, _ := setupTestChain() - builder := &MockConfigBlockBuilder{ - MockConfigGroupBuilder: MockConfigGroupBuilder{ + channel, _ := setupTestChannel() + builder := &mocks.MockConfigBlockBuilder{ + MockConfigGroupBuilder: mocks.MockConfigGroupBuilder{ ModPolicy: "Admins", MSPNames: []string{ org1MSPID, @@ -348,21 +353,21 @@ func TestChainInitializeFromOrderer(t *testing.T) { Index: 0, LastConfigIndex: 0, } - orderer := NewMockOrderer("", nil) - orderer.(MockOrderer).EnqueueForSendDeliver(builder.Build()) - orderer.(MockOrderer).EnqueueForSendDeliver(builder.Build()) - err := chain.AddOrderer(orderer) + orderer := mocks.NewMockOrderer("", nil) + orderer.(mocks.MockOrderer).EnqueueForSendDeliver(builder.Build()) + orderer.(mocks.MockOrderer).EnqueueForSendDeliver(builder.Build()) + err := channel.AddOrderer(orderer) if err != nil { t.Fatalf("Error adding orderer: %v", err) } - err = chain.Initialize(nil) + err = channel.Initialize(nil) if err != nil { t.Fatalf("channel Initialize failed : %v", err) } - mspManager := chain.GetMSPManager() + mspManager := channel.GetMSPManager() if mspManager == nil { - t.Fatalf("nil MSPManager on new chain") + t.Fatalf("nil MSPManager on new channel") } msps, err := mspManager.GetMSPs() if err != nil || len(msps) == 0 { @@ -388,16 +393,16 @@ func TestOrganizationUnits(t *testing.T) { org1MSPID := "ORG1MSP" org2MSPID := "ORG2MSP" - chain, _ := setupTestChain() - orgUnits, err := chain.GetOrganizationUnits() + channel, _ := setupTestChannel() + orgUnits, err := channel.GetOrganizationUnits() if len(orgUnits) > 0 { t.Fatalf("Returned non configured organizational unit : %v", err) } - builder := &MockConfigBlockBuilder{ - MockConfigGroupBuilder: MockConfigGroupBuilder{ + builder := &mocks.MockConfigBlockBuilder{ + MockConfigGroupBuilder: mocks.MockConfigGroupBuilder{ ModPolicy: "Admins", MSPNames: []string{ - chain.GetName(), + channel.GetName(), org1MSPID, org2MSPID, }, @@ -407,24 +412,24 @@ func TestOrganizationUnits(t *testing.T) { Index: 0, LastConfigIndex: 0, } - orderer := NewMockOrderer("", nil) - orderer.(MockOrderer).EnqueueForSendDeliver(builder.Build()) - orderer.(MockOrderer).EnqueueForSendDeliver(builder.Build()) - err = chain.AddOrderer(orderer) + orderer := mocks.NewMockOrderer("", nil) + orderer.(mocks.MockOrderer).EnqueueForSendDeliver(builder.Build()) + orderer.(mocks.MockOrderer).EnqueueForSendDeliver(builder.Build()) + err = channel.AddOrderer(orderer) if err != nil { t.Fatalf("Error adding orderer: %v", err) } - err = chain.Initialize(nil) + err = channel.Initialize(nil) if err != nil { t.Fatalf("channel Initialize failed : %v", err) } - orgUnits, err = chain.GetOrganizationUnits() + orgUnits, err = channel.GetOrganizationUnits() if err != nil { t.Fatalf("CANNOT retrieve organizational units : %v", err) } - if !isValueInList(chain.GetName(), orgUnits) { - t.Fatalf("Could not find %s in the list of organizations", chain.GetName()) + if !isValueInList(channel.GetName(), orgUnits) { + t.Fatalf("Could not find %s in the list of organizations", channel.GetName()) } if !isValueInList(org1MSPID, orgUnits) { t.Fatalf("Could not find %s in the list of organizations", org1MSPID) @@ -444,14 +449,14 @@ func isValueInList(value string, list []string) bool { return false } -func TestChainInitializeFromUpdate(t *testing.T) { +func TestChannelInitializeFromUpdate(t *testing.T) { org1MSPID := "ORG1MSP" org2MSPID := "ORG2MSP" - chain, _ := setupTestChain() - builder := &MockConfigUpdateEnvelopeBuilder{ + channel, _ := setupTestChannel() + builder := &mocks.MockConfigUpdateEnvelopeBuilder{ ChannelID: "mychannel", - MockConfigGroupBuilder: MockConfigGroupBuilder{ + MockConfigGroupBuilder: mocks.MockConfigGroupBuilder{ ModPolicy: "Admins", MSPNames: []string{ org1MSPID, @@ -462,54 +467,55 @@ func TestChainInitializeFromUpdate(t *testing.T) { }, } - err := chain.Initialize(builder.BuildBytes()) + err := channel.Initialize(builder.BuildBytes()) if err != nil { t.Fatalf("channel Initialize failed : %v", err) } - mspManager := chain.GetMSPManager() + mspManager := channel.GetMSPManager() if mspManager == nil { - t.Fatalf("nil MSPManager on new chain") + t.Fatalf("nil MSPManager on new channel") } } -func setupTestChain() (Chain, error) { - client := NewClient() - user := NewUser("test") - cryptoSuite := &MockCryptoSuite{} +func setupTestChannel() (api.Channel, error) { + client := mocks.NewMockClient() + user := mocks.NewMockUser("test") + cryptoSuite := &mocks.MockCryptoSuite{} client.SaveUserToStateStore(user, true) client.SetCryptoSuite(cryptoSuite) - return NewChain("testChain", client) + return NewChannel("testChannel", client) } -func setupMassiveTestChain(numberOfPeers int, numberOfOrderers int) (Chain, error) { - chain, error := setupTestChain() +func setupMassiveTestChannel(numberOfPeers int, numberOfOrderers int) (api.Channel, error) { + channel, error := setupTestChannel() if error != nil { - return chain, error + return channel, error } for i := 0; i < numberOfPeers; i++ { - peer := mockPeer{fmt.Sprintf("MockPeer%d", i), fmt.Sprintf("http://mock%d.peers.r.us", i), []string{}, nil} - err := chain.AddPeer(&peer) + 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, fmt.Errorf("Error adding peer: %v", err) } } for i := 0; i < numberOfOrderers; i++ { - orderer := NewMockOrderer(fmt.Sprintf("http://mock%d.orderers.r.us", i), nil) - err := chain.AddOrderer(orderer) + orderer := mocks.NewMockOrderer(fmt.Sprintf("http://mock%d.orderers.r.us", i), nil) + err := channel.AddOrderer(orderer) if err != nil { return nil, fmt.Errorf("Error adding orderer: %v", err) } } - return chain, error + return channel, error } -func startEndorserServer(t *testing.T) *MockEndorserServer { +func startEndorserServer(t *testing.T) *mocks.MockEndorserServer { grpcServer := grpc.NewServer() lis, err := net.Listen("tcp", testAddress) - endorserServer := &MockEndorserServer{} + endorserServer := &mocks.MockEndorserServer{} pb.RegisterEndorserServer(grpcServer, endorserServer) if err != nil { fmt.Printf("Error starting test server %s", err) diff --git a/fabric-client/client.go b/pkg/fabric-client/client/client.go similarity index 64% rename from fabric-client/client.go rename to pkg/fabric-client/client/client.go index 65df9a63d9..f3c4a5ae25 100644 --- a/fabric-client/client.go +++ b/pkg/fabric-client/client/client.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package client import ( "encoding/json" @@ -13,144 +13,92 @@ import ( "github.com/golang/protobuf/proto" google_protobuf "github.com/golang/protobuf/ptypes/timestamp" - "github.com/hyperledger/fabric-sdk-go/config" - kvs "github.com/hyperledger/fabric-sdk-go/fabric-client/keyvaluestore" + api "github.com/hyperledger/fabric-sdk-go/api" + channel "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/channel" + fc "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal" + packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/packager" + fcUser "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/user" + + "github.com/op/go-logging" + "github.com/hyperledger/fabric/bccsp" fcutils "github.com/hyperledger/fabric/common/util" "github.com/hyperledger/fabric/protos/common" "github.com/hyperledger/fabric/protos/msp" pb "github.com/hyperledger/fabric/protos/peer" protos_utils "github.com/hyperledger/fabric/protos/utils" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" ) -// Client ... -/* - * Main interaction handler with end user. A client instance provides a handler to interact - * with a network of peers, orderers and optionally member services. An application using the - * SDK may need to interact with multiple networks, each through a separate instance of the Client. - * - * Each client when initially created should be initialized with configuration data from the - * consensus service, which includes a list of trusted roots, orderer certificates and IP addresses, - * and a list of peer certificates and IP addresses that it can access. This must be done out of band - * as part of bootstrapping the application environment. It is also the responsibility of the application - * to maintain the configuration of a client as the SDK does not persist this object. - * - * Each Client instance can maintain several {@link Chain} instances representing channels and the associated - * private ledgers. - * - * - */ -type Client interface { - NewChain(name string) (Chain, error) - GetChain(name string) Chain - ExtractChannelConfig(configEnvelope []byte) ([]byte, error) - SignChannelConfig(config []byte) (*common.ConfigSignature, error) - CreateChannel(request *CreateChannelRequest) error - QueryChainInfo(name string, peers []Peer) (Chain, error) - SetStateStore(stateStore kvs.KeyValueStore) - GetStateStore() kvs.KeyValueStore - SetCryptoSuite(cryptoSuite bccsp.BCCSP) - GetCryptoSuite() bccsp.BCCSP - SaveUserToStateStore(user User, skipPersistence bool) error - LoadUserFromStateStore(name string) (User, error) - InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, chaincodePackage []byte, targets []Peer) ([]*TransactionProposalResponse, string, error) - QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error) - QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse, error) - GetIdentity() ([]byte, error) - GetUserContext() User - SetUserContext(user User) -} +var logger = logging.MustGetLogger("fabric_sdk_go") type client struct { - chains map[string]Chain + channels map[string]api.Channel cryptoSuite bccsp.BCCSP - stateStore kvs.KeyValueStore - userContext User -} - -// CreateChannelRequest requests channel creation on the network -type CreateChannelRequest struct { - // required - The name of the new channel - Name string - // required - The Orderer to send the update request - Orderer Orderer - // optional - the envelope object containing all - // required settings and signatures to initialize this channel. - // This envelope would have been created by the command - // line tool "configtx" - Envelope []byte - // optional - ConfigUpdate object built by the - // buildChannelConfig() method of this package - Config []byte - // optional - the list of collected signatures - // required by the channel create policy when using the `config` parameter. - // see signChannelConfig() method of this package - Signatures []*common.ConfigSignature - // optional - transaction ID - // required when using the `config` parameter - TxID string - // optional - nonce - // required when using the `config` parameter - Nonce []byte + stateStore api.KeyValueStore + userContext api.User + config api.Config } // NewClient ... /* * Returns a Client instance */ -func NewClient() Client { - chains := make(map[string]Chain) - c := &client{chains: chains, cryptoSuite: nil, stateStore: nil, userContext: nil} +func NewClient(config api.Config) api.FabricClient { + channels := make(map[string]api.Channel) + c := &client{channels: channels, cryptoSuite: nil, stateStore: nil, userContext: nil, config: config} return c } -// NewChain ... +// NewChannel ... /* - * Returns a chain instance with the given name. This represents a channel and its associated ledger - * (as explained above), and this call returns an empty object. To initialize the chain in the blockchain network, + * Returns a channel instance with the given name. This represents a channel and its associated ledger + * (as explained above), and this call returns an empty object. To initialize the channel in the blockchain network, * a list of participating endorsers and orderer peers must be configured first on the returned object. - * @param {string} name The name of the chain. Recommend using namespaces to avoid collision. - * @returns {Chain} The uninitialized chain instance. - * @returns {Error} if the chain by that name already exists in the application's state store + * @param {string} name The name of the channel. Recommend using namespaces to avoid collision. + * @returns {Channel} The uninitialized channel instance. + * @returns {Error} if the channel by that name already exists in the application's state store */ -func (c *client) NewChain(name string) (Chain, error) { - if _, ok := c.chains[name]; ok { - return nil, fmt.Errorf("Chain %s already exists", name) +func (c *client) NewChannel(name string) (api.Channel, error) { + if _, ok := c.channels[name]; ok { + return nil, fmt.Errorf("Channel %s already exists", name) } var err error - c.chains[name], err = NewChain(name, c) + c.channels[name], err = channel.NewChannel(name, c) if err != nil { return nil, err } - return c.chains[name], nil + return c.channels[name], nil +} + +// GetConfig ... +func (c *client) GetConfig() api.Config { + return c.config } -// GetChain ... +// GetChannel ... /* - * Get a {@link Chain} instance from the state storage. This allows existing chain instances to be saved + * Get a {@link Channel} instance from the state storage. This allows existing channel instances to be saved * for retrieval later and to be shared among instances of the application. Note that it’s the - * application/SDK’s responsibility to record the chain information. If an application is not able - * to look up the chain information from storage, it may call another API that queries one or more + * application/SDK’s responsibility to record the channel information. If an application is not able + * to look up the channel information from storage, it may call another API that queries one or more * Peers for that information. - * @param {string} name The name of the chain. - * @returns {Chain} The chain instance + * @param {string} name The name of the channel. + * @returns {Channel} The channel instance */ -func (c *client) GetChain(name string) Chain { - return c.chains[name] +func (c *client) GetChannel(name string) api.Channel { + return c.channels[name] } -// QueryChainInfo ... +// QueryChannelInfo ... /* - * This is a network call to the designated Peer(s) to discover the chain information. - * The target Peer(s) must be part of the chain to be able to return the requested information. - * @param {string} name The name of the chain. + * This is a network call to the designated Peer(s) to discover the channel information. + * The target Peer(s) must be part of the channel to be able to return the requested information. + * @param {string} name The name of the channel. * @param {[]Peer} peers Array of target Peers to query. - * @returns {Chain} The chain instance for the name or error if the target Peer(s) does not know - * anything about the chain. + * @returns {Channel} The channel instance for the name or error if the target Peer(s) does not know + * anything about the channel. */ -func (c *client) QueryChainInfo(name string, peers []Peer) (Chain, error) { +func (c *client) QueryChannelInfo(name string, peers []api.Peer) (api.Channel, error) { return nil, fmt.Errorf("Not implemented yet") } @@ -161,7 +109,7 @@ func (c *client) QueryChainInfo(name string, peers []Peer) (Chain, error) { * so that multiple app instances can share app state via the database (note that this doesn’t necessarily make the app stateful). * This API makes this pluggable so that different store implementations can be selected by the application. */ -func (c *client) SetStateStore(stateStore kvs.KeyValueStore) { +func (c *client) SetStateStore(stateStore api.KeyValueStore) { c.stateStore = stateStore } @@ -169,7 +117,7 @@ func (c *client) SetStateStore(stateStore kvs.KeyValueStore) { /* * A convenience method for obtaining the state store object in use for this client. */ -func (c *client) GetStateStore() kvs.KeyValueStore { +func (c *client) GetStateStore() api.KeyValueStore { return c.stateStore } @@ -197,7 +145,7 @@ func (c *client) GetCryptoSuite() bccsp.BCCSP { * this cache will not be established and the application is responsible for setting the user context again when the application * crashed and is recovered. */ -func (c *client) SaveUserToStateStore(user User, skipPersistence bool) error { +func (c *client) SaveUserToStateStore(user api.User, skipPersistence bool) error { if user == nil { return fmt.Errorf("user is nil") } @@ -210,7 +158,7 @@ func (c *client) SaveUserToStateStore(user User, skipPersistence bool) error { if c.stateStore == nil { return fmt.Errorf("stateStore is nil") } - userJSON := &UserJSON{PrivateKeySKI: user.GetPrivateKey().SKI(), EnrollmentCertificate: user.GetEnrollmentCertificate()} + userJSON := &fcUser.JSON{PrivateKeySKI: user.GetPrivateKey().SKI(), EnrollmentCertificate: user.GetEnrollmentCertificate()} data, err := json.Marshal(userJSON) if err != nil { return fmt.Errorf("Marshal json return error: %v", err) @@ -230,7 +178,7 @@ func (c *client) SaveUserToStateStore(user User, skipPersistence bool) error { * @returns {Promise} A Promise for a {User} object upon successful restore, or if the user by the name * does not exist in the state store, returns null without rejecting the promise */ -func (c *client) LoadUserFromStateStore(name string) (User, error) { +func (c *client) LoadUserFromStateStore(name string) (api.User, error) { if c.userContext != nil { return c.userContext, nil } @@ -247,12 +195,12 @@ func (c *client) LoadUserFromStateStore(name string) (User, error) { if err != nil { return nil, nil } - var userJSON UserJSON + var userJSON fcUser.JSON err = json.Unmarshal(value, &userJSON) if err != nil { return nil, fmt.Errorf("stateStore GetValue return error: %v", err) } - user := NewUser(name) + user := fcUser.NewUser(name) user.SetEnrollmentCertificate(userJSON.EnrollmentCertificate) key, err := c.cryptoSuite.GetKey(userJSON.PrivateKeySKI) if err != nil { @@ -314,7 +262,7 @@ func (c *client) SignChannelConfig(config []byte) (*common.ConfigSignature, erro if err != nil { return nil, fmt.Errorf("Error getting creator: %v", err) } - nonce, err := GenerateRandomNonce() + nonce, err := fc.GenerateRandomNonce() if err != nil { return nil, fmt.Errorf("Error generating nonce: %v", err) } @@ -336,7 +284,7 @@ func (c *client) SignChannelConfig(config []byte) (*common.ConfigSignature, erro // get all the bytes to be signed together, then sign signingBytes := fcutils.ConcatenateBytes(signatureHeaderBytes, config) - signature, err := SignObjectWithKey(signingBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.GetCryptoSuite()) + signature, err := fc.SignObjectWithKey(signingBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.GetCryptoSuite()) if err != nil { return nil, fmt.Errorf("error singing config: %v", err) } @@ -353,8 +301,8 @@ func (c *client) SignChannelConfig(config []byte) (*common.ConfigSignature, erro /** * Calls the orderer to start building the new channel. * Only one of the application instances needs to call this method. - * Once the chain is successfully created, this and other application - * instances only need to call Chain joinChannel() to participate on the channel. + * Once the channel is successfully created, this and other application + * instances only need to call Channel joinChannel() to participate on the channel. * @param {Object} request - An object containing the following fields: *
`name` : required - {string} The name of the new channel *
`orderer` : required - {Orderer} object instance representing the @@ -370,7 +318,7 @@ func (c *client) SignChannelConfig(config []byte) (*common.ConfigSignature, erro * required by the channel create policy when using the `config` parameter. * @returns {Result} Result Object with status on the create process. */ -func (c *client) CreateChannel(request *CreateChannelRequest) error { +func (c *client) CreateChannel(request *api.CreateChannelRequest) error { haveEnvelope := false if request != nil && request.Envelope != nil { logger.Debug("createChannel - have envelope") @@ -379,7 +327,7 @@ func (c *client) CreateChannel(request *CreateChannelRequest) error { return c.CreateOrUpdateChannel(request, haveEnvelope) } -func (c *client) CreateOrUpdateChannel(request *CreateChannelRequest, haveEnvelope bool) error { +func (c *client) CreateOrUpdateChannel(request *api.CreateChannelRequest, haveEnvelope bool) error { // Validate request if request == nil { return fmt.Errorf("Missing all required input request parameters for initialize channel") @@ -409,7 +357,7 @@ func (c *client) CreateOrUpdateChannel(request *CreateChannelRequest, haveEnvelo return fmt.Errorf("Missing name request parameter for the new channel") } - // chain = null; + // channel = null; var signature []byte var payloadBytes []byte @@ -429,7 +377,7 @@ func (c *client) CreateOrUpdateChannel(request *CreateChannelRequest, haveEnvelo Signatures: request.Signatures, } - channelHeader, err := BuildChannelHeader(common.HeaderType_CONFIG_UPDATE, request.Name, request.TxID, 0, "", time.Now()) + channelHeader, err := channel.BuildChannelHeader(common.HeaderType_CONFIG_UPDATE, request.Name, request.TxID, 0, "", time.Now()) if err != nil { return fmt.Errorf("error when building channel header: %v", err) } @@ -438,7 +386,7 @@ func (c *client) CreateOrUpdateChannel(request *CreateChannelRequest, haveEnvelo return fmt.Errorf("Error getting creator: %v", err) } - header, err := BuildHeader(creator, channelHeader, request.Nonce) + header, err := fc.BuildHeader(creator, channelHeader, request.Nonce) if err != nil { return fmt.Errorf("error when building header: %v", err) } @@ -455,14 +403,14 @@ func (c *client) CreateOrUpdateChannel(request *CreateChannelRequest, haveEnvelo return fmt.Errorf("error marshaling payload: %v", err) } - signature, err = SignObjectWithKey(payloadBytes, c.userContext.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.GetCryptoSuite()) + signature, err = fc.SignObjectWithKey(payloadBytes, c.userContext.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.GetCryptoSuite()) if err != nil { return fmt.Errorf("error singing payload: %v", err) } } // Send request - _, err := request.Orderer.SendBroadcast(&SignedEnvelope{ + _, err := request.Orderer.SendBroadcast(&api.SignedEnvelope{ Signature: signature, Payload: payloadBytes, }) @@ -473,46 +421,6 @@ func (c *client) CreateOrUpdateChannel(request *CreateChannelRequest, haveEnvelo return nil } -// NewPeer ... -/** - * Constructs a Peer given its endpoint configuration settings. - * - * @param {string} url The URL with format of "host:port". - */ -func NewPeer(url string, certificate string, serverHostOverride string) (Peer, error) { - var opts []grpc.DialOption - opts = append(opts, grpc.WithTimeout(time.Second*3)) - if config.IsTLSEnabled() { - tlsCaCertPool, err := config.GetTLSCACertPool(certificate) - if err != nil { - return nil, err - } - creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride) - opts = append(opts, grpc.WithTransportCredentials(creds)) - } else { - opts = append(opts, grpc.WithInsecure()) - } - return &peer{url: url, grpcDialOption: opts, name: "", roles: nil}, nil - -} - -// NewOrderer Returns a Orderer instance -func NewOrderer(url string, certificate string, serverHostOverride string) (Orderer, error) { - var opts []grpc.DialOption - opts = append(opts, grpc.WithTimeout(time.Second*3)) - if config.IsTLSEnabled() { - tlsCaCertPool, err := config.GetTLSCACertPool(certificate) - if err != nil { - return nil, err - } - creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride) - opts = append(opts, grpc.WithTransportCredentials(creds)) - } else { - opts = append(opts, grpc.WithInsecure()) - } - return &orderer{url: url, grpcDialOption: opts}, nil -} - //QueryChannels /** * Queries the names of all the channels that a @@ -520,13 +428,13 @@ func NewOrderer(url string, certificate string, serverHostOverride string) (Orde * @param {Peer} peer * @returns {object} ChannelQueryResponse proto */ -func (c *client) QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error) { +func (c *client) QueryChannels(peer api.Peer) (*pb.ChannelQueryResponse, error) { if peer == nil { return nil, fmt.Errorf("QueryChannels requires peer") } - responses, err := QueryByChaincode("cscc", []string{"GetChannels"}, []Peer{peer}, c) + responses, err := channel.QueryByChaincode("cscc", []string{"GetChannels"}, []api.Peer{peer}, c) if err != nil { return nil, fmt.Errorf("QueryByChaincode return error: %v", err) } @@ -547,12 +455,12 @@ func (c *client) QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error) { * @param {Peer} peer * @returns {object} ChaincodeQueryResponse proto */ -func (c *client) QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse, error) { +func (c *client) QueryInstalledChaincodes(peer api.Peer) (*pb.ChaincodeQueryResponse, error) { if peer == nil { return nil, fmt.Errorf("To query installed chaincdes you need to pass peer") } - responses, err := QueryByChaincode("lscc", []string{"getinstalledchaincodes"}, []Peer{peer}, c) + responses, err := channel.QueryByChaincode("lscc", []string{"getinstalledchaincodes"}, []api.Peer{peer}, c) if err != nil { return nil, fmt.Errorf("Invoke lscc getinstalledchaincodes return error: %v", err) } @@ -575,7 +483,7 @@ func (c *client) QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse * @param {[]string} chaincodeVersion: optional - Array of byte the chaincodePackage */ func (c *client) InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, - chaincodePackage []byte, targets []Peer) ([]*TransactionProposalResponse, string, error) { + chaincodePackage []byte, targets []api.Peer) ([]*api.TransactionProposalResponse, string, error) { if chaincodeName == "" { return nil, "", fmt.Errorf("Missing 'chaincodeName' parameter") @@ -589,7 +497,7 @@ func (c *client) InstallChaincode(chaincodeName string, chaincodePath string, ch if chaincodePackage == nil { var err error - chaincodePackage, err = PackageCC(chaincodePath, "") + chaincodePackage, err = packager.PackageCC(chaincodePath, "") if err != nil { return nil, "", fmt.Errorf("PackageCC return error: %s", err) } @@ -618,7 +526,7 @@ func (c *client) InstallChaincode(chaincodeName string, chaincodePath string, ch if err != nil { return nil, "", fmt.Errorf("Error loading user from store: %s", err) } - signature, err := SignObjectWithKey(proposalBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.GetCryptoSuite()) + signature, err := fc.SignObjectWithKey(proposalBytes, user.GetPrivateKey(), &bccsp.SHAOpts{}, nil, c.GetCryptoSuite()) if err != nil { return nil, "", err } @@ -628,7 +536,7 @@ func (c *client) InstallChaincode(chaincodeName string, chaincodePath string, ch return nil, "", err } - transactionProposalResponse, err := SendTransactionProposal(&TransactionProposal{ + transactionProposalResponse, err := channel.SendTransactionProposal(&api.TransactionProposal{ SignedProposal: signedProposal, Proposal: proposal, TransactionID: txID, @@ -643,7 +551,7 @@ func (c *client) GetIdentity() ([]byte, error) { if c.userContext == nil { return nil, fmt.Errorf("User is nil") } - serializedIdentity := &msp.SerializedIdentity{Mspid: config.GetFabricCAID(), + serializedIdentity := &msp.SerializedIdentity{Mspid: c.config.GetFabricCAID(), IdBytes: c.userContext.GetEnrollmentCertificate()} identity, err := proto.Marshal(serializedIdentity) if err != nil { @@ -653,11 +561,11 @@ func (c *client) GetIdentity() ([]byte, error) { } // GetUserContext ... -func (c *client) GetUserContext() User { +func (c *client) GetUserContext() api.User { return c.userContext } // SetUserContext ... -func (c *client) SetUserContext(user User) { +func (c *client) SetUserContext(user api.User) { c.userContext = user } diff --git a/fabric-client/client_test.go b/pkg/fabric-client/client/client_test.go similarity index 82% rename from fabric-client/client_test.go rename to pkg/fabric-client/client/client_test.go index 813a5705b7..51a6bebaea 100644 --- a/fabric-client/client_test.go +++ b/pkg/fabric-client/client/client_test.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package client import ( "fmt" @@ -12,12 +12,16 @@ import ( "testing" "time" - kvs "github.com/hyperledger/fabric-sdk-go/fabric-client/keyvaluestore" + api "github.com/hyperledger/fabric-sdk-go/api" + mocks "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks" + fcUser "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/user" + + kvs "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/keyvaluestore" bccspFactory "github.com/hyperledger/fabric/bccsp/factory" ) func TestClientMethods(t *testing.T) { - client := NewClient() + client := NewClient(mocks.NewMockConfig()) if client.GetCryptoSuite() != nil { t.Fatalf("Client getCryptoSuite should initially be nil") } @@ -60,7 +64,7 @@ func TestClientMethods(t *testing.T) { } //Client tests: successfully SaveUserToStateStore with skipPersistence true - user = NewUser("someUser") + user = fcUser.NewUser("someUser") err = client.SaveUserToStateStore(user, true) if err != nil { t.Fatalf("client.SaveUserToStateStore return error[%s]", err) @@ -86,14 +90,14 @@ func TestClientMethods(t *testing.T) { } //Client tests: Create new chain - chain, err := client.NewChain("someChain") + chain, err := client.NewChannel("someChain") if err != nil { t.Fatalf("client.NewChain return error[%s]", err) } if chain.GetName() != "someChain" { t.Fatalf("client.NewChain create wrong chain") } - chain1 := client.GetChain("someChain") + chain1 := client.GetChannel("someChain") if chain1.GetName() != "someChain" { t.Fatalf("client.NewChain create wrong chain") } @@ -115,20 +119,19 @@ func TestClientMethods(t *testing.T) { } func TestCreateChannel(t *testing.T) { - client := NewClient() + client := NewClient(mocks.NewMockConfig()) - configTx, err := ioutil.ReadFile("../test/fixtures/channel/mychannel.tx") - //configTx, err := ioutil.ReadFile("../test/fixtures/channel/testchannel.tx") + configTx, err := ioutil.ReadFile("../../../test/fixtures/channel/mychannel.tx") if err != nil { t.Fatalf(err.Error()) } // Setup mock orderer - verifyBroadcast := make(chan *SignedEnvelope) - orderer := NewMockOrderer(fmt.Sprintf("0.0.0.0:1234"), verifyBroadcast) + verifyBroadcast := make(chan *api.SignedEnvelope) + orderer := mocks.NewMockOrderer(fmt.Sprintf("0.0.0.0:1234"), verifyBroadcast) // Create channel without envelope - err = client.CreateChannel(&CreateChannelRequest{ + err = client.CreateChannel(&api.CreateChannelRequest{ Orderer: orderer, Name: "mychannel", }) @@ -137,7 +140,7 @@ func TestCreateChannel(t *testing.T) { } // Create channel without orderer - err = client.CreateChannel(&CreateChannelRequest{ + err = client.CreateChannel(&api.CreateChannelRequest{ Envelope: configTx, Name: "mychannel", }) @@ -146,7 +149,7 @@ func TestCreateChannel(t *testing.T) { } // Create channel without name - err = client.CreateChannel(&CreateChannelRequest{ + err = client.CreateChannel(&api.CreateChannelRequest{ Envelope: configTx, Orderer: orderer, }) @@ -155,7 +158,7 @@ func TestCreateChannel(t *testing.T) { } // Test with valid cofiguration - request := &CreateChannelRequest{ + request := &api.CreateChannelRequest{ Envelope: configTx, Orderer: orderer, Name: "mychannel", @@ -173,7 +176,7 @@ func TestCreateChannel(t *testing.T) { } func TestQueryMethodsOnClient(t *testing.T) { - client := NewClient() + client := NewClient(mocks.NewMockConfig()) _, err := client.QueryChannels(nil) if err == nil { diff --git a/fabric-client/events/consumer/consumer.go b/pkg/fabric-client/events/consumer/consumer.go similarity index 90% rename from fabric-client/events/consumer/consumer.go rename to pkg/fabric-client/events/consumer/consumer.go index a04985d671..fe0d2cd15d 100644 --- a/fabric-client/events/consumer/consumer.go +++ b/pkg/fabric-client/events/consumer/consumer.go @@ -13,8 +13,8 @@ import ( "time" "github.com/golang/protobuf/proto" - config "github.com/hyperledger/fabric-sdk-go/config" - fc "github.com/hyperledger/fabric-sdk-go/fabric-client" + api "github.com/hyperledger/fabric-sdk-go/api" + fc "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal" "github.com/hyperledger/fabric/bccsp" consumer "github.com/hyperledger/fabric/events/consumer" "github.com/hyperledger/fabric/protos/peer" @@ -29,16 +29,6 @@ var logger = logging.MustGetLogger("fabric_sdk_go") const defaultTimeout = time.Second * 3 -//EventsClient holds the stream and adapter for consumer to work with -type EventsClient interface { - RegisterAsync(ies []*ehpb.Interest) error - UnregisterAsync(ies []*ehpb.Interest) error - Unregister(ies []*ehpb.Interest) error - Recv() (*ehpb.Event, error) - Start() error - Stop() error -} - type eventsClient struct { sync.RWMutex peerAddress string @@ -48,11 +38,11 @@ type eventsClient struct { TLSCertificate string TLSServerHostOverride string clientConn *grpc.ClientConn - client fc.Client + client api.FabricClient } //NewEventsClient Returns a new grpc.ClientConn to the configured local PEER. -func NewEventsClient(client fc.Client, peerAddress string, certificate string, serverhostoverride string, regTimeout time.Duration, adapter consumer.EventAdapter) (EventsClient, error) { +func NewEventsClient(client api.FabricClient, peerAddress string, certificate string, serverhostoverride string, regTimeout time.Duration, adapter consumer.EventAdapter) (api.EventsClient, error) { var err error if regTimeout < 100*time.Millisecond { regTimeout = 100 * time.Millisecond @@ -65,7 +55,7 @@ func NewEventsClient(client fc.Client, peerAddress string, certificate string, s } //newEventsClientConnectionWithAddress Returns a new grpc.ClientConn to the configured local PEER. -func newEventsClientConnectionWithAddress(peerAddress string, certificate string, serverhostoverride string) (*grpc.ClientConn, error) { +func newEventsClientConnectionWithAddress(peerAddress string, certificate string, serverhostoverride string, config api.Config) (*grpc.ClientConn, error) { var opts []grpc.DialOption opts = append(opts, grpc.WithTimeout(time.Second*3)) if config.IsTLSEnabled() { @@ -243,7 +233,7 @@ func (ec *eventsClient) processEvents() error { //Start establishes connection with Event hub and registers interested events with it func (ec *eventsClient) Start() error { - conn, err := newEventsClientConnectionWithAddress(ec.peerAddress, ec.TLSCertificate, ec.TLSServerHostOverride) + conn, err := newEventsClientConnectionWithAddress(ec.peerAddress, ec.TLSCertificate, ec.TLSServerHostOverride, ec.client.GetConfig()) if err != nil { return fmt.Errorf("Could not create client conn to %s (%v)", ec.peerAddress, err) } diff --git a/fabric-client/events/eventhub.go b/pkg/fabric-client/events/eventhub.go similarity index 87% rename from fabric-client/events/eventhub.go rename to pkg/fabric-client/events/eventhub.go index e024de750f..ac62db011c 100644 --- a/fabric-client/events/eventhub.go +++ b/pkg/fabric-client/events/eventhub.go @@ -16,8 +16,8 @@ import ( "time" "github.com/golang/protobuf/proto" - fc "github.com/hyperledger/fabric-sdk-go/fabric-client" - consumer "github.com/hyperledger/fabric-sdk-go/fabric-client/events/consumer" + api "github.com/hyperledger/fabric-sdk-go/api" + consumer "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/events/consumer" cnsmr "github.com/hyperledger/fabric/events/consumer" "github.com/hyperledger/fabric/core/ledger/util" @@ -29,35 +29,11 @@ import ( var logger = logging.MustGetLogger("fabric_sdk_go") -// EventHub ... -type EventHub interface { - SetPeerAddr(peerURL string, certificate string, serverHostOverride string) - IsConnected() bool - Connect() error - Disconnect() - RegisterChaincodeEvent(ccid string, eventname string, callback func(*ChaincodeEvent)) *ChainCodeCBE - UnregisterChaincodeEvent(cbe *ChainCodeCBE) - RegisterTxEvent(txID string, callback func(string, pb.TxValidationCode, error)) - UnregisterTxEvent(txID string) - RegisterBlockEvent(callback func(*common.Block)) - UnregisterBlockEvent(callback func(*common.Block)) -} - -// The EventHubExt interface allows extensions of the SDK to add functionality to EventHub overloads. -type EventHubExt interface { - SetInterests(block bool) -} - -// eventClientFactory creates an EventsClient instance -type eventClientFactory interface { - newEventsClient(client fc.Client, peerAddress string, certificate string, serverHostOverride string, regTimeout time.Duration, adapter cnsmr.EventAdapter) (consumer.EventsClient, error) -} - type eventHub struct { // Protects chaincodeRegistrants, blockRegistrants and txRegistrants mtx sync.RWMutex // Map of clients registered for chaincode events - chaincodeRegistrants map[string][]*ChainCodeCBE + chaincodeRegistrants map[string][]*api.ChainCodeCBE // Map of clients registered for block events blockRegistrants []func(*common.Block) // Map of clients registered for transactional events @@ -69,54 +45,36 @@ type eventHub struct { // peer tls server host override peerTLSServerHostOverride string // grpc event client interface - grpcClient consumer.EventsClient + grpcClient api.EventsClient // fabric connection state of this eventhub connected bool // List of events client is interested in interestedEvents []*pb.Interest // Factory that creates EventsClient eventsClientFactory eventClientFactory - // Client - client fc.Client -} - -// ChaincodeEvent contains the current event data for the event handler -type ChaincodeEvent struct { - ChaincodeID string - TxID string - EventName string - Payload []byte - ChannelID string + // FabricClient + client api.FabricClient } -// ChainCodeCBE ... -/** - * The ChainCodeCBE is used internal to the EventHub to hold chaincode - * event registration callbacks. - */ -type ChainCodeCBE struct { - // chaincode id - CCID string - // event name regex filter - EventNameFilter string - // callback function to invoke on successful filter match - CallbackFunc func(*ChaincodeEvent) +// eventClientFactory creates an EventsClient instance +type eventClientFactory interface { + newEventsClient(client api.FabricClient, peerAddress string, certificate string, serverHostOverride string, regTimeout time.Duration, adapter cnsmr.EventAdapter) (api.EventsClient, error) } // consumerClientFactory is the default implementation oif the eventClientFactory type consumerClientFactory struct{} -func (ccf *consumerClientFactory) newEventsClient(client fc.Client, peerAddress string, certificate string, serverHostOverride string, regTimeout time.Duration, adapter cnsmr.EventAdapter) (consumer.EventsClient, error) { +func (ccf *consumerClientFactory) newEventsClient(client api.FabricClient, peerAddress string, certificate string, serverHostOverride string, regTimeout time.Duration, adapter cnsmr.EventAdapter) (api.EventsClient, error) { return consumer.NewEventsClient(client, peerAddress, certificate, serverHostOverride, regTimeout, adapter) } // NewEventHub ... -func NewEventHub(client fc.Client) (EventHub, error) { +func NewEventHub(client api.FabricClient) (api.EventHub, error) { if client == nil { return nil, fmt.Errorf("Client is nil") } - chaincodeRegistrants := make(map[string][]*ChainCodeCBE) + chaincodeRegistrants := make(map[string][]*api.ChainCodeCBE) txRegistrants := make(map[string]func(string, pb.TxValidationCode, error)) eventHub := &eventHub{ @@ -371,16 +329,16 @@ func (eventHub *eventHub) Disconnected(err error) { * @returns {object} ChainCodeCBE object that should be treated as an opaque * handle used to unregister (see unregisterChaincodeEvent) */ -func (eventHub *eventHub) RegisterChaincodeEvent(ccid string, eventname string, callback func(*ChaincodeEvent)) *ChainCodeCBE { +func (eventHub *eventHub) RegisterChaincodeEvent(ccid string, eventname string, callback func(*api.ChaincodeEvent)) *api.ChainCodeCBE { eventHub.mtx.Lock() defer eventHub.mtx.Unlock() eventHub.addChaincodeInterest(ccid, eventname) - cbe := ChainCodeCBE{CCID: ccid, EventNameFilter: eventname, CallbackFunc: callback} + cbe := api.ChainCodeCBE{CCID: ccid, EventNameFilter: eventname, CallbackFunc: callback} cbeArray := eventHub.chaincodeRegistrants[ccid] if cbeArray == nil && len(cbeArray) <= 0 { - cbeArray = make([]*ChainCodeCBE, 0) + cbeArray = make([]*api.ChainCodeCBE, 0) cbeArray = append(cbeArray, &cbe) eventHub.chaincodeRegistrants[ccid] = cbeArray } else { @@ -396,7 +354,7 @@ func (eventHub *eventHub) RegisterChaincodeEvent(ccid string, eventname string, * @param {object} ChainCodeCBE handle returned from call to * registerChaincodeEvent. */ -func (eventHub *eventHub) UnregisterChaincodeEvent(cbe *ChainCodeCBE) { +func (eventHub *eventHub) UnregisterChaincodeEvent(cbe *api.ChainCodeCBE) { eventHub.mtx.Lock() defer eventHub.mtx.Unlock() @@ -506,7 +464,7 @@ func (eventHub *eventHub) getBlockRegistrants() []func(*common.Block) { return clone } -func (eventHub *eventHub) getChaincodeRegistrants(chaincodeID string) []*ChainCodeCBE { +func (eventHub *eventHub) getChaincodeRegistrants(chaincodeID string) []*api.ChainCodeCBE { eventHub.mtx.RLock() defer eventHub.mtx.RUnlock() @@ -516,7 +474,7 @@ func (eventHub *eventHub) getChaincodeRegistrants(chaincodeID string) []*ChainCo } // Return a clone of the array to avoid race conditions - clone := make([]*ChainCodeCBE, len(registrants)) + clone := make([]*api.ChainCodeCBE, len(registrants)) for i, registrants := range registrants { clone[i] = registrants } @@ -598,7 +556,7 @@ func (eventHub *eventHub) notifyChaincodeRegistrants(channelID string, ccEvent * if match { callback := v.CallbackFunc if callback != nil { - callback(&ChaincodeEvent{ + callback(&api.ChaincodeEvent{ ChaincodeID: ccEvent.ChaincodeId, TxID: ccEvent.TxId, EventName: ccEvent.EventName, diff --git a/fabric-client/events/eventhub_test.go b/pkg/fabric-client/events/eventhub_test.go similarity index 95% rename from fabric-client/events/eventhub_test.go rename to pkg/fabric-client/events/eventhub_test.go index 8d71de65e7..9e2b70f832 100644 --- a/fabric-client/events/eventhub_test.go +++ b/pkg/fabric-client/events/eventhub_test.go @@ -17,16 +17,12 @@ import ( "reflect" - "github.com/hyperledger/fabric-sdk-go/config" + api "github.com/hyperledger/fabric-sdk-go/api" "github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric/protos/peer" ) func TestMain(m *testing.M) { - err := config.InitConfig("../../test/fixtures/config/config_test.yaml") - if err != nil { - fmt.Println(err.Error()) - } os.Exit(m.Run()) } @@ -81,7 +77,7 @@ func TestDeadlock(t *testing.T) { go flood(eventsPerThread, threads, func() { eventName := generateTxID() received := newCompletionHandler(timeout) - registration := eventHub.RegisterChaincodeEvent(ccID, eventName, func(event *ChaincodeEvent) { + registration := eventHub.RegisterChaincodeEvent(ccID, eventName, func(event *api.ChaincodeEvent) { ccCompletion.done() received.done() }) @@ -131,10 +127,10 @@ func TestChaincodeEvent(t *testing.T) { t.Fatalf("No client") } - eventReceived := make(chan *ChaincodeEvent) + eventReceived := make(chan *api.ChaincodeEvent) // Register for CC event - registration := eventHub.RegisterChaincodeEvent(ccID, eventName, func(event *ChaincodeEvent) { + registration := eventHub.RegisterChaincodeEvent(ccID, eventName, func(event *api.ChaincodeEvent) { eventReceived <- event }) @@ -147,7 +143,7 @@ func TestChaincodeEvent(t *testing.T) { }) // Wait for the CC event - var event *ChaincodeEvent + var event *api.ChaincodeEvent select { case event = <-eventReceived: eventHub.UnregisterChaincodeEvent(registration) @@ -180,10 +176,10 @@ func TestChaincodeBlockEvent(t *testing.T) { t.Fatalf("No client") } - eventReceived := make(chan *ChaincodeEvent) + eventReceived := make(chan *api.ChaincodeEvent) // Register for CC event - registration := eventHub.RegisterChaincodeEvent(ccID, eventName, func(event *ChaincodeEvent) { + registration := eventHub.RegisterChaincodeEvent(ccID, eventName, func(event *api.ChaincodeEvent) { eventReceived <- event }) @@ -198,7 +194,7 @@ func TestChaincodeBlockEvent(t *testing.T) { }) // Wait for CC event - var event *ChaincodeEvent + var event *api.ChaincodeEvent select { case event = <-eventReceived: eventHub.UnregisterChaincodeEvent(registration) @@ -383,6 +379,6 @@ func TestRegisterChaincodeEvent(t *testing.T) { } // private test callback to be executed on chaincode event -func testChaincodeCallback(ce *ChaincodeEvent) { +func testChaincodeCallback(ce *api.ChaincodeEvent) { fmt.Printf("Received CC event: %v\n", ce) } diff --git a/fabric-client/events/eventmocks.go b/pkg/fabric-client/events/eventmocks.go similarity index 84% rename from fabric-client/events/eventmocks.go rename to pkg/fabric-client/events/eventmocks.go index d5bc5a566f..9c78b12245 100644 --- a/fabric-client/events/eventmocks.go +++ b/pkg/fabric-client/events/eventmocks.go @@ -12,9 +12,12 @@ import ( "testing" "time" - "github.com/hyperledger/fabric-sdk-go/config" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - consumer "github.com/hyperledger/fabric-sdk-go/fabric-client/events/consumer" + api "github.com/hyperledger/fabric-sdk-go/api" + client "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/client" + mocks "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks" + + internal "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal" + "github.com/hyperledger/fabric/bccsp" "github.com/hyperledger/fabric/bccsp/factory" bccspFactory "github.com/hyperledger/fabric/bccsp/factory" @@ -45,7 +48,7 @@ type mockEventClientFactory struct { clients []*mockEventClient } -func (mecf *mockEventClientFactory) newEventsClient(client fabricClient.Client, peerAddress string, certificate string, serverHostOverride string, regTimeout time.Duration, adapter fcConsumer.EventAdapter) (consumer.EventsClient, error) { +func (mecf *mockEventClientFactory) newEventsClient(client api.FabricClient, peerAddress string, certificate string, serverHostOverride string, regTimeout time.Duration, adapter fcConsumer.EventAdapter) (api.EventsClient, error) { mec := &mockEventClient{ PeerAddress: peerAddress, RegTimeout: regTimeout, @@ -109,11 +112,11 @@ func (mec *mockEventClient) Stop() error { func createMockedEventHub(t *testing.T) (*eventHub, *mockEventClientFactory) { // Initialize bccsp factories before calling get client - err := bccspFactory.InitFactories(config.GetCSPConfig()) + err := bccspFactory.InitFactories(mocks.NewMockConfig().GetCSPConfig()) if err != nil { t.Fatalf("Failed getting ephemeral software-based BCCSP [%s]", err) } - eh, err := NewEventHub(fabricClient.NewClient()) + eh, err := NewEventHub(client.NewClient(mocks.NewMockConfig())) if err != nil { t.Fatalf("Error creating event hub: %v", err) } @@ -166,7 +169,7 @@ func (b *MockTxEventBuilder) Build() *pb.Event_Block { Header: &common.BlockHeader{}, Metadata: b.buildBlockMetadata(), Data: &common.BlockData{ - Data: [][]byte{fabricClient.MarshalOrPanic(b.buildEnvelope())}, + Data: [][]byte{internal.MarshalOrPanic(b.buildEnvelope())}, }, }, } @@ -200,14 +203,14 @@ func (b *MockCCEventBuilder) Build() *pb.Event_ChaincodeEvent { func (b *MockTxEventBuilder) buildEnvelope() *common.Envelope { return &common.Envelope{ - Payload: fabricClient.MarshalOrPanic(b.buildPayload()), + Payload: internal.MarshalOrPanic(b.buildPayload()), } } func (b *MockTxEventBuilder) buildPayload() *common.Payload { return &common.Payload{ Header: &common.Header{ - ChannelHeader: fabricClient.MarshalOrPanic(b.buildChannelHeader()), + ChannelHeader: internal.MarshalOrPanic(b.buildChannelHeader()), }, } } @@ -226,7 +229,7 @@ func (b *MockCCBlockEventBuilder) Build() *pb.Event_Block { Header: &common.BlockHeader{}, Metadata: b.buildBlockMetadata(), Data: &common.BlockData{ - Data: [][]byte{fabricClient.MarshalOrPanic(b.buildEnvelope())}, + Data: [][]byte{internal.MarshalOrPanic(b.buildEnvelope())}, }, }, } @@ -245,7 +248,7 @@ func (b *MockCCBlockEventBuilder) buildBlockMetadata() *common.BlockMetadata { func (b *MockCCBlockEventBuilder) buildEnvelope() *common.Envelope { return &common.Envelope{ - Payload: fabricClient.MarshalOrPanic(b.buildPayload()), + Payload: internal.MarshalOrPanic(b.buildPayload()), } } @@ -257,9 +260,9 @@ func (b *MockCCBlockEventBuilder) buildPayload() *common.Payload { fmt.Printf("MockCCBlockEventBuilder.buildPayload\n") return &common.Payload{ Header: &common.Header{ - ChannelHeader: fabricClient.MarshalOrPanic(b.buildChannelHeader()), + ChannelHeader: internal.MarshalOrPanic(b.buildChannelHeader()), }, - Data: fabricClient.MarshalOrPanic(b.buildTransaction()), + Data: internal.MarshalOrPanic(b.buildTransaction()), } } @@ -280,7 +283,7 @@ func (b *MockCCBlockEventBuilder) buildTransaction() *pb.Transaction { func (b *MockCCBlockEventBuilder) buildTransactionAction() *pb.TransactionAction { return &pb.TransactionAction{ Header: []byte{}, - Payload: fabricClient.MarshalOrPanic(b.buildChaincodeActionPayload()), + Payload: internal.MarshalOrPanic(b.buildChaincodeActionPayload()), } } @@ -293,7 +296,7 @@ func (b *MockCCBlockEventBuilder) buildChaincodeActionPayload() *pb.ChaincodeAct func (b *MockCCBlockEventBuilder) buildChaincodeEndorsedAction() *pb.ChaincodeEndorsedAction { return &pb.ChaincodeEndorsedAction{ - ProposalResponsePayload: fabricClient.MarshalOrPanic(b.buildProposalResponsePayload()), + ProposalResponsePayload: internal.MarshalOrPanic(b.buildProposalResponsePayload()), Endorsements: []*pb.Endorsement{}, } } @@ -301,13 +304,13 @@ func (b *MockCCBlockEventBuilder) buildChaincodeEndorsedAction() *pb.ChaincodeEn func (b *MockCCBlockEventBuilder) buildProposalResponsePayload() *pb.ProposalResponsePayload { return &pb.ProposalResponsePayload{ ProposalHash: []byte("somehash"), - Extension: fabricClient.MarshalOrPanic(b.buildChaincodeAction()), + Extension: internal.MarshalOrPanic(b.buildChaincodeAction()), } } func (b *MockCCBlockEventBuilder) buildChaincodeAction() *pb.ChaincodeAction { return &pb.ChaincodeAction{ - Events: fabricClient.MarshalOrPanic(b.buildChaincodeEvent()), + Events: internal.MarshalOrPanic(b.buildChaincodeEvent()), } } @@ -321,7 +324,7 @@ func (b *MockCCBlockEventBuilder) buildChaincodeEvent() *pb.ChaincodeEvent { } func generateTxID() string { - nonce, err := fabricClient.GenerateRandomNonce() + nonce, err := internal.GenerateRandomNonce() if err != nil { panic(fmt.Errorf("error generating nonce: %v", err)) } diff --git a/fabric-client/util.go b/pkg/fabric-client/internal/util.go similarity index 99% rename from fabric-client/util.go rename to pkg/fabric-client/internal/util.go index 1ae16b6131..7502d185da 100644 --- a/fabric-client/util.go +++ b/pkg/fabric-client/internal/util.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package internal import ( "fmt" @@ -36,15 +36,6 @@ func CreateSeekGenesisBlockRequest(channelName string, creator []byte) []byte { }) } -// MarshalOrPanic serializes a protobuf message and panics if this operation fails. -func MarshalOrPanic(pb proto.Message) []byte { - data, err := proto.Marshal(pb) - if err != nil { - panic(err) - } - return data -} - // GenerateRandomNonce generates a random nonce func GenerateRandomNonce() ([]byte, error) { return crypto.GetRandomNonce() @@ -117,3 +108,12 @@ func SignObjectWithKey(object []byte, key bccsp.Key, } return signature, nil } + +// MarshalOrPanic serializes a protobuf message and panics if this operation fails. +func MarshalOrPanic(pb proto.Message) []byte { + data, err := proto.Marshal(pb) + if err != nil { + panic(err) + } + return data +} diff --git a/fabric-client/keyvaluestore/filekeyvaluestore.go b/pkg/fabric-client/keyvaluestore/filekeyvaluestore.go similarity index 100% rename from fabric-client/keyvaluestore/filekeyvaluestore.go rename to pkg/fabric-client/keyvaluestore/filekeyvaluestore.go diff --git a/fabric-client/keyvaluestore/filekeyvaluestore_test.go b/pkg/fabric-client/keyvaluestore/filekeyvaluestore_test.go similarity index 100% rename from fabric-client/keyvaluestore/filekeyvaluestore_test.go rename to pkg/fabric-client/keyvaluestore/filekeyvaluestore_test.go diff --git a/fabric-client/mockbroadcastserver.go b/pkg/fabric-client/mocks/mockbroadcastserver.go similarity index 98% rename from fabric-client/mockbroadcastserver.go rename to pkg/fabric-client/mocks/mockbroadcastserver.go index 6a47173ecb..9b7529f1f8 100644 --- a/fabric-client/mockbroadcastserver.go +++ b/pkg/fabric-client/mocks/mockbroadcastserver.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package mocks import ( "github.com/hyperledger/fabric/protos/common" diff --git a/pkg/fabric-client/mocks/mockclient.go b/pkg/fabric-client/mocks/mockclient.go new file mode 100644 index 0000000000..07c266d4e6 --- /dev/null +++ b/pkg/fabric-client/mocks/mockclient.go @@ -0,0 +1,144 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package mocks + +import ( + "fmt" + + api "github.com/hyperledger/fabric-sdk-go/api" + + "github.com/hyperledger/fabric/bccsp" + "github.com/hyperledger/fabric/protos/common" + pb "github.com/hyperledger/fabric/protos/peer" +) + +// MockClient ... +type MockClient struct { + channels map[string]api.Channel + cryptoSuite bccsp.BCCSP + stateStore api.KeyValueStore + userContext api.User + config api.Config +} + +// NewMockClient ... +/* + * Returns a FabricClient instance + */ +func NewMockClient() api.FabricClient { + channels := make(map[string]api.Channel) + c := &MockClient{channels: channels, cryptoSuite: nil, stateStore: nil, userContext: nil, config: NewMockConfig()} + return c +} + +// NewChannel ... +func (c *MockClient) NewChannel(name string) (api.Channel, error) { + return nil, nil +} + +// GetChannel ... +func (c *MockClient) GetChannel(name string) api.Channel { + return c.channels[name] +} + +// GetConfig ... +func (c *MockClient) GetConfig() api.Config { + return c.config +} + +// QueryChannelInfo ... +func (c *MockClient) QueryChannelInfo(name string, peers []api.Peer) (api.Channel, error) { + return nil, fmt.Errorf("Not implemented yet") +} + +// SetStateStore ... +func (c *MockClient) SetStateStore(stateStore api.KeyValueStore) { + c.stateStore = stateStore +} + +// GetStateStore ... +func (c *MockClient) GetStateStore() api.KeyValueStore { + return c.stateStore +} + +// SetCryptoSuite ... +func (c *MockClient) SetCryptoSuite(cryptoSuite bccsp.BCCSP) { + c.cryptoSuite = cryptoSuite +} + +// GetCryptoSuite ... +func (c *MockClient) GetCryptoSuite() bccsp.BCCSP { + return c.cryptoSuite +} + +// SaveUserToStateStore ... +func (c *MockClient) SaveUserToStateStore(user api.User, skipPersistence bool) error { + return fmt.Errorf("Not implemented yet") + +} + +// LoadUserFromStateStore ... +func (c *MockClient) LoadUserFromStateStore(name string) (api.User, error) { + return NewMockUser("test"), nil +} + +// ExtractChannelConfig ... +func (c *MockClient) ExtractChannelConfig(configEnvelope []byte) ([]byte, error) { + return nil, fmt.Errorf("Not implemented yet") + +} + +// SignChannelConfig ... +func (c *MockClient) SignChannelConfig(config []byte) (*common.ConfigSignature, error) { + return nil, fmt.Errorf("Not implemented yet") + +} + +// CreateChannel ... +func (c *MockClient) CreateChannel(request *api.CreateChannelRequest) error { + return fmt.Errorf("Not implemented yet") + +} + +// CreateOrUpdateChannel ... +func (c *MockClient) CreateOrUpdateChannel(request *api.CreateChannelRequest, haveEnvelope bool) error { + return fmt.Errorf("Not implemented yet") + +} + +//QueryChannels ... +func (c *MockClient) QueryChannels(peer api.Peer) (*pb.ChannelQueryResponse, error) { + return nil, fmt.Errorf("Not implemented yet") +} + +//QueryInstalledChaincodes ... +func (c *MockClient) QueryInstalledChaincodes(peer api.Peer) (*pb.ChaincodeQueryResponse, error) { + return nil, fmt.Errorf("Not implemented yet") +} + +// InstallChaincode ... +func (c *MockClient) InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, + chaincodePackage []byte, targets []api.Peer) ([]*api.TransactionProposalResponse, string, error) { + return nil, "", fmt.Errorf("Not implemented yet") + +} + +// GetIdentity returns MockClient's serialized identity +func (c *MockClient) GetIdentity() ([]byte, error) { + return []byte("test"), nil + +} + +// GetUserContext ... +func (c *MockClient) GetUserContext() api.User { + return c.userContext +} + +// SetUserContext ... +func (c *MockClient) SetUserContext(user api.User) { + c.userContext = user +} diff --git a/pkg/fabric-client/mocks/mockconfig.go b/pkg/fabric-client/mocks/mockconfig.go new file mode 100644 index 0000000000..dc4548cb1f --- /dev/null +++ b/pkg/fabric-client/mocks/mockconfig.go @@ -0,0 +1,152 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package mocks + +import ( + "crypto/x509" + + api "github.com/hyperledger/fabric-sdk-go/api" + + bccspFactory "github.com/hyperledger/fabric/bccsp/factory" + "github.com/spf13/viper" +) + +// MockConfig ... +type MockConfig struct { +} + +// NewMockConfig ... +func NewMockConfig() api.Config { + return &MockConfig{} +} + +//GetServerURL Read configuration option for the fabric CA server URL +func (c *MockConfig) GetServerURL() string { + return "" +} + +//GetServerCertFiles Read configuration option for the server certificate files +func (c *MockConfig) GetServerCertFiles() []string { + return nil +} + +//GetFabricCAClientKeyFile Read configuration option for the fabric CA client key file +func (c *MockConfig) GetFabricCAClientKeyFile() string { + return "" +} + +//GetFabricCAClientCertFile Read configuration option for the fabric CA client cert file +func (c *MockConfig) GetFabricCAClientCertFile() string { + return "" +} + +//GetFabricCATLSEnabledFlag Read configuration option for the fabric CA TLS flag +func (c *MockConfig) GetFabricCATLSEnabledFlag() bool { + return false +} + +// GetFabricClientViper returns the internal viper instance used by the +// SDK to read configuration options +func (c *MockConfig) GetFabricClientViper() *viper.Viper { + return nil +} + +// GetPeersConfig Retrieves the fabric peers from the config file provided +func (c *MockConfig) GetPeersConfig() ([]api.PeerConfig, error) { + return nil, nil +} + +// IsTLSEnabled ... +func (c *MockConfig) IsTLSEnabled() bool { + return false +} + +// GetTLSCACertPool ... +func (c *MockConfig) GetTLSCACertPool(tlsCertificate string) (*x509.CertPool, error) { + return nil, nil +} + +// GetTLSCACertPoolFromRoots ... +func (c *MockConfig) GetTLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) { + return nil, nil +} + +// IsSecurityEnabled ... +func (c *MockConfig) IsSecurityEnabled() bool { + return false +} + +// TcertBatchSize ... +func (c *MockConfig) TcertBatchSize() int { + return 0 +} + +// GetSecurityAlgorithm ... +func (c *MockConfig) GetSecurityAlgorithm() string { + return "" +} + +// GetSecurityLevel ... +func (c *MockConfig) GetSecurityLevel() int { + return 0 + +} + +// GetOrdererHost ... +func (c *MockConfig) GetOrdererHost() string { + return "" +} + +// GetOrdererPort ... +func (c *MockConfig) GetOrdererPort() string { + return "" +} + +// GetOrdererTLSServerHostOverride ... +func (c *MockConfig) GetOrdererTLSServerHostOverride() string { + return "" +} + +// GetOrdererTLSCertificate ... +func (c *MockConfig) GetOrdererTLSCertificate() string { + return "" +} + +// GetFabricCAID ... +func (c *MockConfig) GetFabricCAID() string { + return "" +} + +//GetFabricCAName Read the fabric CA name +func (c *MockConfig) GetFabricCAName() string { + return "" +} + +// GetKeyStorePath ... +func (c *MockConfig) GetKeyStorePath() string { + return "" +} + +// GetFabricCAHomeDir ... +func (c *MockConfig) GetFabricCAHomeDir() string { + return "" +} + +// GetFabricCAMspDir ... +func (c *MockConfig) GetFabricCAMspDir() string { + return "" +} + +// GetCryptoConfigPath ... +func (c *MockConfig) GetCryptoConfigPath() string { + return "" +} + +// GetCSPConfig ... +func (c *MockConfig) GetCSPConfig() *bccspFactory.FactoryOpts { + return nil +} diff --git a/fabric-client/mockcryptosuite.go b/pkg/fabric-client/mocks/mockcryptosuite.go similarity index 98% rename from fabric-client/mockcryptosuite.go rename to pkg/fabric-client/mocks/mockcryptosuite.go index 1bc9b94e91..2a90480a5b 100644 --- a/fabric-client/mockcryptosuite.go +++ b/pkg/fabric-client/mocks/mockcryptosuite.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package mocks import ( "hash" diff --git a/fabric-client/mockdata.go b/pkg/fabric-client/mocks/mockdata.go similarity index 89% rename from fabric-client/mockdata.go rename to pkg/fabric-client/mocks/mockdata.go index ce4f13da4e..b9113d9c6b 100644 --- a/fabric-client/mockdata.go +++ b/pkg/fabric-client/mocks/mockdata.go @@ -4,9 +4,10 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package mocks import ( + "github.com/golang/protobuf/proto" fabric_config "github.com/hyperledger/fabric/common/config" ledger_util "github.com/hyperledger/fabric/core/ledger/util" "github.com/hyperledger/fabric/protos/common" @@ -68,7 +69,7 @@ func (b *MockConfigBlockBuilder) buildBlockMetadata() *common.BlockMetadata { return &common.BlockMetadata{ Metadata: [][]byte{ b.buildSignaturesMetaDataBytes(), - MarshalOrPanic(b.buildLastConfigMetaData()), + marshalOrPanic(b.buildLastConfigMetaData()), b.buildTransactionsFilterMetaDataBytes(), b.buildOrdererMetaDataBytes(), }, @@ -81,7 +82,7 @@ func (b *MockConfigBlockBuilder) buildSignaturesMetaDataBytes() []byte { func (b *MockConfigBlockBuilder) buildLastConfigMetaData() *common.Metadata { return &common.Metadata{ - Value: MarshalOrPanic(b.buildLastConfig()), + Value: marshalOrPanic(b.buildLastConfig()), } } @@ -99,25 +100,25 @@ func (b *MockConfigBlockBuilder) buildLastConfig() *common.LastConfig { } func (b *MockConfigBlockBuilder) buildBlockEnvelopeBytes() [][]byte { - return [][]byte{MarshalOrPanic(b.buildEnvelope())} + return [][]byte{marshalOrPanic(b.buildEnvelope())} } func (b *MockConfigBlockBuilder) buildEnvelope() *common.Envelope { return &common.Envelope{ - Payload: MarshalOrPanic(b.buildPayload()), + Payload: marshalOrPanic(b.buildPayload()), } } func (b *MockConfigBlockBuilder) buildPayload() *common.Payload { return &common.Payload{ Header: b.buildHeader(), - Data: MarshalOrPanic(b.buildConfigEnvelope()), + Data: marshalOrPanic(b.buildConfigEnvelope()), } } func (b *MockConfigBlockBuilder) buildHeader() *common.Header { return &common.Header{ - ChannelHeader: MarshalOrPanic(b.buildChannelHeader()), + ChannelHeader: marshalOrPanic(b.buildChannelHeader()), } } @@ -162,7 +163,7 @@ func (b *MockConfigGroupBuilder) buildOrdererAddressesConfigValue() *common.Conf return &common.ConfigValue{ Version: b.Version, ModPolicy: b.ModPolicy, - Value: MarshalOrPanic(b.buildOrdererAddresses())} + Value: marshalOrPanic(b.buildOrdererAddresses())} } func (b *MockConfigGroupBuilder) buildOrdererAddresses() *common.OrdererAddresses { @@ -212,14 +213,14 @@ func (b *MockConfigGroupBuilder) buildMSPConfigValue(name string) *common.Config return &common.ConfigValue{ Version: b.Version, ModPolicy: b.ModPolicy, - Value: MarshalOrPanic(b.buildMSPConfig(name))} + Value: marshalOrPanic(b.buildMSPConfig(name))} } func (b *MockConfigGroupBuilder) buildBatchSizeConfigValue() *common.ConfigValue { return &common.ConfigValue{ Version: b.Version, ModPolicy: b.ModPolicy, - Value: MarshalOrPanic(b.buildBatchSize())} + Value: marshalOrPanic(b.buildBatchSize())} } func (b *MockConfigGroupBuilder) buildBatchSize() *ab.BatchSize { @@ -233,7 +234,7 @@ func (b *MockConfigGroupBuilder) buildBatchSize() *ab.BatchSize { func (b *MockConfigGroupBuilder) buildMSPConfig(name string) *mb.MSPConfig { return &mb.MSPConfig{ Type: 0, - Config: MarshalOrPanic(b.buildfabricMSPConfig(name)), + Config: marshalOrPanic(b.buildfabricMSPConfig(name)), } } @@ -268,7 +269,7 @@ func (b *MockConfigGroupBuilder) buildSignatureConfigPolicy() *common.ConfigPoli func (b *MockConfigGroupBuilder) buildSignaturePolicy() *common.Policy { return &common.Policy{ Type: int32(common.Policy_SIGNATURE), - Value: MarshalOrPanic(b.buildSignedBySignaturePolicy()), + Value: marshalOrPanic(b.buildSignedBySignaturePolicy()), } } @@ -305,25 +306,25 @@ func (b *MockConfigGroupBuilder) buildApplicationGroup() *common.ConfigGroup { // Build builds an Envelope that contains a mock ConfigUpdateEnvelope func (b *MockConfigUpdateEnvelopeBuilder) Build() *common.Envelope { return &common.Envelope{ - Payload: MarshalOrPanic(b.buildPayload()), + Payload: marshalOrPanic(b.buildPayload()), } } // BuildBytes builds an Envelope that contains a mock ConfigUpdateEnvelope and returns the marshaled bytes func (b *MockConfigUpdateEnvelopeBuilder) BuildBytes() []byte { - return MarshalOrPanic(b.Build()) + return marshalOrPanic(b.Build()) } func (b *MockConfigUpdateEnvelopeBuilder) buildPayload() *common.Payload { return &common.Payload{ Header: b.buildHeader(), - Data: MarshalOrPanic(b.buildConfigUpdateEnvelope()), + Data: marshalOrPanic(b.buildConfigUpdateEnvelope()), } } func (b *MockConfigUpdateEnvelopeBuilder) buildHeader() *common.Header { return &common.Header{ - ChannelHeader: MarshalOrPanic(&common.ChannelHeader{ + ChannelHeader: marshalOrPanic(&common.ChannelHeader{ Type: int32(common.HeaderType_CONFIG_UPDATE)}, ), } @@ -331,7 +332,7 @@ func (b *MockConfigUpdateEnvelopeBuilder) buildHeader() *common.Header { func (b *MockConfigUpdateEnvelopeBuilder) buildConfigUpdateEnvelope() *common.ConfigUpdateEnvelope { return &common.ConfigUpdateEnvelope{ - ConfigUpdate: MarshalOrPanic(b.buildConfigUpdate()), + ConfigUpdate: marshalOrPanic(b.buildConfigUpdate()), Signatures: nil, } } @@ -343,3 +344,12 @@ func (b *MockConfigUpdateEnvelopeBuilder) buildConfigUpdate() *common.ConfigUpda WriteSet: b.buildConfigGroup(), } } + +// marshalOrPanic serializes a protobuf message and panics if this operation fails. +func marshalOrPanic(pb proto.Message) []byte { + data, err := proto.Marshal(pb) + if err != nil { + panic(err) + } + return data +} diff --git a/fabric-client/mockendorserserver.go b/pkg/fabric-client/mocks/mockendorserserver.go similarity index 98% rename from fabric-client/mockendorserserver.go rename to pkg/fabric-client/mocks/mockendorserserver.go index 5636d12c3b..5db9302f5a 100644 --- a/fabric-client/mockendorserserver.go +++ b/pkg/fabric-client/mocks/mockendorserserver.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package mocks import ( "github.com/golang/protobuf/proto" diff --git a/fabric-client/mockorderer.go b/pkg/fabric-client/mocks/mockorderer.go similarity index 84% rename from fabric-client/mockorderer.go rename to pkg/fabric-client/mocks/mockorderer.go index 2a60ee6a37..4999b439a0 100644 --- a/fabric-client/mockorderer.go +++ b/pkg/fabric-client/mocks/mockorderer.go @@ -4,11 +4,13 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package mocks import ( "fmt" + api "github.com/hyperledger/fabric-sdk-go/api" + "github.com/hyperledger/fabric/protos/common" ) @@ -17,7 +19,7 @@ import ( // that the broadcast side and the deliver side are totally // independent from the mocking point of view. type MockOrderer interface { - Orderer + api.Orderer // Enqueues a mock error to be returned to the client calling SendBroadcast EnqueueSendBroadcastError(err error) // Enqueues a mock value (block or error) for delivery @@ -25,24 +27,24 @@ type MockOrderer interface { } type mockOrderer struct { URL string - BroadcastListener chan *SignedEnvelope + BroadcastListener chan *api.SignedEnvelope BroadcastErrors chan error Deliveries chan *common.Block DeliveryErrors chan error // These queues are used to detach the client, to avoid deadlocks - BroadcastQueue chan *SignedEnvelope + BroadcastQueue chan *api.SignedEnvelope DeliveryQueue chan interface{} } // NewMockOrderer ... -func NewMockOrderer(url string, broadcastListener chan *SignedEnvelope) Orderer { +func NewMockOrderer(url string, broadcastListener chan *api.SignedEnvelope) api.Orderer { o := &mockOrderer{ URL: url, BroadcastListener: broadcastListener, BroadcastErrors: make(chan error, 100), Deliveries: make(chan *common.Block, 1), DeliveryErrors: make(chan error, 1), - BroadcastQueue: make(chan *SignedEnvelope, 100), + BroadcastQueue: make(chan *api.SignedEnvelope, 100), DeliveryQueue: make(chan interface{}, 100), } @@ -79,7 +81,7 @@ func (o *mockOrderer) GetURL() string { // SendBroadcast accepts client broadcast calls and reports them to the listener channel // Returns the first enqueued error, or nil if there are no enqueued errors -func (o *mockOrderer) SendBroadcast(envelope *SignedEnvelope) (*common.Status, error) { +func (o *mockOrderer) SendBroadcast(envelope *api.SignedEnvelope) (*common.Status, error) { // Report this call to the listener if o.BroadcastListener != nil { o.BroadcastQueue <- envelope @@ -93,7 +95,7 @@ func (o *mockOrderer) SendBroadcast(envelope *SignedEnvelope) (*common.Status, e } // SendDeliver returns the channels for delivery of prepared mock values and errors (if any) -func (o *mockOrderer) SendDeliver(envelope *SignedEnvelope) (chan *common.Block, +func (o *mockOrderer) SendDeliver(envelope *api.SignedEnvelope) (chan *common.Block, chan error) { return o.Deliveries, o.DeliveryErrors } diff --git a/fabric-client/mockpeer.go b/pkg/fabric-client/mocks/mockpeer.go similarity index 62% rename from fabric-client/mockpeer.go rename to pkg/fabric-client/mocks/mockpeer.go index 01a748504b..c6802da1de 100644 --- a/fabric-client/mockpeer.go +++ b/pkg/fabric-client/mocks/mockpeer.go @@ -4,18 +4,20 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package mocks // TODO: Move protos to this library import ( "encoding/pem" "errors" + api "github.com/hyperledger/fabric-sdk-go/api" + pb "github.com/hyperledger/fabric/protos/peer" ) -// mockPeer is a mock fabricsdk.Peer. -type mockPeer struct { +// MockPeer is a mock fabricsdk.Peer. +type MockPeer struct { MockName string MockURL string MockRoles []string @@ -23,63 +25,63 @@ type mockPeer struct { } // ConnectEventSource does not connect anywhere -func (p *mockPeer) ConnectEventSource() { +func (p *MockPeer) ConnectEventSource() { // done. } // IsEventListened always returns true -func (p *mockPeer) IsEventListened(event string, chain Chain) (bool, error) { +func (p *MockPeer) IsEventListened(event string, chain api.Channel) (bool, error) { return true, nil } // AddListener is not implemented -func (p *mockPeer) AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error) { +func (p *MockPeer) AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error) { return "", errors.New("Not implemented") } // RemoveListener is not implemented -func (p *mockPeer) RemoveListener(eventListenerRef string) (bool, error) { +func (p *MockPeer) RemoveListener(eventListenerRef string) (bool, error) { return false, errors.New("Not implemented") } // GetName returns the mock peer's mock name -func (p mockPeer) GetName() string { +func (p MockPeer) GetName() string { return p.MockName } // SetName sets the mock peer's mock name -func (p *mockPeer) SetName(name string) { +func (p *MockPeer) SetName(name string) { p.MockName = name } // GetRoles returns the mock peer's mock roles -func (p *mockPeer) GetRoles() []string { +func (p *MockPeer) GetRoles() []string { return p.MockRoles } // SetRoles sets the mock peer's mock roles -func (p *mockPeer) SetRoles(roles []string) { +func (p *MockPeer) SetRoles(roles []string) { p.MockRoles = roles } // GetEnrollmentCertificate returns the mock peer's mock enrollment certificate -func (p *mockPeer) GetEnrollmentCertificate() *pem.Block { +func (p *MockPeer) GetEnrollmentCertificate() *pem.Block { return p.MockCert } // SetEnrollmentCertificate sets the mock peer's mock enrollment certificate -func (p *mockPeer) SetEnrollmentCertificate(pem *pem.Block) { +func (p *MockPeer) SetEnrollmentCertificate(pem *pem.Block) { p.MockCert = pem } // GetURL returns the mock peer's mock URL -func (p *mockPeer) GetURL() string { +func (p *MockPeer) GetURL() string { return p.MockURL } // SendProposal does not send anything anywhere but returns an empty mock ProposalResponse -func (p *mockPeer) SendProposal(tp *TransactionProposal) (*TransactionProposalResponse, error) { - return &TransactionProposalResponse{ +func (p *MockPeer) SendProposal(tp *api.TransactionProposal) (*api.TransactionProposalResponse, error) { + return &api.TransactionProposalResponse{ Endorser: p.MockURL, Proposal: tp, ProposalResponse: &pb.ProposalResponse{}, diff --git a/pkg/fabric-client/mocks/mockuser.go b/pkg/fabric-client/mocks/mockuser.go new file mode 100644 index 0000000000..5a41ddc793 --- /dev/null +++ b/pkg/fabric-client/mocks/mockuser.go @@ -0,0 +1,101 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package mocks + +import ( + api "github.com/hyperledger/fabric-sdk-go/api" + "github.com/hyperledger/fabric/bccsp" +) + +// MockUser ... +type MockUser struct { + name string + roles []string + PrivateKey bccsp.Key // ****This key is temporary We use it to sign transaction until we have tcerts + enrollmentCertificate []byte +} + +// NewMockUser ... +/** + * Constructor for a user. + * + * @param {string} name - The user name + */ +func NewMockUser(name string) api.User { + return &MockUser{name: name} +} + +// GetName ... +/** + * Get the user name. + * @returns {string} The user name. + */ +func (u *MockUser) GetName() string { + return u.name +} + +// GetRoles ... +/** + * Get the roles. + * @returns {[]string} The roles. + */ +func (u *MockUser) GetRoles() []string { + return u.roles +} + +// SetRoles ... +/** + * Set the roles. + * @param roles {[]string} The roles. + */ +func (u *MockUser) SetRoles(roles []string) { + u.roles = roles +} + +// GetEnrollmentCertificate ... +/** + * Returns the underlying ECert representing this user’s identity. + */ +func (u *MockUser) GetEnrollmentCertificate() []byte { + return u.enrollmentCertificate +} + +// SetEnrollmentCertificate ... +/** + * Set the user’s Enrollment Certificate. + */ +func (u *MockUser) SetEnrollmentCertificate(cert []byte) { + u.enrollmentCertificate = cert +} + +// SetPrivateKey ... +/** + * deprecated. + */ +func (u *MockUser) SetPrivateKey(privateKey bccsp.Key) { + u.PrivateKey = privateKey +} + +// GetPrivateKey ... +/** + * deprecated. + */ +func (u *MockUser) GetPrivateKey() bccsp.Key { + return u.PrivateKey +} + +// GenerateTcerts ... +/** + * Gets a batch of TCerts to use for transaction. there is a 1-to-1 relationship between + * TCert and Transaction. The TCert can be generated locally by the SDK using the user’s crypto materials. + * @param {int} count how many in the batch to obtain + * @param {[]string} attributes list of attributes to include in the TCert + * @return {[]tcert} An array of TCerts + */ +func (u *MockUser) GenerateTcerts(count int, attributes []string) { + +} diff --git a/fabric-client/orderer.go b/pkg/fabric-client/orderer/orderer.go similarity index 82% rename from fabric-client/orderer.go rename to pkg/fabric-client/orderer/orderer.go index 68153055fa..c2a1e00b37 100644 --- a/fabric-client/orderer.go +++ b/pkg/fabric-client/orderer/orderer.go @@ -4,34 +4,24 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package orderer import ( "crypto/x509" "fmt" "time" - "github.com/hyperledger/fabric-sdk-go/config" + api "github.com/hyperledger/fabric-sdk-go/api" + "google.golang.org/grpc/credentials" + "github.com/hyperledger/fabric/protos/common" ab "github.com/hyperledger/fabric/protos/orderer" + "github.com/op/go-logging" "golang.org/x/net/context" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" ) -// A SignedEnvelope can can be sent to an orderer for broadcasting -type SignedEnvelope struct { - Payload []byte - Signature []byte -} - -// Orderer The Orderer class represents a peer in the target blockchain network to which -// HFC sends a block of transactions of endorsed proposals requiring ordering. -type Orderer interface { - GetURL() string - SendBroadcast(envelope *SignedEnvelope) (*common.Status, error) - SendDeliver(envelope *SignedEnvelope) (chan *common.Block, chan error) -} +var logger = logging.MustGetLogger("fabric_sdk_go") type orderer struct { url string @@ -39,7 +29,7 @@ type orderer struct { } // CreateNewOrdererWithRootCAs Returns a new Orderer instance using the passed in orderer root CAs -func CreateNewOrdererWithRootCAs(url string, ordererRootCAs [][]byte, serverHostOverride string) (Orderer, error) { +func CreateNewOrdererWithRootCAs(url string, ordererRootCAs [][]byte, serverHostOverride string, config api.Config) (api.Orderer, error) { if config.IsTLSEnabled() { tlsCaCertPool, err := config.GetTLSCACertPoolFromRoots(ordererRootCAs) if err != nil { @@ -50,14 +40,14 @@ func CreateNewOrdererWithRootCAs(url string, ordererRootCAs [][]byte, serverHost return createNewOrdererWithoutTLS(url), nil } -func createNewOrdererWithoutTLS(url string) Orderer { +func createNewOrdererWithoutTLS(url string) api.Orderer { var opts []grpc.DialOption opts = append(opts, grpc.WithTimeout(time.Second*3)) opts = append(opts, grpc.WithInsecure()) return &orderer{url: url, grpcDialOption: opts} } -func createNewOrdererWithCertPool(url string, tlsCaCertPool *x509.CertPool, serverHostOverride string) Orderer { +func createNewOrdererWithCertPool(url string, tlsCaCertPool *x509.CertPool, serverHostOverride string) api.Orderer { var opts []grpc.DialOption opts = append(opts, grpc.WithTimeout(time.Second*3)) creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride) @@ -72,7 +62,7 @@ func (o *orderer) GetURL() string { } // SendBroadcast Send the created transaction to Orderer. -func (o *orderer) SendBroadcast(envelope *SignedEnvelope) (*common.Status, error) { +func (o *orderer) SendBroadcast(envelope *api.SignedEnvelope) (*common.Status, error) { conn, err := grpc.Dial(o.url, o.grpcDialOption...) if err != nil { return nil, err @@ -124,7 +114,7 @@ func (o *orderer) SendBroadcast(envelope *SignedEnvelope) (*common.Status, error // @param {*SignedEnvelope} envelope that contains the seek request for blocks // @return {chan *common.Block} channel with the requested blocks // @return {chan error} a buffered channel that can contain a single error -func (o *orderer) SendDeliver(envelope *SignedEnvelope) (chan *common.Block, +func (o *orderer) SendDeliver(envelope *api.SignedEnvelope) (chan *common.Block, chan error) { responses := make(chan *common.Block) errors := make(chan error, 1) @@ -192,3 +182,20 @@ func (o *orderer) SendDeliver(envelope *SignedEnvelope) (chan *common.Block, return responses, errors } + +// NewOrderer Returns a Orderer instance +func NewOrderer(url string, certificate string, serverHostOverride string, config api.Config) (api.Orderer, error) { + var opts []grpc.DialOption + opts = append(opts, grpc.WithTimeout(time.Second*3)) + if config.IsTLSEnabled() { + tlsCaCertPool, err := config.GetTLSCACertPool(certificate) + if err != nil { + return nil, err + } + creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride) + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + opts = append(opts, grpc.WithInsecure()) + } + return &orderer{url: url, grpcDialOption: opts}, nil +} diff --git a/fabric-client/orderer_test.go b/pkg/fabric-client/orderer/orderer_test.go similarity index 79% rename from fabric-client/orderer_test.go rename to pkg/fabric-client/orderer/orderer_test.go index 0c60415a5e..e1a12663b6 100644 --- a/fabric-client/orderer_test.go +++ b/pkg/fabric-client/orderer/orderer_test.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package orderer import ( "fmt" @@ -12,6 +12,10 @@ import ( "testing" "time" + api "github.com/hyperledger/fabric-sdk-go/api" + client "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/client" + mocks "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks" + ab "github.com/hyperledger/fabric/protos/orderer" "google.golang.org/grpc" ) @@ -26,12 +30,12 @@ var testOrdererURL = "0.0.0.0:4584" // process by updating the orderer URL to a different address. // func TestOrdererViaChain(t *testing.T) { - client := NewClient() - chain, err := client.NewChain("testChain-orderer-member") + client := client.NewClient(mocks.NewMockConfig()) + chain, err := client.NewChannel("testChain-orderer-member") if err != nil { t.Fatalf("error from NewChain %v", err) } - orderer, _ := NewOrderer("localhost:7050", "", "") + orderer, _ := NewOrderer("localhost:7050", "", "", mocks.NewMockConfig()) err = chain.AddOrderer(orderer) if err != nil { t.Fatalf("Error adding orderer: %v", err) @@ -42,7 +46,7 @@ func TestOrdererViaChain(t *testing.T) { t.Fatalf("Failed to retieve the new orderer URL from the chain") } chain.RemoveOrderer(orderer) - orderer2, err := NewOrderer("localhost:7054", "", "") + orderer2, err := NewOrderer("localhost:7054", "", "", mocks.NewMockConfig()) if err != nil { t.Fatalf("Failed to create NewOrderer error(%v)", err) } @@ -66,8 +70,8 @@ func TestOrdererViaChain(t *testing.T) { // to send the request. // func TestPeerViaChainMissingOrderer(t *testing.T) { - client := NewClient() - chain, err := client.NewChain("testChain-orderer-member2") + client := client.NewClient(mocks.NewMockConfig()) + chain, err := client.NewChannel("testChain-orderer-member2") if err != nil { t.Fatalf("error from NewChain %v", err) } @@ -89,12 +93,12 @@ func TestPeerViaChainMissingOrderer(t *testing.T) { // to send null data. // func TestOrdererViaChainNilData(t *testing.T) { - client := NewClient() - chain, err := client.NewChain("testChain-orderer-member2") + client := client.NewClient(mocks.NewMockConfig()) + chain, err := client.NewChannel("testChain-orderer-member2") if err != nil { t.Fatalf("error from NewChain %v", err) } - orderer, err := NewOrderer("localhost:7050", "", "") + orderer, err := NewOrderer("localhost:7050", "", "", mocks.NewMockConfig()) if err != nil { t.Fatalf("Failed to create NewOrderer error(%v)", err) } @@ -114,9 +118,9 @@ func TestOrdererViaChainNilData(t *testing.T) { func TestSendDeliver(t *testing.T) { mockServer := startMockServer(t) - orderer, _ := NewOrderer(testOrdererURL, "", "") + orderer, _ := NewOrderer(testOrdererURL, "", "", mocks.NewMockConfig()) // Test deliver happy path - blocks, errors := orderer.SendDeliver(&SignedEnvelope{}) + blocks, errors := orderer.SendDeliver(&api.SignedEnvelope{}) select { case block := <-blocks: if string(block.Data.Data[0]) != "test" { @@ -144,7 +148,7 @@ func TestSendDeliver(t *testing.T) { // Test deliver with deliver error from OS testError := fmt.Errorf("test error") mockServer.DeliverError = testError - blocks, errors = orderer.SendDeliver(&SignedEnvelope{}) + blocks, errors = orderer.SendDeliver(&api.SignedEnvelope{}) select { case block := <-blocks: t.Fatalf("Expected error got block: %#v", block) @@ -157,10 +161,10 @@ func TestSendDeliver(t *testing.T) { } } -func startMockServer(t *testing.T) *MockBroadcastServer { +func startMockServer(t *testing.T) *mocks.MockBroadcastServer { grpcServer := grpc.NewServer() lis, err := net.Listen("tcp", testOrdererURL) - broadcastServer := new(MockBroadcastServer) + broadcastServer := new(mocks.MockBroadcastServer) ab.RegisterAtomicBroadcastServer(grpcServer, broadcastServer) if err != nil { fmt.Printf("Error starting test server %s", err) diff --git a/fabric-client/packager/golang.go b/pkg/fabric-client/packager/golang.go similarity index 100% rename from fabric-client/packager/golang.go rename to pkg/fabric-client/packager/golang.go diff --git a/fabric-client/packager/golang_test.go b/pkg/fabric-client/packager/golang_test.go similarity index 94% rename from fabric-client/packager/golang_test.go rename to pkg/fabric-client/packager/golang_test.go index 8fa8c93e79..f42a0a171e 100644 --- a/fabric-client/packager/golang_test.go +++ b/pkg/fabric-client/packager/golang_test.go @@ -23,7 +23,7 @@ func TestPackageGoLangCC(t *testing.T) { if err != nil { t.Fatalf("error from os.Getwd %v", err) } - os.Setenv("GOPATH", path.Join(pwd, "../../test/fixtures")) + os.Setenv("GOPATH", path.Join(pwd, "../../../test/fixtures")) ccPackage, err := PackageGoLangCC("github.com") if err != nil { diff --git a/fabric-client/packager.go b/pkg/fabric-client/packager/packager.go similarity index 87% rename from fabric-client/packager.go rename to pkg/fabric-client/packager/packager.go index 988b732f18..431081f82c 100644 --- a/fabric-client/packager.go +++ b/pkg/fabric-client/packager/packager.go @@ -4,12 +4,10 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package packager import ( "fmt" - - packager "github.com/hyperledger/fabric-sdk-go/fabric-client/packager" ) // PackageCC ... @@ -33,7 +31,7 @@ func PackageCC(chaincodePath string, chaincodeType string) ([]byte, error) { logger.Debugf("packager: type %s ", chaincodeType) switch chaincodeType { case "golang": - return packager.PackageGoLangCC(chaincodePath) + return PackageGoLangCC(chaincodePath) } return nil, fmt.Errorf("Undefined 'chaincodeType' value") } diff --git a/fabric-client/peer.go b/pkg/fabric-client/peer/peer.go similarity index 77% rename from fabric-client/peer.go rename to pkg/fabric-client/peer/peer.go index 0ba884e204..8f8e394f27 100644 --- a/fabric-client/peer.go +++ b/pkg/fabric-client/peer/peer.go @@ -4,47 +4,20 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package peer import ( "encoding/pem" + "time" + + api "github.com/hyperledger/fabric-sdk-go/api" pb "github.com/hyperledger/fabric/protos/peer" "golang.org/x/net/context" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" ) -// Peer ... -/** - * The Peer class represents a peer in the target blockchain network to which - * HFC sends endorsement proposals, transaction ordering or query requests. - * - * The Peer class represents the remote Peer node and its network membership materials, - * aka the ECert used to verify signatures. Peer membership represents organizations, - * unlike User membership which represents individuals. - * - * When constructed, a Peer instance can be designated as an event source, in which case - * a “eventSourceUrl” attribute should be configured. This allows the SDK to automatically - * attach transaction event listeners to the event stream. - * - * It should be noted that Peer event streams function at the Peer level and not at the - * chain and chaincode levels. - */ -type Peer interface { - ConnectEventSource() - IsEventListened(event string, chain Chain) (bool, error) - AddListener(eventType string, eventTypeData interface{}, eventCallback interface{}) (string, error) - RemoveListener(eventListenerRef string) (bool, error) - GetName() string - SetName(name string) - GetRoles() []string - SetRoles(roles []string) - GetEnrollmentCertificate() *pem.Block - SetEnrollmentCertificate(pem *pem.Block) - GetURL() string - SendProposal(proposal *TransactionProposal) (*TransactionProposalResponse, error) -} - type peer struct { url string grpcDialOption []grpc.DialOption @@ -75,10 +48,10 @@ func (p *peer) ConnectEventSource() { * Peer for a given event. This helps application instance to decide whether it needs to * connect to the event source in a crash recovery or multiple instance deployment. * @param {string} eventName required - * @param {Chain} chain optional + * @param {Channel} channel optional * @result {bool} Whether the said event has been listened on by some application instance on that chain. */ -func (p *peer) IsEventListened(event string, chain Chain) (bool, error) { +func (p *peer) IsEventListened(event string, channel api.Channel) (bool, error) { //to do return false, nil } @@ -183,7 +156,7 @@ func (p *peer) GetURL() string { /** * Send the created proposal to peer for endorsement. */ -func (p *peer) SendProposal(proposal *TransactionProposal) (*TransactionProposalResponse, error) { +func (p *peer) SendProposal(proposal *api.TransactionProposal) (*api.TransactionProposalResponse, error) { conn, err := grpc.Dial(p.url, p.grpcDialOption...) if err != nil { return nil, err @@ -194,10 +167,33 @@ func (p *peer) SendProposal(proposal *TransactionProposal) (*TransactionProposal if err != nil { return nil, err } - return &TransactionProposalResponse{ + return &api.TransactionProposalResponse{ Proposal: proposal, ProposalResponse: proposalResponse, Endorser: p.url, Status: proposalResponse.GetResponse().Status, }, nil } + +// NewPeer ... +/** + * Constructs a Peer given its endpoint configuration settings. + * + * @param {string} url The URL with format of "host:port". + */ +func NewPeer(url string, certificate string, serverHostOverride string, config api.Config) (api.Peer, error) { + var opts []grpc.DialOption + opts = append(opts, grpc.WithTimeout(time.Second*3)) + if config.IsTLSEnabled() { + tlsCaCertPool, err := config.GetTLSCACertPool(certificate) + if err != nil { + return nil, err + } + creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride) + opts = append(opts, grpc.WithTransportCredentials(creds)) + } else { + opts = append(opts, grpc.WithInsecure()) + } + return &peer{url: url, grpcDialOption: opts, name: "", roles: nil}, nil + +} diff --git a/fabric-client/peer_test.go b/pkg/fabric-client/peer/peer_test.go similarity index 78% rename from fabric-client/peer_test.go rename to pkg/fabric-client/peer/peer_test.go index ffe912a376..f36341a7ec 100644 --- a/fabric-client/peer_test.go +++ b/pkg/fabric-client/peer/peer_test.go @@ -4,10 +4,13 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package peer import ( "testing" + + client "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/client" + mocks "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/mocks" ) // @@ -18,12 +21,12 @@ import ( // process by updating the Peer URL to a different address. // func TestPeerViaChain(t *testing.T) { - client := NewClient() - chain, err := client.NewChain("testChain-peer") + client := client.NewClient(mocks.NewMockConfig()) + chain, err := client.NewChannel("testChain-peer") if err != nil { t.Fatalf("error from NewChain %v", err) } - peer, err := NewPeer("localhost:7050", "", "") + peer, err := NewPeer("localhost:7050", "", "", mocks.NewMockConfig()) if err != nil { t.Fatalf("Failed to create NewPeer error(%v)", err) } @@ -37,7 +40,7 @@ func TestPeerViaChain(t *testing.T) { t.Fatalf("Failed to retieve the new peers URL from the chain") } chain.RemovePeer(peer) - peer2, err := NewPeer("localhost:7054", "", "") + peer2, err := NewPeer("localhost:7054", "", "", mocks.NewMockConfig()) if err != nil { t.Fatalf("Failed to create NewPeer error(%v)", err) } @@ -60,8 +63,8 @@ func TestPeerViaChain(t *testing.T) { // to send the request. // func TestOrdererViaChainMissingOrderer(t *testing.T) { - client := NewClient() - chain, err := client.NewChain("testChain-peer") + client := client.NewClient(mocks.NewMockConfig()) + chain, err := client.NewChannel("testChain-peer") if err != nil { t.Fatalf("error from NewChain %v", err) } @@ -82,12 +85,12 @@ func TestOrdererViaChainMissingOrderer(t *testing.T) { // to send null data. // func TestPeerViaChainNilData(t *testing.T) { - client := NewClient() - chain, err := client.NewChain("testChain-peer") + client := client.NewClient(mocks.NewMockConfig()) + chain, err := client.NewChannel("testChain-peer") if err != nil { t.Fatalf("error from NewChain %v", err) } - peer, err := NewPeer("localhost:7050", "", "") + peer, err := NewPeer("localhost:7050", "", "", mocks.NewMockConfig()) if err != nil { t.Fatalf("Failed to create NewPeer error(%v)", err) } diff --git a/fabric-client/user.go b/pkg/fabric-client/user/user.go similarity index 60% rename from fabric-client/user.go rename to pkg/fabric-client/user/user.go index 5bfaf5a923..ba80fe5c2b 100644 --- a/fabric-client/user.go +++ b/pkg/fabric-client/user/user.go @@ -4,41 +4,13 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package user import ( + api "github.com/hyperledger/fabric-sdk-go/api" "github.com/hyperledger/fabric/bccsp" ) -// User ... -/** - * The User struct represents users that have been enrolled and represented by - * an enrollment certificate (ECert) and a signing key. The ECert must have - * been signed by one of the CAs the blockchain network has been configured to trust. - * An enrolled user (having a signing key and ECert) can conduct chaincode deployments, - * transactions and queries with the Chain. - * - * User ECerts can be obtained from a CA beforehand as part of deploying the application, - * or it can be obtained from the optional Fabric COP service via its enrollment process. - * - * Sometimes User identities are confused with Peer identities. User identities represent - * signing capability because it has access to the private key, while Peer identities in - * the context of the application/SDK only has the certificate for verifying signatures. - * An application cannot use the Peer identity to sign things because the application doesn’t - * have access to the Peer identity’s private key. - * - */ -type User interface { - GetName() string - GetRoles() []string - SetRoles([]string) - GetEnrollmentCertificate() []byte - SetEnrollmentCertificate(cert []byte) - SetPrivateKey(privateKey bccsp.Key) - GetPrivateKey() bccsp.Key - GenerateTcerts(count int, attributes []string) -} - type user struct { name string roles []string @@ -46,8 +18,8 @@ type user struct { enrollmentCertificate []byte } -// UserJSON ... -type UserJSON struct { +// JSON ... +type JSON struct { PrivateKeySKI []byte EnrollmentCertificate []byte } @@ -58,7 +30,7 @@ type UserJSON struct { * * @param {string} name - The user name */ -func NewUser(name string) User { +func NewUser(name string) api.User { return &user{name: name} } diff --git a/fabric-client/user_test.go b/pkg/fabric-client/user/user_test.go similarity index 96% rename from fabric-client/user_test.go rename to pkg/fabric-client/user/user_test.go index bcff6fe952..ff5d0480db 100644 --- a/fabric-client/user_test.go +++ b/pkg/fabric-client/user/user_test.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package fabricclient +package user import ( "testing" diff --git a/fabric-client/util/chain_util.go b/pkg/util/chain_util.go similarity index 63% rename from fabric-client/util/chain_util.go rename to pkg/util/chain_util.go index a0ae559810..a5a0744026 100644 --- a/fabric-client/util/chain_util.go +++ b/pkg/util/chain_util.go @@ -13,58 +13,61 @@ import ( "os" "time" - "github.com/hyperledger/fabric-sdk-go/config" + api "github.com/hyperledger/fabric-sdk-go/api" + "github.com/hyperledger/fabric/common/crypto" + + orderer "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/orderer" + peer "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/peer" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - "github.com/hyperledger/fabric-sdk-go/fabric-client/events" "github.com/hyperledger/fabric/protos/common" + protos_utils "github.com/hyperledger/fabric/protos/utils" "github.com/op/go-logging" ) var origGoPath = os.Getenv("GOPATH") var logger = logging.MustGetLogger("fabric_sdk_go") -// GetChain initializes and returns a chain based on config -func GetChain(client fabricClient.Client, chainID string) (fabricClient.Chain, error) { +// GetChannel initializes and returns a channel based on config +func GetChannel(client api.FabricClient, channelID string) (api.Channel, error) { - chain, err := client.NewChain(chainID) + channel, err := client.NewChannel(channelID) if err != nil { - return nil, fmt.Errorf("NewChain return error: %v", err) + return nil, fmt.Errorf("NewChannel return error: %v", err) } - orderer, err := fabricClient.NewOrderer(fmt.Sprintf("%s:%s", config.GetOrdererHost(), config.GetOrdererPort()), - config.GetOrdererTLSCertificate(), config.GetOrdererTLSServerHostOverride()) + orderer, err := orderer.NewOrderer(fmt.Sprintf("%s:%s", client.GetConfig().GetOrdererHost(), client.GetConfig().GetOrdererPort()), + client.GetConfig().GetOrdererTLSCertificate(), client.GetConfig().GetOrdererTLSServerHostOverride(), client.GetConfig()) if err != nil { return nil, fmt.Errorf("NewOrderer return error: %v", err) } - err = chain.AddOrderer(orderer) + err = channel.AddOrderer(orderer) if err != nil { return nil, fmt.Errorf("Error adding orderer: %v", err) } - peerConfig, err := config.GetPeersConfig() + peerConfig, err := client.GetConfig().GetPeersConfig() if err != nil { return nil, fmt.Errorf("Error reading peer config: %v", err) } for _, p := range peerConfig { - endorser, err := fabricClient.NewPeer(fmt.Sprintf("%s:%d", p.Host, p.Port), - p.TLS.Certificate, p.TLS.ServerHostOverride) + endorser, err := peer.NewPeer(fmt.Sprintf("%s:%d", p.Host, p.Port), + p.TLS.Certificate, p.TLS.ServerHostOverride, client.GetConfig()) if err != nil { return nil, fmt.Errorf("NewPeer return error: %v", err) } - err = chain.AddPeer(endorser) + err = channel.AddPeer(endorser) if err != nil { return nil, fmt.Errorf("Error adding peer: %v", err) } if p.Primary { - chain.SetPrimaryPeer(endorser) + channel.SetPrimaryPeer(endorser) } } - return chain, nil + return channel, nil } // SendInstallCC Sends an install proposal to one or more endorsing peers. -func SendInstallCC(client fabricClient.Client, chain fabricClient.Chain, chainCodeID string, chainCodePath string, chainCodeVersion string, chaincodePackage []byte, targets []fabricClient.Peer, deployPath string) error { +func SendInstallCC(client api.FabricClient, channel api.Channel, chainCodeID string, chainCodePath string, chainCodeVersion string, chaincodePackage []byte, targets []api.Peer, deployPath string) error { ChangeGOPATHToDeploy(deployPath) transactionProposalResponse, _, err := client.InstallChaincode(chainCodeID, chainCodePath, chainCodeVersion, chaincodePackage, targets) ResetGOPATH() @@ -83,9 +86,9 @@ func SendInstallCC(client fabricClient.Client, chain fabricClient.Chain, chainCo } // SendInstantiateCC Sends instantiate CC proposal to one or more endorsing peers -func SendInstantiateCC(chain fabricClient.Chain, chainCodeID string, chainID string, args []string, chaincodePath string, chaincodeVersion string, targets []fabricClient.Peer, eventHub events.EventHub) error { +func SendInstantiateCC(channel api.Channel, chainCodeID string, channelID string, args []string, chaincodePath string, chaincodeVersion string, targets []api.Peer, eventHub api.EventHub) error { - transactionProposalResponse, txID, err := chain.SendInstantiateProposal(chainCodeID, chainID, args, chaincodePath, chaincodeVersion, targets) + transactionProposalResponse, txID, err := channel.SendInstantiateProposal(chainCodeID, channelID, args, chaincodePath, chaincodeVersion, targets) if err != nil { return fmt.Errorf("SendInstantiateProposal return error: %v", err) } @@ -100,7 +103,7 @@ func SendInstantiateCC(chain fabricClient.Chain, chainCodeID string, chainID str // Register for commit event done, fail := RegisterTxEvent(txID, eventHub) - if _, err = CreateAndSendTransaction(chain, transactionProposalResponse); err != nil { + if _, err = CreateAndSendTransaction(channel, transactionProposalResponse); err != nil { return fmt.Errorf("CreateTransaction return error: %v", err) } @@ -115,32 +118,32 @@ func SendInstantiateCC(chain fabricClient.Chain, chainCodeID string, chainID str } -// CreateAndJoinChannel creates the channel represented by this chain +// CreateAndJoinChannel creates the channel represented by this channel // and makes the primary peer join it. It reads channel configuration from tx channelConfig file -func CreateAndJoinChannel(client fabricClient.Client, ordererUser fabricClient.User, orgUser fabricClient.User, chain fabricClient.Chain, channelConfig string) error { +func CreateAndJoinChannel(client api.FabricClient, ordererUser api.User, orgUser api.User, channel api.Channel, channelConfig string) error { // Check if primary peer has joined this channel var foundChannel bool - primaryPeer := chain.GetPrimaryPeer() + primaryPeer := channel.GetPrimaryPeer() client.SetUserContext(orgUser) response, err := client.QueryChannels(primaryPeer) if err != nil { return fmt.Errorf("Error querying channels for primary peer: %s", err) } - for _, channel := range response.Channels { - if channel.ChannelId == chain.GetName() { + for _, responseChannel := range response.Channels { + if responseChannel.ChannelId == channel.GetName() { foundChannel = true } } if foundChannel { - // There's no need to create a channel, initialize the chain from the orderer and return - if err := chain.Initialize(nil); err != nil { - return fmt.Errorf("Error initializing chain: %v", err) + // There's no need to create a channel, initialize the channel from the orderer and return + if err := channel.Initialize(nil); err != nil { + return fmt.Errorf("Error initializing channel: %v", err) } return nil } - logger.Infof("***** Creating and Joining channel: %s *****\n", chain.GetName()) + logger.Infof("***** Creating and Joining channel: %s *****\n", channel.GetName()) configTx, err := ioutil.ReadFile(channelConfig) if err != nil { @@ -164,18 +167,18 @@ func CreateAndJoinChannel(client fabricClient.Client, ordererUser fabricClient.U if err != nil { return fmt.Errorf("Error getting creator: %v", err) } - nonce, err := fabricClient.GenerateRandomNonce() + nonce, err := generateRandomNonce() if err != nil { return fmt.Errorf("Could not compute nonce: %s", err) } - txID, err := fabricClient.ComputeTxID(nonce, creator) + txID, err := computeTxID(nonce, creator) if err != nil { return fmt.Errorf("Could not compute TxID: %s", err) } - request := fabricClient.CreateChannelRequest{ - Name: chain.GetName(), - Orderer: chain.GetOrderers()[0], + request := api.CreateChannelRequest{ + Name: channel.GetName(), + Orderer: channel.GetOrderers()[0], Config: config, Signatures: configSignatures, TxID: txID, @@ -193,39 +196,39 @@ func CreateAndJoinChannel(client fabricClient.Client, ordererUser fabricClient.U client.SetUserContext(orgUser) - nonce, err = fabricClient.GenerateRandomNonce() + nonce, err = generateRandomNonce() if err != nil { return fmt.Errorf("Could not compute nonce: %s", err) } - txID, err = fabricClient.ComputeTxID(nonce, creator) + txID, err = computeTxID(nonce, creator) if err != nil { return fmt.Errorf("Could not compute TxID: %s", err) } - genesisBlockRequest := &fabricClient.GenesisBlockRequest{ + genesisBlockRequest := &api.GenesisBlockRequest{ TxID: txID, Nonce: nonce, } - genesisBlock, err := chain.GetGenesisBlock(genesisBlockRequest) + genesisBlock, err := channel.GetGenesisBlock(genesisBlockRequest) if err != nil { return fmt.Errorf("Error getting genesis block: %v", err) } - nonce, err = fabricClient.GenerateRandomNonce() + nonce, err = generateRandomNonce() if err != nil { return fmt.Errorf("Could not compute nonce: %s", err) } - txID, err = fabricClient.ComputeTxID(nonce, creator) + txID, err = computeTxID(nonce, creator) if err != nil { return fmt.Errorf("Could not compute TxID: %s", err) } - joinChannelRequest := &fabricClient.JoinChannelRequest{ - Targets: chain.GetPeers(), + joinChannelRequest := &api.JoinChannelRequest{ + Targets: channel.GetPeers(), GenesisBlock: genesisBlock, TxID: txID, Nonce: nonce, } - transactionProposalResponse, err := chain.JoinChannel(joinChannelRequest) + transactionProposalResponse, err := channel.JoinChannel(joinChannelRequest) if err != nil { return fmt.Errorf("Error joining channel: %s", err) } @@ -237,7 +240,7 @@ func CreateAndJoinChannel(client fabricClient.Client, ordererUser fabricClient.U logger.Debug("JoinChannel Endorser '%s' return ProposalResponse status:%v\n", v.Endorser, v.Status) } - logger.Infof("***** Created and Joined channel: %s *****\n", chain.GetName()) + logger.Infof("***** Created and Joined channel: %s *****\n", channel.GetName()) return nil } @@ -267,3 +270,13 @@ func GenerateRandomID() string { rand.Seed(time.Now().UnixNano()) return randomString(10) } + +// generateRandomNonce generates a random nonce +func generateRandomNonce() ([]byte, error) { + return crypto.GetRandomNonce() +} + +// computeTxID computes a transaction ID from a given nonce and creator ID +func computeTxID(nonce []byte, creator []byte) (string, error) { + return protos_utils.ComputeProposalTxID(nonce, creator) +} diff --git a/fabric-client/util/client_util.go b/pkg/util/client_util.go similarity index 66% rename from fabric-client/util/client_util.go rename to pkg/util/client_util.go index 25e4c4d6c9..ecc70148a1 100644 --- a/fabric-client/util/client_util.go +++ b/pkg/util/client_util.go @@ -9,24 +9,26 @@ package util import ( "fmt" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" + client "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/client" + sdkUser "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/user" - fabricCAClient "github.com/hyperledger/fabric-sdk-go/fabric-ca-client" + api "github.com/hyperledger/fabric-sdk-go/api" + fabricCAClient "github.com/hyperledger/fabric-sdk-go/pkg/fabric-ca-client" - kvs "github.com/hyperledger/fabric-sdk-go/fabric-client/keyvaluestore" + kvs "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/keyvaluestore" bccspFactory "github.com/hyperledger/fabric/bccsp/factory" ) // CreateAndSendTransactionProposal combines create and send transaction proposal methods into one method. // See CreateTransactionProposal and SendTransactionProposal -func CreateAndSendTransactionProposal(chain fabricClient.Chain, chainCodeID string, chainID string, args []string, targets []fabricClient.Peer, transientData map[string][]byte) ([]*fabricClient.TransactionProposalResponse, string, error) { +func CreateAndSendTransactionProposal(channel api.Channel, chainCodeID string, channelID string, args []string, targets []api.Peer, transientData map[string][]byte) ([]*api.TransactionProposalResponse, string, error) { - signedProposal, err := chain.CreateTransactionProposal(chainCodeID, chainID, args, true, transientData) + signedProposal, err := channel.CreateTransactionProposal(chainCodeID, channelID, args, true, transientData) if err != nil { return nil, "", fmt.Errorf("SendTransactionProposal return error: %v", err) } - transactionProposalResponses, err := chain.SendTransactionProposal(signedProposal, 0, targets) + transactionProposalResponses, err := channel.SendTransactionProposal(signedProposal, 0, targets) if err != nil { return nil, "", fmt.Errorf("SendTransactionProposal return error: %v", err) } @@ -43,14 +45,14 @@ func CreateAndSendTransactionProposal(chain fabricClient.Chain, chainCodeID stri // CreateAndSendTransaction combines create and send transaction methods into one method. // See CreateTransaction and SendTransaction -func CreateAndSendTransaction(chain fabricClient.Chain, resps []*fabricClient.TransactionProposalResponse) ([]*fabricClient.TransactionResponse, error) { +func CreateAndSendTransaction(channel api.Channel, resps []*api.TransactionProposalResponse) ([]*api.TransactionResponse, error) { - tx, err := chain.CreateTransaction(resps) + tx, err := channel.CreateTransaction(resps) if err != nil { return nil, fmt.Errorf("CreateTransaction return error: %v", err) } - transactionResponse, err := chain.SendTransaction(tx) + transactionResponse, err := channel.SendTransaction(tx) if err != nil { return nil, fmt.Errorf("SendTransaction return error: %v", err) @@ -65,8 +67,8 @@ func CreateAndSendTransaction(chain fabricClient.Chain, resps []*fabricClient.Tr } // GetClient initializes and returns a client based on config and user -func GetClient(name string, pwd string, stateStorePath string) (fabricClient.Client, error) { - client := fabricClient.NewClient() +func GetClient(name string, pwd string, stateStorePath string, config api.Config) (api.FabricClient, error) { + client := client.NewClient(config) cryptoSuite := bccspFactory.GetDefault() @@ -81,7 +83,7 @@ func GetClient(name string, pwd string, stateStorePath string) (fabricClient.Cli return nil, fmt.Errorf("client.LoadUserFromStateStore return error: %v", err) } if user == nil { - fabricCAClient, err := fabricCAClient.NewFabricCAClient() + fabricCAClient, err := fabricCAClient.NewFabricCAClient(config) if err != nil { return nil, fmt.Errorf("NewFabricCAClient return error: %v", err) } @@ -89,7 +91,7 @@ func GetClient(name string, pwd string, stateStorePath string) (fabricClient.Cli if err != nil { return nil, fmt.Errorf("Enroll return error: %v", err) } - user = fabricClient.NewUser(name) + user = sdkUser.NewUser(name) user.SetPrivateKey(key) user.SetEnrollmentCertificate(cert) err = client.SaveUserToStateStore(user, false) diff --git a/fabric-client/util/events_util.go b/pkg/util/events_util.go similarity index 79% rename from fabric-client/util/events_util.go rename to pkg/util/events_util.go index 1e58e3d6a7..23554fae00 100644 --- a/fabric-client/util/events_util.go +++ b/pkg/util/events_util.go @@ -7,14 +7,14 @@ SPDX-License-Identifier: Apache-2.0 package util import ( - "github.com/hyperledger/fabric-sdk-go/fabric-client/events" + api "github.com/hyperledger/fabric-sdk-go/api" pb "github.com/hyperledger/fabric/protos/peer" ) // RegisterTxEvent registers on the given eventhub for the give transaction // returns a boolean channel which receives true when the event is complete // and an error channel for errors -func RegisterTxEvent(txID string, eventHub events.EventHub) (chan bool, chan error) { +func RegisterTxEvent(txID string, eventHub api.EventHub) (chan bool, chan error) { done := make(chan bool) fail := make(chan error) @@ -34,11 +34,11 @@ func RegisterTxEvent(txID string, eventHub events.EventHub) (chan bool, chan err // RegisterCCEvent registers chain code event on the given eventhub // @returns {chan bool} channel which receives true when the event is complete // @returns {object} ChainCodeCBE object handle that should be used to unregister -func RegisterCCEvent(chainCodeID, eventID string, eventHub events.EventHub) (chan bool, *events.ChainCodeCBE) { +func RegisterCCEvent(chainCodeID, eventID string, eventHub api.EventHub) (chan bool, *api.ChainCodeCBE) { done := make(chan bool) // Register callback for CE - rce := eventHub.RegisterChaincodeEvent(chainCodeID, eventID, func(ce *events.ChaincodeEvent) { + rce := eventHub.RegisterChaincodeEvent(chainCodeID, eventID, func(ce *api.ChaincodeEvent) { logger.Debugf("Received CC event: %v\n", ce) done <- true }) diff --git a/fabric-client/util/user_util.go b/pkg/util/user_util.go similarity index 76% rename from fabric-client/util/user_util.go rename to pkg/util/user_util.go index 3872dcec11..69c52f7958 100644 --- a/fabric-client/util/user_util.go +++ b/pkg/util/user_util.go @@ -11,16 +11,17 @@ import ( "io/ioutil" "path/filepath" + api "github.com/hyperledger/fabric-sdk-go/api" + sdkUser "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/user" + "github.com/hyperledger/fabric-ca/util" - "github.com/hyperledger/fabric-sdk-go/config" - fabricCAClient "github.com/hyperledger/fabric-sdk-go/fabric-ca-client" - fc "github.com/hyperledger/fabric-sdk-go/fabric-client" + fabricCAClient "github.com/hyperledger/fabric-sdk-go/pkg/fabric-ca-client" ) // GetPreEnrolledUser ... -func GetPreEnrolledUser(c fc.Client, keyDir string, certDir string, username string) (fc.User, error) { +func GetPreEnrolledUser(c api.FabricClient, keyDir string, certDir string, username string) (api.User, error) { - privateKeyDir := filepath.Join(config.GetCryptoConfigPath(), keyDir) + privateKeyDir := filepath.Join(c.GetConfig().GetCryptoConfigPath(), keyDir) privateKeyPath, err := getFirstPathFromDir(privateKeyDir) if err != nil { return nil, fmt.Errorf("Error finding the private key path: %v", err) @@ -30,7 +31,7 @@ func GetPreEnrolledUser(c fc.Client, keyDir string, certDir string, username str return nil, fmt.Errorf("Error importing private key: %v", err) } - enrollmentCertDir := filepath.Join(config.GetCryptoConfigPath(), certDir) + enrollmentCertDir := filepath.Join(c.GetConfig().GetCryptoConfigPath(), certDir) enrollmentCertPath, err := getFirstPathFromDir(enrollmentCertDir) if err != nil { return nil, fmt.Errorf("Error finding the enrollment cert path: %v", err) @@ -40,7 +41,7 @@ func GetPreEnrolledUser(c fc.Client, keyDir string, certDir string, username str return nil, fmt.Errorf("Error reading from the enrollment cert path: %v", err) } - user := fc.NewUser(username) + user := sdkUser.NewUser(username) user.SetEnrollmentCertificate(enrollmentCert) user.SetPrivateKey(privateKey) @@ -77,13 +78,13 @@ func getFirstPathFromDir(dir string) (string, error) { } // GetMember ... -func GetMember(client fc.Client, name string, pwd string) (fc.User, error) { +func GetMember(client api.FabricClient, name string, pwd string) (api.User, error) { user, err := client.LoadUserFromStateStore(name) if err != nil { return nil, fmt.Errorf("Error loading user from store: %v", err) } if user == nil { - fabricCAClient, err := fabricCAClient.NewFabricCAClient() + fabricCAClient, err := fabricCAClient.NewFabricCAClient(client.GetConfig()) if err != nil { return nil, fmt.Errorf("NewFabricCAClient return error: %v", err) } @@ -91,7 +92,7 @@ func GetMember(client fc.Client, name string, pwd string) (fc.User, error) { if err != nil { return nil, fmt.Errorf("Enroll return error: %v", err) } - user := fc.NewUser(name) + user := sdkUser.NewUser(name) user.SetPrivateKey(key) user.SetEnrollmentCertificate(cert) err = client.SaveUserToStateStore(user, false) diff --git a/test/integration/base_test_setup.go b/test/integration/base_test_setup.go index 7f85bf11cb..a1848a4510 100644 --- a/test/integration/base_test_setup.go +++ b/test/integration/base_test_setup.go @@ -12,42 +12,43 @@ import ( "path" "time" - "github.com/hyperledger/fabric-sdk-go/config" - "github.com/hyperledger/fabric-sdk-go/fabric-client/events" + "github.com/hyperledger/fabric-sdk-go/pkg/config" + "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/events" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - fcutil "github.com/hyperledger/fabric-sdk-go/fabric-client/util" + api "github.com/hyperledger/fabric-sdk-go/api" + + fcutil "github.com/hyperledger/fabric-sdk-go/pkg/util" bccspFactory "github.com/hyperledger/fabric/bccsp/factory" ) // BaseSetupImpl implementation of BaseTestSetup type BaseSetupImpl struct { - Client fabricClient.Client - OrdererAdminClient fabricClient.Client - Chain fabricClient.Chain - EventHub events.EventHub + Client api.FabricClient + OrdererAdminClient api.FabricClient + Channel api.Channel + EventHub api.EventHub ConnectEventHub bool ConfigFile string - ChainID string + ChannelID string ChainCodeID string Initialized bool ChannelConfig string } -// Initialize reads configuration from file and sets up client, chain and event hub +// Initialize reads configuration from file and sets up client, channel and event hub func (setup *BaseSetupImpl) Initialize() error { - - if err := setup.InitConfig(); err != nil { + configImpl, err := setup.InitConfig() + if err != nil { return fmt.Errorf("Init from config failed: %v", err) } // Initialize bccsp factories before calling get client - err := bccspFactory.InitFactories(config.GetCSPConfig()) + err = bccspFactory.InitFactories(configImpl.GetCSPConfig()) if err != nil { return fmt.Errorf("Failed getting ephemeral software-based BCCSP [%s]", err) } - client, err := fcutil.GetClient("admin", "adminpw", "/tmp/enroll_user") + client, err := fcutil.GetClient("admin", "adminpw", "/tmp/enroll_user", configImpl) if err != nil { return fmt.Errorf("Create client failed: %v", err) } @@ -60,11 +61,11 @@ func (setup *BaseSetupImpl) Initialize() error { return fmt.Errorf("Error getting org admin user: %v", err) } - chain, err := fcutil.GetChain(setup.Client, setup.ChainID) + channel, err := fcutil.GetChannel(setup.Client, setup.ChannelID) if err != nil { - return fmt.Errorf("Create chain (%s) failed: %v", setup.ChainID, err) + return fmt.Errorf("Create channel (%s) failed: %v", setup.ChannelID, err) } - setup.Chain = chain + setup.Channel = channel ordererAdmin, err := GetOrdererAdmin(client) if err != nil { @@ -72,7 +73,7 @@ func (setup *BaseSetupImpl) Initialize() error { } // Create and join channel - if err := fcutil.CreateAndJoinChannel(client, ordererAdmin, org1Admin, chain, setup.ChannelConfig); err != nil { + if err := fcutil.CreateAndJoinChannel(client, ordererAdmin, org1Admin, channel, setup.ChannelConfig); err != nil { return fmt.Errorf("CreateAndJoinChannel return error: %v", err) } @@ -86,7 +87,7 @@ func (setup *BaseSetupImpl) Initialize() error { return nil } -func (setup *BaseSetupImpl) setupEventHub(client fabricClient.Client) error { +func (setup *BaseSetupImpl) setupEventHub(client api.FabricClient) error { eventHub, err := getEventHub(client) if err != nil { return err @@ -103,16 +104,17 @@ func (setup *BaseSetupImpl) setupEventHub(client fabricClient.Client) error { } // InitConfig ... -func (setup *BaseSetupImpl) InitConfig() error { - if err := config.InitConfig(setup.ConfigFile); err != nil { - return err +func (setup *BaseSetupImpl) InitConfig() (api.Config, error) { + configImpl, err := config.InitConfig(setup.ConfigFile) + if err != nil { + return nil, err } - return nil + return configImpl, nil } // InstantiateCC ... -func (setup *BaseSetupImpl) InstantiateCC(chainCodeID string, chainID string, chainCodePath string, chainCodeVersion string, args []string) error { - if err := fcutil.SendInstantiateCC(setup.Chain, chainCodeID, chainID, args, chainCodePath, chainCodeVersion, []fabricClient.Peer{setup.Chain.GetPrimaryPeer()}, setup.EventHub); err != nil { +func (setup *BaseSetupImpl) InstantiateCC(chainCodeID string, channelID string, chainCodePath string, chainCodeVersion string, args []string) error { + if err := fcutil.SendInstantiateCC(setup.Channel, chainCodeID, channelID, args, chainCodePath, chainCodeVersion, []api.Peer{setup.Channel.GetPrimaryPeer()}, setup.EventHub); err != nil { return err } return nil @@ -120,7 +122,7 @@ func (setup *BaseSetupImpl) InstantiateCC(chainCodeID string, chainID string, ch // InstallCC ... func (setup *BaseSetupImpl) InstallCC(chainCodeID string, chainCodePath string, chainCodeVersion string, chaincodePackage []byte) error { - if err := fcutil.SendInstallCC(setup.Client, setup.Chain, chainCodeID, chainCodePath, chainCodeVersion, chaincodePackage, setup.Chain.GetPeers(), setup.GetDeployPath()); err != nil { + if err := fcutil.SendInstallCC(setup.Client, setup.Channel, chainCodeID, chainCodePath, chainCodeVersion, chaincodePackage, setup.Channel.GetPeers(), setup.GetDeployPath()); err != nil { return fmt.Errorf("SendInstallProposal return error: %v", err) } return nil @@ -153,16 +155,16 @@ func (setup *BaseSetupImpl) InstallAndInstantiateExampleCC() error { args = append(args, "b") args = append(args, "200") - return setup.InstantiateCC(setup.ChainCodeID, setup.ChainID, chainCodePath, chainCodeVersion, args) + return setup.InstantiateCC(setup.ChainCodeID, setup.ChannelID, chainCodePath, chainCodeVersion, args) } // Query ... -func (setup *BaseSetupImpl) Query(chainID string, chainCodeID string, args []string) (string, error) { - transactionProposalResponses, _, err := fcutil.CreateAndSendTransactionProposal(setup.Chain, chainCodeID, chainID, args, []fabricClient.Peer{setup.Chain.GetPrimaryPeer()}, nil) +func (setup *BaseSetupImpl) Query(channelID string, chainCodeID string, args []string) (string, error) { + transactionProposalResponses, _, err := fcutil.CreateAndSendTransactionProposal(setup.Channel, chainCodeID, channelID, args, []api.Peer{setup.Channel.GetPrimaryPeer()}, nil) if err != nil { return "", fmt.Errorf("CreateAndSendTransactionProposal return error: %v", err) } - return string(transactionProposalResponses[0].GetResponsePayload()), nil + return string(transactionProposalResponses[0].ProposalResponse.GetResponse().Payload), nil } // QueryAsset ... @@ -172,7 +174,7 @@ func (setup *BaseSetupImpl) QueryAsset() (string, error) { args = append(args, "invoke") args = append(args, "query") args = append(args, "b") - return setup.Query(setup.ChainID, setup.ChainCodeID, args) + return setup.Query(setup.ChannelID, setup.ChainCodeID, args) } // MoveFunds ... @@ -188,14 +190,14 @@ func (setup *BaseSetupImpl) MoveFunds() (string, error) { transientDataMap := make(map[string][]byte) transientDataMap["result"] = []byte("Transient data in move funds...") - transactionProposalResponse, txID, err := fcutil.CreateAndSendTransactionProposal(setup.Chain, setup.ChainCodeID, setup.ChainID, args, []fabricClient.Peer{setup.Chain.GetPrimaryPeer()}, transientDataMap) + transactionProposalResponse, txID, err := fcutil.CreateAndSendTransactionProposal(setup.Channel, setup.ChainCodeID, setup.ChannelID, args, []api.Peer{setup.Channel.GetPrimaryPeer()}, transientDataMap) if err != nil { return "", fmt.Errorf("CreateAndSendTransactionProposal return error: %v", err) } // Register for commit event done, fail := fcutil.RegisterTxEvent(txID, setup.EventHub) - txResponse, err := fcutil.CreateAndSendTransaction(setup.Chain, transactionProposalResponse) + txResponse, err := fcutil.CreateAndSendTransaction(setup.Channel, transactionProposalResponse) if err != nil { return "", fmt.Errorf("CreateAndSendTransaction return error: %v", err) } @@ -212,13 +214,13 @@ func (setup *BaseSetupImpl) MoveFunds() (string, error) { } // getEventHub initilizes the event hub -func getEventHub(client fabricClient.Client) (events.EventHub, error) { +func getEventHub(client api.FabricClient) (api.EventHub, error) { eventHub, err := events.NewEventHub(client) if err != nil { return nil, fmt.Errorf("Error creating new event hub: %v", err) } foundEventHub := false - peerConfig, err := config.GetPeersConfig() + peerConfig, err := client.GetConfig().GetPeersConfig() if err != nil { return nil, fmt.Errorf("Error reading peer config: %v", err) } diff --git a/test/integration/chain_queries_test.go b/test/integration/channel_queries_test.go similarity index 72% rename from test/integration/chain_queries_test.go rename to test/integration/channel_queries_test.go index 083a3027ed..d7ce1c9266 100644 --- a/test/integration/chain_queries_test.go +++ b/test/integration/channel_queries_test.go @@ -11,14 +11,15 @@ import ( "strconv" "testing" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" + api "github.com/hyperledger/fabric-sdk-go/api" + peer "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/peer" ) -func TestChainQueries(t *testing.T) { +func TestChannelQueries(t *testing.T) { testSetup := &BaseSetupImpl{ ConfigFile: "../fixtures/config/config_test.yaml", - ChainID: "mychannel", + ChannelID: "mychannel", ChannelConfig: "../fixtures/channel/mychannel.tx", ConnectEventHub: true, } @@ -27,7 +28,7 @@ func TestChainQueries(t *testing.T) { t.Fatalf(err.Error()) } - chain := testSetup.Chain + channel := testSetup.Channel client := testSetup.Client if err := testSetup.InstallAndInstantiateExampleCC(); err != nil { @@ -35,7 +36,7 @@ func TestChainQueries(t *testing.T) { } // Test Query Info - retrieve values before transaction - bciBeforeTx, err := chain.QueryInfo() + bciBeforeTx, err := channel.QueryInfo() if err != nil { t.Fatalf("QueryInfo return error: %v", err) } @@ -47,7 +48,7 @@ func TestChainQueries(t *testing.T) { } // Test Query Info - retrieve values after transaction - bciAfterTx, err := chain.QueryInfo() + bciAfterTx, err := channel.QueryInfo() if err != nil { t.Fatalf("QueryInfo return error: %v", err) } @@ -57,18 +58,18 @@ func TestChainQueries(t *testing.T) { t.Fatalf("Block size did not increase after transaction") } - testQueryTransaction(t, chain, txID) + testQueryTransaction(t, channel, txID) - testQueryBlock(t, chain) + testQueryBlock(t, channel) - testQueryChannels(t, chain, client) + testQueryChannels(t, channel, client) - testInstalledChaincodes(t, chain, client) + testInstalledChaincodes(t, channel, client) - testQueryByChaincode(t, chain) + testQueryByChaincode(t, channel, client.GetConfig()) // TODO: Synch with test in node SDK when it becomes available - // testInstantiatedChaincodes(t, chain) + // testInstantiatedChaincodes(t, channel) } @@ -101,10 +102,10 @@ func changeBlockState(testSetup *BaseSetupImpl) (string, error) { return txID, nil } -func testQueryTransaction(t *testing.T, chain fabricClient.Chain, txID string) { +func testQueryTransaction(t *testing.T, channel api.Channel, txID string) { // Test Query Transaction -- verify that valid transaction has been processed - processedTransaction, err := chain.QueryTransaction(txID) + processedTransaction, err := channel.QueryTransaction(txID) if err != nil { t.Fatalf("QueryTransaction return error: %v", err) } @@ -114,23 +115,23 @@ func testQueryTransaction(t *testing.T, chain fabricClient.Chain, txID string) { } // Test Query Transaction -- Retrieve non existing transaction - processedTransaction, err = chain.QueryTransaction("123ABC") + processedTransaction, err = channel.QueryTransaction("123ABC") if err == nil { t.Fatalf("QueryTransaction non-existing didn't return an error") } } -func testQueryBlock(t *testing.T, chain fabricClient.Chain) { +func testQueryBlock(t *testing.T, channel api.Channel) { // Retrieve current blockchain info - bci, err := chain.QueryInfo() + bci, err := channel.QueryInfo() if err != nil { t.Fatalf("QueryInfo return error: %v", err) } // Test Query Block by Hash - retrieve current block by hash - block, err := chain.QueryBlockByHash(bci.CurrentBlockHash) + block, err := channel.QueryBlockByHash(bci.CurrentBlockHash) if err != nil { t.Fatalf("QueryBlockByHash return error: %v", err) } @@ -140,13 +141,13 @@ func testQueryBlock(t *testing.T, chain fabricClient.Chain) { } // Test Query Block by Hash - retrieve block by non-existent hash - block, err = chain.QueryBlockByHash([]byte("non-existent")) + block, err = channel.QueryBlockByHash([]byte("non-existent")) if err == nil { t.Fatalf("QueryBlockByHash non-existent didn't return an error") } // Test Query Block - retrieve block by number - block, err = chain.QueryBlock(1) + block, err = channel.QueryBlock(1) if err != nil { t.Fatalf("QueryBlock return error: %v", err) } @@ -156,17 +157,17 @@ func testQueryBlock(t *testing.T, chain fabricClient.Chain) { } // Test Query Block - retrieve block by non-existent number - block, err = chain.QueryBlock(2147483647) + block, err = channel.QueryBlock(2147483647) if err == nil { t.Fatalf("QueryBlock non-existent didn't return an error") } } -func testQueryChannels(t *testing.T, chain fabricClient.Chain, client fabricClient.Client) { +func testQueryChannels(t *testing.T, channel api.Channel, client api.FabricClient) { // Our target will be primary peer on this channel - target := chain.GetPrimaryPeer() + target := channel.GetPrimaryPeer() fmt.Printf("****QueryChannels for %s\n", target.GetURL()) channelQueryResponse, err := client.QueryChannels(target) if err != nil { @@ -179,10 +180,10 @@ func testQueryChannels(t *testing.T, chain fabricClient.Chain, client fabricClie } -func testInstalledChaincodes(t *testing.T, chain fabricClient.Chain, client fabricClient.Client) { +func testInstalledChaincodes(t *testing.T, channel api.Channel, client api.FabricClient) { // Our target will be primary peer on this channel - target := chain.GetPrimaryPeer() + target := channel.GetPrimaryPeer() fmt.Printf("****QueryInstalledChaincodes for %s\n", target.GetURL()) // Test Query Installed chaincodes for target (primary) @@ -197,15 +198,15 @@ func testInstalledChaincodes(t *testing.T, chain fabricClient.Chain, client fabr } -func testInstantiatedChaincodes(t *testing.T, chain fabricClient.Chain) { +func testInstantiatedChaincodes(t *testing.T, channel api.Channel) { // Our target will indirectly be primary peer on this channel - target := chain.GetPrimaryPeer() + target := channel.GetPrimaryPeer() fmt.Printf("QueryInstantiatedChaincodes for primary %s\n", target.GetURL()) // Test Query Instantiated chaincodes - chaincodeQueryResponse, err := chain.QueryInstantiatedChaincodes() + chaincodeQueryResponse, err := channel.QueryInstantiatedChaincodes() if err != nil { t.Fatalf("QueryInstantiatedChaincodes return error: %v", err) } @@ -216,12 +217,12 @@ func testInstantiatedChaincodes(t *testing.T, chain fabricClient.Chain) { } -func testQueryByChaincode(t *testing.T, chain fabricClient.Chain) { +func testQueryByChaincode(t *testing.T, channel api.Channel, config api.Config) { // Test valid targets - targets := chain.GetPeers() + targets := channel.GetPeers() - queryResponses, err := chain.QueryByChaincode("lscc", []string{"getinstalledchaincodes"}, targets) + queryResponses, err := channel.QueryByChaincode("lscc", []string{"getinstalledchaincodes"}, targets) if err != nil { t.Fatalf("QueryByChaincode failed %s", err) } @@ -232,13 +233,13 @@ func testQueryByChaincode(t *testing.T, chain fabricClient.Chain) { } // Create invalid target - firstInvalidTarget, err := fabricClient.NewPeer("test:1111", "", "") + firstInvalidTarget, err := peer.NewPeer("test:1111", "", "", config) if err != nil { t.Fatalf("Create NewPeer error(%v)", err) } // Create second invalid target - secondInvalidTarget, err := fabricClient.NewPeer("test:2222", "", "") + secondInvalidTarget, err := peer.NewPeer("test:2222", "", "", config) if err != nil { t.Fatalf("Create NewPeer error(%v)", err) } @@ -247,18 +248,18 @@ func testQueryByChaincode(t *testing.T, chain fabricClient.Chain) { invalidTargets := append(targets, firstInvalidTarget) invalidTargets = append(invalidTargets, secondInvalidTarget) - // Add invalid targets to chain otherwise validation will fail - err = chain.AddPeer(firstInvalidTarget) + // Add invalid targets to channel otherwise validation will fail + err = channel.AddPeer(firstInvalidTarget) if err != nil { t.Fatalf("Error adding peer: %v", err) } - err = chain.AddPeer(secondInvalidTarget) + err = channel.AddPeer(secondInvalidTarget) if err != nil { t.Fatalf("Error adding peer: %v", err) } // Test valid + invalid targets - queryResponses, err = chain.QueryByChaincode("lscc", []string{"getinstalledchaincodes"}, invalidTargets) + queryResponses, err = channel.QueryByChaincode("lscc", []string{"getinstalledchaincodes"}, invalidTargets) if err == nil { t.Fatalf("QueryByChaincode failed to return error for non-existing target") } @@ -268,6 +269,6 @@ func testQueryByChaincode(t *testing.T, chain fabricClient.Chain) { t.Fatalf("QueryByChaincode number of results mismatch. Expected: %d Got: %d", len(targets), len(queryResponses)) } - chain.RemovePeer(firstInvalidTarget) - chain.RemovePeer(secondInvalidTarget) + channel.RemovePeer(firstInvalidTarget) + channel.RemovePeer(secondInvalidTarget) } diff --git a/test/integration/end_to_end_test.go b/test/integration/end_to_end_test.go index 21d11dfff6..64a09dafad 100644 --- a/test/integration/end_to_end_test.go +++ b/test/integration/end_to_end_test.go @@ -12,14 +12,14 @@ import ( "testing" "time" - "github.com/hyperledger/fabric-sdk-go/fabric-client/util" + "github.com/hyperledger/fabric-sdk-go/pkg/util" ) func TestChainCodeInvoke(t *testing.T) { testSetup := BaseSetupImpl{ ConfigFile: "../fixtures/config/config_test.yaml", - ChainID: "mychannel", + ChannelID: "mychannel", ChannelConfig: "../fixtures/channel/mychannel.tx", ConnectEventHub: true, } diff --git a/test/integration/events_test.go b/test/integration/events_test.go index d43f92d77e..8b2ad669d8 100644 --- a/test/integration/events_test.go +++ b/test/integration/events_test.go @@ -10,8 +10,9 @@ import ( "testing" "time" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - "github.com/hyperledger/fabric-sdk-go/fabric-client/util" + api "github.com/hyperledger/fabric-sdk-go/api" + + "github.com/hyperledger/fabric-sdk-go/pkg/util" "github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric/protos/peer" ) @@ -28,7 +29,7 @@ func TestEvents(t *testing.T) { func initializeTests(t *testing.T) BaseSetupImpl { testSetup := BaseSetupImpl{ ConfigFile: "../fixtures/config/config_test.yaml", - ChainID: "mychannel", + ChannelID: "mychannel", ChannelConfig: "../fixtures/channel/mychannel.tx", ConnectEventHub: true, } @@ -44,7 +45,7 @@ func initializeTests(t *testing.T) BaseSetupImpl { t.Fatalf("installCC return error: %v", err) } - if err := testSetup.InstantiateCC(testSetup.ChainCodeID, testSetup.ChainID, "github.com/events_cc", "v0", nil); err != nil { + if err := testSetup.InstantiateCC(testSetup.ChainCodeID, testSetup.ChannelID, "github.com/events_cc", "v0", nil); err != nil { t.Fatalf("instantiateCC return error: %v", err) } @@ -58,12 +59,12 @@ func testFailedTx(t *testing.T, testSetup BaseSetupImpl) { args = append(args, "invoke") args = append(args, "SEVERE") - tpResponses1, tx1, err := util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil) + tpResponses1, tx1, err := util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, nil) if err != nil { t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err) } - tpResponses2, tx2, err := util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil) + tpResponses2, tx2, err := util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, nil) if err != nil { t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err) } @@ -77,11 +78,11 @@ func testFailedTx(t *testing.T, testSetup BaseSetupImpl) { // Test invalid transaction: create 2 invoke requests in quick succession that modify // the same state variable which should cause one invoke to be invalid - _, err = util.CreateAndSendTransaction(testSetup.Chain, tpResponses1) + _, err = util.CreateAndSendTransaction(testSetup.Channel, tpResponses1) if err != nil { t.Fatalf("First invoke failed err: %v", err) } - _, err = util.CreateAndSendTransaction(testSetup.Chain, tpResponses2) + _, err = util.CreateAndSendTransaction(testSetup.Channel, tpResponses2) if err != nil { t.Fatalf("Second invoke failed err: %v", err) } @@ -109,12 +110,12 @@ func testFailedTxErrorCode(t *testing.T, testSetup BaseSetupImpl) { args = append(args, "invoke") args = append(args, "SEVERE") - tpResponses1, tx1, err := util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil) + tpResponses1, tx1, err := util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, nil) if err != nil { t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err) } - tpResponses2, tx2, err := util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil) + tpResponses2, tx2, err := util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, nil) if err != nil { t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err) } @@ -149,11 +150,11 @@ func testFailedTxErrorCode(t *testing.T, testSetup BaseSetupImpl) { // Test invalid transaction: create 2 invoke requests in quick succession that modify // the same state variable which should cause one invoke to be invalid - _, err = util.CreateAndSendTransaction(testSetup.Chain, tpResponses1) + _, err = util.CreateAndSendTransaction(testSetup.Channel, tpResponses1) if err != nil { t.Fatalf("First invoke failed err: %v", err) } - _, err = util.CreateAndSendTransaction(testSetup.Chain, tpResponses2) + _, err = util.CreateAndSendTransaction(testSetup.Channel, tpResponses2) if err != nil { t.Fatalf("Second invoke failed err: %v", err) } @@ -206,7 +207,7 @@ func testMultipleBlockEventCallbacks(t *testing.T, testSetup BaseSetupImpl) { test <- true }) - tpResponses, tx, err := util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil) + tpResponses, tx, err := util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, nil) if err != nil { t.Fatalf("CreateAndSendTransactionProposal returned error: %v \n", err) } @@ -215,7 +216,7 @@ func testMultipleBlockEventCallbacks(t *testing.T, testSetup BaseSetupImpl) { done, fail := util.RegisterTxEvent(tx, testSetup.EventHub) defer testSetup.EventHub.UnregisterTxEvent(tx) - _, err = util.CreateAndSendTransaction(testSetup.Chain, tpResponses) + _, err = util.CreateAndSendTransaction(testSetup.Channel, tpResponses) if err != nil { t.Fatalf("CreateAndSendTransaction failed with error: %v", err) } diff --git a/test/integration/fabric_ca_test.go b/test/integration/fabric_ca_test.go index 423a5c8748..46db660cfc 100644 --- a/test/integration/fabric_ca_test.go +++ b/test/integration/fabric_ca_test.go @@ -16,12 +16,14 @@ import ( "testing" "time" - config "github.com/hyperledger/fabric-sdk-go/config" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - kvs "github.com/hyperledger/fabric-sdk-go/fabric-client/keyvaluestore" + api "github.com/hyperledger/fabric-sdk-go/api" + + client "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/client" + kvs "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/keyvaluestore" + sdkUser "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/user" bccspFactory "github.com/hyperledger/fabric/bccsp/factory" - fabricCAClient "github.com/hyperledger/fabric-sdk-go/fabric-ca-client" + fabricCAClient "github.com/hyperledger/fabric-sdk-go/pkg/fabric-ca-client" ) // This test loads/enrols an admin user @@ -31,10 +33,14 @@ func TestRegisterEnrollRevoke(t *testing.T) { ConfigFile: "../fixtures/config/config_test.yaml", } - testSetup.InitConfig() - client := fabricClient.NewClient() + config, err := testSetup.InitConfig() + if err != nil { + t.Fatalf("Failed InitConfig [%s]", err) + + } + client := client.NewClient(config) - err := bccspFactory.InitFactories(config.GetCSPConfig()) + err = bccspFactory.InitFactories(config.GetCSPConfig()) if err != nil { t.Fatalf("Failed getting ephemeral software-based BCCSP [%s]", err) } @@ -48,7 +54,7 @@ func TestRegisterEnrollRevoke(t *testing.T) { } client.SetStateStore(stateStore) - caClient, err := fabricCAClient.NewFabricCAClient() + caClient, err := fabricCAClient.NewFabricCAClient(config) if err != nil { t.Fatalf("NewFabricCAClient return error: %v", err) } @@ -83,7 +89,7 @@ func TestRegisterEnrollRevoke(t *testing.T) { if cert509.Subject.CommonName != "admin" { t.Fatalf("CommonName in x509 cert is not the enrollmentID") } - adminUser = fabricClient.NewUser("admin") + adminUser = sdkUser.NewUser("admin") adminUser.SetPrivateKey(key) adminUser.SetEnrollmentCertificate(cert) err = client.SaveUserToStateStore(adminUser, false) @@ -101,7 +107,7 @@ func TestRegisterEnrollRevoke(t *testing.T) { // Register a random user userName := createRandomName() - registerRequest := fabricCAClient.RegistrationRequest{ + registerRequest := api.RegistrationRequest{ Name: userName, Type: "user", Affiliation: "org1.department1", @@ -120,7 +126,7 @@ func TestRegisterEnrollRevoke(t *testing.T) { //re-enroll fmt.Printf("** Attempt to re-enrolled user: '%s'\n", userName) //create new user object and set certificate and private key of the previously enrolled user - enrolleduser := fabricClient.NewUser(userName) + enrolleduser := sdkUser.NewUser(userName) enrolleduser.SetEnrollmentCertificate(ecert) enrolleduser.SetPrivateKey(ekey) //reenroll @@ -133,7 +139,7 @@ func TestRegisterEnrollRevoke(t *testing.T) { t.Fatalf("Error Reenroling user. Enrollmet and Reenrollment certificates are the same.") } - revokeRequest := fabricCAClient.RevocationRequest{Name: userName, CAName: "ca-org1"} + revokeRequest := api.RevocationRequest{Name: userName, CAName: "ca-org1"} err = caClient.Revoke(adminUser, &revokeRequest) if err != nil { t.Fatalf("Error from Revoke: %s", err) diff --git a/test/integration/install_chaincode_test.go b/test/integration/install_chaincode_test.go index b315a20bf5..ab1db0dafd 100644 --- a/test/integration/install_chaincode_test.go +++ b/test/integration/install_chaincode_test.go @@ -14,8 +14,8 @@ import ( "testing" "time" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - "github.com/hyperledger/fabric-sdk-go/fabric-client/util" + packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/packager" + "github.com/hyperledger/fabric-sdk-go/pkg/util" ) const ( @@ -27,7 +27,7 @@ func TestChaincodeInstal(t *testing.T) { testSetup := &BaseSetupImpl{ ConfigFile: "../fixtures/config/config_test.yaml", - ChainID: "mychannel", + ChannelID: "mychannel", ChannelConfig: "../fixtures/channel/mychannel.tx", ConnectEventHub: true, } @@ -52,7 +52,7 @@ func testChaincodeInstallUsingChaincodePath(t *testing.T, testSetup *BaseSetupIm if err := testSetup.InstallCC(chainCodeName, chainCodePath, chainCodeVersion, nil); err != nil { t.Fatalf("installCC return error: %v", err) } - chaincodeQueryResponse, err := client.QueryInstalledChaincodes(testSetup.Chain.GetPrimaryPeer()) + chaincodeQueryResponse, err := client.QueryInstalledChaincodes(testSetup.Channel.GetPrimaryPeer()) if err != nil { t.Fatalf("QueryInstalledChaincodes return error: %v", err) } @@ -82,7 +82,7 @@ func testChaincodeInstallUsingChaincodePackage(t *testing.T, testSetup *BaseSetu chainCodeVersion := getRandomCCVersion() util.ChangeGOPATHToDeploy(testSetup.GetDeployPath()) - chaincodePackage, err := fabricClient.PackageCC(chainCodePath, "") + chaincodePackage, err := packager.PackageCC(chainCodePath, "") util.ResetGOPATH() if err != nil { t.Fatalf("PackageCC return error: %s", err) diff --git a/test/integration/transient_data_test.go b/test/integration/transient_data_test.go index 347e9608c2..74852c410b 100644 --- a/test/integration/transient_data_test.go +++ b/test/integration/transient_data_test.go @@ -9,8 +9,8 @@ package integration import ( "testing" - fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client" - "github.com/hyperledger/fabric-sdk-go/fabric-client/util" + api "github.com/hyperledger/fabric-sdk-go/api" + "github.com/hyperledger/fabric-sdk-go/pkg/util" ) // TestTransient ... @@ -18,7 +18,7 @@ func TestTransient(t *testing.T) { testSetup := BaseSetupImpl{ ConfigFile: "../fixtures/config/config_test.yaml", - ChainID: "mychannel", + ChannelID: "mychannel", ChannelConfig: "../fixtures/channel/mychannel.tx", ConnectEventHub: true, } @@ -42,11 +42,11 @@ func TestTransient(t *testing.T) { transientDataMap := make(map[string][]byte) transientDataMap["result"] = []byte(transientData) - transactionProposalResponse, _, err := util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, transientDataMap) + transactionProposalResponse, _, err := util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, transientDataMap) if err != nil { t.Fatalf("CreateAndSendTransactionProposal return error: %v", err) } - strResponse := string(transactionProposalResponse[0].GetResponsePayload()) + strResponse := string(transactionProposalResponse[0].ProposalResponse.GetResponse().Payload) //validate transient data exists in proposal if len(strResponse) == 0 { t.Fatalf("Transient data does not exist: expected %s", transientData) @@ -57,12 +57,12 @@ func TestTransient(t *testing.T) { } //transient data null transientDataMap["result"] = []byte{} - transactionProposalResponse, _, err = util.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, transientDataMap) + transactionProposalResponse, _, err = util.CreateAndSendTransactionProposal(testSetup.Channel, testSetup.ChainCodeID, testSetup.ChannelID, args, []api.Peer{testSetup.Channel.GetPrimaryPeer()}, transientDataMap) if err != nil { t.Fatalf("CreateAndSendTransactionProposal with empty transient data return an error: %v", err) } //validate that transient data does not exist in proposal - strResponse = string(transactionProposalResponse[0].GetResponsePayload()) + strResponse = string(transactionProposalResponse[0].ProposalResponse.GetResponse().Payload) if len(strResponse) != 0 { t.Fatalf("Transient data validation has failed. An empty transient data was expected but %s was returned", strResponse) } diff --git a/test/integration/utils.go b/test/integration/utils.go index a6723797ef..09f23ec93a 100644 --- a/test/integration/utils.go +++ b/test/integration/utils.go @@ -9,19 +9,19 @@ package integration import ( "fmt" - fc "github.com/hyperledger/fabric-sdk-go/fabric-client" - "github.com/hyperledger/fabric-sdk-go/fabric-client/util" + api "github.com/hyperledger/fabric-sdk-go/api" + "github.com/hyperledger/fabric-sdk-go/pkg/util" ) // GetOrdererAdmin ... -func GetOrdererAdmin(c fc.Client) (fc.User, error) { +func GetOrdererAdmin(c api.FabricClient) (api.User, error) { keyDir := "ordererOrganizations/example.com/users/Admin@example.com/keystore" certDir := "ordererOrganizations/example.com/users/Admin@example.com/signcerts" return util.GetPreEnrolledUser(c, keyDir, certDir, "ordererAdmin") } // GetAdmin ... -func GetAdmin(c fc.Client, userOrg string) (fc.User, error) { +func GetAdmin(c api.FabricClient, userOrg string) (api.User, error) { keyDir := fmt.Sprintf("peerOrganizations/%s.example.com/users/Admin@%s.example.com/keystore", userOrg, userOrg) certDir := fmt.Sprintf("peerOrganizations/%s.example.com/users/Admin@%s.example.com/signcerts", userOrg, userOrg) username := fmt.Sprintf("peer%sAdmin", userOrg) diff --git a/test/scripts/check_lint.sh b/test/scripts/check_lint.sh index 8488c34931..cdc9ad9e63 100755 --- a/test/scripts/check_lint.sh +++ b/test/scripts/check_lint.sh @@ -9,9 +9,9 @@ set -e declare -a arr=( -"./config" -"./fabric-ca-client" -"./fabric-client" +"./pkg/config" +"./pkg/fabric-ca-client" +"./pkg/fabric-client" "./test" )