亚马逊AWS官方博客

在 AWS 上部署基于 Cosmos 技术的企业级联盟链

一、概述

Cosmos 是开源开放、高度可扩展的区块链跨链网络,也是全球最大、最为知名的区块链生态之一。 Cosmos 是一个由 CometBFT(原 Tendermint 团队)推出的支持跨链交互的异构网络,由多条独立、并行的区块链组成去中心化网络,其愿景是打破信息的孤岛效应,实现不同区块链之间的互操作性。

在多链时代,跨链是区块链行业的一个刚需。Cosmos 的跨链模式非常适合专注于垂直领域的公链,通过提供模块化的区块链,为各个应用开发者使用适合自己的公链提供便利。Cosmos 生态的应用程序和协议使用 IBC(区块链间通信协议)进行连接,实现各独立区块链之间的跨主权自由交换资产和数据。Cosmos 的最终目标是创建一个区块链互联网,允许大量自主且易开发的区块链互相扩展和交互。

本文主要围绕 Cosmos 的价值、技术架构进行描述,并详细介绍在 AWS 环境内的 Cosmos 企业级联盟链(IRITA)的快速搭建教程。

二、价值陈述

随着 Cosmos 生态的不断发展和繁荣,Cosmos 相关的技术和生态也越来越多地受到了关注。截至目前,Cosmos 生态上已集成了 272 个应用与服务,管理的数字资产超过 7500 亿美元。

理论上 Cosmos 解决了当今最困难的三个区块链问题:

  1. 可扩展性:CometBFT 共识机制可以理解为投票一致系统,基于 PoS 和 BFT 算法,PoS 选出提议人,BFT 机制下只要有 2/3 节点是诚实的,就能保障投票结果一致;
  2. 可用性:Cosmos SDK 这种模块化的框架,可以非常方便地构建可互操作、特定于应用程序的区块链;
  3. 互操作性:Cosmos 通过 IBC 通信协议实现 HUB 与 ZONE 之间的跨链通信,实现了类似 TCP/IP 的作用。

凭借着这些独特设计,Cosmos 生态项目被给予了更多的自主权、灵活性以及更优秀的性能。

Cosmos 生态系统提供了实现可互操作的多链世界所必需的框架和基础设施工具。Cosmos 专注于自治、主权和可扩展性,为开发人员和企业家提供了一种无需高额前期投资即可进行试验和创新的简便方法。不断发展的社区、链上治理和没有中心化的开发团队,使 Cosmos 成为一个真正去中心化的生态系统。虽然 Cosmos 生态系统提供了巨大的机会,但 L1 空间的竞争愈演愈烈,在极简主义的世界中,Cosmos 正在构建一个更具包容性的多链世界,并正在稳步获得牵引力。

三、方案介绍

Cosmos 的核心模块主要包括:CometBFT 共识、Cosmos SDK 和 IBC (跨链通信协议),在架构上采用了「Hub 和 Zone」模型。

3.1 CometBFT 共识

CometBFT 包括两个主要技术组件:区块链共识引擎(CometBFT Core)和通用应用程序区块链接口(Application BlockChain Interface,ABCI)。CometBFT Core 是基于 CometBFT 共识算法的底层共识引擎,保证所有节点按照相同的顺序记录交易。CometBFT 共识算法采用了非常典型的拜占庭容错方案,是一种 PBFT+Bonded PoS (有质押的权益证明)混合共识。

3.2 Cosmos SDK

Cosmos SDK 是一个帮助开发者加快开发进程的工具包,其典型特点是模块化和可插拔。通过使用 Cosmos SDK,开发者可以在 CometBFT 共识算法的基础上构建自己的区块链或功能组件。Cosmos SDK 为开发者提供了很大的便利性,缩短了开发者的开发周期。

3.3 跨链通信协议(IBC)

Cosmos 由多条独立并行的区块链组成去中心化网络,利用中继技术实现不同区块链之间的跨链。因此,IBC 是整个项目最核心的部分。IBC 是 Cosmos 设计的跨链通信协议,依赖其及时最终性的特点,用于 Hub 与 Zone 之间进行通信,以实现跨链交互。IBC 也是 Cosmos SDK 中的模块之一。

3.4 Hub 和 Zone

Cosmos 在架构上采用了「Hub 和 Zone」模型,与 Hub 连接的 Zone 都是不同的区块链,不同 Zone 之间的跨链交互通过 IBC 来实现。Cosmos 生态中的 Hub 和 Zone 都采用 CometBFT 共识协议,Hub 会追踪记录连接的 Zone 状态,Zone 会将产出的新区块状态发送给 Hub。

3.5 IRITA

跨域行业互信联盟产品(Inter-Realm Industry Trust Alliance,简称 IRITA),是 Cosmos 生态中第一个企业级联盟链产品。IRITA 基于现代区块链技术框架 CometBFT 和 IRIS SDK,并结合边界智能团队在区块链跨链、NFT 技术及大数据隐私保护技术领域多年积累,打造的支持下一代分布式商业系统的企业级联盟链产品线。

IRITA 具有保护隐私的数据加密共享、高效的共识协议、领先的跨链技术、实用性极强的链上链下系统交互及多方协作业务流集成能力、灵活的资产数字化建模与可信交换支撑、以及大数据存储 6 大核心技术优势,可广泛应用于金融、医疗健康、供应链、车联网等多种商业场景,为实体经济提供基于区块链信任机器的价值赋能。

IRITA 支持中国国密标准,并有完善的 SDK 及运维工具支持,在性能、安全可靠性、认证及权限、可维护性、可扩展性和运维监控等多方面都满足企业级应用需求。

边界智能作为 Cosmos 核心技术贡献者,长期深耕于跨链技术领域,其开发的开源代码被数十个全球区块链网络所采用。边界智能技术团队为 Cosmos SDK 贡献了 NFT 模块等功能模块,完成了 ICS-20 代码实现,领导开发了 ICS-721 跨链 NFT 标准及其代码实现等,该功能为 Cosmos 引入基于 IBC 的跨链 NFT 互操作性,并扩展了 IBC 能力。

IRITA 联盟链产品架构

四、部署说明

4.1 节点准备

节点配置要求:

测试环境:2 vCPU、8G 内存、100GB 磁盘,推荐实例类型 m6a.large, m5.large, t3.large

正式环境:4 vCPU、16G 内存、100GB 磁盘,推荐实例类型 m6a.xlarge, m5a.xlarge, m6i.xlarge

创建 4 台区块链节点服务器,其中关键步骤说明如下:

1)选择操作系统:Amazon Linux 2 AMI – Kernel 5.10

2)选择实例类型,例如 m6a.large

3)配置本地存储,分别创建 1 个系统盘(20GB gp3 EBS 卷),1 个数据盘(100GB gp3 EBS 卷),其中数据盘将挂载在 /data 目录下

4)在高级选项 User data 填入以下内容,用于执行节点的初始化操作

#!/bin/bash -ex
# Install Docker
amazon-linux-extras install docker -y
# Start the docker service
systemctl start docker.service
systemctl enable docker.service
# Add user to docker group
usermod -a -G docker ec2-user
# Format and mount data volume
mkfs -t xfs /dev/nvme1n1
mkdir /data
echo "/dev/nvme1n1    /data           xfs    defaults,nofail  0   2" | tee -a /etc/fstab
mount -a
chown ec2-user.ec2-user /data
# Reboot instance
reboot

5)完成以上步骤后得到 4 个区块链节点服务器,并分别命名 node0 至 node3:

6)配置安全组,为每个节点启用以下端口访问

  • 1317:提供 restful api 外部调用,共识节点可不开放、全节点可选
  • 8545-8546:提供 evm 的 rpc 和 websockets 接口,共识节点可不开放、全节点可选
  • 9090:节点对外 grpc 接口,共识节点可不开放、全节点可选
  • 26656:节点间 p2p 网络
  • 26657:节点对外 rpc 接口,共识节点可不开放、全节点可选
  • 26660:提供监控 metrics

创建好后的安全组:

将安全组与每个节点进行关联:

4.2 安装部署

1)在第一台机器(node0)上生成节点数据,chain-id:testnet

# 生成 4 个节点数据,会要求输入 8 次密码
$ docker run -it --rm -v /data:/root bianjie/irita:v3.2.2-wenchangchain irita testnet --v 4 --chain-id testnet --output-dir /root

Enter keyring passphrase:
Re-enter keyring passphrase:
…
…
…
Successfully initialized 4 node directories

2)拷贝数据

此时 node0 的/data 目录下会有 node0、node1、node2、node3 四份节点的数据,将数据拷贝到对应节点的/data 目录下,并命名为 node,拷贝过程注意目录的权限设置。

# 可以使用 scp 将数据拷贝到其它节点(node1~3)的/data 目录下
$ scp -i ~/.ssh/your-private-key.pem -r /data/nodeX ec2-user@172.31.17.118:/data/node

3)修改配置(从此处,四个节点均执行下面操作)

a. 配置其他节点的 peers

确定各个机器的内网 ip 和 peer id

$ ifconfig
$ docker run -it --rm -v /data/node/irita:/root/.irita bianjie/irita:v3.2.2-wenchangchain irita tendermint show-node-id

最后我们可以获取各个节点的 peer 配置,格式为 node_peerid@node_ip:26656

这里建议将获取的信息以表格整理方便后续修改配置文件,例如:

Name node_peerid@node_ip:26656
Node0 cf14286aef99e49c702cba4bd31d3529b8b3c01a@172.31.17.118:26656
Node1 53aabd9bf37c54a2c21ece0671d08131e1b121cf@172.31.24.153:26656
Node2 a35ec424702ed479247c2a8adc546f238f9bc2d5@172.31.17.206:26656
Node3 3368c48c13fb26ca0bcef27680c252877d94eddf@172.31.29.175:26656

修改 /data/node/irita/config/config.toml 中 persistent_peers 配置,各节点只需要配置其他节点的 peers(除去自身的配置)。

例如,在 node0 节点配置应该是这样的:

# node0
persistent_peers = "53aabd9bf37c54a2c21ece0671d08131e1b121cf@172.31.24.153:26656,a35ec424702ed479247c2a8adc546f238f9bc2d5@172.31.17.206:26656,3368c48c13fb26ca0bcef27680c252877d94eddf@172.31.29.175:26656"

b. 修改 /data/node/irita/config/config.toml

# 修改为 false 可以在内网启动节点
addr_book_strict = false

4)各主机上启动节点

$ docker run -itd -p1317:1317 -p26656-26660:26656-26660 -p9090:9090 -p8545:8545 -p8546:8546 -v /data/node/irita:/root/.irita --name node bianjie/irita:v3.2.2-wenchangchain irita start

5)导入验证人

在各个节点的 /data/node 目录下面都存在一个 iritacli 目录,各个节点执行下面操作:

查看助记词:

# 复制文件里面 secret 的值,也就是助记词
cat /data/node0/iritacli/key_seed.json

通过助记词恢复地址:

# 在运行的节点容器中开启一个交互模式终端
$ docker exec -it 951f0200849e bash
# 通过助记词恢复地址,粘贴刚刚复制的助记词,回车,输入第1) 步中设置的密码即可
$ irita keys add validator --recover

列出本地地址:

# 查看本地地址,输入第1) 步中设置的密码
$ irita keys list

6)查看状态

通过访问 http://node-ip-address:26657/status 查看区块链状态信息

4.3 节点配置说明

节点的主要配置文件有:config.toml app.toml genesis.json,其中 genesis.json 是创世区块文件,链启动前修改有效,是链上共识参数包括:chain-id、区块大小、共识节点个数等。

1)config.toml 常用配置,重启节点生效:

 [p2p]
# 对端节点地址形如:ip@id:port,seeds 获取其它广播的节点地址
seeds = ""
persistent_peers = ""
# 是否广播本节点地址
pex = true
# 私有受保护的节点地址,主要用于哨兵节点保护不开放外网的共识节点
private_peer_ids = ""

[mempool]
# 内存池交易数上限
size = 5000
# 节点是否开启广播交易
broadcast = true
# 内存池总体交易大小上限
max_txs_bytes = 1073741824
# 内存池单笔交易大小上限
max_tx_bytes = 1048576

[statesync]
# 状态同步,不通过拷贝 data 数据启动节点,需提供开启快照功能的节点,从最近状态启动无历史区块数据
enable = false

[consensus]
# 出块时间,最终出块时间取决于所有节点
timeout_commit = "5s"

[tx_index]
# 节点是否对块高、交易等创建索引,"null" 不创建索引提高节点性能但无法通过 tx hash 查询交易 
indexer = "kv"

[instrumentation]
# 开启节点监控与监听端口
prometheus = false
prometheus_listen_addr = ":26660"

2)app.toml 常用配置项,重启节点生效:

# 指定节点接收到交易的 gas 单价下限,如交易 gas 200000,如下配置时指定的 fees >= gas * minimum-gas-prices = 200000ugas 交易才会通过节点广播上链
minimum-gas-prices = "1ugas"
# 节点清理历史区块状态减少磁盘用量,有多个策略可选
pruning = "default"
# 节点停止的块高或时间,一般用于停链升级
halt-height = 0
halt-time = 0

# 节点是否开启 rest api server 和对应的 swagger 接口说明
[api]
enable = false
swagger = false

[grpc]
# 节点是否开启 grpc server
enable = true

# 节点是否开启快照功能供其它节点快速启动,snapshot-interval 非零开启,节点块高到达配置值的整数倍开始生成快照,保留数由 snapshot-keep-recent 指定
[state-sync]
snapshot-interval = 0
snapshot-keep-recent = 2

4.4 区块数据同步

新启动的节点,除了从创世区块从零开始同步以外,还有以下三种快速同步的方法:

1)停止一个节点运行,并打包 /root/.irita/data 数据目录然后拷贝到目标主机解压;

2)在亚马逊云平台上运行的节点,对 data 磁盘(EBS 卷) 执行快照(注意快照内勿留下 data 外的其它数据/文件),通过快照为其它节点快速恢复 data 数据,也可以共享快照给其他账户加速节点数据同步;

3)使用 state sync 状态同步快速启动新节点,需要有节点开启区块状态快照功能作为数据源提供给新加入节点,新节点开启 state sync启动方式直接同步最近块高状态(跳过历史区块)快速启动;

4.5 区块链监控

1)开启链监控

修改 /data/node/irita/config/config.toml 中 prometheus 选项,默认端口为 26660

# 修改为 true 以启用 prometheus 监控
prometheus = true

保存后重启节点服务

# 重启
$ docker restart node

通过访问 http://<node-ip-address>:26660/metrics 查看监控的 metrics

常用监控规则如下:

    - "name": "chain"
      "rules": 
      - "alert": "chain Consensus Halt"
        "annotations": 
          "cluster": "Irita nodes"
          "message": "chain consensus has halted for {{ $value }} rounds."
        "expr": |
          max(tendermint_consensus_rounds) > 10
        "for": "1m"
        "labels": 
          "severity": "critical"
      - "alert": "chain Node Out Of Sync"
        "annotations": 
          "cluster": "Irita nodes"
          "message": "chain node '{{ $labels.instance }}' out of block sync for over 5 minutes."
        "expr": |
          changes(tendermint_consensus_latest_block_height{job="chain"}[5m]) == 0 and tendermint_consensus_rounds{job="chain"} == 0
        "for": "1m"
        "labels": 
          "severity": "critical"          
      - "alert": "chain Validator Jailed" # 共识节点被踢出共识节点集
        "annotations": 
          "cluster": "Irita nodes"
          "message": "{{ $value }} validators are jailed"
        "expr": |
          sum(iris_module_stake_jailed{instance="validator"} == 1) by (namespace, instance)
        "for": "1m"
        "labels": 
          "severity": "critical"
      - "alert": "chain Online Voting Power Waring" #共识节点参与共识投票的比例低
        "annotations":
          "cluster": "Irita nodes"
          "message": "chain online voting power is less than 70%."
        "expr": |
          (1 - (tendermint_consensus_byzantine_validators_power + tendermint_consensus_missing_validators_power) / tendermint_consensus_validators_power) <= 0.7
        "for": "1m"
        "labels": 
          "severity": "critical"
      - "alert": "chain Byzantine Validators Waring"
        "annotations":
          "cluster": "Irita nodes"
          "message": "chain has found {{ $value }} byzantine validator(s)."
        "expr": |
          tendermint_consensus_byzantine_validators{instance="chain-validator"} > 0
        "for": "1m"
        "labels": 
          "severity": "critical"
      - "alert": "chain Node Down" #链节点down
        "annotations": 
          "cluster": "Irita nodes"
          "message": "chain node '{{ $labels.instance }}' has disappeared from Prometheus target discovery."
        "expr": |
          up{job="chain"} == 0
        "for": "1m"
        "labels": 
          "severity": "critical"

2)Prometheus 配置

- "job_name": "irita"
  "static_configs":
  - "targets": ["192.168.0.160:26660"]

3)Grafana 配置模板

可以使用完全托管的 Grafana 服务(Amazon Managed Grafana)对来自 Prometheus 数据源的指标数据进行可视化和监控。

在 Amazon Grafana 控制台窗口为 Irita 新建一个 workspace,并完成基本配置:

就绪后,使用 Admin 权限的用户登录,在 Data source 里面添加 prometheus 数据源:

新建 Dashboard绘制模板,并添加仪表板(panel),选择 Irita 作为数据源,在指标浏览器选择所需的度量指标,如 区块高度,交易数量,区块大小,平均出块时间等指标:

Irita 监控面板效果展示:

4.6 资源清理

(1)如需保留测试数据,可先将数据盘卸载

- "job_name": "irita"
  "static_configs":
  - "targets": ["192.168.0.160:26660"]

在 EC2 控制台点击实例,找到对应的实例,点击存储,再点对应的击卷 ID,勾选卷,点击右上角操作中的分离卷。如需删除,选中卷点击操作中的删除即可。

(2)删除实例

在 EC2 控制台点击实例,选择对应的实例,点击右上角实例状态中的终止实例。

五、总结

利用 AWS EC2 部署基于 Cosmos 的区块链节点,可以非常方便地根据负载情况动态调整资源配置,如 CPU、内存、磁盘 IO 等。根据业务需求动态调整资源,可以有效实现降本增效。

在网络层面,联盟链节点之间通过公网互联,安全和性能都会受到影响,而成本却非常高。利用 AWS VPC 对等连接,可以使不同的节点运营方部署在亚马逊云上的节点通过部内骨干网实现跨账号的互联,保障了安全和性能的同时,几乎可以使网络流量成本忽略不计。亚马逊云科技账号之间的资源隔离、权限隔离,又能够很好的保障联盟链以去中心化的方式运行。

数据安全方面,使用 AWS EC2 的数据生命周期管理器(Data Lifecycle Manager),制定节点的数据盘快照策略,定时执行增量快照可以在不停机的状态下完成数据的备份。同时,基于快照恢复磁盘可在秒级完成,大大提高了故障恢复以及新节点启动的效率,避免了节点耗时耗力的从零同步并执行历史所有的区块数据。并且快照可以跨 AWS 账号共享,在多方参与建设的联盟链部署架构中,起到了重要的作用。

使用 Amazon Managed Grafana 托管服务可以更加轻松地可视化和监控节点运行运行状态,并且随着使用需求的增加自动扩展计算和数据库基础设施,以及自动版本更新和安全补丁,从而减轻 Grafana 的运维管理负担。

边界智能将亚马逊云科技的多个产品进行组合,实现基于 Cosmos 的企业级联盟链的一键部署和自动化运维,并计划将联盟链节点部署作为一项托管服务添加到 AWS Marketplace,这样机构客户只需点击几下即可加入现有网络或启动自定义联盟链网络。

本篇作者

肖学嵩

亚马逊云科技初创生态解决方案架构师,15 年 IT 从业经验,现主要负责云计算方案架构的咨询和设计,以技术赋能助力初创企业成长。拥有多年企业级数据中心系统架构设计和实施经验,曾任职于 Sinodata, IBM, Lenovo 等厂商,并先后在私有云和大数据领域有从 0 到 1 的创业经历。

奚海峰

边界智能董事长兼 CTO ,金融科技技术专家,清华大学自动化本科及硕士、美国马里兰大学电气和计算机工程硕士,拥有大型互联网产品研发和分布式应用系统集成等丰富经验。曾担任万向区块链股份公司旗下万云平台 CTO、中国金融在线公司(NASDAQ:JRJC)技术副总裁、世界知名金融服务公司 TUDOR INVESTMENT 及 RBS SEMPRA 主管架构师等职位。在区块链方面有多个前沿技术专利进入实审阶段,拥有深厚的技术研发积累及在 Web3.0 应用中的创新实践经验。

张业龙

边界智能技术总监,10 年以上软件开发、架构设计及项目管理经验。技术专长区块链、DevOps、互联网系统架构设计和开发,对区块链底层技术有深入理解,对容器化服务管理有多年实践。

唐伟峰

边界智能 DevOps 工程师,拥有多年的运维经验。擅长 RedHat、Ubuntu 系统运维,Shell、Python 脚本编程,AWS、Kubernetes 基础架构平台,MySQL、TiDB 等数据库服务,以及区块链及其相关产品的维护运行,深入理解架构分布式去中心化应用。