Hyperledger fabric开发入门
注意:不要在有生产环境的服务器上进行学习测试,(docker-compose关闭服务的时候会清除服务器上所有正在运行的的docker容器)
参考课程:CSDN_超级账本智能合约与DApp
环境配置
目录结构
在gopath中创建
mkdir src
mkdir bin
mkdir pkg
在src中创建mkdir github.com
在github.com中创建mkdir hyperledger
docker安装
一行命令,完成安装:(安装之后记得要把docker服务启动起来)
curl -sSL https://get.daocloud.io/docker | sh
service docker start
而且源在国内
docker-compose安装
通过curl进行安装:
curl -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-``uname -s ``-``uname -m`` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose -v
go安装与配置
参考:http://dicemy.com/29920#Go%E8%AF%AD%E8%A8%80%E5%AE%89%E8%A3%85
一定要注意环境变量的配置
jdk安装
yum list java*
yum install -y java-1.8.0-openjdk-devel.x86_64
java -version
下载fabric的docker镜像
除了baseos下载0.3.1,其余都下1.0.0,然后标记为latest
tools:docker pull hyperledger/fabric-tools:x86_64-1.0.0
ccenv:docker pull hyperledger/fabric-ccenv:x86_64-1.0.0
ca:docker pull hyperledger/fabric-ca:x86_64-1.0.0
orderer:docker pull hyperledger/fabric-orderer:x86_64-1.0.0
peer:docker pull hyperledger/fabric-peer:x86_64-1.0.0
baseos:docker pull hyperledger/fabric-baseos:x86_64-0.3.1
纯命令版:
docker pull hyperledger/fabric-tools:x86_64-1.0.0
docker pull hyperledger/fabric-ccenv:x86_64-1.0.0
docker pull hyperledger/fabric-ca:x86_64-1.0.0
docker pull hyperledger/fabric-orderer:x86_64-1.0.0
docker pull hyperledger/fabric-peer:x86_64-1.0.0
docker pull hyperledger/fabric-baseos:x86_64-0.3.1
注意:记得在所有的安装之后进行tag 编辑成latest状态否则会出现问题
docker tag xxxx xxxx:latest
docker tag hyperledger/fabric-tools:x86_64-1.0.0 hyperledger/fabric-tools:latest
docker tag hyperledger/fabric-ccenv:x86_64-1.0.0 hyperledger/fabric-ccenv:latest
docker tag hyperledger/fabric-ca:x86_64-1.0.0 hyperledger/fabric-ca:latest
docker tag hyperledger/fabric-orderer:x86_64-1.0.0 hyperledger/fabric-orderer:latest
docker tag hyperledger/fabric-peer:x86_64-1.0.0 hyperledger/fabric-peer:latest
docker tag hyperledger/fabric-baseos:x86_64-0.3.1 hyperledger/fabric-baseos:latest
下载fabric源码库
在hyperledger目录下进行git clone https://github.com/hyperledger/fabric.git
git checkout release-1.0
cd /home/gopath/src/github.com/hyperledger/fabric/common/configtx/tool/configtxgen
对工具进行编译。
go install --tags=nopkcs11
注意!!!
奇怪的错误请输入:go env -w GO111MODULE=auto
一定要把这个项目文件的src放在go环境设置下的gopath的文件夹中,输入go env可以查看go安装环境中的gopath文件夹。否则会出现找不到包的报错。
对另一个工具进行编译。
cd /home/gopath/src/github.com/hyperledger/fabric/common/tools/cryptogen
go install --tags=nopkcs11
编译好的工具如下:
下载fabric-samples
cd /home/gopath/src/github.com/hyperledger
git clone https://github.com/hyperledger/fabric-samples.git
git checkout release-1.0
Hello World
1.查看目录
.env:存储一些环境变量
base:储存docker-compose的一些公共服务
byfn.sh:执行脚本
configtx.yaml和crypto-config.yaml:根据之前生成的2个工具,生成相应的配置文件,用来启动网络,放到当前目录的channel-artifacts和crypto-config里面
docker-compose:用于启动网络
scripts:存放测试脚本,做的事:创建通道,加入通道,安装链码,实例化链码,链码交互
2.生成配置
./byfn.sh -m generate -i 1.0.0
注意!!!!
一定要记得吧gopath中的bin目录添加到环境变量中,否则可能无法调用刚才编译好的configtxgen和cryptogen工具
可以通过 export PATH=$PATH:/home/gopath/bin 来临时添加或者使用vim ~/.bash_profile修改PATH 一行,之后使用source ~/.bash_profile生效。
3.启动网络,自动运行测试脚本
./byfn.sh -m up -i 1.0.0
4.关闭网络,自动清楚配置和docker进程
./byfn.sh -m down -i 1.0.0
Hello World 分析
1.查看日志,order和peer分离
peer是按照组织或主体分离的,每一个组织生成ca(存储证书和私钥),msp(存储管理员证书和中间证书),peers(存储每一个peer相关的证书),users(存储每一个用户的证书)
2.查看如下配置
genesis.block:整个网络的创世区块
channel.tx:创建的通道的配置
Org1MSPanchors.tx和Org2MSPanchors.tx:两个主体的锚节点配置
3.启动网络,接着分析日志
fabric网络启动完毕
指定通道名称,和一些变量,通道创建完成
4个peer加入通道
组织中的锚节点在通道中update成功
链码安装到了peer节点
链码实例化
在peer0上进行查询操作,成功
圈圈的是查询结果,查询成功,查询结果为100
进行修改操作,成功
再次查询,结果为90
查看docker进程
3个链码会生成3个image
查看脚本
可以按脚本中的位置找到链码
实现了Init和Invoke接口,就代表是一个fabric智能合约
Init:首先获取参数,不为4个则报错,最终将A和B存到数据库中
Invoke:设置了3个方法,(invoke,delete,query)
invoke:接受3个参数,(谁给谁转账,赚多少)
A给B转账。
持久化数据
接受1个值,从数据库中删除
查询操作,结果以json形式返回
main里只start或者进行一些验证,不写其他代码
srcipts中:初始化操作,A有100元,B有200元
查询A有多少钱,所以打印了100
A给B转账10元
fabric系统架构
架构图
应用层
API:提供了GRPC,(谷歌)RPC框架
SDK:在API基础上封装的SDK,go,java,python,nodejs
事件:分布式系统中,达成共识需要一定的时间,fabric使用异步通信模式开发,触发回调函数执行。
身份:依托于底层的成员服务,是联盟链的认证功能,例如CA
账本:区块链的查询数据,是账本中查出来的,区块高度+交易ID,不重复
交易:对区块链数据进行修改,先提交交易到背书节点,签名认证之后再执行。
智能合约:做合约的安装,实例化和升级
区块链底层
成员服务:提供证书,用于加密和签名
共识服务:CAP(不能全满足,只能满足2个,一致性,可用性和分区容忍性),实际上区块链是弱化了可用性和分区容忍性,所以需要共识算法保证一致性。fabric的共识大概分为三个阶段:
- 首先客户端向背书节点发送一个背书提案,背书节点进行交易模拟,将背书节点和签名返回客户端。
- 然后将背书后的交易,交给排序节点进行排序。有排序节点生成区块,向全网广播。网络节点接受到广播后,先验证区块交易的正确性。
- 验证通过后,存入本地账本。
- PS:排序节点与组织的锚节点使用的是GRPC通信,组织内使用的是gossip协议通信
链码服务:提供安全的,可隔离的交易环境。所以fabric使用docker,链码直接与docker通信。目前阶段对k8s支持的不好,会出问题。
安全及密码服务:fabric定义了一个BCCSP接口,定义签名,加密解密功能,是默认实现了一套国际通用的密码服务,如sha256等
网络拓扑图
- 概念:
- 客户端节点:应用程序和底层的交互媒介,与上层和peer和orderer连接发挥作用,连接peer做交易模拟
- peer节点:包含了锚节点(主节点),在一个组织内可以有多个peer,一个组织中锚节点只有一个,锚节点的作用(与orderer进行通信),锚节点需要HA支持,若锚节点挂了,组织内会选举新的节点与orderer节点进行通信,背书节点(Endorse)理解为担保,与智能合约绑定的,每一个智能合约安装到区块链中,会有一个专属的背书策略,记账节点(committer)所有的peer节点都是记账节点。用于验证从orderer接受的区块,验证交易的有效性,验证通过后,同步到本地账本。
- orderer节点:排序节点,接受全网客户端节点的交易信息,按照一定规则进行排序,将排序好的交易,按照固定的时间间隔打包成区块。与其他组织的主节点进行通信,排序可以用solo(整个网络中只有一个排序节点,使用于开发和测试)和kafka(生产环境下使用,分布式消息队列)模式
- CA节点:可选的,作用:颁发证书,只用被CA认证的节点才能进行交易,fabric不存在51%攻击问题。
- 动作和行为:
- 注册登记:与客户端发起,向CA机构表明自己的身份,获取证书,上图中是第三方的CA,也可以使用官方提供的CA。
- 交易提案:向组织的背书节点提交请求,对应peer节点,组织可以理解为现实中的商业主体,组织是独立的,有两个个数据来源。
- 提交交易:客户端节点向排序节点发请求,orderer内部进行排序打包成区块,广播给其他组织的锚节点,上图是基于kafka实现的,每个组织会选择一个orderer节点进行通信。
交易流程
- 客户端提交交易,最终到记账节点同步数据。
- 智能合约按照要指定背书节点,正常情况下,背书节点返回相同的结果,但签名是不一样的。
- 背书是模拟的过程,不会持久化
- 1,2,3是交易模拟,4,5,6是交易排序,7,8,9是交易同步和记账。交易模拟对应智能合约,交易排序对应共识机制,同步和记账对应账本存储
fabric共识排序
共识机制
- 达成公式需要3个阶段,交易背书,交易排序,交易验证。
- 交易背书:模拟的
- 交易排序:确定交易顺序,最终将排序好的交易打包区块分发。
- 交易验证:区块储存前要进行一下交易验证(不是所有的orderer的东西都能存进去)
Orderer节点的作用
交易排序
- 目的:保证系统的最终一致性(有限状态机)
- solo:单节点排序
- kafka:外置的分布式消息队列
区块分发:
- orderer中的区块并不是最终持久化的区块,
- 是一个中间状态的区块
- 包含了所有交易,不管是有有效还是无效,都会打包传给组织的锚节点。
多通道的数据隔离
- 客户端可以使用某个通道,发送交易
源码目录
从goland中阅读
源码目录
- bccsp:与密码学相关的,加密,数字签名,证书,将密码学中的函数抽象成了接口,方便调用和扩展
- bddtests:行为驱动开发,从需求直接到开发
- common:公共库,错误处理,日志处理,账本存贮,相关工具
- core:是fabric核心库,子目录是各个模块的目录
- comm:网络通信相关
- devenv:官方提供的开发环境,使用的是Vagrant
- docs:文档
- events:事件监听机制
- gossip:通信协议,组织内部的通信,区块同步
- gotools:用于编译
- images:docker镜像相关的
- msp:成员服务管理,member serivce provider 读取证书做签名
- orderer:排序节点
- peer:peer节点
- proposals:用于扩展,新功能的提案
- protos:数据结构的定义
共识机制源码
如果使用goland查看源码时import全部标红的话,进入这个设置,将第一个Enable Go … 这个框勾掉即可。
orderer节点的源码
首先看orderer目录下的main.go
main.go里有一个NewServer
从sever.go可以具体查看交易收集和广播区块
点击Manager,进入Manager.go查看源码(还在sever.go里)
点击chainsupport,查看(在manager.go中)
点receiver进去,看区块切割(在chainsupport.go中)
回顾共识机制源码
- main.go是入口,orderer节点的初始化
- manager.go是控制中枢,是对链的操作,拿到chainsupport对象
- chainsupport.go链对象额代理,与链式对应的关系
- Cut()方法是区块切割
- solo和kafka相关的设置
- sever.go有两个Handle,是交易收集和区块扩散的方法
- 将共识简化为了排序,最终一致性
fabric账本存储
账本存储概念
peer节点做账本存储
orderer是临时存储区块,peer节点时账本存储的持久化,会改变世界状态。
文件系统,区块是存储为文件
区块索引,用于查询区块,是用levelDB实现的
状态数据库,一般村存放区块链最新状态,数据不需要HA,可以从文件系统再次获取,couchDB支持模糊查询
交易读写集
回忆交易流程
- 交易模拟
- 在背书节点执行模拟时,最终返回交易读写集(RWset),告诉区块链在交易中读写了哪些数据
- 交易排序
- 交易验证,交易验证后,更新世界状态,更新的就是读写集中的写集
- 交易模拟
交易读写集的3个概念
- 读集:包含键的列表,键的提交版本,读取赌赢的值,返回的是已提交的状态的值(读已提交),不能读取交易过程中写入的数据。
- 写集:包含键的列表,写入的数据的值,如果多次写入,以最后一次为准。
- 版本号:用区块高度和交易编号组成的。
交易验证阶段是对读写集进行验证(验证读集)
- 验证读集的版本号是和否等于世界状态的版本号
账本存储相关概念
世界状态
- 交易执行后,所有键的最新值
历史数据索引(可选)
区块储存
- 按照文件去存 blockfile_xxxx
- 文件大小是64M,若修改,需要重新编译peer源码
- 账本最大容量64M*
区块读取
- 区块文件流
- 区块流
- 迭代器
区块索引
- 键:区块高度,区块哈希,交易哈希
- 值:区块文件编号,文件内的偏移量,区块数据的长度
区块提交
保存到文件
账本存储相关源码
- 从4方面看,读写集,状态数据, 历史数据,区块文件
- 可以先从core/ledger 下的 ledger_interface.go 中看大体结构
- 读写集,分为交易读写集的生成和交易读写集的验证两个部分去看。
- 交易读写集生成
- fabric/core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/lockbased_tx_simulator.go
- 交易读写集验证
- fabric/core/ledger/kvledger/txmgmt/validator/statebasedval/state_based_validator.go
- 交易读写集生成
- 状态数据库:看levelDB的实现
- fabric/core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go
- 历史数据库:看levelDB的实现
- fabric/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go
- 区块文件读取
- fabric/common/ledger/blkstorage/fsblkstorage/fs_blockstore.go
- 区块流:fabric/common/ledger/blkstorage/fsblkstorage/block_stream.go
账本存储相关源码总结
- 首先看了账本根存储的根目录的接口,从宏观上把握
- 交易读写集的生成和验证
- 数据库增删改查
- 要有一个没有实现的方法,数据剪裁的接口,可能去解决数据无限增长的处理
fabric智能合约
智能合约
fabric_asset配置好的文件下载:点击下载fabric_asset.zip
执行环境:以太坊虚拟智能合约执行环境EVM,fabric执行环境是docker
链码
- 是应用层和区块链底层的中间点
- 每一个链码执行环境是一个独立的docker
- 使用GRPC协议与背书节点通讯,只有背书节点才能运行智能合约
链码的生命周期
- 打包,智能合约的编写和编译
- 安装,将打包好的文件,上传到背书节点
- 实例化,实际的安装了,执行Init方法,只执行一次,构造函数
- 升级,升级和修复链码
- 交互,自己定义的方法的调用
链码的交互流程
系统链码(了解)
- LSCC:管理链码的生命周期
- CSCC:配置管理链码,管理链的配置
- QSCC:查询账本存储,是一个区块索引的外部服务
- ESCC:交易背书的链码,交易执行后的链码进行封装签名,给客户端返回背书交易结果。
- VSCC:交易验证的链码
链码编程的接口
- Init():链码初始化,只执行一次
- Invoke():链码的业务逻辑的编写
- 上面2个方法参数一样,参数是SDK的接口
链码SDK的接口
- 写代码再看
一些注意点
- 分布式多机多节点执行,链码会执行很多次
- 不写随机函数,交易会无效,多次执行不一样
- 系统时间不写,多机时间不一定一样
网络搭建配置的实现
crypto-config.yaml:用于配置组织节点的个数,参考firstnetwork去编写
编写好后,传到linux对应目录
进入deploy目录,设置工作目录为当前目录
export FABRIC_CFG_PATH=$GOPATH/src/fabric_asset/deploy
指定按照yaml文件生成配置
cryptogen generate --config=./crypto-config.yaml
configtx.yaml:用于区块联盟中的组织信息,配合名字和证书等的位置,参考firstnetwork去编写
编写好后,传到linux对应目录
创建用于存放配置的目录
生成系统链的创世区块
-profile 指定联盟配置,-outputBlock 指定存放的位置
configtxgen -profile OneOrgsOrdererGenesis -outputBlock ./config/genesis.block
生成通道的创世交易
profile 指定业务联盟,outputCreateChannelTx存放的路径,插件的名字叫做mychannel
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./config/mychannel.tx -channelID mychannel
注意:如果使用虚拟机为平台的话,会出现用ssh连接执行命令执行出错的情况发生,具体原因不详,但是在虚拟机上可以正常执行并生成成功。
生成两个组织锚节点的交易信息
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./config/Org0MSPanchors.tx -channelID mychannel -asOrg Org0MSP
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./config/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
将docker-compose.yaml拖进deploy目录
启动网络
启动docker,后台运行
查看orderer节点的运行日志
与客户端交互操作
创建通道
-o 指定与哪个orderer节点进行通信,-c指定创建的通道名称,-f指定使用的文件
出现的错误一般情况下是docker-compose中书写有误,e.g.映射路径中etc目录写成了ect
加入通道
查看peer加入的通道列表:
指定主节点
基础网络完成了
安装链码
-n是安装的名字,-v是version,-l是使用的语言
克隆一个会话,交互执行peer0,查看安装的链码
链码实例化
链码交互执行
多次执行查询,得到的结果不同,因为invoke()中使用了随机数,不要这么做。
fabric链码案例
链码入门
编写hello.go,完成后,拖到linux对应目录
安装链码
-n是安装的名字,-v是version,-l是使用的语言
实例化链码
链码调用
账户相关链码
Init()方法与例子程序类似
Invoke()方法包含query,invoke,set,get,
编写完成后拖到linux对应目录
启动容器
交互执行
创建通道
加入通道
设置主节点
安装链码
实例化链码
查询user1的余额
user1给user2转200元
向user1存100元
向user1取200元
贷款还款相关链码
编写Trace下的代码,编写好后,拖到对应linux目录
保证网络基础OK的情况下,安装链码
实例化链码
运行测试
贷款500W
还款500
公民身份信息相关链码
编写citizens下的代码,编写好后,拖到对应linux目录
安装链码
链码实例化
身份查询
合约相关链码
编写contract下的代码,编写好后,拖到对应linux目录
安装链码
链码实例化
发布合约
响应合约
合约成交
合约关闭
查询合约的最新数据
查询合约所有数据
fabric链码案例
流程整理
- 让什么数据上链
- 所有节点备份数据耗费空间,视频等不要上链
- 如何交互
- -c “Args”:[方法名,参数]
- 编写合约
- Init
- Invoke
- 拖到linux运行,基于配置好的网络去部署运行(安装和实例化)
- 合约交互
- SDK调用(页面点击或输入信息)
需求分析
- 开发转让资产
- 功能
- 用户开户和销户
- 资产登记,资产上链,与具体的用户绑定
- 资产转让,资产的所有权变更
- 查询功能,用户查询,资产查询,资产变更的历史查询
- 业务实体
- 用户
- 名字
- 身份证(表示)
- 资产列表
- 资产
- 名字
- 标识
- 特殊属性列表(车:排量,品牌,座位)
- 资产的变更记录
- 资产标识
- 资产的原始拥有者
- 资产变更后的拥有者
- 用户
- 交互方法
- 用户开户
- 参数:名字,标识
- 用户销户
- 标识
- 资产登记
- 名字,标识,特殊属性列表,拥有者
- 资产转让
- 拥有者,资产标识,受让者
- 用户查询
- 参数:标识,返回值:用户实体
- 资产查询
- 参数:标识,返回值:资产实体
- 资产的变更查询
- 参数:资产标识,返回值:资产的变更列表
- 用户开户
合约编写
合约编写完成,传到linux对应目录
创建通道的创世交易(channel名字不能有大写)
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./config/assetschannel.tx -channelID assetschannel
如果出现这个提醒
很有可能是FABRIC_CFG_PATH环境变量没有配置成功,可以直接在deploy目录下设置
export FABRIC_CFG_PATH=$PWD
再次执行该命令即可交互执行
创建通道
加入通道
查看通道
安装链码
链码实例化
注册
用户查询
资产登记
资产查询,查询用户资产绑定
注册了第二个用户
资产转让
查询用户二的用户状态
查询资产一的状态
查询所有资产的变更历史
注销用户2,下面的资产也会随之注销
链码开发者模式
将docker-compose关闭
修改docker-compose配置
运行docker
在另一个会话找到编写好的智能合约
运行链码
在另一个会话进入交互执行
链码安装,实例化,调用之后,修改链码
将第二个,链码运行的对话ctrl+C结束,重新运行链码执行命令
注意:链码开发用这个模式没问题,SDK调用时,可能会出现问题,开发完智能合约关掉开发者模式
外部服务分析
- 如何提供外部服务
- 企业内部各种数据接口,rpc,grpc
- 网站(web),手机(app),通过http
- 智能硬件,socket服务
- SDK提供外部服务,SDK的语言选择
- node.js(官方推荐,效率 9颗星)
- java(实际使用量最大的 9颗星)
- python(使用不太多 3颗星)
- golang(不稳定,常用方法也没有,1颗星)
- SDK的模块
- 区块链的管理:例如通道的创建和加入,链码的安装,实例化等
- 数据查询:区块和交易的查询
- 区块链交互(链码交互):发起交易,invoke,query
- 事件监听:业务事件,系统事件
JavaSDK的使用
maven
为什么使用maven
maven能解决哪些问题?
- 引入jar包
- 解决jar包之间的依赖关系
- 自动获取第三方jar包
- 将项目拆分成多个功能模块
maven简介
1.什么是构建?
- 从开发到运行的一个过程
2.构建的环节
- 清理:删除以前的编译结果,为重新编译做准备
- 编译:将java编译成.class
- 测试:对项目中关键点进行自动测试
- 报告:日志打印
- 打包:将java项目打包成.jar文件,加你个JavaWeb的项目打成.war包
- 安装:将打包结果(jar包或war包),安装到maven仓库
- 部署:将打包结果部署到远程仓库,或者将war部署到服务器上运行。
3.自动化构建
- maven进行自动化构建
maven安装
1.安装
解压到一个目录
配置环境变量,并加入PATH
打开cmd验证安装
maven仓库默认目录为
修改仓库路径,将settings.xml放到.m2下
修改settings.xml,指定仓库位置
Eclipse里配置maven
如下
去掉勾选
使用自己解压的maven
maven工程的创建
创建java工程
创建项目
创建简单工程
填写坐标,选择打包方式
创建web工程
maven仓库
1.仓库的分类
- 本地仓库
- 将maven所有jar存储到本地硬盘
- 远程仓库
- 中央仓库:为全世界所有maven工程提供服务的
- 中央仓库的镜像:亚洲镜像
- 私服:在公司内网自己人访问,
2.仓库中的文件
- 存储三类文件
- maven的插件
- 自己开发的项目模块
- 第三方框架或工具jar包
maven详解
1.maven报错
- 创建工程直接报错,插件下载不完整
2.约定的目录结构
- src/main/java 主程序源码目录
- src/main/resources 主程序配置文件目录
- test是测试的
- target编译结果的目录
3.POM文件
- Project Object Model:项目对象模型
- pom是maven的核心配置
maven父子工程
创建父工程
创建子工程
maven聚合工程
SDK的下载和编译
下载并解压
编译前,需要有JDK,maven,编译好仓库位置。
进入解压目录,cmd中输入 mvn install -DskipTests,跳过测试并编译
有报错的,先将pl.搜出来,注释掉。
编译完成,最后将jar包部署到了仓库的如下位置。
搭建网络&&部署链码
将编写好的工程传到linux
给脚本执行权限
启动网络
进入容器
查看通道
安装链码
实例化链码
将a设置为123
取出a
java外部服务调用
创建maven工程
工程根目录下创建一个cert目录,用于存放证书和私钥
将log4j.xml放到resources下
编写代码
- 首先定义一个实现了User接口的类
Hyperledger fabric开发入门