"HyperLedger Fabric 2.3 Alliance Chain Construction" course study notes

Course Platform: 51CTO
Course Lecturer: Datouwa
Course Introduction: The construction of the alliance chain and the operation of the chain code are explained from scratch. Let everyone truly master the construction of the alliance chain and the chain code deployment and invocation process.

1. Introduction to Hyperledger Fabric Alliance Chain

1.1 Usage scenarios

The data of the blockchain is public, but in some industries such as banking, medical care. These private data cannot be fully disclosed, or a permission mechanism can be established for selective disclosure. By default, all nodes in the blockchain need to maintain the ledger and review the progress of transactions with other members, which is inefficient and expensive. Hyperledger is different, using super nodes to complete the accounting function.

1.2 Generate background

公有链缺点:
1.数据完全公开
2.所有节点参与运算成本大
3.不支持私下机密交易

According to the above shortcomings, the design of Hyperledger focuses on industrial applications, solves the existing shortcomings, and expands the original functions of the industry.
Hyperledger revolutionizes the traditional blockchain model, which includes managing the access permissions of participants. In other words: Hyperledger is a permissioned shared ledger. Hyperledger provides a safe and healthy model for identification, auditing, i.e. privacy .Therefore shorten the operation cycle. Achieve effective expansion. Cope with various requirements in the industry.

一个覆盖众多网络的世界
我们希望能够出现众多的区块链网络,使得每个网络账本都能执行不同的业务,基于这一期望值,而出现了Hyperledger,现在单一普遍的通用网络已经出现.
但是网络与网络之间的通信还尚未有实例.会员就是在个个网络中的通,Hyperledger,除了能够实现这种网络独立运行之外.
还有寻址系统.能够通过一个账本的交易.发现并利用另一个本中正当的交易与智能合约

insert image description here

1.3 Advantages and disadvantages of alliance chain

Advantages :
(1) Strong controllability
Compared with the public chain, because the nodes are generally massive, once a blockchain is formed, the block data cannot be tampered with, for example, there are too many Bitcoin nodes, and you want to tamper with the block Data is almost impossible; in the consortium chain, as long as the majority of all institutions in the consortium reach a consensus, the block data can be changed.
(2) Semi-centralized
consortium chain is only owned by members within the consortium to a certain extent. Because the number of nodes is limited, it is easy to reach a consensus.
(3) Fast transaction speed
In essence, the alliance chain is still a private chain, but because of its limited number of nodes, it is easy to reach a consensus, so the transaction speed is also very fast.
(4) The data will not be disclosed by default
Unlike the public chain, the data of the alliance chain is limited to the internal organization of the alliance and its users have permission to access.
Disadvantages :
(1) Due to the semi-centralized structure of the alliance chain, it is easily attacked by malicious players. It is possible for multiple participants to collude.
(2) Due to the lack of industry unified standards, there will inevitably be various obstacles in the solution, but at present the entire ecology is still far from the unified framework of the alliance chain.
(3) For large comprehensive enterprises, due to their poor flexibility in application scenarios. In order to start a new alliance, it must be approved by the agreement of all members. However, large enterprises have many processes and complicated constraints, so it is very slow to establish such a general network among many large enterprises.

1.4 The basic structure of the alliance chain

insert image description here
The Fabric system is divided by organizations. Each organization contains Peer nodes with different functions, and each Peer node can play multiple roles. All organizations share a unified Orderer cluster.

1.Endorser Peer(背书结点)︰每个链码在实例化的时候都会设置背书策略(Endorsement policy),指定哪些节点对交易背书才有效。
2.Leader Peer (主节点)∶主节点负责和Orderer排序服务节点通信,从排序服务节点处获取最新的区块并在组织内部同步。
3.Committer Peer(记账节点)︰负责验证从排序服务节点接收的区块里的交易,然后将块提交(写入/追加)到其通道账本的副本。
4.Anchor Peer(锚节点)︰在一个通道( channel )上可以被所有其他peer发现的peer5.Order Peer(排序节点)︰排序服务节点接收包含背书签名的交易,对未打包的交易进行排序生成区块,广播给Peer主节点。

1.5 Basic requirements

(1) Demand for network authority The
issuing authority determines the appropriate access authority according to the purpose of the network, and this authority requires identification before conducting transactions on the network. The web operates publicly and is easily integrated into mobile applications. It can run privately, and only through permission verification can you become familiar with its situation. And you can set different levels of permissions according to your needs.
(2) The importance of privacy and confidentiality
We believe that any blockchain architecture has a basic requirement, that is, the identity and behavior patterns of any party on the network do not allow unauthorized persons to inquire about the situation through the ledger. We also want to be able to guarantee the confidentiality of blockchain users' business logic and other transaction parameters. Make sure that no one other than the stakeholders involved in the contract can access the data.

1.6 Introduction to Hyperledger Terminology

chainCode-chaincode
is actually a smart contract in the public chain. Chaincode is a software running on the ledger, which can encode assets, and the transaction instructions (or business logic) in it can also be used to modify assets.
Channel-Channel
Channels are built on a private blockchain on the Fabric network. The isolation and confidentiality of data is realized. The ledger specified by the channel is shared with all peer nodes in the channel, and the transaction party must pass the correct verification of the channel to interact with the ledger. The channel is defined by a "configuration block" .
Gengsis Block - Genesis Block
Genesis Block is a configuration block that initializes the blockchain network or channel. It is also the first block on the blockchain.
Fabric-ca certificate
Fabric-ca is the default certificate management component, which reports to the network Members and their users issue PKl-based certificates.
Client (App)
The client application uses the SDK to deal with the Fabric network. First, the client obtains a valid identity certificate from the CA to join the application channel in the network. Hyperledger Fabric already has SDKs in multiple languages. These SDKs encapsulate the calls to the underlying gRPC interface and can provide more complete client and development support, including multiple implementations such as Node.Js, Python, Java, and Go.
Invoke - call
is used to call the function in chainCode. ChainCode invoke is a transaction, Proposal, and then executes the modular process (endorsement, consensus, verification, submission). The structure of invoke is a function and an array of parameters.
Ledger -ledger
Ledger is a chain of channels, and a database maintained by each peer in the channel.

2. Basic grammar of Go language

The teacher said that you can also refer to the rookie tutorial .
Chapter 2 02 Introduction to the Go Code System

//定义了包名,此文件属于哪个包,每个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)
}

Question 1: If there is an error " go: cannot find GOROOT directory: c: \go
", you need to configure the GOROOT root directory. It needs to be restarted after configuration.
Chapter 2 03 Arrays, loops
Chapter 2 04 Functions
Chapter 2 05 Pointers
Chapter 2 06 Structures
Chapter 2 07 Interfaces, new use
Chapter 2 08 Custom packages

go language summary

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(1020)
	fmt.Println("a: ", a, "a type:", reflect.Typeof(a), " b:", b)
	fno4(123)
}

func fno1()(intint) {
    
    
	return 23
}

//定义号返回的变量(理解为函数局部变量)
func fn02()(sum int) {
    
    
	//var sum int
	//已经声明不需要重复声明
	sum = 100
	return
}


//支持返回指针类型
func fno3(×, y int)(*intint){
    
    
	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)
}


operation result:
insert image description here

3. Quick Start to Shell

Search in the rookie tutorial : shell tutorial, follow the tutorial to learn a little bit

3.1 The first shell script

Linux common directory structure:

/bin目录存放可执行的文件, root和一般账号都可用
/boot这个目录存放开机使用的文件,例如: linux内核和系统启动文件.. ldev存放所有设备文件.包括硬盘、分区、鼠标、键盘、USB等
/etc存放系统所有配置文件,
/home:用户主目录的,当你创建一个用户时,默认的用户文件夹就在该目录下
/mnt*如果需要挂载某些设备,一般建议存放到此目录中
/root: root用户的目录
/usr:注意usr并不是user的缩写,而是Unix Software Resource的缩写,"“Unix操作系统软件资源"放在该目录,而不是用户的数据

first script file

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 !

File permission analysis
insert image description here

insert image description here

3.2 Variables and parameter passing

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线 _。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。

The vi demo01.shscript file can be edited with the following contents:

#!/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 $0"
echo"第二参数为:$1"
echo "总共传递 $# 个参数"

#执行结果说明,双引号内支持变量和转义符,而单引号不支持

insert image description here

3.3 Arrays, for loops

Multiple values ​​can be stored in an array. Bash Shell only supports one-dimensional arrays (multi-dimensional arrays are not supported), and the array size does not need to be defined during initialization (similar to PHP).
Similar to most programming languages, the subscripts of array elements start at 0.
Shell arrays are represented by brackets, and elements are separated by "space" symbols. The syntax format is: array_name=(value1 value2 … valuen)

#!/bin/bash
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}"
done

if [ $1 == $2 ]
then
  echo "a==b"
else
  echo "a!=b"
fi

insert image description here

3.4 Function file contains

(1) Function

#!/bin/bash

funWithReturn(){
    
    
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    #注意,加法外面是两层小括号
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

insert image description here
(2) File Inclusion
Like other languages, Shell can also include external scripts. This makes it easy to encapsulate some common code as a separate file.

Shell 文件包含的语法格式如下:

. filename   # 注意点号(.)和文件名中间有一空格
或
source filename

Note: Included files do not need to have execute permission

#文件fn.sh,这个即为被包含文件,不用为其赋予执行权限
#!/bin/bash
funcDemo(){
    
    
  echo "参数1为:$1"
  echo "参数2为:$2"
  echo "请输入一个数值:"
  read num
  return $(($1 +$2 + ${
    
    num}))
}


#文件callfn.sh
!/bin/bash
#引入同目录的sh文件
source ./fn.sh
funcDemo 1 2
echo "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$ ./callfn.sh 
参数1为:1
参数2为:2
请输入一个数值:
3
result: 6

3.5 case

var='yes'
case $var in
"yes")
	echo 'your choose is yes'
	;;
"no")	
	echo'your choose is no'
	;;
*)
	echo 'your choose is error'
	;;
