zoukankan      html  css  js  c++  java
  • Hyberledger-Fabric 1.00 RPC学习(1)

    参考:http://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html

    本文的目的就是基于Hyperledger Fabric network学习第一个application,blockchain上的application最基本的作用就是查询以及更新账本。看完本文后,将会对application(使用Node.js的fabric SDK)如何与fabric Ledger进行交互的有一个初步了解。

    一.开始一个Test Network

    首页需要确保Hyberledger Fabric所需要的环境已经安装完成。(安装可以参考http://www.cnblogs.com/studyzy/p/6973334.html) 

    克隆一个fabric-samples仓库,然后进入fabcar子目录

    git clone https://github.com/hyperledger/fabric-samples.git
    cd fabric-samples/fabcar

    fabcar目录下包括用于运行样例app的脚本以及应用程序,输入ls,能看到如下文件或文件夹

    chaincode    invoke.js       network         package.json    query.js        startFabric.sh

    我们使用startFabric.sh启动网络,接下来的命令会下载与安装Fabric docker镜像

    ./startFabric.sh

    上述命令主要

    1.启动了一个peer节点、一个ordering节点、一个CA以及CLI容器

    2.创建了一个channel,同时把peer加入到channel中

    3.在peer的文件系统上安装并实例化了智能合约(chaincode),启动了一个chaincode容器

    4.调用了initLedger函数在channel Ledger上生成了10个car

    上述操作由一个组织(organization)或者节点(peer)admin实现。startFaric.sh脚本使用CLI执行上述命令,具体参考Hyperledger Fabric Node SDK repo 

    使用docker ps -a命令查看刚启动的容器。

    下图简要的说明了,application如何与fabric network进行交互的。

     

     

    application如何与network进行交互:application使用API去调用智能合约(chaincode),这些chaincode被托管在network中,同时chaincode的名称与版本是得到认证的。例如,chaincode容器 - dev-peer0.org1.example.com-fabcar-1.0 - ,其中名称是fabcar,版本是1.0,peer是dev-peer0.org1.example.com

    二.查询Ledger

    查询就是从Ledger上读取数据,可以通过单键值或者多键值查询。假如Ledger使用类似json的富数据存储方式,那么其支持复杂查询(例如模糊查询)。

     

    在fabcar目录下,我们可以使用query.js代码可以用于查询在Ledger上的car详情。

    接下来运行JavaScript程序query.js,将会返回在Ledger上的car列表

    node query.js

    返回值为

    Query result count =  1
    Response is  [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},
    {"Key":"CAR1",   "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},
    {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},
    {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},
    {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},
    {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},
    {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},
    {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},
    {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},
    {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]

    展示了10辆车,本例中,car1到car9是key值,record是value值。

    我们来看看query.js里面有哪些内容,通过vim打开query.js

    vim query.js

    发现初始化的参数options包括了chaincode ID,channel名称以及network端点

    var options = {
          wallet_path : path.join(__dirname, './network/creds'),
          user_id: 'PeerAdmin',
          channel_id: 'mychannel',
          chaincode_id: 'fabcar',
          network_url: 'grpc://localhost:7051',
    }

    以下是我们构建的查询块

    const request = {
       chaincodeId: options.chaincode_id,
       txId: transaction_id,
       fcn: 'queryAllCars',
       args: ['']
    }

    chaincode_id用于确定具体的chaincode,接下来调用在chaincode中定义的queryAllCars函数。

    在我们执行node query.js时,调用了queryAllCars函数用于查询Ledger。除了queryAllCars函数之外,还有initLedger, queryCar, queryAllCars, createCar 以及 changeCarOwner函数可以调用。

    接下来,我们打开fabcar.go,看看queryAllCars函数是如何实现查询所有car的。

    func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {
         startKey := "CAR0"
         endKey := "CAR999"
         resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
    }

    该函数使用的fabric shim接口GetStateByRange,用于返回startKey与endKey之间的Ledger数据。这些定义分别被定义为CAR0以及CAR999,因此理论上我们可以创建1000辆车,一个queryAllCars函数即可查询所有车辆信息。

    下图表示一个app是如何调用不同的chaincode的函数。

     

    其中createCar用于更新Ledger,同时最终增加了一个新的block到链上。

    回到查询功能上,让我们回到query.js程序,同时我们将代码中的queryAllCars改成queryCar,同时对key值进行修改,这里key值暂时使用CAR4,query.js将会包括如下代码:

    const request = {
          chaincodeId: options.chaincode_id,
          txId: transaction_id,
          fcn: 'queryCar',
          args: ['CAR4']
    }

    输入node query.js后将会查出如下结果:

    {"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}

    本次查询只查询一辆车,调用了queryCar函数,通过key值去查询。

    三.更新Ledger

    上面我们调用chaincode的查询函数对车辆信息进行了查询,接下来,我们需要尝试对Ledger进行修改。

    首先application先生成一个transaction proposal。就想query的request的一样,这里也需要生成一个request。程序接下来调用channel.SendTransactionProposal API 把transaction proposal发送到endoring peer。

    接着,network(也就是endorsing peer)会返回一个proposal response,application通过这个response对transaction request进行build与sign。然后把这个处理过的request通过channel.sendTransaction API发送至ordering serivce。ordering service将会把transaction打包至到block,接着把block发送到channel中的所有peer做验证。 

    最后,application使用eh.setPeerAddr API  连接到peer的事件监听端口,同时调用eh.registerTxEvent方法并使用具体的transactionID注册事件。该API使得application能够追踪到transaction的具体情况(提交成功还是失败)。其实就是一个通知机制。 

    通过执行invoke.js我们创建了一个新的asset(一辆车)。打开invoke.js,我们能够找到类似query.js中的request。

    vim invoke.js

    能够看到request内容

    // createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'],
    // changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'],
    // send proposal to endorser
    var request = {
        targets: targets,
        chaincodeId: options.chaincode_id,
        fcn: '',
        args: [''],
        chainId: options.channel_id,
        txId: tx_id
    }

    接下来,我们将调用createCar 或 changeCarOwner生成一个新的车。参数如下所示

    var request = {
        targets: targets,
        chaincodeId: options.chaincode_id,
        fcn: 'createCar',
        args: ['CAR11’, ‘Audi’, ‘A4’, ‘Black’, ‘Xiaohu Li’],
        chainId: options.channel_id,
        txId: tx_id
    }

    输入node invoke.js能够看到

     

    peer发出了该事件通知,我们的application通过eh.registerTxEvent API收到了该通知。接下来,我们回到query.js,修改查询key值为CAR11,然后执行代码。

    node query.js

    接下来我们能够看到如下信息:

     

    说明我们刚创建的车辆信息已经写入Ledger中了。

  • 相关阅读:
    CentOS 7.3报Centos7_Base库缺少GPG公钥
    nginx重写(隐藏)index.php目录
    工作经历简写
    Centos7.4安装htop
    nginx 超时时间配置说明
    c#中数据从数据库到客户端主要几种的导出方式(导出到excel,导出到word)
    C#操作word文档如何设置表格的行高
    Windows计划任务定时启动程序运行时发生错误的解决办法
    Asp.Net MVC中请求json文件时返回404 not found的解决办法
    Angularjs 如何自定义Img的ng-load 事件
  • 原文地址:https://www.cnblogs.com/zeyaries/p/7096726.html
Copyright © 2011-2022 走看看