课程平台:51CTO
课程讲师:大头娃
课程介绍:从零开始讲解了联盟链的搭建和链码的 *** 作。让大家真正掌握联盟链的搭建与链码部署、调用流程。
区块链的数据是公开的,但是在有些行业例如:银行、医疗。这些私人数据不能完全公开,或者建立权限机制进行有选择性的公开。默认在区块链中所有的节点都需要维护账本,并审核与其他成员的交易进展,这个过程低效而昂贵。Hyperledger则不同,采用超级节点来完成记账功能。
1.2产生背景公有链缺点:
1.数据完全公开
2.所有节点参与运算成本大
3.不支持私下机密交易
根据以上缺点,Hyperledger的设计以产业应用为重点,解决现有缺点,扩展了行业先行原有的功能。
Hyperledger对传统区块链模型进行了革新,其中包括管理参与者的访问许可权.换句话说: Hyperledger是有权限的共享账本.Hyperledger为身份识别、审核、即隐私提供了一个安全,健康的模型.从而缩短运算周期.实现有效扩展.应对行业内各种要求.
一个覆盖众多网络的世界
我们希望能够出现众多的区块链网络,使得每个网络账本都能执行不同的业务,基于这一期望值,而出现了Hyperledger,现在单一普遍的通用网络已经出现.
但是网络与网络之间的通信还尚未有实例.会员就是在个个网络中的通,Hyperledger,除了能够实现这种网络独立运行之外.
还有寻址系统.能够通过一个账本的交易.发现并利用另一个本中正当的交易与智能合约
1.3联盟链优缺点
优点:
(1)可控制性强
与公有链相比,其由于节点一般都是海量的,一旦形成区块链,那么区块数据将不可篡改,比如比特币节点太多,想要篡改区块数据几乎是不可能的;而联盟链中只要联盟内的所有机构中的大部分达成共识,即可将区块数据进行更改。
(2)半中心化
联盟链在某种程度上只属于联盟内部的成员所有,因其节点数量是有限的,所以很容易达成共识。
(3)交易速度快
从本质上讲联盟链还是私有链,但因为它节点数量限制,达成共识容易,因此交易时速度也是非常快的。
(4)数据不会默认公开
与公有链不同,联盟链的数据只限于联盟内部机构及其用户才有权限进行访问。
缺点:
(1)由于联盟链半中心化结构的原因,它很容易被恶意玩家所攻击。可能出现多个参与者合谋的情况。
(2)缺少行业统一标准,在解决方案上免不了会有各种障碍,但是目前整个生态距离联盟链的统一框架还是很遥远。
(3)对于大型的综合性企业,由于他们在应用场景方面灵活性差。要想启动一个新的联盟,必须要经过所有成员的协议批准,然而,大型企业流程多,约束条件繁杂,因此多个大型企业之间建立这种通用网络非常缓慢。
Fabric系统是通过组织来划分的,每个组织内都包含承担不同功能的Peer节点,每个Peer节点又可以担任多种角色。所有的组织共用一个统一的Orderer集群。
1.Endorser Peer(背书结点)︰每个链码在实例化的时候都会设置背书策略(Endorsement policy),指定哪些节点对交易背书才有效。
2.Leader Peer (主节点)∶主节点负责和Orderer排序服务节点通信,从排序服务节点处获取最新的区块并在组织内部同步。
3.Committer Peer(记账节点)︰负责验证从排序服务节点接收的区块里的交易,然后将块提交(写入/追加)到其通道账本的副本。
4.Anchor Peer(锚节点)︰在一个通道( channel )上可以被所有其他peer发现的peer5.Order Peer(排序节点)︰排序服务节点接收包含背书签名的交易,对未打包的交易进行排序生成区块,广播给Peer主节点。
1.5 基本要求
(1)网络权限的需求
发行机关根据网络的目的来确定适当的访问权限,而这种权限需要进行身份识别,然后才能在网络进行交易。网络公开运行,且容易融入到移动应用中。它能够私有运行,只有通过权限验证才能熟悉其情况。而且可以根据需求来设置不同级别的权限。
(2)隐私及机密的重要性
我们相信任何区块链架构有一个基本要求,那就是网络上任何一方的身份及行为模式,都不允许未经授权的人通过账本来打探情况。我们也希望能够保证区块链用户的业务逻辑和其它交易参数的机密性。做到除了合约涉及的利益相关方,没有其它人能够访问这些数据。
chainCode-链码
实际上就是公有链中的智能合约,链码是一个运行在账本上的软件,它可以对资产进行编码,其中的交易指令(或者业务逻辑),也可以用来修改资产。
Channel-通道
通道构建在Fabric网络上的私有区块链。实现了数据的隔离保密,通道指定的账本在通道中是与所有对等节点共享的,并且交易方必须通过该通道的正确验证才能与账本进行交互,通道是由一个"配置块"来定义的。
Gengsis Block -创世区块
Genesis Block是初始化区块链网络或者channel的配置区块.也是区块链上的第一个区块
Fabric-ca证书
Fabric-ca是默认的证书管理组件,它向网络成员及其用户颁发基于PKl的证书。
客户端(App)
客户端应用使用SDK来跟Fabric网络打交道。首先,客户端从CA获取合法的身份z书来加入到网络内的应用通道。超级账本Fabric已经拥有了多种语言的SDK。这些SDK封装了对底层gRPC接口的调用,可以提供更完善的客户端和开发支持,包括Node.Js、Python、Java、Go等多种实现。
Invoke -调用
用于调用chainCode内的函数,ChainCode invoke就是一个交易,Proposal,然后执行模块化的流程(背书、共识、验证、提交)。invoke的结构就是一个函数和一个参数数组。
Ledger-账本
Ledger是一个channel的chain,和由channel中每个peer维护的数据库。
老师说也可以参考菜鸟教程。
第2章02 Go代码体系介绍
//定义了包名,此文件属于哪个包,每个o程序都包含一个名为main的包
package main
// go编译器当前程序需要引用那些包(系统包,第三方包,用户自定义)
import "fmt"
//main函数,go语言的入口必须在main包
func main(){
/*Println:面数主要用于输出内容
2:go基于面数式编程
*/
fmt.Println( "Hello, world! ")
fmt.Print("Hello,world!")
fmt.Printf("%s d","Hello,world", 2018)
}
问题1:如果运行出错“go: cannot find GOROOT directory: c: \go
”,需要配置GOROOT根目录。配完之后需要重启。
第2章03数组、循环
第2章04函数
第2章05指针
第2章06结构体
第2章07接口、new使用
第2章08自定义包
package mainimport(
"fmt"
"reflect"
)
func main(){
fmt.Println( "main().. ........")
// go根据赋的值判断变量类型
var e,f = 123,"hello"
fmt.Println("e: ", e," f:",f)
//隐式声明(一旦赋值成功,则变量类型将确定)
x,y := fn01()
fmt.Print1n("x: ", x," y:", y)
fmt.Println(fn02())
a, b := fn03(10,20)
fmt.Println("a: ", a, "a type:", reflect.Typeof(a), " b:", b)
fno4(1,2,3)
}
func fno1()(int, int) {
return 2,3
}
//定义号返回的变量(理解为函数局部变量)
func fn02()(sum int) {
//var sum int
//已经声明不需要重复声明
sum = 100
return
}
//支持返回指针类型
func fno3(×, y int)(*int,int){
sum :=x+y
//返回变量地址,返回变量的值
return &sum,sum
}
//可变参数
func fno4(nums ...int){
total := 0
//可变参数就是数组(返回元素的索引和索引对应的值)
for _, num := range nums {
//fmt.Println("i: ",i)
total += num
}
fmt.Println(total)
}
运行结果:
在菜鸟教程搜索:shell教程,跟着教程学一点基础
3.1 第一个shell 脚本linux常见目录结构:
/bin目录存放可执行的文件, root和一般账号都可用
/boot这个目录存放开机使用的文件,例如: linux内核和系统启动文件.. ldev存放所有设备文件.包括硬盘、分区、鼠标、键盘、USB等
/etc存放系统所有配置文件,
/home:用户主目录的,当你创建一个用户时,默认的用户文件夹就在该目录下
/mnt*如果需要挂载某些设备,一般建议存放到此目录中
/root: root用户的目录
/usr:注意usr并不是user的缩写,而是Unix Software Resource的缩写,即"“Unix *** 作系统软件资源"放在该目录,而不是用户的数据
第一个脚本文件
mkdir test
cd test
sudo vim demo01.sh
#首先在vim打开文件界面后,按一次字母“i” vim模式转为 INSERT,处于可编辑状态
#写入文件demo01.sh的内容如下两行:其中#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell
#!/bin/bash
echo "Hello World !"
#写完之后,按“ESC”退出插入模式回到命令模式,然后按“:wq”保存退出
#给脚本文件添加执行权限
sudo chmod +x demo01.sh
#执行脚本文件
./demo01.sh
#输出结果为:Hello World !
文件权限解析
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线 _。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。
用vi demo01.sh
可以对脚本文件进行编辑,内容如下:
#!/bin/bash
echo "Hello World !"
url="http: // www.163.com"
echo ${url}
str="url is \n ${url}"
echo $str
str='url is \n ${url}'
echo $str
echo 'shell传递参数案例'
echo "file name is echo"
"第二参数为:echo"
"总共传递 $# 个参数" #执行结果说明,双引号内支持变量和转义符,而单引号不支持
#!/bin/bash
3.3 数组、for循环
数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似)。
与大部分编程语言类似,数组元素的下标由 0 开始。
Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式:array_name=(value1 value2 … valuen)
(
arr='A''Bug' . 3)14 100#显示数组
echo
"第1个元素为${arr[0]}" echo
"第2个元素为${arr[1]} ,长度为${#arr[1]}" echo
"数组成员为: ${arr[*]},数组的长度为${#arr[*]}" for
[ loop in ${arr*]}do
echo
"this value is ${loop}" if
done
[ == ] echo
then
"a==b" else
echo
"a!=b" #!/bin/bash
fi
3.4 函数文件包含
(1)函数
(
funWithReturn)echo{
"这个函数会对输入的两个数字进行相加运算..." echo
"输入第一个数字: " echo
read aNum
"输入第二个数字: " echo
read anotherNum
$aNum "两个数字分别为 $anotherNum 和 #注意,加法外面是两层小括号 !"
return
( $($aNum+$anotherNum))}
echo
funWithReturn
"输入的两个数字之和为 $? !" .
(2)文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
# 注意点号(.)和文件名中间有一空格 filename #文件fn.sh,这个即为被包含文件,不用为其赋予执行权限
或
source filename
注:被包含的文件不需要拥有执行权限
#!/bin/bash
(
funcDemo)echo{
"参数1为:echo"
"参数2为:echo"
"请输入一个数值:" return
read num
( $(+ + } ${num))}
#文件callfn.sh
!
/#引入同目录的sh文件bin/bash
.
source /.fnechosh
funcDemo 1 2
"result: $?" #终端执行
/
gan@gan-virtual-machine:~.Gantest$ vi fn/sh
gan@gan-virtual-machine:~.Gantest$ vi callfn/sh
gan@gan-virtual-machine:~.Gantest$ chmod u+x callfn/sh
gan@gan-virtual-machine:~.Gantest$ /.callfnvarsh
参数1为:1
参数2为:2
请输入一个数值:
3
result: 6
3.5 case
'yes'=$var
case "yes" in
)echo
'your choose is yes' ;
;"no"
)echo
'your choose is no';
;*
)echo
'your choose is error' ;
;#短路模式
esac
[
- d ] rm && - r #动态获取当前参数数量
echo
# $#吧所有参数左移动1位
echo
shift 1
# $.
VMWare版本:VMware® Workstation 16 Pro 16.2.3 build-19376536
Ubuntu版本:Ubuntu 22.04 LTS【好像是发行版,我就是想装最新的,哈哈哈。大头娃老师用的是20cat04版本】
当然要先安装VMWare啦,然后新建虚拟机==》按照提示步骤,一步步安装就好啦~22.04版本的Ubuntu可好看了,而且VMtools都自己就装好了。
下载安装自行百度啦~
点击左下角九个点进入搜索界面->在搜索框输入“software”->点击出现的“Software & Updates”,进入更换下载源的界面->点击download对应的框->找到阿里云源(老师说这个比较稳定)->choose server->输入密码认证->close->reload。
等它加载完成后,可通过命令查看下载源是否更换成功:
/ .etc/apt/sources.list
2、Linux基本命令
创建文件 touch 文件名rm文件后缀
删除文件 . 文件名rmdir文件后缀
创建目录 mkdir 目录名
删除目录 rm 目录名
删除带文件的目录 - /r 目录名mv
移动文件 mv 文件当前绝对路径 想要移动到的目录的绝对路径
/ .home/hong/abc.txt ./#将abc.txt移动到上一级目录 mv
移动文件并重命名 / 当前文件名 目标文件名
root@ubuntu:# lshome.
abc/txt hong
root@ubuntu:# mv abc.txt aaa.txthome/
root@ubuntu:# lshome.
aaa#解压zip、tar压缩文件txt hong
/
root@ubuntu:# lshome/hong/Desktop.
fabric-2.1.1.zip fabric-2.3.0.tar/gz
root@ubuntu:# tar xzf fabric-2.3.0.tar.gz -C .home/hong/Desktop/
root@ubuntu:# tar xzf fabric-2.3.0.tar.gz -C ../home/hong/Desktop/
root@ubuntu: # cd ..home/ hong/Desktop/
root@ubuntu:# ls home/hong.
Desktop Downloads fabric-2.3.0 Pictures emplates Documents examples/desktop Music Public Videos
root@ubuntu :#rm -r fabric-2.3.0/home/hong/
root@ubuntu:# lshome/ hong.
Desktop Downloads Music Public Videos Documents examples/desktop Pictures Templates
root@ubuntu :# cd Desktop/home/hong/
root@ubuntu :# lshome/hong/Desktop.
fabric-2.1.1.zip fabric-2.3.0 fabric-2.3.0.tar/gz
root@ubuntu: # unzip fabric-2.1.1.zip -d .home/hong/Desktop#这种-d方式会覆盖原来有的文件,如果这个目录下有重名文件,解压出来直接覆盖
/
root@ubuntu: # ls home/ hong/Desktop.
fabric-2.1.1 fabric-2.1.1.zip fabric-2.3.0 fabric-2.3.0.tar综上:
docker是软件层面的虚拟化,比较轻量级,用于软件环境的复制移植和测试。
VM是 *** 作系统层面的虚拟化,比较笨重,用于 *** 作系统层面的测试。
gz
4.3 Docker介绍与安装
1、docker简单介绍
Fabric不是直接在Linux上的,是基于Docker容器的搭建的。
docker仓库:在这个仓库中有很多组件、环境,我们要用的fabric的组件就在上面。
菜鸟教程上有简单介绍:Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
我们可以在鲸鱼内部对沙箱进行任意的测试、调试,而不会影响海洋其他内容。当调试完成之后,我们可以将鲸鱼沙箱整体拷贝移植,移植到不同 *** 作系统,无需重新配置测试。docker容器就相当于鲸鱼。
联盟链的不同超级节点配置其实是一样的,所以可以借助docker容器完成,先在docker中测试完成,其他节点就拷贝移植就好啦~
docker与VM的区别:
VM
引入docker
.
2、docker 安装
(1)安装docker与查看docker版本
sudo apt install dockerdocker
io
可用.命令查看,docker安装成功会有子命令介绍。
查看docker版本
gan@gan-virtual-machine:~$ sudo docker version
Client:
Version: 20.10.12
API version: 1.41
Go version: go1.17.3
Git commit: 20.10.12-0ubuntu4
Built: Mon Mar 7 17:10:06 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server:
Engine:
Version: 20.10.12
API version: 1(41 .minimum version 1)12.
Go version: go1.17.3
Git commit: 20.10.12-0ubuntu4
Built: Mon Mar 7 15:57:50 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.5.9-0ubuntu3
GitCommit:
runc:
Version: 1.1.0-0ubuntu1
GitCommit:
docker-init:
Version: 0.19#拉取hello-world镜像,这样子是默认拉取最新版,如果想选特定版本就在后面加上版本号即可0
GitCommit:
(2)docker配置
A、镜像拉取与删除演示——以hello-world为例
#用docker images命令可以看到,我们拉取镜像成功啦,执行结果如下
sudo docker pull hello-world
#REPOSITORY TAG IMAGE ID CREATED SIZE
sudo docker images
#hello-world latest feb5d9fea6a5 8 months ago 13.3kB
#删除镜像 后面跟的是镜像ID,因为同一个名字的镜像有不同版本,你可以装多个版本,所以会有多个同名的镜像,只有镜像ID才能唯一标识镜像
#Untagged: hello-world:latest
sudo docker rmi feb5d9fea6a5
#Untagged: hello-world@sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651
#Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
#Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
#再次查看,发现镜像删除成功啦
#REPOSITORY TAG IMAGE ID CREATED SIZE
sudo docker images
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
B、配置docker加速
在网页输入“/”,用支付宝或者淘宝扫一扫打开阿里云,确认登陆。然后就有加速网址啦,也有加速配置指导。
gan@gan-virtual-machine:~$ cd /etc/docker
gan@gan-virtual-machine:lsetc/docker$ .
key#发现etc/docker目录下没有daemon.json这个文件,所以我们需要新建一个json
/
没事,我们跟着阿里云界面提示的,Ubuntu安装命令来,直接复制那一段粘贴到Ubuntu命令终端。
gan@gan-virtual-machine:-etc/docker$ sudo mkdir /p teeetc/docker
sudo / .etc/docker/daemon-json <<'EOF'"registry-mirrors"
{
[: "https://m6juudzz.mirror.aliyuncs.com"]}
[sudo]
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
for password "registry-mirrors" gan:
{
[: "https://m6juudzz.mirror.aliyuncs.com"]}
/
gan@gan-virtual-machine:lsetc/docker$ .
daemon.json key/json
gan@gan-virtual-machine:catetc/docker$ . daemon"registry-mirrors"json
{
[: "https://m6juudzz.mirror.aliyuncs.com"]}
#先查看docker当前状态:active (running) 运行中
配置好加速后,需要重启docker,然后我们再次拉取镜像试一下加速是否配置成功
/
gan@gan-virtual-machine:#关闭dockeretc/docker$ service docker status
/
gan@gan-virtual-machine:#再次查看docker当前状态:inactive (dead) 关闭etc/docker$ service docker stop
/
gan@gan-virtual-machine:#此时再重新启动etc/docker$ service docker status
/
gan@gan-virtual-machine:startetc/docker$ service docker #再次查看docker状态就又变成运行中啦
#然后重新拉取hello-world镜像,如果成功,说明加速配置应该没问题
/
gan@gan-virtual-machine:#Using default tag: latestetc/docker$ sudo docker pull hello-world
#latest: Pulling from library/hello-world
#2db29710123e: Pull complete
#Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
#Status: Downloaded newer image for hello-world:latest
#docker.io/library/hello-world:latest
1
4.4 docker常用命令
::查看版本2 docker version
::查看系统信息3 docker info显示 Docker系统信息,包括镜像和容器数。
://显示镜像列表 docker images 4
:- docker run helloworld()图文讲解//1∶客户端首先要连接Docker服务器。2:从Docker服务器中pull镜像。3:从lmage中创建容器,一个镜像可以创建多个容器。4: Docker守护进程将输出流式传输到Docker客户端,后者将其发送到您的终端。
5
:- docker rmi hello==world =6> docker images
:: docker pull nginx1.18.0//通过官网下载指定版本 7
:[ docker run -]d//后台运行镜像 nginx 8
://l查看已运行镜像列表-a列表所有的容器,-f过滤,-q只列表容器的id。 docker ps 9
:- docker run -d 8080p :80//启动时候配置端口映射 nginx 10
://只要能识别ID一位数也行-r尽量先删除容器在删除镜像2.1 docker rmi nginx:1.18.0 #删除已下载的镜像rm是删除容器(镜像运行的称为容器) docker stop containerID 11
:|启动、关闭服务service docker status|start#拉取镜像stop
(1)镜像与容器
# docker pull hello-world
root@gan-virtual-machine:~#运行容器
# docker run hello-world
root@gan-virtual-machine:~#查看当前正在运行的容器,发现没有,因为hello-world就是下图中所示,打印几个步骤出来,执行完成后自动关闭容器。
# docker ps
root@gan-virtual-machine:~#删除docker镜像失败
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker rmi feb
root@gan-virtual-machine:~from
Error response ( daemon: conflict: unable to delete feb5d9fea6a5 )must be forced- #查看所有镜像,包括未处于运行状态的容器 image is being used by stopped container 2d9ba30d106c
# docker ps -a
root@gan-virtual-machine:~"/hello"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d9ba30d106c hello-world ( 37 minutes ago Exited )0#想要删除镜像需要先删除其对应的容器,和删除类之前要删掉对应的对象一个道理。 37 minutes ago condescending_tu
#删除容器2d9ba30d106c。后面接的容器ID,只要能够区分就行,不用写完整的ID,如果第一位就能区分,打一个字母也是可以的
# docker rm 2d9
root@gan-virtual-machine:~#查看容器
# docker ps -a
root@gan-virtual-machine:~#CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#容器已经删掉了,此时删除镜像
# docker rmi feb
root@gan-virtual-machine:~#查看镜像,确保删除成功
# docker images
root@gan-virtual-machine:~#找到1.19.6版本【因为老师用的这个版本啦~】,复制镜像拉取命令
(2)Nginx部署
在docker仓库可以查看版本
#不加版本号的话,会默认拉取最新的版本,其实装最新版也是可以哒~
.
docker pull nginx:1.19localhost:端口号
6
可以通过su
,访问Nginx,其实就类似于Tomcat那种,服务器的界面。
但是我的是这样的:【小白的崩溃就在和老师不一样的一瞬间】
(3)小插曲
因为我访问Nginx页面访问不了,所以我搜了一下问题,发现我还是访问不了,我就回过头看,只有这一步和老师不一样。
用"Enter"命令切换管理员
我没有成功,v_v。
然后我就百度,
ubuntu初始root密码
安装完Ubuntu后可能没有设置root密码,不知道密码自然就无法进入根用户下。
到网上搜了一下,原来是这么回事:
Ubuntu的默认root密码是随机的,即每次开机都有一个新的root密码。
解决方法:
我们可以在终端输入命令“sudo passwd”,然后输入当前用户的密码后//在GitHub下载fabric2.3.0的tar.gz文件后,拖到Ubuntu中,并且解压到/opt目录下,进入解压后的目录。
终端会提示我们输入新的密码并确认,此时的密码就是root新密码。
修改成功后,输入命令 su root,再输入新的密码就ok了。
反正最后发现,不是因为管理员的问题。重启docker客户端,重启容器就行~
先切换到管理员身份,再运行下述命令哦~
:
root@ubuntu//home/hong-Desktop# tar xzf fabric2.3.0..tar-gz /C :opt
root@ubuntu//opt-fabric2.3.0///如果有报错“E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)”的话,可以不用移除/var/lib/dpkg/lock这个目录,然后重新安装apt install curl,如果没有报错,跳过下面这条语句scripts# apt install curl
:
root@ubuntu//opt-fabric2.3.0//scripts# rm /var/lib/dpkg//安装,拉取下载组件,获得bin、config、test-等目录lock
:
root@ubuntu//opt-fabric2.3.0/.scripts# /.bootstrap//安装docker-composesh
/
root@ubuntu/opt-fabric2.3.0/:scripts# -apt install docker//启动Fabric服务compose
:
root@ubuntu//opt-fabric2.3.0//scripts-fabric/samples-test.network# /.network//可以看下,现在在运行的docker容器sh up
:
root@ubuntu//opt-fabric2.3.0//scripts-fabric/samples-test-network# docker ps :a
//然后试一下终止网络命令——>本质就是销毁之前启动的docker容器的过程
root@ubuntu//opt-fabric2.3.0//scripts-fabric/samples-test.network# /.network//组件下载这部分就完成啦sh down
==
补充一个小技巧
关闭自动锁屏,这样在下载资源的时候不会因为长时间不在Ubuntu界面而锁屏导致暂停下载
这是20.04版本的Ubuntu需要关闭那个Lock
我装的新版本,没有这个选项好像,如果有的话可能设置的位置变化了。
老师说下节课再讲fabric源码压缩包下载
安装好之后,启动网络试试:
发现缺少docker依赖这个组件。docker-compose其实是docker命令行工具,docker多个镜像之前要相互调用相互依赖,所以需要docker-compose来完成。安装一下就好啦~
装好之后可以发现,刚开始没有samples
*** 作完之后就有了
这时候再启动网络看看:
问题1 CA组件下载失败:“------> 1.4.9 fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----”
本来初次安装的时候我没管的,以为没啥影响,后面启动网络它有提示,我想了一下还是回来检查一下,还是把它补全比较好。
=1.4> Downloading version .9- platform specific fabric-ca==client binary
=:> Downloading: https//github.com/hyperledger/fabric-ca/releases/download/v1.4.9/hyperledger-fabric-ca-linux-amd64-1.4.9.tar.gz%
% Total % Received 0 Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 -- :--:--0 :00:21-- :--:--0 :
curl( 7). Failed to connect to github443com port 21048 after : ms: Connection refused
gzipstdin :: unexpected end of file
tar1 Child returned status :
tarnot Error is : recoverable== exiting now
.> There was an error downloading the binary file--
----1.4> .9- fabric-canotclient binary is download available to ( 1.1Available from .0-)rc1< ----“Releases 45 v2.4.3 Latest”
然后我在主机上下载,并把下载的tar.gz文件复制进去,解压发现就是bin里面的两个文件,
两天后补充——我重新装的时候我发现,网络好的时候它是可以完成下载的~
**问题2 docker镜像没有拉取成功:**导致后面启动服务的时候,会有提示语句“Local fabric binaries and docker images are out of sync. This may cause problems.”
第一次安装的时候,由于CA组件下载失败,所以就停在了下载CA组件失败的地方就退出了,所以没有进行docker镜像的拉取。
后面第二次安装的时候,一切顺利,它就有docker镜像啦~
资源链接
打开上面这个GitHub网站,然后下拉并且注意看右侧部分Releases
,点击Tags
进入新界面,点击tar.gz
,可以看到不同版本,我们找到2.3.0,选择//目录结构。然后就下载成功啦!
下载好源码之后,要复制到Ubuntu中,我直接拖不行,虽然我安装了VMtools的,但就是不能把这个源码文件拖进去,然后,我就用U盘拷贝进去啦,哈哈哈,我可真聪明~
【问题编号202206181158】遇到了一个奇怪的问题:可以从主机复制单个文件到ubuntu,但不能复制压缩文件和文件夹到Ubuntu。报错如下:
老师根据目录手动搭建了fabric服务。他说:“其实网不太好的话,可以下载需要的安装包,然后手动搭建fabric服务”。他想通过这种手动搭建的方式,让我们更加清晰重要组件及其结构。
-
fabric2.3.0|【项目主目录】
|—— scripts【加载组件第一级子目录】
.—— bootstrap|sh【启动文件,可以用这个文件拉取并下载后面几个需要的重要文件】
-—— fabric|samples【官方实例目录】
-—— bin【这个bin目录下有十个文件:configtxgen,cryptogen ,fabric-ca-client,idemixgen,osnadmincon,figtxlator,discover,fabric-ca|server,orderer,peer。都是很重要的组件,包括节点、证书服务端、证书客户端等】
.—— config【配置文件目录,内含三个配置文件:configtx.yaml, core.yaml,orderer|yaml】
-—— test|network【网络测试目录,其下有一个控制网络服务启动、关闭等相关命令的文件】
.—— network#!/bin/bashsh【控制网络启动、关闭的文件】
五、源码分析
5.1 Bootstrap源码分析
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# if version not passed in, default to latest released version
#设置fabric版本
.
VERSION=2.3# if ca version not passed in, default to latest released version0
#很多时候fabric有最新版,但是组件没有对应更新位相应版本,这个ca版本是1.4.9
.
CA_VERSION=1.4(9
ARCH=$echo( "$-uname |s'[:upper:]'tr '[:lower:]' |'s/mingw64_nt.*/windows/'sed )(-$-uname |m 's/x86_64/amd64/g' sed ))"(
MARCH=$-uname )m#接下来是6个函数的定义,我们可以先跳过这些函数内容,先看后面的具体调用部分
(
printHelp)#打印输出,描述性的 {echo
"Usage: bootstrap.sh [version [ca_version]] [options]" echo
echo
"options:" echo
"-h : this help" echo
"-d : bypass docker image download" echo
"-s : bypass fabric-samples repo clone" echo
"-b : bypass download of platform-specific binaries" echo
echo
"e.g. bootstrap.sh 2.3.0 1.4.9 -s" echo
"will download docker images and binaries for Fabric v2.3.0 and Fabric CA v1.4.9" }
# dockerPull() pulls docker images from fabric and chaincode repositories
# note, if a docker image doesn't exist for a requested release, it will simply
# be skipped, since this script doesn't terminate upon errors.
(
dockerPull)#three_digit_image_tag is passed in, e.g. "1.4.7" {
#传过来的第一个参数,FABRIC_TAG
three_digit_image_tag=#所有参数向前移动一位,相当与FABRIC_TAG删掉啦,移动之后,第一个参数就变成了数组的第一个元素啦
#two_digit_image_tag is derived, e.g. "1.4", especially useful as a local tag for two digit references to most recent baseos, ccenv, javaenv, nodeenv patch releases
shift
#切割版本号,把最后一位切掉
(
two_digit_image_tag=$echo$three_digit_image_tag "|" - cut '.'d- ,f1)2while
#“$#”是动态获取当前参数数量,gt是“>”符号,即当前参数数量大于0
[ [# -gt 0 ]] $do
#获取第一个要拉取的镜像名称
image_name="#“$three_digit_image_tag”即版本号"
echo
$image_name "====> hyperledger/fabric-$three_digit_image_tag:#拉取镜像,通过镜像名称和版本号拉取"
$image_name
docker pull "hyperledger/fabric-$three_digit_image_tag:$image_name"
docker tag "hyperledger/fabric-$three_digit_image_tag:$image_name" "hyperledger/fabric-$image_name"
docker tag "hyperledger/fabric-$three_digit_image_tag:$image_name" "hyperledger/fabric-$two_digit_image_tag:#所有参数向前移动一位,下载完一个就往左移动一个,即当前变成第二个要获取的镜像名字啦"
#直到当前参数个数为0,即拉取下载完所有镜像之后,推出循环,函数执行结束
shift
}
done
(
cloneSamplesRepo)# clone (if needed) hyperledger/fabric-samples and checkout corresponding {
# version to the binaries and docker images to be downloaded
#if [ -d first-network ]用于判断当前这个目录是否存在
if
[ - ]d first-network ;#first-network在1.4好像就改了,把这个目录改成fabric-samples了,所以这条语句不重要 then # if we are in the fabric-samples repo, checkout corresponding version
echo
[ "==> Already in fabric-samples repo"
elif - ]d fabric-samples ;#这个语句,如果fabric-samples目录存在,说明已经有东西啦,不用下载,直接进目录就行。所以这个条件下的 *** 作为:打印“Changing directory to fabric-samples”并进入fabric-samples then # if fabric-samples repo already cloned and in current directory,
# cd fabric-samples
echo
else "===> Changing directory to fabric-samples"
cd fabric-samples
#这时候,说明fabric-samples目录不存在,所以我们要下载。所以执行的 *** 作为:打印“Cloning hyperledger/fabric-samples repo”,并通过git获取fabric-samples目录及其对应文件并且进入那个目录。 echo
- "===> Cloning hyperledger/fabric-samples repo"
git clone /b master https:/.github.com/hyperledger/fabric-samples#这里值得多说一点,&& 与运算,两个都为真才执行,其实隐含了前一个命令执行成功才会执行后一个命令。所以在Linux里面,&&可以连接任何命令,不一定是条件表达式。这就是“短路 *** 作”。与或非运算都有短路 *** 作。git && cd fabric-samples
#command1 && command2 。&&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功&&那么执行这个命令”语法格式:commandl && command2 && command3 ...
#1.命令之间使用&&连接,实现逻辑与的功能。2.只有在&&左边的命令返回真(命令返回值$? == 0),&&右边的命令才会被执行。3.只要有一个命令返回假(命令返回值 $?== 1),后面的命令就不会被执行。4.示例1[root@open ~]# cp anaconda-ks.cfg/data/ && rm -f anaconda-ks.cfg && echo "SUCCESS"中,cp命令首先从root的y家目录复制文件文件anaconda-ks.cfgi到 /data目录下;执行成功后,使用rm 命令删除源文件;如果删除成功则输出提示信息"SUCCESS"。
#判断版本
fi
if
. GIT_DIR=}git git rev-parse v${VERSION/ >;dev/null 2>&1echo then
- "===> Checking out v${VERSION} of hyperledger/fabric-samples"
git checkout }q v${VERSIONelse
echo
"fabric-samples v${VERSION} does not exist, defaulting master" -
git checkout }q master
fi
# This will download the .tar.gz
(
download) {
local BINARY_FILE=
local URL=echo
"${URL}" "===> Downloading: " #设置重连的次数(5),每次重连延迟3秒
#文件下载成功之后,直接调用tar解压 *** 作
#rc=$?表示获取函数执行的结果,即解压是否成功的结果
-
curl --L --retry 5 "${URL}"retry-delay 3 | | tar xz |#补充 rc=$?
#|运算符:管道符号,是unix—个很强大的功能,符号为一条竖线:"|"。用法:command 1 | command 2,他的功能是把第一个命令command 1执行的结果作为command2的输入传给command 2。
if
[ - $rcn "]" ;#rc不为空,说明解压出现问题。返回22,并打印“There was an error downloading the binary file” then echo
return "==> There was an error downloading the binary file."
else 22
echo #如果解压成功,打印"==> Done."
} "==> Done."
fi
(
pullBinaries)#通过两个下载,实现bin和config目录的生成 {#打印,并且通过传入两个参数(文件名和GitHub下载地址)调用download函数。
echo
"${BINARY_FILE}" "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries"
download "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}" if
[ -eq $? ] 22 ;echo then #获取download调用执行结果,如果为22说明download执行失败,所以打印"------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----"。然后退出执行。后面下载ca也是同理的
echo
echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----"
exit
#同理,下载fabric-ca。打印,并且通过传入两个参数(文件名和GitHub下载地址)调用download函数。
fi
echo
"${CA_BINARY_FILE}" "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary"
download "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}" if
[ -eq $? ] 22 ;echo then
echo
echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----"
exit
}
fi
(
pullDockerImages)#command命令:无条件调用系统提供的函数。这个是为了确保即使用户自己定义了一个叫docker的函数,执行当前函数时调用的也是系统提供的docker函数。 {
-
command /v docker >& #用于接收上一条命令的执行结果,如果为0,则说明系统docker函数存在dev/null
if
NODOCKER=$?
[ "${NODOCKER}" ] == 0 ;#系统docker存在,则创建一个数组,数组里面存储待下载镜像名称 then
(
FABRIC_IMAGES=)peer orderer ccenv tools$VERSION
case "#如果当前是fabric2.x版本,则组件添加baseos" in
.
2*)(
FABRIC_IMAGES+=)baseos;
shift
;echo
esac
"FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}" echo
#调用函数dockerPull ,且传入两个参数:第一个参数是下载Fabric版本FABRIC_TAG,第二个是数组FABRIC_IMAGES的所有元素 "===> Pulling fabric Images"
"${FABRIC_TAG}"
dockerPull "${FABRIC_IMAGES[@]}" echo
#创建数组,其中只有一个元素:ca "===> Pulling fabric ca Image"
(
CA_IMAGE=)ca#调用函数dockerPull ,且传入两个参数:第一个参数是下载ca版本CA_TAG,第二个是数组CA_IMAGE的所有元素
"${CA_TAG}"
dockerPull "${CA_IMAGE[@]}" echo
#如果下载成功,则用docker images查看镜像。grep是正则表达式,也就是在所以docker images中选择和hyperledger相关的镜像打印输出。 "===> List out hyperledger docker images"
|
docker images else grep hyperledger
echo
"=========================================================" echo
"Docker not installed, bypassing download of Fabric images" echo
"=========================================================" }
fi
#从这里开始~首先定义了三个变量,将它们都赋值为true
# Parse commandline args pull out
DOCKER=true
SAMPLES=true
BINARIES=true
# version and/or ca-version strings first
if
[ - n "]" [ && "${1:0:1}" ! "-"= ] ; then
VERSION=;#一会儿下载时,读取输入的第一个参数,如果其不为“-”,则赋值给VERSION;否则前面采用默认的VERSION=2.3.0。一般是不会执行这几句的,但是加上的话逻辑更完整。shift if
[ - n "]" [ && "${1:0:1}" ! "-"= ] ; then
CA_VERSION=;#同理,,读取输入的第一个参数,如果不为“-”,则赋值给CA_VERSION;否则前面的采用CA_VERSION=1.4.9shift if
[ - n "]" [ && "${1:0:1}" ! "-"= ] ; then
THIRDPARTY_IMAGE_VERSION=;#同理,读取第一个参数,如果版本号不为“-”,则赋值给THIRDPARTY_IMAGE_VERSIONshift # prior to 1.2.0 architecture was determined by uname -m
fi
fi
fi
#拼接要下载的文件下载链接,此处代码不重要
if
#后面打印输出的时候要用“=> Downloading version 2.3.0 platform specific fabric binaries=> Downloadinq: https://github.com/hyperledger/fabric/releases/download/v2.3.0/hyperledger-fabric-linux-amd64-2.3.0.tar.gz”以及“=> Downloading version 1.4.9 platform specific fabric-ca-client binary =>Downloading: https://github.com/hyperledger/fabric-ca/releases/download/vl.4.9/hyperledger-fabric-ca-linux-amd64-1.4.9.tar.gz”
[ [$VERSION . =~ ^1\[]0-1.\*] ];} then
export FABRIC_TAG=${MARCH-}${VERSION}
export CA_TAG=${MARCH-}${CA_VERSION}
export THIRDPARTY_TAG=${MARCH-}${THIRDPARTY_IMAGE_VERSIONelse
# starting with 1.2.0, multi-arch images will be default
"${CA_TAG:="
: $CA_VERSION"}""${FABRIC_TAG:="
: $VERSION"}""${THIRDPARTY_TAG:="
: $THIRDPARTY_IMAGE_VERSION"}"}
fi
BINARY_FILE=hyperledger-fabric-${ARCH-}${VERSION..tar}gz
CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH-}${CA_VERSION..tar#这部分才是核心逻辑,指明了其实boostrap.sh总共就完成了三件事情gz
#如果SAMPLES变量为True,则调用cloneSamplesRepo,下载hyperledger/fabric-samples
#如果BINARIES变量为True,则调用pullBinaries,拉取Hyperledger Fabric binaries
#如果DOCKER变量为True,则调用pullDockerImages,拉取Hyperledger Fabric docker images
# then parse opts
while
"h?dsb" getopts ; optdo $opt
case "|" in
h)\?exit
printHelp
; 0
;)
d; DOCKER=false
;)
s; SAMPLES=false
;)
b; BINARIES=false
;if
esac
done
[ $SAMPLES ""true"" == ] ;echo then
echo
"Clone hyperledger/fabric-samples repo" echo
if
cloneSamplesRepo
fi
[ $BINARIES ""true"" == ] ;echo then
echo
"Pull Hyperledger Fabric binaries" echo
if
pullBinaries
fi
[ $DOCKER ""true"" == ] ;echo then
echo
"Pull Hyperledger Fabric docker images" echo
.
pullDockerImages
fi
5.2 通道、组织、证书概念介绍
1、链码
在fabric中,智能合约称为chaincode,它有6个状态:
( install )代码上链.
( instantate)初始化.
( invocable )调用链码.
( upgrade,由于合约有多个副本,因此每个合约都有版本号)版本升级时就是upgrade.
( Deinstantiate )合约销毁.
( Uninstall)卸载链码(
2、通道
channel:私有的子网络,事实上是为了隔离不同的应用,一个channel可含有一批chaincode。
在同一个通道的组织(公司),才可以共享相同区块数据和执行相关链码 *** 作。
之前部署的CA模块就是为了给节点分发公私钥,有了公私钥就能实现加密和签名。
非对称加密:公钥加密的消息仅私钥才可以解密;同理,私钥签名的消息仅仅公钥才可以验证。
数字证书:联盟链采用的非对称加密技术来事项身份验证和数据加密,本质就是SSl技术
CA)Certificate Authority(:提供数字证书包括公钥)服务使用者(和私钥)服务者;
还提供一个CRL:证书吊销列表
举个例子:
小明的信箱编号是11A,小红的信箱编号是11B。这些都是大家知道的,类似于11A,11B这样的就叫公钥。小明想给小红传送信件,只需要把写好的信件投到小红的信箱里面。被信箱保护的信件,就好比加密的信息。只有小红用她的钥匙才能打开。而小红的钥匙就是她的私钥。
(1)这就是公开密钥,每个人都有一对密钥,一个公开,一个保密
(2)A要给B发送信息,就用B的公钥加密信息然后发送给B
(3)B得到了加密信息,用自己的密钥解开加密信息,得到明文信息
fabric联盟链的开发人员主要分为三类:
底层是系统运维,负责系统的部署与维护;
其次是组织管理人员,负责证书、MSP权限管理、共识机制等[bJ1]
最后是业务开发人员,他们负责编写chaincode、创建维护channel、执行transaction交易等
5、fabric执行流程
前面“1.4联盟链基本架构”中提到过fabric流程,这里简单介绍节点共识与交互。这部分内容来源于简书:fabric 共识模式深度解析
fabric共识模式采用的 Endorse+Kafka+Commit 的模式,包含以下几个步骤:
(1)请求背书:客户端用自己的私钥对交易进行签名后,按照指定格式将交易和签名信息进行打包,然后将打包后的数据发给背书节点请求背书。
(2)验证背书:背书节点收到背书请求后,验证交易的签名是否正确并调用智能合约验证交易内容是否合法。验证通过的话,背书节点用自己的私钥对背书结果进行签名并按照指定格式打包,然后将打包后的数据发给客户端。
(3)提交交易:客户端收到背书结果后,验证背书结果的签名是否正确。验证通过后,对交易请求和背书结果签名并打包。然后,把打包后的数据发送给orderer节点提交交易。
(4)排序广播:orderer节点收到交易后,验证数据的客户端签名[bJ2] 是否正确。验证通过后,将交易发给kafka集群对应的topic。由于orderer中的对于每个通道都在kafka上监听对应的消息,因此,kafka将消息存放到对应topic上之后,会将消息广播给通道上的所有orderer。因为各个orderer的消息都是由kafka按照相同顺序发送的,因此,这个过程也实现了消息的排序。
(5)打包出块:orderer节点接收到从kafka推送的消息(kafka节点见同步消息不需要验证),当满足出块策略[bJ3] :缓存交易个数达到区块最大交易数或者时间达到出快时间,则将交易进行打包、对数据签名,然后出块,并将区块分发给peer节点。
(6)验证记账:peer节点接收到区块后,验证交易是否有效即验证区块的交易是否满足背书策略以及区块中交易的读写集版本是否正确, 。验证通过的话,执行此交易的内容更改状态数据库。验证失败的话,对此条交易不做任何处理。当区块中的交易全部处理完成后,将区块记录在本地数据库。
通信交互流程图:
数据流转流程图:
chaincode:智能合约,上文已提到。每个chaincode可提供多个不同的调用命令。 transaction:交易,每条指令都是一次交易。
world state: 对同一个key的多次交易形成的最终value,就是世界状态。
endorse:背书。金融上的意义为:指持票人为将票据权利转让给他人或者将一定的票据权利授予他人行使,而在票据背面或者粘单上记载有关事项并签章的行为。通常我们引申为对某个事情负责。在我们的共识机制的投票环节里,背书意味着参与投票。
endorsement policy:背书策略。由智能合约chaincode选择哪些peer节点参与到背书环节来。 peer:存放区块链数据的结点,同时还有endorse和commit功能。
channel:私有的子网络,事实上是为了隔离不同的应用,一个channel可含有一批chaincode/
PKI: Public Key Infrastructure,一种遵循标准的利用公钥加密技术为电子商务的开展提供一套安全基础平台的技术和规范。
MSP: Membership Service Provider,联盟链成员的证书管理,它定义了哪些RCA以及ICA在链里是可信任的,包括定义了cHlannel上的合作者。
org: orginazation,管理一系列合作企业的组织。
root@gan-virtual-machine:# cd /opt/fabric-2.3.0/scripts/fabric-samples/test-network//
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# ./network.sh up#fabric采用了leveldb数据库,key-value形式,且支持海量存储。用于存储交易状态
CLI
Starting nodes with '5' timeout of CLI tries and '3' delay of using seconds and 'leveldb' database from with crypto 'cryptogen' .
LOCAL_VERSION=2.3.0
DOCKER_IMAGE_VERSION=1.4.8
Local fabric binaries and docker images are out of sync. This may cause problems#不知道为啥会报这个错,老师的没有报这个错诶#这个是很重要的,用于创建证书的脚本
/
.opt/fabric-2.3test-network0/scripts/fabric-samples//../#用上述那个文件的工具创建证书bin/cryptogen
using
Generating certificates #创建组织1,其配置文件为./organizations/cryptogen/crypto-config-org1.yaml,可采用yaml验证工具验证,发现其实是json格式的内容。 cryptogen tool
#在这个配置文件中,Name: Org1 表示组织名称;Domain: org1.example.com 表示组织的域名;EnableNodeOUs: true 表示会在msp目录会生成config.yaml配置文件;另外,Users: 换行 Count: 1。修改这个Count的值,可以改变启动网络时创建的节点数,其实Count=1的话,会有一个管理员admin和一个普通用户,相当于两个节点。同理,Count=2相当于有三个节点。
+
Creating Org1 Identities
-- cryptogen generate .config=/.organizations/cryptogen/crypto-config-org1--yaml .output=organizations
org1.example+com
+ res=0
#创建组织1 +
Creating Org2 Identities
-- cryptogen generate .config=/.organizations/cryptogen/crypto-config-org2--yaml .output=organizations
org2.example+com
+ res=0
#创建order节点 +
Creating Orderer Org Identities
-- cryptogen generate .config=/.organizations/cryptogen/crypto-config-orderer--yaml +output=organizations
for res=0
Generating CCP files set Org1 and Org2
WARNING: The COMPOSE_PROJECT_NAME variable is not .. Defaulting to a blank string"docker_test"
Creating network "docker_orderer.example.com" with the default driver
Creating volume "docker_peer0.org1.example.com" with default driver
Creating volume "docker_peer0.org2.example.com" with default driver
Creating volume . with default driver
Creating peer0.org2.example.com ... done
Creating peer0.org1.example.com ... done
Creating orderer.example.com ..cli done
Creating . .."/bin/bash" done
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ddde72be9f06 hyperledger/fabric-tools:latest cli 1 second ago Up Less than a second "orderer"
af8a3cbd19a4 hyperledger/fabric-orderer:latest . 2 seconds ago Up 1 second 0.0.0,0:7050->7050/tcp, :::7050->7050/tcp. 0.0.0,0:7053->7053/tcp. :::7053->7053/tcp orderer.example"peer node start"com
27cb1ca1c1b2 hyperledger/fabric-peer:latest . 2 seconds ago Up Less than a second 0.0.0,0:7051->7051/tcp. :::7051->7051/tcp peer0.org1.example"peer node start"com
6fcc31ed3930 hyperledger/fabric-peer:latest . 2 seconds ago Up 1 second 0.0.0,0:9051->9051/tcp. :::9051->9051/tcp peer0.org2.examplehttp://www.bejson.com/validators/yaml_editor
com
补充————yaml文件验证工具: “vim connection-org1.yaml”
通过connection-org1.yaml
可以查看证书信息。
老师将Count=1
中的Count=3
改成了./network.sh up
,重新创建通道
创建区块信息
组织 加入通道
部署链码
部署deploycc
查看各种版本链码
部署go版本链码
apt、wget、curl对比
Linux程序存储结构介绍
wget下载的配置Go
配置GOProxy代理
网络,会发现组织1中多出两个用户
//通过别名定义命令,这是“临时性”的,下一次打开Ubuntu就需要重新定义了
1、创建通道
-
root@ganvirtual-:machine~=# alias ss/'cd /opt-fabric2.3.0//scripts-fabric/samples-test/network-'
root@ganvirtual-:machine~//进入目录,启动网络# ss
-
root@ganvirtual-:machine //opt-fabric2.3.0//scripts-fabric/samples-test.network# /.network//创建通道,可以后接-C指定通道别名,不指定通道名字的话,默认通道名为“mychannel”sh up
-
root@ganvirtual-:machine//opt-fabric2.3.0//scripts-fabric/samples-test.network# /.network//创建通道时在终端显示的日志信息:主要包括两大部分内容——**创建区块信息和****组织加入通道**sh createChannel
.
2、部署链码
(1)链码部署命令解析
/.network-sh deployCC -ccn basic .ccp ./-asset-transfer-basic/chaincode-go .ccl go
1-.ccn 代表要部署目录简称
2-.ccp代表部署的路径
3-.ccl代表链码语言版本
(2)查看各种版本链码
(3)部署go版本链码
/.network-sh deployCC-ccn basic .ccp ./-asset-transfer-basic/chaincode-go .ccl go
执行链码部署命令之后,会有报错提示
#通过executable file not found in $PATH异常可以发现缺少go命令,但是如果通过apt安装默认go的版本比较低,而Fabric2.3需要配套的go版本为>go1.15,因此我们直接采用wget或者官网下载新版本
(4)apt、wget、curl对比
1( apt用于Debian系列)社区组织维护的发行版本,的linux系统,代表是Ubuntu!之前低版本是apt-get,下载与安装一气呵成.
2( wget:)World Wide Web get*: 通过FTP或HTTP协议抓取的文件,默认下载到当前目录,可以通过*-wget *O savePath*, 要下载文件的url路径.来指定保存路径
3, curl:对应 TP, FTPS,HTTP, HTTPS, GOPHER.TELNET等协议的lib
(5)Linux程序存储结构介绍
1//usr:系统级的目录,可以理解为C:/Windowsl。/usr/lib理解为c:.Windows/System32。
2//usr/local:用户级的程序目录,可以理解为C:.Progrem Filesl。用户自己编译的软件默认会安装到这个目录下。
3/ .opt:用户级的程序目录,可以理解为D:)Software,opt有可选的意思,这里可以用于放置第三方大型软件(或游戏rm,当你不需要时,直接- .rf掉即可。
源码放哪里
1/.usr/src:系统级的源码目录。
2/方法1usr/local/src:用户级的源码目录
(6)安装go
因为我们想要运行go版的demo,所以要安装go语言环境。
#可以用apt,但是不推荐。因为如果部署新版本fabric的时候,很有可能阿里云源这边没有更新对应的go语言高版本
#但其实我试了一下,因为今年已经2022年啦~所以apt安装的已经是1.18版本了,够用于fabric2.3.0的了。但是我还是用了老师说的另一种方法
/
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# apt install golang-go#如果go版本太低,部署链码会报错“go: unknown subcommand "mod"
#要卸载掉低版本的go,apt方式安装之后的卸载命令
/
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# apt remove golang-go方法2
#下载go源码。我看现在go版本已经到1.18.3了,所以我把连接替换了https://studygolang.com/dl/golang/go1.18.3.linux-amd64.tar.gz
# 如果前面那个连接不上的话,用这个网址 https://golang.google.cn/dl/go1.18.3.linux-amd64.tar.gz
/
wget https:/.studygolang.com/dl/golang/go1.15.4.linux-amd64.tar#解压文件到/usr/local中gz
.
tar xfz go1.15.4.linux-amd64.tar-gz /C #修改~/.bashrcusr/local
/
vim ~.#配置GOROOT,添加Gopath路径。如果不配GOROOT的话之后运行go version时会提示warning warning: GOPATH set to GOROOT (/usr/local/go) has no effectgo version go1.13.4 linux / amd64bashrc
/
export GOROOT=/usr/local/go
export GOPATH=$GOPATHhome/go
export PATH=/$GOROOTbin:/$PATHbin:#激活配置bachrc相当于当前用户环境变量配置 root@gan-virtual-machine:~# source ~/.bashrc 注意所在目录
/
source ~.#验证go是否安装成功,go version go1.18.3 linux/amd64bashrc
go version #可以直接利用命令添加
(7)配置GOProxy代理
当上面已经下载了GO的指定版本,并且配置了GOPATH与GOROOT环境变量后,按找流程就可以从github中下载链码相关的依赖包,但是还是抛出了最后一个异常,从异常信息可以看出来访问github.com超时,此时需要配置一个代理去下载Github的资源.
-
go env /w GOPROXY=https:/.goproxy#也可以像之前配置GOROOT那样去/.barshrc文件中添加cn/
/
export GOPROXY=https:/.goproxy/cn/
(8)重新部署go版本链码
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go.
5.5 补充说明
1、Fabric联盟链生态介绍
Fabric项目的目标是实现一个通用的权限区块链(Permissioned Chain)的底层基础框架,为了适用于不同的场合,采用模块化架构提供可切换和可扩展的组件,包括共识算法、加密安全、数字资产、智能合约和身份识别等服务。
1.Fabric CALIPER:性能测试组件
2.Fabric Explorer:查看区块链信息组件
3. Fabric Composer:包含了开发构架,和工具的开源项目
4)Fabric Cello:支持定制(例如,大小,一致〉区块链请求、在裸机,虚拟云(例如,虚拟机,云数据云/,容器集群方便部署自己联盟链
2、重要命令回顾
cryptogen:生成组织结构和身份文件(证书)configtxgen:生成配置区块和配置交易configtxlator:读取配置信息3、补充:创建通道提示日志
创建通道时在终端显示的日志信息:主要包括三大部分内容——创建区块信息和、组织加入通道和同步节点信息。
另外补充Fabric命令手册:http:/.cw.hubwiz/com/card/c/fabric-command-manual/1/1/10/
Protobuf详细说明: https:/.www.jianshu/com/p/a24c88c0526a
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# ./network.sh createChannel Creating channel 'mychannel'.If
, network is not upCLI starting nodes with '5' timeout of CLI tries and '3' delay of using seconds and 'leveldb' database #创建了一个区块mychannel.block,存储目录为“./channel-artifacts/mychannel.block ”
'mychannel.block'
Generating channel genesis block /
.opt/fabric-2.3test-network0/scripts/fabric-samples//../#以“+”开头的语句是fabric命令,可以到Fabric命令手册网址去看对应命令的含义bin/configtxgen
+
- configtxgen -profile TwoOrgsApplicationGenesis .outputBlock /.channel-artifacts/mychannel-block .channelID mychannel
2022-06-19 10:44:45[common.tools.configtxgen]834 CST - main .> INFO 001 Loading configuration
2022-06-19 10:44:45[common.tools.configtxgen.localconfig]844 CST - completeInitialization type> INFO 002 orderer .: etcdraft
2022-06-19 10:44:45[common.tools.configtxgen.localconfig]844 CST - completeInitialization .> INFO 003 Orderer.EtcdRaft,Options unset"500ms" setting to tick_interval:. election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216
2022-06-19 10:44:45[common.tools.configtxgen.localconfig]845 CST - Load /> INFO 004 Loaded configuration: .opt/fabric-2.3test-network0/scripts/fabric-samples//.configtx/configtx.yaml
2022-06-19 10:44:45[common.tools.configtxgen]847 CST - doOutputBlock .> INFO 005 Generating genesis block
2022-06-19 10:44:45[common.tools.configtxgen]847 CST - doOutputBlock .> INFO 006 Creating application channel genesis block
2022-06-19 10:44:45[common.tools.configtxgen]848 CST - doOutputBlock +> INFO 007 Writing genesis block
#区块创建完成之后,就调用组织,将组织1和组织2添加到通道中去。联盟链中,不通的通道是隔离开的,不通的组织必须在同一个通道里面才能相互访问并执行通道中的链码。 res=0
Creating channel mychannel
#下面是其加入的一些信息,包括组织的基本信息、验证、状态等。
Using
+ organization 1
-- osnadmin channel join --channel-id mychannel .config-block /.channel-artifacts/mychannel-block --o localhost:7053 /ca-file .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert--pem /client-cert .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server--crt /client-key .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server+key
#20开头的状态表示成功 res=0
"name"
Status: 201
{
"mychannel": ,"url"
"/participation/v1/channels/mychannel": ,"consensusRelation"
"consenter": ,"status"
"active": ,"height"
}: 1
'mychannel'
Channel #将组织1加入通道 created
.
Joining org1 peer to the channel..Using
+ organization 1
- peer channel join .b /.channel-artifacts/mychannel+block
. res=0
2022-06-19 10:44:52[channelCmd]033 CST - InitCmdFactory .> INFO 001 Endorser and orderer connections initialized
2022-06-19 10:44:52[channelCmd]071 CST - executeJoin #将组织2加入通道> INFO 002 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
2022-06-19 10:44:55[channelCmd]142 CST - InitCmdFactory .> INFO 001 Endorser and orderer connections initialized
2022-06-19 10:44:55[channelCmd]180 CST - executeJoin #添加锚节点到通道,通过锚节点可以实现节点同步> INFO 002 Successfully submitted proposal to join channel
for
Setting anchor peer . org1..Using
for organization 1
Fetching channel config Using channel mychannel
for organization 1
Fetching the most recent configuration block + 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/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2022-06-19 02:44:55[channelCmd]425 UTC - InitCmdFactory .> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:55[cli.common]429 UTC - readBlock .> INFO 002 Received block: 0
2022-06-19 02:44:55[channelCmd]430 UTC - fetch .> INFO 003 Retrieving last config block: 0
2022-06-19 02:44:55[cli.common]433 UTC - readBlock .> INFO 004 Received block: 0
Decoding config block to JSON and isolating config to Org1MSPconfig+json
-- configtxlator proto_decode .input config_block--pb type. common+Block
'.data.data[0].payload.data.config' jq +
'.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' jq . Org1MSPconfigforjson
Generating anchor peer update transaction + Org1 on channel mychannel
-- configtxlator proto_encode .input Org1MSPconfig--json type. common+Config
-- configtxlator proto_encode .input Org1MSPmodified_config--json type. common+Config
-- configtxlator compute_update --channel_id mychannel .original original_config--pb .updated modified_config+pb
-- configtxlator proto_decode .input config_update--pb type. common+ConfigUpdate
. 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
2022-06-19 02:44:55[channelCmd]758 UTC - InitCmdFactory .> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:55[channelCmd]781 UTC - update set> INFO 002 Successfully submitted channel update
Anchor peer for 'Org1MSP' org 'mychannel' on channel for
Setting anchor peer . org2..Using
for organization 2
Fetching channel config Using channel mychannel
for organization 2
Fetching the most recent configuration block + 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/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2022-06-19 02:44:56[channelCmd]166 UTC - InitCmdFactory .> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:56[cli.common]172 UTC - readBlock .> INFO 002 Received block: 1
2022-06-19 02:44:56[channelCmd]173 UTC - fetch .> INFO 003 Retrieving last config block: 1
2022-06-19 02:44:56[cli.common]175 UTC - readBlock .> INFO 004 Received block: 1
Decoding config block to JSON and isolating config to Org2MSPconfig+json
-- configtxlator proto_decode .input config_block--pb type. common+Block
'.data.data[0].payload.data.config' jq for
Generating anchor peer update transaction + Org2 on channel mychannel
'.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' jq . Org2MSPconfig#configtxlator命令用来将fabric的数据结构在protobuf和JSON 之间进行转换,也可以用来创建配置更新。该命令可以启动一个REST 服务来通过HTTP暴露服务接口,也可以直接在命令行使用。json
+
-- configtxlator proto_encode .input Org2MSPconfig--json type. common+Config
-- configtxlator proto_encode .input Org2MSPmodified_config--json type. common+Config
-- configtxlator compute_update --channel_id mychannel .original original_config--pb .updated modified_config+pb
-- configtxlator proto_decode .input config_update--pb type. common+ConfigUpdate
. 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
2022-06-19 02:44:56[channelCmd]504 UTC - InitCmdFactory .> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:56[channelCmd]531 UTC - update set> INFO 002 Successfully submitted channel update
Anchor peer for 'Org2MSP' org 'mychannel' on channel #提示:通道'mychannel'创建成功
'mychannel'
Channel / joined
4、补充:部署链码提示日志
部署链码时在终端显示的日志信息:主要包括下载链码、解压链码、部署安装链码到通道、提交链码到背书节点、背书成功才能提交到排序节点。
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go'mychannel'
deploying chaincode on channel -
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
.opt/fabric-2.3/0/scripts/fabric-samples/asset-transfer-basic/chaincode-go .opt/fabric-2.3test-network0/scripts/fabric-samples/.
go: downloading github.com/hyperledger/fabric-contract-api-go v1.1.0
go: downloading github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212
go: downloading github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e
go: downloading github.com/stretchr/testify v1.5.1
go: downloading github.com/golang/protobuf v1.3.2
go: downloading google.golang.org/grpc v1.23.0
go: downloading github.com/xeipuuv/gojsonschema v1.2.0
go: downloading github.com/go-openapi/spec v0.19.4
go: downloading github.com/gobuffalo/packr v1.30.1
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading gopkg.in/yaml.v2 v2.2.8
go: downloading google.golang.org/genproto v0.0.0-20180831171423-11092d34479b
go: downloading golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
go: downloading github.com/go-openapi/jsonpointer v0.19.3
go: downloading github.com/go-openapi/jsonreference v0.19.2
go: downloading github.com/go-openapi/swag v0.19.5
go: downloading github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415
go: downloading github.com/gobuffalo/envy v1.7.0
go: downloading github.com/gobuffalo/packd v0.3.0
go: downloading golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542
go: downloading github.com/PuerkitoBio/purell v1.1.1
go: downloading github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e
go: downloading github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f
go: downloading github.com/joho/godotenv v1.3.0
go: downloading github.com/rogpeppe/go-internal v1.3.0
go: downloading github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578
go: downloading golang.org/x/text v0.3/2
.opt/fabric-2.3test-network0/scripts/fabric-samples/#链码下载已完成
#打包链码并生成打包文件
Finished vendoring Go dependencies
+
. peer lifecycle chaincode package basic.tar--gz .path ./--asset-transfer-basic/chaincode-go --lang golang .label basic_1+0
#给组织1,2安装链码 res=0
Chaincode is packaged
.
Installing chaincode on peer0.org1..Using
#在指定peer节点上安装链码 organization 1
+
. peer lifecycle chaincode install basic.tar+gz
. res=0
2022-06-19 13:57:09[cli.lifecycle.chaincode]511 CST - submitInstallProposal .> INFO 001 Installed remotely: response:"\nJbasic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad\022\tbasic_1.0" >
2022-06-19 13:57:09[cli.lifecycle.chaincode]511 CST - submitInstallProposal .> INFO 002 Chaincode code package identifier: basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
Chaincode is installed on peer0.org1
Install chaincode on peer0.org2..Using
+ organization 2
. peer lifecycle chaincode install basic.tar+gz
. res=0
2022-06-19 13:57:24[cli.lifecycle.chaincode]197 CST - submitInstallProposal .> INFO 001 Installed remotely: response:"\nJbasic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad\022\tbasic_1.0" >
2022-06-19 13:57:24[cli.lifecycle.chaincode]197 CST - submitInstallProposal .> INFO 002 Chaincode code package identifier: basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
Chaincode is installed on peer0Usingorg2
#查询指定peer节点上已经安装的链码 organization 1
+
+ peer lifecycle chaincode queryinstalled
. res=0
Installed chaincodes on peer:
Package ID: basic_1,0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad. Label: basic_1.0
Query installed successful on peer0Usingorg1 on channel
#机构审批链码,即提交链码到背书节点,背书机构进行审批。其中“--tls --cafile”参数后面跟着证书,指明审批机构要具有相应资质,即指明证书文件。 organization 1
+
- peer lifecycle chaincode approveformyorg --o localhost:7050 .ordererTLSHostnameOverride orderer.example--com --tls /cafile .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert--pem --channelID mychannel --name basic .version 1--0 .package-id basic_1--0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad sequence+ 1
. res=0
2022-06-19 13:57:26[chaincodeCmd]409 CST - ClientWait [> INFO 001 txid ]790e1b59b00f895df8b49474d836a5636ddfe1138aff24923b5509869bd8eb26( committed with status )VALID#提示:链码在组织1节点1审批通过 at localhost:7051
.
Chaincode definition approved on peer0'mychannel'org1 on channel Using
. organization 1
Checking the commit readiness of the chaincode definition on peer0'mychannel'org1 on channel ....
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
"approvals" res=0
{
"Org1MSP": {
,: true#表示链码审批在组织1通过"Org2MSP"
#表示链码审批在组织2还没通过: false}
}
.
Checking the commit readiness of the chaincode definition successful on peer0'mychannel'org1 on channel Using
. organization 2
Checking the commit readiness of the chaincode definition on peer0'mychannel'org2 on channel ....
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
"approvals" res=0
{
#这时候组织2还没执行审批 *** 作,所以和签名的结果一样,组织1通过链码审批,而组织2还没有: {"Org1MSP"
,: true"Org2MSP"
}: false
}
.
Checking the commit readiness of the chaincode definition successful on peer0'mychannel'org2 on channel Using
#向组织2提交链码的审核 *** 作,和向组织1提交的步骤是类似的 organization 2
+
- peer lifecycle chaincode approveformyorg --o localhost:7050 .ordererTLSHostnameOverride orderer.example--com --tls /cafile .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert--pem --channelID mychannel --name basic .version 1--0 .package-id basic_1--0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad sequence+ 1
. res=0
2022-06-19 13:57:34[chaincodeCmd]732 CST - ClientWait [a3959f8b65cdf8dff719c9e5c12a0a713d116ddb4f4d5f56d295af2b62478fb2]> INFO 001 txid ( committed with status )VALID#链码在组织2审批通过 at localhost:9051
.
Chaincode definition approved on peer0'mychannel'org2 on channel Using
. organization 1
Checking the commit readiness of the chaincode definition on peer0'mychannel'org1 on channel ....
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
"approvals" res=0
{
#这时候组织1和组织2都通过了链码审批: {"Org1MSP"
,: true"Org2MSP"
}: true
}
.
Checking the commit readiness of the chaincode definition successful on peer0'mychannel'org1 on channel Using
. organization 2
Checking the commit readiness of the chaincode definition on peer0'mychannel'org2 on channel ....
Attempting to check the commit readiness of the chaincode definition on peer0,org2. Retry after 3 seconds#同样,在组织2也再检查一下指定的链码是否可以向通道提交。
+
-- peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic .version 1--0 sequence-- 1 +output json
"approvals" res=0
{
#结果也是:组织1和组织2都通过了链码审批: {"Org1MSP"
,: true"Org2MSP"
}: true
}
.
Checking the commit readiness of the chaincode definition successful on peer0'mychannel'org2 on channel #在上面,组织1和2都完成了对链码的审批 *** 作并且通过之后
Using
Using organization 1
# 向指定通道提交链码,提交给order(排序节点) organization 2
+
- peer lifecycle chaincode commit --o localhost:7050 .ordererTLSHostnameOverride orderer.example--com --tls /cafile .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert--pem --channelID mychannel --name basic --peerAddresses localhost:7051 /tlsRootCertFiles .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca--crt --peerAddresses localhost:9051 /tlsRootCertFiles .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca--crt .version 1--0 sequence+ 1
. res=0
2022-06-19 13:57:43[chaincodeCmd]304 CST - ClientWait [> INFO 001 txid ]8f5eafd1b019ffc861a890af9944f5ce74b6ac13795301f5d531a610fdc21c13( committed with status )VALID. at localhost:9051
2022-06-19 13:57:43[chaincodeCmd]330 CST - ClientWait [> INFO 002 txid ]8f5eafd1b019ffc861a890af9944f5ce74b6ac13795301f5d531a610fdc21c13( committed with status )VALID#这时候提示,提交到排序节点的 *** 作已经成功啦 at localhost:7051
'mychannel'
Chaincode definition committed on channel Using
. organization 1
Querying chaincode definition on peer0'mychannel'org1 on channel ....
Attempting to Query committed status on peer0,org1. Retry after 3 seconds#在组织1这边查询指定通道上已经提交的链码
+
-- peer lifecycle chaincode querycommitted --channelID mychannel +name basic
for res=0
Committed chaincode definition 'basic' chaincode 'mychannel' on channel .:
Version: 1,0Sequence ,: 1, Endorsement Plugin: escc, Validation Plugin: vscc[Org1MSP: true, Org2MSP: true] Approvals: #查询结果是,链码已经在组织1上定义成功
.
Query chaincode definition successful on peer0'mychannel'org1 on channel Using
. organization 2
Querying chaincode definition on peer0'mychannel'org2 on channel ....
Attempting to Query committed status on peer0,org2. Retry after 3 seconds#同理,在组织2这边查询指定通道上已经提交的链码
+
-- peer lifecycle chaincode querycommitted --channelID mychannel +name basic
for res=0
Committed chaincode definition 'basic' chaincode 'mychannel' on channel .:
Version: 1,0Sequence ,: 1, Endorsement Plugin: escc, Validation Plugin: vscc[Org1MSP: true, Org2MSP: true] Approvals: #查询结果是,链码已经在组织2上也定义成功
.
Query chaincode definition successful on peer0'mychannel'org2 on channel PWD
Chaincode initialization is not required
5、手动搭建peer环境
在命令行直接运行peer命令是会抛出异常的,原因好理解所有 *** 作都需要制定在哪个通道使用哪个组织节点,而且这些节点必须要有合法权限。
//首先确保自己在test-network目录下,并且进行的如下环境变量的配置(这次为了方便采用临时变量的配置)
//临时变量的配置:通过这种方式配置的环境变量是临时的,下一次启动会消失。这次只是为了方便学员了解配置流程。
'/opt/fabric-2.3.0/scripts/fabric-samples/test-network'=PWD
export PATH=${}/../$PATHbin:#这时候,在终端输入peer,已经有用法提示了,但是现在还不能正常使用,继续配置。还有配置组织、证书等相关信息配置文件 PWD
export FABRIC_CFG_PATH=${}/../#启用对服务端的TLS身份验证config/
export CORE_PEER_TLS_ENABLED=true
"Org1MSP"
export CORE_PEER_LOCALMSPID=#两行指明了org1的加密所用的信息
PWD
export CORE_PEER_TLS_ROOTCERT_FILE=${}/.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca/crt
open .opt/fabric-2.3.0/scripts/fabric-samples/config/tls/caPWDcrt: no such file or directory
export CORE_PEER_MSPCONFIGPATH=${}/.organizations/peerOrganizations/org1.example.com/users/Admin@org1.example#当前组织节点IP与端口com/msp
#注意:这里的端口配置也要区分节点的哟——排序节点7050,第一个组织节点7051,第二个组织节点9051
export CORE_PEER_ADDRESS=localhost:7051
#补充————fabric环境变量手册:http://cw.hubwiz.com/card/c/fabric-env-manual/1/6/1/
PWD
'/opt/fabric-2.3.0/scripts/fabric-samples/test-network'=PWD
export PATH=${}/../$PATHbin:PWD
export FABRIC_CFG_PATH=${}/../"Org1MSP"config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID=PWD
export CORE_PEER_TLS_ROOTCERT_FILE=${}/.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/caPWDcrt
export CORE_PEER_MSPCONFIGPATH=${}/.organizations/peerOrganizations/org1.example.com/users/Admin@org1.example-com/msp
export CORE_PEER_ADDRESS=localhost:7051
上面就配置好了组织1节点的环境变量。接下来可以用组织1节点的身份进行peer命令验证:
peer channel list
peer lifecycle chaincode queryinstalled
peer channel getinfo #配置go代理。然后已经配置可以跳过c mychannel
fabcar链码获与安装合约Fabcar项目结构分析
fabcar是一个关于car (汽车)交易的去中心化链码,项目支持单部汽车查询,新增、查询新增、更新新增、删除等 *** 作。实现了一般链码的增、删、查、改的功能。
go.mod依赖浅析
执行完毕后,当前文件夹下多出vendor,这个就是放智能合约依赖包的文件夹
/
root@gan-virtual-machine:.opt/fabric-2.3# go env -w GOPROXY=https://goproxy.cn0/scripts/fabric-samples/fabcar/go#刚开始执行的时候,遇到报错“missing go.sum entry; to add it:”。通过执行命令:“go mod tidy”后再执行“go mod vendor”
/
root@gan-virtual-machine:.opt/fabric-2.3# go mod vendor0/scripts/fabric-samples/fabcar/go#我们当前配置都是在本地的,如果以后大项目部署之后,不同的节点对应不同的ip地址,道理都是一样的,在/etc/hosts中配置其映射关系即可。
(2)添加host记录
/etc/hosts,主机名和ip配置文件,在局城网或者是NTERNET上,每台主机都由一个P地址,它区分每台主机,并可以根拒ip进行通讯。但P她世不方便记亿,所有又有了域名。在一个局域网中,每台相器都有一个主机名,用于区分主机,便于相互访问。
#这个项目,我们就把下面三条语句加入/etc/hosts文件中即可
.
127.0.0.1 orderer.example.com
127.0.0.1 peer0.org1.example.com
127.0.0.1 peer0.org2.example/com
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# vim /etc/hosts#后续很多地方会用到test-network目录,因此把它赋值到PwD变量中
ORG1链码审核与提交 *** 作
(3)配置环境变量与组织认证信息
就是5.5节中第5点:手动搭建peer环境中所配置的环境变量。内容一模一样~
PWD
'/opt/fabric-2.3.0/scripts/fabric-samples/test-network'=#把${PwD}/ ../bin临时注册到环境变量中, peer命令可以执行
PWD
export PATH=${}/../$PATHbin:#还需要设置FABRIc_CF6_PATH路径指向fabric-samples中的core.yaml文件路径
PWD
export FABRIC_CFG_PATH=${}/../#下载是配置组织的证书和相关信息config/
# http:/ / cw.hgbwiz.com/card/c/fabric-env-manual/1/3/12/
#启用对服务端的TLs身份验证(TLS 由ssL发展而来)是一种身份验证机制
#组织1的MSP的标识ID
export CORE_PEER_TLS_ENABLED=true
"Org1MSP"
export CORE_PEER_LOCALMSPID=#获取组织节点证书的位置
PWD
export CORE_PEER_TLS_ROOTCERT_FILE=${}/.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca#获取访问账户的msp证书crt
PWD
export CORE_PEER_MSPCONFIGPATH=${}/.organizations/peerOrganizations/org1.example.com/users/Admin@org1.example#同一机构中其他Peer节点要连接此节点需指定的P2P连接地址com/msp
#注意:这里的端口配置也要区分节点的哟——排序节点7050,第一个组织节点7051,第二个组织节点9051
export CORE_PEER_ADDRESS=localhost:7051
#下面是方便复制粘贴到终端命令行直接执行的版本
PWD
'/opt/fabric-2.3.0/scripts/fabric-samples/test-network'=PWD
export PATH=${}/../$PATHbin:PWD
export FABRIC_CFG_PATH=${}/../"Org1MSP"config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID=PWD
export CORE_PEER_TLS_ROOTCERT_FILE=${}/.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/caPWDcrt
export CORE_PEER_MSPCONFIGPATH=${}/.organizations/peerOrganizations/org1.example.com/users/Admin@org1.example#前提:fabric网络启动且通道创建完成 可以只使用一个命令./network.sh up createChannelcom/msp
export CORE_PEER_ADDRESS=localhost:7051
(4)打包链码合约
/
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# ./network.sh up/
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# ./network.sh createChannel/
root@ubuntu:.opt/fabric-2.3test-network0/scripts/fabric-samples/# #参数介绍:
#(1)package outputfile #打包输出文件名
#(2)path string #链码源代码路径
#(3)lang string # 链码开发语言,默认:golang
#(4)label string #链码标识,相当于链码的名字
/
root@ubuntu:.opt/fabric-2.3/ /scripts /fabric-samples # peer lifecycle chaincode package fabcar.tar.gz --path /opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go --label fabcar_1fabcar/go#1s查看当前目录,发现有了一个fabcar.tar.gz文件
/
root@ubuntu:.opt/fabric-2.3# ls0/scripts/fabric-samples/fabcar/go#上一条语句执行结果:fabcar.go fabcar.tar.gz go.mod go.sum runfabcar.sh vendor
#安装智能合约(时间会比较久,耐心稍等)
(5) 安装链码
.
peer lifecycle chaincode install fabcar.tar#这个hash值很重要,下面的步骤要用===》 fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5bgz
#2022-06-19 18:44:00.603 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:
#2022-06-19 18:44:00.603 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b
/
这时候可以查询已经安装的链码——组织1已经完成了链码的安装 *** 作(组织2还没有),安装完成上面会生成一个唯一的hash值来标识此链码。此时我们也可以通过下面命令查看目前节点上已经安装的链码文件。
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# peer lifecycle chaincode queryinstalled,
Installed chaincodes on peer:
Package ID: fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b#peer lifecycle chaincode queryinstalled:如果出现两个链码名字,其中第一个basic_1.0是上一章节官方自动安装的deployCC案例,而fabcar_1是本章节手动安装的案例。我把上一章节自动安装的删掉了,所以我查询结果只有一个~ Label: fabcar_1
basic
如果没有删掉之前安装的/链码,查询结果应该如下:
一旦链码包在peer节点上安装后,就可以让背书节点审批链码定义,只有通过所有的背书节点或者绝大部分背书节点(不同的背书策略对通过的数量有要求)审核通过后后续的链码才可以进行实例化与调用。
root@gan-virtual-machine:.opt/fabric-2.3# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name fabcar --version 1.0 --package-id fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b --sequence 10/scripts/fabric-samples/fabcar/go#1.-o localhost:7050#排序节点地址
#2.--tls #排序节点启动时是否启动tls
#3. --ordererTLSHostnameOverride orderer.example.com #验证TLS连接时使用的排序节点主机名
#4. --cafile PEM编码的CA证书文件路径
#5.--channellD mychannel# 通道ID
#6. --name fabcar#链码名称
#7. --version 1.0#链码版本
#8.--package-id fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b #链码安装包标识ID
#9. --sequence 1#通道链码定义序列号,默认值:1
#运行结果
#解释:链码审核的过程本身也是一次交易
#2022-06-19 19:08:44.426 CST [chaincodeCmd] ClientWait -> INFO 001 txid [5a9ae2ad8e9dcc9d03201df1cad3dd11664eb2ec3eb041b19b98fcb78ba6148c] committed with status (VALID) at localhost:7051
#如果已经安装上basic链码demo,再装这个fabcar的话,记得修改链码ID为“fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276 ”。反正注意--package-id 后面跟的内容要替换成自己安装成功之后日志显示中出现的hash~
#peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name fabcar --version 1.0 --package-id fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276 --sequence 1
/
ORG1查询看链码审核状态并尝试向通道提交链码
【这一步是不需要的,老师为了给我们讲需要所有组织同意之后才能提交成功,所以现在尝试提交只是为了让我们更加清楚看到现在无法提交成功。】
由于目前组织2还未通过fabcar审核,因此待会组织1提交时会失败而告终,也可以通过下面的命令来查看目前链码被审核通过的组织有哪些。
root@gan-virtual-machine:.opt/fabric-2.3# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --output json0/scripts/fabric-samples/fabcar/go#1. --channellID通道ID
#2.--name链码名称
#3. --version链码版本
#4. --output结果输出格式
#执行结果:组织1已经对链码审核且通过。组织2这边还没通过。
"approvals"
{
"Org1MSP": {
,: true"Org2MSP"
}: false
}
-
没有经过组织2审核通过的链码,我们提交试一下
peer lifecycle chaincode commit --o localhost:7050 .ordererTLSHostnameOverride orderer.example--com --tls /cafile .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert--pem --channelID mychannel --name fabcar --peerAddresses localhost:7051 /tlsRootCertFiles .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca--crt --peerAddresses localhost:9051 /tlsRootCertFiles .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca--crt .version 1--0 sequencePWD 1
后来我知道为什么了,因为我把组织2的证书位置和组织1的证书位置粘贴错了~我还看了好久,我天哪,找个错误可真不容易。
之前ORG1的配置信息都是在shell余令行临时配置,退出命令行就会消失,因此ORG2信息我们可以配置在~/.bashrc文件中,,此文件当前用户每次启动命令行时都会自动加载。
其实组织2这边的 *** 作,出来配置信息不同之外,和组织1的命令是一样的。
通过vim ~/.bashrc进入编辑模式,并且把ORG2的信息附加到最后,保存退出,关闭命令行重启打开,如果还能够识别变量则说明配置成功。
'/opt/fabric-2.3.0/scripts/fabric-samples/test-network'=#把$(PMD}/ ../bin临时注册到环境变量中, peer命令可以执行
PWD
export PATH=${}/../$PATHbin:#还需要设置FABRIc_CF6_PATH路径指向fabric-samples中的core.yaml文件路径
PWD
export FABRIC_CFG_PATH=${}/../#下载是配置组织的证书和相关信息config/
# http://cw.hubwiz.com/card/c/fabric-env-manual/1/3/12/
#启用对服务端的TLS身份验证(TLS 由 ssL发展而来)是一种身份验证机制
#组织1的NSP的标识ID
export CORE_PEER_TLS_ENABLED=true
"Org2MSP"
export CORE_PEER_LOCALMSPID=#获取组织节点证书的位置
PWD
export CORE_PEER_TLS_ROOTCERT_FILE=${}/.organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/caPWDcrt
export CORE_PEER_MSPCONFIGPATH=${}/.organizations/peerOrganizations/org2.example.com/users/Admin@org2.example#同一机构中其他Peer节点要连接此节点需指定的P2P连接地址com/msp
#下面是方便复制粘贴到终端命令行直接执行的版本
export CORE_PEER_ADDRESS=localhost:9051
PWD
'/opt/fabric-2.3.0/scripts/fabric-samples/test-network'=PWD
export PATH=${}/../$PATHbin:PWD
export FABRIC_CFG_PATH=${}/../"Org2MSP"config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID=PWD
export CORE_PEER_TLS_ROOTCERT_FILE=${}/.organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/caPWDcrt
export CORE_PEER_MSPCONFIGPATH=${}/.organizations/peerOrganizations/org2.example.com/users/Admin@org2.example#进入........fabcar/go,发现有了一个fabcar.tar.gz文件,表明链码已经打包好了com/msp
export CORE_PEER_ADDRESS=localhost:9051
(8)ORG2安装链码
/
root@gan-virtual-machine:.opt/fabric-2.3# ls0/scripts/fabric-samples/fabcar/go.
fabcar.go fabcar.tar.gz go.mod go.sum runfabcar#安装链码,结果中链码名字及其hash值与组织1安装之后的结果一样。sh vendor
/
root@gan-virtual-machine:.opt/fabric-2.3# peer lifecycle chaincode install fabcar.tar.gz0/scripts/fabric-samples/fabcar/go#运行结果
/
#2022-06-19 21:07:18.548 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:
#2022-06-19 21:07:18.548 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b
(9)链码的审核
一旦链码包在peer节点上安装后,就可以让背书节点审批链码定义,只有通过所有的背书节点或者绝大部分背书节点不同的背书策缩对通过的数量有要求审核通过后后球的链码才可以进行实例化与调用,由于链码申核配置的是排序节点的的相关信息,因此此代码与ORG1完全相同。
root@gan-virtual-machine:.opt/fabric-2.3# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name fabcar --version 1.0 --package-id fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b,Label: fabcar_1 --sequence 10/scripts/fabric-samples/fabcar/go#运行结果
#查看链码审核状态
#2022-06-19 21:09:43.517 CST [chaincodeCmd] ClientWait -> INFO 001 txid [39a98e0f41600cb2dce82fc05b70e50ea3aa28025c2d134860d725864865eacb] committed with status (VALID) at localhost:9051
(10)查看链码审核状态并提交链码
ORG2查看链码审核状态并提交链码。这时候ORG1,ORG2已经同时通过审核,这次链码可以最终提交
/
root@gan-virtual-machine:.opt/fabric-2.3# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --output json0/scripts/fabric-samples/fabcar/go#运行结果
"approvals"
{
"Org1MSP": {
,: true"Org2MSP"
}: true
}
-
最终把链码提交给组织节点
代码与ORG1相同,只是之前ORG2未通过审核,导致链码第一次提交失败。
peer lifecycle chaincode commit --o localhost:7050 .ordererTLSHostnameOverride orderer.example--com --tls /cafile .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert--pem --channelID mychannel --name fabcar --peerAddresses localhost:7051 /tlsRootCertFiles .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca--crt --peerAddresses localhost:9051 /tlsRootCertFiles .opt/fabric-2.3test-network0/scripts/fabric-samples//.organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca--crt .version 1--0 sequence#返回的结果如下,如图可以看出链码已经提交成功,由于已经同时通过了ORG1,ORG2的审核,因此链码可以提交给排序节点 1
#这样子是没起来的,要这些容器的状态都变成Up才行~
# 2022-06-19 21:57:01.524 CST [chaincodeCmd] ClientWait -> INFO 001 txid [26be9ccdddf6de2c5994406ac2411a5e478112d6f8d005a17be293939be11c89] committed with status (VALID) at localhost:7051
#2022-06-19 21:57:01.527 CST [chaincodeCmd] ClientWait -> INFO 002 txid [26be9ccdddf6de2c5994406ac2411a5e478112d6f8d005a17be293939be11c89] committed with status (VALID) at localhost:9051
#可以看到后面的invoke我就执行不了,本质原因就是链码容器没启起来~
/
root@gan-virtual-machine:.opt/fabric-2.3test-network0/scripts/fabric-samples/# docker ps -a.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7af1a01a5b75 dev-peer0.org2.example.com-basic_1"chaincode -peer.add…"0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad-6c0d5b0755cb92ed5555bd2e8a8765a6f425d1ed5ed9a90e625e01939e2113be . 6 minutes ago Created dev-peer0.org2.example.com-basic_1.0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
dc3cc5f8e9ad dev-peer0.org1.example.com-basic_1"chaincode -peer.add…"0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad-42f57faac8360472e47cbbbf3940e81bba83439702d085878d148089a1b213ca . 6 minutes ago Created dev-peer0.org1.example.com-basic_1"/bin/bash"0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
9d7a9f992eae hyperledger/fabric-tools:latest cli 9 minutes ago Up 9 minutes "peer node start"
b474ffa6a73e hyperledger/fabric-peer:latest , 9 minutes ago Up 9 minutes 7051/tcp. 0.0.0,0:9051->9051/tcp. :::9051->9051/tcp peer0.org2.example"peer node start"com
e6a08f02b506 hyperledger/fabric-peer:latest . 9 minutes ago Up 9 minutes 0.0.0,0:7051->7051/tcp. :::7051->7051/tcp peer0.org1.example"orderer"com
8adfb840488c hyperledger/fabric-orderer:latest . 9 minutes ago Up 9 minutes 0.0.0,0:7050->7050/tcp, :::7050->7050/tcp. 0.0.0,0:7053->7053/tcp. :::7053->7053/tcp orderer.example#采用invoke,调用链码的InitLedger方法初始化数据com
链码的增删改查
前提:上一章节提交成功的步骤还在,或者自己重新安装上一章节的内容再搞一遍~配置环境变量和组织认证信息、打包链码、组织节点审核链码、所有组织节点通过审核后提交链码,这时候链码就背书成功啦。
接下来我们尝试增删改查等方法的调用:
(11)初始化
-
peer chaincode invoke .o orderer.example--com:7050 --tls true $cafilecafile - -C mychannel --n fabcar .peerAddresses peer0.org1.example--com:7051 $org1_CertFilestlsRootCertFiles -- .peerAddresses peer0.org2.example--com:9051 $org2_CertFilestlsRootCertFiles - '{"Args":["InitLedger"]}'c #参数解释
#-o 排序服务器节点
#--cafile排序节点的PEM证书文件路径
#-C通道名称
#-n链码名称
#-peerAddresses锚节点的地址
#--tlsRootCertFiles前面peerAddresses的TLS证书路径
#-c链码的方法和调用方法的参数
#备注,其中
$cafile
/ = .opt/fabric-2.2test-network5/scripts/fabric-samples//.organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert$org1_CertFilespem
/=.opt/fabric-2.2test-network5/scripts/fabric-samples//.organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca$org2_CertFilescrt
/=.opt/fabric-2.2test-network5/scripts/fabric-samples//.organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca#搜到一个解决方案,试一下不知道能不能成功crt
报错了~我感觉我每个字母都核对了一遍,应该没问题啊!可为什么报错呢
查了一下,通道是存在的呀
这个解决方案不行,没有解决问题~
(
docker stop $psdocker - )aqrm
docker ( $psdocker - )aq-
docker rmi (f $|docker image"dev-"grep | '{print }'awk )docker ps -a
然后重新执行一下
【问题编号:202206202151】我用“Created
” 查询到的容器状态是Up
。后来我朋友建议我用2.2.5的版本,让链码容器#采用query调用链码中的QueryCar方法查询单部汽车了,但我还是不知道是什么原因导致的~
(12)查询
-
peer chaincode query -C mychannel -n fabcar '{"Args":["QueryCar","CAR0"]}'c #果然,上一步初始化没有成功是查询不了的,但如果上一步成功是可以查询的
#采用invoke调用链码的CreateCar新增一辆汽车
(13)新增
-
peer chaincode invoke .o orderer.example--com:7050 --tls true $cafilecafile - -C mychannel --n fabcar .peerAddresses peer0O.org1.example--com:7051 $org1_CertFilestlsRootCertFiles -- .peerAddresses peer0.org2.example-com:9051-$org2_CertFilestlsRootCertFiles - '{"Args":["CreateCar","CAR10","GEELY","Borui","Blue","Yujialing"]}'c #采用query调用链码中的QueryCar方法查询新增的汽车
(14)查询新增
-
peer chaincode query -C mychannel -n fabcar " Args"c '{[:"QueryCar", "CAR10" ]}#采用invoke调用链码的ChangeCarOwner 更新汽车所有者
(15)修改
-
peer chaincode invoke .o orderer.example--com:7050 --tls true $cafilecafile - -C mychannel
--n fabcar .peerAddresses
peer0.org1.example--com:7051 $org1_CertFilestlsRootCertFiles -- .peerAddresses peer0.org2.example--com:9051 $org2_CertFilestlsRootCertFiles - "Args"c '{[:"ChangeCarOwner","CAR10","小岳岳"]}package
6.2 编写自己的链码
#编写链码,存为atcc
import main
( "encoding/json"
"fmt"
"log"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
//SmartContract provides functions for managing an Asset
type
struct SmartContract . {
contractapi}Contract
type
struct Asset string {
ID `json: "ID"` string
Owner `json : "owner"` int
Value `json : "Value"`}
func
( *s )SmartContractInitLedger (.ctx contractapi)TransactionContextInterfaceerror := {
assets [ ]:Asset{
{ID"asset1" ,: Owner"ZhangSan" ,: Value300 },:
{ID"asset2" ,:Owner"Lisi" ,: Value400 },:
{ID"asset3" ,:Owner"Klay" ,: Value500 },}
for
_ ,:= asset range , assets {
assetjSON:= err . jsonMarshal()assetif
!= err nil return {
} err
=
err . ctxGetStub().PutState(.asset,ID)assetjSONif
!= err nil return {
. fmtErrorf("failed to put to world state. %v" , ) err}
}
return
nil }
func
(*s )SmartContractReadAsset (.ctx contractapi,TransactionContextInterfacestring id )( *,Asseterror ),{
assetJSON:= err . ctxGetStub().GetState()idif
!= err nil return {
nil ,. fmtErrorf("failed to read from world state: %v", ) err}
if
== assetJSON nil return {
nil ,. fmtErrorf("the asset %s does not exist" ,) id}
var
= asset Asset
err . jsonUnmarshal (,assetJSON& )assetif
!= err nil return {
nil ,} err
return
& ,assetnil }
func
(*s )SmartContractGetAllAssets (.ctx contractapi)TransactionContextInterface( []*,Asseterror )// range query with empty string for startKey and endKey does an{
// open-ended query of all assets in the chaincode namespace
,
resultsIterator:=err . ctxGetStub().GetStateByRange("","" )if
!= err nil return {
nil ,}err
defer
. resultsIteratorClose()var
[ assets ]*forAsset
. resultsIteratorHasNext(), {
queryResponse:= err . resultsIteratorNext()if
!= err nil return {
nil ,} err
var
= asset Asset
err . jsonUnmarshal(.queryResponse,Value& )assetif
!= err nil return {
nil ,} err
=
assets append (,assets& )asset}
return
, assetsnil }
func
main (), {
assetChaincode:= err . contractapiNewChaincode(&}SmartContract{)if
!= err nil . {
logPanicf("Error creating asset-transfer-basic chaincode: %v", ) err}
if
:= err . assetChaincodeStart();!= err nil . {
logPanicf ("Error starting asset-transfer-basic chaincode:%v", ) err}
}
//在配置了组织1信息的终端上执行:
这一部分是我用2.2.5版本成功测了一下fabcar之后再接着学的,所以我是基于之前部署了basic、fabcar两个链码demo的基础上直接运行的。所以就省掉了更改hosts文件和组织信息环境配置的步骤。
//创建链码文件存放目录atcc,并新建atcc.go,写入上述的go语言链码代码段
//我选择在chaincode目录下创建的,这个创建在哪里没关系,自己喜欢就好~【在配置了组织1信息的终端上执行或者配置了组织1信息的终端上执行都可以】
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples-chaincode# mkdir atcc
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples-chaincode# cd atcc
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode.atcc# vim atccgo//获取链码依赖
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincodegoatcc# . mod init atccgo//go: creating new go.mod: module atcc.go
//go: to add module requirements and sums:
// go mod tidy 这里它提示我要用go mod tidy,如果执行之后是正常发现了可拉取的依赖包的话,没有这个提醒可以不用执行这句命令
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincodegoatcc# //go: finding module for package github.com/hyperledger/fabric-contract-api-go/contractapi mod tidy
//go: found github.com/hyperledger/fabric-contract-api-go/contractapi in github.com/hyperledger/fabric-contract-api-go v1.1.1
//拉取依赖并下载到vendor目录下存储
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincodegoatcc# - mod vendor
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode//atcc.go go.mod go.sum vendor 这时候可以看到,依赖下载成功啦atcc# ls
//通过组织1打包链码
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincodepackageatcc# peer lifecycle chaincode . atcc.tar--gz /path /opt-fabric2.2.5//scripts-fabric/samples/chaincode--atcc -label atcc_1
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode//atcc.go atcc.tar.gz go.mod go.sum vendor 可以看到打包完成后,目录下增加了atcc.tar.gz文件atcc# ls
//然后我们将链码包atcc.tar.gz安装到组织1节点上,下面所示:安装成功后,返回status 200且会输出链码包标识ID——“atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48”
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode.atcc# peer lifecycle chaincode install atcc.tar//然后组织1节点要审核链码,通过审核后会输出交易ID——“txid [117c564ffca5a75299a84a613a4c33380c6ed1e6744f2ca85f20efa9823252fd]”gz
//2022-06-21 19:38:06.193 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:6atcc_1" >
//2022-06-21 19:38:06.193 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode-atcc# peer lifecycle chaincode approveformyorg :o localhost7050-- .ordererTLSHostnameOverride orderer.example--com --tls /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert--pem --channelID mychannel --name atcc 1.0version -- package-:id atcc_1--a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 1sequence //可以通过命令查看当前链码的审核状态,因为只有所有组织节点都审核通过之后,才能提交链码。但这个时候只有Org1MSP通过了审核,组织2还没有通过审核
//2022-06-21 19:39:19.540 CST [chaincodeCmd] ClientWait -> INFO 001 txid [117c564ffca5a75299a84a613a4c33380c6ed1e6744f2ca85f20efa9823252fd] committed with status (VALID) at localhost:7051
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode--atcc# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name atcc 1.0version -- 1sequence -- "approvals"output json
{
:"Org1MSP" {
:true ,"Org2MSP"
:false }
}
//也可以通过命令查看当前节点上安装的链码
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode//Installed chaincodes on peer:atcc# peer lifecycle chaincode queryinstalled
//Package ID: basic_1.0:3cfcf67978d6b3f7c5e0375660c995b21db19c4330946079afc3925ad7306881, Label: basic_1.0
//Package ID: fabcar_1:1146b4b491871bf18b23dd67dd8cc058655b36cc0e2274f165ed06b796a8f276, Label: fabcar_1
//Package ID: atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48, Label: atcc_1
//在配置了组织2信息的终端上执行:
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode.atcc# ls
atccgo. atcc.targogz .gomod .//同之前一样,将链码包atcc.tar.gz安装到组织2节点上,安装成功后也会返回status 200且会输出链码包标识ID——“atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48”sum vendor
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode.atcc# peer lifecycle chaincode install atcc.tar//然后组织2节点也要审核链码,通过审核后也会输出交易ID——“txid [117c564ffca5a75299a84a613a4c33380c6ed1e6744f2ca85f20efa9823252fd]”gz
6atcc_1" >//2022-06-21 19:41:36.634 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:
//2022-06-21 19:41:36.634 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode-atcc# peer lifecycle chaincode approveformyorg :o localhost7050-- .ordererTLSHostnameOverride orderer.example--com --tls /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert--pem --channelID mychannel --name atcc 1.0version -- package-:id atcc_1--a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 1sequence //可以通过命令查看当前链码的审核状态,这时候组织1和组织2都审核通过啦,可以提交链码了
//2022-06-21 19:41:53.240 CST [chaincodeCmd] ClientWait -> INFO 001 txid [50999fd3617bd19d9dc26d9826abdfac3a468628872550574cdd5887184250c8] committed with status (VALID) at localhost:9051
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode--atcc# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name atcc 1.0version -- 1sequence -- "approvals"output json
{
:"Org1MSP" {
:true ,"Org2MSP"
:true }
}
//通过组织2提交链码【通过组织1提交也是可以的,提交一次就行啦~都是同步的。】
//提交成功后会输出两条日志信息,说明提交的交易来自两个节点【真实情况下是多个,有多少个节点审核并通过了链码,这里就会有多少条日志信息,且都是对应于同一条交易ID】
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode-atcc# peer lifecycle chaincode commit :o localhost7050-- .ordererTLSHostnameOverride orderer.example--com --tls /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert--pem --channelID mychannel --name atcc :peerAddresses localhost7051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org1.example/com/peers.peer0.org1.example/com/tls.ca--crt :peerAddresses localhost9051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org2.example/com/peers.peer0.org2.example/com/tls.ca--crt 1.0version -- 1sequence //提交成功输出上面的日志之后,可以用docker ps -a 命令看到docker容器中又多了三个节点对应的atcc链码容器,且均处于Up状态。这时候可以进行链码调用啦~
//2022-06-21 19:49:24.598 CST [chaincodeCmd] ClientWait -> INFO 001 txid [b01da77332d3b3525f03a854b5ba4a442010626491a70637aeffd65b622738e0] committed with status (VALID) at localhost:9051
//2022-06-21 19:49:24.624 CST [chaincodeCmd] ClientWait -> INFO 002 txid [b01da77332d3b3525f03a854b5ba4a442010626491a70637aeffd65b622738e0] committed with status (VALID) at localhost:7051
//首先进行链码初始化,如果成功会返回status200,否则会提示错误原因
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode-atcc# peer chaincode invoke .o orderer.example:com7050-- truetls -- /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert-pem -C mychannel --n atcc .peerAddresses peer0.org1.example:com7051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org1.example/com/peers.peer0.org1.example/com/tls.ca--crt .peerAddresses peer0.org2.example:com9051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org2.example/com/peers.peer0.org2.example/com/tls.ca-crt "Args"c '{:["InitLedger"]}//初始化成功之后可以采用query调用链码中的ReadAsset方法查询某条asset记录。-c后面接的是链码中的方法及其所需要的参数,这些方法是自己定义的,如InitLedger、ReadAsset、GetAllAssets,自己编写这个链码中只有这三个方法~'
//2022-06-21 19:55:41.739 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode-atcc# peer chaincode query -C mychannel -n atcc "Args"c '{:["ReadAsset","asset1"]}//{"ID":"asset1","Owner":"ZhangSan","Value":300}'
//也可以采用query调用链码的GetAllAssets查询所有asset记录
-
root@gan-virtual:machine//opt-fabric2.2.5//scripts-fabric/samples/chaincode-atcc# peer chaincode query -C mychannel -n atcc "Args"c '{
:["GetAllAssets"]}//[{"ID":"asset1","Owner":"ZhangSan","Value":300},{"ID":"asset2","Owner":"Lisi","Value":400},{"ID":"asset3","Owner":"Klay","Value":500}]'
//补充第14步:Java调用链码扩展: https://www.cnblogs.com/aarond/p/12173797.html 感兴趣的话可以自己下去看~
//组织1执行
下面是纯命令,没有终端目录提示,更方便复制粘贴~
=
PWD/'/opt-fabric2.2.5//scripts-fabric/samples-test=network'
export PATH}${PWD/../:bin=$PATH
export FABRIC_CFG_PATH}${PWD/..//config=
export CORE_PEER_TLS_ENABLEDtrue=
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:localhost7051package
peer lifecycle chaincode . atcc.tar--gz /path /opt-fabric2.2.5//scripts-fabric/samples/chaincode--atcc .label atcc_1
peer lifecycle chaincode install atcc.tar-gz
peer lifecycle chaincode approveformyorg :o localhost7050-- .ordererTLSHostnameOverride orderer.example--com --tls /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert--pem --channelID mychannel --name atcc 1.0version -- package-:id atcc_1--a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 1sequence --
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name atcc 1.0version -- 1sequence -- //组织2执行output json
=
PWD/'/opt-fabric2.2.5//scripts-fabric/samples-test=network'
export PATH}${PWD/../:bin=$PATH
export FABRIC_CFG_PATH}${PWD/..//config=
export CORE_PEER_TLS_ENABLEDtrue=
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:localhost9051.
peer lifecycle chaincode install atcc.tar-gz
peer lifecycle chaincode approveformyorg :o localhost7050-- .ordererTLSHostnameOverride orderer.example--com --tls /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert--pem --channelID mychannel --name atcc 1.0version -- package-:id atcc_1--a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 1sequence -
peer lifecycle chaincode commit :o localhost7050-- .ordererTLSHostnameOverride orderer.example--com --tls /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert--pem --channelID mychannel --name atcc :peerAddresses localhost7051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org1.example/com/peers.peer0.org1.example/com/tls.ca--crt :peerAddresses localhost9051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org2.example/com/peers.peer0.org2.example/com/tls.ca--crt 1.0version -- 1sequence -
peer chaincode invoke .o orderer.example:com7050-- truetls -- /cafile /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/ordererOrganizations.example/com/orderers.orderer.example/com/msp/tlscacerts.tlsca.example-com.cert-pem -C mychannel --n atcc .peerAddresses peer0.org1.example:com7051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org1.example/com/peers.peer0.org1.example/com/tls.ca--crt .peerAddresses peer0.org2.example:com9051-- /tlsRootCertFiles /opt-fabric2.2.5//scripts-fabric/samples-test/network/organizations/peerOrganizations.org2.example/com/peers.peer0.org2.example/com/tls.ca-crt "Args"c '{:["InitLedger"]}-'
peer chaincode query -C mychannel -n atcc "Args"c '{:["ReadAsset","asset1"]}-'
peer chaincode query -C mychannel -n atcc "Args"c '{
:["GetAllAssets"]}'
补充一个小问题~可以不管
两个打包的链码文件是不同的,这个不重要~跳过就行
fabcar_.tar.gz是fabcar目录下打包的,上一章节弄的,不能实现增删改查
学习小结
虽然这个课程内容还是很基础的,还需要深入学习的东西还有很多很多。但是,通过这个课程了解了shell、go的简单语法,这对之后读代码是有帮助的。另外通过实际案例回顾了区块链相关知识,这对理解区块链以及之后可能需要区块链的地方是有用的。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)