Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions specs/_features/focil/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ class InclusionList(Container):
slot: Slot
validator_index: ValidatorIndex
parent_root: Root
parent_hash: Hash32
transactions: List[Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
```

Expand Down Expand Up @@ -105,18 +104,12 @@ def is_valid_inclusion_list_signature(

```python
def get_inclusion_list_committee(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, IL_COMMITTEE_SIZE]:
"""
Get the inclusion list committee for the given ``slot``
"""
epoch = compute_epoch_at_slot(slot)
committees_per_slot = bit_floor(min(get_committee_count_per_slot(state, epoch), IL_COMMITTEE_SIZE))
members_per_committee = IL_COMMITTEE_SIZE // committees_per_slot

validator_indices: List[ValidatorIndex] = []
for idx in range(committees_per_slot):
beacon_committee = get_beacon_committee(state, slot, CommitteeIndex(idx))
validator_indices += beacon_committee[:members_per_committee]
return validator_indices
seed = get_seed(state, epoch, DOMAIN_IL_COMMITTEE)
indices = get_active_validator_indices(state, epoch)
start = (slot % SLOTS_PER_EPOCH) * IL_COMMITTEE_SIZE
end = start + IL_COMMITTEE_SIZE
return [indices[compute_shuffled_index(uint64(i), uint64(len(indices)), seed)] for i in range(start, end)]
```

## Beacon chain state transition function
Expand Down
40 changes: 22 additions & 18 deletions specs/_features/focil/fork-choice.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class Store(object):
checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict)
latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict)
unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict)
inclusion_lists: List[Transaction] # [New in FOCIL
inclusion_lists: Dict[Tuple[Slot, Root], List[InclusionList]] = field(default_factory=dict) # [New in FOCIL]
inclusion_list_equivocators: Dict[Tuple[Slot, Root], Set[ValidatorIndex]] = field(default_factory=dict)# [New in FOCIL]


### New `on_inclusion_list`
Expand All @@ -66,25 +67,28 @@ def on_inclusion_list(
# Verify inclusion list slot is bounded to the current slot
assert get_current_slot(store) == message.slot

state = store.block_states[message.beacon_block_root]
ilc = get_inclusion_list_committee(state, message.slot)
assert message.beacon_block_root in store.block_states
# Get the inclusion list committee for this slot
state = copy(store.block_states[message.beacon_block_root])
if state.slot < message.slot:
process_slots(state, message.slot)
inclusion_list_committee = get_inclusion_list_committee(state, message.slot)

# Verify inclusion list validator is part of the committee
assert message.validator_index in ilc
validator_index = message.validator_index
assert validator_index.validator_index in inclusion_list_committee

# Verify inclusion list signature
assert is_valid_inclusion_list_signature(state, signed_inclusion_list)

# Check if an inclusion list with the same slot and validator index exists
existing_inclusion_list = next(
(il for il in store.inclusion_lists
if il.slot == message.slot and il.validator_index == message.validator_index),
None
)

# If such an inclusion list exists, remove it
if existing_inclusion_list:
store.inclusion_lists.remove(existing_inclusion_list)
else:
# If no such inclusion list exists, add the new one
store.inclusion_lists.append(message)
```
root = hash_tree_root(inclusion_list_committee)
if validator_index not in inclusion_list_equivocators[(message.slot, root)]:
if validator_index in [il.validator_index for il in inclusion_lists[(message.slot, root)]]
il = [il for il in inclusion_lists[(message.slot, root)] if il.validator_index == validator_index][0]
if not il == message:
inclusion_list_equivocators[(message.slot, root)].add(validator_index)
else:
inclusion_lists[(message.slot, root)].append(message)
```


6 changes: 2 additions & 4 deletions specs/_features/focil/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@ This topic is used to propagate signed inclusion list as `SignedInclusionList`.
The following validations MUST pass before forwarding the `inclusion_list` on the network, assuming the alias `message = signed_inclusion_list.message`:

- _[REJECT]_ The slot `message.slot` is equal to current slot.
- _[IGNORE]_ The current time is `INCLUSION_LIST_CUT_OFF` seconds into the slot.
- _[REJECT]_ The transactions `message.transactions` length is within upperbound `MAX_TRANSACTIONS_PER_INCLUSION_LIST`.
- _[IGNORE]_ The `message` is the first valid message received from the validator with index `message.validate_index` and can be received no more than twice from the same validator index.
- _[IGNORE]_ The block hash `message.parent_block_hash` is a known execution payload in fork choice.
- _[IGNORE]_ The `message` is either the first or second valid message received from the validator with index `message.validator_index`.
- _[REJECT]_ The signature of `inclusion_list.signature` is valid with respect to the validator index.
- _[REJECT]_ The validator index is within the inclusion list committee in `get_inclusion_list_committee(state)`. The `state` is based from `message.parent_block_root` to processing the block up to the current slot as determined by the fork choice.
- _[REJECT]_ The validator index `message.validator_index` is within the inclusion list committee given by `get_inclusion_list_committee(state, message.slot)`, where the `state` is based on `message.parent_block_root` and processed up to `message.slot`. If the validator index cannot immediately be verified against the expected committee, the inclusion list MAY be queued for later processing while the committee for the branch of `message.parent_block_root` is calculated -- in such a case do not REJECT, instead IGNORE this message.

### The Req/Resp domain

Expand Down