主页 > imtoken安全下载地址 > 经典回顾 | 以太坊 1.0 的设计基础(上)

经典回顾 | 以太坊 1.0 的设计基础(上)

imtoken安全下载地址 2023-02-04 06:25:16

以太经典和以太坊算力差别_以太坊经典合约地址是多少_sitechainb.com 以太坊以太经典那个好

点击上方“统一时代”订阅!

unitimes.io

sitechainb.com 以太坊以太经典那个好_以太经典和以太坊算力差别_以太坊经典合约地址是多少

全球视野,独到见解

编者按:本文推荐与《》对比阅读,混读效果更佳。

尽管以太坊借鉴了很多在比特币等较早的加密货币中经过五年尝试和测试的想法,但以太坊也有许多地方不同于当前处理特定协议功能的通用方式。 此外,以太坊必须开发一种全新的经济方法来提供其他现有系统无法提供的功能。 本文档旨在详细说明在构建以太坊协议时做出的微妙的、被忽视的、在某些情况下有争议的决定,并揭示这些方法和潜在替代方案所涉及的风险。

01

原则

以太坊协议的设计过程遵循以下原则:

1. 三明治复杂度模型:我们认为以太坊的底层架构应该尽可能简单,以太坊的接口(包括面向开发者的高级编程语言和面向用户的用户界面)应该尽可能简单易懂. 如果复杂性是不可避免的,那么它应该放在协议的“中间层”。 这里的“中间层”不是核心共识的一部分,终端用户的高级语言编译器是看不到的以太坊经典合约地址是多少,包括参数序列化、反序列化脚本、存储数据结构模型、leveldb存储接口、wire协议(有线协议)等等。 然而,这种偏好并不是绝对的。

2. 自由:用户可以使用以太坊协议做任何事情,我们不应根据其目的性质选择支持或不支持某种类型的以太坊合约或交易。 这类似于“网络中立”概念背后的指导原则。 目前的比特币交易协议不遵循这一原则,这不鼓励用户将区块链用于“未标记的目的(如数据存储、元协议等)”,并且在某些情况下定义明确定义的准协议更改(对于例如,OP_RETURN 被限制为 40 个字节)以应对犯罪者以“未经授权”的方式使用区块链攻击应用程序的意图。 在以太坊中,我们强烈倾向于以大致对应于经济激励的方式设置交易费用,从而将打算阻止或阻碍区块链的用户的活动成本内部化(即 Pigovian 税收)。

以太经典和以太坊算力差别_以太坊经典合约地址是多少_sitechainb.com 以太坊以太经典那个好

3.泛化:在以太坊中,其协议特性和操作码中包含的概念应该尽可能低级,以便它们可以以任何方式组合,包括那些目前看起来无用但以后可能有用的组合。 这允许我们在不需要的时候剥离一些功能,这可以提高这些底层概念的效率。 遵循这一原则的一个例子是我们选择 LOG 操作码作为向(尤其是轻客户端)dapps 提供信息的一种方式,而不是像以前在内部提出的那样简单地记录所有交易和消息——“消息”这个概念实际上是一个集合多个概念,包括“函数调用”和“外部观察者感兴趣的事件”,我们认为有必要将两者分开。

4. 我们没有所谓的特性:泛化的必然结果是我们拒绝构建非常常见的高级用例作为协议的固有部分。 我们认为,如果人们真的想这样做,他们可以在合约中构建一个子协议(例如,由以太币支持的子货币、比特币/莱特币/狗狗币侧链等)。 这方面的一个例子是以太坊中没有类似比特币的“locktime”特性,因为这样的特性可以通过某种协议来模拟。 在这个协议中,用户发送“签名数据包”,这些数据包可以被送入专门处理此类数据包的合约中。 如果这些数据包在特定合约级别有效,则合约将执行相应的功能。

5. 非风险规避:如果一个可能引入高风险的变更能够提供非常可观的收益(比如一般状态转换、区块生成时间减少50倍、共识效率等),那么我们可以容忍这个风险。

这些原则对于以太坊的发展具有相当大的指导意义,但并不是绝对的。 在某些情况下,一些变化,甚至一些明显有益的变化,被推迟到后来的版本(例如在以太坊 1.1 中),因为我们想减少开发时间或不想同时尝试太多激进的事情。

02

区块链级别的协议

本节介绍以太坊对区块链协议所做的一系列更改,包括区块和交易的工作方式、数据的序列化和存储方式以及账户模型背后的机制。

03

为什么选择账户模型

在比特币及其衍生品中,用户余额数据存储在基于未花费交易输出(UTXO)的结构中:系统的全局状态由一组“未花费输出”(即“硬币”)组成。 这样一来,每一枚币都属于一个拥有者并具有价值,每笔交易在花费一枚或多枚币的同时创造一枚或多枚币,但这个过程必须遵守有效期限制:

