目次


ブロックチェーン・ネットワークを改良してデプロイする

開発ツールをインストールし、ネットワークの単体テストを行って IBM Cloud にデプロイする

Comments

注: 現在、IBM Blockchain Platform では、開発に一貫して Hyperledger Fabric を使用するようになっています。ユーザーは任意で Hyperledger Composer を使用することもできますが、その場合、IBM は Hyperledger Composer のサポートを提供しません。

このチュートリアルのパート 1 では、Hyperledger Composer Playground のローカル・バージョンで、単純なビジネス・ネットワークをモデル化してテストする方法を説明しました。今回は Hyperledger Composer の詳細を探り、最終的には作成したネットワーク・モデルを IBM Cloud 上のオンライン Playground にインポートします。

(このパート 2 を完了した後は、最終回のパート 3 に進んで Hyperledger Fabric をコンピューター上にインストールする方法、ビジネス・ネットワークをローカル・インスタンスにデプロイする方法、サンプル・ネットワーク・ブロックチェーン・アプリケーションを操作する方法を学んでください)。

まずは、いくつかの開発ツールをインストールする必要があります。インストール手順については、このリンク先のチュートリアルの動画で説明しています。開発ツールのインストールに続き、パート 1 で取り組んだサンプルの Perishable Goods ネットワークに変更を加えます。具体的には、配送コンテナー内の IoT GPS センサーをモデル化するために GPS 読み取り機能を Shipment 資産に追加し、出荷物が宛先の港に到達した時点でアラートを送信するようにスマート・コントラクト (チェーンコード) を変更します。

このチュートリアルでは、ブロックチェーン・ネットワークの単体テストを行う方法も説明します。そのために、Cucumber というビヘイビア駆動型開発 (BDD) ツールを使用して、Cucumber 機能ファイルでスマート・コントラクトのロジックをテストします。

最後に、IBM Cloud 上でホストされているオンラインの Playground にモデルをインポートします。IBM Cloud 上でもパート 1 で行ったように、モデルとやり取りし、Playground UI を介してトランザクションを送信できます。オンラインの Playground は IBM Cloud 上でホストされているため、モデルを使用するためにインストールしなければならないものは何もありません。

前提条件

以下の前提条件の他、次のセクションで、インストールする必要がある開発ツールを紹介します。

1

環境をセットアップする

このチュートリアルを作成している時点で、Composer がサポートされているのは Ubuntu Linux と MacOS のみです (このリンク先のページで説明されている問題が解決に至っていないため、ネイティブ Windows のサポートは期待できそうにありません)。

インストールする必要があるツールのほとんどについて、インストール手順は Ubuntu Linux と MacOS とで基本的に同じです。違いがある箇所については、手順を進めるなかで説明を加えてあります (このリンク先の動画でコンピューターのセットアップ方法をご覧ください)。

Git は、現在最もよく使われているソース・コード・リポジトリー管理ツールの 1 つです。このチュートリアルに従うには、Git をインストールする必要があります。Ubuntu の場合、Git をインストールするのはわけのないことです。sudo apt-get install Git を実行するだけで、Git をインストールできます。MacOS を実行している場場合は、次のセクションで Node.js をインストールすると、Git と MacOS 用コマンドライン・ツールが一緒にインストールされます。

1a

Node.js をインストールする

Node.js をインストールするのに最も簡単な方法は、nvm を使用することです。nvm は Node バージョン・マネージャー (Node Version Manager) を表します。名前が示唆するとおり、nvm はコンピューター上にインストールされた Node のバ―ジョンを管理するために使用します。nvm をインストールするには、以降で説明する手順のうち、お使いのプラットフォームに対応する手順に従ってください。

Ubuntu Linux 上に nvm をインストールする

Hyperledger Composer チームが、nvm をインストールするためのスクリプトを提供しています。Molecule をインストールするには、次のコマンドを実行してこのスクリプトをダウンロードします。

curl -O https://hyperledger.github.io/composer/prereqs-ubuntu.sh

スクリプトがダウンロードされたら、最新バージョンの nvm (このチュートリアルを作成している時点では、0.33.11) がダウンロードされるようにスクリプトを編集します。スクリプトを保存して実行可能にしてから、次のコマンドを使用して実行します。

chmod u+x prereqs-ubuntu.sh
./prereqs-ubuntu.sh

パスワードの入力を求めるプロンプトが出されます (システム上で sudo を介していることを確認してください)。詳細については、このリンク先のページ「Installing and developing with Hyperledger Composer」にアクセスしてください。

スクリプトが完了したら、Node.js のインストールを開始できます。「nvm を使用して Node.js をインストールする」のセクションまでスキップしてください。

MacOS 上に nvm をインストールする

MacOS には、よく使われている多くのコマンドライン・ツール (Git、make、svn など) の独自バージョンが用意されています。xcode コマンドライン・ツールがインストールされているかどうかを確認するには、ターミナル・ウィンドウを開いて Git と入力し、Enter キーを押します。

図 1. このメッセージが表示されたら、コマンドライン・ツールをインストールする必要があります
Iコマンドライン・ツールをインストールする必要があることを示すメッセージの画面のスクリーンショット
Iコマンドライン・ツールをインストールする必要があることを示すメッセージの画面のスクリーンショット

図 1 に示すようなメッセージが表示されたら、「Install (インストール)」ボタンをクリックしてコマンドライン・ツールをインストールします。インストールは 5 分とかからずに完了します。

ターミナルから次のコマンドを実行します。

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

注:nvm GitHub リポジトリー上に置かれている README を読んで、最新バージョン (このチュートリアルを作成している時点では、0.33.11) をインストールするようにしてください。

スクリプトによって Bash シェルの設定が変更されるため、ターミナル・ウィンドウを終了して開き直すことで、新しい設定をロードする必要があります。

nvm が正常にインストールされていることを確認するには、ターミナル・ウィンドウから nvm --version コマンドを実行します。次のような出力が表示されたら、正常にインストールされています。

$ nvm --version
0.33.11

これで、nvm を使用して Node.js をインストールする準備が整いました。

nvm を使用して Node.js をインストールする

Node.js をインストールするには、コマンドライン・ウィンドウ (Ubuntu の場合) またはターミナル・ウィンドウ (MacOS の場合) を開いて、nvm install v8 コマンドを実行します。これで、LTS バージョンの Node.js がインストールされます。

