Capella - 信标链

  • ethereum
  • 发布于 2024-09-04 17:48
  • 阅读 92

Capella 是一个共识层的升级,主要聚焦于验证者的提取功能。文章详细介绍了验证者提取的自动化过程、新的自定义类型、容器结构以及状态转换函数,特别是对于历史汇总的处理和提取的操作。这些新特性旨在优化以太坊的验证者管理及其提取过程。

Capella -- 信标链

<!-- mdformat-toc start --slug=github --no-anchors --maxlevel=6 --minlevel=2 -->

<!-- mdformat-toc end -->

介绍

Capella 是一个共识层升级,包含与验证者提款相关的多个功能,包括:

  • 自动提款的 可提款 验证者。
  • 对于具有 0x01 提款凭证且余额超过 最大有效余额 的验证者进行部分提款。
  • 操作从 BLS_WITHDRAWAL_PREFIX 更改为 ETH1_ADDRESS_WITHDRAWAL_PREFIX 版本化提款凭证,以便为验证者启用提款。

另一个新功能是独立的状态和区块历史累加器,替代了原来的单一历史根。借助这些累加器,可以验证导致特定状态的整个区块历史,而无需除了状态和区块以外的任何附加信息。

自定义类型

我们定义以下 Python 自定义类型以提高类型提示和可读性:

名称 SSZ 等价物 描述
WithdrawalIndex uint64 Withdrawal 的索引

领域类型

名称
DOMAIN_BLS_TO_EXECUTION_CHANGE DomainType('0x0A000000')

预设

每个区块的最大操作数

名称
MAX_BLS_TO_EXECUTION_CHANGES 2**4 (= 16)

执行

名称 描述
MAX_WITHDRAWALS_PER_PAYLOAD uint64(2**4) (= 16) 每个负载允许的最大提款数量

提款处理

名称
MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP 16384 (= 2**14 )

容器

新容器

Withdrawal
class Withdrawal(Container):
    index: WithdrawalIndex
    validator_index: ValidatorIndex
    address: ExecutionAddress
    amount: Gwei
BLSToExecutionChange
class BLSToExecutionChange(Container):
    validator_index: ValidatorIndex
    from_bls_pubkey: BLSPubkey
    to_execution_address: ExecutionAddress
SignedBLSToExecutionChange
class SignedBLSToExecutionChange(Container):
    message: BLSToExecutionChange
    signature: BLSSignature
HistoricalSummary
class HistoricalSummary(Container):
    """
    `HistoricalSummary` 匹配 phase0 `HistoricalBatch` 的组成部分
    使两者相互兼容 hash_tree_root。
    """
    block_summary_root: Root
    state_summary_root: Root

修改后的容器

ExecutionPayload
class ExecutionPayload(Container):
    # 执行区块头字段
    parent_hash: Hash32
    fee_recipient: ExecutionAddress  # 黄色论文中的 'beneficiary'
    state_root: Bytes32
    receipts_root: Bytes32
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    prev_randao: Bytes32  # 黄色论文中的 'difficulty'
    block_number: uint64  # 黄色论文中的 'number'
    gas_limit: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    # 额外负载字段
    block_hash: Hash32  # 执行区块的哈希
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
    withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]  # [Capella 中的新]
ExecutionPayloadHeader
class ExecutionPayloadHeader(Container):
    # 执行区块头字段
    parent_hash: Hash32
    fee_recipient: ExecutionAddress
    state_root: Bytes32
    receipts_root: Bytes32
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    prev_randao: Bytes32
    block_number: uint64
    gas_limit: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    # 额外负载字段
    block_hash: Hash32  # 执行区块的哈希
    transactions_root: Root
    withdrawals_root: Root  # [Capella 中的新]
BeaconBlockBody
class BeaconBlockBody(Container):
    randao_reveal: BLSSignature
    eth1_data: Eth1Data  # Eth1 数据投票
    graffiti: Bytes32  # 任意数据
    # 操作
    proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
    attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS]
    attestations: List[Attestation, MAX_ATTESTATIONS]
    deposits: List[Deposit, MAX_DEPOSITS]
    voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
    sync_aggregate: SyncAggregate
    # 执行
    execution_payload: ExecutionPayload
    # Capella 操作
    bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]  # [Capella 中的新]
