Login
欢迎来到未来世界

您现在的位置是: 首页 > 计算机 > 区块链

区块链

深度| 以太坊的数据到底是如何存储在以太坊网络的?

区块链 加入收藏
此文我们会深入讨论以太坊数据存储层。我们会介绍区块链“状态”的概念。同时也会讨论Patricia前缀树结构背后的理论,使用谷歌的leveldb数据库演示以太坊前缀树的具体实现。在存储层中,我们存储的是

在本文中,我们将深入讨论以太坊的数据存储层。我们将介绍区块链“国家”的概念。同时将讨论Patricia前缀树结构背后的理论,并使用Google的leveldb数据库演示以太坊前缀树的具体实现。

在存储层,我们存储什么?

首先,我们需要理解为了让区块链系统运行,我们需要存储什么。让我们简单看一下Alice给Bob转账10美元的例子。

我们可以看到,通过执行转移可以改变状态。

我们必须跟踪不同人(州)的余额和其他细节,以及区块链之间发生的细节(转移)。不同的平台会有不同的处理方式。我们可以看到比特币和以太坊是如何处理的。

比特币

比特币的地位是通过UTXO实现的。比特币价值转移是通过转账实现的。更具体地说,比特币用户可以通过创建转账来消费一个或多个UTXOs,并使用其UTXOs作为转账输入。

UTXO模型使得比特币不同于以太坊。我们可以看看这些例子来理解不同之处。

首先,比特币UTXO不能部分消费。如果比特币用户消费了0.5个比特币(使用自己唯一的UTXO,价值1个比特币),需要特意寄回0.5个比特币。如果他们不发这部分,那么这0.5的比特币就会丢失,给挖出转账的矿工。

其次,在最基本的层面上,比特币不包含用户账户余额。使用比特币,用户只需持有私钥,就可以在任何时间点制作一个或多个UTXO。数字钱包看起来像是让比特币区块链能够自动存储和管理用户账户余额,但事实并非如此。

比特币的UTXO系统运行良好,因为数字钱包可以完成大部分转账任务。包括但不限于:
a)处理UTXO
b)存储密钥
c)设置转让费
d)提供返回地址[/]

UTXO模型中的转账可以比作纸币转账。每个账户都会跟踪钱包添加的账单(UTXO)。当我们想花钱时,我们会使用一张或多张钞票(现在的UTXO),这些钞票足以支付开销,也许还能得到一些零钱。(新UTXO)。每张钞票只能消费一次。一旦花费,UTXO将从资金池中移除。

综上所述,我们知道:
比特币区块链不会持有账户余额的密钥
。如果包括在传输中,完整的UTXO将被消耗(有时,一些将获得新的UTXO作为更改)

以太坊
与以上信息相反,以太坊的状态可以管理账户余额,更多信息。以太坊的状态不是一个抽象的概念。它是以太坊底层协议的一部分。根据黄皮书中的描述,以太坊是基于传送的状态机;可以创建基于状态机的传输技术。

让我们从头开始。像其他区块链一样,区块链以太坊是从创作开始的。从那以后,像资金转移、合同和采矿这样的事情将逐渐改变以太坊区块链的状态。以以太坊为例,是账户余额(存储在状态树中),随着转账而变化,与账户相关联。

重要的是,诸如账户余额的数据并不直接存储在以太坊区块链的区块中。只有根节点散列传输、状态数据和接收数据直接存储在区块链上。从下图可以看出。

也许您还从上面的图表中注意到,存储树(存储所有智能合约数据的地方)的根节点的散列实际上指向状态树,从而指向区块链。接下来,我们将讨论更多的细节。

以太坊中有两种不同类型的数据:永久数据和临时数据。永久数据的一个例子是资金转移。一旦转让被确认,将被记录在区块链中;那你永远也改变不了。数据的一个临时例子是特定以太坊账户地址的余额。帐户的余额将被存储在状态树中,并且当有特定的帐户转移时会改变。永久数据是有意义的,就像挖掘转移一样。临时数据(如帐户余额)应单独存储。以太坊将使用数据树结构来管理数据。

以太坊的数据记录就像在银行一样。使用ATM机和存储卡。银行将跟踪每张借记卡,以确保在转账完成前有足够的余额。


UTXO和账户方案之间的对比

UTXO模型的优势:


• 扩容性 – 因为可以同时处理多个UTXO,所以能够完成同步转账并且鼓励扩容创新。
• 隐私 – 尽管比特币并是不完全的匿名系统,但是UTXO可以提供更高层次的隐私性,只要用户使用为每个转账提供新的地址。如果有需要提高隐私性,更多复杂的结构,例如环形结构,也可以考虑使用。
产能扩张——因为可以同时处理多个UTXO,所以可以完成同步转移,鼓励产能扩张和创新。
隐私——虽然比特币不是一个完整的匿名系统,但UTXO可以提供更高层次的隐私,只要用户每次转账都提供一个新地址。如果有必要提高私密性,也可以考虑更复杂的结构,比如环形结构。

账户/余额模型的好处:
简化——以太坊使用的模型可以帮助开发者制定复杂的智能合约,尤其是那些需要状态信息或者包含多方的合约。

例如,跟踪状态并根据状态处理不同任务的智能合约。UTXO的无状态模型将使传输包含状态信息,这与契约的设计是不必要的一致。

效率——除了简化之外,帐户/余额模型更有效,因为每次转账只需要验证发出金额的帐户是否有足够的余额来支付转账。

账户/余额模型的缺陷是双花攻击。可以添加递增的随机数来抵消这种类型的攻击。在以太坊,每个账户都有一个空开随机数,每次转账随机数都会增加。这有助于防止相同的传输进行两次。(注意这个随机数不是工作量证书里的随机数,是一个随机数)

像大多数计算机体系结构一样,这两种模型各有优缺点。一些区块链,如super ledger,也应用了UTXO,因为他们从比特币区块链中获得创新。接下来,我们来看看更多基于这两个模型的技术。


以太坊中的数据树结构是什么?

让我们深入了解一下状态、存储和转移的树形结构。

前缀树——是唯一的,唯一的。

在以太坊中,只有唯一的网络状态前缀树。
这个网络状态前缀树会实时更新。
网络状态前缀树包含秘钥和每个账户的价值对,这些是在以太坊网络上。
秘钥是单个160字节的认证器(以太坊账户的地址)。在以太坊中,只有唯一的网络状态前缀树。
此网络状态前缀树将实时更新。
网络状态前缀树包含每个帐户的密钥和值对,它们位于以太网上。
密钥是一个160字节的认证器(以太坊账号的地址)。

网络状态前缀树的“数值”是通过编译以太坊账户的以下账户明细得到的:
-随机数
-余额
-storage root
-code hash。

状态前缀树的根节点(某一时间点全网状态前缀树的哈希)用于保证状态前缀树的安全性和唯一性;网络状态前缀树根节点基于整个内部网络状态前缀树数据被加密。

存储前缀树,其中存储智能合同数据

存储前缀树是存储智能合同数据的地方。每个以太坊账号都有自己的存储前缀树。存储前缀根节点是一个256字节的哈希值,它作为storageRoot的值存储在网络状态前缀树中。

传输前缀树-每个块都有一个

每个以太坊块都有自己独立的传输前缀树。一个块将包含许多传输。区块内的转移顺序当然由矿工决定。对于转移前缀树中的特殊转移路径,它是该转移在块中的位置因子。将不更新挖掘块;传输在块中的位置不会改变。这意味着一旦您在块传输前端树中找到传输,您可以返回到相同的路径以获得相同的结果。


分析以太坊数据库

在区块链以太坊,有许多MPT(Merkle Patricia Tries)(代表每个街区):


状态前缀树
存储前缀树
传输前缀树
收据前缀树

为了获得特定块中的MPT,我们需要获得它的散列以供参考。以下命令允许我们在创建块中获取状态、转移和接收的根散列。

注意:如果您想要获得最新块(而不是创建块)的根散列,请使用下面的命令。

安装npm、节点、级别和以太网服务器

我们将使用nodejs、level和ethereumjs的组合来检测leveldb数据库。以下命令可以帮助我们准备测试环境。

cd ~ sudo apt-get update sudo apt-get upgrade curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash - sudo apt-get install -y nodejs sudo apt-get install nodejs npm -v nodejs -v npm install levelup leveldown rlp merkle-patricia-tree --save git clone https://github.com/ethereumjs/ethereumjs-vm.git cd ethereumjs-vm npm install ethereumjs-account ethereumjs-util --save

从此,运行下面的代码将获得以太坊账号的密钥(将存储在以太坊网络的状态根中)。该代码与以太坊的leveldb数据库连接,进入以太坊的状态(使用来自区块链区块的stateRoot值),然后可以使用密钥访问以太坊网络中的所有账户。

//Just importing the requirements var Trie = require('merkle-patricia-tree/secure'); var levelup = require('levelup'); var leveldown = require('leveldown'); var RLP = require('rlp'); var assert = require('assert'); //Connecting to the leveldb database var db = levelup(leveldown('/home/timothymccallum/gethDataDir/geth/chaindata')); //Adding the "stateRoot" value from the block so that we can inspect the state root at that block height. var root = '0x8c77785e3e9171715dd34117b047dffe44575c32ede59bde39fbf5dc074f2976'; //Creating a trie object of the merkle-patricia-tree library var trie = new Trie(db, root); //Creating a nodejs stream object so that we can access the data var stream = trie.createReadStream() //Turning on the stream (because the node js stream is set to pause by default) stream.on('data', function (data){ //printing out the keys of the "state trie" console.log(data.key); });

