Hyperledger Fabric学习笔记——应用程序与区块链网络交互

1、运行网络

以javascript为例运行FabCar智能合约和应用程序,同时还提供了go、java和typescript版本的例子,只需要修改下面命令中的javascript为go等即可。由于直接执行下面命令可能在中间过程出现问题,故采用之前手动搭建的方式运行示例网络。运行成功后,网络中将会有两个对等节点和一个排序服务,此网络使用CA,并且已经将javascript版本的fabcar智能合约部署到通道mychannel,并调用智能合约将初始数据存入账本中。

2、安装应用程序

进入fabcar下的javascript目录,并安装应用程序依赖。

cd fabcar/javascript
npm install

该命令将会安装定义在package.json中的关键应用程序依赖,最重要的是fabric-network类;它使得一个应用程序能够使用身份,钱包和网关连接到通道,提交transaction并等待响应。此教程将使用fabric-ca-client类通过他们各自的CA来注册用户,形成有效的身份接下来在fabric-network类方法中使用。

3、注册管理员用户

当我们创建好网络时,一个被叫做admin的作为CA的registrar被创建。我们的第一步是使用enroll.js为admin形成私钥、公钥和X.509证书。这一过程使用CSR(证书签名请求)——私钥和公钥首先在本地形成,然后发送到CA,然后CA返回一个加密的证书提供给应用程序使用。这些资格材料接下来会存储在钱包中,使我们能够充当CA的管理员。

node enrollAdmin.js

这个命令将CA管理员的身份信息保存在wallet目录下。

4、登记并注册一个应用程序用户

admin通常用于和CA协同工作,现在,我们在wallet中有了管理员的身份材料,我们可以创建一个新的应用程序用户来连接到区块链网络。通过下面的命令来登记并注册一个叫做appUser的新的用户:

node registerUser.js

和admin注册相似,这个程序也使用CSR来注册appUser并将其身份资料和admin并列存在wallet中。

5、查询账本

首先,运行query.js程序来返回账本上所有汽车的列表,这个程序使用第二个身份——appUser来连接到账本。

node query.js

用编译器打开query.js来看看query.js程序是如何使用Fabric Node SDK提供的APIs来连接到Fabric网络的。首先应用程序将两个关键的类从fabric-network模块加入范围:Wallets和Gateway。这两个类将用来定位appUser在wallet中的身份并使用身份连接到网络。

const {Gateway, Wallets} = require('fabric-network');

首先,程序使用Wallet类来从文件系统中获得应用程序用户:

const identity = await wallet.get('appUser');

一旦程序获得了身份,它将使用Gateway类来连接到网络:

const gateway = new Gateway();

await gateway.connect(ccpPath,{wallet,identity:'appUser',discovery:{enabled:true,asLocalhost:true}});

ccpPath描述了应用程序连接到网络所使用的连接文件的路径。这里有一个问题,在我开始跟着官方文档进行操作的时候,fabric还是v2.0beta版本,在该版本中此处的一些代码存在问题,并不能够成功执行,后来更新到v2.1版本,此处代码进行了不少修改,而且也印证了之前在更新到2.x版本的说法,将用test-network逐步替代first-network,之前的beta版本处在变革之初,仍然用的是first-network,因此这里方便起见,将代码进行更新,但是连接文件的路径仍然使用first-network那个。同样有改变的还有上面在注册应用程序用户时,beta中注册名为user1,现在为appUser,稍作注意即可。

const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json');

一个网络可以划分为多个通道,下面的代码将应用程序连接到一个特定的,我们智能合约部署的通道mychannel:

const network = await gateway.getNetwork('mychannel');

在这个通道内,我们可以通过FabCar智能合约连接到账本:

const contract = network.getContract('fabcar');

在FabCar中有许多不同的transactions,我们的应用程序起初使用queryAllCars transaction来访问账本的world state数据:

const result = await contract.evaluateTransaction('queryAllCars');

evaluateTransaction是最简单和区块链网络中智能合约交互的方法之一。它简单的选择一个定义在连接文件中的对等节点并发送请求并接受评判。对应的智能合约查询对等节点上账本副本中所有的车并将结果返回应用程序。此次交互并没有导致账本的更新。

6、FabCar智能合约

打开fabric-samples/chaincode/fabcar/javascript/lib目录下的fabcar.js文件来探究一下fabcar智能合约的内容。

首先,我们的智能合约fabcar是通过Contract进行定义的:

class FabCar extends Contract {...

在该类的结构体中,定义了如下一些transactions:initLedger,queryCar,queryAllCars,createCar和changeCarOwner。

让我们通过queryAllCars transaction来看看是如何和账本进行交互的:

async queryAllCars(ctx){

    const startKey = 'CAR0';

    const endKey = 'CAR999';

    const iterator = await ctx.stub.getStateByRange(startKey,endKey);

上面的代码定义了queryAllCars将从账本取回的车信息的范围,余下的代码将查询的结果打包为JSON格式返回应用程序。

应用程序调用一个智能合约中不同的transaction,transaction通过一系列APIs(例如getStateByRange等)来和账本交互。这样,如果要查询CAR4的信息,则可以修改query.js中的部分代码如下;

const result  = await contract.evaluateTransaction('queryCar','CAR4');

保存并重新执行node query.js即可。

7、更新账本

打开invoke.js程序可以看到如下代码:

await contract.submitTransaction('createCar','CAR12','Honda','Accord','Black','Tom');

node invoke.js运行程序。注意到invoke应用程序和区块链网络交互用的是submitTransactionAPI而不是evaluateTransaction,submitTransaction相对更加复杂。与单个对等节点交互相比,SDK将会发送submitTransaction请求给每一个区块链网络中需要的组织的节点。这些节点中的每一个都会通过这个proposal执行请求的智能合约来形成由该节点签名的transaction response并返回SDK。SDK收集所有签名的transaction response到一个transaction中,然后发送到orderer。orderer收集并排序来自所有应用程序的transactions并打包成块。然后将这些块分发到网络中的每一个节点上,进行验证和提交。最终SDK被通知,将控制权交给应用程序。submitTransaction为应用程序完成了以上所有的任务。

Note:submitTransaction包括了一个确认transaction是否被认可并提交到账本的监听。应用程序需要要么利用一个提交的监听,或者通过像submitTransaction这样的API来进行监听。否则将无法知道transaction是否成功被排序验证并提交到账本。

通过标题6中的queryCar即可验证已经将CAR12相关信息加入到账本中了。

接下来对invoke.js程序进行修改,将CAR12赠送给Dave:

await contract.submitTransaction('changeCarOwner','CAR12','Dave');

保存并执行,并通过query.js查看执行结果。

8、总结

通过以上对于账本的一些查询和更新操作,对应用程序连接到区块链网络有了一个基本的认识,应用程序通过一些API使用智能合约中某一transaction,transaction再通过一系列API与账本进行交互,SDK则用于收集来自对等节点的响应以及提交到账本成功后的响应,并将控制权返还应用程序,起到一个协调作用。

猜你喜欢

转载自blog.csdn.net/Nemoosi/article/details/105040757