nvm install v8

次のような出力が表示されます。

$ nvm install v8
Downloading and installing node v8.12.0...
Local cache found: $NVM_DIR/.cache/bin/node-v8.12.0-darwin-x64/node-v8.12.0-darwin-x64.tar.xz
Checksums match! Using existing downloaded archive $NVM_DIR/.cache/bin/node-v8.12.0-darwin-x64/node-v8.12.0-darwin-x64.tar.xz
Now using node v8.12.0 (npm v6.4.1)

注: Composer ツールをインストールするときは、Node 8 を使用する必要があります。そうでないと、grpc をインストールする際にエラーが発生します。

プラットフォームに応じてコードがコンパイルされるため、インストールが完了するまでに数分かかる場合があります (少なくとも MacOS の場合には、時間がかかります)。完了するまで我慢強く待ってください。

最後に、Node.js がインストールされたことを確認します。

$ node -v
v8.12.0

このチュートリアルでは Node.js 8.12.0 をインストールしました。これは、チュートリアルを作成している時点で最新のバージョン 8 です。

1b

Composer コマンドライン・インターフェース (CLI) をインストールする

ビジネス・ネットワークを作成、デプロイ、更新するにも、ブロックチェーン・ネットワーク関連の他の機能を実行するにも、コマンドライン・インターフェース (CLI) を使用します。

Composer CLI をインストールするには、コマンドライン・ウィンドウ (Ubuntu の場合) またはターミナル・ウィンドウ (MacOS の場合) を開いて、次のコマンドを入力します。

npm install -g composer-cli

npm は Node パッケージ・マネージャー (Node Package Manager) を表します。Npm は、nvm で Node.js をインストールしたときに一緒にインストールされています。一般に、npm を使用して Node.js パッケージをインストールすると、パッケージはインストール先のディレクトリー・ツリー内でしか使用可能になりません。-g オプションを指定してグローバルにパッケージをインストールするように npm に指示すると、コンピューター上のどの Node.js プロジェクトでもパッケージを使用できるようになります。

composer-cli が正常にインストールされたことを確認します。コマンドライン・ウィンドウ (Ubuntu の場合) またはターミナル・ウィンドウ (MacOS の場合) から composer -v を実行します。これにより、出力としてバージョン番号が表示されます。

$ composer -v
v0.20.4
1c

VSCode をインストールする

VSCode は Microsoft が提供しているオープンソースのエディターです。Microsoft の VSCode GitHub リポジトリーから、ソース・コードを自由にダウンロードできます。

VSCode をインストールしなくても Hyperledger Composer の開発を行うことはできますが、インストールすることをお勧めします。実際のところ、VSCode はかなり重宝なツールです。VSCode には Hyperledger Composer 拡張機能があり、簡単にインストールして有効化できます。VSCode 拡張機能は Git に円滑に統合し、Composer ビジネス・ネットワークのモデル・ファイル内の構文強調表示機能を提供します。

Ubuntu Linux 上に VSCode をインストールする

Ubuntu (または他の Debian ベースの Linux) 上に VSCode をインストールするには、次のいずれかの方法を選択できます。

  • .deb: Debian パッケージ
  • .rpm: RPM パッケージ・マネージャー (当初は Red Hat パッケージ・マネージャーと呼ばれていました)
  • .tar.gz: TAR 書庫

最もやりやすい方法を選んで、このリンク先の VSCode Web サイト上に記載されている詳細なインストール手順に従ってください。

MacOS 上に VSCode をインストールする

MacOS 上に VSCode をインストールするには、「Download for Mac (Mac 用ダウンロード)」ボタンをクリックし、VSCode アプリを含む ZIP ファイルを Mac にダウンロードします。VSCode をインストールして実行する詳細な手順については、このリンク先の VSCode Web サイトをご覧ください。

1d

1d Hyperledger Composer 拡張機能をインストールする

Hyperledger Composer ファイルを編集するときに構文強調表示機能を最大限活用するために、必ず VSCode の Composer 拡張機能をインストールしてください。VSCode を起動して、UI の左側にある「Extensions (拡張機能)」アイコンをクリックすると (または、Mac 上で Cmd + X キーを押すと)、拡張機能エディターが開きます。

検索フィールドに「Hyperledger」と入力すると、フィールドのすぐ下のリストに Hyperledger Composer 拡張機能が示されます。「Install (インストール)」ボタンをクリックして拡張機能をインストールします。インストールが完了したら、VSCode を再起動して拡張機能を有効にします。

図 2. VSCode の拡張機能マーケットプレイス
VSCode 拡張機能マーケットプレイスのスクリーンショット
VSCode 拡張機能マーケットプレイスのスクリーンショット

これで、VSCode を使用して Hyperledger Composer プロジェクト・ファイルを編集するときは、常に自動的に構文が強調表示されるようになります。図 3 に、VSCode エディター・ウィンドウ内で開かれている perishable.cto モデル・ファイルが示されています。namespace キーワードと enum キーワードに構文強調表示機能が適用されていることに注目してください。

図 3. VSCode 内での Perishable Goods ネットワーク
VSCode 拡張機能マーケットプレイスのスクリーンショット
VSCode 拡張機能マーケットプレイスのスクリーンショット

