当前位置: 首页 > news >正文

从0搭建Hyperledger Fabric2.5环境

Hyperledger Fabric 2.5环境搭建

一.Linux环境准备

# root登录
yum -y install git curl docker docker-compose tree
yum -y install autoconf autotools-dev automake m4 perl
yum -y install libtool
autoreconf -ivf
# 安装jq相关包
cd /opt
git clone --recursive https://github.com/jqlang/jq.git
cd jq
autoreconf -i
./configure --disable-maintainer-mode
make
make install# 强制删除之前的镜像
docker rmi --force $(docker images -q)# 创建用户,设置密码
useradd fabric
passwd fabric
# 添加sudo权限
vi /etc/sudoers
# 在wheel下添加fabric配置
## Same thing without a password
# %wheel        ALL=(ALL)       NOPASSWD: ALL
fabric          ALL=(ALL)       NOPASSWD: ALL
# :wq保存
# 验证是否配置成功
[root@localhost ~]# visudo -cf /etc/sudoers
/etc/sudoers:解析正确# 切换fabric用户
su - fabric# 安装过后检查版本
docker --version
docker-compose --version
# docker后台运行
sudo systemctl start docker
# 开机自启
sudo systemctl enable docker
# 用户添加到组
sudo usermod -a -G docker fabric# 安装go
cd /home/fabric
wget https://golang.google.cn/dl/go1.20.5.linux-amd64.tar.gz
mkdir godir
tar -zxvf go1.20.5.linux-amd64.tar.gz -C ./godir
# 配置环境变量
sudo vi /etc/profile
#golang env config,1.18版本之后无需export GO111MODULE=on,可不设置gopath
export GOROOT=/home/fabric/godir/go
export PATH=$PATH:$GOROOT/bin
export GOPROXY=https://goproxy.cnsource /etc/profile
# 设置代理或者
# go env -w GOPROXY=https://goproxy.cn,direct

二.安装Fabric 、Fabric Samples

  • 克隆超级账本/结构样本存储库。
  • 下载最新的Hyperledger Fabric Docker镜像并将其标记为latest
  • 将以下特定于平台的超级账本 Fabric CLI 工具二进制文件和配置文件下载到fabric-samples /bin 和 /config目录中。

这些二进制文件将帮助您与测试网络进行交互。fabric-samples/bin/config

configtxgen,
configtxlator,
cryptogen,
discover,
idemixgen,
orderer,
osnadmin,
peer,
fabric-ca-client,
fabric-ca-server

下载示例、Docker镜像和二进制文件

su - fabric
# 创建目录
mkdir -p $HOME/go/src/github.com/myproject
cd $HOME/go/src/github.com/myproject
# 获取安装脚本
curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh && chmod +x install-fabric.sh
# 查看帮助
./install-fabric.sh -h

在这里插入图片描述

选择组件

  • docker以使用 Docker 下载结构容器镜像
  • podman使用 podman 下载结构容器镜像
  • binary下载结构二进制文件
  • samples将构造示例 GitHub 存储库克隆到当前目录
# 下载之前修改脚本,添加github代理
#在download附近的https,前面加上https://ghproxy.com/
download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}"
修改为
download "${BINARY_FILE}" "https://ghproxy.com/https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}"download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}"
修改为
download "${CA_BINARY_FILE}" "https://ghproxy.com/https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}"# 执行安装,当前默认fabric 2.5.0, fabric-ca 1.5.6
./install-fabric.sh docker samples binary
or
./install-fabric.sh d s b# 若需要选择fabric版本,则执行如下
# --fabric-version -ca-version 简写分别为-f -c,此处默认ca 1.5.6版本
# ./install-fabric.sh --fabric-version 2.5.0 binary

三.运行测试网络(test network)

启动test network

启动网络,创建一个orderer 两个peer,此时不含通道

cd fabric-samples/test-network
# 删除之前运行的容器或项目
./network.sh down
# 清理容器
docker ps -qa | xargs docker rm
# 启动网络,创建一个orderer 两个peer,此时不含通道
./network.sh up# 查看test-network运行的容器
docker ps -a

在这里插入图片描述

与Fabric 网络交互的每个节点和用户都需要属于 组织,以便参与网络。测试内容 网络包括两个对等组织,即组织1 和组织 2。它还包括一个维护网络排序服务的排序者组织。

Peers 节点存储区块链分类账并在交易之前验证交易 提交到账本。Peers运行包含业务的智能合约 用于管理区块链账本上的资产的逻辑。

网络中的每个peer都需要属于一个组织。在test network中每个组织各自运行一个peer,如peer0.org1.example.com,peer0.org2.example.com

每个Fabric网络还包括一个ordering service (排序服务)。 当peer验证事务并将事务块添加到 区块链分类账,他们不决定交易顺序或包括 他们进入新的块。在分布式网络上,peer可能彼此相距很远,并且对事务何时创建没有共同的看法。就交易顺序达成共识是一个成本高昂的过程,会给peer带来很高的开销。

ordering service (排序服务)允许peer专注于验证交易和 将它们提交到账本。排序节点从客户端收到背书交易后,他们就交易顺序达成共识,然后添加交易信息到区块中。然后将区块分发到peer节点,peer节点将区块添加到区块链分类账本中。

示例网络使用由orderer组织运营的单节点Raft ordering service (orderer.example.com)。
测试网络:单节点排序服务
生产环境:多个排序节点,一个或多个orderer 组织。
不同的排序节点将使用 Raft 共识算法就网络上的交易顺序达成一致。

四.创建通道channel

在 Org1和Org2之间交易创建Fabric通道。通道是特定网络成员之间的专用通信层。 通道只能由受邀加入通道的组织使用,并且对网络的其他成员不可见。每个通道都有一个单独的区块链分类账。已被邀请的组织将其peers加入通道,以存储通道分类账并验证通道上的交易。

# 创建默认通道 mychannel
./network.sh createChannel
# 自定义通道名称
#./network.sh createChannel -c channel1
# 创建多个通道,上述创建完成后,还可以创建通道
./network.sh createChannel -c channel2# 若需要创建通道和启动网络,则可执行
# ./network.sh up createChannel

