从0开始搭建Hyperledger Fabric2.x环境(fabric2.5版本)

news2025/1/19 2:20:52

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.cn

source /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 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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/625981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考A计划-系统架构师-官方考试指定教程-(8/15)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Redis从入门到精通【进阶篇】之数据类型Stream详解和使用示例

文章目录 0.前言1. 基本概念1.1. Stream的结构1.2. 持久化1.3. Stream的消费者组 2.实现原理2.1. Stream的数据结构2.2. Stream的消息追加2.3. Stream的消费2.4. Stream的消费者组 3.Redis Stream底层原理3.1. 基数树&#xff08;Radix Tree&#xff09;3.2. listpacks小结 4.命…

数据清洗、数据处理入门!R语言我来了,数据不再零散!

一、引言 数据清洗和预处理是数据科学中必不可少的一部分&#xff0c;它们能够帮助我们准确地分析和预测未来趋势。如果你曾经尝试过进行分析或建模&#xff0c;你会发现数据往往不像我们所想象的那样干净、整洁。需要对数据进行仔细的检查、清理和处理&#xff0c;才能真正把…

JavaSE笔记(五)重制版

泛型程序设计 在前面我们学习了最重要的类和对象&#xff0c;了解了面向对象编程的思想&#xff0c;注意&#xff0c;非常重要&#xff0c;面向对象是必须要深入理解和掌握的内容&#xff0c;不能草草结束。在本章节&#xff0c;我们还会继续深入了解&#xff0c;从泛型开始&a…

delphi D11编程语言手册 学习笔记(P344-392) 接口/类操作

P344-365 接口 "接口" 的概念和 "类" 特别是 "抽象类" 近似, Delphi 之初并没有接口, 后来(Delphi 3)为了支持 COM 引入了接口, 再后来发展成为 Delphi 重要的语言特性. 使用 COM 步骤可能是这样的:     1.程序在使用组件之初, 先联系 "…

Java-API简析_java.util.ArrayList类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131119289 出自【进步*于辰的博客】 其实我的【Java-API】专栏内的博文对大家来说意义是不大的。…

2023最新ChatGPT商业版4.8.8支持GPT4.0+AI绘画midjourney+实时语音识别输入+后台一键版本更新!

2023最新ChatGPT商业版4.8.8支持GPT4.0AI绘画midjourney永久更新&#xff01; 1.网站系统源码介绍&#xff1a; 程序已支持ChatGPT4.0、Midjourney绘画、GPT3.5 API绘画、语音识别输入、用户会员套餐用户每日签到功能后台管理一键更新版本。支持手机电脑不同布局页面自适应。…

【MySQL 数据库】6、一篇文章学习【索引知识】,提高大数据量的查询效率【文末送书】

目录 一、索引概述二、索引结构(1) 不同类型的索引结构(2) 二叉树和红黑树(3) B 树(4) B树(5) Hash(6) 为什么InnoDB存储引擎选择使用Btree索引结构相对于二叉树&#xff0c;层级更少&#xff0c;搜索效率高&#xff1b; 三、索引的分类(1) 聚集索引和二级索引(2) 思考题 四、索…

STM32之FreeRTOS

目录 FreeRTOS 介绍 什么是 FreeRTOS &#xff1f; 为什么选择 FreeRTOS ? FreeRTOS 资料与源码下载 祼机开发与 FreeRTOS 祼机开发&#xff1a; FreeRTOS&#xff1a; FreeRTOS 实现多任务的原理 二、移植 FreeRTOS 手动移植 使用CubeMX快速移植 快速移植流程…

基于Hadoop与Electron的京东商品评论词云统计系统

一、综合设计目的与要求 合肥工业大学软件工程专业《云计算、大数据技术与应用》课程综合设计报告。 爬取京东或淘宝某一商品的评论1000条&#xff0c;统计词频&#xff08;使用MapReduce或HBase或Hive&#xff09;&#xff0c;并以词云的方式可视化呈现&#xff0c;最后设计为…

python-面向对象:三大特性高级特性

文章目录 前言一、面向对象三大特性&#xff1a;封装、继承、多态1.对象和类2.封装3.继承(1)重写父类方法(2)多继承(3)私有属性与私有方法 4.多态 二、三大特性的应用1.链表的封装2.栈的封装3.队列的封装4.二叉树的封装 三、高级特性1.类属性与实例属性2.类方法与静态方法3.pro…

三相PWM整流器滞环电流控制MATLAB仿真模型

三相PWM整流器滞环电流控制MATLAB仿真模型资源-CSDN文库https://download.csdn.net/download/weixin_56691527/87882090 模型简介&#xff1a; 该模型采用滞环电流控制方法来控制PWM整流器&#xff0c;在matlab/simulink中实现。电流内环采用三个滞环比较器&#xff0c;电压外…

C#,码海拾贝(38)——求解“线性方程组”的“高斯-赛德尔迭代法”之C#源代码

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> /…

Nacos架构与原理 - 自研 Distro 协议 (AP分布式协议)

文章目录 背景设计思想Distro 协议工作原理数据初始化数据校验写操作读操作 小结 背景 Distro 协议是 Nacos 社区自研的⼀种 AP 分布式协议&#xff0c;是面向临时实例设计的⼀种分布式协议&#xff0c;其保证了在某些 Nacos 节点宕机后&#xff0c;整个临时实例处理系统依旧可…

VMware Workstation 17 安装教程

哈喽&#xff0c;大家好。今天一起学习的是VMware Workstation 17的安装&#xff0c;vm虚拟机是小编非常喜欢的生产力软件&#xff0c;小编之前发布的测试教程钧在vm上进行的实验。 VMware Workstation是一款功能强大的桌面虚拟计算机软件&#xff0c;它能够让用户在宿主机操作…

mac 电脑CPU温度怎么看?怎么可以监控Mac CPU温度,为什么我的 MacBook Air 这么热?

众所周知&#xff0c;电脑温度太高会直接影响到系统运行速度&#xff0c;对硬盘伤害也是很大的。特别是夏天&#xff0c;Mac 笔记本有时候运行起来会比较烫。关于 Mac 笔记本的散热&#xff0c;见仁见智。但是我们也比较好奇 CPU、电池的温度。怎么查看Mac CPU温度呢&#xff1…

【Linux工具】编译器、调式器、项目自动化构建工具以及git的使用(1编译器)

【Linux工具】编译器、调式器、项目自动化构建工具以及git的使用&#xff08;1&#xff09; 目录 【Linux工具】编译器、调式器、项目自动化构建工具以及git的使用&#xff08;1&#xff09;Linux编译器-gcc/g使用gcc的编译过程预处理&#xff08;进行宏替换&#xff09;编译&a…

2023/6/8总结

MySQL必知必会 commit 和 rollback 的差异是commit会提交&#xff0c;而rollback不会&#xff0c;就好像是撤回。 使用保留点&#xff1a; 简单的rollback和commit语句就可以写入或者撤销整个事务处理&#xff0c;但是&#xff0c;只是对简单的事务处理才能这样做&#xff0…

chatgpt赋能python:Pythontypedef:介绍及使用方法

Python typedef: 介绍及使用方法 Python作为一种高级编程语言&#xff0c;支持定义类型别名&#xff0c;可以给现有类型起一个新的名字&#xff0c;从而提高代码的可读性和可维护性。在本文中&#xff0c;我们将介绍Python中的typedef概念及其使用方法。 什么是Python typede…

BiFormer实战:使用BiFormer实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整算法设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试热力图可视化展示…