動画: 環境をセットアップする {: #setup-video}

この動画で、環境をセットアップする方法を説明します。

トランスクリプト(英語)

2

ビルドを実行する

必要なツールが揃ったので、これらのツールを実際に動かしていきましょう。用意されている perishable-network GitHub リポジトリーを複製してビルドし、先ほどインストールした Node.js ツールを使って単体テストを行います。

コンピューター上で Hyperledger Composer とネットワーク・モデルの作業ディレクトリーとする場所を決めます。例えば、私は ~/HyperledgerComposer を Composer ルート・ディレクトリーとして使用するので、Bash シェル内で次のコマンドを使用して環境変数を設定します。

$ export COMPOSER_ROOT=~/HyperledgerComposer

チュートリアルを場所に依存させないようにするために、このディレクトリーを $COMPOSER_ROOT として表します。以降の例で $COMPOSER_ROOT が使われている場合、これは、皆さんが作業ディレクトリーとして選択した場所を表します。上記のように、$COMPOSER_ROOT を該当する場所に設定することをお勧めします。

コマンドライン・ウィンドウ (Ubuntu の場合) またはターミナル・ウィンドウ (MacOS の場合) を開いて、カレント・ディレクトリーを $COMPOSER_ROOT ディレクトリーに変更し、次に示すコマンド Git clone https://Github.com/makotogo/developerWorks.Git を入力します。

$ cd $COMPOSER_ROOT
$ pwd
/Users/sperry/HyperledgerComposer
$ git clone https://github.com/jstevenperry/IBM-Developer
Cloning into 'IBM-Developer'...
remote: Enumerating objects: 326, done.
remote: Counting objects: 100% (326/326), done.
remote: Compressing objects: 100% (155/155), done.
remote: Total 1236 (delta 112), reused 279 (delta 80), pack-reused 910
Receiving objects: 100% (1236/1236), 21.92 MiB | 12.73 MiB/s, done.
Resolving deltas: 100% (498/498), done.
$

これで、必要なコードを入手できました。次は、このコードをビルドしてテストします。

Node.js パッケージ・マネージャー (npm) を使用してビルドを実行し、次に単体テストを実行します。この単体テストは、私があらかじめ用意しておいたものです。以下のコマンドを実行してください。

cd $COMPOSER_ROOT/IBM-Developer/Hyperledger/Composer/Basics
npm install && npm test

上記のコマンドによってどのような処理が行われるかと言うと、まず、perishable-network コードが置かれているディレクトリーにナビゲートします。次に、npm install を実行してローカル Node.js 環境 (つまり、perishable-network にとってローカルの環境) をセットアップします。続いて npm test を実行します。これにより、プロジェクトの一部となっている単体テストが実行されます (package.json を参照)。

大量の出力が表示されますが、出力の最後が次のようになっていれば、テストは成功しています。

    .
    .
Perishable Shipping Network
    #shipment
Adding temperature 4.5 to shipment SHIP_001
Received at: Wed Dec 31 1969 18:00:00 GMT-0600 (CST)
Contract arrivalDateTime: Sun Nov 11 2018 14:09:14 GMT-0600 (CST)
Lowest temp reading: 4.5
Highest temp reading: 4.5
Payout: 2500
Grower: farmer@email.com new balance: 2500
Importer: supermarket@email.com new balance: -2500
      ✓ should receive base price for a shipment within temperature range
Adding temperature 4.5 to shipment SHIP_001
Received at: Thu Sep 26 33658 20:46:40 GMT-0500 (CDT)
Contract arrivalDateTime: Sun Nov 11 2018 14:09:14 GMT-0600 (CST)
Late shipment
Payout: 0
Grower: farmer@email.com new balance: 2500
Importer: supermarket@email.com new balance: -2500
      ✓ should receive nothing for a late shipment
Adding temperature 1 to shipment SHIP_001
Received at: Wed Dec 31 1969 18:00:00 GMT-0600 (CST)
Contract arrivalDateTime: Sun Nov 11 2018 14:09:14 GMT-0600 (CST)
Lowest temp reading: 1
Highest temp reading: 4.5
Min temp penalty: 0.2
Payout: 1500
Grower: farmer@email.com new balance: 4000
Importer: supermarket@email.com new balance: -4000
      ✓ should apply penalty for min temperature violation
Adding temperature 11 to shipment SHIP_001
Received at: Wed Dec 31 1969 18:00:00 GMT-0600 (CST)
Contract arrivalDateTime: Sun Nov 11 2018 14:09:14 GMT-0600 (CST)
Lowest temp reading: 1
Highest temp reading: 11
Min temp penalty: 0.2
Max temp penalty: 0.30000000000000004
Payout: 999.9999999999998
Grower: farmer@email.com new balance: 5000
Importer: supermarket@email.com new balance: -5000
      ✓ should apply penalty for max temperature violation


  4 passing (1s)
3

Perishable Goods ビジネス・ネットワークを改良する {: #refine}

Perishable Goods ビジネス・ネットワークは、Grower (生産業者)、Shipper (配送業者)、Importer (輸入業者) からなるビジネス・ネットワークをモデル化したものです。詳細は、README.md ファイル内で確認できます。このネットワーク内のさまざまな参加者の間で交わされる契約は、CTO モデリング言語でモデル化し、JavaScript で作成されたチェーンコード (スマート・コントラクト) によって執行されます。

このセクションの演習では、コンテナー船の位置を確認できるように、IoT GPS センサーが貨物コンテナーに取り付けられていることを前提とします。このセンサーから収集する測定値をネットワーク・モデルに追加するとともに、船が最終目的地に到着した時点でイベントが送信されるようにします。

GPS センサーをネットワーク・モデルに追加するには、ビジネス・モデルに変更を加える必要があります。また、単体テストも追加で作成しなければなりません。ここでは、Mocha で単体テストを作成するのではなく、Cucumber というツールを使用して単体テストを作成する方法を説明します。Cucumber では人間が読んで理解しやすい構文を使えるため、非常に強力なツールとなります。

3a

ネットワーク定義を変更する

このセクションで、用意されているコードを貼り付けて変更した後のソリューションの内容は、IBM-Developer/Hyperledger/Composer/Basics/iot-perishable-network ディレクトリー内に格納されているモデルを見るとわかります。遠慮なく、このモデルを参考として使っててください。

GPS センサーを追加するには、モデルにいくつかの変更を加える必要があります。VSCode を起動して、Perishable Goods ネットワークのルート・ディレクトリー ($COMPOSER_ROOT)/IBM-Developer/Hyperledger/Composer/Basics/perishable-network) を開きます。models ディレクトリー内にある perishable.cto というモデル・ファイルを開いてください。

ShipmentStatus の直下に、次の enum を新しく追加します。これは、コンパス上の主要な位置を表します。

/**
 * Directions of the compass
 */
enum CompassDirection {
  o N
  o S
  o E
  o W
}

方角は、北を表す N、南を表す S などで示します。重要な点として、GPS 座標一式として入力するデータは制約する必要があります。そのため、この enum を使用して、モデルに入力できる値を制約し、有効な値だけが入力されるようにしています。

GPS 測定値を取得するたびに、その値をトランザクションとしてブロックチェーンに記録します。これはつまり、トランザクションを GPS 測定値のモデルに追加する必要があるということです。TemperatureReading トランザクションの直下に、次の GpsReading トランザクションを新しく追加します。

リスト 1. ブロックチェーン内で GPS 測定値の記録を処理するトランザクション

/**
 * A GPS reading for a shipment. E.g. received from a device
 * within a shipping container
 */
transaction GpsReading extends ShipmentTransaction {
  o String readingTime
  o String readingDate
  o String latitude
  o CompassDirection latitudeDir
  o String longitude
  o CompassDirection longitudeDir
}

GPS 測定値には、測定が行われた日時などのパラメーターがいくつか必要です。さらに、緯度と経度の情報も必要です。上記のコードでは、これらの情報をパラメーターとしてトランザクションに提供しています。

次に、トランザクションで GPS 測定値をブロックチェーン内に保存するために、この情報をブロックチェーン資産の一部にする必要があります。船のコンテナーから取得される GPS 測定値は、概念上、出荷物の一部です。したがって、測定値の追加先とする資産は当然 (TemperatureReadings と同じく)、Shipment ということになります。Shipment 資産に追加された測定値は、以下のコードの 7 行目 (o GpsReading[] gpsReadings optional) に該当します。

asset Shipment identified by shipmentId {
  o String shipmentId
  o ProductType type
  o ShipmentStatus status
  o Long unitCount
  o TemperatureReading[] temperatureReadings optional
  o GpsReading[] gpsReadings optional
  --> Contract contract
}

最後に、Importer 参加者の直下に 2 つのイベントを追加します。1 つは温度のしきい値を超えたことを示すイベント、もう 1 つはコンテナー船が最終目的地の港に到着したことを示すイベントです

リスト 2. 新しいイベント - コンテナー内の温度が契約の許容値を超えたことを示すイベントとコンテナー船が港に到着したことを示すイベント

/**
 * An event - when the temperature goes outside the agreed-upon boundaries
 */
event TemperatureThresholdEvent {
  o String message
  o Double temperature
  --> Shipment shipment
}
 
/**
 * An event - when the ship arrives at the port
 */
event ShipmentInPortEvent {
  o String message
  --> Shipment shipment
}

チェーンコードを追加する

GPS 測定値をモデルに追加するために、GPS センサーとトランザクションをモデル化しました。次は、ブロックチェーンの更新を処理する JavaScript チェーンコードを作成する必要があります。それには、lib/logic.js を開いて、このファイルにいくつかの変更を加えます。

まず、次の行をファイルの先頭に追加します。この行は、リンターに対して getParticipantRegistry() などのグローバル関数を無視するよう指示します。

/* global getParticipantRegistry getAssetRegistry getFactory emit */

次に、TemperatureReading トランザクションを処理するコードを temperatureReading 関数に追加します。メソッドの本文全体を次のコードで置き換えてください。

/**
 * A temperature reading has been received for a shipment
 * @param {org.acme.shipping.perishable.TemperatureReading} temperatureReading - the TemperatureReading transaction
 * @transaction
 */
async function temperatureReading(temperatureReading) {  // eslint-disable-line no-unused-vars

    const NS = 'org.acme.shipping.perishable';
    const shipment = temperatureReading.shipment;
    const contract = shipment.contract;
    const factory = getFactory();

    console.log('Adding temperature ' + temperatureReading.centigrade + ' to shipment ' + shipment.$identifier);

    if (shipment.temperatureReadings) {
        shipment.temperatureReadings.push(temperatureReading);
    } else {
        shipment.temperatureReadings = [temperatureReading];
    }

    if (temperatureReading.centigrade < contract.minTemperature ||
        temperatureReading.centigrade > contract.maxTemperature) {
        var temperatureEvent = factory.newEvent(NS, 'TemperatureThresholdEvent');
        temperatureEvent.shipment = shipment;
        temperatureEvent.temperature = temperatureReading.centigrade;
        temperatureEvent.message = 'Temperature threshold violated! Emitting TemperatureEvent for shipment: ' + shipment.$identifier;
        console.log(temperatureEvent.message);
        emit(temperatureEvent);
    }

    // add the temp reading to the shipment
    const shipmentRegistry = await getAssetRegistry(NS + '.Shipment');
    await shipmentRegistry.update(shipment);
}

このコードは、現在の温度測定値を契約条項に照らし合わせ、温度の上限または下限のいずれかを超えている場合は TemperatureThresholdEvent イベントを発行します。

続いて、GpsReading トランザクションを処理する新しい関数を追加します。

注: 必ずコメント・ブロックも追加してください。このブロックに、この後必要になる重要な 2 つのアノテーション (@param@transaction) が含まれています。

/**
 * A GPS reading has been received for a shipment
 * @param {org.acme.shipping.perishable.GpsReading} gpsReading - the GpsReading transaction
 * @transaction
 */
async function gpsReading(gpsReading) {  // eslint-disable-line no-unused-vars

    var factory = getFactory();
    var NS = 'org.acme.shipping.perishable';
    var shipment = gpsReading.shipment;
    var PORT_OF_NEW_YORK = '/LAT:40.6840N/LONG:74.0062W';

    var latLong = '/LAT:' + gpsReading.latitude + gpsReading.latitudeDir + '/LONG:' +
        gpsReading.longitude + gpsReading.longitudeDir;

    if (shipment.gpsReadings) {
        shipment.gpsReadings.push(gpsReading);
    } else {
        shipment.gpsReadings = [gpsReading];
    }

    if (latLong === PORT_OF_NEW_YORK) {
        var shipmentInPortEvent = factory.newEvent(NS, 'ShipmentInPortEvent');
        shipmentInPortEvent.shipment = shipment;
        var message = 'Shipment has reached the destination port of ' + PORT_OF_NEW_YORK;
        shipmentInPortEvent.message = message;
        console.log(message);
        emit(shipmentInPortEvent);
    }

    const shipmentRegistry = await getAssetRegistry(NS + '.Shipment');
    await shipmentRegistry.update(shipment);
}

トランザクションのチェーンコードは、この GPS 測定値を Shipment 資産に含まれる GpsReading の配列内に格納します。その上で、この GPS 測定値が宛先の港に対応するかどうかをチェックし、対応する場合は ShipmentInPort イベントを発行します。最後に、ブロックチェーンを更新して Shipment の現在の状態を反映させます。

3c

Cucumber 機能テストを追加する

仕上げに入りましょう。トランザクションをモデルに追加し、新しい 2 つのイベントも追加しました。ここで、今まで行った変更が有効であることを確認するために単体テストを行います。

features フォルダー内に iot-perishable.feature という名前の新しいファイルを作成し、そのファイルを VSCode 内で開きます。追加する必要のあるセクションについて、1 つずつ簡単に説明していきます。Cucumber については「Cucumber での単体テストの詳細」セクションで詳しく説明しますが、まずは機能を有効にすることが先決です。

まず、Cucumber に対し、テスト対象の機能を指示します。各単体テストの前に準備しなければならないバックグラウンド (セットアップ) があれば、それも指示します。次のコードを空の iot-perishable.feature ファイルに追加してください。

リスト 3. Cucumber の機能とバックグラウンド

Feature: IoT Perishable Network
 
    Background:
        Given I have deployed the business network definition ..
        And I have added the following participants
        """
        [
        {"$class":"org.acme.shipping.perishable.Grower", "email":"grower@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"USA"}, "accountBalance":0},
        {"$class":"org.acme.shipping.perishable.Importer", "email":"supermarket@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"UK"}, "accountBalance":0},
        {"$class":"org.acme.shipping.perishable.Shipper", "email":"shipper@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"Panama"}, "accountBalance":0}
        ]
        """
        And I have added the following asset of type org.acme.shipping.perishable.Contract
            | contractId | grower           | shipper               | importer           | arrivalDateTime  | unitPrice | minTemperature | maxTemperature | minPenaltyFactor | maxPenaltyFactor |
            | CON_001    | grower@email.com | supermarket@email.com | supermarket@email.com | 10/26/2018 00:00 | 0.5       | 2              | 10             | 0.2              | 0.1              | 
         
        And I have added the following asset of type org.acme.shipping.perishable.Shipment
            | shipmentId | type    | status     | unitCount | contract |
            | SHIP_001   | BANANAS | IN_TRANSIT | 5000      | CON_001  |
        When I submit the following transactions of type org.acme.shipping.perishable.TemperatureReading
            | shipment | centigrade |
            | SHIP_001 | 4          |
            | SHIP_001 | 5          |
            | SHIP_001 | 10         |

Scenario という名前でいくつかの単体テストを追加します。iot-perishable.feature ファイル内の Background ブロックの直下に、次のシナリオを追加します。

リスト 4. シナリオ: 温度が合意した範囲内に収まっている場合

Scenario: When the temperature range is within the agreed-upon boundaries
    When I submit the following transaction of type org.acme.shipping.perishable.ShipmentReceived
        | shipment |
        | SHIP_001 |
     
    Then I should have the following participants
    """
    [
    {"$class":"org.acme.shipping.perishable.Grower", "email":"grower@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"USA"}, "accountBalance":2500},
    {"$class":"org.acme.shipping.perishable.Importer", "email":"supermarket@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"UK"}, "accountBalance":-2500},
    {"$class":"org.acme.shipping.perishable.Shipper", "email":"shipper@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"Panama"}, "accountBalance":0}
    ]
    """

このシナリオでは、貨物コンテナー内の温度が合意した範囲内に収まっている場合、生産業者に全額が支払われるようにします。

次に追加するシナリオでは、温度の下限値である摂氏 2 度を 2 度以上超えて下回った場合、契約違反となります。

リスト 5. シナリオ: 温度の下限しきい値を摂氏 2 度以上超えて下回った場合

Scenario: When the low/min temperature threshold is breached by 2 degrees C
    Given I submit the following transaction of type org.acme.shipping.perishable.TemperatureReading
        | shipment | centigrade |
        | SHIP_001 | 0          |
 
    When I submit the following transaction of type org.acme.shipping.perishable.ShipmentReceived
        | shipment |
        | SHIP_001 |
     
    Then I should have the following participants
    """
    [
    {"$class":"org.acme.shipping.perishable.Grower", "email":"grower@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"USA"}, "accountBalance":500},
    {"$class":"org.acme.shipping.perishable.Importer", "email":"supermarket@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"UK"}, "accountBalance":-500},
    {"$class":"org.acme.shipping.perishable.Shipper", "email":"shipper@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"Panama"}, "accountBalance":0}
    ]
    """

このシナリオでは、温度の下限値が摂氏 0 度まで下がった場合、生産業者には、しきい値を超える摂氏 1 度ごとに違反金が課せられます。

次に追加するシナリオでは、温度の上限値しきい値を摂氏 2 度以上超えて上回った場合、契約違反となります。

リスト 6. シナリオ: 温度の上限しきい値を摂氏 2 度以上超えて上回った場合

Scenario: When the hi/max temperature threshold is breached by 2 degrees C
    Given I submit the following transaction of type org.acme.shipping.perishable.TemperatureReading
        | shipment | centigrade |
        | SHIP_001 | 12          |
 
    When I submit the following transaction of type org.acme.shipping.perishable.ShipmentReceived
        | shipment |
        | SHIP_001 |
     
    Then I should have the following participants
    """
    [
    {"$class":"org.acme.shipping.perishable.Grower", "email":"grower@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"USA"}, "accountBalance":1500},
    {"$class":"org.acme.shipping.perishable.Importer", "email":"supermarket@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"UK"}, "accountBalance":-1500},
    {"$class":"org.acme.shipping.perishable.Shipper", "email":"shipper@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"Panama"}, "accountBalance":0}
    ]
    """

このシナリオでは、温度の上限値が摂氏 10 度を超えた場合、生産業者には、しきい値を超える摂氏 1 度ごとに違反金が課せられます。

さらに、リスト 2 に 3 つのシナリオ (2 つの TemperatureThresholdEvent と 1 つの ShipmentInPortEvent) をモデルに追加します (リスト 2 を参照)。

リスト 7. シナリオ: イベント

Scenario: Test TemperatureThresholdEvent is emitted when the min temperature threshold is violated
    When I submit the following transactions of type org.acme.shipping.perishable.TemperatureReading
        | shipment | centigrade |
        | SHIP_001 | 0          |
     
    Then I should have received the following event of type org.acme.shipping.perishable.TemperatureThresholdEvent
        | message                                                                          | temperature | shipment |
        | Temperature threshold violated! Emitting TemperatureEvent for shipment: SHIP_001 | 0           | SHIP_001 |
 
 
Scenario: Test TemperatureThresholdEvent is emitted when the max temperature threshold is violated
    When I submit the following transactions of type org.acme.shipping.perishable.TemperatureReading
        | shipment | centigrade |
        | SHIP_001 | 11         |
     
    Then I should have received the following event of type org.acme.shipping.perishable.TemperatureThresholdEvent
        | message                                                                          | temperature | shipment |
        | Temperature threshold violated! Emitting TemperatureEvent for shipment: SHIP_001 | 11          | SHIP_001 |
 
 
Scenario: Test ShipmentInPortEvent is emitted when GpsReading indicates arrival at destination port
    When I submit the following transaction of type org.acme.shipping.perishable.GpsReading
        | shipment | readingTime | readingDate | latitude | latitudeDir | longitude | longitudeDir |
        | SHIP_001 | 120000      | 20171025    | 40.6840  | N           | 74.0062   | W            |
 
    Then I should have received the following event of type org.acme.shipping.perishable.ShipmentInPortEvent
        | message                                                                           | shipment |
        | Shipment has reached the destination port of /LAT:40.6840N/LONG:74.0062W | SHIP_001 |

最後に、package.json を変更して次に示すような内容にします。それには、package.json の内容全体を以下のリストで置き換えるのが最も簡単な方法です。

{
  "engines": {
    "composer": "^0.20.0"
  },
  "name": "iot-perishable-network",
  "version": "0.2.6",
  "description": "IoT Shipping Perishable Goods Business Network",
  "networkImage": "https://hyperledger.github.io/composer-sample-networks/packages/perishable-network/networkimage.svg",
  "networkImageanimated": "https://hyperledger.github.io/composer-sample-networks/packages/perishable-network/networkimageanimated.svg",
  "scripts": {
    "prepublish": "mkdirp ./dist && composer archive create  --sourceType dir --sourceName . -a ./dist/iot-perishable-network.bna",
    "pretest": "npm run lint",
    "lint": "eslint .",
    "postlint": "npm run licchk",
    "licchk": "license-check-and-add",
    "postlicchk": "npm run doc",
    "doc": "jsdoc --pedantic --recurse -c jsdoc.json",
    "test": "mocha -t 0 --recursive && cucumber-js",
    "deploy": "./scripts/deploy.sh"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/hyperledger/composer-sample-networks.git"
  },
  "keywords": [
    "shipping",
    "goods",
    "perishable",
    "composer",
    "composer-network"
  ],
  "author": "Hyperledger Composer",
  "license": "Apache-2.0",
  "devDependencies": {
    "chai": "^3.5.0",
    "composer-admin": "^0.20.0-0",
    "composer-cli": "^0.20.0-0",
    "composer-client": "^0.20.0-0",
    "composer-common": "^0.20.0-0",
    "composer-connector-embedded": "^0.20.0-0",
    "composer-cucumber-steps": "^0.20.0-0",
    "cucumber": "^2.2.0",
    "eslint": "^3.6.1",
    "istanbul": "^0.4.5",
    "jsdoc": "^3.5.5",
    "license-check-and-add": "~2.3.0",
    "mkdirp": "^0.5.1",
    "mocha": "^3.2.0",
    "moment": "^2.17.1",
    "sinon": "2.3.8",
    "cryptiles": ">=4.1.2",
    "growl": ">=1.10.0"
  },
  "license-check-and-add-config": {
    "folder": ".",
    "license": "LICENSE.txt",
    "exact_paths_method": "EXCLUDE",
    "exact_paths": [
      "composer-logs",
      "dist",
      "node_modules",
      "out",
      ".git",
      "markdown-license.txt",
      ".DS_Store",
      "features"
    ],
    "file_type_method": "EXCLUDE",
    "file_types": [
      ".yml"
    ],
    "insert_license": false,
    "license_formats": {
      "js|cto|acl": {
        "prepend": "/*",
        "append": " */",
        "eachLine": {
          "prepend": " * "
        }
      },
      "md": {
        "file": "./markdown-license.txt"
      }
    }
  }
}

2 つの新しい Node モジュール (42 行目と 43 行目) が package.json に追加されたことに注目してください。これらのモジュールをインストールするには、コマンドライン・ウィンドウ (Ubuntu の場合) またはターミナル・ウィンドウ (MacOS の場合) を開いて、npm install コマンドを実行します。

3d

単体テストを実行する

コマンドラインから nmp を実行して、単体テストを実行します。大量の出力が表示されますが、今回は Mocha テストに加え、Cucumber の機能 Scenario ごとに 1 つの出力ブロックが表示されます。Cucumber 機能テストは、次のように始まります (スペースの制約により、最初の 1 つだけを示しています)。

Feature: IoT Perishable Network
 
  Scenario: When the temperature range is within the agreed-upon boundaries
   Given I have deployed the business network definition ..
   And I have added the following participants
      """
      [
      {"$class":"org.acme.shipping.perishable.Grower", "email":"grower@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"USA"}, "accountBalance":0},
      {"$class":"org.acme.shipping.perishable.Importer", "email":"supermarket@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"UK"}, "accountBalance":0},
      {"$class":"org.acme.shipping.perishable.Shipper", "email":"shipper@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"Panama"}, "accountBalance":0}
      ]
      """
   And I have added the following asset of type org.acme.shipping.perishable.Contract
      | contractId | grower           | shipper               | importer              | arrivalDateTime  | unitPrice | minTemperature | maxTemperature | minPenaltyFactor | maxPenaltyFactor |
      | CON_001    | grower@email.com | supermarket@email.com | supermarket@email.com | 10/26/2018 00:00 | 0.5       | 2              | 10             | 0.2              | 0.1              |
   And I have added the following asset of type org.acme.shipping.perishable.Shipment
      | shipmentId | type    | status     | unitCount | contract |
      | SHIP_001   | BANANAS | IN_TRANSIT | 5000      | CON_001  |
   When I submit the following transactions of type org.acme.shipping.perishable.TemperatureReading
      | shipment | centigrade |
      | SHIP_001 | 4          |
      | SHIP_001 | 5          |
      | SHIP_001 | 10         |
   When I submit the following transaction of type org.acme.shipping.perishable.ShipmentReceived
      | shipment |
      | SHIP_001 |
   Then I should have the following participants
      """
      [
      {"$class":"org.acme.shipping.perishable.Grower", "email":"grower@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"USA"}, "accountBalance":2500},
      {"$class":"org.acme.shipping.perishable.Importer", "email":"supermarket@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"UK"}, "accountBalance":-2500},
      {"$class":"org.acme.shipping.perishable.Shipper", "email":"shipper@email.com", "address":{"$class":"org.acme.shipping.perishable.Address", "country":"Panama"}, "accountBalance":0}
      ]
      """

出力の最後の数行は次のようになっています。この出力は、単体テストが合格したことを意味します。

    .
    .
   And I have added the following asset of type org.acme.shipping.perishable.Shipment
      | shipmentId | type    | status     | unitCount | contract |
      | SHIP_001   | BANANAS | IN_TRANSIT | 5000      | CON_001  |
   When I submit the following transactions of type org.acme.shipping.perishable.TemperatureReading
      | shipment | centigrade |
      | SHIP_001 | 4          |
      | SHIP_001 | 5          |
      | SHIP_001 | 10         |
   When I submit the following transaction of type org.acme.shipping.perishable.GpsReading
      | shipment | readingTime | readingDate | latitude | latitudeDir | longitude | longitudeDir |
      | SHIP_001 | 120000      | 20171025    | 40.6840  | N           | 74.0062   | W            |
   Then I should have received the following event of type org.acme.shipping.perishable.ShipmentInPortEvent
      | message                                                                  | shipment |
      | Shipment has reached the destination port of /LAT:40.6840N/LONG:74.0062W | SHIP_001 |
 
6 scenarios (6 passed)
44 steps (44 passed)
0m02.788s
$

Cucumber での単体テストの詳細 {: #utc}

前のセクションにかなりの情報をつめ込んだことは自覚しているので、ここで時間をとって、詳しく説明したいと思います。まずは、Cucumber の概要を説明します。

Cucumber の概要

Cucumber は、ビヘイビア駆動型開発 (BDD) 向けに設計された単体テスト・ツールです。BDD はテスト駆動型 (TDD) に関連する開発方式ですが、コードの機能上の正確さだけではなく、アプリケーションの動作により重点を置いています。このことは捉えにくいながらも重要な違いです。

Cucumber のテスト・シナリオは、Gherkin という言語で作成します。前のセクションで目にしたとおり、構文はかなり単純なものです。

Feature : The application feature I want to test
  Background:
    Given some pre-condition that applies to each test
 
  Scenario: The test I want to run
      Given something
      And some other thing
      When I do XYZ
      Then ABC is the expected outcome

「ステップ定義」とは、Gherkin の単純な言語テキストのパターンを、テストを実行する実際のコードにリンクする小さなコードのことです。ステップ定義を作成しなければ、テストは実行されません。

Cucumber はキーワード WhenGivenThenAndBut のいずれかに突き当たると、キーワードに続くテキストを関連付けるステップ定義を探します。ちなみに、Cucumber はキーワードを区別しません。つまり、Cucumber にとって、すべてのキーワードはステップに過ぎないのです。言い換えると、Cucumber にとって、When ABCGiven ABC は両方とも「パターンが ABC となっているステップを見つけて実行する」ことを意味します。

例えば、Cucumber は Given I have added the following participants というテキストを見つけると、I have added the following というパターンと一致するステップを探し、見つかった場合はそのステップを実行します。見つからなければ、そのステップを担当者が作成して提供する必要があります。

幸い、Hyperledger Composer チームはすでに、Composer クライアント API の一般的な使用法のほとんどに対応するステップを提供しています。つまり、自分でコードを作成しなくても、これまでに目にしてきたような Gherkin 言語の Composer テストを作成できるということです!前のセクションで package.json に追加した JavaScript ライブラリー composer-cucumber-steps に、必要なコードが含まれています。

Cucumber には優れたドキュメントが用意されています。Cucumber について詳しく学ぶには、このリンク先の Cucumber ドキュメントにアクセスしてください。

4

改良後のネットワークを IBM Cloud にデプロイする

ネットワークを改良して単体テストを行いました。次は、オンラインの Playground にネットワークをロードして、IBM Cloud (https://composer-playground.mybluemix.net/) 上でネットワークとやり取りしましょう。

パート 1 で、Playground を操作して、Perishable Goods ボイラープレート・モデルでネットワークを定義し、モデルをインスタンス化し、インメモリー・ブロックチェーンにトランザクションを送信する方法を説明しました。このセクションでは、ビルド (つまり、npm install ) によって作成された、Perishable Goods ネットワークのビジネス・ネットワーク・アーカイブ (BNA) ファイルを使用し、Playground のインポート機能を使ってネットワークをデプロイします。けれどもその前に、コードにいくつかの変更を加えてからビルドを実行し、BNA ファイルを作成する必要があります。

4a

4a ビジネス・ネットワーク・アーカイブを作成する

コマンドライン・ウィンドウ (Ubuntu の場合) またはターミナル・ウィンドウ (MacOS の場合) を開いて、コマンドラインから npm install を実行します。これにより、ビルドが実行され、BNA ファイルが作成されます。次のような出力が表示されるはずです。

$ cd $COMPOSER_ROOT
$ pwd
/Users/sperry/HyperledgerComposer
$ cd developerWorks/perishable-network/
$ npm install
 

> perishable-network@0.2.6 prepublish /Users/sperry/HyperledgerComposer/IBM-Developer/Hyperledger/Composer/Basics/perishable-network
> mkdirp ./dist && composer archive create  --sourceType dir --sourceName . -a ./dist/perishable-network.bna

Creating Business Network Archive


Looking for package.json of Business Network Definition
	Input directory: /Users/sperry/HyperledgerComposer/IBM-Developer/Hyperledger/Composer/Basics/perishable-network

Found:
	Description: Shipping Perishable Goods Business Network
	Name: perishable-network
	Identifier: perishable-network@0.2.6

Written Business Network Definition Archive file to 
	Output file: ./dist/perishable-network.bna

Command succeeded
4b

IBM Cloud 上のオンライン Playground にモデルをインポートする

IBM Cloud 上のオンライン Playground (https://composer-playground.mybluemix.net/) にアクセスします。(今ではもう) お馴染みのウェルカム画面が表示されます。

図 4. IBM Cloud 上の Playground ウェルカム画面
IBM Cloud 上の Playground ウェルカム画面のスクリーンショット
IBM Cloud 上の Playground ウェルカム画面のスクリーンショット

ウェルカム画面が表示されない場合は、ブラウザーのローカル・ストレージをクリアしてください。

「Let's Blockchain (ブロックチェーンを開始)」ボタンをクリックして開始します。「My Business Networks (マイ・ビジネス・ネットワーク)」ビューが表示されたら、「Deploy a new business network (新しいビジネス・ネットワークをデプロイ)」をクリックします。

図 5. マイ・ビジネス・ネットワーク
IBM Cloud Composer Online Playground - 「My Business Networks          (マイ・ビジネス・ネットワーク)」ビューのスクリーンショット
IBM Cloud Composer Online Playground - 「My Business Networks (マイ・ビジネス・ネットワーク)」ビューのスクリーンショット

次に表示される画面で、「Drop here to upload or browse (アップロードまたは参照するには、ここにドロップ)」をクリックします。「File (ファイル)」ダイアログが開きます。$COMPOSER_ROOT/developerWorks/perishable-network/dist ディレクトリーまでナビゲートして、perishable-network.bna という名前のファイルの場所を指定して「Open (開く)」をクリックします。

図 6. 新規ビジネス・ネットワークのデプロイ
IBM Cloud Composer Online Playground - 新しいビジネス・ネットワークをデプロイする画面のスクリーンショット
IBM Cloud Composer Online Playground - 新しいビジネス・ネットワークをデプロイする画面のスクリーンショット

クリックしたタイルのタイトルが perishable-network に変わります。「Deploy (デプロイ)」ボタンをクリックしてモデルをデプロイします。

図 7. 新規ビジネス・ネットワークのデプロイ
IBM Cloud Composer Online      Playground - 新しいビジネス・ネットワークをデプロイする画面のスクリーンショット
IBM Cloud Composer Online Playground - 新しいビジネス・ネットワークをデプロイする画面のスクリーンショット

これで、IBM Cloud 内のオンライン Playground にモデルがデプロイされました。

4c

モデルとやり取りする

モデルとやり取りする方法は、このシリーズのパート 1 で説明したので十分にお馴染みのはずです。実際、オンラインの Playground は、パート 1 で使用したローカル Playground の IBM Cloud バージョンなので、モデルとやり取りする方法の説明を繰り返すことはしません。復習する必要がある場合は、パート 1 を参照してください。

Perishable Goods ビジネス・ネットワークを改良する」のセクションで、単体テストを実行して新しいモデル内のコードが機能することを確認しました。このセクションでも同じトランザクションをテストしますが、ここではオンラインの Playground を使用してモデルとやり取りし、JavaScript コンソールを使用してトランザクションを確認します。「Admin (管理)」カード上の「Connect now (今すぐ接続)」をクリックして開始してください。

まず、モデルをインスタンス化します。それには、ブラウザー内のアドレス・バーのすぐ下にある「Test (テスト)」タブをクリックします。「Submit Transaction (トランザクションを送信)」ボタンをクリックし、「SetupDemo」トランザクションを選択してから「Submit (送信)」をクリックします。

ここで、JavaScript コンソールを開きます。このコンソールを開く方法はブラウザーによって異なります。

次に、Shipment SHIP_001 の TemperatureReading トランザクションを、温度を摂氏 11 度に設定して送信します。摂氏 11 度は温度の上限しきい値を超えているため、TemperatureThresholdEvent がトリガーされるはずです (図 8 を参照)。

図 8. `TemperatureReading` トランザクションの送信
IBM Cloud      Composer Online Playground - TemperatureReading トランザクションを送信する画面のスクリーンショット
IBM Cloud Composer Online Playground - TemperatureReading トランザクションを送信する画面のスクリーンショット

コンソール内に次のメッセージが表示されたら、テストは合格しています (他にも多数のメッセージが出力されるので、注意して探してください)。

Temperature threshold violated! Emitting TemperatureEvent for shipment: SHIP_001

このメッセージは、イベントが正常に発行されたことを意味します (前に Cucumber の単体テストを実行して成功したので、すでにわかっていることです)。

今度は、Shipment SHIP_001 の GpsReading トランザクションを送信します。次のパラメーターを設定してください (図 9 を参照)。

  • readingTime = 171000
  • readingDate = 20181108
  • latitude = 40.6840
  • latitudeDir = N
  • lonGitude = 74.0062
  • lonGitudeDir = W
図 9. `GpsReading` トランザクションの送信
IBM Cloud Composer     Online Playground - GpsReading トランザクションを送信する画面のスクリーンショット
IBM Cloud Composer Online Playground - GpsReading トランザクションを送信する画面のスクリーンショット

JavaScript コンソールに、以下の出力が表示されるはずです。

Shipment has reached the destination port of /LAT:40.6840N/LONG:74.0062W

おめでとうございます!IBM Cloud 内でモデルが正常に実行されるようになりました。

パート 2 のまとめ

このチュートリアルでは、まず、コンピューター上にローカル Hyperledger Composer 開発用のツールをセットアップしました。Perishable Goods ネットワークを変更して新しいトランザクションと 2 つの新しいイベントを追加し、追加したイベントの単体テストを Cucumber で実行しました。

変更後の Perishable Goods ネットワークから Composer ビジネス・ネットワーク・アーカイブ (BNA) ファイルを作成し、IBM Cloud 上でホストされているオンラインの Playground にモデルをデプロイしてテストしました。

これで、パート 3 に進む準備ができました。パート 3 の目標は、さらにツールをインストールして REST インターフェースを生成し、Hyperledger Composer の力を強化することです。コンピューター上に Hyperledger Fabric をインストールして実行し、本番サーバーを使用する場合と同様に、コンピューター上で稼働する Perishable Goods ネットワークとのやり取りに使用できる GUI を生成します。パート 3 では Playground はもう使用しません!

このコンテンツは当初、2017年11月30日に IBM Developer 上で公開されたものです。


ダウンロード可能なリソース


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing
ArticleID=1066202
ArticleTitle=ブロックチェーン・ネットワークを改良してデプロイする
publish-date=07042019