Account Model & State

The vProgs account model draws inspiration from Solana’s design: accounts hold state data, and transactions pre-declare the accounts they will read and write. This pre-declaration is the key enabler of parallel processing on Kaspa’s BlockDAG – the system can identify non-conflicting transactions and process them concurrently without risking state corruption.


Core Design

Accounts as State Containers

In the vProgs model, an account is a stateful data container owned by a specific vProg. Each vProg p owns an exclusive set of accounts S_p:

  • Accounts hold arbitrary state data relevant to the owning vProg
  • Write access to S_p is exclusive to vProg p – no other program can modify these accounts
  • Read access is permissioned across programs, enabling cross-vProg composability
  • Each account has a well-defined state at every point in the global sequence T

Sovereign Ownership

The exclusivity of account ownership is a foundational security property:

vProg A                    vProg B                    vProg C
+-----------+              +-----------+              +-----------+
| Account 1 |              | Account 4 |              | Account 7 |
| Account 2 |              | Account 5 |              | Account 8 |
| Account 3 |              | Account 6 |              | Account 9 |
+-----------+              +-----------+              +-----------+
     S_a                        S_b                        S_c

  - Write: only A             - Write: only B             - Write: only C
  - Read: A, B, C (*)         - Read: A, B, C (*)         - Read: A, B, C (*)

(*) Cross-vProg reads require concise witnesses

This design means:

  • No shared mutable state between programs – eliminates reentrancy attack classes
  • Independent failure domains – a bug in vProg A cannot corrupt vProg B’s state
  • Per-vProg resource regulation – each program controls its own gas scales and STORM constants
  • Parallel proving – provers for different vProgs can operate without coordination

Transaction Structure

Each transaction x specifies three sets:

Set Symbol Description
Read set r(x) Accounts the transaction will read
Write set w(x) Accounts the transaction will modify
Witness set pi(x) Dependency resolution data (concise witnesses)

A critical constraint: w(x) must be a subset of r(x) – every account that is written must also be read. This ensures that the transaction has full context for any state it modifies.

Pre-Declaration Benefits

Declaring read/write sets upfront provides several architectural advantages:

  1. Parallel scheduling: Non-conflicting transactions (disjoint write sets) can be processed concurrently on the BlockDAG
  2. Deterministic conflict detection: The sequencing layer can identify and correctly serialize conflicting operations
  3. Scope computation: Provers can determine exactly which state they need to access
  4. Gas estimation: Resource costs can be calculated before execution
  5. MEV resistance: Deterministic scheduling reduces front-running opportunities

Computation DAG

The account model gives rise to a Computation DAG (CD) – a directed acyclic graph that tracks dependencies between account states across time.

Vertices and Edges

  • Vertices: v = (a, t) – represent account a’s state at time t in the global sequence
  • Hyperedges: Transactions connect input vertices (reads) to output vertices (writes)
Time -->   t1         t2         t3         t4

Acct A:    v(A,t1) ---------> v(A,t3) ----------> v(A,t4)
                   \                  /
                    \   tx_2         / tx_3
                     \              /
Acct B:    v(B,t1) -> v(B,t2) ----+
                     tx_1

tx_1: reads A,B; writes B
tx_2: reads A; writes A
tx_3: reads A,B; writes A

Dynamic dependency relationships form naturally as transactions reference each other’s outputs. This graph structure is what enables:

  • Scope computation – tracing backward to find what state a prover needs
  • Proof anchoring – compressing history at proven checkpoints
  • Parallelism identification – finding non-conflicting transaction sets

State Compression via Proof Anchoring

When a ZK proof is submitted and verified, it creates a trustless anchor point in the computation DAG. This enables:

  • Historical vertex deletion: State before the anchor can be pruned
  • Reduced scope computation: Future transactions only need to trace back to the nearest anchor
  • Efficient state verification: The anchor’s state commitment is cryptographically guaranteed
Before anchoring:
  v1 -> v2 -> v3 -> v4 -> v5 -> v6 -> v7 -> v8
  [------- full scope for proving v8 ---------]

After anchoring at v5 (ZK proof verified):
  [pruned] -> [anchor v5] -> v6 -> v7 -> v8
              [-- reduced scope for v8 --]

State Commitments

Each vProg’s state is periodically committed to L1 via a hierarchical Merkle structure:

C_p^t = MerkleRoot(
  state_root_step_1,
  state_root_step_2,
  ...
  state_root_step_n
)

Where each state_root_step_i is the Merkle root of all account states in S_p at step i since the last proof submission.

Concise Witnesses

This hierarchical structure enables concise witnesses – compact Merkle inclusion proofs that attest to a specific account’s state at a specific time. A concise witness proves:

“Account a in vProg p had state s at time t

…with a proof size logarithmic in the number of accounts and steps.

Concise witnesses are the mechanism that enables synchronous composability: when vProg_A needs to read state from vProg_B, it provides a concise witness as part of the transaction’s witness set pi(x).


Parallelism on the BlockDAG

The pre-declared read/write sets interact with Kaspa’s BlockDAG structure to enable parallel processing:

Conflict Detection

Two transactions x and y conflict if their write sets overlap:

conflict(x, y)  <=>  w(x) intersection w(y) != empty set

Non-conflicting transactions can be processed in any order or in parallel. Conflicting transactions must be serialized.

DAG-Aware Scheduling

The BlockDAG naturally enables parallel block production. With pre-declared account sets:

  1. Miners include transactions in parallel blocks
  2. DagKnight provides precise ordering of these parallel blocks
  3. Conflicting transactions in parallel blocks are correctly serialized by consensus
  4. Non-conflicting transactions execute in parallel, regardless of block ordering
Block 1 (miner A):          Block 2 (miner B):
  tx_1: w={acct_1}            tx_2: w={acct_3}      <-- no conflict,
  tx_3: w={acct_2}            tx_4: w={acct_4}          parallel OK

Block 3 (miner C):
  tx_5: w={acct_1}                                   <-- conflicts with
                                                         tx_1, serialized
                                                         by DagKnight

Scaling Properties

The parallelism scales with the number of independent account domains:

  • A network with 1000 active vProgs, each with disjoint accounts, can process 1000 streams of transactions in parallel
  • Cross-vProg reads do not create write conflicts (read-only access)
  • Only cross-vProg writes (which are forbidden – write access is exclusive) would create inter-program conflicts

Resource Management

Each vProg autonomously controls its own resource economy:

Gas Scales

Custom pricing for computation within a vProg. A compute-intensive vProg (e.g., ZK proof aggregation) can set higher gas prices than a simple token transfer vProg.

STORM Constants

Regulate state growth and throughput per vProg:

  • Storage growth rate – how fast accounts can be created
  • Throughput caps – maximum transactions per epoch
  • State size limits – bounds on total account data

Storage Costs

Transactions requiring permanent storage must compensate per the vProg’s defined scales. This internalizes the externality of state bloat – the vProg’s users pay for the state they consume.


Base Network Fee Proposal

In anticipation of the advanced capabilities introduced by vProgs, developers are actively discussing a 100x increase to the standard minimum network fee. This proposed change is designed to better secure the network against spam by making it significantly more expensive for attackers to flood blocks with low-value or arbitrary transactions.

Core developers are actively debating this minimum fee policy to balance micropayment viability with network abuse prevention. The current proposal is viewed as a temporary measure against spam rather than a long-term fee solution, and importantly, it can be adjusted by miners without requiring a hardfork.

Phase 1 vs. Phase 2 Account Model

Phase 1: Standalone (Current Target)

In Phase 1, the L1 has no notion of individual accounts within a vProg:

  • L1 is aware only of the overall vProg entity through its L1 covenant
  • The “degenerate” CD commit scheme groups activity by programs/subnets, not accounts
  • Each vProg is modeled as a single KIP-21 lane
  • Account-level state management is entirely internal to the vProg

Phase 2: Full Account Model

In Phase 2, the L1 gains awareness of per-account state:

  • Extended Computation DAG with per-account vertices
  • Cross-vProg atomic transactions via concise witnesses
  • Account-level read/write declarations in transactions
  • Full synchronous composability

The transition from Phase 1 to Phase 2 does not change the KIP-21 outer machinery – only the lane-local update rules change from program-level to account-level.


Comparison to Other Models

Property EVM (Ethereum) Solana vProgs
State model Global shared state Account-based with pre-declaration Account-based with pre-declaration
Write access Any contract can call any other Programs own accounts Exclusive write per vProg
Read access Unrestricted Unrestricted Permissioned via concise witnesses
Execution On-chain re-execution On-chain parallel execution Off-chain, ZK-verified
Conflict handling Serial (single thread) Parallel (non-conflicting) Parallel (BlockDAG + pre-declaration)
Reentrancy risk Yes (shared mutable state) Mitigated (program ownership) Eliminated (exclusive write + ZK)
State bloat Global problem Global problem Per-vProg regulation

Further Reading