理解Serenity | Part I:抽象

链接:https://blog.ethereum.org/2015/12/24/understanding-serenity-part-i-abstraction/

翻译链接:https://ethfans.org/jan/articles/37

以太坊开启开发线路图中最大的里程碑:Serenity

Serenity有两大特性,一个是Casper,基于保证金的PoS权益算法,在此提到过(https://blog.ethereum.org/2015/07/05/on-abstraction/)。此外,我们也在探索增加一个“脚手架”功能的实现来支持随着时间变化平滑的部署扩展性合约(https://blog.ethereum.org/2015/04/05/blockchain-scalability-chain-fibers-redux/),与此同时完全解除(http://www.multichain.com/blog/2015/11/smart-contracts-slow-blockchains/)提到的并行性担忧——在私有链环境下,运行在多核服务器上的以太坊节点性能将会巨大的提升,甚至对公有链也有2-5倍的性能提升。在过去的几个月里,Casper的研究和可扩展性和抽象的形式化(例如EIP 101:https://github.com/ethereum/EIPs/issues/28)在我自己,Vlad Zamfir,Lucius Greg Meredith和其他几个人之间的快速发展,现在我很高兴地宣布 Serenity的第一个概念证明版本,虽然只是一种非常有限的形式,仅适用于测试,现在已经可以使用了。

ethereum目录下运行python test.py就可以把概念原型跑起来(别忘了先从https://github.com/ethereum/serpentSerpent下载和安装最新的 develop分支),如果看到这样的输出就对了:

vub@vub-ThinkPad-X250 15:01:03 serenity/ethereum: python test.py
REVERTING 940534 gas from account 0x0000000000000000000000000000000000000000 to account 0x98c78be58d729dcdc3de9efb3428820990e4e3bf with data 0x
Warning (file "casper.se.py", line 74, char 0): Warning: function return type inconsistent!
Running with 13 maximum nodes
Warning (file "casper.se.py", line 74, char 0): Warning: function return type inconsistent!
Warning (file "casper.se.py", line 74, char 0): Warning: function return type inconsistent!
Length of validation code: 57
Length of account code: 0
Joined with index 0
Length of validation code: 57
Length of account code: 0
Joined with index 1
Length of validation code: 57

这个测试模拟了运行在Casper+Serenity下协议下每5秒出一个块,这个仿真很接近于客户端可以处理的上限了,不过要注意这是以python实现,C++, go语言实现的仿真可能会有更好的表现,其次这是所有13个节点都运行在一台服务器上,所以在一个“正常(normal)”环境下python版本的仿真可以处理大约169个节点 (尽管如此,我们希望共识算法所需要的开销远远下小于100%的CPU占用),所以这并不意味着可以其他Casper运行在数以千计的节点上!如果你的电脑性能较低,尝试用python test.py 10运行10个节点的仿真。当然,我们仍然在继续研究提供Casper的效率,这些问题将来会得到解决,虽然可能会以减慢收敛到最终确认的速度为代价。network.py模拟了一个基本的p2p网络接口,未来会把它替换成运行在真实网络上的真实计算机。

程序代码被分割为几个主要文件:

serenity_blocks.py  描述了block类,state类,区块以及交易级别的状态转移函数(比之前的版本简单一倍)
serenity_transactions.py 描述transaction的代码(比之前简单一倍)
casper.se.py  Casper合约的serpent代码,用来激励正确的打赌
bet.py Casper赌博逻辑和完整的客户端实现
ecdsa_accounts.py 账户相关代码,让你可在Serenity环境下模拟当前的账户验证逻辑
test.py 测试脚本
config.py 配置参数
vm.py 虚拟机(fastvm.py是个更快的实现)
network.py 网络仿真器

在本文中仅讨论抽象特性,因此关键的是serenity.py,ecdsa_accounts.py,senenity_transactions.py。在下一篇讨论Casper的文章中,casper.se.pybet.py将是关注点。

抽象和账户

目前以太坊有两种类型的账户:外部拥有的账户由私钥控制,合约账户由代码控制;对于外部控制的账户,我们指定了一种特别的数字签名算法(secp256k1椭圆曲线签名)和一个特别的序列号(nonce)体系,要求每一个交易必须包含比前一个比前一个交易序号大1的数字,目的是防止重放攻击。我们为提高抽象而做的主要改动是:不再有两种不同类型的账户而是统一为一种合约账户。将会存在一个特殊的“入口(end point)”账户,0x0000000000000000000000000000000000000000,任何人都可以从这个账户发起交易。因而,不再是签名+nonce的账户验证逻辑,而是用户必须用合约来保护他们自己的账户。

最简单有效的此类合约可能要数椭圆曲线签名(ECDSA)验证合约,它可以提供和现在完全样的功能:只有拥有有效签名和序号的交易 ,而且序号在成功交易后会加1,这合约的代码如下:

# We assume that data takes the following schema:
# bytes 0-31: v (ECDSA sig)
# bytes 32-63: r (ECDSA sig)
# bytes 64-95: s (ECDSA sig)
# bytes 96-127: sequence number (formerly called "nonce")
# bytes 128-159: gasprice
# bytes 172-191: to
# bytes 192-223: value
# bytes 224+: data

#Get the hash for transaction signing
~mstore(0, ~txexecgas())
~calldatacopy(32, 96, ~calldatasize() - 96)
~mstore(0, ~sha3(0, ~calldatasize() - 64))
~calldatacopy(32, 0, 96)
# Call ECRECOVER contract to get the sender
~call(5000, 1, 0, 0, 128, 0, 32)
# Check sender correctness; exception if not
if ~mload(0) != 0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1:
    ~invalid()
# Sequece number operations
with minusone = ~sub(0, 1):
    with curseq = self.strorage[minusone]:
        #Check sequence number correctness, exception if not
        if ~calldataload(96) != curseq:
            ~invalid()
        #Increment sequence number
        self.storage[minusone] = curseq + 1
# Make the sub-call and discard output
with x = ~msize():
    ~call(msg.gas - 50000, ~calldataload(160), ~calldataload(192), 160, ~calldatasize() - 224, x, 1000)
    # Pay for gas
    ~mstore(0, ~calldataload(128))
    ~mstore(32,(~txexecgas() - msg.gas + 50000))
    ~call(12000, ETHER, 0, 0, 64, 0, 0)
    ~return(x, ~msize() - x)

这段代码就是用户账户的合约代码;用户如果要从自己的账户发送一个交易,他们会先从地址0发送一个交易到这个账户,交易数据会像上述所示那样包含ECDSA签名,序号,gas价格,目标地址,数额和真正的交易数据。合约代码会检查签名是否符合gas 限制和数据的签名,然后检查序号,如果两者都没有问题就把保存的序号加1,最后发送一条消息支付gas费用结束(注意,旷工可以静态分析账户的合约代码,可以拒绝处理合约最后没有支付gas费用的合约的交易)。

深度抽象的改进有一个重要的后果就是Serenity 引入了一个模型:系统中的所有交易(只要满足基本的格式)都是有效的。现阶段无效的交易在Serenity中将仅仅是没有作用(上例中的invalid是一个尚未使用的操作码,它会使程序执行立即退出)。这意味着交易被打包进区块不再是交易会被真正执行的保证,作为弥补,每一笔交易都会有一条收据记录(receipt entry),通过返回码指明它是否成功执行:0表示由于gas限制交易没有执行,1表示交易执行了但是出错,2表示交易成功执行。收据记录还可以提供更多的信息,例如交易的返回值(现在有自动日志记录)或者自己创建的日志。

这个改动最主要的好处是用户可以在账户策略这个领域自由的创新了。可能的方向包括:

  • Bitcoin-style multisig:比特币风格的签名,账户要求交易同时具有多个私钥的签名,而不是一次接收一个签名,然后把中间结果临时存放在区块链里。
  • Other elliptic curves,其他的椭圆曲线算法,包括ed25519
  • Better integration for more advanced crypto, 更好的集成先进的加密算法,例如环状签名(ring signature), 门限签名(threshold signature), 零知识证明等等。
  • More advanced sequece number scheme,更先进的序号方案,支持更高程度的并行化,让用户可以同时从一个账户发出多个交易,并且更快的把这些交易打包。想想传统的序号和位掩码(bitmask)如果结合会怎样。我们也可以通过各种机智的方法在有效性检查中利用时间戳或是区块的hash值。
  • UTXO-based token management 基于UTXO的代币管理,有些用户处于隐私的原因,不喜欢以太坊使用账户而不是比特币的“未使用的交易输出”(unspent transaction output, UTXO)模型来管理代币的所有权。现在你可以在以太坊中建立一个事实上基于UTXO的系统了,并且Serenity不再显式的特殊对待其中某一个。
  • Innovation in Payment schemes,支付方案的创新,对于某些dapp, “由合约支付费用”可能比“由使用者支付”更有用,使用者可能没有以太币。独特的dapp就可以实现这个支付模型了。如果矿工能对它的代码做静态分析并确信他们可以得到报酬,矿工就会接受这种交易(本质上,我们实现了Rookstock(https://www.rsk.co/)通过可选的支付方案来交易,但是是通过一种更抽象和灵活的方法)。
  • Stronger integration for "ethereum alarm clock "-style applications-与“以太坊闹钟”之类的应用更好的集成,账户的检查代码不一定要检查签名,也可以检查Merkle proof,或者是其他账户的状态。

所有这些场景的提出,首要的目的是说明这样一个观点,通过抽象所有这些另外的机制都可以更加容易的实现,而不再需要创建“一个传输层”来把信息喂给以太坊默认的签名体系。当没有应用是特殊的时候,每个应用都特殊。

一个特别有意思的结果是:在Serenity的设计下,以太坊将具有可选的量子安全性。如果你害怕NSA秘密拥有一台量子计算机,想要把自己的账户变得更安全,你随时可以个人切换使用Lamport签名(https://bitcoinmagazine.com/articles/bitcoin-is-not-quantum-safe-and-how-we-can-fix-1375242150/)。转换到PoS机制进一步巩固了安全性,即使世界上只有NSA有量子计算机他们也不能利用这一点来实施51%攻击。在以太坊的协议层唯一剩下的密码学安全假设只有SHA3的抵御碰撞(collision-resistance)的性质了。

这些改变的另一个结果是,交易数据会变得更加简单。交易将会用四个字段取代现在的九个:目标地址,数据,初始gas和初始化代码。目标地址,数据和初始gas和现在一样,“初始化代码”是一个可选用于保存目标地址账户合约创建代码的字段。

需要这个机制的原因如下。目前以太坊有一个重要的性质,是允许往一个还不存在的账户转账。为了在区块链上创建一个合约接受以太币,你并不需要事先持有任何以太币。为了在Serenity中实现这个性质,我们让账户地址能事先从它的初始化代码中推导出来,通过公式sha3(creator + initcode) % 2**160。这里creator是创建这个合约的账户(默认是地址为0的账户),而initcode就是合约的初始化代码(这段代码的运行结果会成为账户合约的代码,正如现在的CREATE一样)。因此你可以在本地先生成这段初始化代码,计算它的地址,然后让其他人往这个地址转账。然后一旦你想要从这个地址发出第一笔交易,你可以在交易里面包含这段初始化代码,它就会在真正的交易执行之前,被自动执行并创建账户(这段逻辑的实现代码在这里https://github.com/ethereum/pyethereum/blob/42a448be003e07db18cd94159a61f3a361aff57e/ethereum/serenity_blocks.py#L253))。

抽象和区块

Serenity中将实现的另一个干净的分离是将区块(仅仅是一堆交易),状态(例如合约的存储区,代码和账户余额)和共识层完全分开。共识激励在合约内部实现,而如果你希望激励的话,共识级别的对象(例如PoW, 赌注)应该被包含在发往“共识激励管理合约”的交易中。

这应该会让你更容易用其它的共识算法 - Tendermint, HoneyBadgeBFTsubjective consensus甚至是普通的PoW - 替换掉Serenity代码中的Casper。我们非常欢迎这个方向的研究,并且希望能做到最大的灵活。

抽象和存储

目前,以太坊的系统的状态“state”数据实际上相当复杂,包括这些部分:

  • 余额,代码,nonce,账户的存储
  • Gas限制,难度,区块号,时间戳
  • 最后256块的hash值
  • 在执行区块代码内,需要保存交易索引,收据树(receipt tree, EVM中的一个概念)和当前消耗的gas

这些数据结构存在于很多地方,包括区块状态转移函数,状态树,区块头,前一个区块的头。在Serenity中,这些将会被大大简化;虽然许多数据仍然会存在,但他们会被转移到特护的合约中去;因此唯一的将会存在的状态将是一个“tree”,数学上可以看做是形如{address:{key:value}}.账户将会是一些树,账户代码将会被存放在键(key)为“”的地方(SSTORE不可修改),余额会存在于特别的“以太币合约”中,而序号将由每一个账户自己决定如何保存。数据树将会被移动存储区;他们将会被存储在一个内容在每个区块都会被覆盖的“日志合约”中。

这样代码实现中的状态对象可以极大的简化,现在只剩下一个两级的trie了。可扩展性的升级可能要求三级trie(分片ID,地址,主键),还没有得到确定,但是即使这样复杂度也远低于现在。

需要注意,把以太转移进一个合约管理并不是合约抽象的全部。事实上,一个有争议的看法是相对于现状这不是一个很大的进步,因为为了向前兼容那些和以太币相关的操作码(带value参数的CALLBALANCE等等)依然保留着。某种程度上说,这只是数据存放的一次重组。

未来的计划

在第二个概念原型中,我们计划让抽象更进一步。目前区块和交易级别的状态转移函数依然有相当的复杂性(例如更新数据,gas限制,交易索引,区块高度,状态根节点);我们的目标是为交易创建一个“入口”对象来处理所有这些每一个交易都需要的额外的“样板逻辑”,以及“块开始”和“块结束”的入口。理论上的终极目标是制定这样一个协议:仅包含一个入口并且状态转移函数只需要从零地址发送一条包含区块内容并把区块内容视作数据的消息给入口点即可。这样做的目的是尽可能的减少客户端实现的共识关键部分(consensus-critical client implementation)的大小,把尽可能多的逻辑推到以太坊自身上去。这样即使为了达到我们对交易速度和可扩展性的目标,我们需要采用一个接受分叉和一定的新复杂度的新的激进开发制度,也能够确保以太坊的多重客户端形态可以持续而无需额外开发工作和审计。

长期来看,我们打算再python上开发概念原型,Casper团队则共同改进协议的效率,并证明它的安全性和正确性;在某个时刻,

这个协议将成熟到足以处理一个公开的某种形式的测试网络,其上可能会有真实的价值,为人们找出Casper的漏洞提供激励,就像一条真正的链不可避免的遭受的那样。这只是第一步,不过是非常重要的一步,它标志着我们对于权益证明和深度抽象的研究终于从谈话,白板上的数学公式和博客文章变成了能工作的代码。

这个系列的下一篇文章将会讨论Serenity的另一个旗舰特性,Casper共识算法。

猜你喜欢

转载自blog.csdn.net/liudaoqiang_tj/article/details/81368088