区块链:搭建简单Fabric网络并调用智能合约

        使用docker服务搭建Hyperledger/fabric网络的详细教程,实现构建多节点的简单联盟链,并编写、调用智能合约实现投票业务。

目录

背景知识

 Hyperledger Fabric

 基本组件

交易(Transaction)

智能合约

实验目的

实验环境

基础依赖

 安装Golang

安装docker

安装基础依赖包

以⾮root⽤户的身份运⾏Docker

安装docker-compose

搭建fabric环境

搭建测试网络(可选)

chaincode 编写

代码下载

代码投票

命令行投票

链码部署 (deployCC)

环境变量设置

调用交易(invoke)

查询投票(query)


背景知识

        区块链是一种分布式账本技术,通过密码学方法将数据区块按时间顺序连接形成链式结构。它具有去中心化、不可篡改、可追溯等特点。

  • 公有链:完全开放,任何人可参与(如比特币、以太坊)

  • 联盟链:需授权访问,由多个组织共同维护(如Hyperledger Fabric)

  • 私有链:单一组织完全控制

 Hyperledger Fabric

        Hyperledger Fabric是Linux下的开源企业级区块链平台,专为商业应用设计,为联盟链。将Blockchain的数据维护和共识服务进行分离,Orderer节点提供共识服务,实现多通道(channel)的结构。

        特点:多chain和多channel;所谓的chain(链)实际上是包含Peer节点、账本、ordering通道的逻辑结构,它将参与者与数据(包含chaincode在)进行隔离,一个peer节点也可以参与到多个chain中(通过接入多个channel)。

 基本组件

组件作用
Peer节点维护账本,执行链码
Ordering节点排序交易,生成区块
CA(认证中心)颁发数字证书,身份认证
Channel(通道)数据隔离机制,ordering提供给peer的虚拟链路,保密性

交易(Transaction)

  • 应用程序通过SDK发送请求道Peer节点(一个或多个)

  • peer节点分别执行交易(通过chaincode),但是并不将执行结果提交到本地的账本中(可以认为是模拟执行,交易处于挂起状态),参与背书的peer将执行结果返回给应用程序(其中包括自身对背书结果的签名)

  • 应用程序收集背书结果并将结果提交给Ordering服务节点

  • Ordering服务节点执行共识过程并生成block,通过消息通道发布给Peer节点,由peer节点各自验证交易并提交到本地的账本(ledger)中,包括状态(state)的变化,本地的账本称为PeerLedger

智能合约

        即Fabric中的Chaincode,编写Chaincode程序实际上就是要编写一个类,并且这个类要实现fabric预先定义的一个接口,在Fabric中,Chaincode的运行是生成Transaction的唯一来源,也因此Chaincode是外界与Fabric区块链交互的唯一渠道。       

实验目的

        在fabric1.4的架构下,使用docker的容器服务搭建一个具有5个节点的简单联盟链,了解基本的共识,出块,部署、调用智能合约(chaincode)的功能。本实验共有两个任务:

  1. 搭建一个fabric1.4的基础区块链网络
  2. 在fabric的架构下如何去编写、调用智能合约(chaincode),根据简单的业务需求(投票)来设计、实现chaincode。

实验环境

  • Ubuntu20.04(版本非必须)的VMware虚拟机
  • curl
  • Docker  18.09.6-ce和 Docker Compose 1.24.0,支持更高版本
  • Go programming language go1.12.5 (fabric1.4要求go版本为1.11.x或更高Fabric1.0要求1.7.x更高),在系统变量中设置相应的$GOPATH和$GOROOT变量
  • Fabric 1.4可执行文件

基础依赖

# 安装curl
sudo apt install curl
# 为了curl能够⽀持https协议,安装openssl
sudo apt install openssl libssl-dev
# 安装git
sudo apt install git
# 安装cmake
sudo apt install cmake
# 安装jq
sudo apt install jq
# 安装libtool
sudo apt install libtool libltdl-dev

检查安装是否成功:

 安装Golang

后续区块链智能合约用golang编写;

直接下载地址:https://golang.google.cn/dl/

# 下载官⽹的linux x86-64 Archive
wget https://golang.google.cn/dl/go1.19.3.linux-amd64.tar.gz --no-check certificate
# 解压
sudo tar -xzf go1.19.3.linux-amd64.tar.gz -C /usr/local
# 主⽬录下建⽴goDir⽂件夹,做为GOPATH路径
mkdir ~/goDir

下载后改配置文件添加路径,这里将seed改为自己用户名即可,编辑.zshrc:

# 在zsh配置⽂件中添加系统PATH
vim ~/.zshrc
export GOPATH=/home/seed/goDir
export GOROOT=/usr/local/go
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
# 刷新配置⽂件
source ~/.zshrc

 让root也能执⾏go命令,改.zshrc或者 /root/.bashrc:

# 让root也能执⾏go命令(如果root没有安装zsh,则修改 /root/.bashrc)
sudo su
vim ~/.zshrc
export GOPATH=/home/seed/goDir
export GOROOT=/usr/local/go
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin

检查:

安装docker

安装基础依赖包

apt-transport-https允许 apt 包管理器通过 HTTPS 协议与软件源通信;

ca-certificates提供权威机构颁发的根证书,防止中间人攻击;

gnupg-agent用于管理和缓存 GPG(GNU Privacy Guard)密钥(对软件包进行数字签名和验证):

sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common 

从 Docker 官网下载其公钥,验证软件包的签名,并将其添加到系统的可信密钥列表中

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 

添加 Docker 的官方 APT 软件源,add-apt-repository将一个新的软件源添加到系统中,deb 表示这是一个二进制软件包的仓库地址:

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

若拉取镜像失败则换源,阿里云上很多,多加一些,多试几次:

更新本地软件包缓存,安装 Docker 引擎等组件:

sudo apt update 
sudo apt install docker-ce docker-ce-cli containerd.io

以⾮root⽤户的身份运⾏Docker

# 如果出现Cannot connect to the Docker daemon. Is the docker daemon running on this host?
# 解决办法1
sudo chown seed:docker /var/run/docker.sock 
# seed改成⾃⼰的⽤户名# 解决办法2
# 创建⼀个名为docker的组
sudo groupadd docker
# 将你的⽤户添加到docker组
sudo usermod –aG docker $USER
# 重启

检查是否安装成功,看docker版本:

安装docker-compose

运行下列环境安装docker-compose,如下载失败,可前往http://get.daocloud.io/#install-compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose#给相应的二进制文件可执行权限:
sudo chmod +x /usr/local/bin/docker-compose#之后在命令行输入
docker-compose version

检查版本:

重新启动并检查状态是active:

搭建fabric环境

从 GitHub 上克隆 Hyperledger Fabric 的官方样本仓库;

./install-fabric.sh docker再次执行安装脚本,并指定b(binary) 作为参数,这个操作会下载与所拉取镜像版本匹配的 Fabric 二进制工具文件到当前目录的bin文件夹下;

mkdir ~/blockchain
cd blockchain
# github克隆fabric-samples
git clone https://github.com/hyperledger/fabric-samples
cd fabric-samples
# 下载安装脚本并构建docker
wget https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh --no-check-certificate
chmod +x install-fabric.sh
./install-fabric.sh docker
./install-fabric.sh b

并运行其中连通性测试脚本:

# 启动网络
cd test-network
./network.sh up#或者同时创建通道、指定状态数据库
./test-network/network.sh up createChannel -ca -c mychannel -s couchdb# 查看是否创建成功
docker ps# 关闭docker
./network.sh down

返回如下算成功:

       可选:若返回的版本信息不匹配,即出现如下行,fabric-samples/bin默认下载旧的 v2.5.4 版本二进制文件,install-fabric.sh使用新的 v3.0.0 版本的 Docker 镜像,版本不匹配也能联通,但后续可能有问题,可以升级本地二进制文件以匹配 Docker 镜像 (v3.0.0)

LOCAL_VERSION=v2.5.4
DOCKER_IMAGE_VERSION=v3.0.0
Local fabric binaries and docker images are out of sync. This may cause problems.
# 确保你在 fabric-samples 目录下
cd ~/blockchain/fabric-samples#  使用安装脚本,指定版本,重新下载二进制文件
# 这将覆盖 bin 目录下的旧版工具
./install-fabric.sh --fabric-version 3.0.0 binary# 清理之前的网络(如果正在运行)
./test-network/network.sh down#重新运行你的命令
./test-network/network.sh up createChannel -ca -c mychannel -s couchdb

