恢复 Substrate 链: unexpected epoch changes

Posted heyuanxun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了恢复 Substrate 链: unexpected epoch changes相关的知识,希望对你有一定的参考价值。

恢复 Substrate 链

问题描述

使用 Substrate 定制的区块链,所有节点听了一段时间后,链无法工作。

Substrate:polkadot-v0.9.25
共识协议: babe + grandpa
系统:macOS Big Sur (11.3)
cargo: cargo 1.63.0-nightly (a4c1cd0eb 2022-05-18)

babe 协议算法,要求每个 epoch(session) 周期内都需要出块,因此当链出现以下情况,导致无法正常出块时,链就会变成砖块(bricked),无法正常工作。

  • grandpa 节点少于拜占庭容错要求,无法确认块,地址不能在一个 epoch 内出块
  • 所有验证者节点离线

解决方法

出现这种问题时,可以用两种方式解决

Hard Spoon

这种方式的原理是通过 rpc 接口(或者状态数据库)获取到最后正常区块高度下的状态数据,生成一个新的创世块,基于新的创世块运行链。本质上完全是一条新的链,只是继承了状态数据。

如果不在乎区块的历史,只需要保持当前的状态数据,则可以使用此方式。

可参考 fork-off-substrate

我并没有基于这种方式实践成功。
依赖的 polkadot-js 版本过低,升级之后能生成新的创世块文件,用新的创世块运行,还是报错。

Time Warp

Babe 无法正常工作是因为,在最后出块的下一个 epoch 内,没有正常出块,那么如果所有的验证者节点把系统时间调整到最后出块的时间,理论上就可以让链恢复工作了。 正常情况下,区块链和外部时间是一致的,人为的让区块链回到历史时间(最后出块时间),再以加速的时间流逝赶上外部世界的时间。

修改代码

我的链是以 git 路径的方式依赖 substrate crates

需要替换要修改的两个 crates 依赖

修改项目的 Cargo.tom ,节选如下,路径设置为自己修改的 crates 目录即可:

[patch."https://github.com/paritytech/substrate"]
sc-consensus-slots =  path = "/path/to/custom/sc-consensus-slots" 
sp-timestamp =  path = "/path/to/custom/sp-timestamp" 

修改的两个 crates ,参考 d0decd9

这里我们修改为两倍速运行。

sc-consensus-slots
sc-consensus-slots/src/slots.rs

/// Returns the duration until the next slot from now.
pub fn time_until_next_slot(slot_duration: Duration) -> Duration 
	// HOTFIX: poll the slot 2 times as often since we might be in a time warp.
	let slot_duration = slot_duration / 2;
	...

sp-timestamp
sp-timestamp/src/lib.rs

WARP_FACTOR :即时间扭曲的倍数,对应被压缩的是出块时间,合理设置自己的倍数;
FORK_TIMESTAMP:分叉时刻,扭曲的基础时间,这里选择最后确认块的下一块出块时间;
REVIVE_TIMESTAMP: 计划的各验证节点开始运行的时刻,不需要很精确,小于验证节点都拿到修改后的可执行文件,运行的时间即可;

impl InherentDataProvider 
	/// Create `Self` while using the system time to get the timestamp.
	pub fn from_system_time() -> Self 
		let timestamp = current_timestamp().as_millis() as u64;

		// HOTFIX: mutate timestamp to make it revert back in time and have slots
		// happen at 2x their speed from then until we have caught up with the present time.
		const REVIVE_TIMESTAMP: u64 = 1642105111666; // 2022-08-25T20:18:31.666Z
		const FORK_TIMESTAMP: u64 =   1642006674001; // 2022-08-26T16:57:54.001Z
		const WARP_FACTOR: u64 = 2;

		let time_since_revival = timestamp.saturating_sub(REVIVE_TIMESTAMP);
		let warped_timestamp = FORK_TIMESTAMP + WARP_FACTOR * time_since_revival;

		// we want to ensure our timestamp is such that slots run monotonically with blocks
		// at 1/2th of the slot_duration from this slot onwards until we catch up to the
		// wall-clock time.
		let timestamp = timestamp.min(warped_timestamp);

		Self 
			max_drift: std::time::Duration::from_secs(60).into(),
			timestamp: timestamp.into(),
		
	
	...

执行恢复

  1. 备份本地数据
    如: cp -r node1 node1.bak
  2. 回滚未确认的块
    如:./node revert --chain ./specRaw.json --base-path ./node1
  3. 使用时间扭曲的程序启动链,指向原来的数据
  4. 观察日志或管理界面看是否能正常出块
  5. 等待追赶上外部系统时间
  6. 使用原程序继续运行

参考链接

  1. https://github.com/paritytech/substrate/issues/4464
  2. https://github.com/paritytech/substrate/issues/11673
  3. https://substrate.stackexchange.com/questions/168/how-to-unbrick-a-substrate-chain-revert/175#175%EF%BC%89
  4. https://medium.com/polkadot-network/kusamas-first-adventure-2cd4f439a7a4
  5. https://github.com/maxsam4/fork-off-substrate

substrate 区块链框架 概述

1. 定义

Substrate是一个具备区块链核心要素(例如数据存储,p2p通讯,共识算法,密码学组件等)、可用于构建开源、模块化和可扩展区块链的基础技术框架。

Substrate把一个区块链运行所需要的各个模块拆解开,具备可扩展性、模块化、开源、自主可控的特性。开发者可以方便地通过编写runtime(好比一种更高级的智能合约)来修改如加密、共识等模块构建自己的区块链。

  • 核心模块:数据库、加密算法、交易队列、命令行界面、公/私钥生成、RPC等
  • 基本逻辑:数据结构、结算、时间戳、分片等
  • p2p网络:网络节点管理、私讯协议集成、分布式哈希表
  • 共识机制:抵押、Babe、Grandpa、区块落实追踪
  • 治理、升级模型:链上逻辑升级、链上治理
  • dapp:智能合约(联盟链定制化)

2.设计架构
在这里插入图片描述

2.1 Runtime组件

定义如何处理区块,包括状态转换逻辑。

  • runtime代码被编译为Wasm并成为区块链存储状态的一部分
  • 利用Wasm特性实现无分叉链上升级。

2.2 Substrate客户端

Substrate客户端既是针对与客户端本身相同的平台(而不是Wasm)编译的“本地runtime”, 将调用调度到runtime客户端组件的执行程序,它在本机代码和解释Wasm之间进行选择。尽管本地runtime可能会提供性能优势,但是如果执行程序实现了较新的WASM版本,则执行程序将选择解释Wasm来执行。

2.3 存储组件

用于维持以区块链为代表的分布式系统的交易状态。区块链网络使参与者利用共识机制在不可信环境下达成状态存储。Substrate采用一种简单且高效的键值存储机制。

2.4 P2P点对点网络组件

允许客户端与其他网络参与者进行通信。

  • 使用libp2p网络协议栈。
  • 支持模块化、自定义共识引擎。

2.5 RPC(远程过程调用)组件

允许区块链用户与链上网络交互,提供HTTP和WebSocket RPC接口服务。

2.7 遥测组件

通过嵌入Prometheus 服务,能够将区块链网络指标对外暴露

以上是关于恢复 Substrate 链: unexpected epoch changes的主要内容,如果未能解决你的问题,请参考以下文章

Substrate区块链及运行时模块简介

substrate 区块链框架 概述

ChainBridge跨链协议教程EVM/Substrate

跨链协议ChainBridge简明教程EVM/Substrate

创建第一个 Substrate 区块链

波卡链Substrate 生态介绍