Skip to main content

System Architecture Overview

Kosh is built in three layers, adapted to Midnight's unique execution model where contract logic is split across a public ledger, a zero-knowledge circuit, and a local off-chain environment.

Layer Diagram

┌──────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ │
│ Next.js 15 Frontend ←→ Lace Wallet (Chrome Extension) │
│ - Circle management UI │
│ - DApp Connector API v4.0.0 │
│ - Connects to localhost:3000 (dev) │
└───────────────────────────┬──────────────────────────────────┘

┌───────────────────────────▼──────────────────────────────────┐
│ APPLICATION LAYER │
│ │
│ TypeScript DApp (src/dapp/) │
│ ├── Witness functions (member secrets → ZK circuits) │
│ ├── Private state (LevelDB — member secrets local) │
│ ├── Contract interaction (midnight-js-contracts v3.1.0) │
│ └── Proof generation (HTTP → proof server :6300) │
└───────────────────────────┬──────────────────────────────────┘

┌───────────────────────────▼──────────────────────────────────┐
│ PROTOCOL LAYER │
│ │
│ rosca.compact (single monolithic Compact contract) │
│ ├── Public Ledger State │
│ │ ├── MerkleTree<4, Bytes<32>> (member commitments) │
│ │ ├── Set<Bytes<32>> (spent round identifiers) │
│ │ ├── Counter (current round) │
│ │ ├── CircleStatus enum (lifecycle state) │
│ │ └── Pool balance (aggregate NIGHT) │
│ ├── ZK Circuit Logic │
│ │ ├── Membership verification (Merkle path proof) │
│ │ ├── Contribution validation (amount + nullifier) │
│ │ ├── Payout authorization (position verification) │
│ │ └── Default identification (conditional disclosure) │
│ └── Zswap Token Operations │
│ ├── send() (member contribution to pool) │
│ └── receive() (payout from pool to recipient) │
└───────────────────────────┬──────────────────────────────────┘

┌───────────────────────────▼──────────────────────────────────┐
│ INFRASTRUCTURE LAYER │
│ │
│ Docker Compose Stack │
│ ├── Midnight Node v0.22.1 :9944 │
│ ├── Indexer + GraphQL v4.0.0 :8088 │
│ └── Proof Server v8.0.3 :6300 │
│ │
│ Network ID: "undeployed" │
└──────────────────────────────────────────────────────────────┘

Key Design Decisions

Monolithic Contract

Cross-contract calls are not yet supported in Compact. All ROSCA logic — membership, contributions, payouts, defaults, participation records — lives in a single rosca.compact file.

Tradeoff: Larger circuit, longer compile times, but no alternative exists in the current Compact version.

Fixed Member Cap at Compile Time

Compact requires all loop iterations to be known at compile time. No dynamic arrays or unbounded iteration.

Decision: Member pool size is a compile-time constant embedded in the Merkle tree depth. MerkleTree<4, Bytes<32>> gives depth 4 = up to 16 leaves. Multiple compiled variants can be deployed for different circle sizes (4, 8, 16 members).

Round-Robin Payouts

The current implementation uses round-robin payout rotation: leaf position equals payout round number. Bid-based ordering (auction for earlier payout) adds significant circuit complexity and is deferred.

Local Proof Generation

The proof server runs as a Docker container on the user's machine. Witness data (member secrets) never leaves the machine. This is the correct architecture for the Assemble Program. Client-side WASM proofs are on the production roadmap.

SDK Stack

PackageVersionRole
@midnight-ntwrk/midnight-js-contracts3.1.0Deploy + call contracts
@midnight-ntwrk/dapp-connector-api4.0.0Lace wallet integration
@midnight-ntwrk/midnight-js-level-private-state-providerlatestLevelDB private state
@midnight-ntwrk/wallet-sdk-facade2.0.0Unified wallet interface
@midnight-ntwrk/compact-runtime0.14.0Compact output runtime
@midnight-ntwrk/ledger-v88.0.3Ledger types