開発開発者モードでスマートコントラクトをデバッグする

1つは、nodejsを使用してスマートコントラクトを作成する

ステップ1:chaincodeディレクトリに新しいfishccフォルダーを作成し、自分で名前を開始します。
ステップ2:fishccフォルダーに入り、npm initコマンドを実行します。
ステップ3:fabric-shimをインストールします。

npm install --save fabric-shim

ステップ4:新しいapp.jsファイルを作成し、自分でファイル名を指定します。
ステップ5:次のテンプレートに従って契約書を作成します。

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());

手順6:package.jsonファイルを変更し、スクリプトにstartコマンドを追加します。

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

これまでのところ、スマートコントラクトが書かれています。

2.開発開発者モードでスマートコントラクトをデバッグします

Hyperledge Fabricのスマートコントラクトは、各ノードによって開始および維持されます。ただし、開発者モードを使用した後は、スマートコントラクトのコンパイルと起動はユーザーに任されます。スマートコントラクトの開発フェーズでは、開発者モードを使用してスマートコントラクトを作成、コンパイル、および実行すると非常に便利です。

開発者モードの開始は非常に簡単です。すべてのノードのtls機能をオフにします。

- CORE_PEER_TLS_ENABLED=false

ピアノードのコマンドコマンドを変更し、ピアノードの開始コマンドの後に-peer-chaincodedev = trueパラメータを追加します。

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

すべてのピアノードのポート7052を構成します。ポート7052のユーザーノード間のGRPC通信。
ここに画像の説明を挿入
最後に、以下の手順に従ってテストします。

最初のステップ:すべてのノードを開始します。

docker-compose up -d

ステップ2:起動が完了したら、ピアノードコンテナの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"

上記のシェルスクリプトは、チャネルの作成、チャネルの追加、チェーンコードの作成などのタスクを実行します。

ステップ3:別のシェルウィンドウを開き、chaincode / fishccディレクトリに入り、実行を実行しnpm start --peer.address grpc://localhost:7052 --chaincode-id-name fishcc:1.0ます。正​​常に実行された後のインターフェイスは次のとおりです。
ここに画像の説明を挿入
ステップ4:コントラクトをインスタンス化します。

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

インスタンス化を実行すると、実行中のコントラクトウィンドウが次のように表示されます。
ここに画像の説明を挿入
インスタンス化されたコントラクトの結果情報がコントラクトウィンドウに表示されます。

ステップ5:テストします。

# 初始化
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"]}'

3、couchDBを構成します

Hyperledge Fabricは、状態データベースの2つのモードをサポートしています。

  • levelDB:ファイルストレージ、表示と管理が簡単ではない
  • couchDB:独立したコンテナデータベース。豊富なクエリ機能を提供します

3.1couchDBを構成する

最初のステップ:hyperledger / fabric-couchdbイメージをダウンロードします;
ここに画像の説明を挿入
2番目のステップ: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管理プラットフォームのログイン名とログインパスワードを指定します。

ステップ3:ピアノードの環境構成に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

ステップ4:ピアノードの起動シーケンスを指定します。

depends_on:
  - orderer.example.com
  - couchdb

3.2couchDBのシンプルで実用的

最初のステップ:Dockerコンテナを起動します;
ここに画像の説明を挿入
2番目のステップ:ブラウザにhttp://localhost:5984/_utilsコンソール入力します;
ここに画像の説明を挿入
3番目のステップ:ユーザー名とパスワードを入力します。ログインが成功した後、スマートコントラクトが初期化されている場合は、[データベース]列の右側にデプロイされたコントラクトが表示されます。
ここに画像の説明を挿入
上記のmychannel_fishccは、デプロイしたコントラクトです。クリックすると、FISH0、FISH1、FISH2の3つのデータがあることがわかります。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/zhongliwen1981/article/details/104994059