温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

hyperledger fabric客户端相关的开发有哪些

发布时间:2021-12-06 14:37:37 来源:亿速云 阅读:177 作者:小新 栏目:互联网科技

这篇文章将为大家详细讲解有关hyperledger fabric客户端相关的开发有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

hyperledger 的客户端开发, 实际上指的是Chaincode的客户端开发。

同传统的互联网开发一样, 可以理解为hyperledger fabric是C/S架构, 当然这样的类比不是很严谨。那么, 以前的服务端API在hyperledger fabric中相当于Chaincode开发, 以前的容器或者其他类似与Tomcat, Nginx 的服务器相当于 hyperledger 中的 Blockchain 本身, 当然在Blockchain中, 数据存储也在Blockchain上, 所以Blochchain也是新的存储平台, 而传统的客户端开发, 其实就是通过SDK或者Restful APIs 和服务端进行交互, 在hyperledger中, 同样可以使用SDK 或者 Restful APIs 来和服务端进行交互, 只是, 这个交互不仅仅适合自己定义的Chaincode中的业务逻辑来进行交互, 也和Chaincode本身进行交互, 在hyperledger中, 例如客户端application 通过SDK连接访问 peer, channel, orderer , Block, Transaction等。

总的来说, Hyperledger Fabric 客户端开发主要包括通过Chaincode定义业务逻辑, 来改变Blockchain的状态, 通过SDK来和Blockchain进行通讯。

SDK版本

Hyperledger Fabric 提供了多种语言的SDK版本, 目前主要包括:

官方支持的版本:

  • Hyperledger Fabric Node SDK

  • Hyperledger Fabric Java SDK

非官方的版本:

  • Hyperledger Fabric Python SDK

  • Hyperledger Fabric GO SDK

  • Hyperledger Fabric REST SDK

其中, 以 Hyperledger Fabric Node SDK的文档最为详细, 这里以Node SDK 为例来说明Hyperledger Fabric客户端开发。

API作用

在 Hyperledger Fabric 的SDK中, 提供的API的作用主要有:

  • 创建通道 (create channel)

  • 请求节点加入通道 (join channel)

  • 在节点中安装链码 (install chaincode)

  • 通过调用链码来调用事物 (invoke chaincode)

  • 查询事物或者区块的账本 (query chaincode)

在 交易流程 中提供了一个应用程序(SDK), peer 和 orderer 共同处理事物并产生区块的流程。Fabric的安全是通过数字签名来实现的, 在Fabric中所有的请求都必须具有有效注册证书的用户签名。对于在Fabric中被认为有效的证书, 必须具有受信任的证书颁发机构签名。Fabirc支持CA的所有标准, Fabric 同时提供了一个可选的CA实现。

Node SDK 模块

Node SDK由3个顶级模块组成:

  • api : 可插拔式的API, 可自由定制, SDK提供默认实现

  • fabric-client :提供API用来同Hyperledger Fabirc的区块链网络进行交互, 具体就是同peer, orderer 和事件流交互。

  • fabric-ca-client:该API用来同fabirc提供的可选的CA实现Hyperledger Fabric CA交互, 该CA提供成员管理服务。

Node SDK 功能

fabric-client:

  • 创建一个新的通道(create channel)

  • 将通道信息发送给节点用于节点加入 (join channel)

  • 在节点上安装链码 (install chaincode)

  • 在通道中进行链码实例化 (instantiate chaincode)

  • 提交交易, 包括 :提案和交易 (invoke)

  • 查询链码的最新状态 (query)

  • 多种查询功能

  1. 查询通道长度

  2. 通过区块高度查询, 通过区块hash查询区块

  3. 查询一个节点所在的所有通道

  4. 查询节点中安装的所有链码

  5. 查询通道中的所有实例化链码

  6. 通过tansaction ID查询交易

  7. 查询通道的配置数据

  • 监控事件

连接一个节点的事件流

监控一个区块事件

监控交易事件和结果

坚挺链码自定义事件

  • 序列化用户对象和签名功能

  • 多层覆盖式的风层配置设置

  • 日志定义

  • 可插拔式的CryptoSuite

  • 可插拔式的状态存储

  • 自定义的密钥存储

  • 支持TLS和非TLS连接到peer 和orderer

fabric-ca-client:

  • 注册新用户 (register)

  • 登记用户同时获取有Fabric CA签署的注册证书(enroll)

  • 通过注册ID废除已有用户或废除特定证书 (revoke)

  • 自定义的持久化存储

实例

下面通过一个实例来说明Hyperledger Fabric客户端开发。一下是一段Chaincode, 定义了业务逻辑。

【有点类似传统的管理系统开发, chaincode实现CURD的功能, 通过SDK与fabric 交互, 来达到Blockchain状态的改变, 只是, chaincode支持byte和json数据,并且是以KV的形式存储】

/*
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
*/

'use strict';
const shim = require('fabric-shim');
const util = require('util');

let Chaincode = class {

  // The Init method is called when the Smart Contract 'fabcar' is instantiated by the blockchain network
  // Best practice is to have any Ledger initialization in separate function -- see initLedger()
  async Init(stub) {
    console.info('=========== Instantiated fabcar chaincode ===========');
    return shim.success();
  }

  // The Invoke method is called as a result of an application request to run the Smart Contract
  // 'fabcar'. The calling application program has also specified the particular smart contract
  // function to be called, with arguments
  async Invoke(stub) {
    let ret = stub.getFunctionAndParameters();
    console.info(ret);

    let method = this[ret.fcn];
    if (!method) {
      console.error('no function of name:' + ret.fcn + ' found');
      throw new Error('Received unknown function ' + ret.fcn + ' invocation');
    }
    try {
      let payload = await method(stub, ret.params);
      return shim.success(payload);
    } catch (err) {
      console.log(err);
      return shim.error(err);
    }
  }

  async queryCar(stub, args) {
    if (args.length != 1) {
      throw new Error('Incorrect number of arguments. Expecting CarNumber ex: CAR01');
    }
    let carNumber = args[0];

    let carAsBytes = await stub.getState(carNumber); //get the car from chaincode state
    if (!carAsBytes || carAsBytes.toString().length <= 0) {
      throw new Error(carNumber + ' does not exist: ');
    }
    console.log(carAsBytes.toString());
    return carAsBytes;
  }

  async initLedger(stub, args) {
    console.info('============= START : Initialize Ledger ===========');
    let cars = [];
    cars.push({
      make: 'Toyota',
      model: 'Prius',
      color: 'blue',
      owner: 'Tomoko'
    });
    cars.push({
      make: 'Ford',
      model: 'Mustang',
      color: 'red',
      owner: 'Brad'
    });
    cars.push({
      make: 'Hyundai',
      model: 'Tucson',
      color: 'green',
      owner: 'Jin Soo'
    });
    cars.push({
      make: 'Volkswagen',
      model: 'Passat',
      color: 'yellow',
      owner: 'Max'
    });
    cars.push({
      make: 'Tesla',
      model: 'S',
      color: 'black',
      owner: 'Adriana'
    });
    cars.push({
      make: 'Peugeot',
      model: '205',
      color: 'purple',
      owner: 'Michel'
    });
    cars.push({
      make: 'Chery',
      model: 'S22L',
      color: 'white',
      owner: 'Aarav'
    });
    cars.push({
      make: 'Fiat',
      model: 'Punto',
      color: 'violet',
      owner: 'Pari'
    });
    cars.push({
      make: 'Tata',
      model: 'Nano',
      color: 'indigo',
      owner: 'Valeria'
    });
    cars.push({
      make: 'Holden',
      model: 'Barina',
      color: 'brown',
      owner: 'Shotaro'
    });

    for (let i = 0; i < cars.length; i++) {
      cars[i].docType = 'car';
      await stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i])));
      console.info('Added <--> ', cars[i]);
    }
    console.info('============= END : Initialize Ledger ===========');
  }

  async createCar(stub, args) {
    console.info('============= START : Create Car ===========');
    if (args.length != 5) {
      throw new Error('Incorrect number of arguments. Expecting 5');
    }

    var car = {
      docType: 'car',
      make: args[1],
      model: args[2],
      color: args[3],
      owner: args[4]
    };

    await stub.putState(args[0], Buffer.from(JSON.stringify(car)));
    console.info('============= END : Create Car ===========');
  }

  async queryAllCars(stub, args) {

    let startKey = 'CAR0';
    let endKey = 'CAR999';

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

    let allResults = [];
    while (true) {
      let res = await iterator.next();

      if (res.value && res.value.value.toString()) {
        let jsonRes = {};
        console.log(res.value.value.toString('utf8'));

        jsonRes.Key = res.value.key;
        try {
          jsonRes.Record = JSON.parse(res.value.value.toString('utf8'));
        } catch (err) {
          console.log(err);
          jsonRes.Record = res.value.value.toString('utf8');
        }
        allResults.push(jsonRes);
      }
      if (res.done) {
        console.log('end of data');
        await iterator.close();
        console.info(allResults);
        return Buffer.from(JSON.stringify(allResults));
      }
    }
  }

  async changeCarOwner(stub, args) {
    console.info('============= START : changeCarOwner ===========');
    if (args.length != 2) {
      throw new Error('Incorrect number of arguments. Expecting 2');
    }

    let carAsBytes = await stub.getState(args[0]);
    let car = JSON.parse(carAsBytes);
    car.owner = args[1];

    await stub.putState(args[0], Buffer.from(JSON.stringify(car)));
    console.info('============= END : changeCarOwner ===========');
  }
};

shim.start(new Chaincode());

关于“hyperledger fabric客户端相关的开发有哪些”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI