Try   HackMD

FOCIL Prysm Implementation Notes

Last updated date: Tuesday, January 14, 2025
Reference: Prysm PR #14754

Block Processing

Syncing a non-current slot block lacks an inclusion list

While a Prysm node syncing to the head of the chain, a node may lack historical inclusion lists. However, it still needs to call engine_newPayloadV5.

  • In Prysm, if the payload being synced is not for the current slot, the node uses an empty inclusion transaction list as there's nothing in the inclusion list cache.

Action Item: Review the engine API definition to clarify constraints for same-slot scenarios.

Node remembrance of unsatisfied inclusion list block root

The engine_newPayloadV5 API introduces a new argument, it's an inclusion list transactions field (Array of DATA). If any transactions are not part of the executionPayload (even if they can be appended at the end), the API returns:

  • Status: INVALID_INCLUSION_LIST
  • latestValidHash: null
  • validationError: null

If a newly imported execution payload is marked INVALID_INCLUSION_LIST, the Prysm node stores its block root as badInclusionListBlock. It's just a single root, as an inclusion list only applies to the current slot, so no more than one root should be cached at a given time.

Unsatisfied inclusion list block root filters the head root

Prysm node adds a new function, FilteredHeadRoot, which returns the filtered head root to be used for valiator duties. In the function, if the head root matches badInclusionListBlock, it returns the parent block of that root. This method is used for:

  • Attesters: To attest to beacon_block_root.
  • Sync committees: To vote on head_root.
  • Proposers: To build on top of parent_root.

Action Item:

  • The spec already contains get_proposer_head for reorg late block, we should use that and have a consistence place to return head for validator duty.

Block Building

Integrate inclusion lists into block building

Prysm node has a new background routine (updateInclusionListBlockInterval) for updating inclusion lists for execution layer block construction:

  1. Gather the current slot's inclusion list transactions.
  2. Filter out duplicates.
  3. Call engine_updatePayloadWithInclusionListV1 with the existing payloadID.
  4. Cache the new payloadID, which will be used for proposer at the slot of.

This routine runs only if the node is the next slot proposer and a payloadID already exists on top of headRoot for currentSlot + 1.

Action Item:

  • Review Beacon api event stream endpoint for payload attribute, whether we need to add inclusion list there.
  • Another design space is to overload forkchoiceUpdated + attribute to update inclusion list

Syncing

Gossip Validation Pipeline

Prysm has added gossip validation for inclusion lists following the specification. Key points:

  • Inclusion list transactions have the same SSZ list size as the execution payload.
  • Manual checks ensure transactions do not exceed 8 KB.

Action Item: Review and potentially reshuffle the gossip pipeline to address potential DoS concerns.

Inclusion list cache

Inclusion lists are cached in Prysm node using the following structure:

  • Key map[primitives.Slot]map[primitives.ValidatorIndex]
  • Value [][]byte (represents inclusion list transactions)
  • A special flag, seenTwice, tracks repeated entries.

The cache has these methods:

  • Add: Adds an inclusion list entry. If an entry is added twice or more, seenTwice is set to true, and the original transactions are removed.
  • SeenTwice: Returns true if the seenTwice flag is active for a given slot and index.
  • Get: Returns all inclusion list transactions for a slot, excluding duplicates.
  • Delete: Deletes all inclusion list transactions for a slot.

Design considerations:

  • Worst case memory usage is ~4 MB per slot (8 KB per validator, 512 validators per slot).
  • Frequent pruning is necessary. Potential strategies:
    • Prune after processing a block using the block's slot.
    • Use a background pruning routine to handle scenarios where on-chain liveness prevents immediate pruning.

Validator API

Inclusion list duty retrival

Inclusion list duties are returned alongside beacon committee and proposer duties. Prysm provides a gRPC API for this but has not yet added support for the beacon API.

Action Item:

  • Implement beacon API for inclusion lists.
  • Optimize inclusion list committee caching (current shuffling is expensive).

Inclusion list retrival for validator signing

The GetInclusionList endpoint:

  • Input: Slot (supports current and previous slots only).
  • Process:
    1. Fetch the head block hash.
    2. Retrieve the inclusion list from the execution client.
    3. Compute the inclusion list committee.
    4. Populate inclusion list fields and return them.
    5. Return InclusionList with transactions and sync committee root filled.

Note: it keeps the validator index empty. Inclusion list has a validator index field but validator client can just fill that themselves

Action Item: Cache inclusion list responses to prevent repeated execution client calls. Ensure the execution client doesn't prematurely remove transactions. The tradoff here is two seperate requests may produce the same outtime. Leaning towards client implementation detail.

Validator Client Changes

Validator client changes are straightforward:

  1. When a validator is assigned a duty, it waits until the duty time.
  2. Fetches the inclusion list (excluding the validator's own index) from the beacon node.
  3. Signs the inclusion list.
  4. Submits the signed version.