区块
上次修改时间: @imalittlemole(opens in a new tab), 2024年5月26日
区块是指一批交易的组合,并且包含链中上一个区块的哈希。 这将区块连接在一起(成为一个链),因为哈希是从区块数据中加密得出的。 这可以防止欺诈,因为以前的任何区块中的任何改变都会使后续所有区块无效,而且所有哈希都会改变,所有运行区块链的人都会注意到。
前提条件
区块是一个对初学者非常友好的主题。 为了帮助你更好地理解这个页面,我们建议你先阅读帐户、交易和我们的以太坊简介。
为什么要有区块?
为了确保以太坊网络上的所有参与者保持同步状态并就交易的确切历史达成共识,我们将交易分为多个区块。 这意味着同时有数十个(甚至数百个)交易被提交、达成一致并同步。
示意图节选自以太坊虚拟机图解(opens in a new tab)
通过间隔提交,所有网络参与者有足够时间达成共识:即使交易请求每秒发生数十次,但以太坊上的区块仅仅大约每十二秒创建并提交一次。
区块如何工作
为了保存交易历史,区块被严格排序(创建的每个新区块都包含一个其父块的引用),区块内的交易也严格排序。 除极少数情况外,在任何特定时间,网络上的所有参与者都同意区块的确切数目和历史, 并且正在努力将当前的活动交易请求分批到下一个区块。
随机选择的验证者在网络上构建完区块后,该区块将传播到整个网络;所有节点都将该区块添加至其区块链的末尾,然后挑选新的验证者来创建下一个区块。 目前,确切的区块构建过程和提交/共识过程由以太坊的“权益证明”协议规定。
权益证明协议
权益证明是指:
- 验证节点必须向存款合约中质押 32 个以太币,作为抵押品防止发生不良行为。 这有助于保护网络,因为如果发生不诚实活动且可以证实,部分甚至全部质押金额将被销毁。
- 在每个时隙(12 秒的时间间隔)中,会随机选择一个验证者作为区块提议者。 他们将交易打包并执行,然后确定一个新的“状态”。 他们将这些信息包装到一个区块中并传送给其他验证者。
- 其他获悉新区块的验证者再次执行区块中包含的交易,确定他们同意对全局状态提出的修改。 假设该区块是有效的,验证者就将该区块添加进各自的数据库。
- 如果验证者获悉在同一时隙内有两个冲突区块,他们会使用自己的分叉选择算法选择获得最多质押以太币支持的那一个区块。
区块包含什么?
一个区块中包含很多信息。 区块的最高层包含以下字段:
字段 | 简介 |
---|---|
时隙 | 区块所属的时隙 |
proposer_index | 提出区块的验证者的 ID |
parent_root | 上一个区块的哈希 |
state_root | 状态对象的根哈希 |
正文 | 包含多个字段的对象,定义如下 |
区块的 body
包含一些自有字段:
栏目 | 简介 |
---|---|
randao_reveal | 用于选择下一个区块提议者的值 |
eth1_data | 关于存款合约的信息 |
涂鸦 | 用于标记区块的任意数据 |
proposer_slashings | 将要惩罚的验证者列表 |
attester_slashings | 将要受到惩没的证明者列表 |
认证 | 支持当前区块的认证列表 |
存款 | 存款合约新增存款的列表 |
voluntary_exits | 退出网络的验证者列表 |
sync_aggregate | 用于服务轻客户端的验证者子集 |
execution_payload | 从执行客户端传送来的交易 |
attestations
字段包含区块中所有认证的列表。 认证有自己的数据类型,其中包含多条数据。 每个认证包含:
栏目 | 简介 |
---|---|
aggregation_bits | 参与此认证的验证者列表 |
数据 | 具有多个子字段的容器 |
签名 | 所有证明验证者的聚合签名 |
attestation
中的 data
字段包含以下内容:
栏目 | 简介 |
---|---|
时隙 | 认证所涉及的时隙 |
索引 | 证明验证者的索引 |
beacon_block_root | 包含此对象的信标区块的根哈希 |
来源 | 最后一个合理的检查点 |
target | 最新的时段边界区块 |
执行 execution_payload
中的交易会更新全局状态。 所有客户端重新执行 execution_payload
中的交易,以确保新状态与新区块 state_root
字段中的状态相符。 这就是客户端如何判断新区块是否有效且可以安全添加到其区块链的方式。 execution payload
本身是一个包含多个字段的对象。 还有一个 execution_payload_header
,包含有关执行数据的重要摘要信息。 这些数据结构如下组织:
execution_payload_header
包含以下字段:
领域 | 简介 |
---|---|
父_哈希值 | 父块的哈希值 |
fee_recipient | 向其支付交易费的帐户地址 |
state_root | 应用此区块中的更改后,全局状态的根哈希 |
receipts_root | 交易收据树的哈希 |
logs_bloom | 包含事件日志的数据结构 |
prev_randao | 在随机选择验证者时使用的值 |
block_number | 当前区块的编号 |
gas_limit | 此区块允许的最大燃料量 |
gas_used | 此区块中使用的实际燃料量 |
时间戳 | 区块时间 |
extra_data | 作为原始字节的任意附加数据 |
base_fee_per_gas | 基础费值 |
block_hash | 执行区块的哈希 |
transactions_root | 有效载荷中交易的根哈希 |
withdrawal_root | 有效负载中提款的根哈希 |
execution_payload
本身包含以下字段(请注意这与 header 相同,只是它包含的不是交易的根哈希,而是实际的交易列表和提款信息列表):
栏目 | 简介 |
---|---|
父_哈希值 | 父块的哈希值 |
fee_recipient | 支付交易费用的帐户地址 |
state_root | 应用此区块中的更改后,全局的根哈希值 |
receipts_root | 交易收据的哈希值 |
logs_bloom | 包含事件日志的数据结构 |
prev_randao | 在随机验证者选择中使用的值 |
block_number | 当前区块的编号 |
gas_limit | 此区块允许的最大的燃料量 |
gas_used | 此区块中使用的燃料实际量 |
时间戳 | 区块时间 |
extra_data | 作为原始字节任意附加数据 |
base_fee_per_gas | 基本费用值 |
block_hash | 执行区块的哈希值 |
交易 | 要执行交易的列表 |
提款 | 提款对象列表 |
Withdrawals
列表包含了 withdrawal
对象,结构如下:
字段 | 描述 |
---|---|
地址 | 提款帐户地址 |
amount | 提款金额 |
索引 | 提款索引值 |
validatorIndex | 验证者索引值 |
区块时间
区块时间是指两个区块之间的时间间隔。 在以太坊中,时间划分为每 12 秒一个单位,称为“时隙”。 在每个时隙内,选择一个单独的验证者提议区块。 假设所有验证者都在线且完全正常运行,则每个时隙内都会有一个区块产生,意味着区块时间是 12 秒。 但是,偶尔验证者在被要求提议区块时不在线,导致有时候一些时隙是空的。
这种实现与基于工作量证明的系统不同。在工作量证明系统中,区块时间是带有概率性的,并由协议的目标挖矿难度调节。 以太坊的平均区块时间(opens in a new tab)是一个很好的例子,根据不变的新的 12 秒区块时间,可以清楚地推断出从工作量证明到权益证明的过渡。
区块大小
最后一条重要提示是,区块本身的大小是有界限的。 每个区块的目标大小为 1500 万单位燃料,但区块的大小将根据网络需求而增加或减少,直至达到 3000 万单位燃料的区块限制(目标区块大小的 2 倍)。 区块的燃料限制可以相对于上一个区块的燃料限制上调或下调 1/1024 的比例。 因此,验证者可以通过共识来改变区块的燃料限制。 区块中所有交易消耗的总燃料量必须低于区块的燃料限制。 这很重要,因为它可以确保区块不能任意扩大。 如果区块可以任意扩大,由于空间和速度方面的要求,性能较差的全节点将逐渐无法跟上网络。 区块越大,在下一个时隙中及时处理它们需要的算力就越强大。 这是一种集中化的因素,可以通过限制区块大小来抵制。
延伸阅读
还有哪些社区资源对你有所帮助? 请编辑本页面并添加!