搭建测试网络(可选)

参考链接: https://hyperledger-fabric.readthedocs.io/en/release-1.4/build_network.html

        现在已经克隆 Hyperledger Fabric 的官方样本仓库,在执行前面的脚本后,会发现目录下多了fabric-samples,包含了链码示例、应用程序示例、以及部署脚本,现在将使用first-network这个例子。

cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network

        官方提供一个完全注释的脚本byfn.sh,利用这些Docker镜像可以快速引导一个由4个代表2个不同组织的peer节点以及一个排序服务节点的Hyperledger fabric网络。它还将启动一个容器来运行一个将peer节点加入channel、部署实例化链码服务以及驱动已经部署的链码执行交易的脚本。

sudo ./byfn.sh

chaincode 编写

        使用Go语言编写一个用于投票的chaincode,并完成其功能性测试(如投票,统计,查询等)。可以选择多种测试手段,如编写chaincode的测试代码,或者是在dev模式下,使用命令行测试。

golang教程Go 语言之旅

代码下载

可以从github下载课程相关代码,完整代码见仓库:https://github.com/yy158775/blockchain-exp

cd ~/blockchain
git clone https://github.com/yy158775/blockchain-exp
cd blockchain-exp/vote-smartcontract
go mod tidy
# 修改main.go
cd ~/blockchain/blockchain-exp/vote-app
gedit main.go
# 将其中的cryptoPath改为如下路径(之前的⽂件夹相对位置需要与 实验环境搭建 部分所写⼀致)
# cryptoPath = "../../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com"
# certPath = cryptoPath +"/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem"
# 下载依赖
go mod tidy
# 开启network
cd ~/blockchain/fabric-samples/test-network
./network.sh down
./network.sh up
# 创建channel
./network.sh createChannel
# 运⾏
./network.sh deployCC -ccn basic -ccp ../../blockchain-exp/votesmartcontract -ccl go

代码投票

修改main.go的cryptoPath和chaincodeName,通过应用程序调用智能合约:

# 运⾏客户端
cd ~/blockchain/blockchain-exp/vote-app
go mod tidy
go run main.go

根据菜单就能直接投票了:

命令行投票

链码部署 (deployCC)

-ccn: 指定Chaincode名为vote

-ccp指定Chaincode源代码的路径

./network.sh deployCC -ccl go -ccp ./HUST-blockchain-exp/vote-smartcontract/ -ccn vote

环境变量设置

        在执行链码调用invoke/query命令前,必须设置这些环境变量,以指定要操作哪个 Peer 节点和使用哪个身份。

# 设置核心配置路径(假设当前在 test-network 目录)
export FABRIC_CFG_PATH=$PWD/../config/# 启用 TLS 通信
export CORE_PEER_TLS_ENABLED=true# 设置要操作的组织 MSP ID
export CORE_PEER_LOCALMSPID="Org1MSP"# 设置该组织的 TLS 根证书路径(用于验证通信)
export CORE_PEER_TLS_ROOTCERT_FILE=$PWD/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt# 设置管理员用户的 MSP 路径(身份文件)
export CORE_PEER_MSPCONFIGPATH=$PWD/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp# 设置要连接的 Peer 节点地址
export CORE_PEER_ADDRESS=localhost:7051

切换到 Org2 时,需要重新设置以下变量:

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

调用交易(invoke)

调用链码的VoteUser 函数,这是一个会修改账本状态的交易(Transaction)。

peer chaincode invoke \-o localhost:7050 \ # Orderer 地址--ordererTLSHostnameOverride orderer.example.com \--tls \--cafile "$PWD/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" \ # Orderer TLS CA-C mychannel \ # 通道名称-n vote \ # 链码名称--peerAddresses localhost:7051 \ # 需要背书的 Peer 地址 (Org1)--tlsRootCertFiles "$PWD/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" \--peerAddresses localhost:9051 \ # 需要背书的 Peer 地址 (Org2)--tlsRootCertFiles "$PWD/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" \-c '{"function":"VoteUser","Args":["username"]}' # 调用方法和参数

查询投票(query)

        查询单个用户票数:Chaincode的 GetUserVote函数,这是一个仅查询账本状态而不产生交易的查询(Query):

