shohu / estate-sample

Read-only mirror of https://gerrit.hyperledger.org/r/#/admin/projects/fabric-samples
https://hyperledger.org
Apache License 2.0
0 stars 0 forks source link

Node.js が使えるクライアントアプリを見つけてfabric libを使う #11

Closed shohu closed 5 years ago

shohu commented 5 years ago

デスクトップアプリ編

5 Best JavaScript Frameworks for Desktop Apps

  1. Electron
  2. NW.js  JavaScriptを用いてWindows上で動作するアプリケーションを実装できるフレームワーク  NW.jsでデスクトップアプリの夢を見る!
  3. AppJS
  4. Meteor
  5. Proton Native  react に似せて作られているとのこと。これがよさそうか?

Mobile アプリ編

TOP JAVASCRIPT FRAMEWORKS FOR NATIVE MOBILE APPS 2019

  1. ReactNative  node の core 使えない
shohu commented 5 years ago

Electronが良さそう、、、一番開発が活発。

shohu commented 5 years ago

Electronでアプリケーションを作ってみよう

install

$ npm -g install electron

初期設定

$ mkdir electron-estate
$ cd electron-estate
$ npm init -y

参考ページの index.html, index.js を用意して

electron .

したら以下が表示。スムース 👍 スクリーンショット 2019-06-13 16 29 57

shohu commented 5 years ago

ElectronのメニューからJavaScript呼び出し 以下でsourceをdl

git clone https://github.com/atom/electron-quick-start

そのあと、js の renderer.js に alert書き込んだら動いた。ここにfabric lib を読み込ませる。

ただ、 const fs = require('fs') とやっただけで、alertが発生しなくなる、、、

const fs = require('fs')
alert('aaa');

debugをしなければ

shohu commented 5 years ago

Electronの環境構築とVisual Studio Codeでデバッグする方法

debugしようとすると以下エラー スクリーンショット 2019-06-13 17 21 55

以下に lunch.json を置き換える

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
           "name": "Debug",
           "type": "node",
           "request": "launch",
           "cwd": "${workspaceRoot}",
            //    "program": "${workspaceRoot}/main.js",
            //    "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
           "runtimeExecutable": "/Users/shohu33/.nodebrew/current/bin/electron",
           "runtimeArgs": [
               "--enable-logging"
           ],
           "args": [
               "."
           ],
           "windows": {
               "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
           },
           "console":"integratedTerminal",
        }
     ]

}

すると vscodeのconsoleに以下エラー

"Uncaught ReferenceError: require is not defined", source: file:///Users/shohu33/sc/electron-quick-start/renderer.js (4)

require が使えないと。 そうか、browserで呼び出すjsではそりゃ無理だ

shohu commented 5 years ago

試しに以下のような const で fabric の lib 読み込むjs作って、main.jsから呼び出してみる

const fs = require('fs')
const path = require('path')

const FabricCAService = require('fabric-ca-client')
const Client = require('fabric-client')
const hash = require('fabric-client/lib/hash')

const jsrsa = require('jsrsasign')
const { KEYUTIL } = jsrsa
const elliptic = require('elliptic')
const EC = elliptic.ec

function demo() {
    alert('demo!!!');
}

exports.default = demo;

すると、以下エラー

Error: Failed to load gRPC binary module because it was not installed for the current system Expected directory: electron-v5.0-darwin-x64-unknown Found: [node-v57-darwin-x64-unknown] This problem can often be fixed by running "npm rebuild" on the current system Original error: Cannot find module '/Users/shohu33/sc/electron-quick-start/node_modules/grpc/src/node/extension_binary/electron-v5.0-darwin-x64-unknown/grpc_node.node'

npm rebuild 試してみたが、変わらず。

以下に解決策? https://stackoverflow.com/questions/52156883/error-with-firebase-on-electron-app-failed-to-load-grpc

どうも node の version あわせて rebuild する必要があると

$ npm rebuild --runtime=electron --target=8.16.0

をやったが、以下エラー

/Users/shohu33/.node-gyp/8.16.0/include/node/openssl/e_os2.h:276:11: error: 'OPENSSL_EXPORT' macro redefined
      [-Werror,-Wmacro-redefined]
#  define OPENSSL_EXPORT extern
          ^
shohu commented 5 years ago

electron / electron-vueでgRPCを使う これを試してみたが

$ yarn add grpc  electron-rebuild
$ ./node_modules/.bin/electron-rebuild

同じエラー

../deps/grpc/third_party/boringssl/include/openssl/base.h:143:9: error: 'OPENSSL_THREADS' macro redefined [-Werror,-Wmacro-redefined]
#define OPENSSL_THREADS

さらに下みると grpc の 1.17.0 がよばれている。これが 1.21.1 じゃないと最新じゃない。 これ、どうも node 8系つかってたからっぽい、、、、が、fabric 8系じゃないとだめなんじゃなかったっけか。

npm ERR! grpc@1.17.0 install: `node-pre-gyp install --fallback-to-build --library=static_library`
npm ERR! Exit status 1

以下のようにelectrumを4系にしたら通ったので一旦これで進める。

$ node -v
v8.16.0
$ yarn add electron@4.1.0
$ npm rebuild --target=4.1.0 --runtime=electron --dist-url=https://atom.io/download/electron
shohu commented 5 years ago

offline署名のtestを試す

CAをBYFNで立ち上げる。 -a というオプションつけるとCAも立ち上がる

./byfn.sh up -a -l node

CAのportは以下

    ports:
      - "7054:7054"
: 
    ports:
      - "8054:8054"

実行すると以下部分で

  const sendSignedProposalReq = {signedProposal, targets}
  const proposalResponses = await channel.sendSignedProposal(sendSignedProposalReq)

https://fabric-sdk-node.github.io/release-1.3/Channel.html#.sendSignedProposal__anchor

以下エラー

E0617 10:26:29.098517000 4304881088 ssl_transport_security.cc:1229] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.

以下で同じようにはまってる人が Generic ("*") wildcard certificates aren't accepted

証明書が違う??

そうか、そもそもtestがbyfn用のnetworkに作られていないので証明書など指定しなおす必要があるな

carfabのsmartcontractをインストール

以下を使ってインストールしておく https://github.com/shohu/estate-sample/blob/release-1.4/fabcar/startFabric.sh

./startFabric.sh javascript

Admin と User の wallet作成して秘密鍵などを手に入れておく

$ node enrollAdmin.js
Wallet path: /Users/shohu33/sc/estate-sample/fabcar/javascript/wallet
Successfully enrolled admin user "admin" and imported it into the wallet
$ node registerUser.js
Wallet path: /Users/shohu33/sc/estate-sample/fabcar/javascript/wallet
Successfully registered and enrolled admin user "user1" and imported it into the wallet

certは、user1というファイルができるのでその箇所の"BEGIN CERTIFICATE"から"END CERTIFICATE"を抜き出して取得

shohu commented 5 years ago

byfn.sh の環境でテストが動かないので、sdk環境でテストをまず動かして、その環境にelectrumもってくることを試してみる

秘密鍵など作成

以下を動かしておく https://github.com/hyperledger/fabric-sdk-node/blob/release-1.4/test/fixtures/crypto-material/generateAll.sh

コンテナ起動

$ cd fabric-sdk-node/test/fixtures/docker-compose
$ docker-compose up -d
$ docker ps
CONTAINER ID        IMAGE                        COMMAND                  CREATED             STATUS              PORTS                                        NAMES
a9fcfd970fca        hyperledger/fabric-peer      "peer node start"        5 seconds ago       Up 3 seconds        0.0.0.0:8051->8051/tcp                       peer0.org2.example.com
e01292affe52        hyperledger/fabric-peer      "peer node start"        5 seconds ago       Up 3 seconds        0.0.0.0:7051->7051/tcp                       peer0.org1.example.com
397b52e9b888        hyperledger/fabric-couchdb   "tini -- /docker-ent…"   7 seconds ago       Up 5 seconds        4369/tcp, 9100/tcp, 0.0.0.0:6984->5984/tcp   couchdb.org2.example.com
e3cd7d6de665        hyperledger/fabric-ca        "sh -c 'fabric-ca-se…"   7 seconds ago       Up 5 seconds        0.0.0.0:8054->7054/tcp                       ca1.example.com
c5d1a21b2943        hyperledger/fabric-ca        "sh -c 'fabric-ca-se…"   7 seconds ago       Up 5 seconds        0.0.0.0:7054->7054/tcp                       ca0.example.com
95765caced97        hyperledger/fabric-couchdb   "tini -- /docker-ent…"   7 seconds ago       Up 5 seconds        4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp   couchdb.org1.example.com

