LogoLogo
  • INTRODUCTION
  • LEARN
    • Espresso in the Modular Stack
    • The Espresso Network
      • System Overview
      • Properties of HotShot
        • EspressoDA
          • How It Works
      • Interfaces
        • Espresso ↔ Rollup
        • Espresso ↔ L1
        • Rollup ↔ L1
      • Internal Functionality
        • Espresso Node
        • Light Client Contract
        • Fee Token Contract
        • Stake Table
          • How the Stake Table Contract Works
        • Smart Contract Upgradeability
    • Rollup Stacks
      • Integrating a ZK Rollup
        • ZK Rollup Architecture
        • Using Espresso
        • Summary of Changes
      • Integrating an Optimistic Rollup
        • Optimistic Rollup Architecture
        • Using Espresso
        • Summary of Changes
  • Guides
    • Using the Espresso Network
      • Integrating Arbitrum Orbit Chain
        • Quickstart with Arbitrum Nitro Rollups
        • Reading Confirmations from the Espresso Network
        • Arbitrum Nitro Integration Overview
          • Using TEE with Nitro
          • Arbitrum Nitro Trust & Liveness Dependencies
        • Migrating Arbitrum Orbit Chains to Espresso
          • Arbitrum Testnet
            • Nitro Testnet
            • Local Deployment (`docker compose`)
      • Using the Espresso Network as a Cartesi application
    • Running an Espresso Node
    • Running a Builder
    • Bridging with the Espresso Network
  • API Reference
    • Espresso API
      • Status API
      • Catchup API
      • Availability API
      • Node API
      • State API
      • Events API
      • Submit API
      • Earlier Versions
        • v0
          • Status API
          • Catchup API
          • Availability API
          • Node API
          • State API
          • Events API
          • Submit API
    • Builder API
  • Releases
    • Mainnet 1
      • Running a Mainnet 1 Node
      • Contracts
      • Rollup Migration Guide
    • Mainnet 0
      • Running a Mainnet 0 Node
      • Contracts
    • Testnets
      • Decaf Testnet Release
        • Running a Node
        • Contracts
      • Cappuccino Testnet Release
        • Running a Node
        • Deploying a Rollup on Cappuccino
        • Benchmarks
      • Gibraltar Testnet Release
        • Interacting with Gibraltar
        • Arbitrum Nitro integration
        • Deploying a Rollup on Gibraltar
      • Cortado Testnet Release
        • Interacting with Cortado
        • OP Stack Integration
          • Optimism Leader Election RFP
      • Doppio Testnet Release
        • Interacting with Doppio
        • Polygon zkEVM Stack Integration
        • Minimal Rollup Example
        • Benchmarks
      • Americano Testnet Release
  • Appendix
    • Interacting with L1
      • Trustless Sync
      • Fork Recovery
      • Bridging
    • Glossary of Key Terms
Powered by GitBook
On this page
  1. LEARN
  2. The Espresso Network
  3. Interfaces

Espresso ↔ L1

PreviousEspresso ↔ RollupNextRollup ↔ L1

Last updated 8 months ago

Espresso interacts with the L1 via the sequencer contract, which validates HotShot consensus and provides a certified, trustless interface for other participants to check the sequence of blocks. Note that the contract only deals with short block commitments, not full blocks, in order to minimize the cost of sending data to the L1. Anyone who has verified a commitment against the contract can get the corresponding block—and authenticate it against the commitment—from the HotShot availability API.

Espresso interacts with the sequencer contract via an interface like:

// HotShot.sol
struct QC { /* Fields omitted */ } 

// Root of a Merkle tree accumulating the verified sequence of block commitments.
bytes32 public commitmentsRoot;

// Event emitted when new blocks are sequenced.
event NewBlocks(uint firstBlockNumber, uint256[] commitments, bytes32[] frontier);
 
// Called to append a chain of new blocks, given proof that consensus has finalized them.
function newBlocks(QC[] calldata qcs, bytes calldata proof, bytes32[] calldata frontier) external;

The newBlocks method allows a sequencer node to append a list of newly sequenced block commitments to the log stored in the contract. It takes a list of quorum certificates, a validity proof, and a corresponding to commitmentsRoot, and it validates that

  • Each QC extends from the previous QC in the chain (starting with the previously sequenced QC)

  • Each QC is properly signed (the contract will need to store and keep up-to-date the stake table)

  • There are enough QCs to prove finality for one or more block commitments. HotShot consensus currently requires a chain of at least 3 QCs before the first QC in the chain is considered finalized (an upcoming version of HotShot will only require a 2-chain of QCs)

If validation succeeds, it updates commitmentsRoot, which can then be used by other contracts to validate proofs of inclusion of block commitments in the sequence. On success, newBlocks emits a NewBlocks event informing clients (e.g. rollup provers) that new blocks have been appended. Those clients can read the new block commitments from the event logs using an Ethereum client. The event logs also include a snapshot of the Merkle frontier just before the new blocks were appended. A client can construct a Merkle path for any given commitment by appending commitments to the snapshotted frontier.

newBlocks will fail if the given batch has already been sequenced, since qcs will fail the check that it must extend from the last sequenced QC. This ensures that each batch of blocks will only be sequenced once — whoever calls this method first will be the one to sequence it. It is an open question whether the contract will explicitly incentivize sequencer nodes to call newBlocks.

To learn more about the sequencer contract, how it stores data, and how it validates QCs, read the section on .

Merkle frontier
its internal functionality