0%

IPOS共识算法设计

选型思路

本文介绍的共识算法是ionchain中是用的POS算法,即IPOS,这里先简单描述一下我们当初为ionchain选择共识算法的一些考量。

众所周知的是工作量证明算法(POW)是第一个在区块链中使用的共识算法,也被广泛的认证过的实现分布式共识的最好的算法,POW被广泛的用在如比特别,以太坊和一些其他的加密货币中,尽管POW算法有如此广泛的应用,但也存储在一些不容忽视的缺点:

  • 需要非常高的算力
  • 高能源消耗
  • 矿池带来的中心化问题

基于以上这些考虑,我们在选择算法时就忽略了POW,因为一旦我们的项目中使用POW作为共识算法还会带来一些我们无法控制的问题,例如:一些矿场将他们的算力切换到我们链上,挖取大量的货币并将货币在二级市场上抛售,这样我们的货币就有归零的风险。

那么还有没有一种共识算法同时兼具POW的有点,同时也减少POW的缺点呢?有,这个算法就是权益证明(POS),在POW中矿工通过部署大量的矿机来争夺区块的打包权,那么在POS中,矿工是如何来竞争打包权?POS中矿工的算力是用权益来表示的,权益即矿工将所持有的加密货币一部分以保证金的形式存储在系统中,并处于锁定状态(不可以取出),如果以后不想挖矿了可以从系统中取出相应的保证金。在ionchain中是以合约的形式实现保证金的存储与赎回,矿工可以通过调用系统保证金合约来获取相关账户的权益,具体的实现方式可以参考github上开源的项目IPOSContract

权益的问题解决了,接下来要考虑如何选择合适的矿工打包区块,对于选择算法我们会有以下几个目标:

  • 用户拥有的保证金越多,那么该用户被选中的概率就越大
  • 算法选择过程中包含一定程度的概率,以避免出现富有的用户总是被选中生成区块,持续获得的奖励,富人越来越富
  • 目前POS中常用的选择算法有两种:1. 独立同分布随机算法,2. 币龄选择。如果采用币龄选择算法,会导致用户离线攒币龄,等币龄满足条件后才上线打包区块,这样会导致我们的链上的节点在线率不高,所有在IPOS中我们选择独立同分布随机作为选择节点的算法

如何选择节点打包区块的问题解决了,具体的算法将会在下一章节中做详细的介绍,接下来我们应该考虑的是激励的问题了,激励是区块链中一个非常重要的组成部分,在POW算法中对矿工的激励分成两部分:1. 打包生成区块的奖励。 2. 区块中的所有交易费用的奖励。 由于我们使用的是POS算法,在POS中是以权益作为算力的,所以在整个生态中我们需要确保货币不能超发即不能增发货币,所以在POS算法中我们对矿工的奖励只有交易费用这部分。

算法介绍

在POW算法中是通过hash算力来获取区块的打包权的,POS是通过权益来获取打包权的,其实POS是对POW的一种改进,为了便于大家理解POS是如何工作的,在这里我们先介绍POW的工作原理,为了便于阐述,使用hash(...)表示所有的哈希函数,在不同的共识算法中的整数范围是不一样的,例如比特币中整数的范围是\([0,2^{256}-1]\),为了便于描述我们使用\([0,M]\)表示整数范围。

POW公式:

\[ hash(B) \leq M \div D \qquad\qquad\qquad\qquad\qquad (1) \]

其中:

  • \(D \in [1,M]\)表示目标难度,难度越高需要查找的次数也就越多

  • B表示nonce,这只能通过暴力搜索的方式来寻找合适的值

在POW算法中,所有矿工看到的D都是相同的,矿工唯一能改变的就是B值,所有矿工通过不断的寻找合适的nonce来满足上面的不等式。

在POS算法中,需要对上面不等式(1)做一点修改,假设有一个矿工账户为K,账户K在系统中的保证金余额为bal(K),那么我们可以通过以下不等式来定义POS算法

POS公式:

\[ hash(B_{prev},K) \leq S \ast Bal(K) \ast M \div D \qquad (2) \]

其中:

  • \(B_{prev}\) 区块中的一个字段(生成签名),矿工使用生成签名字段与矿工的地址做hash运算生成一个随机数,具体过程在下文中有详细解释。

  • S 父区块到当前区块之间的时间差

  • Bal(K) 矿工K拥有的保证金余额

与(1)不同,矿工唯一可以改变的变量是不等式(2)右侧的时间戳S,因为矿工地址中的保证金被系统锁定。随着时间的流失不等式的右边的值会越来越大,不等式右边的增长幅度与矿工的保证金大小成正比,所以在未来的某一刻一定会到达满足不等式(2)成立的条件。从这个过程中可以看出,在POS中没有涉及到昂贵的计算,矿工的出块速度与其拥有的保证金大小成正相关。

