fabric2.环境部署

1.0前期硬件资源准备

1.1硬件环境整理

准备虚机:分别分配2G内存、2核CPU、20G硬盘资源,网络连接方式为仅主机模式,为使用方便,统一设置root密码为root,普通用户名对应的密码为123456。

主机名 IP 使用情况 备注
p1 192.168.11.130 ZK1、Kafka1、Orderer1、Peer1
p2 192.168.11.133 ZK2、Kafka2、Orderer2、Peer2
p3 192.168.11.131 ZK3、Kafka3、Orderer3、Peer3
p4 192.168.11.132 Kafka4、Peer4、Peer4

1.2虚拟机网络配置

为了实现主机与虚拟机的Linux系统互连,可以对虚拟机进行设置,达到目的。

VMware的网络连接模式有三种:
1、仅主机模式:也就是host_only,这种模式仅仅只让虚拟机与本地物理机通信,不可以上网;
2、NAT模式:这种模式保留仅主机模式的功能下,还能让主机上网;
3、桥接模式:直接让虚拟机使用本地主机的网卡上网。

使用“仅主机模式”,简单的实现虚拟机与本地物理机器通信,只用修改VMnet1就可以。

第一步:

打开VMware菜单,【虚拟机】–【设置】,选择网络适配器的网络链接,我们使用仅主机模式。

第二步:

打开VMware,菜单【编辑】–【虚拟网络编辑器】

第三步:

打开VMware中安装的centos,将ip地址设置到和VMnet1处于同一个网段。

打开ifcfg-ens33,默认是动态获取IP地址,可以手动设置如下(记得在root用户下):

第四步:

重启网卡,使用命令systemctl restart network,然后查看本地的IP地址,就可以实现互联。

第五步:配置host文件

配置主机host:

将配置发送到其他主机(同时在其他主机上配置):

第六步:为了后期复制文件方便,我们需要设置机器间的免密

  1. 设置p1主机的SSH免秘钥
    [root@p1 network-scripts]# cd ~
    [root@p1 ~]# ssh-keygen -t rsa
    [root@p1 ~]# ssh-copy-id p1
    [root@p1 ~]# ssh-copy-id p2
    [root@p1 ~]# ssh-copy-id p3
    [root@p1 ~]# ssh-copy-id p4

2、同理,分别设置p2、p3、p4免密。

第七步:配置虚拟机外网连接

1、保证VMware Network Adapter VMnet1是启用状态

2、将可以连接外网的连接共享属性设置成如下图所示

3、将VMware Network Adapter VMnet1的IP地址设置成与本机IP不同的网段即可

4、linux网络配置如下,同样保持一致

5.通过文件配置如下

6、测试网络连接

7、按照上述步骤分别检查4台机器的网络连接状态。

2.0Fabric入门

2.1先决条件

2.1.1Linux系统内核升级

升级Linux内核

yum update -y

查看内核版本

cat /proc/version

查看系统版本

cat /etc/issue

2.1.2安装git

yum install git 

查看git版本

git version

2.1.3安装cURL

在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具。它支持文件的上传和下载,是综合传输工具,但按传统,习惯称url为下载工具。具体参考连接

https://www.cnblogs.com/duhuo/p/5695256.html

2.1.4安装docker和docker compose

卸载旧版本

首先需要对服务器进行清理, 如果之前安装过Docker , 需要先执行卸载操作,具体命令

如下:

sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine

安装Docker CE

安装yum-utils提供的yum-config-manager,device-mapper-persistent-data和lvm2

sudo yum install  yum-utils device-mapper-persistent-data lvm2

使用下面的命令来设置稳定存储库:

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

可以选择性地启用edge 和测试存储库,这些存储库包含在Docker 中,在默认情况下是禁用的。具体执行命令如下:

sudo yum-config-manager --enable docker-ce-edge
sudo yum-config-manager --enable docker-ce-test

也可以通过使用禁用标志来运行yum-config-manager 命令, 以禁用edge 或测试存储库。

要重新启用它, 可以使用-enable 标志。下面的命令禁用edge 存储库:

yum-config-manager --disable docker-ce-edge

最后, 可执行如下命令安装最新版本的Docker CE :

yum install docker-ce -y

还能通过如下命令安装指定版本的Docker CE :

yum install docker-ce -<VERSION STRING>

执行查询Docke r 版本号, 看是否安装成功:

docker --version

Docker启动及常用命令

Docker CE 安装完成后, 需要启动它并设置为开机启动。

Docker 启动命令如下:

service docker start

Docker 开机自启动命令如下:

chkconfig docker on

Docker 常用命令如下。

杀死所有正在运行的容器:

docker kill $(docker ps -a -q)

删除所有己经停止的容器:

docker rm $(docker ps -a -q)

删除所有镜像:

docker rmi $(docker images -q)

强制删除所有镜像:

docker rmi -f $(docker images -q)

Docker-Compose 安装

Compose 是定义和运行多容器Docker 应用程序的工具,可以使用YAML 文件来配置应用服务。然后, 通过单个命令可以从配置中创建井启动所有服务。

要了解更多关于组合的特性,请参阅特性列表:

https://docs.docker.com/compose/overview/#features

使用Compose 基本上是一个三步骤的过程:

( 1 )用Dockerfile 定义应用程序的环境,这样它可以在任何地方复制。

(2 )通过docker-compose. yml 在服务中定义所启动的各个应用,这些应用将在相互隔离的环境中同时运行。

(3 )运行docke r-compose up ,启动Co mpo se 并运行整个应用程序。

在线安装Docker-Compose

安装Docker-Compose 需要服务器支持curl 命令,如果服务器不支持curl , 需要执行如下操作安装c url 依赖:

yum install curl

通过https://github.com/docker/compose/releases 网址,可以查看Docker Compose 最新发行版的动向。

执行如下操作下载Docke r Compose :

curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

该下载目录为/usr/local/bin/docker-compose,且权限己经给出, 再执行docker-compose -version 检查版本号,或许会有如下提示:

-bash: /usr/bin/docker-compose: No such file or directory

如果出现上述提示, 则执行以下操作:

cp /usr/local/bin/docker-compose /usr/bin

将docker-compose 复制到/usr/ bin 目录下,再次执行:

docker-compose --version

正常情况下会打印docker-compose 的版本信息,如下所示:

docker-compose version 1.20.0-rc1, build 86428af

2.1.5 Go 语言环境安装

go1.13.X及以上版本

下载go语言包

wget https://studygolang.com/dl/golang/go1.14.linux-amd64.tar.gz

tar -C /usr/local -zxvf go1.14.linux-amd64.tar.gz

tar解压时遇到解压的部分文件丢失,从Windows上解压完再复制到虚拟机上,需要赋予go执行权限

chmod a+x /usr/local/go/bin/go

Go语言环境变量

考虑到以后将会在Go 语言中编写链码程序,有两个环境变量需要正确设置: 可以将这些设置永久地保存在适当的启动文件中。

修改/etc/profile 文件使其永久性生效,并对所有系统用户生效,在文件末尾加上如下两行代码:

export PATH=$PATH:/usr/local/go/bin
export GOPATH=/opt/gopath

