Hyperledger fabric智能合约编写(一)

简介: 本篇文章主要对链码编写的主要思路和部分API进行梳理。

1、fabric链码版本区别

Fabric链码分成了两个大版本,1.x和2.x版本,两者主要区别为:

1、导入包的不同

1.x导入的包为:


"[github.com/hyperledger/fabric/core/chaincode/shim](http://github.com/hyperledger/fabric/core/chaincode/shim)"

  pb "[github.com/hyperledger/fabric/protos/peer](http://github.com/hyperledger/fabric/protos/peer)"

2.0导入的包为:


"[github.com/hyperledger/fabric-contract-api-go/contractapi](http://github.com/hyperledger/fabric-contract-api-go/contractapi)"

2、方法结构不同

Fabric2.0链码中不需要invoke和init方法

3、方法中调用形式参数类型、返回值不同

1.x方法为:

createCar1(stub shim.ChaincodeStubInterface, args []string) pb.Response { }

2.x方法为:

Create(ctx contractapi.TransactionContextInterface,key string,value string)error { }

2、contractapi包简单分析

image.png

从官方的fabric-samples提供的各种简单的Go链码中可以看到,一般我们链码方法都是自定义一个SmartContract struct, 里面包含了comtractapi包中的Contract struct。Contract struct实现了ContractInterface 接口,自定义的结构体通过水平组合Contract可以快速帮助我自定义的结构体实现ContractInterface接口。

type SimpleChaincode struct {
    contractapi.Contract
}
type Contract struct {
    Name                      string
    Info                      metadata.InfoMetadata
    UnknownTransaction        interface{}
    BeforeTransaction         interface{}
    AfterTransaction          interface{}
    TransactionContextHandler SettableTransactionContextInterface
}

ContractInterface 定义了有效合约应具有的功能。链码中使用的合约必须实现此接口。因此应用链码会直接将contractapi.Contract嵌套在链码结构体中,以实现ContractInterface接口。

type ContractInterface interface {
    //获取当前描述智能合约的元数据
    GetInfo() metadata.InfoMetadata

    //在合约向链码转化的时候,获取合约中的未知的交易集合
    GetUnknownTransaction() interface{}

    //获取before transaction 集合
    GetBeforeTransaction() interface{}

    //获取after transaction 集合
    GetAfterTransaction() interface{}

    //GetName 返回合约的名称。当合约用于创建新链码时,该函数将被调用,返回的名称将用于在初始化/调用时识别链码中的合约。
    GetName() string

    //GetTransactionContextHandler返回约定函数使用的SettableTransactionContextInterface。
       //合约向链码转化时,将调用此函数并存储返回的事务上下文。
       //当通过init/Invoke调用链代码时,如果函数需要其参数列表中的上下文,则会创建存储类型的事务上下文,并将其作为参数发送给命名合约的函数(after,before和未知函数)。
       //如果采用事务上下文的函数采用接口作为上下文,则此函数返回的事务上下文必须满足该接口
    GetTransactionContextHandler() SettableTransactionContextInterface
}

除正常链码之外,contractapi包也提供了很多正常链码的扩展功能:

  • IgnoreContractInterface 扩展了ContractInterface, 并提供了其他功能,可用于标记哪些函数不应通过调用/查询链码来访问;

  • EvaluationContractInterface扩展了ContractInterface,标示这些function应该被query(查询)而不是被invoke(调用)

从上面图可以看出来我们定义的应用结构体,通过入参NewChaincode(contracts...ContractInterface)(*ContractChainCode,error)函数,可以转换为ContractChaincode结构体,NewChaincode基本逻辑就是该函数解析每个传递的函数,并存储链码要使用的组成细节,合约的公共函数存储在链代码中,并且可以调用。同时系统合约被添加到链码中,它提供了获取链码元数据的功能。生成的元数据是一个JSON格式的MetadataContractChaincode,包含每个合约的名称以及他们接受/返回的公共函数和类型的详细信息。它还概述了合同和链码的版本详细信息。

同时ContractChaincode实现了Chaincode接口,该接口是fabric每一个链码都必须实现的接口,里面提供了Invoke和Init方法,这就是fabric1.x链码的交互接口,fabric2.x链码实现就是对fabric1.x进行封装,便于开发人员链码编写。

3、shim包简单分析

3.1 shim包结构内容

在contractapi包中发现,contractapi包仅仅是为了方便交互,对shim进行了一个封装,调用的接口还是需要获取shim包中的ChaincodeStub

