目前有以太网协议的8个实现:
这些实现的区别在于:
对于企业用例,性能可能非常重要。 在对以太坊客户进行基准测试方面做了一些努力,请参阅:
https://github.com/ethereum/wiki/wiki/Benchmarks
但是,对所有可能具有高性能的客户端(C ++,Go,Haskell,Java,Parity)的一套全面的基准测试将是一项非常有用的任务。 关于许可,Go是LGPL许可的,C ++是GPL许可的,但是有一种努力(结果仍然不确定)将其重新许可给Apache,Java是麻省理工学院,而Parity是GPL。
Ethereum节点必须支持的配置文件有一个非正式标准,它描述了网络参数。 目标是允许节点轻松连接到测试网络,专用网络,并从长远来看,指定具有不同属性的替代网络,包括一致性算法,P2P网络协议,初始状态和协议规则。 这里描述了标准:
https://github.com/ethereum/wiki/wiki/Ethereum-Chain-Spec-Format
企业以太坊版应尊重标准的超集,以便以正确的配置设置启动的节点将充当以太坊公共链节点(但有更多API和其他功能对企业用途有用),但节点以不同的方式启动设置将使用PBFT参与给定的联盟链网络,或者使用不同虚拟机的测试网络,或者比公共链更早地结合新的可扩展性功能的网络等。
目前,以太坊客户支持工作共识的证明。 需要以这样一种方式模块化共识算法,即可以使用股权证明(Casper)以及私有链特定共识算法,可能的初始目标是PBFT和DPOS(基本上是一轮)罗宾一致算法)。 第一步是准确确定共识算法“类”的“接口”应该是什么样子。
界面的可能草图如下:
submitTransaction(tx)
:向参与节点提交事务。 节点将尝试将其包含在块中,或者对其进行投票,或者在一致性算法中执行等效操作。sendMessage(msg, node_id)
:向另一个节点发送消息。broadcastMessage(msg)
:广播消息。getMostRecent(conf_level)
:获取满足给定确认级别的最新块。 在工作证明或DPOS中, conf_level
将表示确认的数量,因此它将返回链中的第n个最后一个块; 在PBFT确认是二进制(即最终确认是即时的)所以它总是返回最近确认的块。请注意,公共链共识还需要激励模型,即。 奖励表现良好并可能惩罚表现不佳的参与者的共识参与者的方法。 我们通过提供两个选项来抽象:
finalize
,它对状态进行修改并可以使用块作为输入。initialize
,这会对状态进行修改并可以使用块作为输入。请注意, finalize
或initialize
可能只是调用一些标准契约,并将块头作为数据; 以太坊公共连锁计划长期采用这种方法。 在财团链中,没有必要使用这些功能来激励; 但是,它们可能对其他目的有用(例如,自动运行预定的操作)。 因此,由于这些操作的效用并不与共识激励严格相关,因此不应将它们视为共识界面的一部分; 相反,它们应被视为交易处理规则。
在私有链环境中,有几种最常用的共识算法:
PBFT和DPOS(纯粹作为一种共识算法,不包括某类令牌持有者对代表投票的能力)各有各的优缺点。 特别:
Casper旨在作为一种加密经济算法,任何人都可以通过存钱来成为验证者。 但是,只需指定固定的验证器集,就可以将其重新用于许可的上下文。 一旦Casper在主要的以太坊客户端实施,这种方法值得探索。
在需要特定安全属性的某些情况下,可能需要提供权威证明,并且以太坊的技术更多地用于提供确定性和可验证的执行和审计属性,而不是传统意义上的分散。 因此,实现所有这三个并使每个用户可以选择使用哪个给定应用程序是有意义的。
注意 :有一种常见的误解,即不同的算法具有广泛不同的事务处理能力,例如。 DPOS可以处理100 tx /秒,而PBFT可以处理1000 tx / sec等。而在未来的分片区块链的情况下,这可能是真的,在区块链的上下文中,每个节点处理每个事务,但事实并非如此; 无论使用何种一致性算法,处理每个事务都需要相同数量的计算工作量,尽管可能存在小差异,因为某些算法需要在短程分叉的情况下重新计算事务,有些算法可以更安全地允许事务处理链中性能的差异通常几乎完全是由于协议和实现的差异,而不是共识算法(公共链容量往往低得多的重要例外)他们的额外经济限制,更小的节点大小和集中化问题)。
在以太坊协议开发中,主要的重要哲学之一是抽象概念:协议本身应尽可能简单,并尽可能在合同代码中实现,而不是通过硬协议规则实现。 抽象目标包括:
抽象的目的如下:
EES可能希望提前实现其中一些抽象功能。
以太坊目前的P2P网络是Kademlia架构,详情如下:
专用链可能希望使用相同的网络代码(但在配置文件中设置了不同的网络ID),或者使用其他类型的网络; 最可能的替代方案是每个节点直接连接到每个其他节点的设计(非常可行,并且在具有少于20个节点的网络中可能是最佳的)。 此外,还可以选择定制在网络或更低级别进行的连接(例如,所有节点是否应位于同一子网中?如果它们在物理上彼此靠近,那么光纤连接是否最佳?); 许多细节很大程度上超出了EES代码库的范围,但代码库应该确保它在许多常见的预期配置下运行良好。
有关可用方法的更详细说明,请参阅https://blog.ethereum.org/2016/01/15/privacy-on-the-blockchain/ 。
目前,以太坊代码库支持一组基本API,用于查询区块链,查询合同状态,过滤日志,发送交易等。进行更复杂查询的主要方式(例如,在特定令牌中返回特定帐户的余额)在区块链上发布,在区块链订单簿上返回要约的要价等,是通过“虚拟交易”的概念。 本质上,这个想法是客户端可以假装在本地执行一个事务,这会调用一个返回值的契约函数。 然后API将(可能同步)返回值。
但是,可能需要更多高级API,特别是在不仅需要访问当前状态而且还需要访问先前状态,获取有关事务的信息以及更高级的区块链分析形式的用例时; 此外,API还有与API格式兼容的空间,用户已经熟悉并期望这些API格式。
可能非常有用的特定API类是能够对区块链进行SQL和类似查询。 这方面有一些现有项目,请参阅:
然而,在使这些系统最有效并且广泛适用于许多用例方面仍有许多工作要做。
以太坊中的用户界面属于广泛类别,包括:
验证以太坊中的块的过程目前包含以下特别是计算密集型操作:
已经进行了一些基准测试,表明单个以太坊节点每秒能够进行大约1000-2000次交易,并且在给定当前软件的情况下,小型联盟网络每秒能够进行几百次交易。 这些限制是由于(1)带宽限制和(2)计算限制的组合而产生的。
在单笔交易中,我们可以期待:
以太坊虚拟机是一种独特的架构,针对以下属性进行了优化:
重要提示 :“气体”和“以太”不是一回事。 气体是一种机制,允许EVM内部的计算被确定性地计量,即。 合同以确定性地限制对某些固定数量的计算步骤的调用。 以太是支付交易费用的一种方式,预计交易费用与燃气消耗量成正比。 以太币的比特币模拟是BTC,比特币模拟的气体是事务在一个块中占用的字节数; 在以太坊中,单独测量字节是不够的,因为你还需要测量计算,因此需要测量气体的概念。 在私人链上,你不需要用乙醚来支付天然气; 您可以提出备用规则集,例如,简单地要求每个事务的最大气体限制为100万。
请注意,原始EVM 不是为高性能计算而设计的。 当创建EVM 1.0规范时,关于区块链脚本内部可以完成的工作的大多数想法都在50行代码之下,包括“if ... then”逻辑和基本算法,并且在这种环境中可以做出强有力的案例EVM执行中即使100倍的低效率也不会对总事务处理时间产生显着影响,因为大量的事务处理负载以验证椭圆曲线签名的形式出现(需要循环通过椭圆曲线添加超过1000次,其中每次添加本身包含许多256位操作)。
然而,最近我们已经意识到在EVM中存在对高性能计算的非常大的需求,特别是为了实现更复杂的密码术(例如,环签名,部分同态加密,其他种类的椭圆曲线,灯管签名); 因此,我们意识到我们目前在EVM方面的工作还不够。 我们目前有两种方法可以同时解决这个问题:
WebAssembly计划是开发一个“转换编译器”,它采用WebAssembly代码并将其转换为WebAssembly代码,在每个分支点跟踪其自身的“气体消耗”,并在剩余气体低于零时自动停止。 选择WebAssembly是因为设计要求在许多情况下类似于以太坊,例如。 用户将在他们的浏览器中运行不受信任的WebAssembly代码,代码大小也需要很小,因为代码是实时下载的,并且已经存在多个实现以及它们之间的兼容性目标。 但是,WebAssembly缺乏气体计数的概念,并且转换编译器将修复该问题,同时允许使用未修改的WebAssembly实现来执行实际操作。 它还将禁止浮点数和潜在的非确定性的其他来源。 请注意,无法保证WebAsssembly将成为主要的公共链VM,但进一步开发它并使其成为私人链使用的候选者可能是有意义的。
领先的EVM改进建议是添加一组256个64位寄存器,以及专门用于处理这些寄存器的操作码。 这允许以接近本机速度处理仅需要64位精度的操作。 如果实施此提议,则可以通过在升级的EVM和WASM之间进行双向编译来将其与WebAssembly路由合并,从而使WASM成为此升级的EVM的实现之一。
“预编译合同”是在本机代码中实现的操作,可以通过在预先指定的地址调用合同来访问。 目前的预编译包括:
0x000....0001
)0x000....0002
)0x000....0002
)在许多行业用例中,目标是将现有的库集成到财务计算(例如OpenGamma )或不同形式的密码术以符合行业或国家标准,或加速复杂的业务逻辑(例如订单簿)这需要以非常高的速度运行。 这样做的应用程序可能希望指定自己的预编译。 我们建议私有链预编译采用0x000....000400
到0x000....0fffff
(即1024到1048575)范围内的地址,以避免与可能的未来公共链功能发生冲突。
2016年9月和10月,针对各种以太坊实施和以太坊协议进行了一系列拒绝服务攻击。 其中很大一部分利用了Go实现中的“二次内存消耗”漏洞,其中客户端在每次调用时都低效地复制了潜在的大量缓存状态,从而导致处理速度非常慢或由于客户端耗尽内存。 此外,由于读取状态的操作码(例如EXTCODECOPY,BALANCE,CALL)定价不正确,并且因为SUICIDE操作码中的设计缺陷提供了一种非常便宜地膨胀状态的方法,因此出现了大量攻击。空账号。 这些问题在10月17日的硬盘中得到了解决。
截至撰写本文时,主要的剩余拒绝服务问题是客户端进行O(log(n))数据库读取以读取状态条目,以及当状态太大而无法容纳到内存中时(由于以前的攻击不再可能,状态大大增加之后的情况)这使得处理状态读取操作码变慢。
有两种方法可以解决此问题。 一种是实现一个缓存,允许在O(1)数据库读取中读取状态条目(可能是在最佳实现中读取的单个数据库); 这解决了问题,但仍然留下了事务处理能力的下限。 单个SSD读取需要100微秒 ; 因此,leveldb读取可能需要200-400微秒,创建每秒约2500次读取的上限,或每秒约500次事务。 离线节点能够同步的要求进一步降低了这一点。 由于需要更新状态树(添加O(log(n))开销),写入时间可长达10倍,但这可以在后台进程中完成。 因此,将状态存储在SSD中使得难以有效地处理超过~100tx / sec。
另一种方法是实施措施,以确保国家的总规模保持足够小,以适应记忆。 在公共链中,这需要为账户收取“租金”(见这里 , 这里 , 这里和这里的建议); 在联盟链中,这只需要一个良好的垃圾收集策略,并在需要时为验证器节点添加更多RAM。
Merkle树(有时也称为“Merkle Patricia树”,“Patricia trie”,“Merkle Patricia trie”或“trie”)是以太坊协议的重要组成部分,特别是在公共链中提供了大量价值。 树的功能(详见此处 , 此处和此处有更详细的说明)是提供一个加密认证的数据结构,存储整个状态(即账户余额,合同存储,随机数等); 每个32字节的根哈希映射唯一(假设SHA3的加密安全性)映射到特定状态,其大小可能是千兆字节。
这允许以下好处:
虽然在撰写本文时还没有人提出过这样的产品,但可以想象一个运行其业务逻辑单节点私有链的集中式服务,它使用Merkle树的独立光可验证功能来为其用户提供服务。具有很强的可审计性和真实性保证。 例如,交换机可以承诺提供允许任何用户在任何时间下载与其账户数据相对应的Merkle分支的API,并且还在每次操作之后发布其内部状态的根散列。 如果用户看到他们的余额意外减少并且想要确保没有渎职行为,他们可以使用二进制搜索算法来确定他们的余额减少了哪个操作,然后下载该操作的执行证明并验证这项行动是合法的。 因此,Merkle树在许多财团和私人连锁应用以及公共链中都有益处。
然而,Merkle树也带来了效率成本; 因此,在那些不需要它的应用程序中,最佳解决方案可能是简单地删除Merkle树,而是直接将状态存储在数据库中,因此三个状态更改将对应于三个数据库操作。 也就是说,重要的是不要过快地跳到这个结论,因为有几种方法可以优化Merkle树而不必完全删除它。 这包括:
最优策略是追求三条路径(即,添加一个选项来实例化一个没有Merkle树的以太坊链,探索协议hardforking选项,以使Merkle树更有效,并探索代码的软件级改进)。
当前以太坊模型的一个常见批评(参见http://www.multichain.com/blog/2015/11/smart-contracts-slow-blockchains/ )是因为它在交易可以产生的影响中如此开放有,并行验证交易是困难的。 删除中间状态根计算后,可以使用的一种启发式策略的工作方式如下:
k
事务t[1] ... t[k]
。 在当前状态之上处理所有并行线程(如果它读取已经写入的数据,则为每个线程提供一个单独的缓存),并在执行期间跟踪每个线程读取的地址集和每个线程的地址集。线程写道。(i, j)
是最早的碰撞(按j
排序),其中(i) i < j
,(ii) t[j]
读取事务t[i]
写的东西。t[1] ... t[j-1]
包含的状态更新。 回到第1步,从t[j]
作为第一个交易。在一般情况下,这可能会实现大幅加速,但这并不能保证; 此外,依赖于该方案可能会使您的应用程序容易受到拒绝服务攻击,其中攻击者发送大量故意无法并行的事务以防止任何并行执行发生 - 在最坏的情况下,性能将不会更好比单线程的情况。 上面详述的Merkle树变化将主要允许Merkle树计算的并行化,并且椭圆曲线签名验证在现有客户端中预先计算并且可以已经并行化,但这是目前我们可以做到的。
Ethereum 2.0和3.0的长期路线图是实现“分片”的概念,其中状态被分解为多个部分,每个部分由一部分节点存储,并且影响状态的不同部分的事务被处理由不同的节点并行。 本路线图的一部分是允许事务静态声明一个地址范围,在这个地址范围内,它们可以进行同步操作,因此在不保持整个状态的情况下处理这些事务实际上是可行的。 超出规定地址范围的呼叫将返回OUT_OF_RANGE
错误,类似于有效的OUT_OF_GAS
错误。
公共区块链分片是一项复杂的技术挑战,因为除了涉及数据库分片的常见问题之外,还存在加密经济挑战,因为公共区块链的特定形式的分布式计算具有每个节点不信任任何其他节点的独特属性,所以另一个节点简单地说它处理和验证了一组给定的交易是不够的。 但是,就私人和财团链而言,不需要走这么远; 相反,它只需要实现与事务可并行性有关的分片路线图的一部分(即指定地址范围的事务),然后通过要求网络中的每个节点简单地添加更多CPU核心和更多带宽来实现可扩展性。
这种分片的一个挑战是在许多应用中需要进行多次操作,即需要交叉分片,即。具有分散在整个州的效果,使得具有窄地址范围的单个交易不能覆盖它。这些案例的解决方案是异步编程语言,允许将操作分成多个阶段。例如,从碎片A到碎片B的硬币转移将包括以下步骤:
有关如何完成此操作的详细信息,请参阅此演示文稿(视频)。
一个重要的高级任务是实际创建编程语言,以便轻松实现这些类型的异步跨分片操作。请注意,很多这项工作将同时为编程语言奠定基础,编程语言可编译为跨多个区块链的应用程序。
触及公共和财团链智能合同的智能合约编程的一个重要方面是安全性,包括防止良性开发人员错误,以及合同作者为了试图欺骗用户而包含的恶意攻击。关于公共以太坊区块链的合同编程错误的汇编列表可以在这里找到:
https://blog.ethereum.org/2016/06/19/thinking-smart-contract-security/
安全研究员Andrew Miller的旧论文可以在这里找到:
https://eprint.iacr.org/2015/460.pdf
关于安全合同编程技术的以太坊维基文档可以在这里找到:
https://github.com/ethereum/wiki/wiki/Safety
第一个链接还包括可以对EVM以及以太坊开发环境进行的可能的增量改进,以便最大限度地降低此类攻击的风险。另外,由于入射DAO在2016年6月一直存在,以便于更安全的合同开发了一些提议的电子信息产品的:EIP 114,116,117,118和119。对于财团链开发社区而言,在公共链生态系统之前实施以安全为重点的EIP可能并不明智,因为我们不希望通过为联盟链生态系统制定一套安全的合同编程实践来混淆开发人员,并且公共链生态系统(除非绝对不可避免,例如在公共链上,游戏理论问题更加不可避免)。
除了低级别的改进之外,还可以构建更高级别的工具,以提高合同编程生态系统的安全性。这些分为两大类:
请注意,必须注意这些工具如何与底层环境集成;例如,纯函数式语言经常被引用作为以太坊契约编程挑战的解决方案,但如果我们看看DAO盗窃的具体情况,我们可以看到它是由于“重新入侵”黑客而产生的,其中一个合同称为然后调用原始合同的不受信任的合同,即使您尝试在当前的EVM上实现纯函数式语言,您也会遇到这样的挑战:如果您需要再次签订合同,则很难确定子合同除非实现EVM级操作码,否则不会进行一些“不纯的”状态改变操作STATIC_CALL
。
一般来说,不可能有一种神奇的技术可以解决所有智能合约安全问题; 相反,我们将看到增量方法的组合,包括新语言,更好的分析工具,更好的开发工具,更好的标准和最佳实践以及对底层EVM的更改。应将更好的标准和最佳实践集成到开发工具中,以使程序员更容易适应; 区块链技术的很大一部分价值在于减少建立高信任系统的准入门槛,如果以前的入门门槛只能被多年专业开发人员教育的要求所取代,那么该技术的潜力可以说是显着的降低。
状态渠道是区块链技术的流行短期可扩展性,隐私和延迟解决方案。有关州渠道的一些信息可以在这里找到:
一些实现包括:
许多联盟链应用程序要求某些节点(例如,监管机构)具有特殊权限。可能的特权包括:
在某些情况下,这些特权最好在基础协议之上的层中实现; 例如,在新智能合约的发行受到严格限制的链中(或者甚至在整个链只有一个合约的情况下),可以将这些特征实现到合同本身的代码中。在隐私保护解决方案的情况下,监管机构能够查看明文状态只能在顶层进行,因为隐私保护解决方案本身将通过顶层构建。
在其他情况下,这些特权最好通过更改底层协议来实现。最简单的方法是引入一些新的操作码,例如。0xed = SSTORE_EXT
(设置外部帐户的存储),0xee = WITHDRAW
(从另一个帐户中排除ETH),0xef = SET_CODE
(设置另一个帐户的代码),并且只给一个地址使用这些操作码的特权(例如地址254)。这样一个“特权地址”是未来作为抽象路线图的一部分可能在以太坊实施的一个特征(在公共链中,只有系统级合同,如实施合同创建功能的假设合同,可以访问这个特权地址,因此不会被任何组织或个人用作“后门”,但在私人和财团链中,它可以作为特权机制使用。
一旦财团链启动,事后就不可避免地会有理由改变一致的参与者。 这包括:
处理这个有几种方法:
如果需要,共识抽象应该能够涵盖所有三种模式。如果(i)共识集存储在链内合同中并且一致性算法不提供即时终结性(例如DPOS),或者(ii)共识集存储在外部机制中,那么谨慎的做法是在达成共识集更改和更改变为活动时之间存在延迟。卡斯珀目前为公共链计划的股权协议证明的方法是将区块链时间分成12小时的“时期”,并使用在上一个时期开始时定义的验证集(即一个始终是在过去的12到24小时之间)作为当前区块的共识。
您可能希望使用外部机制的原因是为频繁脱机节点提供更高的安全保障。具体而言,特别是如果共识集很小,则存在以下风险:在一段时间内,大多数历史密钥将被泄露,并且如果攻击者获得这些密钥,则他们将能够创建替代链并且欺骗长 - 离线节点,这个链是合法的。使用外部机制来存储共识参与者会使这种情况发生得更加困难;虽然这种方法可能并不适合所有应用程序,但在许多情况下,联盟本身可能足够大,以至于50%的历史密钥折衷是不太可能的。
请注意,精心设计的设置甚至可以通过使用一致性算法来容忍外部机制的短期故障,该算法可以容忍感知共识机制中的小差异; 这也需要限制共识参与者可以改变的速度,并且规则如果机制不可用,则应该使用最新的可用共识集(尽管这是高度理论化的)。
另请参见:本文,其中显示了拜占庭容错一致性算法在验证器转换期间可以保持安全属性的一种方法。
https://github.com/ethereum/wiki/wiki/Consortium-Chain-Development