Links

Workflow

General Storage Proof Workflow

General Workflow

1. Accessing the block hash

Every piece of data on the blockchain belongs to a specific block. The block hash serves as a unique identifier for that block, summarizing all its contents, primarily through the block header. Before anything else in the storage proof workflow, we need to determine and authenticate the block hash of the block containing the data we're interested in.

2. Accessing the block header

Sample EVM header on Ethereum L1
Once we have access to the relevant block hash, our next step is to access the block header.
To do this, we hash the block header associated with the block hash we retrieved in the previous step. Next, the hash of the provided block header is compared to the block hash:
  • We retrieved using the BLOCKHASH opcode
or
  • The already-proven block hash from the Historical Block Hash Accumulator.
This step ensures that the block header being worked with is genuine. Once this step is complete, the smart contract can access any value found inside the block header.

3. Determining the Desired Root (Optional)

Root Node being the State Root
With the block header in hand, we can dive deeper into its contents, specifically:
  • stateRoot: A cryptographic summary of the entire state of the blockchain at the time of the block.
  • receiptsRoot: A cryptographic summary of all transaction outcomes (receipts) in the block.
  • transactionsRoot: A cryptographic summary of all transactions that took place in the block.
These roots can be decoded, enabling us to verify the inclusion of specific accounts, receipts, or transactions within the block.
For instance, if you're aiming to validate something against the state of Ethereum at that block height, you'd extract the stateRoot.

4. Verifying Data Against the Chosen Root (Optional)

Access account Storage Trie Root given a State Root
With the chosen root at our disposal and given that Ethereum employs the Merkle-Patricia Trie structure, we can utilize Merkle inclusion proofs to validate the presence of data within the tree. The steps for verification will vary based on the data and depth of the data within the block.
For instance:
  • Surface-Level Data: If you're verifying data that resides directly under the main trie (e.g., the balance of an account), then an inclusion proof against the selected root would suffice.
  • Deeper Data Layers: For data that lies deeper, such as information within an account's storage trie, additional inclusion proofs are necessary. This means that after confirming the account's existence in the state trie, a subsequent inclusion proof would be needed to verify a particular piece of data within that account's storage.
Further examples of storage proof workflows can be explored here.