Fabric自定义插件的开发-扩展插件的组织方式

说明:链码开发语言是golang,源码分析是基于v1.4.3版本

Peer节点支持扩展插件,以满足不同的业务需求。
相关配置在core.yaml文件中,配置项为peer.handlers,共支持4类扩展插件:
    a) authFilters,用于拒绝或转发client的提案;
    b) decorators,用于附加或修改peer传递给链码的参数;
    c) endorsers,自定义的背书实现,可以修改背书的格式,扩展内容等;
    d) validators,自定义的交易校验实现,可以修改校验的方式,扩展校验的内容等;

系列文章:
1、Fabric自定义插件的开发-Decorator插件开发
2、Fabric自定义插件的开发-Validators插件开发
3、Fabric自定义插件的开发-Auth插件开发

插件的原理关注之前的文章《fabric系统链码插件开发总结》
peer启动之后,根据配置文件,构造插件相关的library.Config对象,并初始化插件库:
相关代码如下:

函数:func serve(args []string) error {}
位置:peer/node/start.go:129
函数:func InitRegistry(c Config) Registry {}
位置:core/handlers/library/registry.go:80
函数:func (r *registry) loadHandlers(c Config) {}
位置:core/handlers/library/registry.go:92
函数:func (r *registry) evaluateModeAndLoad(c *HandlerConfig, handlerType HandlerType, extraArgs ...string) {}
位置:core/handlers/library/registry.go:110

library.Config对象定义如下:

type Config struct {
	AuthFilters []*HandlerConfig `mapstructure:"authFilters" yaml:"authFilters"`
	Decorators  []*HandlerConfig `mapstructure:"decorators" yaml:"decorators"`
	Endorsers   PluginMapping    `mapstructure:"endorsers" yaml:"endorsers"`
	Validators  PluginMapping    `mapstructure:"validators" yaml:"validators"`
}

可见,AuthFilters和Decorators是Slice结构,而Endorsers和Validators是map结构。
在Peer中维护的插件库是一个单例,内部对象是:core/handlers/library.registry,实现了Lookup(HandlerType) interface{}方法获取对应的Handler,定义如下:

type registry struct {
	filters    []auth.Filter
	decorators []decoration.Decorator
	endorsers  map[string]endorsement2.PluginFactory
	validators map[string]validation.PluginFactory
}

所有成员最终都是接口类型对象,方便扩展,只需要实现接口即可。而endorsers和validators需要指定key,这样支持给不同的链码指定不同的扩展插件。通过链码实例化或升级时的-E和-V参数来指定。
加载的核心代码:

函数:func (r *registry) loadPlugin(pluginPath string, handlerType HandlerType, extraArgs ...string) {}
位置:core/handlers/library/registry.go:147
函数:func (r *registry) loadCompiled(handlerFactory string, handlerType HandlerType, extraArgs ...string) {}
位置:core/handlers/library/registry.go:119

插件的定义:

type HandlerConfig struct {
	Name    string `mapstructure:"name" yaml:"name"`
	Library string `mapstructure:"library" yaml:"library"`
}

根据Library是否为空,来决定使用哪种加载方式。

插件方式加载loadPlugin

相关代码如下:

func (r *registry) initAuthPlugin(p *plugin.Plugin) {}
func (r *registry) initDecoratorPlugin(p *plugin.Plugin) {}
func (r *registry) initEndorsementPlugin(p *plugin.Plugin, extraArgs ...string) {}
func (r *registry) initValidationPlugin(p *plugin.Plugin, extraArgs ...string) {}
静态方式加载loadCompiled

其实就是使用fabric的默认实现,相关代码如下:

func (r *HandlerLibrary) DefaultAuth() auth.Filter {}
func (r *HandlerLibrary) ExpirationCheck() auth.Filter {}
func (r *HandlerLibrary) DefaultDecorator() decoration.Decorator {}
func (r *HandlerLibrary) DefaultEndorsement() endorsement.PluginFactory {}
func (r *HandlerLibrary) DefaultValidation() validation.PluginFactory {}

一般,自定义的扩展插件都是使用Library方式指定,这样可以不修改fabric的源码,也不需要重新编译peer,直接使用官方镜像即可。

插件方式加载的具体实现后续梳理并举例实现~

你可能感兴趣的:(Hyperledger,Fabric)