Chaincode 介绍
chaincode作用
Fabric的Chaincode是一段运行在容器中的程序。Chaincode是客户端程序和Fabric之间的桥梁。
通过Chaincode客户端程序可以发起交易,查询交易。
chaincode 运行环境
Chaincode是运行在Dokcer容器中,因此相对来说安全。
支持语言
目前支持 java,node,go,go是最稳定的。其他还在完善。
chaincode 运行和使用步骤
创建代码目录
mkdir -p {path}
存放编写好的chaincode源代码
部署chaincode
1
peer chaincode install -n {chaincodeId} -v {version} -p {path}
实例化chaincode
1
peer chaincode instantiate -o {order_address} -C {channel} -n {chaincodeId} -v {version} -c '{"Args": ["init", "a", "100", "b", "200"]}' -P "OR('Org1MSP.member', 'Org2MSP.member')"
调用chaincode
1
peer chaincode invoke -o {order_address} -C {chainnel} -n {chaincodeId} -v {version} -c '{"Args":["invoke", "1", "a", "b"]}'
Golang 版Chaincode 编写规范
Chaincode 代码结构
包名
一个chaincode通常是一个 Goalng源文件,包名必须是main —— package main
shim包
“github.com/hyperledger/fabric/core/shaincode/shim”
pb “github.com/hyperledger/fabric/protos/peer”
shim提供了Fabric系统的上下文环境,包含了Chaincode和Fabic交互的接口。
在Chaincode中,执行赋值,查询,等功能都是需要通过shim.
定义结构体
1 | type chainCodeExample struct {} |
chaincode必须定义一个结构体,结构体的名称可以是任意符合Golang命名规范的字符串,并且必须实现Init 和 Invoke 接口方法;
实现Init方法
1 | func (t *chainCodeExample) Init(stub shim.ChaincodeStubInterface) pb.Response { |
Init方法是系统初始化方法,当执行命令 peer chaincode instantiate 实例化chaincode的时候调用该方法;
实现Invoke方法
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
Invoke方法主要是写入数据等对链进行查询和插入修改等操作的主要方法;
shim包核心方法
Success
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
Success 方法负责将正确的消息返回给调用chaincode 的客户端
Error
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
Error方法将错误的信息返回给调用Chaincode的客户端。
LogLevel
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
LogLevel 方法负责修改Chaincode 中运行日志级别
Chaincode StubInterface 接口方法
shim包提供了一个接口 ChaincodeStubInte, 在Invoke方法和Init 方法中该接口作为参数传入方法中;
ChaincodeStubInte 主要方法
- GetFunctionAndParameters 获取调用链码的方法名和参数列表
- PutState 存储数据到账本中
- DelState 删除账本中的数据
- GetState 从账本中获取指定数据
- CreateCompositeKey 创建符合键
- GetStateByPartialCompositeKey 通过符合键取值
- SplitCompositeKey 拆分复合键
- GetStateByRange 查询指定key 指定范围的历史记录
- GetHistoryForKey 获取指定key的历史记录
- GetTxID 获取交易编号
- GetTxTimestamp 获取交易的时间
- GetCreator 获取交易的创建者
- InvokeChaincode 调用其他的链码
1、 PutState方法
将调用者的数据存储到Fabric链上
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
2、 GetState方法
将调用者的数据存储到Fabric链上
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
3、GetStateByRange方法
根据Key的范围来查询相关数据
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
4、GetHistoryForKey方法
查询某个键的历史记录
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
5、DelState 方法
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
6、CreateCompositeKey 方法
负责创建组合键
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
7、GetStateByPartialCompositeKey 和 SplitCompositeKey 方法
用来查询复合键的值
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
8、GetTxTimestamp方法
负责好偶去当前客户端发送交易的时间戳
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
9、InvokeChaincode方法
用来在chaincode中调用其他的chaincode链码
1 | func (t *chainCodeExample) Invoke (stub shim.ChaincodeStubInterface) pb.Response { |
Chaincode 操作命令
1 | Available Commands: |
Chaincode背书规则指定
背书介绍
Fabaric 中对数据参与方对数据的确认是真实通过Chaincode来进行的。
什么是背书呢?
背书就是仪表交易被确认的过程。大概意思就是交易你必须背会一本书才能操作。
背书策略被用来指示对相关的参与方如何对交易进行确认。当一个节点接收到一个交易请求的时候,会调用vscc系统(系统Chaincode,专门负责处理背书相关的操作)与交易的Chaincode共同来验证交易的合法性。在vscc和交易的 Chaincode共同对交易的确认中,通常会做一下的校验。
- 所有的背书是否有效
- 参与背书的数量是否满足要求
- 所有背书参与方是否满足要求
指定背书规则的方法
背书策略的设置是通过Chaincode部署时instantiate命令中的-p参数来设置的。
1 | peer chaincode instantiate -o {order_address} -C {channel} -n {chaincodeId} -v {version} -c '{"Args": ["init", "a", "100", "b", "200"]}' -P "OR('Org1MSP.member', 'Org2MSP.member')" |
这个参数包说明是当前Chaincode发起的交易,需要组织编号为 Org1MSP的组织编号为Org2MSP的组织中的任何一个用户共同参与交易的确认并且同意。这样交易才能生效并且记录到 区块链中。
通过上述背书策略的示例我们可以知道背书策略是通过一定的关键字和系统的属性组成的。
背书编写示例
逻辑与关系
1
AND('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')
逻辑或关系
1
OR('Org1MSP.member', 'Org2MSP.member', 'Org3MSP.member')
逻辑与或关系并存
1
OR('Org1MSP.member', AND('Org2MSP.member', 'Org3MSP.member'))