多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 以太坊的账户设计 以太坊的账户设计,替代了UTXO这一区块链中最为关键的对象设计(或者说放弃了UTXO设计),转而采用一种更简单的方法:状态存储一个账户列表,每个账户都有余额,以及以太坊特定的数据(代码和内部存储),如果发送账户有足够的余额,则交易有效余额来支付它,在这种情况下,发送账户被借记,接收账户被记入价值。 如果接收帐户有代码,则代码会运行,并且内部存储也可能会更改,或者代码甚至可能会向其他帐户创建额外的消息,从而导致进一步的借记和贷记。 ### 以太坊账户分类 * 在以太坊中,有两种类型的账户:外部账户(EOA,也称为基本账户)和合约账户。 * EOA 账户可以使用它相互发送以太币并部署智能合约 * 合约账户是部署智能合约时创建的账户。 * 每个智能合约都有自己的以太坊账户 * 帐户状态包含有关以太坊帐户的信息。 例如,它存储一个账户有多少以太币以及该账户发送的交易数量。 每个帐户都有一个帐户状态。 如果 一下结构中,codeHash 为空,则说明该账户是一个简单的外部账户,只存在 nonce 和 balance。 以太坊账户包含以下信息: 1. **nonce** 以太坊所有的交易都是基于 account ,不同于基于 utxo 的比特币,因此需要对每次交易都按顺序记录,nonce值就是这个顺序,nonce 是交易原始地址的属性。它不存储在以太坊区块链上,而是通过计算从一个地址发送的交易数量来计。 从该地址发送的交易数量(如果当前是 EOA 账户)或该账户产生的合约创建操作每发起一笔交易,nonce就会加1。对于发起的解释: 1.外部账户(EOA)每发送一笔交易; 2.合约账户(Contract Wallet) 每创建一个合约 而转入交易、合约调用其他合约等属于内部调用,因此 nonce 值不变。 nonce可以记录交易顺序,同时防止重放攻击(因为任何人都可以看到这笔交易,然后复制粘贴,重复提交给以太坊的网络,耗尽你的余额,也就是所谓的重放攻击)、加速(基于 nonce 的特性,自增和唯一性,使用相同的 nonce 重新发起交易即可实现加速)或取消交易。 **2. balance** 该账户拥有的以太币数量 (单位是 Wei) 。 **3. storageRoot** storage trie的根节点的hash值,标示合约存储结构的 MPT 树根节点 hash 值。仅仅智能合约账户不为空。 **4. codeHash** 仅在合约账户上该属性有效,标示合约代码对应的 Hash 值。 对于合约账户,这是存储 EVM 代码哈希的账户。 对于 EOA 帐户(基本账户),请将此留空。 帐户状态中一个不容忽视的细节是,包括上述在内的所有对象都是可变的(codeHash 除外)。 例如,当一个账户向其他账户发送以太币时,除了随机数增加外,该账户的余额也会相应变化。 如果部署了易受攻击的智能合约,codeHash 的不变性使得无法修复和更新该合约。 相应地,只能部署新合约(易受攻击的版本将始终存在于区块链上)。 这就是为什么有必要使用 Truffle 进行智能合约开发和部署,并在使用 Solidity 编程时遵循最佳实践(确保智能合约的健壮性)。 ![](https://img.kancloud.cn/ac/a3/aca3cd6370ab81cf976e3bf09927fc01_2402x658.png) ### 以太坊账户的数据存储规则 以太坊用 NoSQL 数据库以 Key-Value 的形式存储所有的数据。针对账户数据结构,需要存储的数据主要包含智能合约的 Storage 和基本的账户信息。对应的存储规则如下: 1. 针对智能合约 Storage,将数据按照编码规则映射成 MPT,然后将 MPT 的所有节点的 Key 和 Value 构建一个 RLP List 编码作为数据库存储的 Value 值,将该 Value 值进行 Sha3 计算 hash 值作为数据库存储的 Key 值进行存储。 2. 针对基本账户信息,将其对应智能合约 Storage 的 MPT Root Hash 保存于账户的 StorageRoot 属性,然后将系统中的所有 Account 构建一个 MPT。按照和 Storage 的数据库存储方式将 MPT 的所有节点进行存储。 帐户状态存储有关帐户的信息,例如帐户有多少以及从该帐户发送了多少交易。 它有四个字段:nonce、balance、storageRoot 和 codeHash。 **以太坊账户状态信息是世界状态树中的叶节点**。 ### (智能合约)账户存储树 Account Storage Trie 是存储与帐户关联的数据的位置。 帐户存储树的根哈希由帐户状态存储。 **每个智能合约帐户都有一个帐户存储树。** 账户存储树是保存与智能合约账户相关的数据的结构:也就是说账户存储树仅适用于合约账户。在EOA中,storageRoot为空,codeHash为空字符串的哈希值。 所有智能合约数据都以 32 字节的映射形式存储在账户存储树中。 ![](https://img.kancloud.cn/d9/15/d915d18813785a490fb55e32a7a8b71c_1217x549.png)