BeaconState
class BeaconState(Container):
    # 版本控制
    genesis_time: uint64
    genesis_validators_root: Root
    slot: Slot
    fork: Fork
    # 历史
    latest_block_header: BeaconBlockHeader
    block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
    state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
    historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT]  # 在 Capella 中被冻结,替换为 historical_summaries
    # Eth1
    eth1_data: Eth1Data
    eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
    eth1_deposit_index: uint64
    # 注册表
    validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
    balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
    # 随机性
    randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
    # 处罚
    slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR]  # 每个周期的处罚有效余额和
    # 参与
    previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
    current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
    # 最终性
    justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH]  # 针对每个最近证明周期设置的位
    previous_justified_checkpoint: Checkpoint
    current_justified_checkpoint: Checkpoint
    finalized_checkpoint: Checkpoint
    # 不活跃性
    inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT]
    # 同步
    current_sync_committee: SyncCommittee
    next_sync_committee: SyncCommittee
    # 执行
    latest_execution_payload_header: ExecutionPayloadHeader  # [在 Capella 中修改]
    # 提款
    next_withdrawal_index: WithdrawalIndex  # [在 Capella 中的新]
    next_withdrawal_validator_index: ValidatorIndex  # [在 Capella 中的新]
    # 从 Capella 及以后的深度历史
    historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]  # [在 Capella 中新]

助手

谓词

has_eth1_withdrawal_credential
def has_eth1_withdrawal_credential(validator: Validator) -> bool:
    """
    检查 ``validator`` 是否具有以 0x01 开头的 "eth1" 提款凭证。
    """
    return validator.withdrawal_credentials[:1] == ETH1_ADDRESS_WITHDRAWAL_PREFIX
is_fully_withdrawable_validator
def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch: Epoch) -> bool:
    """
    检查 ``validator`` 是否可以完全提款。
    """
    return (
        has_eth1_withdrawal_credential(validator)
        and validator.withdrawable_epoch &lt;= epoch
        and balance > 0
    )
is_partially_withdrawable_validator
def is_partially_withdrawable_validator(validator: Validator, balance: Gwei) -> bool:
    """
    检查 ``validator`` 是否可以部分提款。
    """
    has_max_effective_balance = validator.effective_balance == MAX_EFFECTIVE_BALANCE
    has_excess_balance = balance > MAX_EFFECTIVE_BALANCE
    return has_eth1_withdrawal_credential(validator) and has_max_effective_balance and has_excess_balance

信标链状态转移函数

时期处理

注意: 在 Capella 中,函数 process_historical_summaries_update 替代了 process_historical_roots_update

def process_epoch(state: BeaconState) -> None:
    process_justification_and_finalization(state)
    process_inactivity_updates(state)
    process_rewards_and_penalties(state)
    process_registry_updates(state)
    process_slashings(state)
    process_eth1_data_reset(state)
    process_effective_balance_updates(state)
    process_slashings_reset(state)
    process_randao_mixes_reset(state)
    process_historical_summaries_update(state)  # [在 Capella 中修改]
    process_participation_flag_updates(state)
    process_sync_committee_updates(state)
历史摘要更新
def process_historical_summaries_update(state: BeaconState) -> None:
    # 设置历史区块根累加器。
    next_epoch = Epoch(get_current_epoch(state) + 1)
    if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
        historical_summary = HistoricalSummary(
            block_summary_root=hash_tree_root(state.block_roots),
            state_summary_root=hash_tree_root(state.state_roots),
        )
        state.historical_summaries.append(historical_summary)

区块处理

def process_block(state: BeaconState, block: BeaconBlock) -> None:
    process_block_header(state, block)
    # [在 Capella 中修改] 删除了 Capella 中的 `is_execution_enabled` 检查
    process_withdrawals(state, block.body.execution_payload)  # [Capella 中的新]
    process_execution_payload(state, block.body, EXECUTION_ENGINE)  # [在 Capella 中修改]
    process_randao(state, block.body)
    process_eth1_data(state, block.body)
    process_operations(state, block.body)  # [在 Capella 中修改]
    process_sync_aggregate(state, block.body.sync_aggregate)
get_expected_withdrawals
def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]:
    epoch = get_current_epoch(state)
    withdrawal_index = state.next_withdrawal_index
    validator_index = state.next_withdrawal_validator_index
    withdrawals: List[Withdrawal] = []
    bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
    for _ in range(bound):
        validator = state.validators[validator_index]
        balance = state.balances[validator_index]
        if is_fully_withdrawable_validator(validator, balance, epoch):
            withdrawals.append(Withdrawal(
                index=withdrawal_index,
                validator_index=validator_index,
                address=ExecutionAddress(validator.withdrawal_credentials[12:]),
                amount=balance,
            ))
            withdrawal_index += WithdrawalIndex(1)
        elif is_partially_withdrawable_validator(validator, balance):
            withdrawals.append(Withdrawal(
                index=withdrawal_index,
                validator_index=validator_index,
                address=ExecutionAddress(validator.withdrawal_credentials[12:]),
                amount=balance - MAX_EFFECTIVE_BALANCE,
            ))
            withdrawal_index += WithdrawalIndex(1)
        if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
            break
        validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
    return withdrawals