func (t *SimpleChaincode) InitLedger(ctx contractapi.TransactionContextInterface) error {
    key := "assetGlobal"
    exist, err := ctx.GetStub().GetState(key)

type TransactionContextInterface interface {
    // GetStub should provide a way to access the stub set by Init/Invoke
    GetStub() shim.ChaincodeStubInterface
    // GetClientIdentity should provide a way to access the client identity set by Init/Invoke
    GetClientIdentity() cid.ClientIdentity
}

// ChaincodeStub is an object passed to chaincode for shim side handling of
// APIs.
type ChaincodeStub struct {
    TxID                       string
    ChannelID                  string
    chaincodeEvent             *pb.ChaincodeEvent
    args                       [][]byte
    handler                    *Handler
    signedProposal             *pb.SignedProposal
    proposal                   *pb.Proposal
    validationParameterMetakey string

    // Additional fields extracted from the signedProposal
    creator   []byte
    transient map[string][]byte
    binding   []byte

    decorations map[string][]byte
}
`

shim里面的handler.go是链码服务和peer服务通信的功能代码,目前主要关注提供了哪些与账本交互的API接口,方便学习编写链码。从interface.go看出,链码的与账本交互API主要由ChaincodeStubInterface来提供,剩下的三个Iterator都是账本富查询的迭代器接口。

ChaincodeStubInterface由ChaincodeStub来实现,了解ChaincodeStub结构体的方法,我们基本上就掌握了fabric链码的编写方法了,官方API文档和fabric-sample中的链码示例中也可以学到。

2、API功能分类

链码最最最(重点说三遍)主要的功能就是对账本进行操作,加上一些msp身份认证等的附加功能,目的也是更安全的对账本进行操作。

辅助功能:例如参数获取,交易获取,网络信息获取等。

  • 参数获取:这类方法在链码2.x中已经不需要了,contractapi包中的NewChaincode方法已经帮我们把参数进行了填充,让我们可以和编写常规方法一样去编写链码方法。
    -- 获取信息类型的函数:GetTxID()、GetChannel()、GetCreator()、GetSignedProposal()、GetTxTimestamp()
  • 状态操作:对账本的K-V进行操作
    1.读写: PutState、DelState、GetStateByRange、GetStateByRangeWithPagination、GetHistoryForKey
    2.复合键:SplitCompositeKey、CreateCompositeKey、GetStateByPartialCompositeKey、GetStateByPartialCompositeKeyWithPagination
    3.对此Key的背书策略设置:SetStateValidationParameter、GetStateValidationParameter
  • 私有数据库操作:
    1.读写:GetPrivateData、GetPrivateDataHash(方便非私有成员对交易进行验证,仅可读取数据的Hash)、PutPrivateData、DelPrivateData、PurgePrivateData、GetPrivateDataByRange
    2.Key级别的背书策略设置:SetPrivateDataValidationParameter、GetPrivateDataValidationParameter
    3.复合键:GetPrivateDataByPartialCompositeKey
  • 富查询:GetQueryResult、GetPrivateDataQueryResult
  • 暂态数据:GetTransient(暂态数据主要是为了保护数据,字面意思,通过暂态数据传递进来的数据不会永久存储,会有专门的数据对其进行暂存,目前只能用于传递结构体数据)
  • 事件设置:SetEvent(主要绑定在专门的函数执行完后出发所设定的事件,一个方法中最多只能设置一个Event,如果设置两个Event,则首个Event会被第二个Event覆盖)
  • GetBinding:返回事务绑定,该绑定用于强制应用程序数据(如上文中的暂态字段中存储的数据)与提案本身之间的链接。有助于避免可能得重放攻击。
  • GetDecorations:返回关于源自对等方的提案的附加数据(如果适用)。这些数据是由对等端的装饰器设置的,这些装饰器附加或变异传递给链代码的链代码输入。

原文链接:
https://blog.csdn.net/weixin_43274469/article/details/129643800

相关文章
|
6月前
|
开发框架 .NET 区块链
Hyperledger fabric部署链码(五)初始化与链码升级
fabric部署chaincode-go(智能合约)系列之五
|
6月前
|
JavaScript 测试技术 Go
Hyperledger fabric部署链码(一)打包链码
fabric部署chaincode-go(智能合约)系列之一
|
6月前
|
测试技术 Go 区块链
Hyperledger fabric 测试环境部署
Hyperledger fabric 测试环境部署及相关问题解答
109 3
|
6月前
|
Go API 区块链
Hyperledger Fabric相关概念介绍
在学习Hyperledger Fabric的过程中,初步对相关概念的了解。
Hyperledger Fabric相关概念介绍
|
6月前
|
JSON 区块链 数据格式
Hyperledger fabric部署链码(四)提交链码定义到channel
fabric部署chaincode-go(智能合约)系列之四
|
6月前
|
测试技术 API 区块链
Hyperledger fabric部署链码(三)批准链码定义
fabric部署chaincode-go(智能合约)系列之三
|
6月前
|
区块链
Hyperledger fabric部署链码(二)安装链码到fabric
fabric部署chaincode-go(智能合约)系列之二
|
8月前
|
消息中间件 Java Kafka
Hyperledger Fabric 通道配置文件和容器环境变量详解
Fabric 节点的主配置路径为 FABRIC_CFG_PATH 环境变量所指向路径(默认为 /etc/hyperledger/fabric)。在不显式指定配置路径时,会尝试从主配置路径下查找相关的配置文件。
220 0
|
安全 区块链 数据库
联盟链 Hyperledger Fabric 应用场景
本文主要通过一个例子分享以Hyperledger Fabric为代表的联盟链应用场景。
648 0
联盟链 Hyperledger Fabric 应用场景
|
Java API 区块链
Hyperledger Fabric 2.x Java区块链应用
在上一篇文章中分享了智能合约的安装并使用cli客户端进行合约的调用;本文将使用Java代码基于fabric-gateway-java进行区块链网络的访问与交易,并集成SpringBoot框架。
742 0
Hyperledger Fabric 2.x Java区块链应用