\(B_{prev}\) 作用与生成方法

在POW算法中所有矿工都解的是同一道题目,即如何使不等式(1)成立,在POS算法中我们需要满足之前所说的两个条件:

  1. 矿工被选中的概率,与矿工所持有的保证金数额成正比
  2. 在算法选择过程中包含一定程度的概率,以避免出现富有的矿工总是被选中生成区块,持续获得的奖励,富人越来越富

第一个条件好满足,从不等式(2)中就可以看出,矿工持有的保证金额度越高不等式右边的增长幅度就越快。为了满足第二个条件,我们引入了\(B_{prev}\)生成签名,生成签名可以看作是一个不可预测的随机数,它为了不等式(2)的左边,这意味着每一个矿工所需要解决的题目是不相同的,这样就可以避免富有的矿工总是被选中。下面是\(B_{prev}\)的生成过程:

  1. 在区块头中有一个生成签名的字段\(B_{prev}\)
  2. 将当前矿工的地址与父区块的\(B_{prev}\)做hash运算,可以看出每一个矿工得到的值都是不一样的。
  3. 将运算后的结果取前八个字节作为不等式(2)左边的值

公式简化

现在我们将不等式(2)做一点简化,IPOS中会在创始块中设置一个字段BaseTarget(基础目标),这个BaseTarget就相当于POW算法中的难度,在区块链系统中所有的节点都是可以自由加入、退出的,所以我们需要根据全网中的现有算力来调整难度,目的是维持出块速度保持稳定。

baseTarget公式:

\[ T_b=M \div D \]

一旦BaseTarget初始化后,之后就会针对BaseTarget进行调整了,具体调整方法在下文中有详细的解释。

相应的对不等式(2)右边进行相应的替代,不等式(2)右边:

\[ {T_k}={T_b} \times {S} \times {B_k} \]

其中:

  • \(T_k\)是当前矿工计算后的值,这个值会随着时间增加而增长

在上文中解释了IPOS中的随机数生成规则,同样这里使用\(H_k\)来替代不等式(2)左边的部分,不等式(2) 左边

\[ H_k = hash(B_{prev},K)[0:8] \]

新的不等式:

\[ H_k \leq T_b \times S \times B_k \qquad\qquad\qquad (3) \]

不等式(3)就是经过简化后的公式,上面提到过为了问题出块速度需要根据全网中的算力,对BaseTarget进行相关的调整,以下就是BaseTarget调整的公式。

BaseTarget 调整公式:

\[ T_b= \begin{cases} T_p \ast \frac {min(S,R_{max})}{15} & {S > 15} \\ T_p - T_p \ast \gamma \ast \frac {10 - max(S,R_{min})}{15} & {S \leq 15} \end{cases} \]

其中:

  • \(R_{max}\)=22 当区块时间大于15秒时,目标降低的最大比率

  • \(R_{min}\)=8 当块时间小于15秒时,目标增加的最小比率

  • \(\gamma\)=0.64

  • S 是最近3个区块的平均时间,目前保证出块时间稳定在15秒左右

  • \(T_p\) 父区块的baseTarget

  • \(T_b\) 当前账户计算出的baseTarget

攻击

零成本攻击(Nothing at Stake)

在一个零成本攻击中,矿工试图在block的每个分支上都继续创建block,因为这个行为几乎对攻击者毫无成本;另外,忽略任何一个分支都可能会导致丢失奖励,一旦某一个分支因为最大的累计难度成为正式的区块链;

现在这类攻击只是在理论上可能发生,并不实际;Ionchain网络不会经历长的block分支,低区块收益也无法提供非常强的利益刺激;进一步讲,为了很小的利益而影响网络的安全和信任是得不偿失的。

作为ionchain发展路线图中的一部分,一个叫做“经济集合”概念的特性可以针对这种攻击提供保护,它通过强制要求交易创建时包含一个之前block的hash值来探测网络中非正常的行为并给予处罚(暂时失去挖矿能力)

历史攻击(History Attacks)

在一个历史攻击中,某个人获得了一大笔货币,并出售,然后试图从交易前创建一个成功的分支替换区块链数据;如果失败了,对攻击者不会有任何损失,因为货币已经成功出售了;如果攻击成功,那么攻击者又拿回了他们已经出售的货币。这种攻击的一个极端例子就是攻击者需要获取账户的私钥,然后从创世块开始构建一个成功分支;

在ionchain中,一般的历史攻击都会失败,因为所有可以用来挖矿的权益都需要停留区块达到5769个(一天的时间),这就限制了攻击者,从时间框架上无法实现成功的攻击。

实现

算法的具体实现可以参考github上的开源项目ionchain-core