Defines storage for Smart Contract Optimistic Rollups.
Commitments
Commitment
s are stored directly in the L1 context. Commitments are immutable and content-addressed, and can be indexed by a Commitment_hash
.
A commitment represents a claim about the state of a PVM.
We also keep auxiliary state about each commitment, namely:
- When it was first added.
- Its current number of stakers.
This auxiliary data is not part of the commitment itself. They represent information that the L1 knows about the claim, not the claim itself.
Predecessors and Boot state
Each commitment contains the hash of its predecessor. Multiple commitments can have the same predecessor. Therefore, commitments form a Merkle tree.
Conceptually the root of this tree is the Commitment_hash.zero
. This commitment claims that the PVM (Proof-generating Virtual Machine) is in a pre-boot state and waiting to start booting by interpreting the boot sector with respect to the Machine semantics.
Cemented and Disputable commitments
Commitments accepted as true by the protocol are referred to as Cemented. A commitment that is not cemented is said to be disputable.
Stakers
The Stakers table maps Stakers (implicit accounts) to commitments hashes.
Let Stakers(S)
mean "looking up the key S in Stakers
".
A staker S
is directly staked on C
if Stakers(S) = C
. A staker S
is indirectly staked on C
if C
is an ancestor of Stakers(S)
in the commitment tree.
Dispute
Commitments that have at least one sibling are referred to as Disputed. More formally, a commitment C is disputed if at least one staker is not (directly or indirectly) staked on C.
Dispute resolution
The rollup protocol ensures that all disputes are resolved before cementing a commitment. Therefore, cemented commitments form a list rather than a tree.
In the context we only store the Last Cemented Commitment (LCC), which is by definition a descendant of zero
. We also store all Disputable commitments that have at least one Staker.
For example, assuming the full set of commitments for a rollup looks like this:
LCC staker1 staker2
| | |
| V |
V --c3 |
zero--c1 --c2--/ |
\ V
--c4------ c5
then commitments c2..c5
will be stored in the context.
Conflicts
Let Commitments(S) be the set of commitments directly staked on by staker S.
Two stakers A and B are:
- In total agreement iff Commitments(A) = Commitments(B).
- In partial agreement iff either Commitments(A) ⊂ Commitments(B), or Commitments(B) ⊂ Commitments(A).
- In conflict iff they are neither in total or partial agreement.
We can further refine a conflict to note what they are in conflict about, e.g. they may be in conflict about the inbox, about execution, or both. We can resolve conflicts by first resolving the conflict about inbox, then about execution (since execution is irrelevant if the inbox is not correct).
last_cemented_commitment context rollup
returns the last cemented commitment of the rollup.
If no commitments have been cemented, the rollup is said to be in a pre-boot state, and last_cemented_commitment = Commitment_hash.zero
.
May fail with:
Sc_rollup_does_not_exist
if rollup
does not exist
last_cemented_commitment_hash_with_level ctxt sc_rollup
returns the hash and level of the last cemented commitment (lcc) for sc_rollup
. If the rollup exists but no lcc exists, the initial commitment Sc_rollup.Commitment.zero
together with the rollup origination level is returned.
May fail with:
Sc_rollup_does_not_exist
if rollup
does not exist
get_commitment context rollup commitment_hash
returns the commitment with the given hash.
May fail with:
Sc_rollup_does_not_exist
if rollup
does not existSc_rollup_unknown_commitment
if commitment
does not exist
get_commitment_opt_unsafe context rollup commitment_hash
returns an Option.t
which is either a defined value containing the commitment with the given hash, or `None` if such a commitment does not exist. This function *must* be called only after they have checked for the existence of the rollup, and therefore it is not necessary for it to check for the existence of the rollup again. Otherwise, use the safe function get_commitment
.
get_commitment_unsafe context rollup commitment_hash
returns the commitment with the given hash. This function *must* be called only after they have checked for the existence of the rollup, and therefore it is not necessary for it to check for the existence of the rollup again. Otherwise, use the safe function get_commitment
.
May fail with:
Sc_rollup_unknown_commitment
if commitment
does not exist
set_commitment_added ctxt rollup node current
sets the commitment addition time of node
to current
iff the commitment time was not previously set, and leaves it unchanged otherwise.
get_predecessor_opt_unsafe ctxt rollup commitment_hash
returns an Option.t
value containing the rollup
commitment predecessor of commitment_hash
in the ctxt
, if any. It does not check for the existence of the rollup
.
check_if_commitments_are_related ~descendant ~ancestor
checks whether a commitment with hash ~ancestor
exists as a predecessor of ~descendant
, among the list of commitments stored for rollup
in ctxt
.
Hash a commitment and account for gas spent.