Fabric 项目的搭建 —— amd 到 arm && fabric 1 .x 到 fabric 2.x
在 m2 Mac 上,用 ubuntu server 虚拟机搭建一个 fabric 的项目,记录一下踩坑过程
文章目录
在 m2 Mac 上搭建了基本的 fabric 环境之后,现在运行一个实际的项目。原项目是一个基于 fabric 的交易溯源系统,使用的 fabric 1.4.2 节点,移植到 mac 上遇到了很多问题,记录一下
原项目地址:https://gitee.com/real__cool/fabdeal
1 更换适合自己操作系统和架构的节点镜像以及binary工具
注意节点镜像和 binary 工具需要是统一的版本的,我选择的是 2.5.4 版本,包括 peer、orderer、fabric-tools、二进制工具包。工具包 hyperledger-fabric-linux-arm64-2.5.4
需要在官方 GitHub 中下载对应操作系统和架构的,docker 镜像只需要选择好版本,拉取镜像时会自动根据操作系统以及架构拉取正确的镜像。
2 创建通道出现问题 – 根据版本修改configtx.yaml
出现问题的命令:
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./config/genesis.block -channelID firstchannel
参考这一篇博客:link,但需要根据自己所使用的 fabric 版本来修改,因为每个版本的这个文件的格式要求是不同的,可以参考对应的 fabric 官方的 fabric-samples 中的 configtx.yaml 来进行更改。在更改中遇到的错误如下(看懂 configtx.yaml 后应该就不会遇到这么多错误,其实都是因为配置有各种错误)
2.1 配置文件中的对象拥有无效的 key
2024-01-29 09:32:30.370 UTC 0002 PANI [common.tools.configtxgen.localconfig] Load -> Error loading config from config cache: Error unmarshalling config into struct: 2 error(s) decoding:
* 'Application.Organizations[0]' has invalid keys: Capabilities
* 'Orderer.Organizations[0]' has invalid keys: Capabilities
Application.Organizations[0]
和Orderer.Organizations[0]
中找到了不应存在的Capabilities
键。这通常意味着Capabilities
定义可能被放置在了错误的位置,或者格式不正确。
2.2 orderer 节点意外退出
Error: failed to create deliver client for orderer: orderer client failed to connect to orderer.carunion.com:7050: failed to create new connection: context deadline exceeded
这个错误说明无法正常连接到 orderer 节点,可以查看 docker 容器的状态
此时可以使用命令docker logs dockerName
查看容器日志
根据日志信息,orderer.carunion.com
容器退出的原因是对引导块的验证失败。错误信息指出在没有先启用orderer支持的情况下,无法启用通道功能。很有可能就是 OrdererCapabilities 相关的配置出现了问题,结果发现是 profiles 中压根就没配置 orderer 的 OrdererCapabilities
3 安装链码出现问题
出现问题的命令:
docker exec cli bash -c "$BENZPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode"
3.1 找不到 chaincode 包 / GOPATH 问题
- 检查映射:确认
docker-compose.ymal
中的- ./../chaincode:/opt/gopath/src/chaincode
是否正确映射了宿主机上的链码目录到容器内的/opt/gopath/src/chaincode
。 - 进入CLI容器:使用
docker exec -it cli bash
进入cli
容器。 - 检查链码路径:在
cli
容器内,运行ls /opt/gopath/src/chaincode
来查看链码文件是否存在。 - 验证GOPATH:在
cli
容器内,运行echo $GOPATH
确认GOPATH
是否正确设置为/opt/gopath
。
发现 GOPATH 没有设置,因此在 docker-compose 中的 environment 中进行设置
3.2 依赖包的问题(踩了很多坑,结论是直接使用 vendor 打包,尽量不要对原本的依赖包进行改动)
============== 以下是踩坑过程 ================
这个项目原本是用的 1.4.2 版本的 fabric,由于需要在 Linux/arm 上运行换成了较新的 2.5.4 ,这可能导致依赖包出现各种问题
- 升级 shim/pb 两个依赖包的版本
-
先根据博客 link 将
github.com/hyperledger/fabric/core/chaincode/shim
换成了github.com/hyperledger/fabric-chaincode-go/shim
,结果 go mod tidy 出现了问题,大概是说 pb 库有问题再根据 ChatGPT 的一些引导:
-
将 shim 和 pb 都换成新更新的版本,注意所有的 .go 文件只要 import 了这两个包都要换掉,然后 go mod tidy,然后尝试 install ,还是出现类似的错误,表明在尝试获取链码部署规范时,依赖解析过程中遇到了问题,新版本的
github.com/hyperledger/fabric-chaincode-go/shim
包依然不完整
- 手动使用 go get 获取校验有问题的 shim 包
-
根据 stackoverflow 中的一个帖子 link ,执行安装之前,先手动在 cli 容器中 go get 解析出现错误的 shim 包,为了执行 go get 语句,首先还需要在容器中安装 git,这个过程可以: 1)自己在官方的 fabric-tool 镜像的基础上打包一个新的镜像一次性完成,也可以 2)使用命令行每次启动 cli 容器后,install 链码之前手动安装。为了方便选择了第二种方法:
docker exec cli bash -c "go get github.com/hyperledger/fabric-chaincode-go/shim" docker exec cli bash -c "$BENZPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode" docker exec cli bash -c "$TESLAPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode"
这样执行之后能够完整验证 shim 包,但是出现了另一个问题:
Error: install failed with status: 500 - chaincode installed to peer but could not build chaincode: docker build failed: docker image build failed: docker build failed: Error returned from build: 1 "chaincode/input/src/google.golang.org/protobuf/reflect/protodesc/editions.go:24:12: pattern editions_defaults.binpb: no matching files found"
显示 install 过程成功了,但是在 build 时出现了问题,protobuf 包中有一个文件无法找到。但实际上我通过访问给出的这个网址是可以发现 editions_defaults.binpb 文件是存在的,之后尝试了更换不同版本的 go,也都有这个问题。
后来发现可能是因为先执行了 go get 命令,这会对项目的依赖版本造成影响……总之就是由于对 go 不是很熟悉,绕了很多弯路……
============== 回到正轨 ==============
- 使用 vendor
综合来说目前的问题在于
a) 目前使用的 fabric 2.x 版本,但链码是原先 1.x 版本使用的依赖包
b) 只对一些依赖包进行对应的升级会导致整个依赖包环境出现问题,如远程仓库拉取、验证时的问题
因此 go mod vendor 可以解决这个问题:
当使用 Go Modules 时,项目会有一个 go.mod
文件,这个文件列出了项目所依赖的其他模块及其版本。还可能有一个 go.sum
文件,它包含了依赖的模块的特定哈希值,用于确保这些依赖的一致性和完整性。
这时候 go mod vendor
命令就发挥了作用:
- 创建 vendor 目录:当你在项目根目录执行
go mod vendor
命令时,Go 将会根据go.mod
文件中定义的依赖,将这些依赖的精确版本复制到项目的vendor
目录中。这包括依赖的所有必要文件,比如 Go 源码文件。 - 隔离依赖:这个
vendor
目录允许你的项目隔离其依赖,使得项目不再依赖于全局的 Go 模块缓存或者依赖的远程仓库。这对于确保项目的依赖版本一致性和构建的可复现性是非常有用的。 - 构建时使用 vendor 目录:当你在有
vendor
目录的项目中构建 Go 程序时,Go 构建系统会优先使用vendor
目录中的依赖,而不是去全局的 Go 模块缓存或者远程仓库中查找这些依赖。
它可以将整个项目的依赖复制到本地,而不需要依赖远程仓库,这样就可以完美地解决我们的问题:使用老版本的一套(原先的 go.mod 完全保留),用 vendor 直接先将完整的依赖复制到本地,然后由于是将整个 chaincode 目录注入到了 cli 容器中,也就包括了 vendor 目录。也就是最后使用的还是老版本的 shim / pb 包,实际上在 fabric 2.x 的节点上也是可以运行的,可能因为 peer 节点安装链码后,实例化、执行链码都是通过在 peer 节点上创建一个新的容器来运行的,这个过程也是隔离的,因此实际上链码的版本与 peer 节点的版本无关,只要链码自己能编译通,在 policy 允许的情况下就可以放在任何 peer 节点上运行(猜测)
具体的做法,在 chaiancode 目录下:
go mod vnedor
此时再安装链码,就可以成功安装:
但是最后不会使用这个命令安装链码,会引入链码生命周期,先打包再安装,详见下一节
4 实例化、执行链码的问题 — 新版本引入新的链码生命周期
fabric 1.x 版本中,安装、实例化链码的指令:
########### fabric 1.x ##############
# 安装链码
docker exec cli bash -c "$BENZPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode"
docker exec cli bash -c "$TESLAPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode"
# 实例化链码
docker exec cli bash -c "$BENZPeer0Cli peer chaincode instantiate -o orderer.carunion.com:7050 -C appchannel -n fabric-realty -l golang -v 1.0.0 -c '{\"Args\":[\"init\"]}' -P \"AND ('BENZMSP.member','TESLAMSP.member')\""
上一步的问题解决之后可以成功执行安装链码的指令,然后执行实例化指令时出现以下问题:
这个错误表明尝试使用旧的链码生命周期命令(peer chaincode instantiate
)在已经迁移到新的链码生命周期的通道上部署链码。从 Hyperledger Fabric 2.0 开始,引入了新的链码生命周期,旨在提供更细粒度的控制和更大的灵活性
fabric 2.0 版本中使用新的生命周期命令处理链码的安装、部署、执行应该是如下的步骤:
########### fabric 2.x ##############
# 1. cli 容器上打包链码
docker exec cli peer lifecycle chaincode package fabric-realty.tar.gz --path /opt/gopath/src/chaincode/fabric-realty --lang golang --label fabric-realty_1.0.0
# 2. 用 cli 在 peer 上安装链码
docker exec cli bash -c "$BENZPeer0Cli peer lifecycle chaincode install fabric-realty.tar.gz"
docker exec cli bash -c "$TESLAPeer0Cli peer lifecycle chaincode install fabric-realty.tar.gz"
# 3. 获取链码包的 package-id
docker exec cli bash -c "$BENZPeer0Cli peer lifecycle chaincode queryinstalled"
# 4. 每个批准链码(根据 channel policy)(填入上一步得到的 package-id)
docker exec cli bash -c "$BENZPeer0Cli peer lifecycle chaincode approveformyorg --channelID appchannel --name fabric-realty --version 1.0.0 --package-id <package-id> --sequence 1 --waitForEvent"
docker exec cli bash -c "$TESLAPeer0Cli peer lifecycle chaincode approveformyorg --channelID appchannel --name fabric-realty --version 1.0.0 --package-id <package-id> --sequence 1 --waitForEvent"
# 5. 提交链码定义
docker exec cli bash -c "$BENZPeer0Cli peer lifecycle chaincode commit -o orderer.carunion.com:7050 --channelID appchannel --name fabric-realty --version 1.0.0 --sequence 1 --waitForEvent --peerAddresses peer0.tesla.com:7051 --peerAddresses peer0.benz.com:7051"
需要注意以下三个点:
- 满足具体的背书策略
依照 configtx.yaml 中定义的背书策略,比如该项目Application
部分,定义了两个关键的背书策略,LifecycleEndorsement
和 Endorsement
,都设置为 "MAJORITY Endorsement"
。这意味着对于链码的生命周期操作(如安装、批准、提交)以及链码的执行,需要大多数组织的背书。该项目配置中包含了三个组织:CARUNION、BENZ、TESLA,对于链码的提交操作,至少需要其中两个组织。
- 提交链码的命令的形式(记得追加 --peerAddresses)
如果不追加 --peerAddresses 的话,会出现以下的错误,表明由于没有满足背书策略而导致提交链码失败
- 查询链码定义的准备状态:
# 查询准备状态
docker exec cli bash -c "$BENZPeer0Cli peer lifecycle chaincode checkcommitreadiness --channelID appchannel --name fabric-realty --version 1.0.0 --sequence 1 --output json"
可以得到结果,两个组织都已经批准了,按道理说是满足了背书策略的
- 查询 peer 节点的日志
docker logs peer0.benz.com
还是说只有一个背书,而需要两个背书
解决这个问题需要在提交链码时加上所有的组织的节点
- instantiate --> invoke
注意,Fabric 2.x 中,链码的生命周期管理方式发生了变化,不再使用 peer chaincode instantiate
命令来初始化链码,instantiate
步骤被替换为 commit
步骤,链码的初始化是作为第一次调用 peer chaincode invoke
的一部分完成的。比如在 commit
成功以后使用 instantiate
命令,会出现如下的错误
由于废弃了 peer chaincode instantiate
命令,链码的初始化需要在 Invoke
方法中自行处理。这通常通过在 Invoke
方法中检查特定的状态或标志来确定是否执行初始化逻辑,并在首次调用时执行这些逻辑。具体需要更改对应的链码逻辑
5 fabric-explorer 的问题
fabric 官方的浏览器的安装,实际上也是镜像的问题,由于早期的 docker hub 的官方版本 hyperledger/explorer 以及 hyperledger/explorer-db 都没有 arm 架构的,但是 GitHub 中官方维护的版本是有 arm 架构的镜像的
按照官方的流程即可搭建 fabric 的浏览器
网址:https://github.com/hyperledger-labs/blockchain-explorer
参考博客:https://blog.csdn.net/weixin_62159253/article/details/131669771
更多推荐
所有评论(0)