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、方法结构不同

Fabric 2.0链码不需要 Invoke 和Init 方法。

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

1.x方法为:

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

2.0方法为:

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

freerent链码还没开始编写,该篇文章主要对链码编写的主要思路和部分API进行进行梳理。

2. contractapi包简单分析

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

type SmartContract 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() string

//GetTransactionContextHandler返回约定函数使用的SettableTransactionContextInterface。

// 合约向链码转化时,将调用此函数并存储返回的事务上下文。

// 当通过Init/Invoke调用链代码时,如果函数需要其参数列表中的上下文,

// 则会创建存储类型的事务上下文,并将其作为参数发送给命名合约函数(以及之前/之后和未知函数)。

// 如果采用事务上下文的函数采用接口作为上下文,则此函数返回的事务上下文必须满足该接口

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进行封装,便于开发人员的链码编写。

2. shim包简单分析

2.1 shim包结构内容

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

//ctx contractapi.TransactionContextInterface

ctx.GetStub().PutState(id, assetJSON)

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接口,方便编写链码。从interfaces.go看出,链码的与账本交互API主要有ChaincodeStubInterface来提供,剩下的三个Iterator都是账本富查询的迭代器接口。

ChaincodeStubInterface由ChaincodeStub来实现,了解ChaincodeStub结构体的方法,我们基本上就掌握了fabric链码编写的方法了,其实直接看官方API文档也一样可以学习到。

2.2 API功能分类

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

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

参数获取:这类方法在链码2.X中已经不需要了,contractapi包中的NewChaincode函数已经帮我们把参数进行了填充,让我们可以和编写其他方法一样去编写链码方法。获取信息类型的函数:GetTxID()、GetChannelID()、GetCreator() 、GetSignedProposal()、GetTxTimestamp() 状态操作:对账本的k-v进行操作,

读写:PutState、DelState、GetStateByRange、GetStateByRangeWithPagination、GetHistoryForKey复合键:SplitCompositeKey、CreateCompositeKey、GetStateByPartialCompositeKey、GetStateByPartialCompositeKeyWithPagination对此Key的背书策略设置:SetStateValidationParameter、GetStateValidationParameter 私有数据库操作:

读写:GetPrivateData、GetPrivateDataHash(方便非私有成员对交易进行验证,仅可读取数据的Hash)、PutPrivateData、DelPrivateData、PurgePrivateData、 GetPrivateDataByRangekey级别的背书策略设置:SetPrivateDataValidationParameter、GetPrivateDataValidationParameter复合键:GetPrivateDataByPartialCompositeKey 富查询:GetQueryResult、GetPrivateDataQueryResult暂态数据:GetTransient(暂态数据主要为了保护数据,字面理解通过暂态数据传递进来的数据不会永久存储,会有专门的数据对他进行暂存,目前只是用来传递结构体数据。 )事件设置:SetEvent(主要绑定在专门的函数执行完后触发所设定的事件**,一个方法中最多只能设置一个Event**,不然第一个会被第二个给覆盖。)GetBinding(没用过):返回事务绑定,该绑定用于强制应用程序数据(如上面瞬态字段中存储的数据)与提案本身之间的链接。这有助于避免可能的重放攻击。GetDecorations(没用过):返回关于源自对等方的提案的附加数据(如果适用)。这些数据是由对等端的装饰器设置的,这些装饰器附加或变异传递给链代码的链代码输入。

推荐阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: