继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Hyperledger Fabric(超级账本) Java 开发区块链 部署运行智能合约

汪汪一只猫
关注TA
已关注
手记 568
粉丝 129
获赞 718

部署并运行 Java 链代码示例

您已经定义并启动了本地区块链网络,而且已构建 Java shim 客户端 JAR 并安装到本地 Maven 存储库中,现在已准备好在之前下载的 Hyperledger Fabric 附带的一个 Java 链代码示例上构建、注册和调用交易。

部署并运行链代码

您将执行以下步骤:

  • 使用 Gradle 构建示例。

  • 通过运行 Gradle 构建软件为您创建的脚本,向验证对等网络注册该示例。

  • 使用 SoapUI 将示例部署到本地区块链网络。

  • 使用 SoapUI 在示例链代码上调用交易。

1.构建示例

导航到 $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example 目录。

接下来,通过命令行,使用此命令启动 Gradle 构建软件:

gradle -b build.gradle build

您会看到以下输出:

$ cd GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example
$ gradle -b build.gradle build
Starting a Gradle Daemon (subsequent builds will be faster):examples:chaincode:java:Example:compileJava:examples:chaincode:java:Example:processResources UP-TO-DATE:examples:chaincode:java:Example:classes:examples:chaincode:java:Example:jar:examples:chaincode:java:Example:startScripts:examples:chaincode:java:Example:distTar:examples:chaincode:java:Example:distZip:examples:chaincode:java:Example:assemble:examples:chaincode:java:Example:compileTestJava UP-TO-DATE:examples:chaincode:java:Example:processTestResources UP-TO-DATE:examples:chaincode:java:Example:testClasses UP-TO-DATE:examples:chaincode:java:Example:test UP-TO-DATE:examples:chaincode:java:Example:check UP-TO-DATE:examples:chaincode:java:Example:build:examples:chaincode:java:Example:copyToLib BUILD SUCCESSFUL Total time: 6.935 secs

该构建过程通过两种形式创建了一个位于目录 build/distributions 中的独立发行版:TAR 文件和 ZIP 文件,每个文件都包含运行链代码所需的所有资源,其中包括一个用于驱动链代码的名为 Example 的脚本。

Example 链代码现在已准备好向本地区块链网络注册。

2.注册示例

确保本地区块链网络正在运行。如果未运行,则需要启动它。如果需要温习一下相关内容,请参阅“启动区块链网络”部分。

如果您未在 $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example 目录下,请导航到这里。

接下来,将 Example.zip(或 Example.tar)解压到 build/distributions 目录中:

$ cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/java/Example
$ cd build/distributions/
$ unzip Example.zip 
Archive:  Example.zip  inflating: Example/lib/chaincode.jar  
  inflating: Example/lib/grpc-all-0.13.2.jar  
  inflating: Example/lib/commons-cli-1.3.1.jar  
  inflating: Example/lib/shim-client-1.0.jar  
  inflating: Example/lib/grpc-netty-0.13.2.jar  
  inflating: Example/lib/grpc-auth-0.13.2.jar  
  inflating: Example/lib/grpc-protobuf-nano-0.13.2.jar  
  inflating: Example/lib/grpc-core-0.13.2.jar  
  inflating: Example/lib/grpc-protobuf-0.13.2.jar  
  inflating: Example/lib/grpc-okhttp-0.13.2.jar  
  inflating: Example/lib/grpc-stub-0.13.2.jar  
  inflating: Example/lib/protobuf-java-3.0.0.jar  
  inflating: Example/lib/netty-tcnative-boringssl-static-1.1.33.Fork21-osx-x86_64.jar  
  inflating: Example/lib/netty-codec-http2-4.1.0.CR3.jar  
  inflating: Example/lib/google-auth-library-oauth2-http-0.3.0.jar  
  inflating: Example/lib/guava-18.0.jar  
  inflating: Example/lib/protobuf-javanano-3.0.0-alpha-5.jar  
  inflating: Example/lib/jsr305-3.0.0.jar  
  inflating: Example/lib/okio-1.6.0.jar  
  inflating: Example/lib/okhttp-2.5.0.jar  
  inflating: Example/lib/netty-codec-http-4.1.0.CR3.jar  
  inflating: Example/lib/netty-handler-4.1.0.CR3.jar  
  inflating: Example/lib/google-auth-library-credentials-0.3.0.jar  
  inflating: Example/lib/google-http-client-1.19.0.jar  
  inflating: Example/lib/google-http-client-jackson2-1.19.0.jar  
  inflating: Example/lib/netty-codec-4.1.0.CR3.jar  
  inflating: Example/lib/netty-buffer-4.1.0.CR3.jar  
  inflating: Example/lib/netty-transport-4.1.0.CR3.jar  
  inflating: Example/lib/httpclient-4.0.1.jar  
  inflating: Example/lib/jackson-core-2.1.3.jar  
  inflating: Example/lib/netty-common-4.1.0.CR3.jar  
  inflating: Example/lib/netty-resolver-4.1.0.CR3.jar  
  inflating: Example/lib/httpcore-4.0.1.jar  
  inflating: Example/lib/commons-logging-1.1.1.jar  
  inflating: Example/lib/commons-codec-1.3.jar  
  inflating: Example/bin/Example     
  inflating: Example/bin/Example.bat