test

test実行して以下エラー

$ node signTransactionOffline.js
TAP version 13
: 
2019-06-17T05:46:44.855Z - error: [FabricCAClientService.js]: Failed to enroll admin, error:%o message=Calling enrollment endpoint failed with error [Error: write EPROTO 4484330944:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:../deps/openssl/openssl/ssl/s23_clnt.c:827:

これはcaのdocker-composeに以下パラメータ入れた。byfnを参照した

エラー対応 : routines:SSL3_GET_RECORD:wrong

次は以下エラー Handshake failed with fatal error SSL_ERROR_SSL: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number.

echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile

結局以下に変更。

  1. grpcs -> grpc
        // 'grpcs://localhost:7051',
        'grpc://localhost:7051',
  1. https -> http
    // const caService = new FabricCAService('https://localhost:7054', tlsOptions, 'ca-org1');
    const caService = new FabricCAService('http://localhost:7054', tlsOptions, 'ca-org1');
  1. FABRIC_CA_SERVER_TLS_ENABLEDをfalse. docker-compose.yaml
      - FABRIC_CA_SERVER_TLS_ENABLED=false

エラー対応 : access denied: channel [mychannel] creator org [Org1MSP]

以下のような対応が必要だと想われる。

 ____    _____      _      ____    _____
/ ___|  |_   _|    / \    |  _ \  |_   _|
\___ \    | |     / _ \   | |_) |   | |
 ___) |   | |    / ___ \  |  _ <    | |
|____/    |_|   /_/   \_\ |_| \_\   |_|

Build your first network (BYFN) end-to-end test

Channel name : mychannel
Creating channel...
+ peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

これは、fabcarの中のstartFabric.shにchannel作成があった。 これをそのまま使うことにした。

Error: 2 UNKNOWN

2019-06-17T07:10:33.623Z - info: [Peer.js]: sendProposal - Received proposal response from: grpc://localhost:7051 status: Error: 2 UNKNOWN: Stream removed fabric call --- 2.5 [ { Error: 2 UNKNOWN: Stream removed

https://github.com/hyperledger/composer/issues/4305

fabcarのディレクトリをもってきたやってもいっしょだ。うまくいかない。

shohu commented 5 years ago

以下の方法で offline署名のscriptが動いた 👍

  1. sampleソースから以下持ち込む  - chaincode  - first-network  - fabcar
  2. ネットワーク構築  cd ./fabcar  ./startFabric.sh javascript
  3. ソースを以下に修正  - ユーザーの privateKeyPathなどは、first-network/crypto-configの下のファイルにあわせる  - peer, ordererも同じく first-network/crypto-configの下のファイルにあわせる  - chaincode呼び出しを以下のようにfabcarのchaincodeに変更
    const transactionProposalReq = {
    fcn: 'createCar',
    args: ['CAR12', 'Honda', 'Accord', 'Black', 'Tom'],
    chaincodeId: 'fabcar',
    channelId: 'mychannel'
    }
  4. 起動
    $ yarn start
    yarn run v1.15.2
    $ electron .
    : 
    Successfully build commit transaction proposal
    2019-06-17T08:33:25.876Z - info: [Remote.js]: Successfully connected to remote gRPC server
    Successfully commit should response success { status: 'SUCCESS', info: '' }
    Successfully registered event for e48ff071bf55e36bb82c9e5b2e655fc5de694075b4bb39ced15b13472689ad68
    Successfully called connect on localhost:7051
    Event has been seen with transaction code:ENDORSEMENT_POLICY_FAILURE for transaction id:e48ff071bf55e36bb82c9e5b2e655fc5de694075b4bb39ced15b13472689ad68 for blockNum:7
    Successfully transactionMonitor
shohu commented 5 years ago

estateのchaincodeをインストール

  1. chaincodeのestateフォルダを、PJのchaincode配下にもってくる
  2. estateフォルダ内で npm install
  3. fabcarのstartFabric.shを改造して estate用にする。
  4. node estate.js で estateのchaincodeを呼び出せるように改造

offlineからestateのchaincodeの呼び出し できた 👍