以太坊经典合约地址是多少_sitechainb.com 以太坊以太经典那个好_以太经典和以太坊算力差别

每个引用的输入都必须有效且未花费

交易必须包含与每个输入相匹配的所有者签名

输入的总值必须等于或大于输出的总值

以太坊经典合约地址是多少_sitechainb.com 以太坊以太经典那个好_以太经典和以太坊算力差别

因此,在比特币系统中,用户的“余额”实际上是用户拥有的能够给出有效签名的私钥对应的所有币值的总和。

以太坊摒弃了这个方案,采用了一种更简单的方法:让状态存储一个账户列表(每个账户都有余额)和与以太坊相关的特定数据(代码和内部存储)。 如果交易发送方的账户有足够的余额来支付款项,则交易有效。 在这种情况下,发送方和接收方的账户将按照借贷记账方式进行价值转移。 如果接收者账户拥有代码,并且代码运行,其内部存储也可能会被更改,或者代码可能会向其他账户创建额外的消息,从而导致进一步的价值转移。

使用 UTXO 模型的好处是:

1. 更高的隐私性:如果用户每次收到交易都使用新地址,外人往往很难将这些账户相互关联起来。 这个特性使得以太币在大多数情况下非常适合作为货币,但并不是非常适合所有 dapp,因为 dapp 通常需要跟踪与用户相关的复杂状态,并且可能没有像货币这样简单的用户状态分区方案。

2. 潜在的可扩展性范式:理论上,UTXO 更兼容某些类型的可扩展性范式,因为我们只能依靠特定币种的所有者来维护 Merkle 所有权证明。 此外,即使包括所有者在内的所有人都决定忘记数据,最终受害的也只有币的所有者。 在账户范式中,如果每个人都丢失了与该账户对应的 Merkle 树的特定部分,他们将无法以任何方式处理影响该账户的任何消息,包括向该账户发送消息。 然而,现实中存在不依赖于 UTXO 的可扩展性范式(这句话不好理解)。

使用帐户模型的好处是:

以太经典和以太坊算力差别_以太坊经典合约地址是多少_sitechainb.com 以太坊以太经典那个好

1. 节省大量空间:比如一个账户有5个UTXO以太坊经典合约地址是多少,从UTXO模型切换到账户模型需要的空间为(20 + 32 + 8) * 5 = 300字节(地址20字节为txid,txid为32字节,value为8字节)减少为20 + 8 + 2 = 30字节(地址为20字节,value为8字节,nonce值(即随机数),下同)消耗2字节(详见下文))。 事实上,由于账户需要存储在 Patricia 树中(见下图),这部分节省的空间不是很大,但也不小。 此外,交易所需的空间变得更小(例如,在以太坊中只有 100 个字节,在比特币中为 200 到 250 个字节),因为每笔交易只需要创建一个引用和一个签名,然后产生一个输出。

2、更好的可替代性:由于在区块链层面没有概念来区分特定一套币的来源,无论从技术上还是法律上,都需要根据币的来源来区分特定一套币。 为其制定红黑名单方案是不可行的。

3. 简单性:更容易编码和理解。 当涉及复杂的脚本时尤其如此。 尽管我们可以强制任意去中心化应用程序进入 UTXO 范例,例如启用脚本来限制允许特定 UTXO 花费的 UTXO 类型,并要求花费行为包括对脚本评估的应用程序状态根的更改的 Merkle 树证明,但是相对于账户范式,UTXO范式更加复杂和简单。

4.持久化轻客户端引用:轻客户端可以通过向下特定方向扫描状态树,随时访问与帐户相关的所有数据。 在 UTXO 范例中,这些参考数据会随着每次交易而变化,这对于尝试使用上述 UTXO 状态根传播机制的长期运行的 dapp 来说将是一个特别棘手的问题。

总之,鉴于我们正在处理包含任意状态和代码的 dapp,我们认为账户模型的好处远远超过其他选择。 此外,根据“我们没有所谓的特长”的原则,如果人们真的很重视个人隐私,那么我们可以通过合约中签署的数据包协议来构建混合器(mixer)和硬币(coinjoin)方案.

账户范式的一个弱点是,为了防止重放攻击,每一笔交易都必须有一个“nonce值”,这样账户就可以跟踪使用了哪些nonce值,并且只接受最后使用过的nonce值之后的那个当前 nonce 值为 1 的交易。这意味着即使不再使用的帐户也永远无法从帐户状态中删除。 这个问题的一个简单解决方案是要求交易包含一个块号,使它们在一定时期后不可重放,并在每个时期重置 nonce 值。 矿工或其他用户需要“ping”不再使用的帐户以将它们从状态中删除,如果我们将整体扫描作为区块链协议本身的一部分进行,这将非常昂贵。 为了加快以太坊1.0的发展,我们没有采用这种机制; 然而,以太坊 1.1 及后续版本可能会使用这种机制。

