Fabric链码开发
智能合约
随着区块链技术的应用和发展,区块链几大关键技术正在经历快速演进,如共识算法、智能合约、跨链事务、隐私保护等。
而和用户最相关的是能为用户带来价值的、跑在区块链之上的智能合约。
智能合约可以看做是一个跨学科的复合名词,合约取自法律上的合同概念,智能是指自动执行的计算机程序,
合在一起的智能合约就是像计算机程序一样自动执行的法律合同。
要实现智能合约,首先需要使用计算机语言编写合同中的条款,然后将编写的程序部署到区块链上去执行。
从计算机用户角度看,智能合约可以限定为更好理解的智能合约代码。
智能合约最早的形式是比特币中的扩展脚本,由于比特币设计之初没有考虑智能合约,因此这种扩展脚本受到诸多限制。
后来Ethereum平台设计了合约编程语言solidity,提供了执行合约的虚拟机,进一步提升了智能合约的表述能力。
而fabric的智能合约,直接采用Java、Go这种传统编程语言,功能和权限更加强大。
由于区块链智能合约在商业上应用面临法律效力问题,因此现有智能合约一般会在代码中存储一份相应的法律合同文本文件,
以应对法律风险。到今天,除了法律合同,智能合约已经应用到了更多的场景中,比如数字化交易所、供应链、物流等。
Fabric链码基础知识
Fabric的智能合约称为链码(chaincode),分为系统链码和用户链码。
系统链码用来实现系统层面的功能,包括系统的配置,用户链码的部署、升级、用户交易的签名和验证策略等。
用户链码用于实现用户的应用功能,开发者编写链码应用程序并将其部署在网络上。终端用户通过与网络节点交互的客户端应用程序调用链码。
链码被编译成一个独立的应用程序,运行于隔离的docker容器中,在链码部署的时候会自动生成合约的docker镜像。
链码和数据隔离
相较于以太坊,Fabric链码和底层账本是分开的,升级链码时并不需要迁移账本数据到新链码中,真正实现了逻辑和数据的分离。
链码支持采用Go、Java、Nodejs语言编写,对于大多数开发人员来说并不陌生,能快速上手。
链码和Peer节点的交互
Peer节点的主要功能是调用智能合约执行交易和记账。
1、Fabric链码通过grpc与peer节点交互,当peer节点收到客户端请求的输入(propsal)后,
会通过发送一个链码消息对象(带输入消息,调用者消息)给对应的链码。
2、链码调用ChaincodeBase里面的invoke方法,通过发送获取数据(getState)和写入数据(putState)消息,
向peer节点获取账本状态信息和发送预提交状态。
3、链码发送最终输出结果给peer节点,节点对输入(propsal)和输出(propsalreponse)进行背书签名,完成第一段签名提交。
之后客户端收集所有peer节点的第一段提交信息,组装事务(transaction)并签名,发送事务到orderer节点排队,最终orderer产生区块,
并发送给各个peer节点,把输入输出落到账本上,完成第二段提交过程。
链码开发基础
链码开发的基础,一句话总结起来就是:一个基类,两个查询,一个写入。
一个基类
Java中的ChaincodeBase是自定义链码的合约基类,里面的run方法是peer调用链码的入口函数,
其中必须自定义一个init方法,用于合约初始化及升级初始化动作。
Go由于其动态接口的特性,不需要特别声明实现合约接口。但是必须实现两个接口方法:
Init用于合约初始化及升级初始化动作。
Invoke是peer调用链码的入口函数。
ChaincodeStub里面包含丰富的账本操作,常用的有getCallerCertificate、getState、putState、invokeChaincode、rangeQueryState、getTxId等。
因为fabric默认的状态数据库是个k/v库,常用的方法就以下几个。
两个查询
是指getState和rangeQueryState两个查询函数。
getState获取单独的key对应的value值。
rangeQueryState(k1,k2)获取k1开始,k2结束的所有k/v对象,返回的是个Map<string, string>对象,其中k1、k2按字典序排序。
一个写入
putState写入数据,此处要注意下,putState并不会马上落到账本上,要等到第二阶段交易提交共识达成后,数据才会落地。
链码开发经验
以json方式存储业务实体并在key上建立索引
因为只有一个key-value状态数据库,value为json的数据可以快速解析,key上加一些字段简单索引字段的值,如Pk_TxId交易id_某字段值,来实现范围查询。
fabric的k-v数据库用的是leveldb,插入的key值用的字典序,所以索引字段值必须固定长度,否则调用stub.rangeQueryState进行范围查询,会取出一堆不正确的数据。
写入的数据不能立即获取到
通过putState写入的数据并不会立即落到账本上,要等到第二阶段交易所有peer节点达成共识后,数据才会落地。
因此不可以立即获取之前写入的值,比如批量插入数据,利用putState写入数据,再通过getState函数来判断主键是否重复。
链码里边的方法需要加锁吗
不需要。peer节点已经实现了消息队列,发给链码的链码消息都是顺序执行的,不是并行执行。
参考文档
链码(chaincode)开发精解,搭建属于自己的区块链!
http://rdcqii.hundsun.com/portal/article/694.html