1 Star 0 Fork 0

BUPT-ZKJC/fabric-sdk-go

Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
Clone or Download
fabsdk.go 18.47 KB
Copy Edit Raw Blame History
MJL authored 2021-08-06 18:40 . first commit
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
// Package fabsdk enables client usage of a Hyperledger Fabric network.
package fabsdk
import (
"math/rand"
"time"
"gitee.com/bupt-zkjc/fabric-sdk-go/internal/github.com/hyperledger/fabric/core/operations"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/common/logging"
coptions "gitee.com/bupt-zkjc/fabric-sdk-go/pkg/common/options"
contextApi "gitee.com/bupt-zkjc/fabric-sdk-go/pkg/common/providers/context"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/common/providers/core"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/common/providers/fab"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/common/providers/msp"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/context"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/core/config/lookup"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/core/cryptosuite"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/core/logging/api"
fabImpl "gitee.com/bupt-zkjc/fabric-sdk-go/pkg/fab"
sdkApi "gitee.com/bupt-zkjc/fabric-sdk-go/pkg/fabsdk/api"
"gitee.com/bupt-zkjc/fabric-sdk-go/pkg/fabsdk/metrics"
metricsCfg "gitee.com/bupt-zkjc/fabric-sdk-go/pkg/fabsdk/metrics/cfg"
mspImpl "gitee.com/bupt-zkjc/fabric-sdk-go/pkg/msp"
"github.com/pkg/errors"
)
var logger = logging.NewLogger("fabsdk")
// FabricSDK provides access (and context) to clients being managed by the SDK.
type FabricSDK struct {
opts options
provider *context.Provider
cryptoSuite core.CryptoSuite
system *operations.System
clientMetrics *metrics.ClientMetrics
}
type configs struct {
cryptoSuiteConfig core.CryptoSuiteConfig
endpointConfig fab.EndpointConfig
identityConfig msp.IdentityConfig
metricsConfig metricsCfg.MetricsConfig
}
type options struct {
Core sdkApi.CoreProviderFactory
MSP sdkApi.MSPProviderFactory
Service sdkApi.ServiceProviderFactory
Logger api.LoggerProvider
CryptoSuiteConfig core.CryptoSuiteConfig
endpointConfig fab.EndpointConfig
IdentityConfig msp.IdentityConfig
ConfigBackend []core.ConfigBackend
ProviderOpts []coptions.Opt // Provider options are passed along to the various providers
metricsConfig metricsCfg.MetricsConfig
}
// Option configures the SDK.
type Option func(opts *options) error
type closeable interface {
Close()
}
type contextCloseable interface {
CloseContext(ctxt fab.ClientContext)
}
// New initializes the SDK based on the set of options provided.
// ConfigOptions provides the application configuration.
func New(configProvider core.ConfigProvider, opts ...Option) (*FabricSDK, error) {
pkgSuite := defPkgSuite{}
return fromPkgSuite(configProvider, &pkgSuite, opts...)
}
// fromPkgSuite creates an SDK based on the implementations in the provided pkg suite.
// TODO: For now leaving this method as private until we have more usage.
func fromPkgSuite(configProvider core.ConfigProvider, pkgSuite pkgSuite, opts ...Option) (*FabricSDK, error) {
coreProv, err := pkgSuite.Core()
if err != nil {
return nil, errors.WithMessage(err, "Unable to initialize core pkg")
}
mspProv, err := pkgSuite.MSP()
if err != nil {
return nil, errors.WithMessage(err, "Unable to initialize core pkg")
}
svc, err := pkgSuite.Service()
if err != nil {
return nil, errors.WithMessage(err, "Unable to initialize service pkg")
}
lg, err := pkgSuite.Logger()
if err != nil {
return nil, errors.WithMessage(err, "Unable to initialize logger pkg")
}
sdk := FabricSDK{
opts: options{
Core: coreProv,
MSP: mspProv,
Service: svc,
Logger: lg,
},
}
err = initSDK(&sdk, configProvider, opts)
if err != nil {
return nil, err
}
return &sdk, err
}
// WithCryptoSuiteConfig injects a CryptoSuiteConfig interface to the SDK
// it accepts either a full interface of CryptoSuiteConfig or a list
// of sub interfaces each implementing one (or more) function(s) of CryptoSuiteConfig
func WithCryptoSuiteConfig(cryptoConfigs ...interface{}) Option {
return func(opts *options) error {
c, err := cryptosuite.BuildCryptoSuiteConfigFromOptions(cryptoConfigs...)
if err != nil {
return err
}
opts.CryptoSuiteConfig = c
return nil
}
}
// WithEndpointConfig injects a EndpointConfig interface to the SDK
// it accepts either a full interface of EndpointConfig or a list
// of sub interfaces each implementing one (or more) function(s) of EndpointConfig
func WithEndpointConfig(endpointConfigs ...interface{}) Option {
return func(opts *options) error {
c, err := fabImpl.BuildConfigEndpointFromOptions(endpointConfigs...)
if err != nil {
return err
}
opts.endpointConfig = c
return nil
}
}
// WithIdentityConfig injects a IdentityConfig interface to the SDK
// it accepts either a full interface of IdentityConfig or a list
// of sub interfaces each implementing one (or more) function(s) of IdentityConfig
func WithIdentityConfig(identityConfigs ...interface{}) Option {
return func(opts *options) error {
c, err := mspImpl.BuildIdentityConfigFromOptions(identityConfigs...)
if err != nil {
return err
}
opts.IdentityConfig = c
return nil
}
}
// WithCorePkg injects the core implementation into the SDK.
func WithCorePkg(core sdkApi.CoreProviderFactory) Option {
return func(opts *options) error {
opts.Core = core
return nil
}
}
// WithMSPPkg injects the MSP implementation into the SDK.
func WithMSPPkg(msp sdkApi.MSPProviderFactory) Option {
return func(opts *options) error {
opts.MSP = msp
return nil
}
}
// WithServicePkg injects the service implementation into the SDK.
func WithServicePkg(service sdkApi.ServiceProviderFactory) Option {
return func(opts *options) error {
opts.Service = service
return nil
}
}
// WithLoggerPkg injects the logger implementation into the SDK.
func WithLoggerPkg(logger api.LoggerProvider) Option {
return func(opts *options) error {
opts.Logger = logger
return nil
}
}
// WithMetricsConfig injects a MetricsConfig interface to the SDK
// it accepts either a full interface of MetricsConfig or a list
// of sub interfaces each implementing one (or more) function(s) of MetricsConfig
func WithMetricsConfig(metricsConfigs ...interface{}) Option {
return func(opts *options) error {
c, err := metricsCfg.BuildConfigMetricsFromOptions(metricsConfigs...)
if err != nil {
return err
}
opts.metricsConfig = c
return nil
}
}
// WithProviderOpts adds options which are propagated to the various providers.
func WithProviderOpts(sopts ...coptions.Opt) Option {
return func(opts *options) error {
opts.ProviderOpts = append(opts.ProviderOpts, sopts...)
return nil
}
}
// WithErrorHandler sets an error handler that will be invoked when a service error is experienced.
// This allows the client to take a decision of whether to ignore the error, shut down the client context,
// or shut down the entire SDK.
func WithErrorHandler(value fab.ErrorHandler) Option {
return WithProviderOpts(withErrorHandlerProviderOpt(value))
}
// providerInit interface allows for initializing providers
// TODO: minimize interface
type providerInit interface {
Initialize(providers contextApi.Providers) error
}
func initSDK(sdk *FabricSDK, configProvider core.ConfigProvider, opts []Option) error { //nolint
for _, option := range opts {
err := option(&sdk.opts)
if err != nil {
return errors.WithMessage(err, "Error in option passed to New")
}
}
// Initialize logging provider with default logging provider (if needed)
if sdk.opts.Logger == nil {
return errors.New("Missing logger from pkg suite")
}
logging.Initialize(sdk.opts.Logger)
//Initialize configs if not passed through options
cfg, err := sdk.loadConfigs(configProvider)
if err != nil {
return errors.WithMessage(err, "failed to initialize configuration")
}
// Initialize rand (TODO: should probably be optional)
rand.Seed(time.Now().UnixNano())
// Initialize state store
userStore, err := sdk.opts.MSP.CreateUserStore(cfg.identityConfig)
if err != nil {
return errors.WithMessage(err, "failed to create state store")
}
// Initialize Signing Manager
signingManager, err := sdk.opts.Core.CreateSigningManager(sdk.cryptoSuite)
if err != nil {
return errors.WithMessage(err, "failed to create signing manager")
}
// Initialize IdentityManagerProvider
identityManagerProvider, err := sdk.opts.MSP.CreateIdentityManagerProvider(cfg.endpointConfig, sdk.cryptoSuite, userStore)
if err != nil {
return errors.WithMessage(err, "failed to create identity manager provider")
}
// Initialize Fabric provider
infraProvider, err := sdk.opts.Core.CreateInfraProvider(cfg.endpointConfig)
if err != nil {
return errors.WithMessage(err, "failed to create infra provider")
}
// Initialize local discovery provider
localDiscoveryProvider, err := sdk.opts.Service.CreateLocalDiscoveryProvider(cfg.endpointConfig)
if err != nil {
return errors.WithMessage(err, "failed to create local discovery provider")
}
channelProvider, err := sdk.opts.Service.CreateChannelProvider(cfg.endpointConfig, sdk.opts.ProviderOpts...)
if err != nil {
return errors.WithMessage(err, "failed to create channel provider")
}
sdk.initMetrics(cfg)
//update sdk providers list since all required providers are initialized
sdk.provider = context.NewProvider(context.WithCryptoSuiteConfig(cfg.cryptoSuiteConfig),
context.WithEndpointConfig(cfg.endpointConfig),
context.WithIdentityConfig(cfg.identityConfig),
context.WithCryptoSuite(sdk.cryptoSuite),
context.WithSigningManager(signingManager),
context.WithUserStore(userStore),
context.WithLocalDiscoveryProvider(localDiscoveryProvider),
context.WithIdentityManagerProvider(identityManagerProvider),
context.WithInfraProvider(infraProvider),
context.WithChannelProvider(channelProvider),
context.WithClientMetrics(sdk.clientMetrics),
)
//initialize
if pi, ok := infraProvider.(providerInit); ok {
err = pi.Initialize(sdk.provider)
if err != nil {
return errors.WithMessage(err, "failed to initialize infra provider")
}
}
if pi, ok := localDiscoveryProvider.(providerInit); ok {
err = pi.Initialize(sdk.provider)
if err != nil {
return errors.WithMessage(err, "failed to initialize local discovery provider")
}
}
if pi, ok := channelProvider.(providerInit); ok {
err = pi.Initialize(sdk.provider)
if err != nil {
return errors.WithMessage(err, "failed to initialize channel provider")
}
}
logger.Debug("SDK initialized successfully")
return nil
}
// Close frees up caches and connections being maintained by the SDK
func (sdk *FabricSDK) Close() {
logger.Debug("SDK closing")
if pvdr, ok := sdk.provider.LocalDiscoveryProvider().(closeable); ok {
pvdr.Close()
}
if pvdr, ok := sdk.provider.ChannelProvider().(closeable); ok {
pvdr.Close()
}
sdk.provider.InfraProvider().Close()
}
// CloseContext frees up caches being maintained by the SDK for the given context
func (sdk *FabricSDK) CloseContext(ctxt fab.ClientContext) {
logger.Debug("Closing clients for the given context...")
if pvdr, ok := sdk.provider.LocalDiscoveryProvider().(contextCloseable); ok {
logger.Debugf("Closing local discovery provider...")
pvdr.CloseContext(ctxt)
}
if pvdr, ok := sdk.provider.ChannelProvider().(contextCloseable); ok {
logger.Debugf("Closing context in channel client...")
pvdr.CloseContext(ctxt)
}
}
//Config returns config backend used by all SDK config types
func (sdk *FabricSDK) Config() (core.ConfigBackend, error) {
if sdk.opts.ConfigBackend == nil {
return nil, errors.New("unable to find config backend")
}
return lookup.New(sdk.opts.ConfigBackend...), nil
}
//Context creates and returns context client which has all the necessary providers
func (sdk *FabricSDK) Context(options ...ContextOption) contextApi.ClientProvider {
clientProvider := func() (contextApi.Client, error) {
identity, err := sdk.newIdentity(options...)
if err == ErrAnonymousIdentity {
identity = nil
err = nil
}
return &context.Client{Providers: sdk.provider, SigningIdentity: identity}, err
}
return clientProvider
}
//ChannelContext creates and returns channel context
func (sdk *FabricSDK) ChannelContext(channelID string, options ...ContextOption) contextApi.ChannelProvider {
channelProvider := func() (contextApi.Channel, error) {
clientCtxProvider := sdk.Context(options...)
return context.NewChannel(clientCtxProvider, channelID)
}
return channelProvider
}
// initializeCryptoSuite Initializes crypto provider
func (sdk *FabricSDK) initializeCryptoSuite(cryptoSuiteConfig core.CryptoSuiteConfig) error {
var err error
sdk.cryptoSuite, err = sdk.opts.Core.CreateCryptoSuiteProvider(cryptoSuiteConfig)
if err != nil {
return errors.WithMessage(err, "failed to initialize crypto suite")
}
// Setting this cryptosuite as the factory default
if !cryptosuite.DefaultInitialized() {
err = cryptosuite.SetDefault(sdk.cryptoSuite)
if err != nil {
return errors.WithMessage(err, "failed to set default crypto suite")
}
} else {
logger.Debug("default cryptosuite already initialized")
}
return nil
}
//loadConfigs load config from config backend when configs are not provided through opts
func (sdk *FabricSDK) loadConfigs(configProvider core.ConfigProvider) (*configs, error) {
c := &configs{
identityConfig: sdk.opts.IdentityConfig,
endpointConfig: sdk.opts.endpointConfig,
cryptoSuiteConfig: sdk.opts.CryptoSuiteConfig,
metricsConfig: sdk.opts.metricsConfig,
}
var configBackend []core.ConfigBackend
var err error
if configProvider != nil {
configBackend, err = configProvider()
if err != nil {
return nil, errors.WithMessage(err, "unable to load config backend")
}
}
//configs passed through opts take priority over default ones
// load crypto suite config
c.cryptoSuiteConfig, err = sdk.loadCryptoConfig(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "unable to load crypto suite config")
}
//Initialize cryptosuite once crypto Suite config is available
err = sdk.initializeCryptoSuite(c.cryptoSuiteConfig)
if err != nil {
return nil, errors.WithMessage(err, "unable to initialize cryptosuite using crypto suite config")
}
// load endpoint config
c.endpointConfig, err = sdk.loadEndpointConfig(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "unable to load endpoint config")
}
// load identity config
c.identityConfig, err = sdk.loadIdentityConfig(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "unable to load identity config")
}
// load metrics config
c.metricsConfig, err = sdk.loadMetricsConfig(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "unable to load metrics config")
}
sdk.opts.ConfigBackend = configBackend
return c, nil
}
//loadEndpointConfig loads config from config backend when configs are not provided through opts or override missing interfaces from opts with config backend
func (sdk *FabricSDK) loadEndpointConfig(configBackend ...core.ConfigBackend) (fab.EndpointConfig, error) {
endpointConfigOpt, ok := sdk.opts.endpointConfig.(*fabImpl.EndpointConfigOptions)
// if optional endpoint was nil or not all of its sub interface functions were overridden,
// then get default endpoint config and override the functions that were not overridden by opts
if sdk.opts.endpointConfig == nil || (ok && !fabImpl.IsEndpointConfigFullyOverridden(endpointConfigOpt)) {
defEndpointConfig, err := fabImpl.ConfigFromBackend(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "failed to initialize endpoint config from config backend")
}
// if opts.endpointConfig was not provided during WithEndpointConfig(opts...) call, then return default endpointConfig
if sdk.opts.endpointConfig == nil {
return defEndpointConfig, nil
}
// else fill any empty interface from opts with defEndpointConfig interface (set default function for ones not provided by WithEndpointConfig() call) and return
return fabImpl.UpdateMissingOptsWithDefaultConfig(endpointConfigOpt, defEndpointConfig), nil
}
// if optional endpoint config was completely overridden but !ok, then return an error
if !ok {
return nil, errors.New("failed to retrieve config endpoint from opts")
}
return endpointConfigOpt, nil
}
func (sdk *FabricSDK) loadCryptoConfig(configBackend ...core.ConfigBackend) (core.CryptoSuiteConfig, error) {
cryptoConfigOpt, ok := sdk.opts.CryptoSuiteConfig.(*cryptosuite.CryptoConfigOptions)
if sdk.opts.CryptoSuiteConfig == nil || (ok && !cryptosuite.IsCryptoConfigFullyOverridden(cryptoConfigOpt)) {
defCryptoConfig := cryptosuite.ConfigFromBackend(configBackend...)
if sdk.opts.CryptoSuiteConfig == nil {
return defCryptoConfig, nil
}
return cryptosuite.UpdateMissingOptsWithDefaultConfig(cryptoConfigOpt, defCryptoConfig), nil
}
if !ok {
return nil, errors.New("failed to retrieve crypto suite configs from opts")
}
return cryptoConfigOpt, nil
}
func (sdk *FabricSDK) loadIdentityConfig(configBackend ...core.ConfigBackend) (msp.IdentityConfig, error) {
identityConfigOpt, ok := sdk.opts.IdentityConfig.(*mspImpl.IdentityConfigOptions)
if sdk.opts.IdentityConfig == nil || (ok && !mspImpl.IsIdentityConfigFullyOverridden(identityConfigOpt)) {
defIdentityConfig, err := mspImpl.ConfigFromBackend(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "failed to initialize identity config from config backend")
}
if sdk.opts.IdentityConfig == nil {
return defIdentityConfig, nil
}
return mspImpl.UpdateMissingOptsWithDefaultConfig(identityConfigOpt, defIdentityConfig), nil
}
if !ok {
return nil, errors.New("failed to retrieve identity configs from opts")
}
return identityConfigOpt, nil
}
func (sdk *FabricSDK) loadMetricsConfig(configBackend ...core.ConfigBackend) (metricsCfg.MetricsConfig, error) {
metricsConfigOpt, ok := sdk.opts.metricsConfig.(*metricsCfg.OperationsConfigOptions)
if sdk.opts.metricsConfig == nil || (ok && !metricsCfg.IsMetricsConfigFullyOverridden(metricsConfigOpt)) {
defMetricsConfig, err := metricsCfg.ConfigFromBackend(configBackend...)
if err != nil {
return nil, errors.WithMessage(err, "failed to initialize metrics config from config backend")
}
if sdk.opts.metricsConfig == nil {
return defMetricsConfig, nil
}
return metricsCfg.UpdateMissingOptsWithDefaultConfig(metricsConfigOpt, defMetricsConfig), nil
}
if !ok {
return nil, errors.New("failed to retrieve metrics configs from opts")
}
return metricsConfigOpt, nil
}
func withErrorHandlerProviderOpt(value fab.ErrorHandler) coptions.Opt {
return func(p coptions.Params) {
if setter, ok := p.(errHandlerSetter); ok {
logger.Debugf("... setting error handler")
setter.SetErrorHandler(value)
}
}
}
type errHandlerSetter interface {
SetErrorHandler(value fab.ErrorHandler)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/bupt-zkjc/fabric-sdk-go.git
git@gitee.com:bupt-zkjc/fabric-sdk-go.git
bupt-zkjc
fabric-sdk-go
fabric-sdk-go
84f269695ead

Search