esac
#短路模式
[ -d $1 ] && rm -r $1
#动态获取当前参数数量
echo $#
#吧所有参数左移动1位
shift 1
echo $#

insert image description here
insert image description here

Fourth, fabric installation

4.1 Ubuntu installation

VMWare版本:VMware® Workstation 16 Pro 16.2.3 build-19376536
Ubuntu版本:Ubuntu 22.04 LTS【好像是发行版,我就是想装最新的,哈哈哈。大头娃老师用的是20.04版本】

Of course, you have to install VMWare first, and then create a new virtual machine=="Follow the prompts and install it step by step. The 22.04 version of Ubuntu looks good, and VMtools is installed by itself.
Download and install Baidu by yourself~

4.2 Ubuntu Basic Commands and Configurations

1. Change the download source

Click the nine dots in the lower left corner to enter the search interface -> enter "software" in the search box -> click the "Software & Updates" that appears, enter the interface for changing the download source -> click the box corresponding to download -> find Alibaba Cloud Source (Teacher Said this is relatively stable)->choose server->enter password authentication->close->reload.

insert image description here
insert image description here
insert image description here
After it is loaded, you can run the command to check whether the download source has been replaced successfully:

cat /etc/apt/sources.list

insert image description here

2. Basic Linux commands

创建文件 touch 文件名.文件后缀
删除文件 rm 文件名.文件后缀
创建目录 mkdir 目录名
删除目录 rmdir 目录名
删除带文件的目录 rm -r 目录名/
移动文件 mv 文件当前绝对路径  想要移动到的目录的绝对路径
		mv /home/hong/abc.txt  ../    #将abc.txt移动到上一级目录
移动文件并重命名 mv 当前文件名 目标文件名
root@ubuntu:/home# ls
abc.txt hong
root@ubuntu:/home# mv abc.txt aaa.txt
root@ubuntu:/home# ls
aaa.txt hong

#解压zip、tar压缩文件
root@ubuntu:/home/hong/Desktop# ls
fabric-2.1.1.zip fabric-2.3.0.tar.gz
root@ubuntu:/home/hong/Desktop# tar xzf fabric-2.3.0.tar.gz -C .
root@ubuntu:/home/hong/Desktop# tar xzf fabric-2.3.0.tar.gz -C ../
root@ubuntu: /home/ hong/Desktop# cd ..
root@ubuntu:/ home/hong# ls
Desktop Downloads fabric-2.3.0 Pictures  emplates Documents examples.desktop Music Public Videos
root@ubuntu :/home/hong#rm -r fabric-2.3.0/
root@ubuntu:/home/ hong# ls
Desktop Downloads Music Public Videos Documents examples.desktop Pictures Templates
root@ubuntu :/home/hong# cd Desktop/
root@ubuntu :/home/hong/Desktop# ls
fabric-2.1.1.zip fabric-2.3.0 fabric-2.3.0.tar.gz

root@ubuntu: /home/hong/Desktop# unzip fabric-2.1.1.zip -d .
#这种-d方式会覆盖原来有的文件,如果这个目录下有重名文件,解压出来直接覆盖
root@ubuntu: / home/ hong/Desktop# ls
fabric-2.1.1 fabric-2.1.1.zip fabric-2.3.0 fabric-2.3.0.tar.gz

4.3 Docker introduction and installation

1. A brief introduction to docker

Fabric is not directly on Linux, it is built based on Docker containers.
Docker warehouse : There are many components and environments in this warehouse, and the components of the fabric we will use are on it.
There is a brief introduction in the rookie tutorial: Docker is an open source application container engine, based on the Go language and open sourced in compliance with the Apache2.0 protocol. Docker allows developers to package their applications and dependencies into a lightweight, portable container , which can then be distributed to any popular Linux machine, and can also be virtualized. The container completely uses the sandbox mechanism, and there will not be any interface between each other (similar to the iPhone app), and more importantly, the performance overhead of the container is extremely low.
insert image description here
We can perform arbitrary testing and debugging on the sandbox inside the whale without affecting other contents of the ocean. After the debugging is completed, we can transplant the whole copy of the whale sandbox to different operating systems without reconfiguring the test. Docker containers are the equivalent of whales.
The configuration of different super nodes of the alliance chain is actually the same, so it can be done with the help of the docker container. The test is completed in the docker first, and the other nodes can be copied and transplanted~

The difference between docker and VM:
VM
insert image description here
introduces docker
insert image description here

综上:
docker是软件层面的虚拟化,比较轻量级,用于软件环境的复制移植和测试。
VM是操作系统层面的虚拟化,比较笨重,用于操作系统层面的测试。

2. docker installation

(1) Install docker and view the docker version

sudo apt install docker.io

Available dockercommands to view, docker installation success will have sub-command introduction.
insert image description here
View docker version

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.0
  GitCommit:        

(2) Docker configuration
A, image pull and delete demonstration - take hello-world as an example

#拉取hello-world镜像,这样子是默认拉取最新版,如果想选特定版本就在后面加上版本号即可
sudo docker pull hello-world
#用docker images命令可以看到,我们拉取镜像成功啦,执行结果如下
sudo docker images
#REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
#hello-world   latest    feb5d9fea6a5   8 months ago   13.3kB
#删除镜像  后面跟的是镜像ID,因为同一个名字的镜像有不同版本,你可以装多个版本,所以会有多个同名的镜像,只有镜像ID才能唯一标识镜像
sudo docker rmi feb5d9fea6a5
#Untagged: hello-world:latest
#Untagged: hello-world@sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651
#Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
#Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
#再次查看,发现镜像删除成功啦
sudo docker images
#REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

B. Configure docker accelerator

Enter " https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors" on the webpage, scan with Alipay or Taobao to open Alibaba Cloud, and confirm the login. Then there is the accelerator website, as well as the accelerator configuration guide.
insert image description here

gan@gan-virtual-machine:~$ cd /etc/docker
gan@gan-virtual-machine:/etc/docker$ ls
key.json
#发现etc/docker目录下没有daemon.json这个文件,所以我们需要新建一个

It's okay, we follow the Ubuntu installation command as prompted by the Alibaba Cloud interface, and directly copy and paste that paragraph into the Ubuntu command terminal.

gan@gan-virtual-machine:/etc/docker$ sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
    
    
  "registry-mirrors": ["https://m6juudzz.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
[sudo] password for gan: 
{
    
    
  "registry-mirrors": ["https://m6juudzz.mirror.aliyuncs.com"]
}
gan@gan-virtual-machine:/etc/docker$ ls
daemon.json  key.json
gan@gan-virtual-machine:/etc/docker$ cat daemon.json 
{
    
    
  "registry-mirrors": ["https://m6juudzz.mirror.aliyuncs.com"]
}

After configuring the accelerator, you need to restart docker, and then we pull the image again to test whether the accelerator is configured successfully

#先查看docker当前状态:active (running)  运行中
gan@gan-virtual-machine:/etc/docker$ service docker status
#关闭docker
gan@gan-virtual-machine:/etc/docker$ service docker stop
#再次查看docker当前状态:inactive (dead) 关闭
gan@gan-virtual-machine:/etc/docker$ service docker status
#此时再重新启动
gan@gan-virtual-machine:/etc/docker$ service docker start
#再次查看docker状态就又变成运行中啦


#然后重新拉取hello-world镜像,如果成功,说明加速器配置应该没问题
gan@gan-virtual-machine:/etc/docker$ sudo docker pull hello-world
#Using default tag: latest
#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

4.4 Common commands of docker

1:查看版本: docker version
2:查看系统信息: docker info显示 Docker系统信息,包括镜像和容器数。
3: docker images //显示镜像列表
4: docker run hello-world(图文讲解)
//1∶客户端首先要连接Docker服务器。2:从Docker服务器中pull镜像。3:从lmage中创建容器,一个镜像可以创建多个容器。4: Docker守护进程将输出流式传输到Docker客户端,后者将其发送到您的终端。
5: docker rmi hello-world ===> docker images
6: docker pull nginx:1.18.0 //通过官网下载指定版本
7: docker run [-d] nginx //后台运行镜像
8: docker ps //l查看已运行镜像列表-a列表所有的容器,-f过滤,-q只列表容器的id。
9: docker run -d -p 8080:80 nginx //启动时候配置端口映射
10: docker stop containerID //只要能识别ID一位数也行-r尽量先删除容器在删除镜像2.1 docker rmi nginx:1.18.0 #删除已下载的镜像rm是删除容器(镜像运行的称为容器)
11:启动、关闭服务service docker status|start|stop

(1) Image and container
insert image description here

#拉取镜像
root@gan-virtual-machine:~# docker pull hello-world
#运行容器
root@gan-virtual-machine:~# docker run hello-world
#查看当前正在运行的容器,发现没有,因为hello-world就是下图中所示,打印几个步骤出来,执行完成后自动关闭容器。
root@gan-virtual-machine:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

insert image description here

#删除docker镜像失败
root@gan-virtual-machine:~# docker rmi feb
Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is being used by stopped container 2d9ba30d106c

#查看所有镜像,包括未处于运行状态的容器
root@gan-virtual-machine:~# docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED          STATUS                      PORTS     NAMES
2d9ba30d106c   hello-world   "/hello"   37 minutes ago   Exited (0) 37 minutes ago             condescending_tu
#想要删除镜像需要先删除其对应的容器,和删除类之前要删掉对应的对象一个道理。
#删除容器2d9ba30d106c。后面接的容器ID,只要能够区分就行,不用写完整的ID,如果第一位就能区分,打一个字母也是可以的
root@gan-virtual-machine:~# docker rm 2d9
#查看容器
root@gan-virtual-machine:~# docker ps -a
#CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
#容器已经删掉了,此时删除镜像
root@gan-virtual-machine:~# docker rmi feb
#查看镜像,确保删除成功
root@gan-virtual-machine:~# docker images

insert image description here

(2) Nginx deployment
You can view the version in the docker warehouse
insert image description here
insert image description here

#找到1.19.6版本【因为老师用的这个版本啦~】,复制镜像拉取命令
#不加版本号的话,会默认拉取最新的版本,其实装最新版也是可以哒~
docker pull nginx:1.19.6

insert image description here
You can localhost:端口号access Nginx, which is actually similar to Tomcat's server interface.
insert image description here

But mine is like this: [Xiaobai's collapse was at a moment different from the teacher]
insert image description here

insert image description here
insert image description here

(3) Small episode
Because I couldn't access the Nginx page, I searched for the problem and found that I still couldn't access it, so I looked back, only this step was different from the teacher. Switch admin
with command I have no success, v_v. Then I Baidu,su
insert image description here

insert image description here

ubuntu初始root密码
安装完Ubuntu后可能没有设置root密码,不知道密码自然就无法进入根用户下。
到网上搜了一下,原来是这么回事:
Ubuntu的默认root密码是随机的,即每次开机都有一个新的root密码。
解决方法:
我们可以在终端输入命令“sudo passwd”,然后输入当前用户的密码后"Enter"。
终端会提示我们输入新的密码并确认,此时的密码就是root新密码。
修改成功后,输入命令 su root,再输入新的密码就ok了。

Anyway, it was finally found that it was not because of the administrator's problem. Restart the docker client and restart the container~
insert image description here

4.5 Fabric component download

1. Condensed version: Fabric component download and pull command

Switch to administrator first, and then run the following command~

//在GitHub下载fabric2.3.0的tar.gz文件后,拖到Ubuntu中,并且解压到/opt目录下,进入解压后的目录
root@ubuntu:/home/hong/Desktop# tar xzf fabric-2.3.0.tar.gz -C /opt
root@ubuntu:/opt/fabric-2.3.0/scripts# apt install curl
//如果有报错“E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)”的话,可以不用移除/var/lib/dpkg/lock这个目录,然后重新安装apt install curl,如果没有报错,跳过下面这条语句
root@ubuntu:/opt/fabric-2.3.0/scripts# rm /var/lib/dpkg/lock
//安装,拉取下载组件,获得bin、config、test-等目录
root@ubuntu:/opt/fabric-2.3.0/scripts# ./bootstrap.sh 
//安装docker-compose
root@ubuntu/opt/fabric-2.3.0/scripts# :apt install docker-compose
//启动Fabric服务
root@ubuntu:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh up
//可以看下,现在在运行的docker容器
root@ubuntu:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# docker ps -a
//然后试一下终止网络命令——>本质就是销毁之前启动的docker容器的过程
root@ubuntu:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh down
//组件下载这部分就完成啦

insert image description here
insert image description here
insert image description here

Add a little trick
to turn off the automatic lock screen, so that when downloading resources, the screen will not be locked due to being out of the Ubuntu interface for a long time, which will cause the download to be suspended.
This is the 20.04 version of Ubuntu, which needs to be turned off.
insert image description here

The new version I installed does not seem to have this option. If there is, the location of the settings may have changed.
insert image description here

2. Screenshot of the download component process [screenshot record of the teacher's steps, you can skip it without watching]

The teacher said that in the next lesson, we will talk about the download of the fabric source code package
insert image description here
insert image description here
insert image description here
insert image description here
. After installation, start the network and try:
insert image description here

Found missing docker dependency on this component. Docker-compose is actually a docker command-line tool. Before multiple docker images need to call each other and depend on each other, docker-compose is required to complete it. Just install it~
insert image description here
After installation, you can find that there are no samples at the beginning and
insert image description here
after the operation is completed,
insert image description here
insert image description here
then start the network and see:
insert image description here

3. The problem of ca component download failure

Problem 1 CA component download failed: "------> 1.4.9 fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----
" I don't care, I thought it would have no effect. It will prompt when I start the network later. I thought about it and I should come back and check it, or it is better to complete it.

===> Downloading version 1.4.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 % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:21 --:--:--     0
curl: (7) Failed to connect to github.com port 443 after 21048 ms: Connection refused

gzip: stdin: unexpected end of file
tar: Child returned status 1
tar: Error is not recoverable: exiting now
==> There was an error downloading the binary file.

------> 1.4.9 fabric-ca-client binary is not available to download  (Available from 1.1.0-rc1) <----

Then I downloaded it on the host, and copied the downloaded tar.gz file into it. After decompressing it, I found that it was the two files in the bin.
insert image description here
After two days, I added it. When I reinstalled, I found that it can complete the download when the network is good. yes~
insert image description here

**Question 2 The docker image was not pulled successfully: **When the service is started later, there will be a prompt "Local fabric binaries and docker images are out of sync. This may cause problems."
insert image description here

When installing for the first time, because the download of the CA component failed, it stopped at the place where the download of the CA component failed and exited, so the docker image was not pulled.
insert image description here
When it was installed for the second time later, everything went well, and it had a docker image~
insert image description here

4.6 Process analysis of fabric download components

1. Fabric source code download

Resource link
Open the GitHub website above, then pull down and pay attention to the right part “Releases 45 v2.4.3 Latest”, click Releasesto enter the new interface, click Tags, you can see different versions, we find 2.3.0, select tar.gz. Then the download is successful!
insert image description here
insert image description here
insert image description here

After downloading the source code, I want to copy it to Ubuntu. I can't drag it directly. Although I installed VMtools, I just can't drag the source code file into it. Then, I copy it in with a U disk, hahaha, I really Clever~
[Issue ID 202206181158] I ran into a strange problem: I can copy a single file from the host to ubuntu, but not zip files and folders to Ubuntu. The error is as follows:
insert image description here

2. Component installation analysis

The teacher manually built the fabric service according to the catalog. He said: "In fact, if the network is not very good, you can download the required installation package, and then manually build the fabric service." He wanted to give us a clearer picture of the important components and their structure by doing this manually.

//目录结构
fabric-2.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.sh【控制网络启动、关闭的文件】
							

insert image description here

Five, source code analysis

5.1 Bootstrap source code analysis

#!/bin/bash
#
# 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.0
# if ca version not passed in, default to latest released version
#很多时候fabric有最新版,但是组件没有对应更新位相应版本,这个ca版本是1.4.9
CA_VERSION=1.4.9
ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')")
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=$1
    #所有参数向前移动一位,相当与FABRIC_TAG删掉啦,移动之后,第一个参数$1就变成了数组的第一个元素啦
    shift
    #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
    #切割版本号,把最后一位切掉
    two_digit_image_tag=$(echo "$three_digit_image_tag" | cut -d'.' -f1,2)
    #“$#”是动态获取当前参数数量,gt是“>”符号,即当前参数数量大于0
    while [[ $# -gt 0 ]]
    do
    	#获取第一个要拉取的镜像名称
        image_name="$1"
        #“$three_digit_image_tag”即版本号
        echo "====> hyperledger/fabric-$image_name:$three_digit_image_tag"
        #拉取镜像,通过镜像名称和版本号拉取
        docker pull "hyperledger/fabric-$image_name:$three_digit_image_tag"
        docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name"
        docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name:$two_digit_image_tag"
        #所有参数向前移动一位,下载完一个就往左移动一个,即当前$1变成第二个要获取的镜像名字啦
        shift
    #直到当前参数个数为0,即拉取下载完所有镜像之后,推出循环,函数执行结束
    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 ]; then #first-network在1.4好像就改了,把这个目录改成fabric-samples了,所以这条语句不重要
        # if we are in the fabric-samples repo, checkout corresponding version
        echo "==> Already in fabric-samples repo"
    elif [ -d fabric-samples ]; then #这个语句,如果fabric-samples目录存在,说明已经有东西啦,不用下载,直接进目录就行。所以这个条件下的操作为:打印“Changing directory to fabric-samples”并进入fabric-samples
        # if fabric-samples repo already cloned and in current directory,
        # cd fabric-samples
        echo "===> Changing directory to fabric-samples"
        cd fabric-samples
    else  #这时候,说明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.git && cd fabric-samples
         #这里值得多说一点,&& 与运算,两个都为真才执行,其实隐含了前一个命令执行成功才会执行后一个命令。所以在Linux里面,&&可以连接任何命令,不一定是条件表达式。这就是“短路操作”。与或非运算都有短路操作。
    	#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>&1; then
        echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
        git checkout -q v${
    
    VERSION}
    else
        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=$1
    local URL=$2
    echo "===> Downloading: " "${URL}"
    #设置重连的次数(5),每次重连延迟3秒
    #文件下载成功之后,直接调用tar解压操作
    #rc=$?表示获取函数执行的结果,即解压是否成功的结果
    curl -L --retry 5 --retry-delay 3 "${URL}" | tar xz || rc=$?
    #补充
    #|运算符:管道符号,是unix—个很强大的功能,符号为一条竖线:"|"。用法:command 1 | command 2,他的功能是把第一个命令command 1执行的结果作为command2的输入传给command 2。
    if [ -n "$rc" ]; then #rc不为空,说明解压出现问题。返回22,并打印“There was an error downloading the binary file”
        echo "==> There was an error downloading the binary file."
        return 22
    else #如果解压成功,打印"==> Done."
        echo "==> Done."
    fi
}

pullBinaries() {
    
    #通过两个下载,实现bin和config目录的生成
	#打印,并且通过传入两个参数(文件名和GitHub下载地址)调用download函数。
    echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries"
    download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}"
    if [ $? -eq 22 ]; 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 <----"
        echo
        exit
    fi
	#同理,下载fabric-ca。打印,并且通过传入两个参数(文件名和GitHub下载地址)调用download函数。
    echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary"
    download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}"
    if [ $? -eq 22 ]; then 
        echo
        echo "------> ${CA_TAG} fabric-ca-client binary is not available to download  (Available from 1.1.0-rc1) <----"
        echo
        exit
    fi
}

pullDockerImages() {
    
    
	#command命令:无条件调用系统提供的函数。这个是为了确保即使用户自己定义了一个叫docker的函数,执行当前函数时调用的也是系统提供的docker函数。
    command -v docker >& /dev/null
    #用于接收上一条命令的执行结果,如果为0,则说明系统docker函数存在
    NODOCKER=$?
    if [ "${NODOCKER}" == 0 ]; then
    	#系统docker存在,则创建一个数组,数组里面存储待下载镜像名称
        FABRIC_IMAGES=(peer orderer ccenv tools)
        case "$VERSION" in
        #如果当前是fabric2.x版本,则组件添加baseos
        2.*)
            FABRIC_IMAGES+=(baseos)
            shift
            ;;
        esac
        echo "FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}"
        echo "===> Pulling fabric Images"
        #调用函数dockerPull ,且传入两个参数:第一个参数是下载Fabric版本FABRIC_TAG,第二个是数组FABRIC_IMAGES的所有元素
        dockerPull "${FABRIC_TAG}" "${FABRIC_IMAGES[@]}"
        echo "===> Pulling fabric ca Image"
        #创建数组,其中只有一个元素:ca
        CA_IMAGE=(ca)
        #调用函数dockerPull ,且传入两个参数:第一个参数是下载ca版本CA_TAG,第二个是数组CA_IMAGE的所有元素
        dockerPull "${CA_TAG}" "${CA_IMAGE[@]}"
        echo "===> List out hyperledger docker images"
        #如果下载成功,则用docker images查看镜像。grep是正则表达式,也就是在所以docker images中选择和hyperledger相关的镜像打印输出。
        docker images | grep hyperledger
    else
        echo "========================================================="
        echo "Docker not installed, bypassing download of Fabric images"
        echo "========================================================="
    fi
}

#从这里开始~首先定义了三个变量,将它们都赋值为true
DOCKER=true
SAMPLES=true
BINARIES=true

# Parse commandline args pull out
# version and/or ca-version strings first
if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then
    VERSION=$1;shift  #一会儿下载时,读取输入的第一个参数,如果其不为“-”,则赋值给VERSION;否则前面采用默认的VERSION=2.3.0。一般是不会执行这几句的,但是加上的话逻辑更完整。
    if [ -n "$1" ]  && [ "${1:0:1}" != "-" ]; then
        CA_VERSION=$1;shift  #同理,,读取输入的第一个参数,如果不为“-”,则赋值给CA_VERSION;否则前面的采用CA_VERSION=1.4.9
        if [ -n  "$1" ] && [ "${1:0:1}" != "-" ]; then
            THIRDPARTY_IMAGE_VERSION=$1;shift #同理,读取第一个参数,如果版本号不为“-”,则赋值给THIRDPARTY_IMAGE_VERSION
        fi
    fi
fi

# prior to 1.2.0 architecture was determined by uname -m
#拼接要下载的文件下载链接,此处代码不重要
#后面打印输出的时候要用“=> 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”
if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then
    export FABRIC_TAG=${
    
    MARCH}-${
    
    VERSION}
    export CA_TAG=${
    
    MARCH}-${
    
    CA_VERSION}
    export THIRDPARTY_TAG=${
    
    MARCH}-${
    
    THIRDPARTY_IMAGE_VERSION}
else
    # 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.gz

#这部分才是核心逻辑,指明了其实boostrap.sh总共就完成了三件事情
#如果SAMPLES变量为True,则调用cloneSamplesRepo,下载hyperledger/fabric-samples
#如果BINARIES变量为True,则调用pullBinaries,拉取Hyperledger Fabric binaries
#如果DOCKER变量为True,则调用pullDockerImages,拉取Hyperledger Fabric docker images
# then parse opts
while getopts "h?dsb" opt; do
    case "$opt" in
        h|\?)
            printHelp
            exit 0
            ;;
        d)  DOCKER=false
            ;;
        s)  SAMPLES=false
            ;;
        b)  BINARIES=false
            ;;
    esac
done

if [ "$SAMPLES" == "true" ]; then
    echo
    echo "Clone hyperledger/fabric-samples repo"
    echo
    cloneSamplesRepo
fi
if [ "$BINARIES" == "true" ]; then
    echo
    echo "Pull Hyperledger Fabric binaries"
    echo
    pullBinaries
fi
if [ "$DOCKER" == "true" ]; then
    echo
    echo "Pull Hyperledger Fabric docker images"
    echo
    pullDockerImages
fi

5.2 Introduction to concepts of channel, organization and certificate

1. Chain code

In fabric, a smart contract is called chaincode, and it has 6 states:

. install (代码上链)
. instantate(初始化)
. invocable (调用链码)
. upgrade(由于合约有多个副本,因此每个合约都有版本号,版本升级时就是upgrade)
. Deinstantiate (合约销毁)
. Uninstall(卸载链码)

2. Channel

channel: A private sub-network, in fact, to isolate different applications, a channel can contain a batch of chaincodes.
Only organizations (companies) in the same channel can share the same block data and perform related chaincode operations.

3. Certificates and Encryption

The previously deployed CA module is to distribute public and private keys to nodes, and encryption and signatures can be achieved with the public and private keys.
Asymmetric encryption: Messages encrypted by public key can only be decrypted by private key; similarly, messages signed by private key can only be verified by public key.

数字证书:联盟链采用的非对称加密技术来事项身份验证和数据加密,本质就是SSl技术
CA(Certificate Authority):提供数字证书包括公钥(服务使用者)和私钥(服务者)
还提供一个CRL:证书吊销列表

for example:
insert image description here

Xiao Ming's mailbox number is 11A, and Xiaohong's mailbox number is 11B. These are known to everyone, similar to 11A, 11B are called public keys. If Xiaoming wants to send a letter to Xiaohong, he only needs to put the written letter into Xiaohong's mailbox. Letters protected by mailboxes are like encrypted messages. Only Xiaohong can open it with her key. And Xiaohong's key is her private key.
(1) This is the public key, everyone has a pair of keys, one is public and the other is secret
(2) A wants to send information to B, it encrypts the information with B's public key and sends it to B
(3) B gets Encrypted information, decrypt the encrypted information with your own key, and get the plaintext information

4. Consortium chain architecture

fabric联盟链的开发人员主要分为三类:
底层是系统运维,负责系统的部署与维护;
其次是组织管理人员,负责证书、MSP权限管理、共识机制等;
最后是业务开发人员,他们负责编写chaincode、创建维护channel、执行transaction交易等

insert image description here

5. Fabric execution process

The fabric process was mentioned in the previous "1.4 Basic Architecture of Alliance Chain", here is a brief introduction to node consensus and interaction. This part of the content comes from the short book: In-depth analysis of fabric consensus mode

The Endorse+Kafka+Commit mode adopted by the fabric consensus mode includes the following steps:

(1)请求背书:客户端用自己的私钥对交易进行签名后,按照指定格式将交易和签名信息进行打包,然后将打包后的数据发给背书节点请求背书。

(2)验证背书:背书节点收到背书请求后,验证交易的签名是否正确并调用智能合约验证交易内容是否合法。验证通过的话,背书节点用自己的私钥对背书结果进行签名并按照指定格式打包,然后将打包后的数据发给客户端。

(3)提交交易:客户端收到背书结果后,验证背书结果的签名是否正确。验证通过后,对交易请求和背书结果签名并打包。然后,把打包后的数据发送给orderer节点提交交易。

(4)排序广播:orderer节点收到交易后,验证数据的客户端签名[bJ1] 是否正确。验证通过后,将交易发给kafka集群对应的topic。由于orderer中的对于每个通道都在kafka上监听对应的消息,因此,kafka将消息存放到对应topic上之后,会将消息广播给通道上的所有orderer。因为各个orderer的消息都是由kafka按照相同顺序发送的,因此,这个过程也实现了消息的排序。

(5)打包出块:orderer节点接收到从kafka推送的消息(kafka节点见同步消息不需要验证),当满足出块策略[bJ2] :缓存交易个数达到区块最大交易数或者时间达到出快时间,则将交易进行打包、对数据签名,然后出块,并将区块分发给peer节点。

(6)验证记账:peer节点接收到区块后,验证交易是否有效即验证区块的交易是否满足背书策略以及区块中交易的读写集版本是否正确[bJ3] 。验证通过的话,执行此交易的内容更改状态数据库。验证失败的话,对此条交易不做任何处理。当区块中的交易全部处理完成后,将区块记录在本地数据库。

Communication interaction flow chart:
insert image description here

Data flow flow chart:
insert image description here

5.3 test-network startup analysis

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.3.0/scripts/fabric-samples/test-network# ./network.sh up
#fabric采用了leveldb数据库,key-value形式,且支持海量存储。用于存储交易状态
Starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb' with crypto from '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.3.0/scripts/fabric-samples/test-network/../bin/cryptogen
#用上述那个文件的工具创建证书
Generating certificates using cryptogen tool
#创建组织1,其配置文件为./organizations/cryptogen/crypto-config-org1.yaml,可采用yaml验证工具验证,发现其实是json格式的内容。
#在这个配置文件中,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
+ res=0
Generating CCP files for Org1 and Org2
WARNING: The COMPOSE_PROJECT_NAME variable is not set. Defaulting to a blank string.
Creating network "docker_test" with the default driver
Creating volume "docker_orderer.example.com" with default driver
Creating volume "docker_peer0.org1.example.com" with default driver
Creating volume "docker_peer0.org2.example.com" with default driver
Creating peer0.org2.example.com ... done
Creating peer0.org1.example.com ... done
Creating orderer.example.com    ... done
Creating cli                    ... done
CONTAINER ID   IMAGE                               COMMAND             CREATED         STATUS                  PORTS                                                                                  NAMES
ddde72be9f06   hyperledger/fabric-tools:latest     "/bin/bash"         1 second ago    Up Less than a second                                                                                          cli
af8a3cbd19a4   hyperledger/fabric-orderer:latest   "orderer"           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.com
27cb1ca1c1b2   hyperledger/fabric-peer:latest      "peer node start"   2 seconds ago   Up Less than a second   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp                                              peer0.org1.example.com
6fcc31ed3930   hyperledger/fabric-peer:latest      "peer node start"   2 seconds ago   Up 1 second             0.0.0.0:9051->9051/tcp, :::9051->9051/tcp                                              peer0.org2.example.com


Supplement --- yaml file verification tool: You can view certificate information http://www.bejson.com/validators/yaml_editor
insert image description here
through . The teacher changed the in to , re- network, you will find that there are two more users in organization 1“vim connection-org1.yaml”
insert image description here
connection-org1.yamlCount=1Count=3./network.sh up
insert image description here

5.4 Channel Creation and Chaincode Deployment

创建通道
	创建区块信息
	组织	加入通道
部署链码
	部署deploycc
	查看各种版本链码
	部署go版本链码
	apt、wget、curl对比
	Linux程序存储结构介绍
	wget下载的配置Go
	配置GOProxy代理

1. Create a channel

//通过别名定义命令,这是“临时性”的,下一次打开Ubuntu就需要重新定义了
root@gan-virtual-machine:~#  alias ss='cd /opt/fabric-2.3.0/scripts/fabric-samples/test-network/'
root@gan-virtual-machine:~#  ss
//进入目录,启动网络
root@gan-virtual-machine :/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh up
//创建通道,可以后接-C指定通道别名,不指定通道名字的话,默认通道名为“mychannel”
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh createChannel
//创建通道时在终端显示的日志信息:主要包括两大部分内容——**创建区块信息和****组织加入通道**

2. Deploy the chaincode

(1) Chaincode deployment command parsing

./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
1.-ccn 代表要部署目录简称
2.-ccp代表部署的路径
3.-ccl代表链码语言版本

(2) View various version chain codes
insert image description here

(3) Deploy the go version chaincode

./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) Comparison of apt, wget and 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) Introduction to Linux program storage structure

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./usr/local/src:用户级的源码目录

(6) Install go
Because we want to run the go version of the demo, we need to install the go language environment.
method 1

#可以用apt,但是不推荐。因为如果部署新版本fabric的时候,很有可能阿里云源这边没有更新对应的go语言高版本
#但其实我试了一下,因为今年已经2022年啦~所以apt安装的已经是1.18版本了,够用于fabric2.3.0的了。但是我还是用了老师说的另一种方法
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# apt install golang-go
#如果go版本太低,部署链码会报错“go: unknown subcommand "mod"
#要卸载掉低版本的go,apt方式安装之后的卸载命令
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# apt remove golang-go

Method 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.gz
#解压文件到/usr/local中
tar xfz go1.15.4.linux-amd64.tar.gz -C /usr/local
#修改~/.bashrc
vim ~/.bashrc
#配置GOROOT,添加Gopath路径。如果不配GOROOT的话之后运行go version时会提示warning warning: GOPATH set to GOROOT (/usr/local/go) has no effectgo version go1.13.4 linux / amd64

export GOROOT=/usr/local/go
export GOPATH=/home/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH


#激活配置bachrc相当于当前用户环境变量配置  root@gan-virtual-machine:~# source ~/.bashrc  注意所在目录
source ~/.bashrc
go version #验证go是否安装成功,go version go1.18.3 linux/amd64

(7) Configure the GOProxy proxy
When the specified version of GO has been downloaded above, and the GOPATH and GOROOT environment variables are configured, you can download the chaincode-related dependency packages from github according to the search process, but the last exception is still thrown. , it can be seen from the abnormal information that the access to github.com has timed out. At this time, an agent needs to be configured to download the resources of Github.

#可以直接利用命令添加
go env -w GOPROXY=https://goproxy.cn/
#也可以像之前配置GOROOT那样去/.barshrc文件中添加
export GOPROXY=https://goproxy.cn/

(8) Redeploy the go version chaincode

root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

5.5 Supplementary Instructions

1. Introduction to the Fabric Consortium Chain Ecosystem

The goal of the Fabric project is to realize the underlying basic framework of a general permissioned blockchain (Permissioned Chain). In order to be suitable for different occasions, a modular architecture is used to provide switchable and scalable components, including consensus algorithms, encryption security, digital Services such as assets, smart contracts, and identification.
insert image description here

1.Fabric CALIPER:性能测试组件
2.Fabric Explorer:查看区块链信息组件
3. Fabric Composer:包含了开发构架,和工具的开源项目
4.Fabric Cello:支持定制(例如,大小,一致〉区块链请求、在裸机,虚拟云(例如,虚拟机,云数据云),容器集群方便部署自己联盟链

2. Review of important orders

  1. cryptogen: Generate organizational structure and identity files (certificates)
  2. configtxgen: Generate configuration blocks and configuration transactions
  3. configtxlator: read configuration information
    insert image description here
    insert image description here

3. Supplement: Create a channel prompt log

The log information displayed on the terminal when the channel is created: mainly includes three major parts - creating block information and , organizing the joining channel and synchronizing node information .

另外补充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.3.0/scripts/fabric-samples/test-network# ./network.sh createChannel Creating channel 'mychannel'.

If network is not up, starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb'
#创建了一个区块mychannel.block,存储目录为“./channel-artifacts/mychannel.block ”
Generating channel genesis block 'mychannel.block'
/opt/fabric-2.3.0/scripts/fabric-samples/test-network/../bin/configtxgen
#以“+”开头的语句是fabric命令,可以到Fabric命令手册网址去看对应命令的含义
+ configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/mychannel.block -channelID mychannel
2022-06-19 10:44:45.834 CST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2022-06-19 10:44:45.844 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: etcdraft
2022-06-19 10:44:45.844 CST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 Orderer.EtcdRaft.Options unset, setting to tick_interval:"500ms" election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216 
2022-06-19 10:44:45.845 CST [common.tools.configtxgen.localconfig] Load -> INFO 004 Loaded configuration: /opt/fabric-2.3.0/scripts/fabric-samples/test-network/configtx/configtx.yaml
2022-06-19 10:44:45.847 CST [common.tools.configtxgen] doOutputBlock -> INFO 005 Generating genesis block
2022-06-19 10:44:45.847 CST [common.tools.configtxgen] doOutputBlock -> INFO 006 Creating application channel genesis block
2022-06-19 10:44:45.848 CST [common.tools.configtxgen] doOutputBlock -> INFO 007 Writing genesis block
+ res=0
Creating channel mychannel
#区块创建完成之后,就调用组织,将组织1和组织2添加到通道中去。联盟链中,不通的通道是隔离开的,不通的组织必须在同一个通道里面才能相互访问并执行通道中的链码。
#下面是其加入的一些信息,包括组织的基本信息、验证、状态等。
Using organization 1
+ osnadmin channel join --channel-id mychannel --config-block ./channel-artifacts/mychannel.block -o localhost:7053 --ca-file /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 --client-cert /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt --client-key /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
+ res=0
#20开头的状态表示成功
Status: 201
{
    
    
	"name": "mychannel",
	"url": "/participation/v1/channels/mychannel",
	"consensusRelation": "consenter",
	"status": "active",
	"height": 1
}

Channel 'mychannel' created
#将组织1加入通道
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.033 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-06-19 10:44:52.071 CST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
#将组织2加入通道
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.142 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-06-19 10:44:55.180 CST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
#添加锚节点到通道,通过锚节点可以实现节点同步
Setting anchor peer for org1...
Using organization 1
Fetching channel config for channel mychannel
Using organization 1
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2022-06-19 02:44:55.425 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:55.429 UTC [cli.common] readBlock -> INFO 002 Received block: 0
2022-06-19 02:44:55.430 UTC [channelCmd] fetch -> INFO 003 Retrieving last config block: 0
2022-06-19 02:44:55.433 UTC [cli.common] 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
+ jq '.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"}}' Org1MSPconfig.json
Generating anchor peer update transaction for 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.758 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:55.781 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
Anchor peer set for org 'Org1MSP' on channel 'mychannel'

Setting anchor peer for org2...
Using organization 2
Fetching channel config for channel mychannel
Using organization 2
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2022-06-19 02:44:56.166 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:56.172 UTC [cli.common] readBlock -> INFO 002 Received block: 1
2022-06-19 02:44:56.173 UTC [channelCmd] fetch -> INFO 003 Retrieving last config block: 1
2022-06-19 02:44:56.175 UTC [cli.common] 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
+ jq '.data.data[0].payload.data.config'
Generating anchor peer update transaction for Org2 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' Org2MSPconfig.json
#configtxlator命令用来将fabric的数据结构在protobuf和JSON 之间进行转换,也可以用来创建配置更新。该命令可以启动一个REST 服务来通过HTTP暴露服务接口,也可以直接在命令行使用。
+ 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.504 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-06-19 02:44:56.531 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
Anchor peer set for org 'Org2MSP' on channel 'mychannel'
#提示:通道'mychannel'创建成功
Channel 'mychannel' joined

4. Supplement: Deploy chaincode prompt log

The log information displayed on the terminal when deploying the chain code: mainly includes downloading the chain code , decompressing the chain code , deploying and installing the chain code to the channel , submitting the chain code to the endorsement node , and submitting it to the ordering node only after the endorsement is successful .

root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
deploying chaincode on channel 'mychannel'
executing with the following
- CHANNEL_NAME: mychannel
- CC_NAME: basic
- CC_SRC_PATH: ../asset-transfer-basic/chaincode-go
- CC_SRC_LANGUAGE: go
- CC_VERSION: 1.0
- CC_SEQUENCE: 1
- CC_END_POLICY: NA
- CC_COLL_CONFIG: NA
- CC_INIT_FCN: NA
- DELAY: 3
- MAX_RETRY: 5
- VERBOSE: false
Vendoring Go dependencies at ../asset-transfer-basic/chaincode-go
/opt/fabric-2.3.0/scripts/fabric-samples/asset-transfer-basic/chaincode-go /opt/fabric-2.3.0/scripts/fabric-samples/test-network
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.3.0/scripts/fabric-samples/test-network
#链码下载已完成
Finished vendoring Go dependencies
#打包链码并生成打包文件
+ peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-go --lang golang --label basic_1.0
+ res=0
Chaincode is packaged
#给组织1,2安装链码
Installing chaincode on peer0.org1...
Using organization 1
#在指定peer节点上安装链码
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2022-06-19 13:57:09.511 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad\022\tbasic_1.0" > 
2022-06-19 13:57:09.511 CST [cli.lifecycle.chaincode] 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.197 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad\022\tbasic_1.0" > 
2022-06-19 13:57:24.197 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
Chaincode is installed on peer0.org2


Using organization 1
#查询指定peer节点上已经安装的链码
+ peer lifecycle chaincode queryinstalled
+ res=0
Installed chaincodes on peer:
Package ID: basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad, Label: basic_1.0
Query installed successful on peer0.org1 on channel
Using organization 1
#机构审批链码,即提交链码到背书节点,背书机构进行审批。其中“--tls --cafile”参数后面跟着证书,指明审批机构要具有相应资质,即指明证书文件。
+ 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 basic --version 1.0 --package-id basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad --sequence 1
+ res=0
2022-06-19 13:57:26.409 CST [chaincodeCmd] ClientWait -> INFO 001 txid [790e1b59b00f895df8b49474d836a5636ddfe1138aff24923b5509869bd8eb26] committed with status (VALID) at localhost:7051
#提示:链码在组织1节点1审批通过
Chaincode definition approved on peer0.org1 on channel 'mychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
#检查指定的链码是否可以向通道提交。
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
    
    
	"approvals": {
    
    
		"Org1MSP": true,#表示链码审批在组织1通过
		"Org2MSP": false#表示链码审批在组织2还没通过
	}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
#检查指定的链码是否可以向通道提交。
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
    
    
	"approvals": {
    
    #这时候组织2还没执行审批操作,所以和签名的结果一样,组织1通过链码审批,而组织2还没有
		"Org1MSP": true,
		"Org2MSP": false
	}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'mychannel'
Using organization 2
#向组织2提交链码的审核操作,和向组织1提交的步骤是类似的
+ 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 basic --version 1.0 --package-id basic_1.0:4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad --sequence 1
+ res=0
2022-06-19 13:57:34.732 CST [chaincodeCmd] ClientWait -> INFO 001 txid [a3959f8b65cdf8dff719c9e5c12a0a713d116ddb4f4d5f56d295af2b62478fb2] committed with status (VALID) at localhost:9051
#链码在组织2审批通过
Chaincode definition approved on peer0.org2 on channel 'mychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
#这时候再检查一下指定的链码是否可以向通道提交。
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
    
    
	"approvals": {
    
    #这时候组织1和组织2都通过了链码审批
		"Org1MSP": true,
		"Org2MSP": true
	}
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
#同样,在组织2也再检查一下指定的链码是否可以向通道提交。
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
    
    
	"approvals": {
    
    #结果也是:组织1和组织2都通过了链码审批
		"Org1MSP": true,
		"Org2MSP": true
	}
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'mychannel'

#在上面,组织1和2都完成了对链码的审批操作并且通过之后

Using organization 1
Using organization 2
# 向指定通道提交链码,提交给order(排序节点)
+ peer lifecycle chaincode commit -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 basic --peerAddresses localhost:7051 --tlsRootCertFiles /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /opt/fabric-2.3.0/scripts/fabric-samples/test-network/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.304 CST [chaincodeCmd] ClientWait -> INFO 001 txid [8f5eafd1b019ffc861a890af9944f5ce74b6ac13795301f5d531a610fdc21c13] committed with status (VALID) at localhost:9051
2022-06-19 13:57:43.330 CST [chaincodeCmd] ClientWait -> INFO 002 txid [8f5eafd1b019ffc861a890af9944f5ce74b6ac13795301f5d531a610fdc21c13] committed with status (VALID) at localhost:7051
#这时候提示,提交到排序节点的操作已经成功啦
Chaincode definition committed on channel 'mychannel'



Using organization 1
Querying chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to Query committed status on peer0.org1, Retry after 3 seconds.
#在组织1这边查询指定通道上已经提交的链码
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
#查询结果是,链码已经在组织1上定义成功
Query chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Querying chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to Query committed status on peer0.org2, Retry after 3 seconds.
#同理,在组织2这边查询指定通道上已经提交的链码
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
#查询结果是,链码已经在组织2上也定义成功
Query chaincode definition successful on peer0.org2 on channel 'mychannel'
Chaincode initialization is not required

5. Manually build the peer environment

Running the peer command directly on the command line will throw an exception. The reason is that it is easy to understand that all operations need to specify which organization node is used in which channel, and these nodes must have legal permissions.
insert image description here

insert image description here
//First make sure that you are in the test-network directory, and configure the following environment variables (this time to facilitate the configuration of temporary variables)
//Configuration of temporary variables: The environment variables configured in this way are temporary, It will disappear on the next boot. This time is just for the convenience of students to understand the configuration process.

PWD='/opt/fabric-2.3.0/scripts/fabric-samples/test-network'
export PATH=${
    
    PWD}/../bin:$PATH    #这时候,在终端输入peer,已经有用法提示了,但是现在还不能正常使用,继续配置。还有配置组织、证书等相关信息配置文件
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
#启用对服务端的TLS身份验证
export CORE_PEER_LOCALMSPID="Org1MSP"
#两行指明了org1的加密所用的信息
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
 open /opt/fabric-2.3.0/scripts/fabric-samples/config/tls/ca.crt: no such file or directory

export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
#当前组织节点IP与端口
export CORE_PEER_ADDRESS=localhost:7051
#注意:这里的端口配置也要区分节点的哟——排序节点7050,第一个组织节点7051,第二个组织节点9051

#补充————fabric环境变量手册:http://cw.hubwiz.com/card/c/fabric-env-manual/1/6/1/


PWD='/opt/fabric-2.3.0/scripts/fabric-samples/test-network'
export PATH=${
    
    PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

The environment variables of the organization 1 node are configured above. Next, you can use the identity of the organization 1 node to perform peer command verification:

peer channel list
peer lifecycle chaincode queryinstalled
peer channel getinfo -c mychannel

insert image description here
insert image description here

6. fabcar official case deployment implementation

6.1 fabcar project acquisition and installation

fabcar chain code acquisition and installation contract Fabcar project structure analysis
fabcar is a decentralized chain code for car (car) transactions. The project supports single car query, addition, query addition, update addition, deletion and other operations. It realizes the functions of adding, deleting, checking and modifying the general chain code.

insert image description here
go.mod dependency analysis
insert image description here
insert image description here

(1) Get the fabcar dependency package

After the execution is completed, there will be more vendors in the current folder, which is the folder where the smart contract dependencies are placed.

#配置go代理。然后已经配置可以跳过
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# go env -w GOPROXY=https://goproxy.cn
#刚开始执行的时候,遇到报错“missing go.sum entry; to add it:”。通过执行命令:“go mod tidy”后再执行“go mod vendor”
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# go mod vendor

(2) Add host record

/etc/hosts, host name and ip configuration file, on the bureau city network or INTERNET, each host has a P address, which distinguishes each host and can deny ip for communication. But it is inconvenient to remember 100 million in her world, and all have a domain name. In a local area network, each camera has a host name, which is used to distinguish the hosts and facilitate mutual access.

#我们当前配置都是在本地的,如果以后大项目部署之后,不同的节点对应不同的ip地址,道理都是一样的,在/etc/hosts中配置其映射关系即可。
#这个项目,我们就把下面三条语句加入/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.3.0/scripts/fabric-samples/test-network# vim /etc/hosts

insert image description here

ORG1 chain code review and submission operations

(3) Configure environment variables and organization authentication information

This is point 5 in Section 5.5: Manually build the environment variables configured in the peer environment. The content is the same~

#后续很多地方会用到test-network目录,因此把它赋值到PwD变量中
PWD='/opt/fabric-2.3.0/scripts/fabric-samples/test-network'
#把${PwD}/ ../bin临时注册到环境变量中, peer命令可以执行
export PATH=${
    
    PWD}/../bin:$PATH
#还需要设置FABRIc_CF6_PATH路径指向fabric-samples中的core.yaml文件路径
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
#下载是配置组织的证书和相关信息
# http:/ / cw.hgbwiz.com/card/c/fabric-env-manual/1/3/12/
#启用对服务端的TLs身份验证(TLS 由ssL发展而来)是一种身份验证机制
export CORE_PEER_TLS_ENABLED=true
#组织1的MSP的标识ID
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
#获取访问账户的msp证书
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
#同一机构中其他Peer节点要连接此节点需指定的P2P连接地址
export CORE_PEER_ADDRESS=localhost:7051
#注意:这里的端口配置也要区分节点的哟——排序节点7050,第一个组织节点7051,第二个组织节点9051


#下面是方便复制粘贴到终端命令行直接执行的版本
PWD='/opt/fabric-2.3.0/scripts/fabric-samples/test-network'
export PATH=${
    
    PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

(4) Package chain code contract

#前提:fabric网络启动且通道创建完成  可以只使用一个命令./network.sh up createChannel
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh up
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# ./network.sh createChannel

root@ubuntu:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# 
#参数介绍:
#(1)package outputfile #打包输出文件名
#(2)path string #链码源代码路径
#(3)lang string # 链码开发语言,默认:golang
#(4)label string #链码标识,相当于链码的名字


root@ubuntu:/opt/fabric-2.3. /scripts /fabric-samples /fabcar/go# peer lifecycle chaincode package fabcar.tar.gz --path /opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go --label fabcar_1
#1s查看当前目录,发现有了一个fabcar.tar.gz文件
root@ubuntu:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# ls
#上一条语句执行结果:fabcar.go fabcar.tar.gz go.mod go.sum runfabcar.sh vendor


(5) Install the chaincode

#安装智能合约(时间会比较久,耐心稍等)
peer lifecycle chaincode install fabcar.tar.gz
#2022-06-19 18:44:00.603 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b\022\010fabcar_1" > 
#2022-06-19 18:44:00.603 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b
#这个hash值很重要,下面的步骤要用===》   fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b

insert image description here
At this time, you can query the installed chain code - organization 1 has completed the chain code installation operation (organization 2 has not yet), and a unique hash value will be generated to identify this chain code after the installation is complete. At this point, we can also use the following command to view the chaincode files that have been installed on the current node.

root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b, Label: fabcar_1
#peer lifecycle chaincode queryinstalled:如果出现两个链码名字,其中第一个basic_1.0是上一章节官方自动安装的deployCC案例,而fabcar_1是本章节手动安装的案例。我把上一章节自动安装的删掉了,所以我查询结果只有一个~

If the previously installed chaincode is not deleted basic, the query result should be as follows:
insert image description here

(6) ORG1 chain code review and submission operations

Once the chaincode package is installed on the peer node, the endorsing node can approve the chaincode definition. Only after passing all the endorsement nodes or most of the endorsement nodes (different endorsement policies have requirements for the number of passes), the subsequent approvals are passed. Chaincode can be instantiated and invoked.

root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# 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 1

#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 Query to see the chain code review status and try to submit the chain code to the channel
[This step is not necessary, the teacher needs the consent of all organizations to submit it successfully, so trying to submit now is just to make us more clearly see that it is not possible now Submitted successfully. ]
Since organization 2 has not yet passed the fabcar audit, the submission of organization 1 will fail and end later. You can also use the following command to view the organizations whose chain codes have been audited.

 root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --output json

#1. --channellID通道ID
#2.--name链码名称
#3. --version链码版本
#4. --output结果输出格式

#执行结果:组织1已经对链码审核且通过。组织2这边还没通过。
{
    
    
	"approvals": {
    
    
		"Org1MSP": true,
		"Org2MSP": false
	}
}

There is no chain code that has been approved by organization 2, let's submit it for a try

peer lifecycle chaincode commit -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 --peerAddresses localhost:7051 --tlsRootCertFiles /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1.0 --sequence 1

insert image description here
insert image description here
Later I figured out why, because I pasted the wrong certificate location for organization 2 and the certificate location for organization 1~ I've been looking at it for a long time, my god, it's not easy to find a mistake.

ORG2 chain code review and submission operations

Previously, the configuration information of ORG1 was temporarily configured in the remaining command line of the shell, and it disappeared after exiting the command line. Therefore, the ORG2 information can be configured in the ~/.bashrc file. This file will be automatically loaded every time the current user starts the command line. .
In fact, the operations on the organization 2 side are the same as the commands for organization 1 except for the different configuration information.

(7) Configure ORG2 organization information

Enter the editing mode through vim ~/.bashrc, and append the information of ORG2 to the end, save and exit, close the command line and restart it. If the variable can still be recognized, the configuration is successful.

PWD='/opt/fabric-2.3.0/scripts/fabric-samples/test-network'
#把$(PMD}/ ../bin临时注册到环境变量中, peer命令可以执行
export PATH=${
    
    PWD}/../bin:$PATH
#还需要设置FABRIc_CF6_PATH路径指向fabric-samples中的core.yaml文件路径
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
#下载是配置组织的证书和相关信息
# http://cw.hubwiz.com/card/c/fabric-env-manual/1/3/12/
#启用对服务端的TLS身份验证(TLS 由 ssL发展而来)是一种身份验证机制
export CORE_PEER_TLS_ENABLED=true
#组织1的NSP的标识ID
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 
#同一机构中其他Peer节点要连接此节点需指定的P2P连接地址
export CORE_PEER_ADDRESS=localhost:9051


#下面是方便复制粘贴到终端命令行直接执行的版本
PWD='/opt/fabric-2.3.0/scripts/fabric-samples/test-network'
export PATH=${
    
    PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

(8) ORG2 installation chain code

#进入........fabcar/go,发现有了一个fabcar.tar.gz文件,表明链码已经打包好了
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# ls
fabcar.go  fabcar.tar.gz  go.mod  go.sum  runfabcar.sh  vendor
#安装链码,结果中链码名字及其hash值与组织1安装之后的结果一样。
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# peer lifecycle chaincode install fabcar.tar.gz
#运行结果
#2022-06-19 21:07:18.548 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b\022\010fabcar_1" > 
#2022-06-19 21:07:18.548 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:4e7996bf4058869807f239b859a97dc609ed19e2fcfd10f1bf86540f6dd3cf5b

(9) Review of chain code

Once the chaincode package is installed on the peer node, the endorsing node can approve the chaincode definition. Only after passing all the endorsement nodes or most of the endorsement nodes with different endorsement policies, there is a requirement for the number of passes to pass the review. The chain code can be instantiated and invoked. Since the chain code declaration core configures the relevant information of the ordering node, this code is exactly the same as ORG1.

root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# 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 1

#运行结果
#2022-06-19 21:09:43.517 CST [chaincodeCmd] ClientWait -> INFO 001 txid [39a98e0f41600cb2dce82fc05b70e50ea3aa28025c2d134860d725864865eacb] committed with status (VALID) at localhost:9051

(10) View the chain code review status and submit the chain code

ORG2 checks the chaincode review status and submits the chaincode. At this time, ORG1 and ORG2 have passed the review at the same time, and this time the chain code can be finally submitted

#查看链码审核状态
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/fabcar/go# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --output json
#运行结果
{
    
    
	"approvals": {
    
    
		"Org1MSP": true,
		"Org2MSP": true
	}
}


The chain code is finally submitted to the organization node
. The code is the same as ORG1, but ORG2 failed to pass the review before, resulting in the failure of the first submission of the chain code.

peer lifecycle chaincode commit -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 --peerAddresses localhost:7051 --tlsRootCertFiles /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /opt/fabric-2.3.0/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1.0 --sequence 1


#返回的结果如下,如图可以看出链码已经提交成功,由于已经同时通过了ORG1,ORG2的审核,因此链码可以提交给排序节点
# 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

insert image description here

#这样子是没起来的,要这些容器的状态都变成Up才行~
#可以看到后面的invoke我就执行不了,本质原因就是链码容器没启起来~
root@gan-virtual-machine:/opt/fabric-2.3.0/scripts/fabric-samples/test-network# docker ps -a
CONTAINER ID   IMAGE                                                                                                                                                                    COMMAND                  CREATED         STATUS         PORTS                                                                                  NAMES
7af1a01a5b75   dev-peer0.org2.example.com-basic_1.0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad-6c0d5b0755cb92ed5555bd2e8a8765a6f425d1ed5ed9a90e625e01939e2113be   "chaincode -peer.add…"   6 minutes ago   Created                                                                                               dev-peer0.org2.example.com-basic_1.0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
dc3cc5f8e9ad   dev-peer0.org1.example.com-basic_1.0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad-42f57faac8360472e47cbbbf3940e81bba83439702d085878d148089a1b213ca   "chaincode -peer.add…"   6 minutes ago   Created                                                                                               dev-peer0.org1.example.com-basic_1.0-4ec191e793b27e953ff2ede5a8bcc63152cecb1e4c3f301a26e22692c61967ad
9d7a9f992eae   hyperledger/fabric-tools:latest                                                                                                                                          "/bin/bash"              9 minutes ago   Up 9 minutes                                                                                          cli
b474ffa6a73e   hyperledger/fabric-peer:latest                                                                                                                                           "peer node start"        9 minutes ago   Up 9 minutes   7051/tcp, 0.0.0.0:9051->9051/tcp, :::9051->9051/tcp                                    peer0.org2.example.com
e6a08f02b506   hyperledger/fabric-peer:latest                                                                                                                                           "peer node start"        9 minutes ago   Up 9 minutes   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp                                              peer0.org1.example.com
8adfb840488c   hyperledger/fabric-orderer:latest                                                                                                                                        "orderer"                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.com

Chain code additions, deletions, and changes

Prerequisite: The steps for the successful submission of the previous chapter are still there, or you can reinstall the content of the previous chapter and do it again ~ configure environment variables and organization certification information, package chain code, organize node audit chain code, and all organization nodes pass the audit After submitting the chain code, the chain code is endorsed successfully.
Next, we try to call methods such as adding, deleting, modifying and checking:
(11) Initialization

#采用invoke,调用链码的InitLedger方法初始化数据
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $cafile -C mychannel -n fabcar --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $org1_CertFiles --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $org2_CertFiles -c '{"Args":["InitLedger"]}'
#参数解释
#-o 排序服务器节点
#--cafile排序节点的PEM证书文件路径
#-C通道名称
#-n链码名称
#-peerAddresses锚节点的地址
#--tlsRootCertFiles前面peerAddresses的TLS证书路径
#-c链码的方法和调用方法的参数


#备注,其中
$cafile = /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
$org1_CertFiles=/opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
$org2_CertFiles=/opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt


Reported an error ~ I feel that I have checked every letter, it should be no problem! But why is the error reported? I
insert image description here
checked it, and the channel exists.
insert image description here
This solution does not work, and it does not solve the problem~

#搜到一个解决方案,试一下不知道能不能成功
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)
docker rmi -f $(docker image|grep "dev-" |awk '{print $3}')
然后重新执行一下

[Question ID: 202206202151] docker ps -aThe container status I queried with " " is Created. Later, my friend suggested that I use the 2.2.5 version to let the chaincode container Up, but I still don't know what caused it~
insert image description here

(12) Query

#采用query调用链码中的QueryCar方法查询单部汽车
peer chaincode query -C mychannel -n fabcar -c '{"Args":["QueryCar","CAR0"]}'
#果然,上一步初始化没有成功是查询不了的,但如果上一步成功是可以查询的

(13) New

#采用invoke调用链码的CreateCar新增一辆汽车
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $cafile -C mychannel -n fabcar --peerAddresses peer0O.org1.example.com:7051 --tlsRootCertFiles $org1_CertFiles --peerAddresses peer0.org2.example.com:9051--tlsRootCertFiles $org2_CertFiles -c '{"Args":["CreateCar","CAR10","GEELY","Borui","Blue","Yujialing"]}'

(14) New query

#采用query调用链码中的QueryCar方法查询新增的汽车
peer chaincode query -C mychannel -n fabcar -c '{
    
    " Args":["QueryCar" , "CAR10"]}

(15) Modification

#采用invoke调用链码的ChangeCarOwner 更新汽车所有者
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $cafile -C mychannel
-n fabcar --peerAddresses
peer0.org1.example.com:7051 --tlsRootCertFiles $org1_CertFiles --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $org2_CertFiles -c '{
    
    "Args":["ChangeCarOwner","CAR10","小岳岳"]}

6.2 Write your own chaincode

#编写链码,存为atcc


package main

import (
"encoding/json"
"fmt"
"log"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)

//SmartContract provides functions for managing an Asset
type SmartContract struct {
    
    
	contractapi.Contract
}


type Asset struct {
    
    
	ID string `json: "ID"`
	Owner string `json : "owner"`
	Value int`json : "Value"`
}


func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
    
    
	assets := []Asset{
    
    
		{
    
    ID: "asset1", Owner: "ZhangSan", Value: 300},
		{
    
    ID: "asset2",Owner: "Lisi", Value: 400},
		{
    
    ID: "asset3",Owner: "Klay", Value: 500},
	}

	for _, asset := range assets {
    
    
		assetjSON, err := json.Marshal(asset)
		if err != nil {
    
    
			return err
		}

		err = ctx.GetStub().PutState(asset.ID,assetjSON)
		if err != nil {
    
    
			return fmt.Errorf( "failed to put to world state. %v"  , err)
		}
	}
	return nil
}


