数字货币曾是区块链技术的唯一应用场景
对智能合约的支持突破了场景限制, 丰富了区块链应用的适用范围, 可以支持多行业、大规模的商业应用
区块链应用: 一般由若干部署在区块链网络中的智能合约, 以及调用这些智能合约的应用程序组成
用户专注于与业务本身相关的应用程序
智能合约则封装了与区块链账本直接交互的相关过程, 被应用程序调用
智能合约本质上是为了对上层业务逻辑进行支持且直接与账本结构打交道, 处于核心位置.
所以设计得当可以简化上层应用开发的过程
应用程序通过调用智能合约提供的方法接口实现业务逻辑, 可以使用JavaScript、Python、Go、Java等主流语言进行开发
链码延伸自智能合约的概念, 支持使用主流高级编程语言实现
区块链网络中的成员商定业务逻辑后, 可将业务逻辑编程到链码中, 所有人遵守合约执行
链码会创建一些状态(state)并写入账本中。状态带有绑定到链码的命名空间,仅限于创建他的链码使用,不能被其他链码直接访问。不过,在合适的范围内,一个链码也可以调用另一个链码,间接访问其状态
链码在Fabric节点上的隔离沙盒(目前为Docker容器)中运行, 并通过gRPC协议与节点进行交互
Fabric中支持多种语言实现链码,包括Golang、JavaScript、Java等
链码实现需要引入如下依赖包
“github.com/hyperledger/fabric/core/chaincode/shim”
“github.com/hyperledger/fabric/protos/peer”
每个链码都需要实现chaincode接口:
type Chaincode interface{ Init(stub ChaincodeStubInterface) peer.Response Invoke(stub ChaincodeStubInterface) peer.Response }
编写链码, 关键是实现Init与Invoke两个方法
Init方法在链码部署或升级时被调用, 完成初始化工作
对数据进行操作时, Invoke方法被调用, 因此响应调用或查询的业务逻辑都需要在此方法中实现
一个链码的必要结构如下
package main
//引入必要的包
import(
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
//声明一个结构体
type SimpleChaincode struct {
}
//为结构体添加Init方法
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
//在该方法中实现链码初始化或升级时的处理逻辑
//编写时可灵活使用stub中的API
}
//为结构体添加Invoke方法
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{
//在该方法中实现链码运行中被调用或查询时的处理逻辑
//编写时可灵活使用stub中的API
}
//主函数,需要调用shim.Start( )方法
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
链码需要将数据记录在分布式账本中.需要记录的数据称为状态, 以K-V对的形式存储
账本状态交互API可以对账本状态进行操作
GetState(key string) ([]byte, error) 通过Key来返回数组的特定值
PutState(key string, value []byte) error 账本中写入特定的键和值
DelState(key string) error 从账本中移除指定的键和值
GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) 根据指定的范围内的健值
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error) 返回指定健的所有历史值
GetQueryResult(query string) (StateQueryIteratorInterface, error) 对(支持富查询功能的)状态数据库进行富查询
GetTxID() string 返回交易提案中指定的交易ID
GetTxTimestamp() (*timestamp.Timestamp, error) 返回交易创建的时间戳,这个时间戳是peer收到交易的当前时间
GetBinding() ([]byte, error) 返回交易的binding信息
GetSignedProposal() (*pb.SignedProposal, error) 返回与交易提案相关的所有数据
GetCreator() ([]byte, error) 返回该交易的提交者的身份信息
GetTransient() (map[string][]byte, error) 返回交易中不会被写至账本中的一些临时信息
GetArgs() [][]byte 返回调用链码时交易提案中指定的参数
GetArgsSlice() ([]byte, error) 返回调用链码时交易提案中指定的参数
GetFunctionAndParameters() (function string, params []string) 返回调用链码时交易提案中指定的被调用的函数名称及其参数
GetStringArgs() []string 返回调用链码时指定的参数
-c ‘{“Args”:[“fn”, “param1”, “param2”, “paramN”]}’