process_withdrawals
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
    expected_withdrawals = get_expected_withdrawals(state)
    assert payload.withdrawals == expected_withdrawals

    for withdrawal in expected_withdrawals:
        decrease_balance(state, withdrawal.validator_index, withdrawal.amount)

    # 如果此区块包含提款,则更新下一个提款索引
    if len(expected_withdrawals) != 0:
        latest_withdrawal = expected_withdrawals[-1]
        state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)

    # 更新下一个验证者索引以开始下一个提款浪潮
    if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
        # 下一个浪潮在最新提款的验证者索引后面开始
        next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators))
        state.next_withdrawal_validator_index = next_validator_index
    else:
        # 如果没有完整的提款集,则通过浪潮的最大长度提前进行浪潮
        next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
        next_validator_index = ValidatorIndex(next_index % len(state.validators))
        state.next_withdrawal_validator_index = next_validator_index
修改后的 process_execution_payload

注意: 函数 process_execution_payload 被修改为使用新的 ExecutionPayloadHeader 类型,并删除了 is_merge_transition_complete 检查。

def process_execution_payload(state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine) -> None:
    payload = body.execution_payload
    # [在 Capella 中修改] 删除了 Capella 中的 `is_merge_transition_complete` 检查
    # 验证父哈希与之前的执行负载头的一致性
    assert payload.parent_hash == state.latest_execution_payload_header.block_hash
    # 验证 prev_randao
    assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state))
    # 验证时间戳
    assert payload.timestamp == compute_timestamp_at_slot(state, state.slot)
    # 验证执行负载是否有效
    assert execution_engine.verify_and_notify_new_payload(NewPayloadRequest(execution_payload=payload))
    # 缓存执行负载头
    state.latest_execution_payload_header = ExecutionPayloadHeader(
        parent_hash=payload.parent_hash,
        fee_recipient=payload.fee_recipient,
        state_root=payload.state_root,
        receipts_root=payload.receipts_root,
        logs_bloom=payload.logs_bloom,
        prev_randao=payload.prev_randao,
        block_number=payload.block_number,
        gas_limit=payload.gas_limit,
        gas_used=payload.gas_used,
        timestamp=payload.timestamp,
        extra_data=payload.extra_data,
        base_fee_per_gas=payload.base_fee_per_gas,
        block_hash=payload.block_hash,
        transactions_root=hash_tree_root(payload.transactions),
        withdrawals_root=hash_tree_root(payload.withdrawals),  # [Capella 中的新]
    )
修改后的 process_operations

注意: 函数 process_operations 被修改为处理区块中包含的 BLSToExecutionChange 操作。

def process_operations(state: BeaconState, body: BeaconBlockBody) -> None:
    # 验证未处理的存款是否处理到最大存款数量
    assert len(body.deposits) == min(MAX_DEPOSITS, state.eth1_data.deposit_count - state.eth1_deposit_index)

    def for_ops(operations: Sequence[Any], fn: Callable[[BeaconState, Any], None]) -> None:
        for operation in operations:
            fn(state, operation)

    for_ops(body.proposer_slashings, process_proposer_slashing)
    for_ops(body.attester_slashings, process_attester_slashing)
    for_ops(body.attestations, process_attestation)
    for_ops(body.deposits, process_deposit)
    for_ops(body.voluntary_exits, process_voluntary_exit)
    for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)  # [Capella 中的新]
process_bls_to_execution_change
def process_bls_to_execution_change(state: BeaconState,
                                    signed_address_change: SignedBLSToExecutionChange) -> None:
    address_change = signed_address_change.message

    assert address_change.validator_index &lt; len(state.validators)

    validator = state.validators[address_change.validator_index]

    assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX
    assert validator.withdrawal_credentials[1:] == hash(address_change.from_bls_pubkey)[1:]

    # 跨分叉的域,因为地址更改在跨分叉期间有效
    domain = compute_domain(DOMAIN_BLS_TO_EXECUTION_CHANGE, genesis_validators_root=state.genesis_validators_root)
    signing_root = compute_signing_root(address_change, domain)
    assert bls.Verify(address_change.from_bls_pubkey, signing_root, signed_address_change.signature)

    validator.withdrawal_credentials = (
        ETH1_ADDRESS_WITHDRAWAL_PREFIX
        + b'\x00' * 11
        + address_change.to_execution_address
    )
  • 原文链接: github.com/ethereum/cons...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
ethereum
ethereum
江湖只有他的大名,没有他的介绍。