有趣的是,一旦转移发生,以太坊中的帐户只会被添加到状态树中(与该特定帐户相关)。例如,使用“新建帐户”创建一个新帐户将不会在状态树中包括该帐户;即使在许多街区被挖掘出来之后。但是,如果帐户中记录了成功的转移(消耗燃料并包含在采矿区块中),则状态树中将仅显示该成功的转移。这是一个聪明的逻辑,因为它将防止欺诈者不断创建新帐户和阻止状态树。

解码数据

您已经注意到,查询leveldb可以回复解码后的结果。这是因为以太坊使用自己特定的“修改的MPT(Merkle Patricia Trie)”与leveldb进行交互。以太坊Wiki提供了在以太坊中设计和部署MPT(Merkle Patricia Trie)和RLP(递归长度前缀)解码的信息。简单来说,以太坊在前缀树数据结构上进行了扩展。例如,修改后的MPT(Merkle Patricia Trie)包含了一种通过“扩展”节点创建快捷方式的方法。

以太坊中单个修改的MPT(Merkle Patricia Trie)节点为:
空 byte(对应null)
数组(对应分支)包含17个对象
[/]

以太坊前缀树是按照固定的规则设计和创建的,最好的检测方法是使用计算机代码。下一个例子使用ethereumjs。Ethereumjs易于安装和使用;非常适合快速连接以太坊leveldb数据库。

以下代码(当提供特定的块stateRoot和以太坊帐户地址时)将以可读的形式返回帐户的正确余额。

//Mozilla Public License 2.0 //As per https://github.com/ethereumjs/ethereumjs-vm/blob/master/LICENSE //Requires the following packages to run as nodejs file https://gist.github.com/tpmccallum/0e58fc4ba9061a2e634b7a877e60143a //Getting the requirements var Trie = require('merkle-patricia-tree/secure'); var levelup = require('levelup'); var leveldown = require('leveldown'); var utils = require('ethereumjs-util'); var BN = utils.BN; var Account = require('ethereumjs-account'); //Connecting to the leveldb database var db = levelup(leveldown('/home/timothymccallum/gethDataDir/geth/chaindata')); //Adding the "stateRoot" value from the block so that we can inspect the state root at that block height. var root = '0x9369577baeb7c4e971ebe76f5d5daddba44c2aa42193248245cf686d20a73028'; //Creating a trie object of the merkle-patricia-tree library var trie = new Trie(db, root); var address = '0xccc6b46fa5606826ce8c18fece6f519064e6130b'; trie.get(address, function (err, raw) { if (err) return cb(err) //Using ethereumjs-account to create an instance of an account var account = new Account(raw) console.log('Account Address: ' + address); //Using ethereumjs-util to decode and present the account balance console.log('Balance: ' + (new BN(account.balance)).toString()); })

结论

我们已经证明以太坊有管理状态的能力。这种先进的设计有许多优点。

流动性

假设移动设备和物联网设备是很普遍的,未来电商就取决于安全,稳定和快速的移动应用。
我们认知到了可移动性的优势,我们也知道区块链大小的逐渐增加是难以置信的。将整个区块链存储在移动设备是不可能的。假设移动设备和物联网设备通用,未来的电子商务依赖于安全、稳定、快速的移动应用。
我们认识到移动性的优势,我们也知道区块链规模的逐渐增大是不可思议的。在移动设备上存储整个区块链是不可能的。

快速,并且不损失安全性

以太坊国家的设计和改良MPT(Merkle Patricia Trie)的使用提供了许多机会。以太坊前缀树上的每个函数都使用加密哈希。而且,根据节点的特殊加密哈希,前缀树可以用来证明前缀树没有被欺骗。

例如,对前缀树的任何修改都会完全改变根哈希。这种加密功能将为轻客户端(那些不存储整个区块链的设备)提供一个机会,以便他们可以快速访问区块链。即账户“0x … 4857”是否有足够的资金完成块高“5044866”的转账?

速度限制

以太坊描述了一个很有意思的问题,就是存储账户的概念。想象一下这个场景,两个用户每天都可以从账户中提取总余额的1%。这个想法只是在未来的规划中有所提及,但已经获得了很大的兴趣,因为理论上,它可以作为以太坊基础协议层的一部分(相对于必须是第二层和第三方钱包)。也许你还记得我们之前讨论的比特币UTXO。UTXO对区块链数据视而不见。比特币区块链不会储存用户的账户余额。所以比特币的底层协议层基本不可能完成任何类型的每日限速。

消费者信心

我们已经看到了很多关于轻客户端的发展,更具体地说,是可以与区块链技术交互的安全、稳定和快速的移动应用。

电子商务区块链的成功部署肯定会支持速度、安全性和可用性。这样可以提高消费者的信心,同时可以通过智能设计提供更高的可用性、安全性和性能,从而提高主流接受度。

原文:https://hackernoon.com/getting-deep-into-ethereum-how-data-is-stored-in-ethereum-e3f669d96033
作者:vasa
编译:nuszjj
图集详情底部广告位