|
|
|
|
@@ -698,7 +698,7 @@
|
|
|
|
|
- name: compute_matrix
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="compute_matrix" fork="fulu" hash="b39370ca">
|
|
|
|
|
<spec fn="compute_matrix" fork="fulu" hash="0b88eac1">
|
|
|
|
|
def compute_matrix(blobs: Sequence[Blob]) -> Sequence[MatrixEntry]:
|
|
|
|
|
"""
|
|
|
|
|
Return the full, flattened sequence of matrix entries.
|
|
|
|
|
@@ -714,8 +714,8 @@
|
|
|
|
|
MatrixEntry(
|
|
|
|
|
cell=cell,
|
|
|
|
|
kzg_proof=proof,
|
|
|
|
|
row_index=blob_index,
|
|
|
|
|
column_index=cell_index,
|
|
|
|
|
row_index=blob_index,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
return matrix
|
|
|
|
|
@@ -739,7 +739,7 @@
|
|
|
|
|
- file: beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go
|
|
|
|
|
search: func computeOnChainAggregate(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="compute_on_chain_aggregate" fork="electra" hash="128055d6">
|
|
|
|
|
<spec fn="compute_on_chain_aggregate" fork="electra" hash="f020af4c">
|
|
|
|
|
def compute_on_chain_aggregate(network_aggregates: Sequence[Attestation]) -> Attestation:
|
|
|
|
|
aggregates = sorted(
|
|
|
|
|
network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0]
|
|
|
|
|
@@ -760,8 +760,8 @@
|
|
|
|
|
return Attestation(
|
|
|
|
|
aggregation_bits=aggregation_bits,
|
|
|
|
|
data=data,
|
|
|
|
|
committee_bits=committee_bits,
|
|
|
|
|
signature=signature,
|
|
|
|
|
committee_bits=committee_bits,
|
|
|
|
|
)
|
|
|
|
|
</spec>
|
|
|
|
|
|
|
|
|
|
@@ -2366,40 +2366,18 @@
|
|
|
|
|
- file: beacon-chain/state/state-native/getters_withdrawal.go
|
|
|
|
|
search: func (b *BeaconState) ExpectedWithdrawals(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="get_expected_withdrawals" fork="capella" hash="09191977">
|
|
|
|
|
def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]:
|
|
|
|
|
epoch = get_current_epoch(state)
|
|
|
|
|
<spec fn="get_expected_withdrawals" fork="capella" hash="d6a98c14">
|
|
|
|
|
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
# Get validators sweep withdrawals
|
|
|
|
|
validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
|
|
|
|
|
get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
|
|
|
|
)
|
|
|
|
|
withdrawals.extend(validators_sweep_withdrawals)
|
|
|
|
|
|
|
|
|
|
return withdrawals, processed_validators_sweep_count
|
|
|
|
|
</spec>
|
|
|
|
|
|
|
|
|
|
- name: get_expected_withdrawals#electra
|
|
|
|
|
@@ -2407,80 +2385,26 @@
|
|
|
|
|
- file: beacon-chain/state/state-native/getters_withdrawal.go
|
|
|
|
|
search: func (b *BeaconState) ExpectedWithdrawals(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="get_expected_withdrawals" fork="electra" hash="060932cd">
|
|
|
|
|
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
|
|
|
|
|
epoch = get_current_epoch(state)
|
|
|
|
|
<spec fn="get_expected_withdrawals" fork="electra" hash="cfce862b">
|
|
|
|
|
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64, uint64]:
|
|
|
|
|
withdrawal_index = state.next_withdrawal_index
|
|
|
|
|
validator_index = state.next_withdrawal_validator_index
|
|
|
|
|
withdrawals: List[Withdrawal] = []
|
|
|
|
|
processed_partial_withdrawals_count = 0
|
|
|
|
|
|
|
|
|
|
# [New in Electra:EIP7251]
|
|
|
|
|
# Consume pending partial withdrawals
|
|
|
|
|
for withdrawal in state.pending_partial_withdrawals:
|
|
|
|
|
if (
|
|
|
|
|
withdrawal.withdrawable_epoch > epoch
|
|
|
|
|
or len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP
|
|
|
|
|
):
|
|
|
|
|
break
|
|
|
|
|
# Get partial withdrawals
|
|
|
|
|
partial_withdrawals, withdrawal_index, processed_partial_withdrawals_count = (
|
|
|
|
|
get_pending_partial_withdrawals(state, withdrawal_index, withdrawals)
|
|
|
|
|
)
|
|
|
|
|
withdrawals.extend(partial_withdrawals)
|
|
|
|
|
|
|
|
|
|
validator = state.validators[withdrawal.validator_index]
|
|
|
|
|
has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
|
|
|
|
|
total_withdrawn = sum(
|
|
|
|
|
w.amount for w in withdrawals if w.validator_index == withdrawal.validator_index
|
|
|
|
|
)
|
|
|
|
|
balance = state.balances[withdrawal.validator_index] - total_withdrawn
|
|
|
|
|
has_excess_balance = balance > MIN_ACTIVATION_BALANCE
|
|
|
|
|
if (
|
|
|
|
|
validator.exit_epoch == FAR_FUTURE_EPOCH
|
|
|
|
|
and has_sufficient_effective_balance
|
|
|
|
|
and has_excess_balance
|
|
|
|
|
):
|
|
|
|
|
withdrawable_balance = min(balance - MIN_ACTIVATION_BALANCE, withdrawal.amount)
|
|
|
|
|
withdrawals.append(
|
|
|
|
|
Withdrawal(
|
|
|
|
|
index=withdrawal_index,
|
|
|
|
|
validator_index=withdrawal.validator_index,
|
|
|
|
|
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
|
|
|
|
amount=withdrawable_balance,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
withdrawal_index += WithdrawalIndex(1)
|
|
|
|
|
# Get validators sweep withdrawals
|
|
|
|
|
validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
|
|
|
|
|
get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
|
|
|
|
)
|
|
|
|
|
withdrawals.extend(validators_sweep_withdrawals)
|
|
|
|
|
|
|
|
|
|
processed_partial_withdrawals_count += 1
|
|
|
|
|
|
|
|
|
|
# Sweep for remaining.
|
|
|
|
|
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
|
|
|
|
for _ in range(bound):
|
|
|
|
|
validator = state.validators[validator_index]
|
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
|
total_withdrawn = sum(w.amount for w in withdrawals if w.validator_index == validator_index)
|
|
|
|
|
balance = state.balances[validator_index] - total_withdrawn
|
|
|
|
|
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:]),
|
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
|
amount=balance - get_max_effective_balance(validator),
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
withdrawal_index += WithdrawalIndex(1)
|
|
|
|
|
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
|
|
|
|
break
|
|
|
|
|
validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
|
|
|
|
return withdrawals, processed_partial_withdrawals_count
|
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
|
return withdrawals, processed_partial_withdrawals_count, processed_validators_sweep_count
|
|
|
|
|
</spec>
|
|
|
|
|
|
|
|
|
|
- name: get_filtered_block_tree
|
|
|
|
|
@@ -3053,7 +2977,7 @@
|
|
|
|
|
- name: get_proposer_head
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="get_proposer_head" fork="phase0" hash="15d44290">
|
|
|
|
|
<spec fn="get_proposer_head" fork="phase0" hash="99e8fc05">
|
|
|
|
|
def get_proposer_head(store: Store, head_root: Root, slot: Slot) -> Root:
|
|
|
|
|
head_block = store.blocks[head_root]
|
|
|
|
|
parent_root = head_block.parent_root
|
|
|
|
|
@@ -3084,7 +3008,10 @@
|
|
|
|
|
head_weak = is_head_weak(store, head_root)
|
|
|
|
|
|
|
|
|
|
# Check that the missing votes are assigned to the parent and not being hoarded.
|
|
|
|
|
parent_strong = is_parent_strong(store, parent_root)
|
|
|
|
|
parent_strong = is_parent_strong(store, head_root)
|
|
|
|
|
|
|
|
|
|
# Re-org more aggressively if there is a proposer equivocation in the previous slot.
|
|
|
|
|
proposer_equivocation = is_proposer_equivocation(store, head_root)
|
|
|
|
|
|
|
|
|
|
if all(
|
|
|
|
|
[
|
|
|
|
|
@@ -3100,6 +3027,8 @@
|
|
|
|
|
):
|
|
|
|
|
# We can re-org the current head by building upon its parent block.
|
|
|
|
|
return parent_root
|
|
|
|
|
elif all([head_weak, current_time_ok, proposer_equivocation]):
|
|
|
|
|
return parent_root
|
|
|
|
|
else:
|
|
|
|
|
return head_root
|
|
|
|
|
</spec>
|
|
|
|
|
@@ -3117,11 +3046,10 @@
|
|
|
|
|
- name: get_proposer_score
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="get_proposer_score" fork="phase0" hash="164b8de0">
|
|
|
|
|
<spec fn="get_proposer_score" fork="phase0" hash="2c8d8a27">
|
|
|
|
|
def get_proposer_score(store: Store) -> Gwei:
|
|
|
|
|
justified_checkpoint_state = store.checkpoint_states[store.justified_checkpoint]
|
|
|
|
|
committee_weight = get_total_active_balance(justified_checkpoint_state) // SLOTS_PER_EPOCH
|
|
|
|
|
return (committee_weight * PROPOSER_SCORE_BOOST) // 100
|
|
|
|
|
return compute_proposer_score(justified_checkpoint_state)
|
|
|
|
|
</spec>
|
|
|
|
|
|
|
|
|
|
- name: get_randao_mix
|
|
|
|
|
@@ -3509,26 +3437,10 @@
|
|
|
|
|
- file: beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go
|
|
|
|
|
search: func (f *ForkChoice) Weight(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="get_weight" fork="phase0" hash="f2e4e8ef">
|
|
|
|
|
<spec fn="get_weight" fork="phase0" hash="b18bf25c">
|
|
|
|
|
def get_weight(store: Store, root: Root) -> Gwei:
|
|
|
|
|
state = store.checkpoint_states[store.justified_checkpoint]
|
|
|
|
|
unslashed_and_active_indices = [
|
|
|
|
|
i
|
|
|
|
|
for i in get_active_validator_indices(state, get_current_epoch(state))
|
|
|
|
|
if not state.validators[i].slashed
|
|
|
|
|
]
|
|
|
|
|
attestation_score = Gwei(
|
|
|
|
|
sum(
|
|
|
|
|
state.validators[i].effective_balance
|
|
|
|
|
for i in unslashed_and_active_indices
|
|
|
|
|
if (
|
|
|
|
|
i in store.latest_messages
|
|
|
|
|
and i not in store.equivocating_indices
|
|
|
|
|
and get_ancestor(store, store.latest_messages[i].root, store.blocks[root].slot)
|
|
|
|
|
== root
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
attestation_score = get_attestation_score(store, root, state)
|
|
|
|
|
if store.proposer_boost_root == Root():
|
|
|
|
|
# Return only attestation score if ``proposer_boost_root`` is not set
|
|
|
|
|
return attestation_score
|
|
|
|
|
@@ -3615,7 +3527,7 @@
|
|
|
|
|
- file: beacon-chain/core/transition/state.go
|
|
|
|
|
search: func GenesisBeaconState(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="initialize_beacon_state_from_eth1" fork="phase0" hash="c69537d6">
|
|
|
|
|
<spec fn="initialize_beacon_state_from_eth1" fork="phase0" hash="d3a0ddd4">
|
|
|
|
|
def initialize_beacon_state_from_eth1(
|
|
|
|
|
eth1_block_hash: Hash32, eth1_timestamp: uint64, deposits: Sequence[Deposit]
|
|
|
|
|
) -> BeaconState:
|
|
|
|
|
@@ -3627,7 +3539,7 @@
|
|
|
|
|
state = BeaconState(
|
|
|
|
|
genesis_time=eth1_timestamp + GENESIS_DELAY,
|
|
|
|
|
fork=fork,
|
|
|
|
|
eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
|
|
|
|
|
eth1_data=Eth1Data(deposit_count=uint64(len(deposits)), block_hash=eth1_block_hash),
|
|
|
|
|
latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
|
|
|
|
|
randao_mixes=[eth1_block_hash]
|
|
|
|
|
* EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
|
|
|
|
|
@@ -4162,10 +4074,11 @@
|
|
|
|
|
- name: is_parent_strong
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="is_parent_strong" fork="phase0" hash="e06641a8">
|
|
|
|
|
def is_parent_strong(store: Store, parent_root: Root) -> bool:
|
|
|
|
|
<spec fn="is_parent_strong" fork="phase0" hash="02a3fd0b">
|
|
|
|
|
def is_parent_strong(store: Store, root: Root) -> bool:
|
|
|
|
|
justified_state = store.checkpoint_states[store.justified_checkpoint]
|
|
|
|
|
parent_threshold = calculate_committee_fraction(justified_state, REORG_PARENT_WEIGHT_THRESHOLD)
|
|
|
|
|
parent_root = store.blocks[root].parent_root
|
|
|
|
|
parent_weight = get_weight(store, parent_root)
|
|
|
|
|
return parent_weight > parent_threshold
|
|
|
|
|
</spec>
|
|
|
|
|
@@ -4683,7 +4596,7 @@
|
|
|
|
|
- file: beacon-chain/blockchain/receive_block.go
|
|
|
|
|
search: func (s *Service) ReceiveBlock(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="on_block" fork="phase0" hash="aff24b59">
|
|
|
|
|
<spec fn="on_block" fork="phase0" hash="5f45947a">
|
|
|
|
|
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
|
|
|
|
block = signed_block.message
|
|
|
|
|
# Parent block must be known
|
|
|
|
|
@@ -4713,19 +4626,8 @@
|
|
|
|
|
# Add new state for this block to the store
|
|
|
|
|
store.block_states[block_root] = state
|
|
|
|
|
|
|
|
|
|
# Add block timeliness to the store
|
|
|
|
|
seconds_since_genesis = store.time - store.genesis_time
|
|
|
|
|
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
|
|
|
|
epoch = get_current_store_epoch(store)
|
|
|
|
|
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
|
|
|
|
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
|
|
|
|
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
|
|
|
|
store.block_timeliness[hash_tree_root(block)] = is_timely
|
|
|
|
|
|
|
|
|
|
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
|
|
|
|
is_first_block = store.proposer_boost_root == Root()
|
|
|
|
|
if is_timely and is_first_block:
|
|
|
|
|
store.proposer_boost_root = hash_tree_root(block)
|
|
|
|
|
record_block_timeliness(store, block_root)
|
|
|
|
|
update_proposer_boost_root(store, block_root)
|
|
|
|
|
|
|
|
|
|
# Update checkpoints in store if necessary
|
|
|
|
|
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
|
|
|
|
@@ -4739,7 +4641,7 @@
|
|
|
|
|
- file: beacon-chain/blockchain/receive_block.go
|
|
|
|
|
search: func (s *Service) ReceiveBlock(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="on_block" fork="bellatrix" hash="a3193d92">
|
|
|
|
|
<spec fn="on_block" fork="bellatrix" hash="e81d01c3">
|
|
|
|
|
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Run ``on_block`` upon receiving a new block.
|
|
|
|
|
@@ -4780,19 +4682,8 @@
|
|
|
|
|
# Add new state for this block to the store
|
|
|
|
|
store.block_states[block_root] = state
|
|
|
|
|
|
|
|
|
|
# Add block timeliness to the store
|
|
|
|
|
seconds_since_genesis = store.time - store.genesis_time
|
|
|
|
|
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
|
|
|
|
epoch = get_current_store_epoch(store)
|
|
|
|
|
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
|
|
|
|
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
|
|
|
|
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
|
|
|
|
store.block_timeliness[hash_tree_root(block)] = is_timely
|
|
|
|
|
|
|
|
|
|
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
|
|
|
|
is_first_block = store.proposer_boost_root == Root()
|
|
|
|
|
if is_timely and is_first_block:
|
|
|
|
|
store.proposer_boost_root = hash_tree_root(block)
|
|
|
|
|
record_block_timeliness(store, block_root)
|
|
|
|
|
update_proposer_boost_root(store, block_root)
|
|
|
|
|
|
|
|
|
|
# Update checkpoints in store if necessary
|
|
|
|
|
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
|
|
|
|
@@ -4806,7 +4697,7 @@
|
|
|
|
|
- file: beacon-chain/blockchain/receive_block.go
|
|
|
|
|
search: func (s *Service) ReceiveBlock(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="on_block" fork="capella" hash="560056ad">
|
|
|
|
|
<spec fn="on_block" fork="capella" hash="7450531c">
|
|
|
|
|
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Run ``on_block`` upon receiving a new block.
|
|
|
|
|
@@ -4839,19 +4730,8 @@
|
|
|
|
|
# Add new state for this block to the store
|
|
|
|
|
store.block_states[block_root] = state
|
|
|
|
|
|
|
|
|
|
# Add block timeliness to the store
|
|
|
|
|
seconds_since_genesis = store.time - store.genesis_time
|
|
|
|
|
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
|
|
|
|
epoch = get_current_store_epoch(store)
|
|
|
|
|
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
|
|
|
|
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
|
|
|
|
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
|
|
|
|
store.block_timeliness[hash_tree_root(block)] = is_timely
|
|
|
|
|
|
|
|
|
|
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
|
|
|
|
is_first_block = store.proposer_boost_root == Root()
|
|
|
|
|
if is_timely and is_first_block:
|
|
|
|
|
store.proposer_boost_root = hash_tree_root(block)
|
|
|
|
|
record_block_timeliness(store, block_root)
|
|
|
|
|
update_proposer_boost_root(store, block_root)
|
|
|
|
|
|
|
|
|
|
# Update checkpoints in store if necessary
|
|
|
|
|
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
|
|
|
|
@@ -4865,7 +4745,7 @@
|
|
|
|
|
- file: beacon-chain/blockchain/receive_block.go
|
|
|
|
|
search: func (s *Service) ReceiveBlock(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="on_block" fork="deneb" hash="9565acee">
|
|
|
|
|
<spec fn="on_block" fork="deneb" hash="bbad196e">
|
|
|
|
|
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Run ``on_block`` upon receiving a new block.
|
|
|
|
|
@@ -4903,19 +4783,8 @@
|
|
|
|
|
# Add new state for this block to the store
|
|
|
|
|
store.block_states[block_root] = state
|
|
|
|
|
|
|
|
|
|
# Add block timeliness to the store
|
|
|
|
|
seconds_since_genesis = store.time - store.genesis_time
|
|
|
|
|
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
|
|
|
|
epoch = get_current_store_epoch(store)
|
|
|
|
|
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
|
|
|
|
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
|
|
|
|
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
|
|
|
|
store.block_timeliness[hash_tree_root(block)] = is_timely
|
|
|
|
|
|
|
|
|
|
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
|
|
|
|
is_first_block = store.proposer_boost_root == Root()
|
|
|
|
|
if is_timely and is_first_block:
|
|
|
|
|
store.proposer_boost_root = hash_tree_root(block)
|
|
|
|
|
record_block_timeliness(store, block_root)
|
|
|
|
|
update_proposer_boost_root(store, block_root)
|
|
|
|
|
|
|
|
|
|
# Update checkpoints in store if necessary
|
|
|
|
|
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
|
|
|
|
@@ -4929,7 +4798,7 @@
|
|
|
|
|
- file: beacon-chain/blockchain/receive_block.go
|
|
|
|
|
search: func (s *Service) ReceiveBlock(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="on_block" fork="fulu" hash="4f955de9">
|
|
|
|
|
<spec fn="on_block" fork="fulu" hash="b8f279b9">
|
|
|
|
|
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Run ``on_block`` upon receiving a new block.
|
|
|
|
|
@@ -4967,19 +4836,8 @@
|
|
|
|
|
# Add new state for this block to the store
|
|
|
|
|
store.block_states[block_root] = state
|
|
|
|
|
|
|
|
|
|
# Add block timeliness to the store
|
|
|
|
|
seconds_since_genesis = store.time - store.genesis_time
|
|
|
|
|
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
|
|
|
|
epoch = get_current_store_epoch(store)
|
|
|
|
|
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
|
|
|
|
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
|
|
|
|
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
|
|
|
|
store.block_timeliness[hash_tree_root(block)] = is_timely
|
|
|
|
|
|
|
|
|
|
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
|
|
|
|
is_first_block = store.proposer_boost_root == Root()
|
|
|
|
|
if is_timely and is_first_block:
|
|
|
|
|
store.proposer_boost_root = hash_tree_root(block)
|
|
|
|
|
record_block_timeliness(store, block_root)
|
|
|
|
|
update_proposer_boost_root(store, block_root)
|
|
|
|
|
|
|
|
|
|
# Update checkpoints in store if necessary
|
|
|
|
|
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
|
|
|
|
@@ -5074,7 +4932,7 @@
|
|
|
|
|
- name: prepare_execution_payload#capella
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="prepare_execution_payload" fork="capella" hash="28db1590">
|
|
|
|
|
<spec fn="prepare_execution_payload" fork="capella" hash="c258893e">
|
|
|
|
|
def prepare_execution_payload(
|
|
|
|
|
state: BeaconState,
|
|
|
|
|
safe_block_hash: Hash32,
|
|
|
|
|
@@ -5087,12 +4945,15 @@
|
|
|
|
|
parent_hash = state.latest_execution_payload_header.block_hash
|
|
|
|
|
|
|
|
|
|
# Set the forkchoice head and initiate the payload build process
|
|
|
|
|
# [New in Capella]
|
|
|
|
|
withdrawals, _ = get_expected_withdrawals(state)
|
|
|
|
|
|
|
|
|
|
payload_attributes = PayloadAttributes(
|
|
|
|
|
timestamp=compute_time_at_slot(state, state.slot),
|
|
|
|
|
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
|
|
|
|
suggested_fee_recipient=suggested_fee_recipient,
|
|
|
|
|
# [New in Capella]
|
|
|
|
|
withdrawals=get_expected_withdrawals(state),
|
|
|
|
|
withdrawals=withdrawals,
|
|
|
|
|
)
|
|
|
|
|
return execution_engine.notify_forkchoice_updated(
|
|
|
|
|
head_block_hash=parent_hash,
|
|
|
|
|
@@ -5105,7 +4966,7 @@
|
|
|
|
|
- name: prepare_execution_payload#deneb
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="prepare_execution_payload" fork="deneb" hash="f3387ec6">
|
|
|
|
|
<spec fn="prepare_execution_payload" fork="deneb" hash="59f61f3a">
|
|
|
|
|
def prepare_execution_payload(
|
|
|
|
|
state: BeaconState,
|
|
|
|
|
safe_block_hash: Hash32,
|
|
|
|
|
@@ -5117,11 +4978,13 @@
|
|
|
|
|
parent_hash = state.latest_execution_payload_header.block_hash
|
|
|
|
|
|
|
|
|
|
# Set the forkchoice head and initiate the payload build process
|
|
|
|
|
withdrawals, _ = get_expected_withdrawals(state)
|
|
|
|
|
|
|
|
|
|
payload_attributes = PayloadAttributes(
|
|
|
|
|
timestamp=compute_time_at_slot(state, state.slot),
|
|
|
|
|
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
|
|
|
|
suggested_fee_recipient=suggested_fee_recipient,
|
|
|
|
|
withdrawals=get_expected_withdrawals(state),
|
|
|
|
|
withdrawals=withdrawals,
|
|
|
|
|
# [New in Deneb:EIP4788]
|
|
|
|
|
parent_beacon_block_root=hash_tree_root(state.latest_block_header),
|
|
|
|
|
)
|
|
|
|
|
@@ -5136,7 +4999,7 @@
|
|
|
|
|
- name: prepare_execution_payload#electra
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="prepare_execution_payload" fork="electra" hash="567b3739">
|
|
|
|
|
<spec fn="prepare_execution_payload" fork="electra" hash="5414b883">
|
|
|
|
|
def prepare_execution_payload(
|
|
|
|
|
state: BeaconState,
|
|
|
|
|
safe_block_hash: Hash32,
|
|
|
|
|
@@ -5149,7 +5012,7 @@
|
|
|
|
|
|
|
|
|
|
# [Modified in EIP7251]
|
|
|
|
|
# Set the forkchoice head and initiate the payload build process
|
|
|
|
|
withdrawals, _ = get_expected_withdrawals(state)
|
|
|
|
|
withdrawals, _, _ = get_expected_withdrawals(state)
|
|
|
|
|
|
|
|
|
|
payload_attributes = PayloadAttributes(
|
|
|
|
|
timestamp=compute_time_at_slot(state, state.slot),
|
|
|
|
|
@@ -5171,7 +5034,7 @@
|
|
|
|
|
- file: beacon-chain/core/blocks/attestation.go
|
|
|
|
|
search: func ProcessAttestationNoVerifySignature(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="process_attestation" fork="phase0" hash="6ac78cd0">
|
|
|
|
|
<spec fn="process_attestation" fork="phase0" hash="d8e86aa9">
|
|
|
|
|
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
|
|
|
|
data = attestation.data
|
|
|
|
|
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
|
|
|
|
|
@@ -5183,8 +5046,8 @@
|
|
|
|
|
assert len(attestation.aggregation_bits) == len(committee)
|
|
|
|
|
|
|
|
|
|
pending_attestation = PendingAttestation(
|
|
|
|
|
data=data,
|
|
|
|
|
aggregation_bits=attestation.aggregation_bits,
|
|
|
|
|
data=data,
|
|
|
|
|
inclusion_delay=state.slot - data.slot,
|
|
|
|
|
proposer_index=get_beacon_proposer_index(state),
|
|
|
|
|
)
|
|
|
|
|
@@ -7208,31 +7071,18 @@
|
|
|
|
|
- file: beacon-chain/core/blocks/withdrawals.go
|
|
|
|
|
search: func ProcessWithdrawals(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="process_withdrawals" fork="capella" hash="ed6a9c5a">
|
|
|
|
|
<spec fn="process_withdrawals" fork="capella" hash="901f9fc4">
|
|
|
|
|
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
|
|
|
|
expected_withdrawals = get_expected_withdrawals(state)
|
|
|
|
|
assert payload.withdrawals == expected_withdrawals
|
|
|
|
|
# Get expected withdrawals
|
|
|
|
|
withdrawals, processed_validators_sweep_count = get_expected_withdrawals(state)
|
|
|
|
|
assert payload.withdrawals == withdrawals
|
|
|
|
|
|
|
|
|
|
for withdrawal in expected_withdrawals:
|
|
|
|
|
decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
|
|
|
|
# Apply expected withdrawals
|
|
|
|
|
apply_withdrawals(state, withdrawals)
|
|
|
|
|
|
|
|
|
|
# Update the next withdrawal index if this block contained withdrawals
|
|
|
|
|
if len(expected_withdrawals) != 0:
|
|
|
|
|
latest_withdrawal = expected_withdrawals[-1]
|
|
|
|
|
state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)
|
|
|
|
|
|
|
|
|
|
# Update the next validator index to start the next withdrawal sweep
|
|
|
|
|
if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
|
|
|
|
# Next sweep starts after the latest withdrawal's validator index
|
|
|
|
|
next_validator_index = ValidatorIndex(
|
|
|
|
|
(expected_withdrawals[-1].validator_index + 1) % len(state.validators)
|
|
|
|
|
)
|
|
|
|
|
state.next_withdrawal_validator_index = next_validator_index
|
|
|
|
|
else:
|
|
|
|
|
# Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
|
|
|
|
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
|
|
|
|
|
# Update withdrawals fields in the state
|
|
|
|
|
update_next_withdrawal_index(state, withdrawals)
|
|
|
|
|
update_next_withdrawal_validator_index(state, processed_validators_sweep_count)
|
|
|
|
|
</spec>
|
|
|
|
|
|
|
|
|
|
- name: process_withdrawals#electra
|
|
|
|
|
@@ -7240,39 +7090,23 @@
|
|
|
|
|
- file: beacon-chain/core/blocks/withdrawals.go
|
|
|
|
|
search: func ProcessWithdrawals(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="process_withdrawals" fork="electra" hash="dd99a91f">
|
|
|
|
|
<spec fn="process_withdrawals" fork="electra" hash="67870972">
|
|
|
|
|
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
|
|
|
|
# [Modified in Electra:EIP7251]
|
|
|
|
|
expected_withdrawals, processed_partial_withdrawals_count = get_expected_withdrawals(state)
|
|
|
|
|
# Get expected withdrawals
|
|
|
|
|
withdrawals, processed_partial_withdrawals_count, processed_validators_sweep_count = (
|
|
|
|
|
get_expected_withdrawals(state)
|
|
|
|
|
)
|
|
|
|
|
assert payload.withdrawals == withdrawals
|
|
|
|
|
|
|
|
|
|
assert payload.withdrawals == expected_withdrawals
|
|
|
|
|
|
|
|
|
|
for withdrawal in expected_withdrawals:
|
|
|
|
|
decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
|
|
|
|
# Apply expected withdrawals
|
|
|
|
|
apply_withdrawals(state, withdrawals)
|
|
|
|
|
|
|
|
|
|
# Update withdrawals fields in the state
|
|
|
|
|
update_next_withdrawal_index(state, withdrawals)
|
|
|
|
|
# [New in Electra:EIP7251]
|
|
|
|
|
# Update pending partial withdrawals
|
|
|
|
|
state.pending_partial_withdrawals = state.pending_partial_withdrawals[
|
|
|
|
|
processed_partial_withdrawals_count:
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Update the next withdrawal index if this block contained withdrawals
|
|
|
|
|
if len(expected_withdrawals) != 0:
|
|
|
|
|
latest_withdrawal = expected_withdrawals[-1]
|
|
|
|
|
state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)
|
|
|
|
|
|
|
|
|
|
# Update the next validator index to start the next withdrawal sweep
|
|
|
|
|
if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
|
|
|
|
# Next sweep starts after the latest withdrawal's validator index
|
|
|
|
|
next_validator_index = ValidatorIndex(
|
|
|
|
|
(expected_withdrawals[-1].validator_index + 1) % len(state.validators)
|
|
|
|
|
)
|
|
|
|
|
state.next_withdrawal_validator_index = next_validator_index
|
|
|
|
|
else:
|
|
|
|
|
# Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
|
|
|
|
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
|
|
|
|
|
update_pending_partial_withdrawals(state, processed_partial_withdrawals_count)
|
|
|
|
|
update_next_withdrawal_validator_index(state, processed_validators_sweep_count)
|
|
|
|
|
</spec>
|
|
|
|
|
|
|
|
|
|
- name: queue_excess_active_balance
|
|
|
|
|
@@ -7303,7 +7137,7 @@
|
|
|
|
|
- name: recover_matrix
|
|
|
|
|
sources: []
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="recover_matrix" fork="fulu" hash="9b01f005">
|
|
|
|
|
<spec fn="recover_matrix" fork="fulu" hash="3db21f50">
|
|
|
|
|
def recover_matrix(
|
|
|
|
|
partial_matrix: Sequence[MatrixEntry], blob_count: uint64
|
|
|
|
|
) -> Sequence[MatrixEntry]:
|
|
|
|
|
@@ -7323,8 +7157,8 @@
|
|
|
|
|
MatrixEntry(
|
|
|
|
|
cell=cell,
|
|
|
|
|
kzg_proof=proof,
|
|
|
|
|
row_index=blob_index,
|
|
|
|
|
column_index=cell_index,
|
|
|
|
|
row_index=blob_index,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
return matrix
|
|
|
|
|
@@ -7373,7 +7207,7 @@
|
|
|
|
|
- file: beacon-chain/forkchoice/ro.go
|
|
|
|
|
search: func (ro *ROForkChoice) ShouldOverrideFCU(
|
|
|
|
|
spec: |
|
|
|
|
|
<spec fn="should_override_forkchoice_update" fork="bellatrix" hash="9a8043af">
|
|
|
|
|
<spec fn="should_override_forkchoice_update" fork="bellatrix" hash="c055d92a">
|
|
|
|
|
def should_override_forkchoice_update(store: Store, head_root: Root) -> bool:
|
|
|
|
|
head_block = store.blocks[head_root]
|
|
|
|
|
parent_root = head_block.parent_root
|
|
|
|
|
@@ -7414,7 +7248,7 @@
|
|
|
|
|
# `store.time` early, or by counting queued attestations during the head block's slot.
|
|
|
|
|
if current_slot > head_block.slot:
|
|
|
|
|
head_weak = is_head_weak(store, head_root)
|
|
|
|
|
parent_strong = is_parent_strong(store, parent_root)
|
|
|
|
|
parent_strong = is_parent_strong(store, head_root)
|
|
|
|
|
else:
|
|
|
|
|
head_weak = True
|
|
|
|
|
parent_strong = True
|
|
|
|
|
|