Sequencer

Table of Contents

Sequencer Policy

Sequencer Policy is the process of optimistically enacting rules outside of consensus (the state-transition function in this context), and the choices can then be asynchronously validated by verifiers and the fault-proof.

In the context of superchain interoperability, sequencer policy is utilized to enable cross-chain message relay without adding additional state-transition complexity or cross-chain synchronicity to the protocol.

Block Building

The goal is to present information in a way where it is as efficient as possible for the block builder to only include executing messages that have a corresponding initiating message. It is not possible to enforce the ability to statically analyze a transaction, so execution MAY be required to determine the information required to include executing messages.

Static analysis

Note that static analysis is never reliable because even if the top level transaction.to is equal to the CrossL2Inbox, it is possible that there is a reentrant CALL. The block builder SHOULD NOT rely on static analysis for building blocks.

Dependency confirmations

The sequencer MAY include an executing message in a block with any desired level of confirmation safety around the dependency of the message.

Confirmation levels:

  • pre-confirmation: through direct signaling by the block builder of the initiating message.
  • direct-dependency confirmation: verify the inclusion of the initiating message, but not the transitive dependencies.
  • transitive-dependency confirmation: verify the message and all transitive dependencies are included in canonical blocks within the specified safety-view (unsafe/safe/finalized).

When operating at lower-safety confirmation levels, the block builder SHOULD re-validate included executing messages at an increased safety level, before the block is published.

Pre-confirmations

The block builder can include executing messages that have corresponding initiating messages that only have pre-confirmation levels of security if they trust the block builder that initiates.

Using an allowlist and identity turns sequencing into an integrated game which increases the ability for block builders to trust each other. Better pre-confirmation technology will help to scale the block builder set to untrusted actors.

Without pre-confirmations, the block builder cannot include messages of other concurrent block building work.

Pre-confirmations MAY be invalidated, and assumptions around message-validity SHOULD be treated with care.

Streaming pre-confirmations: "shreds"

In the context of low-latency block building, each pre-confirmation may be communicated in the form of a "shred": the most minimal atomic state-change that can be communicated between actors in the system.

In the context of cross-chain block-building, shreds may be used to communicate initiated cross-chain messages, to validate executing messages against.

Shreds may be streamed, and potentially signal rewinds in case of invalidated dependencies.

This block builder feature is in ongoing research, and may be developed and experimented with between block builders without further protocol rules changes.

Direct-dependency confirmation

By verifying the direct dependency the block-builder does not have to implement pre-confirmations, and can rely on its direct view of the remote chain.

The block builder MAY require cryptographic proof of the existence of the log that the identifier points to, if it trusts the remote canonical chain but not its RPC server.

The block builder MAY also trust a remote RPC and use the following algorithm to verify the existence of the log.

The following pseudocode represents how to check existence of a log based on an Identifier. If the value True is returned, then it is safe to include the transaction.

success, receipt = evm.apply_transaction(tx)

if not success:
  return True

for log in receipt.logs:
  if is_executing_message(log):
      id = abi.decode(log.data)
      messageHash = log.topics[1]

      # assumes there is a client for each chain in the dependency set
      eth = clients[id.chainid]

      if eth is None:
        return False

      logs = eth.getLogs(id.origin, from=id.blocknumber, to=id.blocknumber)
      log = filter(lambda x: x.index == id.logIndex && x.address == id.origin)
      if len(log) == 0:
        return False

      if messageHash != hash(encode(log[0])):
        return False

      block = eth.getBlockByNumber(id.blocknumber)

      if id.timestamp != block.timestamp:
        return False

return True

Transitive-dependency confirmation

When operating pessimistically, the direct-dependency validation may be applied recursively, to harden against unstable message guarantees at the cost of increased cross-chain latency.

The transitive dependencies may also be enforced with safe or even finalized safety-views over the blocks of the chains in the dependency set, to further ensure increased cross-chain safety.

Sponsorship

If a user does not have ether to pay for the gas of an executing message, application layer sponsorship solutions can be created. It is possible to create an MEV incentive by paying tx.origin in the executing message. This can be done by wrapping the L2ToL2CrossDomainMessenger with a pair of relaying contracts.

Security Considerations

Cross Chain Message Latency

The latency at which a cross chain message is relayed from the moment at which it was initiated is bottlenecked by the security of the preconfirmations. An initiating transaction and a executing transaction MAY have the same timestamp, meaning that a secure preconfirmation scheme enables atomic cross chain composability. Any sort of equivocation on behalf of the sequencer will result in the production of invalid blocks.