使用现有的区块链做二次开发是件非常痛苦的事情,用以太坊作为二次开发来说明一下,以太坊是将所有功能全部放在一个进程中实现的,所以在使用以太坊做开发时,经常会出现牵一发而动全身的情况,比如我们想在以太坊上新增一个交易结构(投票交易),那么我们来看一下将会影响到哪些模块,首先肯定是交易模块,交易需要被打包到区块中,所以区块模块也需要跟着做修改,区块需要在本地做共识(POW证明),所以共识模块也需要做相应的修改,共识后的区块需要进行全网广播,所以p2p区块同步这块也要做相应的修改。仅仅新增一个交易,就需要做这么多的连带修改,这将给对我们的开发代码巨大的不必要的工作量。所以非常需要一个框架帮助我们开发区块链项目,就像使用spring boot开发web应用一样,开发人员只需要关注业务。
Substrate介绍
Substrate是一个可扩展,模块化,开源的区块链框架,它实现了区块链开发中遇到大部分常用功能,比如p2p网络,共识算法,常用加密算法,数据存储,交易管理等,同时substrate将区块链相关的业务逻辑进行了抽象,开发人员可以只需要关心业务逻辑相关的实现,专注于区块链业务。
为什么substrate是一个框架而不是一个库,对于框架与库的区别请看上面这张图,我们开发的代码时如果需要调用其他代码,那么被调用的代码可以称为库,库只是一些功能的集合,并且需要其他人主动调用,框架的定义特征是控制反转,框架会主动调用我们的代码,程序执行的控制流与数据流都处在框架的控制下。所以我们在使用substrate的时候,substrate框架会控制在什么时候建立p2p网络,什么时候将交易加入到交易池,什么时候产生区块,什么时候对区块进行共识,我们需要做的就是实现具体的功能等待框架来调用。
以下是Substrate为我们提供构建区块链所需要的所有组件
Database
Networking
Transaction Queue
Consensus
Runtime‘
Database
区块链的本质是共享账本,所以需要对数据做持久化处理。substrate不会对上层区块链业务中使用那种区块结构,具体存储什么内容内容做任何假设,substrate在数据层使用最简单的键值对存储,实现方式是MPT。MPT存储结构可以校验一个键是否在树中,这对于轻客户端非常重要,在与区块链网络进行交互时,轻客户端需要依赖这种merkle proof来确认某个交易或状态是否存在主链上。
Networking
区块链中的节点分布在全球各地,需要有一种点对点网络协议将这些节点连接起来组成网络,所有节点可以在网络上共享交易,区块以及其他信息。substrate采用的libp2p模块化的p2p网络堆栈,libp2p不会限制我们使用那种网络协议,我们可以在libp2p上自定义自己的网络协议
libp2p是一个模块化的网络栈,通过将各种传输和p2p协议结合在一起,使得开发人员很容易构建大型、健壮的p2p网络。
Transaction Queue
网络上的交易被矿工收起起来并打包到区块中,然后矿工会顺序执行区块中的交易生成下一个状态,这里区块中的交易顺序会影响账本的最终状态。
substrate提供了一个方法,让我们自定义交易池中的交易顺序。substrate会假设交易有一个用于决定交易打包优先级的权重weight属性和一个用于创建交易依赖关系的标签tag属性。最简单的交易依赖关系是线性的,但也有复杂的依赖关系,substrate会自动处理这些复杂性。
Consensus
共识是对一种共同的状态达成一致的方法。为了使区块链的状态继续创建并向前推进,网络中的所有节点都必须一致并达成共识。这是去中心化网络中的节点能够保持彼此同步的方式。如果一个去中心化的区块链中节点没有共识,就无法确保一个节点相信的真实状态被其他节点所共享。共识的目的是在参与者都有自己「主观观点」的网络中,提供关于状态的「客观观点」。它是这些节点进行通信并达成一致的过程,并且能够生产出新的块。
共识算法是让分布式网络中的节点对某个状态达成一致的方法,在以太坊等区块链上,共识引擎与其他区块链组件紧密耦合,想要替换一个新的共识算法难度很大。substrate设计了一个抽象的共识层,在实际开发过程中可以很容易地替换共识算法,即便在区块链运行的过程中也可以做到共识算法的热插拔。substrate内置了多种共识算法模板:如工作量证明POW,Aura等。substrate共识算法的特别之处在于将区块的生产(BABE)与区块的最终确认(Grandpa)分开。
BABE/Grandpa 混合共识机制
· BABE出块,高效率的出块,最快2秒一个块
· Grandpa大量高效率确认区块,一次可以确认多个
Runtime
区块链中的状态变化是通过在上一个区块的基础上执行一系列交易完成的,每个交易的执行规则是通过状态转移函数(state transition function)决定的。状态转移函数可以很简单比如在加密货币系统中状态转移函数可以简单定义为:“只有货币所有权的用户可以消费某个货币”,也可以很复杂比如我们可以将状态转移函数定义为具有图灵完备性质的虚拟机。
在substrate中通过runtime让开发人员自定义自己的状态转移函数,在区块链中状态转移函数就是开发人员最需要关注的业务逻辑。substrate为了让runtime的开发尽可能灵活简单,substrate提供了一系列内置模块,这些模块称为pallets,开发人员可以自由组合这些模块到runtime中。比如:需要在区块链中有智能合约功能只需要将contract模块加入到runtime中即可,
除了内置的pallets开发人员也可以自定义pallet,pallet有以下五个部分构成,自定义pallet可以对每个部分进行实现。
// 1. Imports and Dependencies
// The pallet supports the use of any Rust library which compiles
// with the `no_std` flag.
use support::{decl_module, decl_event, decl_storage, …}
// 2. Runtime Configuration Trait
// All of the runtime types and consts go in here. If the pallet
// is dependent on specific other pallets, then their configuration traits
// should be added to the inherited traits list.
pub trait Trait: system::Trait { … }
// 3. Runtime Events
// Events are a simple means of reporting specific conditions and circumstances
// that have happened that users, Dapps and/or chain explorers would find
// interesting and otherwise difficult to detect.
decl_event!{ … }
// 4. Runtime Storage
// This allows for type-safe usage of the Substrate storage database, so you can
// keep things around between blocks.
decl_storage! { … }
// 5. The Pallet Declaration
// This defines the `Module` struct that is ultimately exported from this pallet.
// It defines the callable functions that this pallet exposes and orchestrates
// actions this pallet takes throughout block execution.
decl_module! { … }
Runtime 无分叉升级
任何代码都会涉及到升级现有功能,bug修复,添加新的功能的问题,然而runtime是属于链上状态转移函数,对链上的状态转移函数进行修改会影响全网的共识,甚至会造成链的分叉。现在网络上一个节点运行STF V1版本的状态转移函数,而另一个节点上的运行升级后的版本STF V2,这时他们执行区块#3里面的交易后会得到两个不同的状态,导致链发生分叉。
substrate是通过让全网的节点对要升级的runtime代码达成共识后再执行runtime代码的方式来解决分叉的问题。首先主链上的数据都是经过全网的节点共识的,所以substrate将runtime的代码编译成wasm二进制格式,然后将runtime的二进制代码存储到主链上。任何运行中的节点都可以校验链上的runtime代码是不是最新的,如果链上有最新的runtime代码,则执行链上的代码,如果没有最新的代码,则执行本地的runtime代码
通过这种方法substrate可以实现链上逻辑的升级,而且不会发生分叉。
总结
substrate是一个可扩展,模块化,开源的区块链框架,具有以下几个优点:
可无分叉升级,通过将runtime代码编译成wasm代码存储在链上,代码经过网络上的节点共识后就完成了升级
高效率,substrate是用rust开发,rust具有内存安全,没有垃圾回收避免了性能问题,强类型系统编译时避免了错误
模块化设计,开发人员可以根据需要对存储,共识,p2p网络进行定制
polkadot生态圈,可无缝对接 Polkadot,融入更大的生态,不必从头开始构建自己的社区。