生效配置文件

source /etc/profile

使其修改生效。随后可通过下述命令查看是否添加成功:

echo $PATH

最后,可通过如下命令查看当前Go 版本的信息:

go version

将go文件夹复制到其他机器

[root@p1 local]# scp -r  go root@p2:/usr/local/ 
[root@p1 apps]# scp /etc/profile root@p2:/etc
[root@p1 local]# scp -r  go root@p3:/usr/local/ 
[root@p1 apps]# scp /etc/profile root@p3:/etc
[root@p1 local]# scp -r  go root@p4:/usr/local/ 
[root@p1 apps]# scp /etc/profile root@p4:/etc
[root@p1 apps]# ssh p2
[root@p2 ~]# source /etc/profile
[root@p1 apps]# ssh p3
[root@p3 ~]# source /etc/profile
[root@p1 apps]# ssh p4
[root@p4 ~]# source /etc/profile

2.1.6安装node.js

下载node-v13.11.0-linux-x64.tar.xz,并传送至虚拟机的/usr/local目录下,

解压node-v13.11.0-linux-x64.tar.xz

[root@p3 local]#tar xf node-v13.11.0-linux-x64.tar.xz 

重命名下:

[root@p3 local]#mv node-v13.11.0-linux-x64 nodejs

建立软连接:

[root@p3 local]# ln -s /usr/local/nodejs/bin/npm /usr/local/bin/
[root@p3 local]# ln -s /usr/local/nodejs/bin/node /usr/local/bin/

查看版本号:

[root@p3 local]# npm -v
6.13.7
[root@p3 local]# node -v
v13.11.0

同理部署其他机器环境。

2.1.7安装python

根据官网介绍,Fabric Node.js SDK 需要 Python 2.7 进行相关操作。检查版本:

python --version

2.2fabric源码安装

下载项目到go目录并checkout到1.1分支

创建文件夹:

mkdir -p $GOPATH/src/github.com/hyperledger

进入文件夹:

cd $GOPATH/src/github.com/hyperledger

下载fabric:

git clone https://github.com/hyperledger/fabric.git

网速度太慢可以更换下载源,https://gitee.com/hbhssl/fabric.git
可以在码云上导入源码再clone到本地

2.2.1测试网络

确定机器上要放置Fabric-samples 存储库的位置,然后在终端窗口中输入该目录,我选取的是/opt/gopath/src/github.com/hyperledger。

如果要使用最新的生产版本,请省略所有版本标识符。

curl -sSL https://bit.ly/2ysbOFE | bash -s
或者
curl -sSL https : //raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s -- 2.0.0 1.4.4 0.4.18

下载指定版本:

curl -sSL https://bit.ly/2ysbOFE | bash -s -- <fabric_version> <fabric-ca_version> <thirdparty_version>
例:
curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.0.0 1.4.4 0.4.18

将下载好的工具类添加到path中:

export PATH=<path to download location>/bin:$PATH
例:
export PATH=/opt/gopath/src/github.com/hyperledger/fabric-samples/bin:$PATH

建立测试网络

test-network在fabric-samples存储库目录中找到用于启动网络的脚本。使用以下命令导航到测试网络目录:

cd fabric-samples/test-network

从test-network目录内部,运行以下命令以从以前的运行中删除所有容器或工件:

./network.sh down

手动删除所有docker镜像

docker rm  $(docker ps -a | grep "hyperledger/*" | awk "{print $1}") -f

清除以前的网络,提供全新的环境:

docker network prune

然后,您可以通过发出以下命令来启动网络:

./network.sh up

命令创建一个由两个对等节点(一个订购节点)组成的结构网络。您在运行时不会创建任何渠道,尽管我们将在以后的步骤中实现。如果命令成功完成,您将看到正在创建的节点的日志:

测试网络的组成部分

部署测试网络后,您可能需要一些时间来检查其组件。运行以下命令以列出计算机上运行的所有Docker容器。您应该看到该network.sh脚本创建的三个节点:

docker ps -a

建立通道

使用network.sh脚本在Org1和Org2之间创建频道,并将其对等方加入该频道。运行以下命令以使用默认名称创建频道mychannel:

./network.sh createChannel

命令成功执行,您将在日志中看到以下消息:

您也可以使用channel标志创建具有自定义名称的频道。例如,以下命令将创建一个名为的通道channel1:

./network.sh createChannel -c channel1

通道标志还允许您通过指定不同的通道名称来创建多个通道。创建mychannel或后channel1,您可以使用以下命令创建另一个名为的频道channel2:

./network.sh createChannel -c channel2

如果要一步一步建立网络并创建频道,可以将up和createChannel模式一起使用:

./network.sh up createChannel

在通道上启动链码

使用以下命令在频道上启动链码:

./network.sh deployCC

启动成功后在日志中看到以下汽车清单:

备注:

[root@p1 test-network]# ./network.sh deployCC
deploying chaincode on channel 'mychannel'

Vendoring Go dependencies ...
/opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode/fabcar/go /opt/gopath/src/github.com/hyperledger/fabric-samples/test-network
/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network
Finished vendoring Go dependencies
Using organization 1
++ peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1
++ res=1
++ set +x
Error: failed to normalize chaincode path: 'go list' failed with: go tool asm: fork/exec /usr/local/go/pkg/tool/linux_amd64/asm: permission denied: exit status 1
!!!!!!!!!!!!!!! Chaincode packaging on peer0.org1 has failed !!!!!!!!!!!!!!!!

ERROR !!! Deploying chaincode failed

遇到以上问题是go配置过程中存在权限问题,赋权即可

[root@p1 test-network]# chmod -R 777 /usr/local/go

与网络互动

启动测试网络后,可以使用peerCLI与网络进行交互。peerCLI允许您从CLI调用已部署的智能合约,更新通道或安装和部署新的智能合约。

在test-network目录进行操作,使用以下命令将这些二进制文件添加到您的CLI路径

export PATH=${PWD}/../bin:${PWD}:$PATH

设置FABRIC_CFG_PATH指向存储库中的core.yaml文件fabric-samples:

export FABRIC_CFG_PATH=$PWD/../config/

设置环境变量,以允许您以peer Org1的形式操作CLI:

# Environment variables for Org1

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

运行以下命令以获取已添加到通道分类帐中的汽车的列表:

peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

命令成功执行,则在运行脚本时,可以看到与日志中打印的汽车相同的列表:

当网络成员要转移或更改分类帐上的资产时,将调用链码。使用以下命令通过调用fabcar链码来更改分类帐中汽车的所有者:

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"changeCarOwner","Args":["CAR9","Dave"]}'

命令成功,看到以下响应:

由于fabcar链码的背书策略要求事务由Org1和Org2签名,因此chaincode invoke命令需要既针对目标 peer0.org1.example.com又peer0.org2.example.com使用–peerAddresses 标志。由于已为网络启用TLS,因此该命令还需要使用该–tlsRootCertFiles标志为每个对等方引用TLS证书。

调用链代码后,我们可以使用另一个查询来查看该调用如何更改了区块链分类账上的资产。由于我们已经查询过Org1对等体,因此我们可以借此机会查询Org2对等体上运行的链码。设置以下环境变量以作为Org2进行操作:

