EIP-3076: Validator client interchange format (slashing protection)

Discussions with Trent Mohay on the Eth R&D discord raised some deficiencies in the current spec when it comes to potentially invalid data. I’ve been expanding the test coverage in the test repo, and have a few decisions that I need stakeholders to provide feedback on.

Decision 1: Duplicate Pubkeys

Presently the spec says nothing of the case where the data array contains multiple
entries with the same pubkey. We have three options:

  • ACCEPT: explicitly allow duplicate pubkeys
  • REJECT: explicitly reject duplicate pubkeys
  • ABSTAIN: leave duplicate pubkey semantics up to the implementation

Arguments for ACCEPT

  • Simple implementation. No need to add additional checks. Lighthouse and Teku
    use ACCEPT semantics, likely by accident.

Arguments for REJECT

  • There is little sense in allowing multiple entries when the inner arrays
    serve the same purpose.

Arguments for ABSTAIN

  • I can’t think of any.

Testing

The duplicate_pubkey_not_slashable test case exercises this code path.

Decision 2: Importing Slashable Data

It’s possible for an interchange file to contain blocks and attestations that
are mutually slashable, i.e. the interchange file contains evidence that the
validator has already committed a slashable offence. It’s also possible for
an interchange to contain messages that are slashable with respect to ones already
in the database.

Our options:

  • ACCEPT: require implementations to import files even if they contain slashable data
  • ACCEPT_PARTIAL: require implementations to import all validators that are not slashable,
    and reject all that are slashable
  • REJECT: require implementations to reject any imported file if it contains slashable data
  • ABSTAIN: allow implementations to choose a semantics that works for them

Arguments for ACCEPT

  • Rejecting a file could prompt a user to abandon the import rather than going through
    the tedious process of editing out the slashable/slashed validators by hand.

Arguments for ACCEPT_PARTIAL

  • As for ACCEPT: more inputs accepted, less user confusion
  • Unlike ACCEPT: compatible with databases that can’t store slashable messages (see REJECT).

Arguments for REJECT

  • Many slashing protection strategies assume that the database does not already
    contain any slashable messages, and store data according to this
    assumption. In these cases, enforcing ACCEPT semantics would greatly
    complicate both the specification and implementation, e.g. which of two slashable
    attestations that are surrounding should be kept and stored?
  • It’s reasonable for a slashing protection implementation to import an interchange file
    by processing each message as if it is a new message to be signed, which would necessarily
    reject any slashable data contained in the interchange file.

Arguments for ABSTAIN

  • Some slashing protection strategies (like Teku’s) handle this gracefully and can move
    forward even in the presence of existing slashable data.

Testing

The following test cases exercise these code paths:

  • single_validator_slashable_blocks
  • single_validator_slashable_attestations_double_vote
  • single_validator_slashable_attestations_surrounds_existing
  • single_validator_slashable_attestations_surrounded_by_existing

Decision 3: Ordering

The specification doesn’t currently place ordering requirements on blocks or attestations
within a file, but it may simplify implementation to do so.

  • ORDERED: require messages to be ordered, and for implementations to reject unordered files
  • UNORDERED: allow messages to be unordered, and require implementations to accept unordered files
  • ABSTAIN: allow implementations to choose ordered or unordered semantics

Arguments for ORDERED

  • Compatible with the import approach where messages are imported one-at-a-time as if they are
    new messages to be signed. If they are unordered, then an import will run afoul of the
    ordering conditions (2), (4) and (5).
  • It is straight-forward to order messages on export

Arguments for UNORDERED

  • It is also straight-forward to order messages on import, if required by the implementation

Arguments for ABSTAIN

  • I can’t think of any.

Testing

  • single_validator_out_of_order_blocks
  • single_validator_out_of_order_attestations

Decision 4: Signing Roots

Presently signing roots are optional, but this has some downsides, so we could consider making them
mandatory.

  • MANDATORY: require signing_root on all blocks and attestations
  • OPTIONAL: allow signing_root to be omitted

Arguments for MANDATORY

  • Simplifies slashability considerations: with
    the way the spec is worded now, we have to consider a message without a
    signing root as slashable with respect to any other message with the same
    slot/target epoch. This complicates several things, including:
    • (Assuming Decision 2: REJECT) Importing the same file twice if it
      lacks signing roots. The second time the same messages are imported
      they need to be considered slashable wrt the first import (no
      idempotence).
    • Import/export cycles between different clients. If I export with signing roots from
      implementation A, import to another implementation B that erases signing roots,
      and then later re-export from B to A, then A has no way of knowing that some of
      the included messages are actually fine because they’re the ones it signed earlier.
  • Most implementations with complete databases support signing roots
    (Lighthouse, web3signer, Prysm [soon]). Teku could be adapted to. I don’t
    know about Nimbus.

Arguments for OPTIONAL

  • No need to change Teku (particularly post-audit, so close to mainnet).