$ node estate.js
Successfully build endorse transaction proposal
Successfully build commit transaction proposal
Successfully commit should response success { status: 'SUCCESS', info: '' }
Successfully registered event for da5a3afb03e5dc25e276af3ac5f619dc5f8f764c5619ec9d26c69f01550e40b9
Successfully called connect on localhost:7051
Event has been seen with transaction code:ENDORSEMENT_POLICY_FAILURE for transaction id:da5a3afb03e5dc25e276af3ac5f619dc5f8f764c5619ec9d26c69f01550e40b9 for blockNum:4
Successfully transactionMonitor
Estate program complete.
shohu commented 5 years ago

Event has been seen with transaction code:ENDORSEMENT_POLICY_FAILURE for transaction id:edbc1615124a8aed88c0c666b1876e9d0d05223e01f3d9ad0a2667cab0c6948c for blockNum:6

こちらがエラーであるため、データ登録できていなかった 😢

https://stackoverflow.com/questions/52773566/hyperledger-fabric-client-endorsement-policy-failure ここによると

This likely occurred because when you need multiple peers from different orgs to have the transaction be sent to, the endorsement policy is AND.

であるとのこと。2つのpeerをあげてないからだめ?initiate は org1だけだから AND から OR にすればいいんだか。

該当箇所はおそらく以下

docker exec \
  -e CORE_PEER_LOCALMSPID=Org1MSP \
  -e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \
  cli \
  peer chaincode instantiate \
    -o orderer.example.com:7050 \
    -C mychannel \
    -n $CHAINCODE_ID \
    -l "$CC_RUNTIME_LANGUAGE" \
    -v $VERSION \
    -c '{"Args":["org.estatenet.estatecontract:instantiate"]}' \
    -P "AND('Org1MSP.member','Org2MSP.member')" \
    --tls \
    --cafile ${ORDERER_TLS_ROOTCERT_FILE} \
    --peerAddresses peer0.org1.example.com:7051 \
    --tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE}

テストなのでこちらの -P の部分を AND から OR にする。

うまくいった 👍

$ node estate.js create
Successfully build endorse transaction proposal
Successfully build commit transaction proposal
Successfully commit should response success { status: 'SUCCESS', info: '' }
Successfully registered event for 158ff78adb2e7ddbcb1306521c12e8a537b309934e9d1a6ed33bf60d6090f1f3
Successfully called connect on localhost:7051
Event has been seen with transaction code:VALID for transaction id:158ff78adb2e7ddbcb1306521c12e8a537b309934e9d1a6ed33bf60d6090f1f3 for blockNum:4
Successfully transactionMonitor
Estate program complete.
shohu commented 5 years ago

find などの参照するだけのmethodがうまくいかない

$ node estate.js find
======== find !!!!!
Successfully build endorse transaction proposal
Successfully build commit transaction proposal
Successfully commit should response success { status: 'SUCCESS', info: '' }
Successfully registered event for fc3ada8c75d8196c0168af0241a3d3dec09bfce407002fb222b9b22fce41308d
Successfully called connect on localhost:7051
Event has been seen with transaction code:VALID for transaction id:fc3ada8c75d8196c0168af0241a3d3dec09bfce407002fb222b9b22fce41308d for blockNum:7
Successfully transactionMonitor
Estate program complete.

こんな感じでどうも block が進んでいます。transaction を発行しないようなmethodがありそう。 fabcar は evaluateTransaction で実行している。これにあたるもの

        const result = await contract.evaluateTransaction('queryAllCars');

以下は使える?

https://fabric-sdk-node.github.io/release-1.4/Channel.html#queryByChaincode__anchor

    var request = {
        fcn: 'find',
        args: [
            'apart',
            '000001',
        ],
        chaincodeId: 'estate',
        channelId: 'mychannel',
    };
    let response_payloads = await channel.queryByChaincode(request);
    if (response_payloads) {
        console.log("========", response_payloads);
    }
    return;

上記を試してみたが

Error: No identity has been assigned to this client

がでてしまう。channelに何か設定する必要があるんかな、、、

他のsampleだとchannel を以下のように作成していて、clientをまず作ってる。たぶん、これにidentify設定しているんだろうな。

        client = await helper.getClientForOrg(org_name, username);
        logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
        channel = client.getChannel(channelName);
shohu commented 5 years ago

https://stackoverflow.com/questions/56646247/how-do-i-get-fabcar-object-response-at-offline-process に答えに書いた

const proposalResponses = await channel.sendSignedProposal(sendSignedProposalReq);

ここでresponse取れる