您可能想知道 “为何有如此多的文件?”该发行版包含(在独立进程中)单独运行链代码所需的一切资源,以及所有依赖 JAR 文件。

要注册链代码示例,可在 build/distributions 文件夹中执行以下脚本:

./Example/bin/Example

这会运行一个独立进程来向本地区块链网络注册链代码示例。您会看到以下终端窗口输出:

$ ./Example/bin/Example
Hello world! starting [Ljava.lang.String;@7ef20235Feb 22, 2017 10:05:08 AM example.Example mainINFO: starting
Feb 22, 2017 10:05:08 AM org.hyperledger.java.shim.ChaincodeBase newPeerClientConnectionINFO: Inside newPeerCLientConnection
Feb 22, 2017 10:05:08 AM io.grpc.internal.TransportSet$1 callINFO: Created transport io.grpc.netty.NettyClientTransport@3dd7b80b(/127.0.0.1:7051) for /127.0.0.1:7051Feb 22, 2017 10:05:14 AM io.grpc.internal.TransportSet$TransportListener transportReadyINFO: Transport io.grpc.netty.NettyClientTransport@3dd7b80b(/127.0.0.1:7051) for /127.0.0.1:7051 is ready

查看本地区块链网络的控制台,您会看到以下输出行:

.
.vp0_1         | 16:05:14.048 [chaincode] HandleChaincodeStream -> DEBU 06d Current context deadline = 0001-01-01 00:00:00 +0000 UTC, ok = falsevp0_1         | 16:05:14.065 [chaincode] processStream -> DEBU 06e []Received message REGISTER from shimvp0_1         | 16:05:14.065 [chaincode] HandleMessage -> DEBU 06f []Handling ChaincodeMessage of type: REGISTER in state createdvp0_1         | 16:05:14.065 [chaincode] beforeRegisterEvent -> DEBU 070 Received REGISTER in state createdvp0_1         | 16:05:14.065 [chaincode] registerHandler -> DEBU 071 registered handler complete for chaincode hellovp0_1         | 16:05:14.065 [chaincode] beforeRegisterEvent -> DEBU 072 Got REGISTER for chaincodeID = name:"hello" , sending back REGISTERED
.
.

记下注册日志输出中的 chaincodeID name(示例中为 hello;如上面 第 8 行 所示)。以后在通过结构的 REST 接口部署 Example 链代码时,JSON 消息中需要使用此信息。

上面的输出表明 Example 链代码正在运行,而且已向本地区块链验证对等网络注册,并做好了部署准备。

3.部署示例

Hyperledger Fabric 提供了一个用于与该结构交互的 REST Web 服务接口。与 fabric 的第一次交互是部署链代码。确保本地区块链网络正在运行,然后启动 SoapUI,单击 REST 按钮创建一个新的 REST 项目。您会看到一个类似图 3 的对话框,在其中输入用于所有 REST 请求的基础 URL:

输入 http://localhost:7050 作为 URL,然后单击 OK。端口 7050 是 fabric 使用的默认 REST 端口,而且因为区块链网络是在本地计算机上运行的,所以将使用 localhost 作为主机名。

在 SoapUI 启动后,可以执行一次快速冒烟测试,以确保它能与本地区块链网络进行通信。展开刚创建的新的 REST 资源,直到看到 Request 1,然后在 Editor 窗口中打开它。使用 GET 方法,在 resource 下输入 /chain。确保单击了 output 选项卡上的 JSON 选项,然后运行请求(通过单击 arrow 图标)。执行此请求时,会在 Editor 窗口右侧的输出选项卡中返回当前区块的哈希值,如图 4 所示:

如果看到一条类似图 4 的 JSON 消息(当然您的网络的 currentBlockHash 值会有所不同),那么您已准备好部署 Example 链代码。

右键单击 REST Project 1 (http://localhost:7050) 下的端点并选择 New Resource;您会看到一个包含 Resource Path 字段的 “New REST Resource” 对话框(参见图 5):

输入 /chaincode 作为 resource path,然后单击 OK,您会看到 SoapUI Projects 面板中显示了新资源。打开对此资源的请求(默认情况下该请求名为 Request 1),将方法更改为 POST,并将此 JSON 粘贴到请求编辑器窗口左下角的请求区域:

{"jsonrpc": "2.0",  "method": "deploy",  "params": {    "type": 1,    "chaincodeID":{        "name": "hello"
    },    "CtorMsg": {        "args": [""]
    }
  },  "id": 1}

有 3 点需要注意:

第 3 行:method 值必须为 deploy。
第 6-7 行:JSON 消息中的 chaincodeID.name 必须与您在上一节中注册 Example 链代码时所用的 chaincodeID 匹配(在 Example 链代码中,该值为 hello)。
第 13 行:id 值用于协调请求。本教程不需要过多地考虑它,但要注意的是,在响应中始终会发送回该值(参见下一个清单)。
提交此请求时,JSON 输出应如下所示:

{   "jsonrpc": "2.0",   "result":    {      "status": "OK",      "message": "hello"
   },   "id": 1}

图 6 给出了 SoapUI 中的输出的屏幕截图。JSON 输出消息会显示在输出选项卡中,该选项卡位于请求编辑器的右侧。

终端窗口中的网络日志输出应包含以下行:

.
.
vp0_1         | 20:48:39.482 [rest] ProcessChaincode -> INFO 0c4 REST processing chaincode request...
vp0_1         | 20:48:39.482 [rest] processChaincodeDeploy -> INFO 0c5 REST deploying chaincode...
vp0_1         | 20:48:39.483 [devops] Deploy -> DEBU 0c6 Creating deployment transaction (hello)
vp0_1         | 20:48:39.483 [devops] Deploy -> DEBU 0c7 Sending deploy transaction (hello) to validator
vp0_1         | 20:48:39.483 [peer] sendTransactionsToLocalEngine -> DEBU 0c8 Marshalling transaction CHAINCODE_DEPLOY to send to local engine
vp0_1         | 20:48:39.483 [peer] sendTransactionsToLocalEngine -> DEBU 0c9 Sending message CHAIN_TRANSACTION with timestamp seconds:1487796519 nanos:483661510  to local engine
vp0_1         | 20:48:39.483 [consensus/noops] RecvMsg -> DEBU 0ca Handling Message of type: CHAIN_TRANSACTION 
vp0_1         | 20:48:39.483 [consensus/noops] broadcastConsensusMsg -> DEBU 0cb Broadcasting CONSENSUS
vp0_1         | 20:48:39.483 [peer] Broadcast -> DEBU 0cc Broadcast took 1.135s
vp0_1         | 20:48:39.483 [consensus/noops] RecvMsg -> DEBU 0cd Sending to channel tx uuid: hello
vp0_1         | 20:48:39.483 [rest] processChaincodeDeploy -> INFO 0ce Successfully deployed chainCode: hello
vp0_1         | 20:48:39.484 [rest] ProcessChaincode -> INFO 0cf REST successfully deploy chaincode: {"jsonrpc":"2.0","result":{"status":"OK","message":"hello"},"id":1}
.
.

第 3-4 行显示了输出,表明网络已收到部署消息,并且该结构正在部署链代码。第 13-14 行表明链代码已成功部署。

在运行链代码的终端窗口中,可以注意到以下输出:

$ ./build/distributions/Example/bin/Example
Hello world! starting [Ljava.lang.String;@7ef20235Feb 22, 2017 2:44:43 PM example.Example main
INFO: starting
Feb 22, 2017 2:44:43 PM org.hyperledger.java.shim.ChaincodeBase newPeerClientConnection
INFO: Inside newPeerCLientConnection
Feb 22, 2017 2:44:43 PM io.grpc.internal.TransportSet$1 callINFO: Created transport io.grpc.netty.NettyClientTransport@46adccd3(/127.0.0.1:7051) for /127.0.0.1:7051Feb 22, 2017 2:44:48 PM io.grpc.internal.TransportSet$TransportListener transportReady
INFO: Transport io.grpc.netty.NettyClientTransport@46adccd3(/127.0.0.1:7051) for /127.0.0.1:7051 is ready
Feb 22, 2017 2:48:40 PM example.Example runINFO: In run, function:
Feb 22, 2017 2:48:40 PM example.Example run

我包含了所有上下文输出,在向区块链网络发送部署消息时,您会看到类似第 11-13 行的消息。

4.在示例上调用交易

最后,将会调用 hello 方法,可以看到它会在运行链代码的终端窗口的日志消息中显示出来。

在 SoapUI 中的 chaincode 资源下,右键单击 Method 1 并选择 Clone Method。将该方法命名为 Invoke,然后单击 OK。打开新的 Invoke 方法下的 Request 1,并粘贴到以下 JSON 请求中:

{"jsonrpc": "2.0",  "method": "invoke",  "params": {    "type": 1,    "chaincodeID":{        "name": "hello"
    },    "CtorMsg": {        "args": ["hello"]
    }
  },  "id": 2}

运行该请求时,会看到以下 JSON 响应:

{ "jsonrpc":"2.0", "result": { "status":"OK", "message":"1c1811d0-a958-4c58-ab1d-e1df550c18a3" }, "id":2 }

图 7 给出了 SoapUI 中的输出的屏幕截图

网络日志输出应包含以下行:

..vp0_1         | 21:44:35.143 [rest] ProcessChaincode -> INFO 555 REST processing chaincode request...
vp0_1         | 21:44:35.143 [rest] processChaincodeInvokeOrQuery -> INFO 556 REST invoke chaincode...
vp0_1         | 21:44:35.143 [devops] invokeOrQuery -> INFO 557 Transaction ID: 1c1811d0-a958-4c58-ab1d-e1df550c18a3
vp0_1         | 21:44:35.143 [devops] createExecTx -> DEBU 558 Creating invocation transaction (1c1811d0-a958-4c58-ab1d-e1df550c18a3)
vp0_1         | 21:44:35.143 [devops] invokeOrQuery -> DEBU 559 Sending invocation transaction (1c1811d0-a958-4c58-ab1d-e1df550c18a3) to validator
vp0_1         | 21:44:35.143 [peer] sendTransactionsToLocalEngine -> DEBU 55a Marshalling transaction CHAINCODE_INVOKE to send to local engine
vp0_1         | 21:44:35.143 [peer] sendTransactionsToLocalEngine -> DEBU 55b Sending message CHAIN_TRANSACTION with timestamp seconds:1487799875 nanos:143438691  to local engine
vp0_1         | 21:44:35.143 [consensus/noops] RecvMsg -> DEBU 55c Handling Message of type: CHAIN_TRANSACTION 
vp0_1         | 21:44:35.143 [consensus/noops] broadcastConsensusMsg -> DEBU 55d Broadcasting CONSENSUS
vp0_1         | 21:44:35.143 [peer] Broadcast -> DEBU 55e Broadcast took 1.249s
vp0_1         | 21:44:35.143 [consensus/noops] RecvMsg -> DEBU 55f Sending to channel tx uuid: 1c1811d0-a958-4c58-ab1d-e1df550c18a3
vp0_1         | 21:44:35.143 [rest] processChaincodeInvokeOrQuery -> INFO 560 Successfully submitted invoke transaction with txid (1c1811d0-a958-4c58-ab1d-e1df550c18a3)
vp0_1         | 21:44:35.143 [rest] ProcessChaincode -> INFO 561 REST successfully submitted invoke transaction: {"jsonrpc":"2.0","result":{"status":"OK","message":"1c1811d0-a958-4c58-ab1d-e1df550c18a3"},"id":2}..

链代码日志输出如下所示:

$ ./build/distributions/Example/bin/Example
Hello world! starting [Ljava.lang.String;@7ef20235Feb 22, 2017 3:26:57 PM example.Example main
INFO: starting
Feb 22, 2017 3:26:57 PM org.hyperledger.java.shim.ChaincodeBase newPeerClientConnection
INFO: Inside newPeerCLientConnection
Feb 22, 2017 3:26:57 PM io.grpc.internal.TransportSet$1 callINFO: Created transport io.grpc.netty.NettyClientTransport@765e4953(/127.0.0.1:7051) for /127.0.0.1:7051Feb 22, 2017 3:27:02 PM io.grpc.internal.TransportSet$TransportListener transportReady
INFO: Transport io.grpc.netty.NettyClientTransport@765e4953(/127.0.0.1:7051) for /127.0.0.1:7051 is ready
Feb 22, 2017 3:27:24 PM example.Example runINFO: In run, function:
Feb 22, 2017 3:27:24 PM example.Example runSEVERE: No matching case for function:
Feb 22, 2017 3:30:55 PM example.Example runINFO: In run, function:hello
hello invoked

我再次给出了所有链代码输出。您可以看到哪些地方(第 16 行)调用了 hello 函数。

现在您已知道如何在本地区块链网络上构建、部署和运行 Java 链代码。在下一节中,将会使用 Eclipse IDE(几乎)从头编写一个链代码程序,使用 Gradle 构建该链代码程序,然后使用 SoapUI 体验它。


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP