原文作者:Mike Tang

原文来源:Web3.0 Explorer

Compound(https://compund.finanice)在 2021 年 3 月正式上线了其独立链网络 Gateway(原名 Compound Chain)。Gateway 是一条独立的链,它的方针是成为一个一致的 Defi 纽带,完结跨链的 Defi——你能够质押链 A 上的财物,在链 B 上告贷——从而将一切链的财物全部打通,提高全网络财物运用率和流动性

Gateway 的呈现根据如下的判别:未来国际必定是一个多链的国际,即没有一条区块链能处理一切问题。未来会有许多条链,许多种或许性。所以人们的财物会被涣散到各个独立的渠道。怎么提高这些涣散的财物的运用率,便是 Gateway 要研究和处理的问题。

Gateway 的体系架构

为什么Compound选择Substrate进行独立链的开发Gateway 架构图

如架构图所示,Gateway 经过针对各种链(Peer Chain)开发特定的 Starport(Peer Chain 上的一组合约或组件),来衔接一切的链。

本文不会在 Gateway 的 Defi 相关事物上做过多叙说,本文首要就 Gateway 为何挑选 Substrate 进行开发做一个扼要的剖析。

为什么要挑选 Substate

Compound 官方的说法:

We chose Substrate so that we could focus on building application code, instead of inventing consensus algorithms; it』s a modern framework built on a modern language, Rust. 

(https://medium.com/compound-finance/gateway-623f6f48d2b6)

咱们挑选 Substrate 以便咱们能够聚焦在构建运用代码上,而不是去创造共同算法;而且它是一个现代结构,构建在现代言语 Rust 之上。

Rust 言语是一门面向安全的现代编程言语。关于 Rust 言语的良好口碑,本文也不再赘述,感兴趣的朋友能够阅览《2020 开发者调查报告:Rust 再次成为最受欢迎的言语》。Rust 简直已成为当今区块链开发的首选言语,比方:Polkadot, Near, Solana, Dfinity,FileCoin 的底层等等都是 Rust 完结的。Rust 言语有以下明显特性:

● 内存安全:其独有的一切权和生命期规划,理论上确保不会呈现内存过错。处理了底层体系缺点中的 70% 的问题

● 并发安全:在并发编程(多线程,多协程)中,能确保并发的安全性

● 高功用:与 C/C++是同一级的功用,现在干流言语中的顶级

● 零开支笼统:此特性让 Rust 能够无缝衔接 C 言语的既有生态,而没有功用丢失

● 强壮的笼统表达能力:Rust 学习了许多函数式言语的表达力,让其表达更干练

● 现代的工程化设施:Cargo 和 crates.io 这种现代化的辅佐体系,让 Rust 构建杂乱工程时轻松自在

● 活跃活跃的社区:Rust 从一开端便是以社区方式开发迭代的,这点其实十分有意思,与 go 这种集权式开发明显不同

了解 Rust 的这些特性后,咱们再去了解「Rust 言语简直已成为当今区块链开发的首选言语「这句话就显得很自然了。区块链自身以安全性为第一位,这点与 Rust 的规划理念彻底共同。区块链中要做大量的核算,也需求高功用,这点 Rust 也是见义勇为。区块链体系一般比较杂乱,对工程相关根底设施的要求很高,而 Rust 强壮的工程性规划,让其在团队、开源社区开发中,特别适合大型项意图协作。

以注重安全性闻名的 Paritytech 公司,用 Rust 言语开发了以太坊的 parity 客户端。然后持续用 Rust 开发了新项目 Polkadot,在开发 Polkadot 的过程中,逐步形成了一个重大决议:将区块链的一切功用,拆解成笼统的规划,完结到一个开源的、通用的区块链结构中,并以此结构为东西,构建 Polkadot 产品。而这个区块链结构的重大成果,便是本文的主角——Substrate。

Substrate 是一个用 Rust 言语开发的以通用性为方针的区块链开发结构。它的规划元素,比方暗码学算法、存储结构 MPT 树,账户体系等,大部分学习自有史以来最成功的以太坊的根底设施,(这个能够了解,Paritytech 最早便是做以太坊客户端起家的,Gavin Wood 也是以太坊的联合创始人之一)。一个结构,要做到通用,就需求高度笼统。而高度笼统的价值往往会显得结构杂乱,不易于运用。所以 Substrate 也供给了许多 DSL(领域特定言语),便利新手学习运用。简略概括一下,Substrate 具有如下特点:

面向通用。其规划面向通用领域,而不是专为某一条链做开发的 SDK。每个团队都能够运用 Substrate 开宣布一条彻底独立的不依靠于任何既有网络的链出来(比方,运用 Substrate 开发的区块链能够与 Polkadot 无关,这也是 Paritytech 的规划方针之一) 功用全面。能掩盖区块链简直一切的场景,能够说是现在市面上功用最全面的区块链结构 Runtime 代码编译成 wasm 履行。Wasm 是当今区块链业界干流的 VM 字节码挑选 可定制性超强。Substrate 自身是一堆涣散的组件,能够在一套规范束缚下,自在替换组件,自在组合

工程规划便是做取舍,当它强调一方面的时候,在另一方面,就会有必定的退让。Substrate 也有自己的不足:

● 新引进一些概念名词(比方:extrinsic),需求重新学习了解,上手有必定门槛

● 强调通用,导致在某些方面过于笼统,代码视觉比较杂乱(比方泛型参数特别多)。而这些笼统将 Rust 的高档语法特性做了充沛的展现,代码噪音较大

● 整个工程代码量较大,依靠的包十分多(现在有 1000 多个),导致编译时刻比较长(普通笔记本几十分钟以上),对开发机功用要求较高

如上能够看到,这些不足首要是 Substrate 的规划方针——通用——自身带来的客观依靠杂乱性造成的。

瑕不掩瑜,作为现在为止最强的区块链开发结构之一,Substrate 受到了越来越多立异团队的欢迎,Compound 团队挑选 Substrate 进行 Gateway 的开发也就顺理成章了。

Substrate 的功用组件

为什么Compound选择Substrate进行独立链的开发Substrate 整体结构图

从架构图能够看到,Substrate 有如下几大组件:

● P2p Networking P2p 网络

● Runtime 运转时

● Storage 存储

● Consensus 共同

● RPC 远程过程调用

● Telemetry 客户端监测东西

P2p 网络,是区块链体系必备的子体系。多个节点经过 p2p 衔接成组成同一个网络。在节点与节点之间发音讯传递数据,网络中的音讯传达有或许经过多个中继节点传达后到达。在 Substrate 中,运用的是 rust-libp2p(https://github.com/libp2p/rust-libp2p),此项目也首要是由 Paritytech 在负责保护。

Runtime,运转时,是区块链事务逻辑的完结部分。也便是说要用区块链干什么实际的事,就需求写在这里面。Substrate 支撑将 Runtime 代码编译成 wasm 字节码或 native code 两种方式运转(跟着 wasm vm 运转速度的提高,未来 native code 方式或许会被扔掉,这也能下降一些内部杂乱性)。在 Runtime 中能够操作 Storage,完结状况的改变,因而 Runtime 整体也被称作状况搬运函数(State Transition Function, STF)。

Storage,存储子体系,是区块链体系中不可短少的组成部分。在 Substrate 中,Storage 用于耐久化 Runtime 的逻辑对状况的改变,同时也支撑对外的 RPC 状况读取接口,Runtime 中的 Event 在宣布前,也会在 Storage 中做短暂的存储。共同体系的方针,也是对 Storage 中的状况达到共同。Storage 子体系在底层用的是 kv 数据库 rocksdb 或 paritydb。

Consensus,共同子体系,用于在网络的参加方之间就区块链的状况达到共同,也便是「共同」。由所以分布式体系,所谓区块链的状况,并没有一个微观的上帝视角能看到一个一致的微观状况。这个状况,其实便是各个节点的状况,每个节点有自己的本地状况视图,也有一个「部分「的大局视图。每个节点经过本地视图与大局视图的比对,做出决议计划。共同体系要在各个节点上达到一个共同的状况,从而推进体系往前运转。

RPC,远程过程调用,用于向节点外部供给拜访的接口。一个 Substrate node 自身能够作为一个服务而存在,外界能够经过这些 rpc 接口拜访 node 的本地状况信息或向 node 提交改变恳求。Substrate 同时供给 HTTP 和 Websocket 两种 rpc 通道。

Telemetry,客户端监测东西,用于收集 node 的运转信息,发送到远端的 Prometheus 服务器。

Substrate 的开发方式

Substrate 是一个通用开发结构。它为不同层次的开发者供给了三种开发风格。

一:直接运用 Substrate 自带的 node 起链。关于想快速起链,体会效果的开发者,能够直接运用 Substrate 预置的 node 的完结。只需求修正一个 JSON 配置文件,就能够跑起来,详细可定制以下内容:

● 创始区块的状况信息

● 账户 Account

● 余额 Balance

● Staking 份额等

二:Runtime FRAME pallets 的开发。这种开发方式经过写 Runtime 中的 pallet 代码,将事务逻辑完结到 pallet 中。然后将自界说的 pallets 和其依靠的 Substrate 自带的 pallets 一同编译成 wasm 字节码运转,这是大部分 Substrate 开发者的挑选。

三:根据 Substrate Core 深度定制。Substrate 已完结成涣散的组件,做了充沛的笼统宽和耦。关于一些高档开发者,在某些特定的场景下,能够彻底从底层重新组合这些组件,完结深度的 node 的定制。比方,能够做到:

● 运用不同的暗码曲线和哈希算法

● 运用不同的序列化办法

● 替换不同的共同算法

● 彻底去除 FRAME 层代码,运用另一种言语编写事务,只要能确保编译到 wasm 且遵循 Substrate 的规范即可

● 等等

下图展示了三个层次的开发难度和技能灵敏性之间的关系。

为什么Compound选择Substrate进行独立链的开发直接运用 Substrate Node 最简略,可是最不灵敏。根据 Substrate Core 开发最灵敏,可是最难。进行 FRAME pallets 开发处于中心方位。也是大部分 Substrate 开发者应该采用的方法。

Substrate 的优异之处

Substrate 的规划有许多优异之处,咱们来了解一下。

可晋级无分叉 Runtime

由于 Substrate 的 Runtime 代码编译为 wasm 运转,然后 wasm 字节码自身作为买卖的数据直接提交到链上,再藉由链自身的 p2p 网络全网传达,完结事务逻辑的更新。每个节点在收到更新版本的 wasm 字节码后,将其更新到代码段,在某个块之后就运用新版本的 wasm 来履行逻辑。

有了这种热更新代码机制,事务代码的晋级不再会引起分叉(软分叉或硬分叉)了,也便是说,不会由所以技能客观的原因,导致网络的分叉(人为主动分叉还是能够的)。

需求留意的是,这种晋级仅限于 wasm 字节码能掩盖的部分——也即 Runtime 中的代码——的晋级。假如改动了 node 代码自身(即 Runtime 外的部分),依然需求告诉一切节点进行手动或 devops 替换。

可替换的暗码学库

Substrate 同时支撑几种暗码学曲线:

● ECDSA

● Ed25519

● SR25519

同时支撑几种 Hash:

● Blake2

● xxHash

开发者可根据自己的需求挑选运用。假如没有你想要的,依照它的架构为其增加新的曲线和 Hash 函数也不难。

层次丰厚的 Account 体系

Substrate 的 Account Key 分三个层次:

● Stash Key

● Controller Key

● Session Keys

Stash Key 是用来存资金的账户,其私钥部分应该尽或许安全地存储在冷钱包中。Controller Key 用来操控 Validator 的参数,也是 Stash Key 的一个中心署理账户,在更新验证人调集时十分有用。Session Keys 用来对共同相关的音讯进行签名。Session Keys 能够有多个,每一个都有自己专门的用处,一般可组合在一同运用,如:

impl_opaque_keys! https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg

pub struct SessionKeys https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg

pub grandpa: Grandpa,

pub babe: Babe,

pub im_online: ImOnline,

pub authority_discovery: AuthorityDiscovery,

}

}

上述代码将 4 个独立的 Session Keys: Grandpa session key, Babe session key, ImOnline session key, AuthorityDiscovery session key 组合在一同成为一个大的 SessionKeys。

能够将 Session Keys 了解成 Validator 运转过程中的唯一标识(Identification)。Session Keys 每过一个 Session 最好更换一次,这样能最大程度确保安全性。

Substrate 经过这种分层的 Account Key 的规划,既确保了安全性,又供给了充沛的灵敏性,基本能掩盖一切运用场景的需求。

笼统可切换的共同引擎

Substrate 规划了一套共同结构,这套共同结构十分了得。它将块的生产(proposal)与敲定(finalize)别离,同时包容了 Nakamoto 类(只有概率性敲定,无确定性敲定)共同和 BFT 类(有确定性敲定)共同。

Substrate 为出块供给了以下几种算法:

● Aura:slot 方式,在一个已知的 authority set 中,运用 round robin 方式轮流出块

● Babe:slot 方式,在一个已知的 authority set 中,运用可验证随机函数 VRF 随机挑选出块节点(每个 slot 或许不止一个出块人)

● Pow:工作量证明出块

这几种出块算法,假如没有 Finalize Gadget 合作,只能做到概率性敲定(finalization),而无法做到确定性敲定。Substrate 供给了 Grandpa 这个 Finalize Gadget,用于确定性敲定。

出块算法与敲定算法能够自在合作运用。所以有 Aura/Grandpa, Babe/Grandpa, 乃至 Pow/Grandpa 这几种组合。而在不需求确定性敲定的场景下,当然也能够不运用 Grandpa。Substrate 给了开发者充沛的自在。

Substrate 共同结构还供给了其它一些根底设施:

● Fork Choince Rules: Longest Chain Rule 或 GHOST Rule,用于决议在链有分叉的情况下,怎么挑选一个最好的链的算法

● Import Queue:导入行列

● Block Import Trait:块导入接口

● Block Import Pipeline:块导入流水线

Substrate 还供给了在 Runtime 中对共同过程进行协调操控的功用。比方,在 Pow 运转过程中调整难度,在 PoA 中决议下一个是否轮转到,在 PoS 中动态修正 Stake 的权重等等。

在 Substrate 这一套齐备的根底设施之上,假如他自带的共同引擎无法满足开发者的需求,开发者还能够依照他的规范开发自己的共同引擎,引进到结构中运用,而且可在 Runtime 中进行适当操控。

Off-Chain 特性

Off-Chain 特性是 Substrate 中供给的一套相当强壮的根底设施。毕竟对区块链来说,链上的逻辑操作空间十分有限,有些事情有必要经过链下来完结。在没有 Off-Chain Worker (OCW) 之前,这一类事情,通常是由预言机 Oracle 来完结。预言机是外部服务,经过区块链节点 RPC 接口向区块链提交买卖从而把外界的信息传到链上去。这种方法虽然是可行的,但它在安全性、集成性、可扩展性和根底设施效率问题上面,依然不够好。

为了让链下数据的集成更安全和有用,Substrate 供给了 off-chain 相关的特性。其架构图如下:

为什么Compound选择Substrate进行独立链的开发Off-chain Worker 架构图

Off-chain 特性包含三大组件:

● Off-Chain Worker

● Off-Chain Storage

● Off-Chain Indexing

Off-Chain Worker 用于完结链下逻辑。其代码与 Runtime 代码写在一同,并被编译到同一个 wasm 字节码字符串中,在同一个买卖中被传达到全网络。可是在履行的时候,Off-Chain Worker 的代码是在独立的 VM 中履行的,即与 Runtime 逻辑的履行彻底隔离开。详细来说,Off-Chain Worker 能够完结如下功用:

● 将核算的成果以买卖方式提交到链上

● 包含一个全功用的 HTTP 客户端,能够拜访外部服务的数据

● 能够拜访本地 node 的 keystore,这样便能够验证和签名买卖

● 能够拜访本地的 KV 数据库,且在一切 off-chain worker 中同享这个数据库

● 本地的安全的熵源,用来产生随机数

● 能够拜访本节点的本地时刻

● 能够 sleep 和 resume 工作

Off-Chain Storage 是链下逻辑独立的存储空间,与链上的 Storage 是彻底隔离开的。它具有如下特性:

● 能被 Off-Chain Worker 读取和写入

● 存储在 node 本地,不会传递到网络中其它节点去,不会参加网络共同

● 被一切同时运转的 Off-Chain Workers 同享拜访(因而需求锁操作)。因而,能够运用其在不同的 Workers 之间通讯

● 能被 Runtime 代码写入,可是不能读。因而,可根据其完结必定的链上链下交互功用

● 可被 wasm 环境外的 node 中的代码读取,因而能被 RPC 读取

Off-Chain Indexing 供给了在 Runtime 环境中,向 Off-Chain Storage 写入数据的能力。可是不能读取  Off-Chain Storage 中的数据。这为一些新的编程范式供给了或许性。

其它还有一些,比方,完善的 OCW 集成测试结构等等。

Substrate 的 Off-chain 特性十分强壮,令人形象深入。

齐备灵敏的 Gas 费核算机制

有以太坊开发经历的朋友都知道,Gas 费机制是十分成功的一个规划,对链的安全和平稳运转十分重要。简直一切后来的区块链都直接学习了这种规划。而在 Substrate 中,供给了十分完整详尽的机制和配置参量来帮助开发者规划他们自己的 Gas 费算法。Substrate 中内置了如下 Gas 核算和配置参量:

● Includsion Fee: 包含 length_fee 和 weight_fee

● Fee Multiplier

● Additional Fees,包含

○ Bonds

○ Deposits

○ Burns

○ Limits

● Default Weight Annotations

● Dynamic Weights

● Post Dispatch Weight Correction

● Custom Fees

● Custom Inclusion Fee

咱们这里不再对每个条目做详细解释,详细意义请参阅:https://substrate.dev。

能够看到,Substrate 对 Gas 费核算的规划十分全面,乃至稍显杂乱。其意图依然是完结通用区块链结构的方针——该有的都应该有,而且要能开箱即用。

Substrate 十分适合用于发动独立的链或许是面向 Web3.0 运用的 Appchain,一般这些链会在用户体会上下足功夫。比方关于运用的普通用户来讲,运用服务的过程中,或许会认识不到 Gas 费的存在,在这种场景下,Substrate 供给的上述丰厚的 Gas 费机制,能做到 Gas 费置零或许设置为代付。这类特性便有时机让 Substrate 成为最适合 Web3.0 App 的开发结构之一。

Runtime API 与 RPC 集成

Substrate 供给了一套 RPC 扩展结构,让开发者能够(在 Substrate 默认供给的接口之外)扩展开发自己的 RPC 接口。由于 RPC 完结代码是在 node 中,Runtime 之外,所以理论上来说,能够在 Substrate 中开发全功用(做任何事情)的 RPC 服务。这就使得 Substrate 成为了一个强壮的 RPC 开发结构。

而往往咱们需求与 Runtime 中的状况进行交互,这时就需求用到 Runtime API 了。Runtime API 是 Runtime 内与外的桥梁,也能够说是链上与链下的桥梁。

所以 RPC 与 Runtime API 组合起来,就能够将外部恳求发起到获取链上状况的流程全部打通。合作自界说的 Runtime API 功用和 RPC 扩展接口功用,给予了开发者巨大的灵敏性和或许性。也为 Substrate 成为一个一体化集成式的 Web3.0 开发结构打下根底。

Gateway 怎么运用 Substrate

为了搞清楚 Gateway 是怎么运用 Substrate 的,咱们直接拉它的源代码下来扼要剖析一番。

git clone https://github.com/compound-finance/gateway

cd gateway && ls

能够看到,有如下首要目录(咱们加了扼要注释)。

ethereum/ 以太坊上的 Starport 合约代码

ethereum-client/ 以太坊相关类型界说和根底东西函数

gateway-crypto/ Gateway 用到的暗码相关的根底东西函数

integration/ 集成测试代码

node/ Substrate 的自界说 node 代码

our-std/ Gateway 的 std 代码,是对 sp_std 的简略封装,并增加了一点额外的东西

pallets/ Gateway 独立链的主体事务逻辑代码

runtime/ Substrate 的运转时构建代码

types-derive/ Gateway 用到的类型相关过程宏

能够看到,现在 Gateway 只完结了到 ethereum 的 startport 衔接,其它链的对接还在开发中,会逐步加入。

主体事务代码在 pallets/ 目录下,此目录下有三个子目录。

cash/ 主体事务逻辑

oracle/ 从喂价机获取价格的代码

runtime-interfaces/ 一些运转时接口

咱们从 pallets/cash/src/lib.rs 看起。这是一个规范的 pallet 文件,其结构有

● trait Config 的界说

● decl_storage! 界说链上存储部分

● decl_event! 界说事情输出部分

● decl_module! 界说模块完结部分

在模块完结部分中,有 fn offchain_worker(block_number: T::BlockNumber) https://bicoin8.com/wp-content/uploads/2023/04/202304211cHpE0.jpg} 这个函数。其完结首要是这两个函数调用:

internal::events::track_chain_events::<T>()

internal::notices::process_notices::<T>(block_number)

咱们知道,Substrate 的 offchain_worker 进口,是在每个块导入本地状况数据库时调用。也即 fn offchain_worker(block_number: T::BlockNumber) 这个函数会被每个块驱动履行,每个块履行一次这个函数。因而,每增加一个块,上面的代码会分别处理 events 和 notices 这两块内容,而这两块内容的代码在 internal 模块中界说。

持续追踪 pallets/cash/src/internal/events.rs 和 pallets/cash/src/internal/notices.rs 文件后,能够整理出大体的逻辑要点:

● Offchain_worker 每个块调用一次

● 在 offchain_worker 代码中,会调用到 ethereum-client/ 供给的以太坊根底类型和辅佐东西,发 http 恳求到以太坊的事情服务器,批量获取以太坊的 events,并分类处理

● 处理后的成果会以发买卖的方式从 offchain_worker 中提交到链上

● 进入 Runtime 事务逻辑进行处理

pallets/oracle/ 里面的逻辑流程也类似:在 offchain_worker 中,用 http 恳求从喂价机地址获取数据,然后提交给链上运用。

了解了上述流程后,也就能比较轻松地了解 Compound 在 Ethereum 上做 Compound Governance Proposal 是怎么影响到 Gateway 链上的验证人节点调集更新的了。其依然是经过以太坊的事情向外抛出信息,事情服务器收集到事情后,缓存下来。Gateway 这边的 Offchain worker 每新增一个块就去事情服务器上批量取一次最近的事情。获取到最近的事情后,按对应的逻辑迭代处理就行了。而 Substrate 中要更新验证人调集,需求用到 Controler account,以及 SetKeys 等相关由 Substrate 供给的功用。

限于篇幅,咱们这里的剖析点到为止,这里只扼要的剖析了 Gateway Pallet 粗线条的逻辑流程,然后对 Offchain Worker 部分做了重点关注。

能够看到,Gateway 充沛运用 Substrate 供给的根底设施,很便利地完结了事务逻辑以及链上代码与链下代码的集成,以及与其它链的交互。整个代码完结得十分清晰,值得咱们学习学习。

总结

本篇,咱们介绍了 Gateway 的整体架构,Substrate 的功用模块,Substrate 结构的特色之处,以及 Gateway 是怎么充沛运用 Substrate 供给的根底设施进行独立链的开发。

视野开拓

蒲寿庚对泉州的崛起居功阙伟。在他的主导下,泉州与上百个国家形成了贸易关系,货物贸易十分繁忙,市舶司管理的海船数量一度有15000艘之多。他还在泉州至杭州之间,专门设置了“海上站赤”(即海驿)15站,每站备有海船5艘,水军200人,专门运送从泉州入口的番货及贡品。因商贸之繁荣,泉州商人名闻天下,元代学者吴澄记载,泉州是“富商巨贾之窟宅,号为天下最”。-《浩荡两千年》

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注