04

默克尔帕特里夏树

Merkel Patricia树(简称MPT,也称trie,为方便起见,除非有特殊情况,以下将trie简称为“树”),最早由Alan Reiner构想并在Ripple协议中实现。 作为以太坊的主要数据结构,用于存储所有账户状态以及每个区块中的交易和收据。 MPT 是 Merkle 树 [1] 和 Patricia 树 [2] 的结合,通过吸收两者的元素来创建同时具有以下两个属性的结构:

每个唯一的键/值对都唯一地映射到根哈希,并且不可能欺骗成为树的一部分(除非攻击者拥有大约 2^128 的哈希能力)

以太经典和以太坊算力差别_sitechainb.com 以太坊以太经典那个好_以太坊经典合约地址是多少

我们可以在对数时间内对键/值对进行修改、增删操作

这种结构使我们能够提供高效且易于更新的全局状态树“指纹”。 以太坊MPT的正式解释请参考:

MPT 中的具体设计决策包括:

1.节点有两种类型,kv节点和发散节点(更多细节请参考MPT规范)。 kv节点的存在提高了效率,因为如果树在某个区域比较稀疏,kv节点可以作为一个“捷径”,这样我们就不需要保存深度为64的树了。

2.让离散节点以十六进制而不是二进制运行:这样做是为了提高查找效率。 我们现在认为这种选择不太理想,因为我们可以在具有一批存储节点的二进制范式中模拟十六进制树的查找效率。 然而,由于这种二叉树结构容易出现实现错误并最终导致状态根不匹配,我们决定将此重组推迟到 1.1 版。

3.空值和非成员没有区别:这是基于简单性的考虑,这种方案更兼容以太坊的默认设置。 这个默认设置是指:未设置的值(如余额)通常被视为零,用空字符串表示。 但是,我们注意到这种方法会损害一些通用性,因此效果不是最优的。

4. 终止节点和非终止节点的区别: 从技术上讲,“节点终止”标志是不必要的,因为在以太坊中,所有树都用于存储静态密钥长度。 但是我们还是加入这个属性来提高以太坊的通用性,希望以太坊MPT的实现可以原封不动的用于其他加密协议。

5. 在“安全树”(状态和账户存储树)中使用sha3(k)作为key:通过设置弱势离散节点链的最大深度为64层,不断调用SLOAD和SSTORE,我们可以使DoS对树的攻击更加困难。 请注意,此方案还使枚举树变得更加困难。 如果你想让客户端有枚举能力,最简单的解决办法是维护一个数据库映射sha3(k) -> k。

05

RLP

以太经典和以太坊算力差别_以太坊经典合约地址是多少_sitechainb.com 以太坊以太经典那个好

RLP(“递归长度前缀”)编码是以太坊使用的主要序列化格式,我们随处可见,例如区块、交易、账户状态数据和 Telegram 协议消息。 有关 RLP 的正式阐述,请参阅:

RLP 旨在成为一种高度简约的序列化格式,其唯一目的是存储嵌套的字节数组。 与 protobuf [3]、BSON [4] 和其他现有解决方案不同,RLP 不会尝试定义任何特定的数据类型,例如 boolean、float、double 甚至 integer。 相反,它只是将结构存储为嵌套数组,并将其留给协议来确定数组的含义。 这里没有明确支持key/value映射,如果要支持key/value映射,半官方的建议是将这些映射表示为[[k1, v1], [k2, v2], ... ] where k1, k2 ...按照字符串的标准排序进行排序。

RLP 的替代方案是使用现有算法,例如 protobuf 或 BSON。 但是,我们更喜欢 RLP,因为它 (1) 易于实现,并且 (2) 保证了字节级别的绝对完美一致性。 在很多语言中,key/value maps 没有明确的排序,浮点格式有很多特殊情况会导致相同的数据有不同的编码结果,从而产生不同的哈希值。 通过在内部开发协议,我们可以确信协议的设计遵循这些目标(这是一个通用原则,也适用于代码的其他部分,例如 VM)。 请注意,BitTorrent 使用的 bencode 提供了一个不错的 RLP 替代方案——尽管它使用十进制编码长度,这使得它略逊于二进制 RLP。

06

压缩算法

Telegram 协议和数据库都使用自定义压缩算法来存储数据。 我们可以将这种算法描述为“游程编码零,其他值保持原样”。 当然,对于普通值也有一些特例,比如sha3('')。 例如:

>>> 压缩('马')

'马'

>>> compress('驴龙1231231243')

'驴龙 1231231243'

>>> 压缩('\xf8\xaf\xf8\xab\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xbe{b\xd5\xcd\x8d\x87\x97')

'\xf8\xaf\xf8\xab\xa0\xfe\x9e\xbe{b\xd5\xcd\x8d\x87\x97'

>>> 压缩("\xc5\xd2F\x01\x86\xf7#