dev开发者模式调试智能合约

一、使用nodejs编写智能合约

第一步:在chaincode目录下新建一个fishcc文件夹,名字自己起;
第二步:进入fishcc文件夹,执行npm init命令;
第三步:安装fabric-shim;

npm install --save fabric-shim

第四步:新建app.js文件,文件名称自己指定。
第五步:按照下面模板编写合约。

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

let Chaincode = class {
    
    
	
  async Init(stub) {
    
    
    console.info('execute Init method...');
    return shim.success('');
  }
  
  async Invoke(stub) {
    
    
    let ret = stub.getFunctionAndParameters();
    let method = this[ret.fcn];
    if (!method) {
    
    
      let errMsg = ret.fcn + ' method does not exist';
      throw new Error(errMsg);
    }
    try {
    
    
      let payload = await method(stub, ret.params);
      return shim.success(payload);
    } catch (err) {
    
    
      console.log(err);
      return shim.error(err);
    }
  }
  
  async xxx(stub, args) {
    
    
    console.info('调用智能合约方法,xxx方法名根据实际自己指定');
  }
  
}
  
shim.start(new Chaincode());

完整的合约代码如下所示:

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

let Chaincode = class {
    
    
	
  async Init(stub) {
    
    
    return shim.success('');
  }
  
  async Invoke(stub) {
    
    
    let ret = stub.getFunctionAndParameters();
    let method = this[ret.fcn];
    if (!method) {
    
    
      throw new Error(ret.fcn + ' method does not exist.');
    }
    try {
    
    
      let payload = await method(stub, ret.params);
      return shim.success(payload);
    } catch (err) {
    
    
      console.log(err);
      return shim.error(err);
    }
  }
  
  async initLedger(stub, args) {
    
    
    let fishes = [];
    fishes.push({
    
    
       vessel: "Fish001", 
       location: "67.0006, -70.5476", 
       timestamp: "1504054225",
       holder: "zhang"
    });
    fishes.push({
    
    
       vessel: "Fish002", 
       location: "57.9006, -78.3478", 
       timestamp: "1504054666",
       holder: "li"
    });
    fishes.push({
    
    
       vessel: "Fish003", 
       location: "77.9034, -75.3455", 
       timestamp: "1504054888",
       holder: "wang"
    });
    
    for (let i = 0; i < fishes.length; i++) {
    
    
      await stub.putState('FISH' + i, Buffer.from(JSON.stringify(fishes[i])));
      console.info('Added <--> ',fishes[i]);
    }
  }
  
  async queryFish(stub, args) {
    
    
    if (args.length != 1) {
    
    
      throw new Error('args length is not equals 1.');
    }
    let fishNumber = args[0];
    let fishAsBytes = await stub.getState(fishNumber);
    if (!fishAsBytes || fishAsBytes.toString().length <= 0) {
    
    
      throw new Error('no data found.');
    }
    console.log(fishAsBytes.toString());
    return fishAsBytes;
  }
  
  async recordFish(stub, args) {
    
    
    if (args.length != 5) {
    
    
	  throw new Error('Args length is not equals 5.');
    }

    var fish = {
    
    
      vessel: args[1],
      location: args[2],
      timestamp: args[3],
      holder: args[4]
    };

    await stub.putState(args[0], Buffer.from(JSON.stringify(fish)));
  }
  
  async queryAllFish(stub, args) {
    
    
    let startKey = 'FISH0';
    let endKey = 'FISH999';

    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 changeFishHolder(stub, args) {
    
    
    if (args.length != 2) {
    
    
      throw new Error('Args length is not equals 2.');
    }
    let fishAsBytes = await stub.getState(args[0]);
    let fish = JSON.parse(fishAsBytes);
    fish.holder = args[1];
    await stub.putState(args[0], Buffer.from(JSON.stringify(fish)));
  }
}
  
shim.start(new Chaincode());

第六步:修改package.json文件,在scripts中添加start命令;

"scripts": {
    
    
  "start": "node app.js"
},

到此为止智能合约编写完成。

二、dev开发者模式调试智能合约

Hyperledge Fabric的智能合约由各个节点负责启动和维护。但是使用开发者模式后,智能合约的编译和启动工作就交给了用户负责。在智能合约的开发阶段,使用开发者模式去编写、编译、运行智能合约是非常有用的。

启动开发者模式非常简单,我们关闭所有节点的tls功能。

- CORE_PEER_TLS_ENABLED=false

修改peer节点的command命令,在peer node start命令后面加上-peer-chaincodedev=true参数。

command: peer node start --peer-chaincodedev=true	

为所有peer节点配置7052端口。7052端口用户节点之间的grpc通讯。
在这里插入图片描述
最后,我们按照如下步骤进行测试。

第一步:启动所有节点;

docker-compose up -d

第二步:启动完成后进行其中peer节点容器的scripts目录,执行start.sh脚本。

#!/bin/bash
rm -f ../channel-artifacts/mychannel.block
printf "start create channel...\n"
peer channel create -o orderer.example.com:7050 -c mychannel -f ../channel-artifacts/channel.tx
printf "end create channel...\n"
mv mychannel.block ../channel-artifacts
printf "peer0.org1.example.com start join channel...\n"
peer channel join -b ../channel-artifacts/mychannel.block
printf "peer0.org1.example.com end join channel...\n"
printf "peer0.org1.example.com start install chaincode...\n"
peer chaincode install -n fishcc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/fishcc
printf "peer0.org1.example.com end install chaincode...\n"
printf "start packaging chaincode...\n"
peer chaincode package -n fishcc -p /opt/gopath/src/github.com/chaincode/fishcc -v 1.0 fishcc.1.0.out -l node
printf "end packaging chaincode"
mv fishcc.1.0.out ../channel-artifacts
export CORE_PEER_ADDRESS=peer1.org1.example.com:7051
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key
printf "peer1.org1.example.com start join channel...\n"
peer channel join -b ../channel-artifacts/mychannel.block
printf "peer1.org1.example.com end join channel...\n"
printf "peer1.org1.example.com start install chaincode...\n"
peer chaincode install ../channel-artifacts/fishcc.1.0.out
printf "peer1.org1.example.com end install chaincode...\n"
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key
printf "peer0.org2.example.com start join channel...\n"
peer channel join -b ../channel-artifacts/mychannel.block
printf "peer0.org2.example.com end join channel...\n"
printf "peer0.org2.example.com start install chaincode...\n"
peer chaincode install ../channel-artifacts/fishcc.1.0.out
printf "peer0.org2.example.com end install chaincode...\n"
export CORE_PEER_ADDRESS=peer1.org2.example.com:7051
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.key
printf "peer1.org2.example.com start join channel...\n"
peer channel join -b ../channel-artifacts/mychannel.block
printf "peer1.org2.example.com end join channel...\n"
printf "peer1.org2.example.com start install chaincode...\n"
peer chaincode install ../channel-artifacts/fishcc.1.0.out
printf "peer1.org2.example.com end install chaincode...\n"

上面shell脚本执行创建通道、加入通道、创建链码等工作。

第三步:打开另外一个shell窗口,进入chaincode/fishcc目录,然后执行执行npm start --peer.address grpc://localhost:7052 --chaincode-id-name fishcc:1.0,执行成功后的界面如下所示:
在这里插入图片描述
第四步:实例化合约。

peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n fishcc -l node -v 1.0 -c '{"Args":[""]}' -P "AND('Org1MSP.member')"

执行实例化后,可以看到运行合约窗口如下:
在这里插入图片描述
我们可以在合约窗口中看到实例化合约的结果信息。

第五步:测试。

# 初始化
peer chaincode invoke -C mychannel -n fishcc -c '{"Args":["initLedger"]}' -o orderer.example.com:7050

# 查询
peer chaincode invoke -C mychannel -n fishcc -c '{"Args":["queryFish","FISH0"]}'

三、配置couchDB

Hyperledge Fabric支持两种模式的状态数据库:

  • levelDB:文件形式存储,不易查看管理
  • couchDB:独立容器数据库,提供了丰富的查询功能

3.1 配置couchDB

第一步:下载hyperledger/fabric-couchdb镜像;
在这里插入图片描述
第二步:在docker-compose配置文件中配置couchDB服务;

couchdb:
    container_name: couchdb
    image: hyperledger/fabric-couchdb
    environment:
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=123456
    ports:
      - 5984:5984
    networks:
      - byfn

上面COUCHDB_USER和COUCHDB_PASSWORD分别指定couchDB管理平台的登录名和登录密码。

第三步:在peer节点的环境配置中添加couchDB的配置信息;

- CORE_LEDGER_STATE_STATEDATABASE=CouchDB
- CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
- CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
- CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=123456

第四步:指定peer节点的启动顺序;

depends_on:
  - orderer.example.com
  - couchdb

3.2 couchDB的简单实用

第一步:启动docker容器;
在这里插入图片描述
第二步:在浏览器上输入http://localhost:5984/_utils进入控制台;
在这里插入图片描述
第三步:输入用户名和密码。登录成功后,如果已经初始化智能合约,那么在Databases栏目的右边可以看到部署的合约。
在这里插入图片描述
上面mychannel_fishcc就是我们部署的合约。点击进去后可以看到有三条数据,分别是FISH0、FISH1、FISH2。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhongliwen1981/article/details/104994059
今日推荐