func(s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error){
    
    
	assetJSON, err := ctx.GetStub().GetState(id)
	if err != nil {
    
    
		return nil, fmt.Errorf("failed to read from world state: %v" , err)
	}
	if assetJSON == nil {
    
    
		return nil, fmt.Errorf( "the asset %s does not exist", id)
	}

	var asset Asset
	err = json. Unmarshal(assetJSON, &asset)
	if err != nil {
    
    
		return nil, err
	}
	return &asset, nil
}


func(s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error){
    
    
// range query with empty string for startKey and endKey does an
// open-ended query of all assets in the chaincode namespace
	resultsIterator,err := ctx.GetStub().GetStateByRange("", "")
	if err != nil {
    
    
		return nil,err
	}
	defer resultsIterator.Close()
	
	var assets []*Asset
	for resultsIterator.HasNext() {
    
    
		queryResponse, err := resultsIterator.Next()
		if err != nil {
    
    
			return nil, err
		}
		var asset Asset
		err = json.Unmarshal(queryResponse.Value, &asset)
		if err != nil {
    
     
			return nil, err
		}
		assets = append(assets, &asset)
	}
	return assets, nil
}


func main() {
    
    
	assetChaincode, err := contractapi.NewChaincode(&SmartContract{
    
    })
	if err != nil {
    
    
		log.Panicf("Error creating asset-transfer-basic chaincode: %v" , err)
	}
	if err := assetChaincode.Start(); err != nil {
    
    
		log. Panicf("Error starting asset-transfer-basic chaincode:%v" , err)
	}
}

