Zoom-in: A formal backbone model for the vProg computation DAG

Context/broader-outlook: vprog proposal.

The following presents a minimal formal model for the computational cost of synchronous composability for verifiable programs (vProgs) operating on a shared sequencer. The model defines a “computational scope”—the historical dependency subgraph a vProg must execute to validate a new transaction. The model shows that frequent zero-knowledge proof (ZKP) submissions act as a history compression mechanism, reducing this scope and thereby the cost of cross-vProg interaction.

1. The Model

Consider a system of vProgs interacting through a global, ordered sequence of operations.

  • vProg & Accounts: A verifiable program, p, is a state transition function combined with a set of accounts it exclusively owns, S_p. Only p has write-access to any account a \in S_p.

  • Operation sequence (T): The system’s evolution is defined by a global sequence of operations, T = \langle op_1, op_2, \dots \rangle, provided by a shared sequencer. An operation is either a Transaction (x) or a ZK-Proof Submission (z).

  • Transaction (x): An operation describing an intended state transition. It is defined by a tuple containing:

    • r(x): The declared read-set of account IDs.
    • w(x): The write-set of account IDs, with the constraint that w(x) \subseteq r(x).
    • \pi(x): The witness set. A (potentially empty) set of witnesses, where each proves the state of an account a at a specific time t'. These are provided to resolve the transaction’s dependency scope and are independent of the direct read-set r(x).
  • ZK-Proof submission & state commitments:

    • A proof object, z_p^i, submitted by vProg p, attests to the validity of its state transitions up to a time t. It contains a state commitment, C_p^t.
    • Structure: This commitment C_p^t is a Merkle root over the sequence of per-step state roots created by p since its last proof z_p^{i-1} (e.g., from time j to t=j+k).
    • Implication: This hierarchical structure is crucial because it allows for the creation of concise witnesses for the state of any account owned by p at any intermediate time between proof submissions.
  • Execution rule: Any vProg p that owns an account in w(x) must execute transaction x.

  • Remark on composability: This execution rule enables two primary forms of composable transactions:

    1. Single-writer composability: The write-set w(x) is owned by a single vProg, but the read-set r(x) includes accounts from other vProgs.
    2. Multi-writer composability: The write-set w(x) contains accounts owned by two or more vProgs. This implies a more complex interaction, such as a cross-vProg function call, and requires all owning vProgs to execute the transaction per the rule above.

2. The Computation DAG

The flow of state dependencies is modeled using a Computation DAG G = (V, E), whose structure is determined dynamically by the global sequence of transaction declarations.

  • Vertices (V): A vertex v = (a, t) represents the state of account a at time t. The state data for a vertex is not computed globally; instead, it is computed and stored locally by a vProg only when required by a scope execution.

  • Edges (E): The set E contains the system’s transactions. Each transaction x_t acts as a hyperedge, connecting a set of input vertices (its reads) to a set of output vertices (its writes).

  • Graph construction: When a transaction x_t appears in the sequence:

    1. New vertices are created for each account in its write-set, \{v_{a, t} \mid a \in w(x_t)\}.
    2. The transaction x_t itself is added to E, forming a dependency from the set of vertices it reads from to the set of new vertices it creates.
  • State compression: When a proof z_p^i appears in the sequence, it logically compresses the dependency history for all accounts in S_p. This creates a new, trustless anchor point in the DAG that other vProgs can reference. The historical vertices are now considered eligible for physical deletion by nodes after a safe time delay.

  • Remark on the write-set constraint: The rule w(x) \subseteq r(x), defined earlier, is enforced to ensure the DAG’s structure is independent of execution outcomes. If a transaction contains a conditional write to an account a_w \in w(x) that fails, the new vertex v_{a_w, t} must still be populated with a valid state. By requiring a_w to also be in the read-set r(x), we guarantee that the prior state of a_w is available to be carried forward.

3. Computational Scope

The scope is the set of historical transactions a vProg must re-execute to validate a new transaction, x_t.

  • Read vertices (R(x_t)): The dynamic set of graph vertices that the transaction’s declared read-set, r(x), resolves to at time t. For each account a \in r(x), this corresponds to the vertex v_{a,k} with the largest timestamp k < t.

  • Anchor set (A(p, x_t)): The set of vertices that serve as terminal points for the dependency traversal. For a vProg p executing x_t, this set includes:

    1. All vertices whose state is proven by a witness in \pi(x_t).
    2. All vertices for which p has already computed and stored the state data from a previous scope execution.
  • Scope definition: The scope is the set of historical transactions whose outputs are routable to the transaction’s inputs without passing through any known anchor. More formally:
    Let \text{routable}(S, A) be the set of all vertices v from which there exists a path to a vertex in the set S that does not pass through any vertex in the set A.

    The set of vertices in the scope is then V_{scope} = \text{routable}(R(x_t), A(p, x_t)).

    The Scope is the set of all transactions that created the vertices in V_{scope}.

    Note: this set can be computed procedurally by a backwards graph traversal, e.g., BFS, starting from the vertices in R(x_t) where the traversal along any path is halted upon reaching a vertex in the anchor set A(p, x_t).

  • Remark on witnesses and anchor time: Unaligned proof submissions can create “alternating” dependencies. The hierarchical state commitment structure solves this by allowing a transaction issuer to choose a single, globally consistent witness anchor time, t_{anchor}, for all provided witnesses. This transforms the starting point for the scope computation from a jagged edge into a clean, straight line, limiting the scope to the DAG segment between t_{anchor} and t.


Core Contributions

This model provides a formal ground for several key properties of the proposed architecture, centered on sovereignty, scalability, and the emergence of a shared economy.

First, the model provides a formalization of vProg sovereignty. Despite the shared environment, vProgs retain full autonomy. Liveness sovereignty is guaranteed because a vProg’s ability to execute and prove its own state is never contingent on the cooperation of its peers. Furthermore, resource sovereignty is provided by the Scope function, which allows a vProg to price the computational load of any transaction and protect itself from denial-of-service attacks.

Second, the model provides a rigorous framework for analyzing computational efficiency and scalability, which is detailed in the following section. The key insight is that system-wide performance exhibits a sharp phase transition that can be managed by tuning the proof frequency to prevent the formation of a giant dependency component.

Finally, the Scope cost function serves as a primitive for a shared economy. It creates a positive-sum game of “dependency elimination,” where self-interested vProgs are incentivized to compress their history, making them cheaper dependencies for the entire ecosystem. It also provides a foundation for sophisticated economic mechanisms like scope-cost sharing or Continuous Account Dependency (CAD).


Scalability and Phase Transitions

System-wide performance is a direct function of the proof epoch length, F, which we define as the number of transactions between consecutive proof submissions. Assuming a globally coordinated proof frequency for simplicity, the total computational overhead does not degrade linearly but exhibits a sharp phase transition. This means efficiency is maintained by keeping the proof epoch length sufficiently short. The dependency entanglement within an epoch can be analyzed by reducing the timed computation DAG to a timeless, undirected graph G'_F, where vertices are accounts and an edge connects any two accounts that interact within a transaction. In this reduced graph, the size of the largest connected component serves as a proxy for the maximum aggregate scope a single vProg might need to compute.

The formation of this graph can be modeled using the well-known Erdős–Rényi random graph model. Let N be the total number of accounts and q be the probability of a cross-vProg transaction. A classic result for random graphs is the existence of a sharp phase transition: a “giant component” emerges if the edge probability p (proportional to Fq/N^2) exceeds the critical threshold of 1/N. To avoid this, the epoch length must be kept below this threshold, approximately F < N/q. For any F below this value, the largest dependency clusters are small, on the order of O(\log N). This result implies that the computational overhead becomes manageable. Instead of the worst-case scenario where a vProg re-executes the entire epoch’s history—a cost of O(nC), where n is the number of vProgs and C is the ideal cost—the work for an average vProg is the cost of executing its own transactions, plus a small, logarithmically-sized fraction of other transactions.

While real-world transaction patterns may be non-uniform, similar critical threshold phenomena are known to exist in more complex models like power-law graphs. The key insight remains: the model provides a formal basis for managing system-wide efficiency by tuning the proof epoch length F to stay within a region that prevents the formation of a giant dependency component. This efficiency mechanism is the foundation for the positive-sum game described earlier. Self-interested vProgs are incentivized to compress their history frequently, as doing so makes them cheaper and more attractive dependencies for the entire ecosystem. This economic pressure helps justify our initial simplifying assumption of a global proof epoch, as vProgs that fail to keep pace will effectively be excluded from composable interactions due to their high cost.

1 Like

Nice writeup!

Pls provide example explaining how defining scope as Past(R(x_t)) minus Past(p_{t-1}) does not hold. I’m using p_t as notation for the past of the prog’s state at time {t-1}

1 Like

There are two arguments as to why the pure past diff Past(R(x_t)) \setminus Past(p_{t-1}) does not suffice (related to the two terms in the anchor set).

  1. witnesses provided by the txn can cut the past diff thus reducing the scope size (ie a witness can be provided to a point way above Past(p_{t-1}))

  2. precisely because of the case above, being within Past(p_{t}) does not mean the transaction was actually computed by the prog, hence state data might be locally unknown for some vertices in this past (think of transactions within the past diff at time t but below the aforementioned cut).


The following case illustrates both points:

  • Prog p owns account A. Accounts B, C are foreign
  • A_{t-5} is the maximal vertex for account A at time t-1
  • Txn x_t reads from B_{t-1}, A_{t-5} and writes to A_t. It provides a witness directly to B_{t-1}
  • Txn x_{t-2} read from B_{t-3} and wrote to C_{t-2} and B_{t-1}
  • Txn x_{t-3} read from B_{t-4} and wrote to B_{t-3}
  • Txn x_{t+1} reads from C_{t-2} and writes to A_{t+1}. It provides a witness to B_{t-4}.

At time t, a witness was provided to B_{t-1}, so txns x_{t-2}, x_{t-3} were not executed by p, but entered its past.

At time t+1, a witness is provided to B_{t-4}, so p will need to execute x_{t-3}, x_{t-2} in order to compute C_{t-2} (despite being in its past already).

Edit: B_{t-1} should be technically named B_{t-2} to follow the correct indexing convention.

2 Likes

Why is

Why did x_{t-2} enter the past of p?

Edited to clarify the point.

There’s still some mismatch between text and drawing but the general point is understood – that the past of vp contains elements on which it is stateless (here B_{t-3},B_{t-4}).

Below is a short extension to the above regarding the gas design as I currently see it. I focused on the execution aspect for now though parts of the discussion may apply to other resources such as permanent/transient storage.


Gas Scaling Factor

  • GS(i) denotes the gas scale associated with VProg i.
    This reflects differences in proving environments across VProgs: distinct proving stacks may vary substantially in cost per unit of computation. Further, individual VProgs may wish to impose differing caps on their total proof resource usage. For simplicity, I will assume this scaling factor is transparent to L1.

Proof Gas Vector

  • PG(x) is the (unscaled) proof gas vector for transaction x.
    This is a sparse vector indexed by vProgs i such that x writes to i, where each entry PGᵢ(x) denotes an upper bound on the prover-side cost of including x in the execution trace of VProg i.

The intended role of PG(x) is:

  1. To support L1 enforced caps on the total proving load submitted per block for a VProg (adjusted to the gas scale)
  2. To enable reimbursement of provers within L2s, compensating them for their contributions according to the actual proving burden.

Previously we assumed the raw computation per tx consumed by a VProg (“logic zone” in older jargon) was in direct proportion to the proof costs and hence the two aspects could be capped as one. This is no longer the case, as we now expect VProg provers (and VProg users) to execute but not prove the transactions in their missing scope, which could result in substantial overhead which cannot be disregarded.


Execution Mass

To retain execution feasibility in light of the above, we must separately constrain the execution load.

  • EM(x) - the execution mass vector of transaction x, with each coordinate EM_v(x) representing the execution burden of x from the perspective of VProg v.

This execution mass of x is defined as:

EM_v(x)=\sum_{y\in scope(x,v)}\sum_i PG_i(y)⋅GS(i)/+∑PGi(x)⋅GS(i)

That is, a follower of v must execute all transactions in the scope of x (as needed to compute x) as well as x itself.

This expression defines a static upper bound on the compute burden placed on v, derivable solely from the DAG structure and the declared PG values, which can be inferred without execution of the transactions.

If L1 is made aware of the DAG structure, then EM(x) can be deterministically computed by miners, similar to transaction masses today. Otherwise, transaction issuers should include within the transaction an upper bound for the execution mass commitment (per VProg), where a transaction is only considered “valid” if the commitment exceeds the true value on all coordinates. Validity could be determined by a dedicated enshrined VProg aware of the Dag structure, for example. In either case, it is L1 that enforces a cap on the masses (or their commitments).


Potential Issue: DoS via Proof Gas Overestimation

To best illustrate this issue, consider a vProg v that is rarely written to, but frequently read from. A malicious transaction that writes to v with a vastly overstated PG_v will inflate EM_u(x) for the “next” transaction on all reading VProgs u, degrading execution performance.
While this impact is limited in to circa one transaction per u, it is cheap and can be repeated indefinitely if unconsummated gas is returned to the user. Some mechanism for discouraging overestimation may be necessary.

1 Like

Following offline discussions I have fixed the definition of a scope from using the past relation to using the routable definition. See above. Essentially using the past relation was wrong here as seen in the example above.