Onchain storage
Contract Storage
Storage: Each contract on EVM chain has storage trie that contains the values of the variables it holds. For example, if a contract has the following:
uint256 price;
mapping(address => uin256) balances;
Then the price value and all the pairs (address,uint256)
of the mapping are stored in the storage
trie of the contract.
At each block, a new trie is created containing all the values of the variables for this specific block. The root of the storage is stored in the contract information for that block.
Historical Values as Table
The zkCoprocessor exposes the data of the contract in a very well known form: an SQL table. More specifically, the zkCoprocessor keeps historical valuess for each block. In a nutshell, it is a time serie database that keeps appending the values of all variables tracked for each block.
Let's take the previous example with the two variables price
and balances
. The zkCoprocessor
exposes these two variables as two separated tables:
Table for single variables
The zkCoprocessor exposes a single table for all the different "single" variables (uint256, etc), not arrays or mappings.
Block | Price |
---|---|
b1 | p1 |
b2 | p2 |
Table for Aggregate Variables
The zkCoprocessor exposes a single table per "aggregate" variable such as a mapping and arrays.
Block | Key | Balance |
---|---|---|
b1 | k1 | 10 |
b1 | k2 | 20 |
b2 | k1 | 15 |
b2 | k2 | 20 |
As you can see, this table contains multiple rows for the same block, one for each entry in the mapping!
The reason the tables are exposed in this way is because it is the most sensible way to expose the historical values of a contract inside the rigid structure of SQL tables. Indeed, if one had all the variables inside a single table, it would look like the following:
Block | Key | Balance | Price |
---|---|---|---|
b1 | k1 | 10 | p1 |
b1 | k2 | 20 | p1 (same) |
b2 | k1 | 15 | p2 |
b2 | k2 | 20 | p2 (same) |
There would be useless and sometimes large repetition of elements. This is because contracts have variables have have only one dimension (uint256) or two dimensions (arrays) or more !
The next subsections are going deeper in the technicals of the storage, state and blocks transformation.