This part was learned after I successfully tested fabcar with version 2.2.5, so I ran it directly based on the previous deployment of basic and fabcar chaincode demos. Therefore, the steps of changing the hosts file and organizing the information environment configuration are omitted.

//在配置了组织1信息的终端上执行:
//创建链码文件存放目录atcc,并新建atcc.go,写入上述的go语言链码代码段
//我选择在chaincode目录下创建的,这个创建在哪里没关系,自己喜欢就好~【在配置了组织1信息的终端上执行或者配置了组织1信息的终端上执行都可以】
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode# mkdir atcc
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode# cd atcc
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# vim atcc.go
//获取链码依赖
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# go mod init atcc.go 
//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/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# go mod tidy
//go: finding module for package github.com/hyperledger/fabric-contract-api-go/contractapi
//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/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# go mod vendor
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# ls
//atcc.go  go.mod  go.sum  vendor   这时候可以看到,依赖下载成功啦
//通过组织1打包链码
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode package atcc.tar.gz --path /opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc --label atcc_1
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# ls
//atcc.go  atcc.tar.gz  go.mod  go.sum  vendor   可以看到打包完成后,目录下增加了atcc.tar.gz文件
//然后我们将链码包atcc.tar.gz安装到组织1节点上,下面所示:安装成功后,返回status 200且会输出链码包标识ID——“atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48”
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode install atcc.tar.gz
//2022-06-21 19:38:06.193 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nGatcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48\022\006atcc_1" > 
//2022-06-21 19:38:06.193 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48
//然后组织1节点要审核链码,通过审核后会输出交易ID——“txid [117c564ffca5a75299a84a613a4c33380c6ed1e6744f2ca85f20efa9823252fd]”
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.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 --version 1.0 --package-id atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 --sequence 1
//2022-06-21 19:39:19.540 CST [chaincodeCmd] ClientWait -> INFO 001 txid [117c564ffca5a75299a84a613a4c33380c6ed1e6744f2ca85f20efa9823252fd] committed with status (VALID) at localhost:7051
//可以通过命令查看当前链码的审核状态,因为只有所有组织节点都审核通过之后,才能提交链码。但这个时候只有Org1MSP通过了审核,组织2还没有通过审核
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name atcc --version 1.0 --sequence 1 --output json
{
    
    
	"approvals": {
    
    
		"Org1MSP": true,
		"Org2MSP": false
	}
}
//也可以通过命令查看当前节点上安装的链码
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode queryinstalled
//Installed chaincodes on peer:
//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/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# ls
atcc.go  atcc.tar.gz  go.mod  go.sum  vendor
//同之前一样,将链码包atcc.tar.gz安装到组织2节点上,安装成功后也会返回status 200且会输出链码包标识ID——“atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48”
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode install atcc.tar.gz
//2022-06-21 19:41:36.634 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nGatcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48\022\006atcc_1" > 
//2022-06-21 19:41:36.634 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48
//然后组织2节点也要审核链码,通过审核后也会输出交易ID——“txid [117c564ffca5a75299a84a613a4c33380c6ed1e6744f2ca85f20efa9823252fd]”
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.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 --version 1.0 --package-id atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 --sequence 1
//2022-06-21 19:41:53.240 CST [chaincodeCmd] ClientWait -> INFO 001 txid [50999fd3617bd19d9dc26d9826abdfac3a468628872550574cdd5887184250c8] committed with status (VALID) at localhost:9051
//可以通过命令查看当前链码的审核状态,这时候组织1和组织2都审核通过啦,可以提交链码了
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name atcc --version 1.0 --sequence 1 --output json
{
    
    
	"approvals": {
    
    
		"Org1MSP": true,
		"Org2MSP": true
	}
}
//通过组织2提交链码【通过组织1提交也是可以的,提交一次就行啦~都是同步的。】
//提交成功后会输出两条日志信息,说明提交的交易来自两个节点【真实情况下是多个,有多少个节点审核并通过了链码,这里就会有多少条日志信息,且都是对应于同一条交易ID】
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc#  peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.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 localhost:7051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1.0 --sequence 1
//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
//提交成功输出上面的日志之后,可以用docker ps -a 命令看到docker容器中又多了三个节点对应的atcc链码容器,且均处于Up状态。这时候可以进行链码调用啦~
//首先进行链码初始化,如果成功会返回status200,否则会提示错误原因
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/fabric-2.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.com:7051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{
    
    "Args":["InitLedger"]}'
//2022-06-21 19:55:41.739 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 
//初始化成功之后可以采用query调用链码中的ReadAsset方法查询某条asset记录。-c后面接的是链码中的方法及其所需要的参数,这些方法是自己定义的,如InitLedger、ReadAsset、GetAllAssets,自己编写这个链码中只有这三个方法~
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer chaincode query -C mychannel -n atcc -c '{
    
    "Args":["ReadAsset","asset1"]}'
//{"ID":"asset1","Owner":"ZhangSan","Value":300}
//也可以采用query调用链码的GetAllAssets查询所有asset记录
root@gan-virtual-machine:/opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc# peer chaincode query -C mychannel -n atcc -c '{
    
    "Args":["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   感兴趣的话可以自己下去看~

The following is a pure command, there is no terminal directory prompt, it is more convenient to copy and paste~

//组织1执行
PWD='/opt/fabric-2.2.5/scripts/fabric-samples/test-network'
export PATH=${
    
    PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

peer lifecycle chaincode package atcc.tar.gz --path /opt/fabric-2.2.5/scripts/fabric-samples/chaincode/atcc --label atcc_1
peer lifecycle chaincode install atcc.tar.gz 
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.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 --version 1.0 --package-id atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 --sequence 1
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name atcc --version 1.0 --sequence 1 --output json



//组织2执行
PWD='/opt/fabric-2.2.5/scripts/fabric-samples/test-network'
export PATH=${
    
    PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${
    
    PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${
    
    PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
    
    PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

peer lifecycle chaincode install atcc.tar.gz 
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.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 --version 1.0 --package-id atcc_1:a682cc7b1295ef65592650b9bcd0936ebc7812fb842eee436b8e1ca9dbc1da48 --sequence 1
 peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /opt/fabric-2.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 localhost:7051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1.0 --sequence 1
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/fabric-2.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.com:7051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/fabric-2.2.5/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{
    
    "Args":["InitLedger"]}'
peer chaincode query -C mychannel -n atcc -c '{
    
    "Args":["ReadAsset","asset1"]}'
peer chaincode query -C mychannel -n atcc -c '{
    
    "Args":["GetAllAssets"]}'




Add a small question ~ can be ignored

Foreword:
insert image description here

The two packaged chaincode files are different, this is not important ~ just skip it

fabcar.tar.gz is packaged in the chaincode directory, which can be added, deleted, modified and checked
. fabcar_.tar.gz is packaged in the fabcar directory. It was obtained in the previous chapter and cannot be added, deleted, modified and checked.

insert image description here
One of the teachers is 3. More M, the other is 2. More M. I suspect that I can add, delete, modify and check normally, and there is no difference, because I looked at the directory structure, and the 7.55M directory packaged in the chaincode directory is equivalent to two fabcar directories. The content should be the same, there are too many, I can't compare the content of the files one by one~
insert image description here

learning summary

Although the content of this course is still very basic, there are still many things that need to be learned in depth. However, through this course, I learned the simple syntax of shell and go, which is helpful for reading the code later. In addition, blockchain related knowledge is reviewed through practical cases, which is useful for understanding blockchain and where it may be needed later.
Thank you very much, Teacher Datouwa~ Very good talk! very beneficial.
The road is a long way to go, and I will go up and down to search for it. fighting~

Guess you like

Origin blog.csdn.net/weixin_49422491/article/details/125309519