在这里插入图片描述

在这里插入图片描述

创建通道日志

[fabric@localhost test-network]$ ./network.sh createChannel
Using docker and docker-compose
Creating channel 'mychannel'.
If network is not up, starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb 
Network Running Already
Using docker and docker-compose
Generating channel genesis block 'mychannel.block'
/home/fabric/go/src/github.com/myproject/fabric-samples/bin/configtxgen
+ configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/mychannel.block -channelID mychannel
2023-06-08 21:59:38.056 CST 0001 INFO [common.tools.configtxgen] main -> Loading configuration
2023-06-08 21:59:38.065 CST 0002 INFO [common.tools.configtxgen.localconfig] completeInitialization -> orderer type: etcdraft
2023-06-08 21:59:38.066 CST 0003 INFO [common.tools.configtxgen.localconfig] completeInitialization -> Orderer.EtcdRaft.Options unset, setting to tick_interval:"500ms" election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216 
2023-06-08 21:59:38.066 CST 0004 INFO [common.tools.configtxgen.localconfig] Load -> Loaded configuration: /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/configtx/configtx.yaml
2023-06-08 21:59:38.069 CST 0005 INFO [common.tools.configtxgen] doOutputBlock -> Generating genesis block
2023-06-08 21:59:38.069 CST 0006 INFO [common.tools.configtxgen] doOutputBlock -> Creating application channel genesis block
2023-06-08 21:59:38.070 CST 0007 INFO [common.tools.configtxgen] doOutputBlock -> Writing genesis block
+ res=0
Creating channel mychannel
Using organization 1
+ osnadmin channel join --channelID mychannel --config-block ./channel-artifacts/mychannel.block -o localhost:7053 --ca-file /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --client-cert /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt --client-key /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
+ res=0
Status: 201
{"name": "mychannel","url": "/participation/v1/channels/mychannel","consensusRelation": "consenter","status": "active","height": 1
}Channel 'mychannel' created
Joining org1 peer to the channel...
Using organization 1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2023-06-08 21:59:44.252 CST 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-06-08 21:59:44.281 CST 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel
Joining org2 peer to the channel...
Using organization 2
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2023-06-08 21:59:47.363 CST 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-06-08 21:59:47.392 CST 0002 INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel
Setting anchor peer for org1...
Using organization 1
Fetching channel config for channel mychannel
Using organization 1
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
2023-06-08 13:59:47.844 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-06-08 13:59:47.850 UTC 0002 INFO [cli.common] readBlock -> Received block: 0
2023-06-08 13:59:47.850 UTC 0003 INFO [channelCmd] fetch -> Retrieving last config block: 0
2023-06-08 13:59:47.852 UTC 0004 INFO [cli.common] readBlock -> Received block: 0
Decoding config block to JSON and isolating config to Org1MSPconfig.json
+ configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
+ jq '.data.data[0].payload.data.config' config_block.json
Generating anchor peer update transaction for Org1 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' Org1MSPconfig.json
+ configtxlator proto_encode --input Org1MSPconfig.json --type common.Config --output original_config.pb
+ configtxlator proto_encode --input Org1MSPmodified_config.json --type common.Config --output modified_config.pb
+ configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb --output config_update.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
+ jq .
++ cat config_update.json
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"mychannel",' '"isolated_data":' '{},' '"read_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org1MSP":' '{' '"groups":' '{},' '"mod_policy":' '"",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '},' '"write_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org1MSP":' '{' '"groups":' '{},' '"mod_policy":' '"Admins",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"AnchorPeers":' '{' '"mod_policy":' '"Admins",' '"value":' '{' '"anchor_peers":' '[' '{' '"host":' '"peer0.org1.example.com",' '"port":' 7051 '}' ']' '},' '"version":' '"0"' '},' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output Org1MSPanchors.tx
2023-06-08 13:59:48.413 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-06-08 13:59:48.433 UTC 0002 INFO [channelCmd] update -> Successfully submitted channel update
Anchor peer set for org 'Org1MSP' on channel 'mychannel'
Setting anchor peer for org2...
Using organization 2
Fetching channel config for channel mychannel
Using organization 2
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
2023-06-08 13:59:48.945 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-06-08 13:59:48.950 UTC 0002 INFO [cli.common] readBlock -> Received block: 1
2023-06-08 13:59:48.950 UTC 0003 INFO [channelCmd] fetch -> Retrieving last config block: 1
2023-06-08 13:59:48.952 UTC 0004 INFO [cli.common] readBlock -> Received block: 1
Decoding config block to JSON and isolating config to Org2MSPconfig.json
+ configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
+ jq '.data.data[0].payload.data.config' config_block.json
Generating anchor peer update transaction for Org2 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' Org2MSPconfig.json
+ configtxlator proto_encode --input Org2MSPconfig.json --type common.Config --output original_config.pb
+ configtxlator proto_encode --input Org2MSPmodified_config.json --type common.Config --output modified_config.pb
+ configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb --output config_update.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
+ jq .
++ cat config_update.json
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"mychannel",' '"isolated_data":' '{},' '"read_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org2MSP":' '{' '"groups":' '{},' '"mod_policy":' '"",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '},' '"write_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org2MSP":' '{' '"groups":' '{},' '"mod_policy":' '"Admins",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"AnchorPeers":' '{' '"mod_policy":' '"Admins",' '"value":' '{' '"anchor_peers":' '[' '{' '"host":' '"peer0.org2.example.com",' '"port":' 9051 '}' ']' '},' '"version":' '"0"' '},' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output Org2MSPanchors.tx
2023-06-08 13:59:49.391 UTC 0001 INFO [channelCmd] InitCmdFactory -> Endorser and orderer connections initialized
2023-06-08 13:59:49.410 UTC 0002 INFO [channelCmd] update -> Successfully submitted channel update
Anchor peer set for org 'Org2MSP' on channel 'mychannel'
Channel 'mychannel' joined

通道名称注意事项

  1. 仅包含小写 ASCII 字母数字、点 ‘.’ 和短划线 ‘-’
  2. 少于 250 个字符
  3. 以字母开头

五.在通道上启动链码

通道之间分类账通过智能合约进行交互。

  1. 智能合约包含业务逻辑管理区块链分类账上的资产。网络成员运行的应用程序调用智能合约在分类账上创建资产、更改和转移这些资产。应用程序可查询智能合约以读取账本上的数据。

  2. 为了确保交易有效,使用智能合约创建的交易通常需要由多个组织签名才能提交到通道分类账。多重签名是 Fabric 信任模型不可或缺的一部分。要求对一笔交易进行多次背书可以防止渠道上的一个组织篡改其peer的分类账或使用未经同意的业务逻辑。要签署交易,每个组织都需要在其peer上调用并执行智能合约,然后对交易输出进行签名。如果输出是一致的,并且已经由足够多的组织签名,则可以将交易提交到分类账。指定通道上需要执行智能合约的集合组织的策略被称为背书策略,该策略是为每个链代码设置的,作为链代码定义的一部分。

  3. 在 Fabric 中,智能合约以称为链码。链码安装在组织的peer节点上,然后部署到通道中,可用于背书交易和与区块链分类账交互。在将链码部署到通道之前,通道的成员需要就建立链码治理的链码定义达成一致。当所需数量的组织达成一致时,可以将链码定义提交到通道,链码则可以使用。

在通道上启动链码

# 使用network.sh创建通道后,可以使用以下命令在通道上启动链代码:./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

deployCC 子命令将在peer0.org1.example.com和peer0.org2.example.com安装asset-transfer (basic)链码,在使用通道标志指定的通道上部署链码(默认mychannel)。第一次部署链码,将安装链码相关依赖。使用语言标志-ccl,可以指定安装Go、Typescript或 JavaScript 链码。 您可以在fabric-samples的asset-transfer-basic文件夹中找到asset-transfer (basic)链码。此文件夹包含作为示例提供的示例链码和教程。

在这里插入图片描述

链码日志

[fabric@localhost test-network]$ ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
Using docker and docker-compose
deploying chaincode on channel 'mychannel'
executing with the following
- CHANNEL_NAME: mychannel
- CC_NAME: basic
- CC_SRC_PATH: ../asset-transfer-basic/chaincode-go
- CC_SRC_LANGUAGE: go
- CC_VERSION: 1.0
- CC_SEQUENCE: 1
- CC_END_POLICY: NA
- CC_COLL_CONFIG: NA
- CC_INIT_FCN: NA
- DELAY: 3
- MAX_RETRY: 5
- VERBOSE: false
Vendoring Go dependencies at ../asset-transfer-basic/chaincode-go
~/go/src/github.com/myproject/fabric-samples/asset-transfer-basic/chaincode-go ~/go/src/github.com/myproject/fabric-samples/test-network
~/go/src/github.com/myproject/fabric-samples/test-network
Finished vendoring Go dependencies
+ peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go --lang golang --label basic_1.0
+ res=0
++ peer lifecycle chaincode calculatepackageid basic.tar.gz
+ PACKAGE_ID=basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57
Chaincode is packaged
Installing chaincode on peer0.org1...
Using organization 1
+ jq -r 'try (.installed_chaincodes[].package_id)'
+ grep '^basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57$'
+ peer lifecycle chaincode queryinstalled --output json
+ test 1 -ne 0
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2023-06-08 22:42:29.444 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nJbasic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57\022\tbasic_1.0" > 
2023-06-08 22:42:29.456 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57
Chaincode is installed on peer0.org1
Install chaincode on peer0.org2...
Using organization 2
+ grep '^basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57$'
+ peer lifecycle chaincode queryinstalled --output json
+ jq -r 'try (.installed_chaincodes[].package_id)'
+ test 1 -ne 0
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2023-06-08 22:43:52.357 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nJbasic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57\022\tbasic_1.0" > 
2023-06-08 22:43:52.396 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57
Chaincode is installed on peer0.org2
Using organization 1
+ jq -r 'try (.installed_chaincodes[].package_id)'
+ grep '^basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57$'
+ peer lifecycle chaincode queryinstalled --output json
+ res=0
basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57
Query installed successful on peer0.org1 on channel
Using organization 1
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID mychannel --name basic --version 1.0 --package-id basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57 --sequence 1
+ res=0
2023-06-08 22:43:54.752 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [536e459cb17675dffd66b390222e9c1fbbd260c7b2352e3c3cc79e2c00fd2934] committed with status (VALID) at localhost:7051
Chaincode definition approved on peer0.org1 on channel 'mychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": false}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": false}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'mychannel'
Using organization 2
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID mychannel --name basic --version 1.0 --package-id basic_1.0:e4de097efb5be42d96aebc4bde18eea848aad0f5453453ba2aad97f2e41e0d57 --sequence 1
+ res=0
2023-06-08 22:44:03.169 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [952e8fd42b124ae5006e7fd41816b1bc6dfb6320dcd6ccd7d09aedffc858dbe2] committed with status (VALID) at localhost:9051
Chaincode definition approved on peer0.org2 on channel 'mychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{"approvals": {"Org1MSP": true,"Org2MSP": true}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'mychannel'
Using organization 1
Using organization 2
+ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem --channelID mychannel --name basic --peerAddresses localhost:7051 --tlsRootCertFiles /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem --peerAddresses localhost:9051 --tlsRootCertFiles /home/fabric/go/src/github.com/myproject/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem --version 1.0 --sequence 1
+ res=0
2023-06-08 22:44:11.781 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [009e9c153fb77c941a1aa77735f83ffbd21fe7a6d7afd7db0c004399ca06627c] committed with status (VALID) at localhost:9051
2023-06-08 22:44:11.784 CST 0002 INFO [chaincodeCmd] ClientWait -> txid [009e9c153fb77c941a1aa77735f83ffbd21fe7a6d7afd7db0c004399ca06627c] committed with status (VALID) at localhost:7051
Chaincode definition committed on channel 'mychannel'
Using organization 1
Querying chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to Query committed status on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Querying chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to Query committed status on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org2 on channel 'mychannel'
Chaincode initialization is not required

六. 与网络交互

使用peer的CLI进行网络交互,peer CLI调用已部署的智能合约,更新通道或安装、部署新的智能合约。

环境变量设置

cd fabric-samples/test-network
# 确保能使用fabric-samples二进制文件
export PATH=${PWD}/../bin:$PATH
# 如configtxgen  configtxlator  cryptogen  discover  fabric-ca-client  fabric-ca-server  ledgerutil  orderer  osnadmin  peer# 设置FABRIC_CFG_PATH指向fabric-samples中的core.yaml的文件
export FABRIC_CFG_PATH=$PWD/../config/
ls $FABRIC_CFG_PATH

设置Org1的peer使用CLI的环境变量

# Environment variables for Org1export 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

CORE_PEER_TLS_ROOTCERT_FILE和CORE_PEER_MSPCONFIGPATH环境变量指向organizations文件夹中的Org1加密材料。

初始化账本

使用资产初始化账本,CLI 不访问Fabric Gateway peer,因此必须指定每个认可的peer。

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --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":"InitLedger","Args":[]}'

在这里插入图片描述

查询账本

从 CLI 查询账本,查询已添加到通道账本的资产列表。

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

在这里插入图片描述

查询结果

[{"AppraisedValue":300,"Color":"blue","ID":"asset1","Owner":"Tomoko","Size":5},{"AppraisedValue":400,"Color":"red","ID":"asset2","Owner":"Brad","Size":5},{"AppraisedValue":500,"Color":"green","ID":"asset3","Owner":"Jin Soo","Size":10},{"AppraisedValue":600,"Color":"yellow","ID":"asset4","Owner":"Max","Size":10},{"AppraisedValue":700,"Color":"black","ID":"asset5","Owner":"Adriana","Size":15},{"AppraisedValue":800,"Color":"white","ID":"asset6","Owner":"Michel","Size":15}]

资产转移

网络成员调用链码转移或更改账本上的资产。使用以下命令通过调用资产转移(基本)链码来更改账本上资产的所有者:

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --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":"TransferAsset","Args":["asset6","Christopher"]}'

在这里插入图片描述
因为资产转移(基本)链码的背书策略交易需要要由Org1和 Org2 签名,链码调用命令需要peer0.org1.example.com和peer0.org2.example.com使用–peerAddresses标记。网络启用了 TLS,因此该命令还需要–tlsRootCertFiles标志使用每个peer的 TLS 证书。

查询账本

在我们调用链码之后,我们可以使用另一个查询来查看调用如何 更改了区块链分类账上的资产。由于我们已经查询了 Org1 peer,我们可以查询 Org2 peer上运行的链码。将以下环境变量设置为作为 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
##在peer0.org2.example.com上查询asset-transfer (basic)链码
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'

在这里插入图片描述

七.关闭网络

该命令将停止并删除节点和链码容器,删除 组织加密材料,并从您的 Docker 注册表中删除链码镜像。该命令还会从以前的运行中删除通道和 docker卷 。

./network.sh down

八.目录结构

上述操作完成观察目录结构

cd fabric-samples/test-network
tree.
├── addOrg3
│   ├── addOrg3.sh
│   ├── ccp-generate.sh
│   ├── ccp-template.json
│   ├── ccp-template.yaml
│   ├── compose
│   │   ├── compose-ca-org3.yaml
│   │   ├── compose-couch-org3.yaml
│   │   ├── compose-org3.yaml
│   │   ├── docker
│   │   │   ├── docker-compose-ca-org3.yaml
│   │   │   ├── docker-compose-couch-org3.yaml
│   │   │   ├── docker-compose-org3.yaml
│   │   │   └── peercfg
│   │   │       └── core.yaml
│   │   └── podman
│   │       ├── peercfg
│   │       │   └── core.yaml
│   │       ├── podman-compose-ca-org3.yaml
│   │       ├── podman-compose-couch-org3.yaml
│   │       └── podman-compose-org3.yaml
│   ├── configtx.yaml
│   ├── fabric-ca
│   │   ├── org3
│   │   │   └── fabric-ca-server-config.yaml
│   │   └── registerEnroll.sh
│   ├── org3-crypto.yaml
│   └── README.md
├── basic.tar.gz
├── CHAINCODE_AS_A_SERVICE_TUTORIAL.md
├── channel-artifacts
│   ├── channel2.block
│   └── mychannel.block
├── compose
│   ├── compose-ca.yaml
│   ├── compose-couch.yaml
│   ├── compose-test-net.yaml
│   ├── docker
│   │   ├── docker-compose-ca.yaml
│   │   ├── docker-compose-couch.yaml
│   │   ├── docker-compose-test-net.yaml
│   │   └── peercfg
│   │       └── core.yaml
│   └── podman
│       ├── peercfg
│       │   └── core.yaml
│       ├── podman-compose-ca.yaml
│       ├── podman-compose-couch.yaml
│       └── podman-compose-test-net.yaml
├── configtx
│   └── configtx.yaml
├── log.txt
├── monitordocker.sh
├── network.sh
├── organizations
│   ├── ccp-generate.sh
│   ├── ccp-template.json
│   ├── ccp-template.yaml
│   ├── cryptogen
│   │   ├── crypto-config-orderer.yaml
│   │   ├── crypto-config-org1.yaml
│   │   └── crypto-config-org2.yaml
│   ├── fabric-ca
│   │   ├── ordererOrg
│   │   │   └── fabric-ca-server-config.yaml
│   │   ├── org1
│   │   │   └── fabric-ca-server-config.yaml
│   │   ├── org2
│   │   │   └── fabric-ca-server-config.yaml
│   │   └── registerEnroll.sh
│   ├── ordererOrganizations
│   │   └── example.com
│   │       ├── ca
│   │       │   ├── ca.example.com-cert.pem
│   │       │   └── priv_sk
│   │       ├── msp
│   │       │   ├── admincerts
│   │       │   ├── cacerts
│   │       │   │   └── ca.example.com-cert.pem
│   │       │   ├── config.yaml
│   │       │   └── tlscacerts
│   │       │       └── tlsca.example.com-cert.pem
│   │       ├── orderers
│   │       │   └── orderer.example.com
│   │       │       ├── msp
│   │       │       │   ├── admincerts
│   │       │       │   ├── cacerts
│   │       │       │   │   └── ca.example.com-cert.pem
│   │       │       │   ├── config.yaml
│   │       │       │   ├── keystore
│   │       │       │   │   └── priv_sk
│   │       │       │   ├── signcerts
│   │       │       │   │   └── orderer.example.com-cert.pem
│   │       │       │   └── tlscacerts
│   │       │       │       └── tlsca.example.com-cert.pem
│   │       │       └── tls
│   │       │           ├── ca.crt
│   │       │           ├── server.crt
│   │       │           └── server.key
│   │       ├── tlsca
│   │       │   ├── priv_sk
│   │       │   └── tlsca.example.com-cert.pem
│   │       └── users
│   │           └── Admin@example.com
│   │               ├── msp
│   │               │   ├── admincerts
│   │               │   ├── cacerts
│   │               │   │   └── ca.example.com-cert.pem
│   │               │   ├── config.yaml
│   │               │   ├── keystore
│   │               │   │   └── priv_sk
│   │               │   ├── signcerts
│   │               │   │   └── Admin@example.com-cert.pem
│   │               │   └── tlscacerts
│   │               │       └── tlsca.example.com-cert.pem
│   │               └── tls
│   │                   ├── ca.crt
│   │                   ├── client.crt
│   │                   └── client.key
│   └── peerOrganizations
│       ├── org1.example.com
│       │   ├── ca
│       │   │   ├── ca.org1.example.com-cert.pem
│       │   │   └── priv_sk
│       │   ├── connection-org1.json
│       │   ├── connection-org1.yaml
│       │   ├── msp
│       │   │   ├── admincerts
│       │   │   ├── cacerts
│       │   │   │   └── ca.org1.example.com-cert.pem
│       │   │   ├── config.yaml
│       │   │   └── tlscacerts
│       │   │       └── tlsca.org1.example.com-cert.pem
│       │   ├── peers
│       │   │   └── peer0.org1.example.com
│       │   │       ├── msp
│       │   │       │   ├── admincerts
│       │   │       │   ├── cacerts
│       │   │       │   │   └── ca.org1.example.com-cert.pem
│       │   │       │   ├── config.yaml
│       │   │       │   ├── keystore
│       │   │       │   │   └── priv_sk
│       │   │       │   ├── signcerts
│       │   │       │   │   └── peer0.org1.example.com-cert.pem
│       │   │       │   └── tlscacerts
│       │   │       │       └── tlsca.org1.example.com-cert.pem
│       │   │       └── tls
│       │   │           ├── ca.crt
│       │   │           ├── server.crt
│       │   │           └── server.key
│       │   ├── tlsca
│       │   │   ├── priv_sk
│       │   │   └── tlsca.org1.example.com-cert.pem
│       │   └── users
│       │       ├── Admin@org1.example.com
│       │       │   ├── msp
│       │       │   │   ├── admincerts
│       │       │   │   ├── cacerts
│       │       │   │   │   └── ca.org1.example.com-cert.pem
│       │       │   │   ├── config.yaml
│       │       │   │   ├── keystore
│       │       │   │   │   └── priv_sk
│       │       │   │   ├── signcerts
│       │       │   │   │   └── Admin@org1.example.com-cert.pem
│       │       │   │   └── tlscacerts
│       │       │   │       └── tlsca.org1.example.com-cert.pem
│       │       │   └── tls
│       │       │       ├── ca.crt
│       │       │       ├── client.crt
│       │       │       └── client.key
│       │       └── User1@org1.example.com
│       │           ├── msp
│       │           │   ├── admincerts
│       │           │   ├── cacerts
│       │           │   │   └── ca.org1.example.com-cert.pem
│       │           │   ├── config.yaml
│       │           │   ├── keystore
│       │           │   │   └── priv_sk
│       │           │   ├── signcerts
│       │           │   │   └── User1@org1.example.com-cert.pem
│       │           │   └── tlscacerts
│       │           │       └── tlsca.org1.example.com-cert.pem
│       │           └── tls
│       │               ├── ca.crt
│       │               ├── client.crt
│       │               └── client.key
│       └── org2.example.com
│           ├── ca
│           │   ├── ca.org2.example.com-cert.pem
│           │   └── priv_sk
│           ├── connection-org2.json
│           ├── connection-org2.yaml
│           ├── msp
│           │   ├── admincerts
│           │   ├── cacerts
│           │   │   └── ca.org2.example.com-cert.pem
│           │   ├── config.yaml
│           │   └── tlscacerts
│           │       └── tlsca.org2.example.com-cert.pem
│           ├── peers
│           │   └── peer0.org2.example.com
│           │       ├── msp
│           │       │   ├── admincerts
│           │       │   ├── cacerts
│           │       │   │   └── ca.org2.example.com-cert.pem
│           │       │   ├── config.yaml
│           │       │   ├── keystore
│           │       │   │   └── priv_sk
│           │       │   ├── signcerts
│           │       │   │   └── peer0.org2.example.com-cert.pem
│           │       │   └── tlscacerts
│           │       │       └── tlsca.org2.example.com-cert.pem
│           │       └── tls
│           │           ├── ca.crt
│           │           ├── server.crt
│           │           └── server.key
│           ├── tlsca
│           │   ├── priv_sk
│           │   └── tlsca.org2.example.com-cert.pem
│           └── users
│               ├── Admin@org2.example.com
│               │   ├── msp
│               │   │   ├── admincerts
│               │   │   ├── cacerts
│               │   │   │   └── ca.org2.example.com-cert.pem
│               │   │   ├── config.yaml
│               │   │   ├── keystore
│               │   │   │   └── priv_sk
│               │   │   ├── signcerts
│               │   │   │   └── Admin@org2.example.com-cert.pem
│               │   │   └── tlscacerts
│               │   │       └── tlsca.org2.example.com-cert.pem
│               │   └── tls
│               │       ├── ca.crt
│               │       ├── client.crt
│               │       └── client.key
│               └── User1@org2.example.com
│                   ├── msp
│                   │   ├── admincerts
│                   │   ├── cacerts
│                   │   │   └── ca.org2.example.com-cert.pem
│                   │   ├── config.yaml
│                   │   ├── keystore
│                   │   │   └── priv_sk
│                   │   ├── signcerts
│                   │   │   └── User1@org2.example.com-cert.pem
│                   │   └── tlscacerts
│                   │       └── tlsca.org2.example.com-cert.pem
│                   └── tls
│                       ├── ca.crt
│                       ├── client.crt
│                       └── client.key
├── prometheus-grafana
│   ├── docker-compose.yaml
│   ├── grafana
│   │   ├── config.monitoring
│   │   └── provisioning
│   │       ├── dashboards
│   │       │   ├── dashboard.yml
│   │       │   └── hlf-performances.json
│   │       └── datasources
│   │           └── datasource.yml
│   ├── grafana_db
│   │   └── grafana.db
│   ├── prometheus
│   │   └── prometheus.yml
│   └── README.md
├── README.md
├── scripts
│   ├── ccutils.sh
│   ├── configUpdate.sh
│   ├── createChannel.sh
│   ├── deployCCAAS.sh
│   ├── deployCC.sh
│   ├── envVar.sh
│   ├── org3-scripts
│   │   ├── joinChannel.sh
│   │   └── updateChannelConfig.sh
│   ├── pkgcc.sh
│   ├── setAnchorPeer.sh
│   └── utils.sh
├── setOrgEnv.sh
└── system-genesis-block

九. Fabric CA使用

Hyperledger Fabric使用公钥基础设施(PKI)来验证所有网络参与者的行为。每个节点、网络管理员和提交交易的用户都需要有一个公共证书和私钥来验证其身份。这些身份需要有一个有效的信任根,确定这些证书是由一个网络成员的组织颁发的。network.sh脚本在创建peer节点和ordering节点之前,会创建所有部署和运行网络所需的加密材料。

  1. 默认network.sh脚本使用cryptogen工具来创建证书和密钥
  2. cryptogen工具用于开发和测试环境(为具有有效信任根的Fabric 组织快速创建所需的加密材料)

cryptogen 工具为 Org1、Org2 和 Orderer Org 创建证书和密钥。
在这里插入图片描述

测试和生产都可以使用CA创建组织身份。
生产环境:每个组织运行一个CA(或多个中间CA)
一个组织执行的CA创建的所有身份都共享一个信任根。

# 使用CA启动测试网络
./network down
./network.sh up -ca
# network.sh会调用organizations/fabric-ca/registerEnroll.sh脚本生成加密文件

在这里插入图片描述
在这里插入图片描述

使用Fabric CA客户端向每个组织的CA注册节点和用户身份。

  1. 脚本使用 enroll 命令为每个身份生成一个 MSP 文件夹。
  2. MSP文件夹包含了每个身份的证书和私钥,并建立了该身份在运营CA的组织中的角色和成员资格。
# 查看MSP文件夹内容
tree organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/
# organizations/peerOrganizations/org1.example.com
# 使用cryptogen生成的结构
│       │   └── users
│       │       ├── Admin@org1.example.com
│       │       │   ├── msp
│       │       │   │   ├── admincerts
│       │       │   │   ├── cacerts
│       │       │   │   │   └── ca.org1.example.com-cert.pem
│       │       │   │   ├── config.yaml
│       │       │   │   ├── keystore
│       │       │   │   │   └── priv_sk
│       │       │   │   ├── signcerts
│       │       │   │   │   └── Admin@org1.example.com-cert.pem
│       │       │   │   └── tlscacerts
│       │       │   │       └── tlsca.org1.example.com-cert.pem
│       │       │   └── tls
│       │       │       ├── ca.crt
│       │       │       ├── client.crt
│       │       │       └── client.key# 使用CA后的结构
│       │   └── users
│       │       ├── Admin@org1.example.com
│       │       │   └── msp
│       │       │       ├── cacerts
│       │       │       │   └── localhost-7054-ca-org1.pem
│       │       │       ├── config.yaml
│       │       │       ├── IssuerPublicKey
│       │       │       ├── IssuerRevocationPublicKey
│       │       │       ├── keystore
│       │       │       │   └── 9f6fe34d35072af8dbfb800ba739fb0e7978d4340bf77333e2ac62c138732d39_sk
│       │       │       ├── signcerts
│       │       │       │   └── cert.pem
│       │       │       └── user

管理用户证书:signcerts/cert.pem
私钥:keystore/xxxx_sk

查看证书内容

cd fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/msp/signcertsopenssl x509 -in cert.pem -inform pem -noout -text

相关文章:

从0搭建Hyperledger Fabric2.5环境

Hyperledger Fabric 2.5环境搭建 一.Linux环境准备 # root登录 yum -y install git curl docker docker-compose tree yum -y install autoconf autotools-dev automake m4 perl yum -y install libtool autoreconf -ivf # 安装jq相关包 cd /opt git clone --recursive https…...

Rust每日一练(Leetday0026) 最小覆盖子串、组合、子集

目录 76. 最小覆盖子串 Minimum Window Substring &#x1f31f;&#x1f31f;&#x1f31f; 77. 组合 Combinations &#x1f31f;&#x1f31f; 78. 子集 Subsets &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Gola…...

c# 从零到精通-ArrayList-Hashtable的操作

c# 从零到精通-ArrayList-Hashtable的操作 1、ArrayList的操作 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace Test11 { class Program { static void Main(string[] args) { ArrayList list …...

pnpm带来了什么

首先 pnpm 和 npm yarn 一样是包管理工具&#xff0c;他解决了npm 和 yarn 存在的一些问题 npm3之前每个依赖都是一层嵌套一层的&#xff0c;每个依赖里都有node_modules 用来存放依赖所需的依赖包导致重复下载的依赖包很多&#xff0c;一层层嵌套&#xff0c;嵌套很深&#x…...

图像分类模型嵌入flask中开发PythonWeb项目

图像分类模型嵌入flask中开发PythonWeb项目 图像分类是一种常见的计算机视觉任务&#xff0c;它的目的是将输入的图像分配到预定义的类别中&#xff0c;如猫、狗、花等。图像分类模型是一种基于深度学习的模型&#xff0c;它可以利用大量的图像数据来学习图像的特征和类别之间…...

GIT安装教程(入门)

目录 前言 Git作者 官网 GIT优点 GIT缺点 为什么要使用 Git 下载以及安装步骤 一、官网下载 二、GIT安装步骤 1、安装get程序 2、许可声明 3、选择安装路径 4、选择git组件 5、创建菜单名称 6、 git文件默认编辑器 7、设置新存储库中初始分支的名称 8、调整Pa…...

全志V3S嵌入式驱动开发(触摸屏驱动)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 所谓的触摸屏&#xff0c;其实就是在普通的lcd屏幕之上&#xff0c;再加一层屏而已。这个屏是透明的&#xff0c;这样客户就可以看到下面lcd屏幕的…...

死信队列详解

什么是死信队列&#xff1f; 在消息队列中&#xff0c;执行异步任务时&#xff0c;通常是将消息生产者发布的消息存储在队列中&#xff0c;由消费者从队列中获取并处理这些消息。但是&#xff0c;在某些情况下&#xff0c;消息可能无法正常地被处理和消耗&#xff0c;例如&…...

我用ChatGPT写2023高考语文作文(五):北京卷I

2023年 北京卷 I 适用地区&#xff1a;北京 “续航”一词&#xff0c;原指连续航行&#xff0c;今天在使用中被赋予了新的含义&#xff0c;如为青春续航、科技为经济发展续航等。 请以“续航”为题目&#xff0c;写一篇议论文。 要求&#xff1a;论点明确&#xff0c;论据充实&…...

《微服务实战》 第二十八章 分布式锁框架-Redisson

前言 Redisson 在基于 NIO 的 Netty 框架上&#xff0c;充分的利⽤了 Redis 键值数据库提供的⼀系列优势&#xff0c;在Java 实⽤⼯具包中常⽤接⼝的基础上&#xff0c;为使⽤者提供了⼀系列具有分布式特性的常⽤⼯具类。使得原本作为协调单机多线程并发程序的⼯具包获得了协调…...

局部搜索,变邻域搜索算法

目录 局部搜索 02 变邻域搜索算法 局部搜索 1.1 局部搜索是什么玩意儿? 官方一点:局部搜索是解决优化问题的一种启发式算法。对于某些计算起来非常复杂的优化问题,比如各种NP-难问题,要找到最优解需要的时间随问题规模呈指数增长,因此诞生了各种启发式算法来退而求其次…...

软件工程实训——第一天

第一天 前后分离 前端&#xff1a;android 后端&#xff1a;springbootmbatis-plus 高心星 软件工程的思维来开发项目 问题定义 可行性研究 需求分析 概要设计 详细设计 编码 测试 维护 需求分析 1.用户的信息管理 2.新增支出 3.新增收入 4.支出统计 5.收入…...

嵌入式C语言中if/else如何优化详解

观点一&#xff08;灵剑&#xff09;&#xff1a; 前期迭代懒得优化&#xff0c;来一个需求&#xff0c;加一个if&#xff0c;久而久之&#xff0c;就串成了一座金字塔。 当代码已经复杂到难以维护的程度之后&#xff0c;只能狠下心重构优化。那&#xff0c;有什么方案可以优雅…...

【LSTM】读取时间序列数据 | 时间序列数据的小批量划分方法

由于序列数据本质上是连续的&#xff0c;因此我们在处理数据时需要解决这个问题。当序列过长而不能被模型一次性全部处理时&#xff0c;我们希望能拆分这样的序列以便模型方便读取。 Q&#xff1a;怎样随机生成一个具有n个时间步的mini batch的特征和标签&#xff1f; A&…...

K8s in Action 阅读笔记——【12】Securing the Kubernetes API server

K8s in Action 阅读笔记——【12】Securing the Kubernetes API server 12.1 Understanding authentication 在上一章中&#xff0c;我们提到API服务器可以配置一个或多个认证插件&#xff08;授权插件也是同样的情况&#xff09;。当API服务器接收到一个请求时&#xff0c;它…...

爆肝整理,3个月从功能进阶自动化测试,一跃成测试卷王...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 首先先了解自动化…...

人生这场概率游戏,怎么玩

只会标准答案&#xff0c;是不可救药的愚蠢 那么为了便于理解&#xff0c;我用一些典型的案例来讲解&#xff0c;什么是概率游戏&#xff0c;以及这个游戏&#xff0c;应该怎么玩。 比如典型的相亲&#xff0c;婚恋。人生大事&#xff0c;用标准答案来说&#xff0c;你的意中人…...

Redis笔记

缓存过期时间很重要&#xff01;redis是单线程的 对于内存过多的3中方案&#xff1a; 惰性删除&#xff1a; 在定时删除的基础上&#xff0c;对于已经过期了的数据&#xff0c;redis的随机选择算法一直没有选中这个数据&#xff0c;所以导致它就一直没被删除&#xff0c;但是…...

centos 安装supervisor并运行网站

前言 之前一直用宝塔的**进程守护管理器【Supervisor】**来启动一些项目,如ThinkPHP、Hyperf的项目,或laravel的一些命令。如果不用宝塔怎么办呢? 一、简介[supervisor] [Supervisor] 是用Python开发的一个client/server服务,是Linux/Unix系统下的一个进程管理工具,不支…...

Hadoop面试题十道

问题 1&#xff1a;Hadoop是什么&#xff1f; 答案&#xff1a;Hadoop是一个开源的分布式计算框架&#xff0c;用于处理大规模数据集的存储和处理。它基于Google的MapReduce和Google文件系统&#xff08;GFS&#xff09;的思想&#xff0c;旨在解决大数据量的处理和分析问题。…...

使用Docker-Compose对Docker容器集群快速编排

目录 一、Docker-Compose1、Docker-Compose使用场景2、Docker-Compose简介3、Docker-Compose安装部署4、YAML 文件格式及编写注意事项5、Docker Compose配置常用字段6、Docker Compose 常用命令7、Docker Compose 文件结构8、docker Compose撰写nginx 镜像9、docker Compose撰写…...

React-Redux 对Todolist修改

在单独使用redux的时候 需要手动订阅store里面 感觉特别麻烦 不错的是react有一个组件可以帮我们解决这个问题, 那就是react-redux。 react-redux提供了Provider 和 connent给我们使用。 先说一下几个重点知道的知识 Provider 就是用来提供store里面的状态 自动getState()co…...

初识微信小程序

新建小程序 创建一个新的微信小程序项目&#xff1a; 打开微信开发者工具&#xff0c;点击“新建项目”。 在弹出的窗口中&#xff0c;填写小程序的 AppID、项目名称和项目目录等信息。 点击“确定”按钮&#xff0c;等待微信开发者工具自动下载并安装所需的依赖库和框架。 …...

我们该如何入门编程呢

提醒&#xff1a;以下内容仅做参考&#xff0c;可自行发散。在发布作品前&#xff0c;请把不需要的内容删掉。 随着信息技术的快速发展&#xff0c;编程已经成为一个越来越重要的技能。那么&#xff0c;我们该如何入门编程呢&#xff1f;选择编程语言&#xff1a;选择一种编程…...

App 软件开发《判断6》试卷及答案

App 软件开发《判断6》试卷及答案 文章目录 App 软件开发《判断6》试卷及答案判断题&#xff08;对的打“√”&#xff0c;错的打“”&#xff1b;共0分&#xff09;1&#xff0e;”ionic resources --icon"命令用于生成适应不同分辨率的App图标所应用的图片。(✔)2&#…...

MVC工作原理

MVC工作原理 有视图的情况 1.客户端&#xff08;浏览器&#xff09;发起请求&#xff0c;DispatcherServlet拦截请求。 2.DispatcherServlet根据请求信息调用HandlerMapping。HandlerMapping根据uri去匹配查询能处理的Handler&#xff08;也就是我们所说的Controller&#x…...

使用 Redis 统计网站 UV 的方法

使用 Redis 统计网站 UV 的方法(概率算法) 文章目录 前言思路HyperLogLog 使用 Redis 命令操作使用 Java 代码操作 HyperLogLog 实现原理及特点使用 Java 实现 HyperLogLog小结 前言 网站 UV 就是指网站的独立用户访问量Unique Visitor&#xff0c;即相同用户的多次访问需要…...

黑客工具软件大全

黑客工具软件大全100套 给大家准备了全套网络安全梓料&#xff0c;有web安全&#xff0c;还有渗透测试等等内容&#xff0c;还包含电子书、面试题、pdf文档、视频以及相关的网络安全笔记 &#x1f447;&#x1f447;&#x1f447; 《黑客&网络安全入门&进阶学习包》 &a…...

uniapp主题切换功能的第二种实现方式(scss变量+require)

在上一篇 “uniapp主题切换功能的第一种实现方式&#xff08;scss变量vuex&#xff09;” 中介绍了第一种如何切换主题&#xff0c;但我们总结出一些不好的地方&#xff0c;例如扩展性不强&#xff0c;维护起来也困难等等&#xff0c;那么接下我再给大家介绍另外一种切换主题的…...

# 蓝牙音频相关知识

蓝牙音频相关知识 文章目录 蓝牙音频相关知识1 音频源2 蓝牙音频编解码器3 一些标准4 蓝牙音频其他相关知识4.1 蓝牙版本4.2 ANC&#xff08;主动降噪&#xff09;4.3 音响相关参数4.4 音质评价4.5 HI-Fi声音特点4.6 耳机线材4.7 耳机分类4.8 IP防尘防水等级4.9 噪音与量化噪音…...

山东天成水利建设有限公司网站/seo工资一般多少

如果你有一个苹果&#xff0c;我有一个苹果我们交换以后&#xff0c;还是一人一个苹果但如果你有一种思想&#xff0c;我有一种思想我们交换以后&#xff0c;每个人便拥有了两种思想&#xff1b; 转载于:https://www.cnblogs.com/JoinZhang/archive/2006/01/03/310096.html...

深圳建站公司优化/黄石市seo关键词优化怎么做

由于项目中大量用到了DataSet之类的东西&#xff0c;而vs2003下没有什么好用的查看工具&#xff0c;在网上查相关工具的时候&#xff0c;发现Codeproject上有两个比较合适的工具&#xff0c;其中又以http://www.codeproject.com/csharp/DataSetQuickWatchExt.asp的作法最为理想…...

白银市建设局网站王浩/管理培训班

10月1日-10月7日&#xff0c;我们携手8家战略媒体&#xff0c;99家合作媒体&#xff0c;开展了“国庆soulmate寻缘之旅”为期七天的活动。 突破以往的活动形式&#xff0c; 国庆寻缘之旅分为三个阶段“初识”、“相知”、“相恋”&#xff0c;从陌生到熟悉&#xff0c;让寻缘的…...

河源建设用地竞拍网站/百度最新秒收录方法2023

一&#xff0c;Activity的主要作用 Activity位于src目录下面&#xff0c;创建的Activity继承Activity类&#xff0c;并且要重写onCreate方法。可以把Activity理解成.net里面的Form,只不过.net里面的Form上面的控件是可见的&#xff0c;是我们托拉拽上去的&#xff0c;而Activit…...

做属于公司的网站有什么好处/爱廷玖达泊西汀

我相信大家在用nohup 后台起线程的时候都会遇到这样一个问题&#xff0c;随着nohup运行次数的增加&#xff0c;会导致本机上有许多nohup.out 文件。 这些nohup.out 文件分散在系统的各个位置&#xff0c;会导致占用许多的空间&#xff0c;这里我写了一个脚本用来删除本机上的所…...

招聘网站源码下载/app推广兼职是诈骗吗

ps命令时显示当前系统进程信息的命令&#xff0c;与top不同的是&#xff0c;ps返回的事当前活动进程的信息清单。所以&#xff0c;如果想要得到动态更新显示的信息&#xff0c;使用top命令。 默认ps&#xff1a; 选定所有有效进程&#xff08;EUID&#xff09;转载于:https://w…...