peer chaincode query -C mychannel -n vote -c '{"Args":["GetUserVote", "usernane1"]}'
("id":2, "usernane":"usernane","votes":1)

        查询所有投票:Chaincode的GetAllVotes函数:

peer chaincode query -C mychannel -n vote -c '{"Args":["GetAllVotes"]}'
[{"id":0,"username":"Alice","votes":2},{"id":1,"username":"Mike","votes":1},{"id":2,"username":"usernane1","votes":1}]

恭喜成功!下一篇挖矿!

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

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

相关文章

Web前端面试题(2)

Web前端面试题(附答案及解析)&#xff08;2025.9月最新版&#xff09;-CSDN博客 1.link 与 import 的区别和用法 主要区别 特性<link>import语法类型HTML标签CSS规则加载方式并行加载&#xff08;与其他资源同时加载&#xff09;串行加载&#xff08;必须等待主CSS文件…

Paxos协议

目录 Paxos 是什么&#xff08;What&#xff09; Paxos 的目的&#xff08;Why&#xff09; 角色与职责&#xff08;Who&#xff09; 基本流程&#xff08;How&#xff09; 常见问题与对策 什么是多数派&#xff08;Quorum&#xff09; Paxos vs Raft 异同点 Paxos 是什…

第十二篇:Qcom Camx打印实时帧率 FPS

一、第一种方式(有些低平台可能没有) adb shell setprop persist.vendor.camera.enableFPSLog TRUE adb shell setprop persist.vendor.camera.systemLogEnable TRUE adb shell setprop vendor.debug.camera.overrideLogLevels 0xff chi-cdk/core/chiframework/chxextensi…

TRAE通用6A规则+敏捷开发5S规则

网上研究别人的一些规则,也搞一份给大家 6A工作流项目规则 身份定义 你是一位资深的软件架构师和工程师,具备丰富的项目经验和系统思维能力。你的核心优势在于: 上下文工程专家:构建完整的任务上下文,而非简单的提示响应 规范驱动思维:将模糊需求转化为精确、可执行的规…

【Nginx开荒攻略】Nginx主配置文件结构与核心模块详解:从0到1掌握nginx.conf:

目录 引言 1 nginx.conf的整体结构 2 main全局块详解 2.1 核心指令解析 2.1.1 user&#xff1a;运行用户 2.1.2 worker_processes&#xff1a;工作进程数 2.1.3 pid&#xff1a;PID文件路径 2.1.4 worker_rlimit_nofile&#xff1a;文件描述符限制 2.2 main块配置示例…

【前端教程】从基础到优化:一个登录页面的完善过程

最近做了一个简单的登录页面,主要练习了文本框的onfocus与onblur事件的使用。虽然功能实现了,但仔细想想还有不少可以改进的地方。今天就来分享一下这个登录页面的开发过程和优化思路。 初始实现与解析 先来看一下最初的实现代码: <!DOCTYPE html> <html> &l…

独家 | 抖音生活服务调整:涂晴接管市场和达人运营,旭凯担任北部大区负责人

文/刀客doc(头条精选作者)刀客doc独家获悉&#xff0c;9月8日抖音生活服务完成新一轮组织调整&#xff0c;并已在内部all hands完成官宣。此次调整主要涉及北部大区、达人运营与市场部三大条线的人事轮换与汇报关系变更。核心变动如下&#xff1a;涂晴&#xff0c;原抖音生活服…

class_9:java 抽象类和接口

