2. 通过命令行体验链

2.1. 概述

通过本文你可以通过命令行和cmc工具搭建长安链多节点集群和部署智能合约,完成长安链的初步体验。

通过源码搭建长安链并且上链查数据需要以下步骤,本文将一一演示

  • 下载长安链及证书管理工具源码

  • 编译源码

  • 生成节点证书

  • 编译及安装包制作

  • 启动节点集群

  • 查看节点状态

  • 使用CMC工具安装、调用、查询一个合约

2.2. 环境依赖

2.2.1. 硬件依赖

配置 最低配置 推荐配置
CPU 1.5GHz 2.4GHz
内存 8GB 16GB
核心 4核 8核
带宽 2Mb 10Mb
### 软件依赖

当前文档在centos7.6操作下完成,以下为本次演示所需的依赖 软件列表如下:

名称 版本 描述 是否必须
git / 源码管理
golang 1.16+ 编译环境
gcc 7.3+ 编译环境依赖
glibc 2.18 智能合约执行环境依赖
tmux / 默认快速启动命令依赖
wasmer运行时库 libwasmer_runtime_c_api.so / 库在chainmaker-go/main目录下,将该库路径添加至系统PATH环境变量下
启动脚本默认包含,单独启动需加上如下配置:
cd deployPath/lib
cp xxx/main/libwasmer_runtime_c_api.so libwasmer.so
export LD_LIBRARY_PATH=deployPath/lib:$LD_LIBRARY_PATH

2.2.1.1. git

下载地址:https://git-scm.com/downloads

安装步骤,请参看:https://git-scm.com/book/en/v2/Getting-Started-Installing-Git

2.2.1.2. golang

版本为1.16或以上

下载地址:https://golang.org/dl/

安装步骤,请参看:https://golang.org/doc/install

2.2.1.3. gcc

  1. 检查 gcc 版本

gcc --version

显示结果若 < 7.3,则执行下面步骤升级

  1. 升级 gcc

sudo yum install centos-release-scl
sudo yum install devtoolset-7-gcc*
scl enable devtoolset-7 bash

注意:第三条指令scl enable devtoolset-7 bash 只是在当前会话中升级了gcc,如果想每次登录gcc自动升级,可以把scl enable devtoolset-7 bash 放在 ~/.bash_profile 文件中。

2.3. 环境搭建

下面将介绍使用脚本搭建搭建环境。

2.3.1. 使用脚本搭建

适用于LinuxMacOS

2.3.1.1. 源码下载

长安链官网下载源码:https://git.chainmaker.org.cn/chainmaker/chainmaker-go

当前为私有仓库,需要先进行账号注册

  • 下载chainmaker-go源码到本地

$ git clone -b v2.3.0_alpha https://git.chainmaker.org.cn/chainmaker/chainmaker-go.git
  • 下载证书生成工具源码到本地

$ git clone -b v2.3.0 https://git.chainmaker.org.cn/chainmaker/chainmaker-cryptogen.git

2.3.1.2. 源码编译

  • 编译证书生成工具

$ cd chainmaker-cryptogen
$ make

2.3.1.3. 配置文件生成

  • 将编译好的chainmaker-cryptogen,软连接到chainmaker-go/tools目录

# 进入工具目录
$ cd chainmaker-go/tools

# 软连接chainmaker-cryptogen到tools目录下
$ ln -s ../../chainmaker-cryptogen/ .
  • 2.1版本之后,ChainMaker支持多种身份模式,由于不同身份模式下,配置文件的目录结构和内容差异较大,在此我们选择身份模式PermissionedWithCert(详情见身份权限管理)作为示例。

2.3.1.3.1. PermissionedWithCert

原始的身份模式,即证书模式

进入chainmaker-go/scripts目录,执行prepare.sh脚本生成单链4节点集群配置,存于路径chainmaker-go/build

prepare.sh脚本支持生成solo模式节点证书和配置,以及4/7/10/13/16节点的证书和配置

# 进入脚本目录
$ cd ../scripts

# 查看脚本帮助
$ ./prepare.sh -h
Usage:  
  prepare.sh node_cnt(1/4/7/10/13/16) chain_cnt(1-4) p2p_port(default:11301) rpc_port(default:12301)
    eg1: prepare.sh 4 1
    eg2: prepare.sh 4 1 11301 12301

