An in-depth look at how ZKsync ensures data availability through state diffs and compresses data to optimize L1 submissions, plus tools for reconstructing L2 state from L1 public data.

Data availability is a cornerstone of ZKsync's architecture, ensuring that the entire Layer 2 (L2) state can be reconstructed from the data submitted to Ethereum's Layer 1 (L1). This process not only secures the network but also optimizes cost-efficiency through innovative data management techniques.

State diffs: Optimizing storage slots

Instead of submitting detailed transaction data, ZKsync focuses on posting state diffs to L1. These diffs represent changes in the blockchain's state, enabling ZKsync to efficiently manage how data is stored and referenced:

  • Efficient Use of Storage Slots: Changes to the same storage slots across multiple transactions can be grouped, reducing the amount of data that needs to be sent to L1 and thereby lowering gas costs.
  • Compression Techniques: All data sent to L1, including state diffs, is compressed to further reduce costs. Read more about ZKsync's compression methods.

Additional data posted to L1

In addition to state diffs, ZKsync also posts other crucial information to ensure comprehensive data availability:

  • L2 to L1 Logs and Messages: These ensure that communications and events are recorded and accessible.
  • Published Bytecodes: The bytecodes of deployed smart contracts are made available, crucial for contract interaction and verification.
  • Compressed State Diffs: Further optimizes data management by reducing the size of state changes posted to L1.

Validiums and zkPorter: Balancing Security and Efficiency

When a chain opts not to post its data on-chain, it operates under a model known as a validium. This approach significantly reduces costs by keeping data off-chain but introduces risks related to data accessibility and security:

  • zkPorter: A hybrid model that combines features of rollups and validiums, zkPorter segments data responsibilities, allowing some storage slots to remain off-chain while critical data is posted to L1. Learn more about zkPorter.

Recreating L2 State From L1 Pubdata

ZKsync provides tools to validate and reconstruct the L2 state from data available on L1. Here's how this process is typically managed:

Basic Flow

  1. First, we need to filter all of the transactions to the L1 ZKsync contract for only the commitBlocks transactions where the proposed block has been referenced by a corresponding executeBlocks call (the reason for this is that a committed or even proven block can be reverted but an executed one cannot).
  2. Once we have all the committed blocks that have been executed, we then will pull the transaction input and the relevant fields. The kinds of pubdata we’ll pull from transaction data:
    • L2 to L1 Logs
    • L2 to L1 Messages
    • Published Bytecodes
    • Compressed State Diffs

Key components for state reconstruction

State Diffs

State diffs are essential for understanding changes within the blockchain's state, represented as key-value pairs:

naive way: ( storage_slot, address, value )
actual: ( derived_key, value )
compressed: ( derived_key or enumeration index, compressed_value )
  • Format: Typically presented as (derived_key, value), where derived_key is a hash of the storage slot and address, and value represents the storage value.
  • Compression and Enumeration: After the initial post, derived_key can be replaced with an enumeration index to optimize data size. The deeper meaning is that an enumeration key is the leaf index in our storage Merkle tree.

Contract Bytecodes

The handling of contract bytecodes involves:

  • Compression and Indexing: Opcodes are chunked, indexed, and compressed by the server-side operator before being verified and sent to L1.
  • Verification and Storage: A system contract ensures the accuracy of the compression before submission, with uncompressed bytecode hashes stored in AccountStorage for reference.

This process is split into 2 different parts:

The compressed bytecode makes it way up through factoryDeps and the hash of uncompressed bytecode is stored on the AccountStorage contract so the hash of the uncompressed bytecode will be part of the state diffs

Made with ❤️ by the ZKsync Community