# Environment variables for Org2

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

查询在以下位置运行的fabcar链码peer0.org2.example.com:

peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

结果将显示"CAR9"已转移到Dave:

[{"Key":"CAR0", "Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1", "Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR2", "Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR3", "Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4", "Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5", "Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6", "Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7", "Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8", "Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9", "Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Dave"}}]

中断网络

使用完测试网络后,可以使用以下命令关闭网络:

./network.sh down

该命令将停止并删除节点和链码容器,删除组织加密材料,并从Docker注册表中移除链码映像。该命令还会从以前的运行中删除通道工件和docker卷,从而在遇到任何问题时允许您再次运行。./network.sh up

与证书颁发机构建立网络

运行以下命令以关闭所有正在运行的网络:

./network.sh down

然后,您可以使用CA标志启动网络:

./network.sh up -ca

运行成功后:

2.2.2开发应用程序-商业票据

先决条件

必备条件:node版本:8.9.0及以上;docker版本:18.06及以上

实用工具:VSCode:1.28及以上;NVM(node version manager)

安装NVM

[root@p1 p1]# git clone git://github.com/creationix/nvm.git ~/nvm
正克隆到 '/root/nvm'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 7694 (delta 1), reused 4 (delta 1), pack-reused 7685
接收对象中: 100% (7694/7694), 2.62 MiB | 236.00 KiB/s, done.
处理 delta 中: 100% (4865/4865), done.
[root@p1 p1]# command -v nvm
[root@p1 p1]# cd ~/nvm/
[root@p1 nvm]# command -v nvm
[root@p1 nvm]# echo "source ~/nvm/nvm.sh" >> ~/.bashrc
[root@p1 nvm]# source ~/.bashrc
[root@p1 nvm]# nvm list-remote
    iojs-v1.0.0
    iojs-v1.0.1

启动测试网络并使用商业票据目录中提供的脚本创建频道。转到commercial-paper目录fabric-samples:

cd fabric-samples/commercial-paper

然后使用脚本启动测试网络:

./network-starter.sh

如果命令成功执行,您将在日志中看到正在创建的测试网络。您可以使用以下命令查看在本地计算机上运行的Fabric节点:docker ps

[root@p1 commercial-paper]# docker ps 
CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                        NAMES
e71c26ae5b0d        hyperledger/fabric-peer:amd64-2.0.0      "peer node start"        51 seconds ago      Up 49 seconds       7051/tcp, 0.0.0.0:9051->9051/tcp             peer0.org2.example.com
14385bbf7601        hyperledger/fabric-peer:amd64-2.0.0      "peer node start"        51 seconds ago      Up 49 seconds       0.0.0.0:7051->7051/tcp                       peer0.org1.example.com
d351ca080a3e        hyperledger/fabric-orderer:amd64-2.0.0   "orderer"                53 seconds ago      Up 51 seconds       0.0.0.0:7050->7050/tcp                       orderer.example.com
eaecd78a0449        hyperledger/fabric-couchdb               "tini -- /docker-ent…"   53 seconds ago      Up 51 seconds       4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp   couchdb0
231c320876ec        hyperledger/fabric-couchdb               "tini -- /docker-ent…"   53 seconds ago      Up 51 seconds       4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp   couchdb1

对等端 节点 容器 组织 雇员
Org1 peer0.org1.example.com f98791ffa664 DigiBank Balaji
Org2 peer0.org2.example.com 78abb5575932 MagnetoCorp Isabella
Org1对等点CouchDB数据库 couchdb0 3624bddc453a DigiBank
Org2对等点CouchDB数据库 couchdb1 706481a0fed1 MagnetoCorp
Order orderer.example.com d1d4f45b10e3

这些容器都构成一个 名为的Docker网络net_test。您可以使用以下命令查看网络:docker network