抽象类 需要用abstract 修饰类和接口abstract class Person{String address;String name;abstract public void eat();abstract public void drink();public void printInfo(){System.out.println("name " name);}} class Student extends Person{public void eat()…

【C++】队列queue的使用

语法 在 C 中&#xff0c;队列的语法如下&#xff1a; #include <queue>// 声明队列 std::queue<Type> q;这里 Type 是队列中存储元素的数据类型。 常用操作 队列提供了以下常用操作&#xff1a; empty(): 检查队列是否为空。 size(): 返回队列中的元素数量。 fron…

HTTP 协议的基本格式

目录 &#xff08;一&#xff09;HTTP是什么 &#xff08;二&#xff09;报文格式 &#xff08;1&#xff09;请求 ①首行 1.URL 2.方法&#xff08;method&#xff09; Ⅰ.GET Ⅱ.POST Ⅲ.PUT Ⅳ.DELETE 3.版本号 ②请求头&#xff08;header&#xff09; 1.键值对…

计算机网络的基本概念-2

1、数据交换技术&#xff1a;电路交换、报文交换与分组交换网络核心部分的关键设备是路由器&#xff0c;其工作方式是分组交换。要理解分组交换&#xff0c;必须先了解其前两种技术。1. 电路交换 (Circuit Switching)核心思想&#xff1a;通信前必须预先建立一条专用的物理通路…

车载网络技术--SOME_IP协议详解

文章目录前言SOME/IP概念SOME/IP协议格式SOME/IP功能介绍序列化序列化规则发布和订阅服务发现&#xff08;SOME/IP-SD&#xff09;SOME/IP-TP协议使用场景SOME/IP-TP协议参考文章&#xff1a;前言 本文介绍了SOME/IP协议的具体内容&#xff0c;包括报文格式&#xff0c;协议选…

JVM 核心知识全解析:从类加载到垃圾回收的深度认知

什么是JVM&#xff1f; JVM全称&#xff08;Java Virtual Machine&#xff09;&#xff0c;中译为&#xff1a;Java虚拟机 本质&#xff1a;是一个运行在计算机上的程序 职责&#xff1a;运行Java字节码文件&#xff08;因为计算机只能认识机器码文件&#xff0c;所以需要JVM将…

Keepalived 负载均衡

Keepalived 负载均衡 Keepalived 可以与 LVS&#xff08;Linux Virtual Server&#xff09;结合&#xff0c;提供强大的四层负载均衡功能。它通过 IPVS&#xff08;IP Virtual Server&#xff09;内核模块实现高性能的负载分发。 核心组件 Virtual Server&#xff1a;虚拟服务器…

拷打DeepSeek实现自动生成差分电荷计算文件和后处理

差分电荷&#xff08;charge density difference&#xff09;是材料模拟中分析电子结构变化的直观工具。 它把成键后的真实电荷密度减去成键前各碎片叠加的电荷密度&#xff0c;得到一张“电子迁移地图” 于是可以一眼看出化学键形成时电子从哪里来到哪里去&#xff0c;表面吸…

AI问答-Nuxt4:什么时候发布的,有哪些特性,和Nuxt3相比 有哪些优势 / Nuxt4 / Nuxt-v4

Nuxt 4于2025年7月至8月期间正式发布&#xff0c;作为Nuxt框架的重大版本更新&#xff0c;其核心聚焦于稳定性提升、开发者体验优化及性能增强&#xff0c;与Nuxt 3相比&#xff0c;优势体现在项目结构、数据获取、类型系统、开发工具链等多个层面。一、Nuxt 4 发布时间线测试阶…

isinstance()和insubclass()

​​isinstance() 和 issubclass() 的功能与用法​​​​1. isinstance(obj, classinfo)​​​​功能​​&#xff1a;检查对象 obj 是否是 classinfo 类&#xff08;或其子类&#xff09;的实例。 ​​返回值​​&#xff1a;True 或 False。 ​​用法​​&#xff1a;class A…

判断QMetaObject::invokeMethod()里的函数是否调用成功

今天&#xff0c;在Qt编程&#xff0c;碰到一个需要使用invokeMethod方式来获取函数是否执行成功的情况。     invokeMethod()即可以同步调用&#xff0c;也可以异步调用。若调用者、被调用者&#xff0c;都在同一个线程&#xff0c;则是同步调用&#xff1b;若调用者、被调用…

【linux】特殊权限

us对文件&#xff1a;用户执行该文件时&#xff0c;会以文件所有者的权限运行chmod us filename # 符号模式 chmod 4755 filename # 数字模式&#xff08;4表示SetUID&#xff09;典型应用&#xff1a;/usr/bin/passwd&#xff08;允许普通用户修改自己的密码&#xff0c;…

OpenCV:指纹识别

目录 一、核心算法 1&#xff1a;SIFT 特征提取&#xff08;尺度不变特征变换&#xff09; 1.1 算法原理&#xff08;4 步核心流程&#xff09; 1.2 重点代码实现与参数解析 1.3 关键输出解读 二、核心算法 2&#xff1a;FLANN 特征匹配&#xff08;快速最近邻搜索&#x…