# 生成单链4节点集群的证书和配置
$ ./prepare.sh 4 1
begin check params...
begin generate certs, cnt: 4
input consensus type (0-SOLO,1-TBFT(default),3-HOTSTUFF,4-RAFT,5-DPOS):
input log level (DEBUG|INFO(default)|WARN|ERROR):
enable docker vm (YES|NO(default))
begin generate node1 config...
begin generate node2 config...
begin generate node3 config...
begin generate node4 config...

# 查看生成好的节点证书和配置
$ tree -L 3 ../build/
../build/
├── config
│   ├── node1
│   │   ├── certs
│   │   ├── chainconfig
│   │   ├── chainmaker.yml
│   │   └── log.yml
│   ├── node2
│   │   ├── certs
│   │   ├── chainconfig
│   │   ├── chainmaker.yml
│   │   └── log.yml
│   ├── node3
│   │   ├── certs
│   │   ├── chainconfig
│   │   ├── chainmaker.yml
│   │   └── log.yml
│   └── node4
│       ├── certs
│       ├── chainconfig
│       ├── chainmaker.yml
│       └── log.yml
├── crypto-config
│   ├── wx-org1.chainmaker.org
│   │   ├── ca
│   │   ├── node
│   │   └── user
│   ├── wx-org2.chainmaker.org
│   │   ├── ca
│   │   ├── node
│   │   └── user
│   ├── wx-org3.chainmaker.org
│   │   ├── ca
│   │   ├── node
│   │   └── user
│   └── wx-org4.chainmaker.org
│       ├── ca
│       ├── node
│       └── user
└── crypto_config.yml
  • 关于自动生成的端口说明

通过prepare.sh脚本生成的配置,默认是在单台服务器上部署,故自动生成的端口号,是从一个起始端口号开始依次递增,可以通过命令行参数修改起始端口号。

主要有2个端口,p2p端口(用于节点互联)和rpc端口(用于客户端与节点通信),p2p起始端口为11301rpc起始端口为12301

如果生成4个节点的配置,p2p端口分别为:11301、11302、11303、11304rpc端口分别为:12301、12302、12303、12304

如果是在多机部署,希望生成固定的端口号,请参考:【多机部署】

2.3.1.4. 编译及安装包制作

  • 生成证书(prepare.sh脚本)后执行build_release.sh脚本,将编译chainmaker-go模块,并打包生成安装,存于路径chainmaker-go/build/release

$ ./build_release.sh
$ tree ../build/release/
../build/release/
├── chainmaker-v2.0.0-wx-org1.chainmaker.org-20210406194833-x86_64.tar.gz
├── chainmaker-v2.0.0-wx-org2.chainmaker.org-20210406194833-x86_64.tar.gz
├── chainmaker-v2.0.0-wx-org3.chainmaker.org-20210406194833-x86_64.tar.gz
├── chainmaker-v2.0.0-wx-org4.chainmaker.org-20210406194833-x86_64.tar.gz
└── crypto-config-20210406194833.tar.gz

2.3.1.5. 启动节点集群

  • 执行cluster_quick_start.sh脚本,会解压各个安装包,调用bin目录中的start.sh脚本,启动chainmaker节点

$ ./cluster_quick_start.sh normal
  • 启动成功后,将*.tar.gz备份,以免下次启动再次解压缩时文件被覆盖

$ mkdir -p ../build/bak
$ mv ../build/release/*.tar.gz ../build/bak

若需要关闭集群,使用脚本:

$ ./cluster_quick_stop.sh

2.3.1.6. 查看节点启动使用正常

  • 查看进程是否存在

$ ps -ef|grep chainmaker | grep -v grep
25261  2146  4 19:55 pts/20   00:00:01 ./chainmaker start -c ../config/wx-org1.chainmaker.org/chainmaker.yml
25286  2146  4 19:55 pts/20   00:00:01 ./chainmaker start -c ../config/wx-org2.chainmaker.org/chainmaker.yml
25309  2146  4 19:55 pts/20   00:00:01 ./chainmaker start -c ../config/wx-org3.chainmaker.org/chainmaker.yml
25335  2146  4 19:55 pts/20   00:00:01 ./chainmaker start -c ../config/wx-org4.chainmaker.org/chainmaker.yml
  • 查看端口是否监听

$ netstat -lptn | grep 1230
tcp6       0      0 :::12301                :::*                    LISTEN      25261/./chainmaker  
tcp6       0      0 :::12302                :::*                    LISTEN      25286/./chainmaker  
tcp6       0      0 :::12303                :::*                    LISTEN      25309/./chainmaker  
tcp6       0      0 :::12304                :::*                    LISTEN      25335/./chainmaker 
  • 检查节点是否有ERROR日志

$ cat ../build/release/*/bin/panic.log
$ cat ../build/release/*/log/system.log
$ cat ../build/release/*/log/system.log |grep "ERROR\|put block\|all necessary"
//若看到all necessary peers connected则表示节点已经准备就绪。

2.4. 使用CMC命令行工具部署、调用合约

为了验证所搭建的链功能是否正常,可以通过cmc命令行工具来进行验证。

2.4.1. 编译&配置

cmc工具的编译&运行方式如下:

创建工作目录 $WORKDIR 比如 ~/chainmaker
启动测试链 在工作目录下 使用脚本搭建

# 编译cmc
$ cd $WORKDIR/chainmaker-go/tools/cmc
$ go build
# 配置测试数据
$ cp -rf ../../build/crypto-config ../../tools/cmc/testdata/ # 使用chainmaker-cryptogen生成的测试链的证书
# 查看help
$ cd ../../chainmaker-go/tools/cmc
$ ./cmc --help

2.4.2. 部署示例合约

  • 创建wasm合约

    $ ./cmc client contract user create \
    --contract-name=fact \
    --runtime-type=WASMER \
    --byte-code-path=./testdata/claim-wasm-demo/rust-fact-2.0.0.wasm \
    --version=1.0 \
    --sdk-conf-path=./testdata/sdk_config.yml \
    --admin-key-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.key,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.sign.key,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.sign.key \
    --admin-crt-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.sign.crt,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.sign.crt,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.sign.crt \
    --sync-result=true \
    --params="{}"
    

    如下返回表示成功: EVM contract name in hex: 532c238cec7071ce8655aba07e50f9fb16f72ca1 response: message:”OK” contract_result:<result:”\n(532c238cec7071ce8655aba07e50f9fb16f72ca1\022\0031.0\030\005<\n\026wx-org1.chainmaker.org\020\001\032 F]\334,\005O\200\272\353\213\274\375nT\026%K\r\314\362\361\253X\3562\377\216\250kh\031” message:”OK” > tx_id:”e2af1241ff464d47b869a69ce8a615df50da57d3faff4754ad6e45b9f914b938” 注:智能合约编写参见:智能合约开发

  • 调用wasm合约

    $ ./cmc client contract user invoke \
    --contract-name=fact \
    --method=save \
    --sdk-conf-path=./testdata/sdk_config.yml \
    --params="{\"file_name\":\"name007\",\"file_hash\":\"ab3456df5799b87c77e7f88\",\"time\":\"6543234\"}" \
    --sync-result=true
    

    如下返回表示成功: INVOKE contract resp, [code:0]/[msg:OK]/[contractResult:gas_used:12964572 contract_event:<topic:”topic_vx” tx_id:”7c9e98befbb64cec916765d760d4def5aa26f8bac78d419c9018b8d220e7f041” contract_name:”fact” contract_version:”1.0” event_data:”ab3456df5799b87c77e7f88” event_data:”” event_data:”6543234” > ]/[txId:7c9e98befbb64cec916765d760d4def5aa26f8bac78d419c9018b8d220e7f041]

  • 查询合约

    $ ./cmc client contract user get \
    --contract-name=fact \
    --method=find_by_file_hash \
    --sdk-conf-path=./testdata/sdk_config.yml \
    --params="{\"file_hash\":\"ab3456df5799b87c77e7f88\"}"
    

    如下返回表示成功: QUERY contract resp: message:”SUCCESS” contract_result:<result:”{“file_hash”:”ab3456df5799b87c77e7f88”,”file_name”:””,”time”:”6543234”}” gas_used:24354672 > tx_id:”25716b955ebd4a258c4bd6b6f682f1341dfe97e4bd18495c864992f1618a2003”

2.4.3. 查询链上数据

查询链上block和transaction 主要参数说明如下:

  --sdk-conf-path:指定cmc使用sdk的配置文件路径
  --chain-id:指定链Id
  • 根据区块高度查询链上未归档区块

    ./cmc query block-by-height [blockheight] \
    --chain-id=chain1 \
    --sdk-conf-path=./testdata/sdk_config.yml
    
  • 根据区块hash查询链上未归档区块

    ./cmc query block-by-hash [blockhash] \
    --chain-id=chain1 \
    --sdk-conf-path=./testdata/sdk_config.yml
    
  • 根据txid查询链上未归档区块

    ./cmc query block-by-txid [txid] \
    --chain-id=chain1 \
    --sdk-conf-path=./testdata/sdk_config.yml
    
  • 根据txid查询链上未归档tx

    ./cmc query tx [txid] \
    --chain-id=chain1 \
    --sdk-conf-path=./testdata/sdk_config.yml
    

2.4.3.1. 查询链配置

```sh
./cmc client chainconfig query \
--sdk-conf-path=./testdata/sdk_config.yml
```

2.5. 长安链部署目录说明

此目录为使用: chainmaker-go/scripts/cluster_quick_start.sh启动后的的目录结构说明。

 taifu@chainmaker:chainmaker-go/build$ tree
.
├── backup # 下次重新prepare.sh时,此次的备份。
├── config # 使用 prepare.sh 生成的节点配置信息
│   ├── node1 # 节点1-4
│   ├── node2
│   ├── node3
│   └── node4
├── crypto-config # 使用 prepare.sh 生成的组织证书信息
│   ├── wx-org1.chainmaker.org # 组织名称1-4
│   │   ├── ca # 该组织的根证书 ca
│   │   ├── node # 由该组织的根证书签发的节点证书 common/consensus
│   │   └── user # 由该组织的根证书签发的用户证书 admin/client/light
│   ├── wx-org2.chainmaker.org
│   │   ├── ca
│   │   ├── node
│   │   └── user
│   ├── wx-org3.chainmaker.org
│   │   ├── ca
│   │   ├── node
│   │   └── user
│   └── wx-org4.chainmaker.org
│       ├── ca
│       ├── node
│       └── user
├── crypto_config.yml # 使用 prepare.sh 生成以上证书的配置文件(扩展组织、证书可使用到)
├── pkcs11_keys.yml # 使用 prepare.sh 生成的硬件加密机相关配置
└── release # 使用 build_release.sh 生成的打包好的部署文件夹
    ├── crypto-config-20220720141039.tar.gz # 证书集 即上面的crypto-config文件夹的压缩包
    ├── chainmaker-v2.3.0_alpha-wx-org2.chainmaker.org # 使用 cluster_quick_start.sh 启动链后,解压缩后的部署文件
    │   ├── bin  # 操作管理脚本目录
    │   ├── config # 配置文件目录
    │   ├── data # 数据目录
    │   ├── lib # 依赖目录
    │   └── log # 日志目录
    ├── chainmaker-v2.3.0_alpha-wx-org2.chainmaker.org-20220720141039-x86_64.tar.gz # 使用 build_release.sh 生成的打包好的部署文件
    ├── chainmaker-v2.3.0_alpha-wx-org3.chainmaker.org
    │   ├── bin
    │   ├── config
    │   ├── data
    │   ├── lib
    │   └── log
    ├── chainmaker-v2.3.0_alpha-wx-org3.chainmaker.org-20220720141039-x86_64.tar.gz
    ├── chainmaker-v2.3.0_alpha-wx-org4.chainmaker.org
    │   ├── bin
    │   ├── config
    │   ├── data
    │   ├── lib
    │   └── log
    │── chainmaker-v2.3.0_alpha-wx-org4.chainmaker.org-20220720141039-x86_64.tar.gz
    |
    |
    | # 以下为部署节点文件详情
    ├── chainmaker-v2.3.0_alpha-wx-org1.chainmaker.org # 解压缩后的部署文件
    │   ├── bin  # 操作管理脚本目录
    │   │   ├── chainmaker # 二进制文件
    │   │   ├── chainmaker.service # 基于 linux 系统的 systemd 自拉起服务
    │   │   ├── docker-vm-standalone-start.sh # 独立启动 docker 虚拟机引擎脚本
    │   │   ├── docker-vm-standalone-stop.sh # 独立停止 docker 虚拟机引擎脚本
    │   │   ├── init.sh # 基于 linux 系统的 systemd 自拉起服务部署脚本
    │   │   ├── panic.log # 异常日志输出及控制台输出日志文件
    │   │   ├── restart.sh # 重启节点脚本
    │   │   ├── run.sh # 基于 linux 系统的 systemd 自拉起服务管理脚本
    │   │   ├── start.sh # 启动节点脚本
    │   │   └── stop.sh # 停止节点脚本
    │   ├── config # 配置文件目录
    │   │   └── wx-org1.chainmaker.org
    │   │       ├── certs # 证书
    │   │       │   ├── ca
    │   │       │   │   ├── wx-org1.chainmaker.org
    │   │       │   │   │   └── ca.crt
    │   │       │   ├── node 
    │   │       │   │   |── common1 # 同步节点证书(通过chainmaker.yml配置为节点证书,表示只可同步)
    │   │       │   │   └── consensus1 # 共识节点证书(通过chainmaker.yml配置为节点证书不代表就可以参与共识,共识管理是在链配置bc.yml中)
    │   │       │   │       ├── consensus1.nodeid # xxx.sign.crt生成的节点id
    │   │       │   │       ├── consensus1.sign.crt # 签名证书
    │   │       │   │       ├── consensus1.sign.key # 签名key
    │   │       │   │       ├── consensus1.tls.crt # tls连接证书
    │   │       │   │       └── consensus1.tls.key # tls连接key
    │   │       │   └── user # 用户证书
    │   │       │       ├── admin1 # 管理员
    │   │       │       │   ├── admin1.sign.crt
    │   │       │       │   ├── admin1.sign.key
    │   │       │       │   ├── admin1.tls.crt
    │   │       │       │   └── admin1.tls.key
    │   │       │       ├── client1 # 普通客户端
    │   │       │       │   ├── client1.addr
    │   │       │       │   ├── client1.sign.crt
    │   │       │       │   ├── client1.sign.key
    │   │       │       │   ├── client1.tls.crt
    │   │       │       │   └── client1.tls.key
    │   │       │       └── light1 # 轻节点,只可同步当前组织的数据(区块、交易)
    │   │       │           ├── light1.sign.crt
    │   │       │           ├── light1.sign.key
    │   │       │           ├── light1.tls.crt
    │   │       │           └── light1.tls.key
    │   │       ├── chainconfig # 链配置
    │   │       │   │── bc1.yml # 第一条链配置
    │   │       │   └── bc2.yml # 第二条链配置
    │   │       ├── chainmaker.yml # 节点配置
    │   │       └── log.yml # 日志配置
    │   ├── data # 数据目录
    │   │   └── wx-org1.chainmaker.org
    │   │       ├── block # 区块数据/索引(必须)
    │   │       │   └── chain1
    │   │       │       └── store_block
    │   │       │           ├── 000001.log
    │   │       │           ├── CURRENT
    │   │       │           ├── LOCK
    │   │       │           ├── LOG
    │   │       │           └── MANIFEST-000000
    │   │       ├── history # 历史数据
    │   │       │   └── chain1
    │   │       │       └── store_history
    │   │       │           ├── 000001.log
    │   │       │           ├── CURRENT
    │   │       │           ├── LOCK
    │   │       │           ├── LOG
    │   │       │           └── MANIFEST-000000
    │   │       ├── ledgerData1 # 中间数据(必须)
    │   │       │   └── chain1 # 链ID
    │   │       │       ├── bfdb # 区块实际存储数据(文件存储方式)
    │   │       │       │   └── 00000000000000000001.fdb.END
    │   │       │       ├── localdb # 中间状态数据
    │   │       │       │   ├── 000001.log
    │   │       │       │   ├── CURRENT
    │   │       │       │   ├── LOCK
    │   │       │       │   ├── LOG
    │   │       │       │   └── MANIFEST-000000
    │   │       │       └── wal_QmSQeH1SV65YkafQG6y7uqabF4Xwzn5VoXniFBXrzy4Eqn # 异常恢复临时数据
    │   │       │           └── 00001_1.wal
    │   │       ├── result # 结果集数据
    │   │       │   └── chain1
    │   │       │       └── store_result
    │   │       │           ├── 000001.log
    │   │       │           ├── CURRENT
    │   │       │           ├── LOCK
    │   │       │           ├── LOG
    │   │       │           └── MANIFEST-000000
    │   │       └── state # 状态数据(必须)
    │   │           └── chain1
    │   │               └── store_state
    │   │                   ├── 000001.log
    │   │                   ├── CURRENT
    │   │                   ├── LOCK
    │   │                   ├── LOG
    │   │                   └── MANIFEST-000000
    │   ├── lib # 依赖目录
    │   │   ├── libwasmer.so # wasmer(rust)运行引擎
    │   │   └── wxdec # wxvm(c++)运行引擎
    │   └── log # 日志目录
    │       ├── system.log # 当前1小时的日志
    │       └── system.log.2022072014 # 历史日志
    └── chainmaker-v2.3.0_alpha-wx-org1.chainmaker.org-20220720141039-x86_64.tar.gz # 使用 build_release.sh 生成的打包好的部署文件