内置权益证明加密货币 第1部分: 基本结构
(注:本文为ConsensusResearch系列文章中第一篇的翻译。ConsensusResearch是一个PoS模型的独立研究组织,主要由数学博士andruiman和计算机科学博士kushti(Alexander Chepurnoy, http://chepurnoy.org, 也是Nxt核心开发人员之一)组成。ConsensusResearch论坛:https://nxtforum.org/consensus-research/ )
https://github.com/xiongzm/articles-papers/blob/master/articles/inside-pos-1.md
内置权益证明加密货币 第1部分: 基本结构
前言
纯权益证明(PoS)机制和混合权益证明机制加密货币目前正处于上升的趋势之中。以最著名的纯POS机制的加密货币Nxt为例,目前Nxt已经有几十个分叉版本(其中一些非常有前景);Ethereum团队也在探索混合PoS/PoW机制挖矿原理,还有很多PoS型加密货币。与此同时,在概念方面也存在很多忧虑,没有足够好的正式形式说明。比如,有名的最为不幸的 “无风险”(Nothing at Stake)攻击至今仍然没有很好的描述和说明。可怕的是不论权益证明好的方面还是不好的方面,目前其背后都没有形成良好的模型和形式化的描述。这一系列文章的挑战就是在这方面取得了一些进展。
前提条件
我假设您已经了解比特币和工作证明挖矿的一些简单常识。最好还有基本的编码技术以理解一些代码片段。Haskell编程语言(Haskell知识不是必须的)在文中被用来进行代码片段描述。我们将从尽可能简单的模型开始。我偏向于从最简单的事情逐步深入到更难一点的问题,而不是从一开始就进入最复杂的情况。
时间
维基百科将时间定义为“一种量度,事件可以通过过去,经由现在到达未来而可以排序,也是事件持续过程以及事件之间的间隔的一种测量”。在分布式环境中,因为时钟的同步以及事件的排序等等问题,时间的处理是一件很头痛的事情。幸运的是基于区块链的网络使得一些问题更加容易。因此,我们的模型可以更加简易:我们假设系统中所有时钟全部完美同步!即便如此,因为区块链网络的特性,在模型质量方面我们也不会损失太多。稍后我们将引入局部时间。
在我们的方法中,时间定义为以秒为单位,自创世块后经历的秒数,因此我们第一个对象定义相当简单:
type Timestamp = Integer
交易模型
比特币类模型中交易具有与其他交易输出相关联的交易输入部分,和它自己的输出(可能没有花费掉),与此不同,我们将从更简单的情况开始。首先,我们引入账户对象:
data Account =
Account {
balance :: Integer,
publicKey :: ByteString,
isForging :: Bool
}
账户中具有明确定义的账户余额。相比于真实的加密货币,这里有很多简化的东西,尤其是:
我们这里没有地址。在真实货币中,地址是hash(公钥), 然而我们使用公钥本身作为地址。
我们甚至不使用私钥!在交易签名中需要使用私钥,这不是我们现在研究考虑的范围。
描述完时间和账户对象后,我们可以对交易进行如下的定义:
data Transaction =
Transaction {
sender :: Account,
recipient :: Account,
amount :: Integer,
fee :: Integer,
txTimestamp :: Timestamp
}
当然,现在离实际应用还差得很远。上面定义的交易中没有id, 甚至没有签名,因此任何人都可以很容易的印钱。
铸币
在权益证明型加密货币中没有第三方矿工,然而,股东可以是区块生成者。与工作证明型货币中的挖矿相对应的,我们则使用铸币。两者意义相当,但是:铸币是区块生成的一个过程。还记得上述的账户定义吗?isForging数据域表示账户是否正在参与铸币。
区块链
我们知道在每种加密货币中交易被打包进入区块中。从下面的区块定义开始,权益证明的本质开始在我们模型中显现:
data Block =
Block {
transactions :: [Transaction],
generator :: Account,
blockTimestamp :: Timestamp
baseTarget :: Integer,
generationSignature :: ByteString
}
其中transactions和blockTimestamp数据域显而易见。generator是生成这个区块的账户。baseTarget和generationSignature数据域与铸币算法相关,我们将在本系列文章的下一章中进行解释。
区块链则是由区块组成的序列:
data BlockChain = BlockChain { blocks :: [Block] }
有效余额
在权益证明中生成区块的概率依赖于账户的余额。在Nxt这一类加密货币中,其概率则是有效余额的函数。比如,在Nxt中,账户的有效余额是自上一个区块之前1440个区块时的余额减去这1440个区块区间的所有花费,再加上其他账户授权给该账户铸币的额度。我们可以有如下简单的定义:
effectiveBalance :: Account -> Integer
effectiveBalance acc = balance acc
因此我们的模型中有效余额就仅仅只是当前的余额。
网络
到目前为止我们还没有谈到点对点p2p网络。网络中第一个需要定义的对象是节点:
data Node =
Node {
nodeChain :: BlockChain,
unconfirmedTxs :: [Transaction],
account :: Account
}
同样,我们进行了一些简化:
* 每个节点仅有一个区块链(这一点对于目前Nxt的参考软件实现的确是事实)
* 每个节点只有一个账户
接下来,定义连接(Connection)对象为节点的一个二元组:
type Connection = (Node, Node)
我们现在可以定义我们模型中最大的类型,系统:
data System =
System {
nodes :: [Node],
connections :: [Connection],
accounts :: [Account]
}
在权益证明型货币中通常所有的货币都是在创世块中被“印”出来的。Nxt系统中在创世块中设置的余额为10亿:
systemBalance :: Integer
systemBalance = 1000000000
分叉
和工作证明型加密货币一样,在权益证明型加密货币中也可能发生分叉。如何定义分叉呢?区块链存储在节点中,而系统有一系列的节点([Node]),因此从系统中可以提取出带有签名的区块树(具体实现在此忽略)。
blockTree :: System -> BlockTree
其中BlockTree仅仅是一系列区块链的别名:type BlockTree = [BlockChain]
为什么将一个列表称之为树呢?所有的区块链都有一些共同的前缀(至少存在共同的创世块),因此事实上我们正在处理的是树结构。然而,在系统的类型方面没有强制使用树结构,这肯定不是一个最好的设计,但是为简单起见,我们在此就这样。
性能分析
如何采用Haskell代码来帮助我们进行形式模型分析?让我们从Gavin Wood's Ethereum YellowPaper 中给出的一个属性开始:
正则区块链是从根通过区块树到叶子的一个路径。为了确定路径而达成共识,概念上我们认定为拥有最多计算量的路径,或者说是最重的路径。
正则区块链应该通过一个具有签名的函数来定义:
canonicalBlockchain :: System -> Maybe BlockChain
(同样,目前没有具体的实现)。也许区块链BlockChain可以仅仅是blockchain(因此已定义了),或者是没有任何东西(意味着没有定义) 因此,如果函数结果是定义了一个具有正则区块链的系统,那么我们可以强制更严格的条件,比如之前一段时间的正则区块链应该是当前正则区块链的前缀。
有如下两种方式来给出关于性能的结论:
1. 我们可以做出可执行的铸币算法模型,然后收集函数结果的统计信息。
2. 我们可以将我们的Haskell模型翻译成具有支持Haskell类似的语言(比如Coq),然后根据Curry–Howard correspondence,就可以形成定理并且证明模型属性。
以上两种方法在接下来的一章中都将展示出来。
结论及进一步的工作
通过最简单的函数给出了我们模型中的数据结构(Timestamp, Account, Transaction, Block, BlockChain, Node, Connection, System, BlockTree)。下一章中将定义铸币算法函数,然后将提供可执行的程序模拟和形式分析。
微信掃描關注公眾號,及時掌握新動向
2.本文版權歸屬原作所有,僅代表作者本人觀點,不代表比特範的觀點或立場
2.本文版權歸屬原作所有,僅代表作者本人觀點,不代表比特範的觀點或立場