主页 > imtokenapp下载安装 > 深度 | 以太坊数据如何存储在以太坊网络中?

深度 | 以太坊数据如何存储在以太坊网络中?

imtokenapp下载安装 2023-02-15 06:09:56

在以太坊区块链中,有很多MPTs(Merkle Patricia Tries)(代表每个区块):

• 状态前缀树

• 存储前缀树

• 传输前缀树

• 收据前缀树

为了获得特定区块中的 MPT,我们需要获得其根哈希作为参考。 以下命令将允许我们获取创世块的状态、传输和接收的根哈希。

1*IbnRm4TYAY55u7Ax2ZL_6A

注意:如果要获取最新块(不是创世块)的根哈希,请使用以下命令。

安装 npm、node、level 和 ethereumjs

我们将结合使用 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);
 });

有趣的是,一旦转账发生,以太坊中的账户就会被添加到状态树中(与该特定账户相关)。 例如,使用“geth account new”创建一个新帐户将不会将该帐户包含在状态树中; 即使在开采了许多区块之后。 但是,如果帐户中记录了一次成功的转账(这会花费 gas 并已包含在一个已开采的区块中),那么只有它会出现在状态树中。 这是一个聪明的逻辑,因为它可以防止欺诈者不断创建新帐户并阻塞状态树。

解码数据

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

在以太坊中,MPT(Merkle Patricia Trie)节点的单个修改版本是:

• 空字节(对应于 NULL)

• 17个对象的数组(对应分支)

• 2 个对象的数组(对应于叶子)

• 包含2个对象的数组(对应扩展名)

以太坊前缀树是按照固定规则设计和创建的,检测它的最好方法是使用计算机代码。 以下示例使用 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 对区块链数据是盲目的以太坊官网查余额,比特币区块链不存储用户账户余额。 因此,比特币的底层协议层基本上不可能完成任何一种每日限速。

消费者信心

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

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

原版的:

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

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

1*fLjE6g-m_YTTXTXqLnpA0w

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

我们可以看到可以通过执行传输来更改状态。

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

比特币

比特币的状态是通过 UTXO 实现的。 比特币价值转移是通过转账来完成的。 更具体地说,比特币用户可以通过创建转账并输入他们的 UTXO 作为转账来花费 1 个或多个 UTXO。

UTXO 模型使比特币不同于以太坊。 我们可以查看这些示例以了解差异。

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

1*8ckJdAnUMNNd190LNJLz7Q

其次,在最基本的层面上,比特币不包含用户账户余额。 使用比特币,用户可以简单地持有私钥并在任何时间点执行一个或多个 UTXO。 虽然数字钱包看起来允许比特币区块链自动存储和管理用户账户余额,但事实并非如此。

1*0doOO9uDGB3yqfPnsUrAEA

比特币的 UTXO 系统运行良好,因为数字钱包可以执行大多数转账任务。 这些包括但不限于:

a) 处理 UTXO

b) 存储密钥

c) 设置转账费用

d) 提供回邮地址

e) 描述 UTXO 状态(显示可行性、待转账和全部余额)

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

总之,我们知道:

• 比特币区块链不持有账户余额

• 密钥

• 如果包含在转账中,则将花费完整的 UTXO(有时,部分会获得新的 UTXO 作为找零)

以太坊

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

让我们从头开始。 与其他区块链一样,以太坊区块链从创世块开始。 此后,转账、合约、挖矿等都改变了以太坊区块链的状态。 例如,在以太坊中,随着转账而变化的账户余额(存储在状态树中)与账户相关联。

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

1*f0vOn0lRgrY5NjFlbUMBFg

或许你也注意到,从上图来看,存储树(存储所有智能合约数据的地方)的根节点哈希实际上指向状态树,从而指向区块链。 接下来,我们讨论更多细节。

以太坊中有两种不同的数据类型:永久数据和临时数据。 永久数据的一个例子是汇款。 一旦确认转账,就会记录在区块链中; 那么它永远无法改变。 临时数据的一个例子是特定以太坊账户地址的余额。 账户余额存储在状态树中,并在特定账户发生转账时发生变化。 永久数据是有意义的,就像挖矿转账一样,而临时数据,比如账户余额,应该分开存储。 以太坊使用数据树结构来管理数据。

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

UTXO模型的好处:

• 可扩展性——因为可以同时处理多个UTXO,所以可以同时完成转账,鼓励扩展创新。

• 隐私——虽然比特币不是一个完全匿名的系统,但UTXO 可以提供更高级别的隐私,只要用户每次转账都使用新的地址。 如果需要提高隐私性,也可以考虑更复杂的结构,比如环形结构。

账户/余额模型的好处:

• 简单性——以太坊使用的模型可以帮助开发人员实现复杂的智能合约,尤其是那些需要状态信息或涉及多方的合约。

例如,跟踪状态并根据状态处理不同任务的智能合约。 UTXO 的无状态模型将允许传输包含状态信息,这也不必要地符合合约的设计。

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

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

与大多数计算机体系结构一样,这两种模型各有利弊。 一些区块链,例如 Hyperledger,也实现了 UTXO以太坊官网查余额,因为它们从比特币区块链中汲取了创新。 接下来,我们将研究基于这两个模型的更多技术。

让我们更深入地了解状态、存储和传输的树结构。

状态前缀树 - 是独一无二的。

在以太坊中,只有一棵唯一的网络状态前缀树。

这个网络状态前缀树会实时更新。

网络状态前缀树包含以太坊网络上每个账户的键值对。

密钥是一个 160 字节的验证码(以太坊账户的地址)。

网络状态前缀树的“值”是通过编译以太坊账户的以下账户详情获得的:

-随机数

- 平衡

-存储根

-codeHash

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

1*-Q00GpGTphTOtBWPRu1e3g

1*NFM4Cb5eJdzJXvj9-dUorg

存储前缀树,存储智能合约数据的地方

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

1*9AvbCSNqn5m9z0qhWjE6cg

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

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

1*dWv4-5OQoa52QE03G9Qkwg