[root@p1 commercial-paper]# docker network inspect net_test 
[
    {
        "Name": "net_test",
        "Id": "dd33aca5a020694d86a5a78f26e1497b5292caa65b7e64aa0046b97d5cd62e01",
        "Created": "2020-04-01T14:17:04.910883091+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.20.0.0/16",
                    "Gateway": "172.20.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "3624bddc453a64427db1ca727b4067859fa5fd8b5ec1cdbef0a390fc4f52f0ec": {
                "Name": "couchdb0",
                "EndpointID": "178b94184377b6b031b4775fbd079df3e4c01baf31984ebff761709975b8f226",
                "MacAddress": "02:42:ac:14:00:04",
                "IPv4Address": "172.20.0.4/16",
                "IPv6Address": ""
            },
            "706481a0fed13e3f226dd06bd67cfb22f3efbc2edb40e604e98645cba017a9b2": {
                "Name": "couchdb1",
                "EndpointID": "72bed54d83e4d170f3594c3c73683924ba6f4e477f1d5a5167de178dd2f12c24",
                "MacAddress": "02:42:ac:14:00:03",
                "IPv4Address": "172.20.0.3/16",
                "IPv6Address": ""
            },
            "78abb5575932dd704df8555df4144126ffab8617d231639c1a05fb9908ad9bdc": {
                "Name": "peer0.org2.example.com",
                "EndpointID": "3b684c8035874ac005370b6bff4108af71925a4a429d7156412b965f904a8ff7",
                "MacAddress": "02:42:ac:14:00:05",
                "IPv4Address": "172.20.0.5/16",
                "IPv6Address": ""
            },
            "d1d4f45b10e3620057d0b9b9e18585570aa3c37ae5912f34595ebca83098de76": {
                "Name": "orderer.example.com",
                "EndpointID": "5583465ee920cfddaf5592e949b16306a1cb8561bc38a47f6ecc44ae9807b31f",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            },
            "f98791ffa664a1bfeef6b608a95019f691b1c480f692e638a57095bd167d414d": {
                "Name": "peer0.org1.example.com",
                "EndpointID": "9154602ebabebc76fe83ad582dc8ca2ac72eb15f3db8b75ab2616ca7b617d8e8",
                "MacAddress": "02:42:ac:14:00:06",
                "IPv4Address": "172.20.0.6/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

作为MagnetoCorp监视网络

在fabric-samples存储库中打开一个新窗口,并使用以下命令切换到MagnetoCorp目录:

cd commercial-paper/organization/magnetocorp

为方便查看日志,可以安装logspout工具,该工具将不同的输出流收集到一个位置,从而可以轻松地从单个窗口查看正在发生的情况。

为方便代码编辑,选用vscode。

在MagnetoCorp目录中,运行以下命令以运行 monitordocker.sh 脚本并启动logspout与PaperNet相关的容器的工具net_test:

[root@p1 magnetocorp]#  ./configuration/cli/monitordocker.sh net_test

成功后:

[root@p1 cli]# ./monitordocker.sh net_test
Starting monitoring on all containers on the network net_test
3cb93b55cc12a71ea9899673527d81bee537a003d97230bb3d6397a1e412e368
curl: (56) Recv failure: Connection reset by peer

现在,该窗口将显示本教程其余部分中Docker容器的输出,因此继续并打开另一个命令窗口。我们要做的下一步是检查MagnetoCorp将用于向商业票据发行的智能合约。

遇到以下问题:

[root@p1 cli]# ./monitordocker.sh net_test
Starting monitoring on all containers on the network net_test
WARNING: IPv4 forwarding is disabled. Networking will not work.
1c1855c7ded0f3a52178fadd98f5ba53873dabb07fdb498b01b52d68d825df5f
curl: (56) Recv failure: Connection reset by peer

解决方法:

[root@p1 cli]# vim /usr/lib/sysctl.d/00-system.conf 

添加如下代码:

net.ipv4.ip_forward=1

重启network服务:

[root@p1 cli]# systemctl restart network

检查商业票据智能合约

issue,buy并且redeem是在商业票据智能合同心脏的三个功能。应用程序使用它来提交交易,这些交易相应地在分类账上发行,购买和赎回商业票据。我们的下一个任务是检查智能合约。

在fabric-samples目录中打开一个新终端,然后切换到MagnetoCorp文件夹以充当MagnetoCorp开发人员。然后,您可以contract使用选择的编辑器(在本教程中为VS Code)在目录中查看智能合约:【非root用户下进行code操作】。在lib文件夹目录中,您将看到papercontract.js文件-其中包含商业票据智能合约!

将智能合约部署到渠道

在papercontract被应用程序调用之前,必须将其安装到测试网络的适当对等节点上,然后使用Fabric链码生命周期在通道上进行定义。Fabric链码生命周期允许多个组织在将链码部署到通道之前就链码的参数达成一致。因此,我们需要以MagnetoCorp和DigiBank的管理员身份安装和批准链码。

MagnetoCorp管理员将的副本安装papercontract到MagnetoCorp对等方。

智能合约是应用程序开发的重点,并且包含在称为chaincode的Hyperledger Fabric工件中。可以在单个链码中定义一个或多个智能合约,安装链码将允许PaperNet中的不同组织使用它们。这意味着只有管理员才需要担心链码。其他人都可以根据智能合约进行思考。

以MagnetoCorp的形式安装和批准智能合约

以MagnetoCorp管理员的身份安装和批准智能合约。确保您正在该magnetocorp文件夹中进行操作。MagnetoCorp管理员可以使用peerCLI 与PaperNet进行交互。但是,管理员需要在命令窗口中设置某些环境变量,以使用正确的peer二进制集,将命令发送到MagnetoCorp对等方的地址,并使用正确的加密材料对请求进行签名。您可以使用示例提供的脚本在命令窗口中设置环境变量。在magnetocorp目录中运行以下命令:

source magnetocorp.sh

您将在窗口中看到环境变量的完整列表。现在,我们可以使用此命令窗口以MagnetoCorp管理员的身份与PaperNet进行交互。

第一步是安装papercontract智能合约。可以使用以下命令将智能合约打包为链码 。在MagnetoCorp管理员的命令窗口中,运行以下命令来创建chaincode包:peer lifecycle chaincode package

(magnetocorp admin)$ peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0

MagnetoCorp管理员现在可以使用以下命令在MagnetoCorp对等方上安装链码:peer lifecycle chaincode install

(magnetocorp admin)$ peer lifecycle chaincode install cp.tar.gz

如果命令成功执行,您将在终端上看到类似于以下内容的消息:

[root@p1 magnetocorp]# peer lifecycle chaincode install cp.tar.gz
2020-04-01 14:29:30.105 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEcp_0:5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c\022\004cp_0" > 
2020-04-01 14:29:30.114 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: cp_0:5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c
[root@p1 magnetocorp]# 



[root@p1 magnetocorp]# source magnetocorp.sh
Using organization 2
Using organization 2
export CORE_PEER_ADDRESS="localhost:9051"
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_MSPCONFIGPATH="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp"
export CORE_PEER_TLS_ENABLED="true"
export CORE_PEER_TLS_ROOTCERT_FILE="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
export FABRIC_CFG_PATH="/opt/gopath/src/github.com/hyperledger/fabric-samples/commercial-paper/organization/magnetocorp/../../../config"
export ORDERER_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
export PATH="/opt/gopath/src/github.com/hyperledger/fabric-samples/commercial-paper/organization/magnetocorp/../../../bin:/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network:/root/.sdkman/candidates/java/current/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/go/bin:/usr/local/jdk8/bin:/usr/local/maven/bin:/home/p1/.nvm/nvm.sh:/home/p1/.local/bin:/home/p1/bin"
export PEER0_ORG1_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
export PEER0_ORG2_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
export PEER0_ORG3_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt"
export PEER_PARMS="--peerAddresses localhost:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
rm:是否删除普通文件 "/tmp/env.orig"?
[root@p1 magnetocorp]# 
[root@p1 magnetocorp]# 
[root@p1 magnetocorp]# 
[root@p1 magnetocorp]# peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0
[root@p1 magnetocorp]# peer lifecycle chaincode install cp.tar.gz
2020-04-01 14:29:30.105 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEcp_0:5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c\022\004cp_0" > 
2020-04-01 14:29:30.114 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: cp_0:5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c
[root@p1 magnetocorp]# 

由于MagnetoCorp管理员已将CORE_PEER_ADDRESS=localhost:9051其命令设置为peer0.org2.example.com,因此 表示该对象已成功安装。INFO 001 Installed remotely…``papercontract

安装智能合约后,我们需要批准链码定义为papercontractMagnetoCorp。第一步是找到我们安装在对等方上的链码的packageID。我们可以使用以下命令查询packageID :peer lifecycle chaincode queryinstalled

[root@p1 magnetocorp]# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: cp_0:5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c, Label: cp_0

下一步将需要包ID,因此我们将其保存为环境变量。软件包ID可能对于所有用户而言都不相同,因此您需要使用从命令窗口返回的软件包ID来完成此步骤。

[root@p1 magnetocorp]# export PACKAGE_ID=cp_0:5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c

管理员现在可以使用以下命令批准MagnetoCorp的链码定义 :peer lifecycle chaincode approveformyorg

[root@p1 magnetocorp]# peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
2020-04-01 14:44:19.022 CST [chaincodeCmd] ClientWait -> INFO 001 txid [fcef4e37aed66f2d8ed5f81bc4e2e2a5fd93cadaae9fce5ecfe3a4945cfa6ca8] committed with status (VALID) at 
[root@p1 magnetocorp]# 

作为DigiBank安装并批准智能合约

默认情况下,结构链代码生命周期需要通道上的大多数组织才能将链代码定义成功提交到通道。这意味着我们需要批准papernet链码为MagnetoCorp和DigiBank,以从2中获得必需的多数。在中打开一个新的终端窗口,导航到目录/opt/gopath/src/github.com/hyperledger/fabric-samples/commercial-paper/organization/magnetocorp。

使用DigiBank文件夹中的脚本设置环境变量,使您可以充当DigiBank管理员:

source digibank.sh

我们现在可以安装并批准papercontract为DigiBank。运行以下命令来打包链码:

(digibank admin)$ peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0

管理员现在可以在DigiBank对等方上安装链码了:

(digibank admin)$ peer lifecycle chaincode install cp.tar.gz

然后,我们需要查询并保存刚刚安装的链码的packageID:

(digibank admin)$ peer lifecycle chaincode queryinstalled

将程序包ID保存为环境变量。使用从控制台返回的程序包ID完成此步骤。

export PACKAGE_ID=cp_0:ffda93e26b183e231b7e9d5051e1ee7ca47fbf24f00a8376ec54120b1a2a335c

Digibank管理员现在可以批准以下链代码的定义papercontract:

(digibank admin)$ peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA

以上步骤的完整操作过程如下:

[root@p1 p1]# cd /opt/gopath/src/github.com/hyperledger/fabric-samples/commercial-paper/organization/digibank/
[root@p1 digibank]# ll
总用量 4
drwxr-xr-x. 2 root root 117 3月  26 14:50 application
drwxr-xr-x. 4 root root 119 3月  26 14:50 application-java
drwxr-xr-x. 3 root root  17 3月  26 14:50 configuration
drwxr-xr-x. 5 root root 163 3月  26 14:50 contract
drwxr-xr-x. 4 root root  91 3月  26 14:50 contract-go
drwxr-xr-x. 4 root root 153 3月  26 14:50 contract-java
-rwxr-xr-x. 1 root root 738 3月  26 14:50 digibank.sh
drwxr-xr-x. 2 root root  50 3月  26 16:39 gateway
[root@p1 digibank]# source digibank.sh
Using organization 1
Using organization 1
export CORE_PEER_ADDRESS="localhost:7051"
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp"
export CORE_PEER_TLS_ENABLED="true"
export CORE_PEER_TLS_ROOTCERT_FILE="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
export FABRIC_CFG_PATH="/opt/gopath/src/github.com/hyperledger/fabric-samples/commercial-paper/organization/digibank/../../../config"
export ORDERER_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
export PATH="/opt/gopath/src/github.com/hyperledger/fabric-samples/commercial-paper/organization/digibank/../../../bin:/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network:/root/.sdkman/candidates/java/current/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/go/bin:/usr/local/jdk8/bin:/usr/local/maven/bin:/home/p1/.nvm/nvm.sh:/home/p1/.local/bin:/home/p1/bin"
export PEER0_ORG1_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
export PEER0_ORG2_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
export PEER0_ORG3_CA="/opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt"
export PEER_PARMS="--peerAddresses localhost:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
rm:是否删除普通文件 "/tmp/env.orig"?
[root@p1 digibank]# 
[root@p1 digibank]# 
[root@p1 digibank]# peer lifecycle chaincode package cp.tar.gz --lang node --path ./contract --label cp_0
[root@p1 digibank]# peer lifecycle chaincode install cp.tar.gz
2020-04-01 14:53:01.789 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEcp_0:46eb5e8fae138e4ba37621951bc4a77ef9efad45a8da5aa57b0b3ac817214594\022\004cp_0" > 
2020-04-01 14:53:01.789 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: cp_0:46eb5e8fae138e4ba37621951bc4a77ef9efad45a8da5aa57b0b3ac817214594
[root@p1 digibank]# 
[root@p1 digibank]# 
[root@p1 digibank]# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: cp_0:46eb5e8fae138e4ba37621951bc4a77ef9efad45a8da5aa57b0b3ac817214594, Label: cp_0
[root@p1 digibank]# export PACKAGE_ID=cp_0:46eb5e8fae138e4ba37621951bc4a77ef9efad45a8da5aa57b0b3ac817214594
[root@p1 digibank]# peer lifecycle chaincode approveformyorg --orderer localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name papercontract -v 0 --package-id $PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
2020-04-01 14:54:53.696 CST [chaincodeCmd] ClientWait -> INFO 001 txid [166979b110b2fc48e1612775e1bb937bbf80e2aefff3d33ca93456052921ef72] committed with status (VALID) at

将链码定义提交给通道

DigiBank和MagnetoCorp都已批准了papernet链码,我们将需要大多数(2之2)来将链码定义提交给渠道。一旦在通道上成功定义了链码,链码中的 CommercialPaper智能合约papercontract就可以由通道上的客户端应用程序调用。由于任何一个组织都可以将链码提交给渠道,因此我们将继续以DigiBank管理员身份进行操作:

DigiBank管理员将链码的定义提交papercontract到通道后,将创建一个新的Docker链码容器,以papercontract在两个PaperNet对等体上运行

DigiBank管理员使用命令将链码定义提交到:peer lifecycle chaincode commitpapercontractmychannel

[root@p1 digibank]# peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --peerAddresses localhost:7051 --tlsRootCertFiles ${PEER0_ORG1_CA} --peerAddresses localhost:9051 --tlsRootCertFiles ${PEER0_ORG2_CA} --channelID mychannel --name papercontract -v 0 --sequence 1 --tls --cafile $ORDERER_CA --waitForEvent
2020-04-01 14:57:36.642 CST [chaincodeCmd] ClientWait -> INFO 001 txid [029d759bd82de1740ed76728047e96a91efac7eb1f28de538dd765030f858b70] committed with status (VALID) at localhost:9051
2020-04-01 14:57:36.725 CST [chaincodeCmd] ClientWait -> INFO 002 txid [029d759bd82de1740ed76728047e96a91efac7eb1f28de538dd765030f858b70] committed with status (VALID) at localhost:7051
[root@p1 digibank]# 

链码容器将在链码定义提交到通道后启动。您可以使用该命令查看 在两个对等方上都启动的容器。docker ps``papercontract

[root@p1 digibank]# docker ps
CONTAINER ID        IMAGE                                                                                                                                                               COMMAND                  CREATED              STATUS              PORTS                                        NAMES
522d8ce4e992        dev-peer0.org2.example.com-cp_0-5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c-e07b3b06d71856bbf3231a90f87ad03cdf794073bb87c25b588394a6cc3bf823   "docker-entrypoint.s…"   About a minute ago   Up About a minute                                                dev-peer0.org2.example.com-cp_0-5190287c1ce48b1147206e66d5e7e7d968708719aea167dcbaa824101af3b40c
d06b016497f9        dev-peer0.org1.example.com-cp_0-46eb5e8fae138e4ba37621951bc4a77ef9efad45a8da5aa57b0b3ac817214594-724a34ef3af63e0cb26768193198f7a571f3f1ccf691374e09b75f2986f1e63d   "docker-entrypoint.s…"   About a minute ago   Up About a minute                                                dev-peer0.org1.example.com-cp_0-46eb5e8fae138e4ba37621951bc4a77ef9efad45a8da5aa57b0b3ac817214594
4272461910da        gliderlabs/logspout                                                                                                                                                 "/bin/logspout"          36 minutes ago       Up 36 minutes       127.0.0.1:8000->80/tcp                       logspout
f98791ffa664        hyperledger/fabric-peer:amd64-2.0.0                                                                                                                                 "peer node start"        41 minutes ago       Up 41 minutes       0.0.0.0:7051->7051/tcp                       peer0.org1.example.com
78abb5575932        hyperledger/fabric-peer:amd64-2.0.0                                                                                                                                 "peer node start"        41 minutes ago       Up 41 minutes       7051/tcp, 0.0.0.0:9051->9051/tcp             peer0.org2.example.com
d1d4f45b10e3        hyperledger/fabric-orderer:amd64-2.0.0                                                                                                                              "orderer"                41 minutes ago       Up 41 minutes       0.0.0.0:7050->7050/tcp                       orderer.example.com
3624bddc453a        hyperledger/fabric-couchdb                                                                                                                                          "tini -- /docker-ent…"   41 minutes ago       Up 41 minutes       4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp   couchdb0
706481a0fed1        hyperledger/fabric-couchdb                                                                                                                                          "tini -- /docker-ent…"   41 minutes ago       Up 41 minutes       4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp   couchdb1
[root@p1 digibank]# 

应用结构

papercontractMagnetoCorp的应用程序调用其中包含的智能合约issue.js。伊莎贝拉(Isabella)使用该应用程序向发行商业票据的总账提交交易00001。让我们快速检查一下issue应用程序如何工作。

网关允许应用程序专注于事务的生成,提交和响应。它协调不同网络组件之间的交易建议,订购和通知处理。

因为该issue应用程序代表Isabella提交事务,所以它首先从她的钱包中检索Isabella的X.509证书,该证书 可能存储在本地文件系统或硬件安全模块 HSM中。然后,issue 应用程序可以利用网关在通道上提交事务。Hyperledger Fabric SDK提供了 网关抽象,因此应用程序可以在将网络交互委派给网关的同时专注于应用程序逻辑。网关和钱包使编写Hyperledger Fabric应用程序变得很简单。

因此,让我们检查一下issueIsabella将要使用的应用程序。为她打开一个单独的终端窗口,然后fabric-samples找到MagnetoCorp /application文件夹:

(isabella)$ cd commercial-paper/organization/magnetocorp/application/
(isabella)$ ls

addToWallet.js      issue.js        package.json

addToWallet.js是Isabella将用于将其身份加载到她的钱包中的程序,issue.js并将通过使用该身份00001代表MagnetoCorp 创建商业票据papercontract。

转到包含MagnetoCorp应用程序副本的目录 issue.js,然后使用代码编辑器进行检查:

(isabella)$ cd commercial-paper/organization/magnetocorp/application
(isabella)$ code issue.js

检查该目录;它包含问题应用程序及其所有依赖项。

请注意以下关键程序行issue.js:

  • const { Wallets, Gateway } = require(‘fabric-network’);
    该语句将两个关键的Hyperledger Fabric SDK类纳入了范围- Wallet和Gateway.M
  • const wallet = await Wallets.newFileSystemWallet(’…/identity/user/isabella/wallet’);
    该语句标识该应用程序isabella在连接到区块链网络通道时将使用钱包。由于Isabella的X.509证书位于本地文件系统中,因此该应用程序将创建一个new FileSystemWallet。该应用程序将在isabella钱包中选择一个特定的身份。
  • await gateway.connect(connectionProfile, connectionOptions);
    这行代码使用标识的网关connectionProfile使用中标识的网关连接到网络 ConnectionOptions。
    分别查看如何…/gateway/networkConnection.yaml和User1@org1.example.com用于这些值。
  • const network = await gateway.getNetwork(‘mychannel’);
    此连接应用到网络信道mychannel,其中,所述 papercontract先前实例化。
  • const contract = await network.getContract(‘papercontract’);
    该语句使应用程序可以访问papercontract链码。一旦应用程序发布了getContract,它就可以提交到链代码内实现的任何智能合约交易。
  • const issueResponse = await contract.submitTransaction(‘issue’, ‘MagnetoCorp’, ‘00001’, …);
    此代码行使用issue 智能合约中定义的交易将交易提交到网络。MagnetoCorp,00001…是该issue交易用于创建新商业票据的值。
  • let paper = CommercialPaper.fromBuffer(issueResponse);
    该语句处理来自issue事务的响应。响应需要从缓冲区反序列化为 对象paper,该CommercialPaper对象可以由应用程序正确解释。

随时检查目录中的其他文件/application以了解其issue.js工作原理,并在应用程序主题中详细阅读其实现方式。

应用程序依赖

该issue.js应用程序是用JavaScript编写的,旨在在作为PaperNet网络客户端的Node.js环境中运行。按照惯例,MagnetoCorp的应用程序建立在许多外部节点程序包上-以提高开发质量和速度。考虑一下issue.js包括js-yaml 包处理YAML网关连接配置文件,或fabric-network 包访问的Gateway 和Wallet类:

const yaml = require('js-yaml');
const { Wallets, Gateway } = require('fabric-network');

必须使用以下命令将这些软件包从npm下载到本地文件系统。按照惯例,必须将软件包安装到相对于应用程序的目录中,以便在运行时使用。npm install``/node_modules

检查package.json文件以查看如何issue.js标识要下载的软件包及其确切版本:

  "dependencies": {
    "fabric-network": "~1.4.0",
    "fabric-client": "~1.4.0",
    "js-yaml": "^3.12.0"
  },

npm版本控制功能非常强大;您可以在此处了解更多信息 。

让我们使用命令安装这些软件包-这可能需要一分钟才能完成:npm install

上图为执行前后结果对比。

检查node_modules目录以查看已安装的软件包。有很多,因为js-yaml和fabric-network本身是基于其他npm软件包构建的!有用的是,该package-lock.json 文件标识了所安装的确切版本,如果您想精确地复制环境,这可以证明是无价的。测试,诊断问题或交付经过验证的应用程序。

钱包

伊莎贝拉几乎准备issue.js发行MagnetoCorp商业票据 00001; 剩下要做的一项任务!由于issue.js代表伊莎贝拉(Isabella)并因此代表MagnetoCorp,它将使用她钱包中的身份来 反映这些事实。现在,我们需要执行此一次性活动,向她的钱包添加适当的X.509凭据。

在Isabella的终端窗口中,运行addToWallet.js程序以将身份信息添加到她的钱包:

(isabella)$ node addToWallet.js

done

addToWallet.js是一个简单的文件复制程序,您可以随时检查。它将身份从测试网络样本移至Isabella的钱包。让我们关注该程序的结果-用来向PaperNet提交交易的钱包内容:

(isabella)$ ls ../identity/user/isabella/wallet/

isabella.id

Isabella可以在她的钱包中存储多个身份,尽管在我们的示例中,她仅使用一个。该wallet文件夹包含一个isabella.id文件,该文件提供Isabella连接到网络所需的信息。伊莎贝拉(Isabella)使用的其他身份将拥有自己的文件。您可以打开此文件以查看issue.js将在JSON文件中代表Isabella使用的身份信息。为了清楚起见,已对输出进行格式化。

(isabella)$  cat ../identity/user/isabella/wallet/*

{
  "credentials": {
    "certificate": "-----BEGIN CERTIFICATE-----\nMIICKTCCAdCgAwIBAgIQWKwvLG+sqeO3LwwQK6avZDAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMi5leGFtcGxlLmNvbTAeFw0yMDAyMDQxOTA5MDBaFw0zMDAyMDExOTA5MDBa\nMGwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ8wDQYDVQQLEwZjbGllbnQxHzAdBgNVBAMMFlVzZXIxQG9y\nZzIuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT4TnTblx0k\ngfqX+NN7F76Me33VTq3K2NUWZRreoJzq6bAuvdDR+iFvVPKXbdORnVvRSATcXsYl\nt20yU7n/53dbo00wSzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADArBgNV\nHSMEJDAigCDOCdm4irsZFU3D6Hak4+84QRg1N43iwg8w1V6DRhgLyDAKBggqhkjO\nPQQDAgNHADBEAiBhzKix1KJcbUy9ey5ulWHRUMbqdVCNHe/mRtUdaJagIgIgYpbZ\nXf0CSiTXIWOJIsswN4Jp+ZxkJfFVmXndqKqz+VM=\n-----END CERTIFICATE-----\n",
    "privateKey": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQggs55vQg2oXi8gNi8\nNidE8Fy5zenohArDq3FGJD8cKU2hRANCAAT4TnTblx0kgfqX+NN7F76Me33VTq3K\n2NUWZRreoJzq6bAuvdDR+iFvVPKXbdORnVvRSATcXsYlt20yU7n/53db\n-----END PRIVATE KEY-----\n"
  },
  "mspId": "Org2MSP",
  "type": "X.509",
  "version": 1
}

在文件中,您会注意到以下内容:

  • 一个"privateKey":用来代签梁洛施的交易,但尚未发放的她直接控制之外。
  • 一个"certificate":,其中包含Isabella的公钥以及证书颁发机构在证书创建时添加的其他X.509属性。该证书分发到网络,以便不同的参与者在不同的时间可以通过密码验证由伊莎贝拉私钥创建的信息。

您可以在此处了解有关证书的更多信息。实际上,证书文件还包含某些特定于Fabric的元数据,例如Isabella的组织和角色-在wallet主题中了解更多。

发行申请

Isabella现在可以使用issue.js提交将发行MagnetoCorp商业票据的交易00001:

(isabella)$ node issue.js

Connect to Fabric gateway.
Use network channel: mychannel.
Use org.papernet.commercialpaper smart contract.
Submit commercial paper issue transaction.
Process issue transaction response.{"class":"org.papernet.commercialpaper","key":"\"MagnetoCorp\":\"00001\"","currentState":1,"issuer":"MagnetoCorp","paperNumber":"00001","issueDateTime":"2020-05-31","maturityDateTime":"2020-11-30","faceValue":"5000000","owner":"MagnetoCorp"}
MagnetoCorp commercial paper : 00001 successfully issued for value 5000000
Transaction complete.
Disconnect from Fabric gateway.
Issue program complete.

该node命令将初始化Node.js环境并运行issue.js。从程序输出中我们可以看到,发行了面值为500万美元的MagnetoCorp商业票据00001。

如您所见,为了实现这一点,应用程序调用issue中的CommercialPaper智能合约中定义的交易papercontract.js。MagnetoCorp管理员已在网络中安装并实例化了该文件。这是智能合约,它通过Fabric API与分类帐进行交互,最著名的是putState()和getState(),将新的商业票据表示为世界状态内的向量状态。我们将看到智能载体中也定义了buy和redeem事务随后如何操纵此向量状态。

底层的Fabric SDK一直都在处理交易认可,订购和通知过程,从而使应用程序的逻辑简单明了;SDK使用网关提取网络详细信息和 connectionOptions来声明更高级的处理策略,例如事务重试。

现在,让我们关注MagnetoCorp 00001的生命周期,将重点转移到DigiBank的一名员工Balaji,他将使用DigiBank应用程序购买该商业票据。

Digibank应用

Balaji使用DigiBank的buy应用程序向分类帐提交交易,分类帐将商业票据的所有权00001从MagnetoCorp转移到DigiBank。该CommercialPaper智能合同是一样的,通过MagnetoCorp的应用程序使用,然而该交易不同,这一次-这是buy不是issue。让我们检查DigiBank的应用程序如何工作。

打开Balaji的单独终端窗口。在中fabric-samples,转到包含应用程序的DigiBank应用程序目录,buy.js然后使用编辑器将其打开:

(balaji)$ cd commercial-paper/organization/digibank/application/
(balaji)$ code buy.js

如您所见,此目录同时包含Balaji将使用的buy和redeem应用程序。

DigiBank的商业票据目录包含buy.js和redeem.js 应用程序。

DigiBank的buy.js应用程序在结构上issue.js与MagnetoCorp的应用程序非常相似,但 有两个重要区别:

  • 身份:该用户是DigiBank用户,Balaji而不是MagnetoCorp的 Isabella
    const wallet = await Wallets.newFileSystemWallet(’…/identity/user/balaji/wallet’);
    查看应用程序balaji在连接到PaperNet网络通道时如何使用钱包。buy.js选择balaji钱包中的特定身份 。
  • 交易:被调用的交易buy不是issue
    const buyResponse = await contract.submitTransaction(‘buy’, ‘MagnetoCorp’, ‘00001’, …);
    一buy交易与价值观提交MagnetoCorp,00001…,被使用的CommercialPaper智能合同类商业票据的所有权转让00001给DigiBank。

随时检查目录中的其他文件application以了解应用程序如何工作,并详细阅读buy.js应用程序主题中如何实现。

以DigiBank身份运行

购买和赎回商业票据的DigiBank应用程序与MagnetoCorp的发行应用程序具有非常相似的结构。因此,让我们安装它们的依赖项并设置Balaji的钱包,以便他可以使用这些应用程序购买和赎回商业票据。

像MagnetoCorp一样,Digibank必须使用命令安装所需的应用程序包,这又需要很短的时间才能完成。npm install

在DigiBank管理员窗口中,安装应用程序依赖项:

(digibank admin)$ cd commercial-paper/organization/digibank/application/
(digibank admin)$ npm install

(            ) extract:lodash: sill extract ansi-styles@3.2.1
(...)
added 738 packages in 46.701s

在Balaji的命令窗口中,运行addToWallet.js程序以将身份添加到他的钱包:

(balaji)$ node addToWallet.js

done

该addToWallet.js程序已将的身份信息添加balaji到他的钱包,该信息将被用来向buy.js并redeem.js提交交易 PaperNet。

与Isabella一样,Balaji可以在他的钱包中存储多个身份,尽管在我们的示例中,他仅使用一个。他对应的id文件digibank/identity/user/balaji/wallet/balaji.id与Isabella的文件 非常相似-请随时检查。

购买申请

Balaji现在可以buy.js用来提交一笔交易,该交易会将MagnetoCorp商业票据00001的所有权转让给DigiBank。

buy在Balaji的窗口中运行该应用程序:

(balaji)$ node buy.js

Connect to Fabric gateway.
Use network channel: mychannel.
Use org.papernet.commercialpaper smart contract.
Submit commercial paper buy transaction.
Process buy transaction response.
MagnetoCorp commercial paper : 00001 successfully purchased by DigiBank
Transaction complete.
Disconnect from Fabric gateway.
Buy program complete.

您可以看到程序输出,Balaji代表DigiBank成功购买了MagnetoCorp商业用纸00001。buy.js调用了智能合约中buy定义的交易,该 交易使用和 Fabric API 在世界范围内CommercialPaper更新了商业票据。如您所见,购买和发行商业票据的应用程序逻辑与智能合约逻辑非常相似。00001putState()getState()

兑换申请

商业票据00001生命周期中的最后一笔交易是DigiBank用MagnetoCorp赎回的。Balaji用于redeem.js提交交易以执行智能合约中的兑换逻辑。

redeem在Balaji的窗口中运行事务:

(balaji)$ node redeem.js

Connect to Fabric gateway.
Use network channel: mychannel.
Use org.papernet.commercialpaper smart contract.
Submit commercial paper redeem transaction.
Process redeem transaction response.
MagnetoCorp commercial paper : 00001 successfully redeemed with MagnetoCorp
Transaction complete.
Disconnect from Fabric gateway.
Redeem program complete.

再次,请参阅在redeem.js调用中redeem定义的交易时如何成功赎回商业票据00001 CommercialPaper。再次,它更新00001了世界范围内的商业票据,以反映所有权归还给票据发行人MagnetoCorp。

清理

完成使用《商业票据》教程后,您可以使用脚本来清理环境。使用命令窗口导航回到商业票据样本的根目录:

cd fabric-samples/commercial-paper

然后,您可以使用以下命令关闭网络:

./network-clean.sh

除logspout工具外,此命令还将关闭对等方,CouchDB容器和网络的订购节点。它还将删除我们为Isabella和Balaji创建的身份。请注意,分类账上的所有数据都将丢失。如果您想再次阅读本教程,则将从一个干净的初始状态开始。

2.3在结构中使用私有数据

参考网址:https://hyperledger-fabric.readthedocs.io/en/latest/private_data_tutorial.html

3.fabric-sdk-java

3.1java环境安装

首先需要卸载openjdk,查看已安装的jdk

--查看已安装的jdk:
[root@p1 p1]# rpm -qa|grep jdk
--卸载
[root@localhost ~]# yum -y remove java*
--查看版本
[root@localhost ~]# java -version

安装

--解压文件、重命名,复制到软件安装目录
[root@p1 apps]# tar -zxvf jdk-8u221-linux-x64.tar.gz
[root@p1 apps]# mv jdk1.8.0_221 jdk8
[root@p1 apps]# cp -r jdk8/ /usr/local/
--配置环境变量
[root@p1 apps]# vim /etc/profile
--将以下内容复制到文件中保存退出
#JAVA1.8
export JAVA_HOME=/usr/local/jdk8
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
--将以上内容复制到文件中保存退出
[root@p1 apps]# source /etc/profile
[root@p1 apps]# java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)

3.2maven环境安装

下载安装包、重命名、配置环境变量

[root@p1 apps]# ls
fabric  go1.14.linux-amd64.tar.gz  jdk8                        nodejs
go      hbhssl-fabric-master.zip   jdk-8u221-linux-x64.tar.gz  node-v13.11.0-linux-x64.tar.xz
[root@p1 apps]# wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
--2020-03-27 09:49:06--  http://mirrors.hust.edu.cn/apache/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
正在解析主机 mirrors.hust.edu.cn (mirrors.hust.edu.cn)... 202.114.18.160
正在连接 mirrors.hust.edu.cn (mirrors.hust.edu.cn)|202.114.18.160|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:5494427 (5.2M) [application/octet-stream]
正在保存至: “apache-maven-3.1.1-bin.tar.gz”

100%[=============================================================================================>] 5,494,427   4.38MB/s 用时 1.2s   

2020-03-27 09:49:07 (4.38 MB/s) - 已保存 “apache-maven-3.1.1-bin.tar.gz” [5494427/5494427])

[root@p1 apps]# ls
apache-maven-3.1.1-bin.tar.gz  go1.14.linux-amd64.tar.gz  jdk-8u221-linux-x64.tar.gz
fabric                         hbhssl-fabric-master.zip   nodejs
go                             jdk8                       node-v13.11.0-linux-x64.tar.xz
[root@p1 apps]# tar zxf apache-maven-3.1.1-bin.tar.gz 
[root@p1 apps]# ls
apache-maven-3.1.1             fabric  go1.14.linux-amd64.tar.gz  jdk8                        nodejs
apache-maven-3.1.1-bin.tar.gz  go      hbhssl-fabric-master.zip   jdk-8u221-linux-x64.tar.gz  node-v13.11.0-linux-x64.tar.xz
[root@p1 apps]# mv apache-maven-3.1.1  maven
[root@p1 apps]# ls
apache-maven-3.1.1-bin.tar.gz  go1.14.linux-amd64.tar.gz  jdk-8u221-linux-x64.tar.gz  node-v13.11.0-linux-x64.tar.xz
fabric                         hbhssl-fabric-master.zip   maven
go                             jdk8                       nodejs
[root@p1 apps]# cp -r maven/ /usr/local/
[root@p1 apps]# cd /usr/local/
[root@p1 local]# ls
bin  etc  games  go  include  jdk8  lib  lib64  libexec  maven  nodejs  sbin  share  src
[root@p1 local]# vim /etc/profile
--将以下内容复制到文件中
#maven
export M2_HOME=/usr/local/maven
export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
--将以上内容复制到文件中
[root@p1 local]# source /etc/profile
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/go/bin:/home/p1/.local/bin:/home/p1/bin:/usr/local/jdk8/bin
[root@p1 local]# mvn -v
Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 23:22:22+0800)
Maven home: /usr/local/maven
Java version: 1.8.0_221, vendor: Oracle Corporation
Java home: /usr/local/jdk8/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1062.18.1.el7.x86_64", arch: "amd64", family: "unix"

4.0blockchain-explorer

1、blockchain-explorer/app/persistence/postgreSQL/db目录下执行./createdb.sh

[root@host-192-100-36-247 blockchain-explorer]# cd app/persistence/postgreSQL/db
[root@host-192-100-36-247 blockchain-explorer]#  ./createdb.sh

2、进入blockchain-explorer目录,执行npm install --unsafe-perm下载依赖文件夹node_modules

[root@host-192-100-36-247 blockchain-explorer]# npm install --unsafe-perm

3、接下来进入blockchain-explorer/ cd app/test/ 目录下执行npm install下载对应的依赖模块:

[root@host-192-100-36-247 blockchain-explorer]# cd app/test/
[root@host-192-100-36-247 test]# npm install

4、test目录下执行npm run test

[root@host-192-100-36-247 test]# npm run test

5、接下来进入blockchain-explorer/client目录,执行npm install下载相关依赖模块:

[root@host-192-100-36-247 test]# cd ..
[root@host-192-100-36-247 app]# cd ../..
[root@host-192-100-36-247 hyperledger]# cd blockchain-explorer/client/
[root@host-192-100-36-247 client]# npm install

6、当前目录下执行npm test – -u --coverage

[root@host-192-100-36-247 client]# npm test -- -u --coverage

7、可以看到所有的测试都通过了。接下来运行 npm run build命令

[root@host-192-100-36-247 client]# npm run build

运行完会在当前目录下生成build和coverage两个文件夹

8、

5.智能合约部署

1、herocu

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值