Hyperledger Fabric开发实战

Hyperledger Fabric开发实战-06使用SDK

2018-11-29  本文已影响0人  史圣杰

本文是在阅读《区块链开发实战-Hyperledger Fabric关键技术与案例分析》一书的同时,在实践中记录的一些实践步骤与经验分享。

Hyperledger Fabric开发实战-07 开发流程

Fabric的Orderer节点和Peer节点都提供了基于Grpc协议的接口,通过这些接口可以和这些节点进行交互,但是如果直接使用这些接口,需要自己定义很多protobuf协议的文件,为了简化开发,Fabric提供了Node.js,Go,Java等语言的相关SDK,方便用户与相关节点进行交互。在项目的开发中,我们大都通过调用Peer模块的Grpc接口,与系统进行交互。

Fabric Node.js SDK是目前相对比较完善且成熟的SDK,因此以Node.js为例进行学## 习。

环境准备

由于需要使用到Node.js,需要先安装,由于我的8.11.1版本在安装依赖时一直报错,之后重新安装了8.9.3版本,才能正常使用

wget https://nodejs.org/dist/v8.9.3/node-v8.9.3-linux-x64.tar.xz
tar -xvf node-v8.9.3-linux-x64.tar.xz
sudo mv node-v8.9.3-linux-x64 /usr/local
sudo ln -s /usr/local/node-v8.9.3-linux-x64/bin/node /usr/local/bin/node 
sudo ln -s /usr/local/node-v8.9.3-linux-x64/bin/npm /usr/local/bin/npm 

验证版本

node -v
npm -v

编写Node.js时,为了调试方便,推荐使用Visual Studio Code

编写程序

1.安装依赖

首先创建一个目录sdkstudy,用来存放需要源代码,之后在里面创建package.json文件,

{
    "name": "fabric-sdk-node-study",
    "version": "0.0.1",
    "description": "fabric-sdk-node-study",
    "main": "main.js",
    "keywords": [],
    "engines": {
        "node": ">=8.0.0",
        "npm": ">=3.10.10"
    },
    "dependencies": {
        "fabric-ca-client": "^1.0.0",
        "fabric-client": "^1.0.0"
    },
    "license": "Apache-2.0"
}

dependencies里面是我们需要使用到的sdk,在sdkstudy中输入npm install命令安装。如果出现错误,请尝试使用sudo npm install --unsafe-perm

2.编写代码

在使用sdk时,我们首先要创建client对象,并指定Orderer,Peer和Channel,之后通过本地证书或caserver获取证书,最后再与Peer进行交互。

// import 
var co = require("co")
var path = require("path")
var fs = require("fs")
var util = require("util")
var hfclient = require("fabric-client")
var Peer = require("fabric-client/lib/Peer.js");
var EventHub = require("fabric-client/lib/ChannelEventHub");
var User = require("fabric-client/lib/User.js");
var crypto = require("crypto")
var FabricCAService = require("fabric-ca-client")

// 证书文件的缓存目录
var tempdir = "/home/shisj/mycode/github_wksp/fabric/nodejs-client/client-study/kvs";

// fabric client agent
var client = new hfclient();
var cryptoSuite = hfclient.newCryptoSuite()
cryptoSuite.setCryptoKeyStore(hfclient.newCryptoKeyStore({path:tempdir}))
client.setCryptoSuite(cryptoSuite);
const ORDERER_IP = "xxx.xx.xxx.xxx";
const PEER_IP = "xx.xxx.xx.xxx";
// 创建CA客户端 
var channel = client.newChannel("cmbcchannel666");
var order = client.newOrderer("grpc://" + ORDERER_IP + ":7050");
channel.addOrderer(order);

var peer = client.newPeer("grpc://"+PEER_IP+":7051");
channel.addPeer(peer);

使用本地证书

使用本地证书的时候,首先需要获取Org1组织的Admin的证书和私钥,再创建用户


function readAllFiles(dirPath){
    var files = fs.readdirSync(dirPath);  
    var data = fs.readFileSync(path.join(dirPath,files[0]), 'utf8');
    return data;
}

/**
 * 根据cryptogen模块生成的帐号通过Fabric接口进行相关的操作
 */
function getOrgUser4Local(){
    var keyPath = "/home/shisj/mycode/github_wksp/fabric/nodejs-client/client-study/fabric-config/msp/keystore";
    var keyPEM = Buffer.from(readAllFiles(keyPath)).toString()
    var certPath = "/home/shisj/mycode/github_wksp/fabric/nodejs-client/client-study/fabric-config/msp/signcerts";
    var certPEM = readAllFiles(certPath).toString()

    return hfclient.newDefaultKeyValueStore({path:tempdir})
    .then((store) =>{
        client.setStateStore(store);
        return client.createUser({
            username:"user87",
            mspid:"Org1MSP",
            cryptoContent:{
                privateKeyPEM:keyPEM,
                signedCertPEM:certPEM
            }
        })
    })
    
}

最后,就可以连接到Peer查看账本的相关信息了


co((function *(){
    let member = yield getOrgUser4Local()
    let resultPeerInfo = yield channel.queryInfo(peer)
    console.info("============当前peer加入的某个channel的区块数============");
    console.info(JSON.stringify(resultPeerInfo))

    console.info("============当前peer加入了那些channel============");
    var result = yield client.queryChannels(peer)
    console.info(JSON.stringify(result))

    //console.info("============当前peer加入的某个channel的区块数的区块号============");
    //result = yield client.queryChannels(2,peer,null)
    //console.info(JSON.stringify(result))

    console.info("============当前peer加入chaincode[install]的信息============");
    result = yield client.queryInstalledChaincodes(peer)
    var chaincodes = result.chaincodes;
    chaincodes.forEach(element => {
        console.info("chaincode name is %s, version is %s ",element.name,element.version);
    });
    // console.info(JSON.stringify(result))
})())

与Peer通信时,还可以调用Chaincode

   let tx_id = client.newTransactionID();
   var request = {
       targets: peer,
       chaincodeId:"statechaincode",
       fcn:"invoke",
       args:["a","b","1"],
       chainId:"cmbcchannel666",
       txId:tx_id
   };
  // 
   let chaincodeInvokeResult = yield channel.sendTransactionProposal(request);
上一篇下一篇

猜你喜欢

热点阅读