A React + Vite + TypeScript application for demonstrating L2PS (Layer 2 Privacy Subnets) capabilities. This POC showcases private transaction flows, authenticated history access, and the rollup mechanism.
cd docs/l2ps-poc
npm install
npm run dev
# Open http://localhost:5173Prerequisites: Node.js 18+, running Demos node with L2PS configured.
| Feature | Description |
|---|---|
| Wallet Connection | BIP39 mnemonic β Ed25519 keypair |
| Dual Transaction Modes | L1 (public) and L2PS (private) |
| Client-Side Encryption | AES-256 encryption in browser |
| Authenticated History | Signature-verified L2PS history access |
| Interactive Learn Tab | Educational demos and explanations |
| Filter Tabs | View All, L2PS only, or L1 only transactions |
L2PS transactions are encrypted client-side before leaving the wallet. The POC requires AES Key and IV that match the node configuration.
Option A: Environment Variables (Recommended)
Create .env in docs/l2ps-poc/:
VITE_NODE_URL="http://127.0.0.1:53550"
VITE_L2PS_UID="testnet_l2ps_001"
VITE_L2PS_AES_KEY="b9346ff30a8202cd46caa7b4b0142bfc727c99cc0f8667580af945b493038055"
VITE_L2PS_IV="f5405674114eb2adea5774d36b701a6d"Option B: UI Settings
Click "Advanced Settings" in the Send tab to configure keys at runtime.
# Generate 256-bit AES Key (64 hex characters)
openssl rand -hex 32
# Generate 128-bit IV (32 hex characters)
openssl rand -hex 16Client and Node keys MUST match!
| Location | Files |
|---|---|
| Client (POC) | .env or UI settings |
| Node | data/l2ps/<uid>/private_key.txt and iv.txt |
If keys don't match, transactions will fail decryption on the node.
- Generate New: Creates a fresh BIP39 24-word mnemonic
- Connect Wallet:
- Derives Ed25519 keypair from mnemonic
- Connects to Demos Node via WebSocket
- Fetches initial balance
Note: In production, use secure mnemonic storage and hardware wallet integration.
Standard blockchain transaction visible to everyone:
Alice β Bob: 5 DEM
β
[Everyone sees: "Alice β Bob: 5 DEM"]
Encrypted transaction with rollup:
Alice β Bob: 5 DEM
β
[Browser encrypts with AES-256]
β
[Network sees: "Encrypted blob β L2PS Network"]
β
[Only L2PS nodes can decrypt]
| Type | Fee | Destination |
|---|---|---|
| L1 Transaction | 0 DEM | N/A |
| L2PS Transaction | 1 DEM | Burned (removed from circulation) |
The 1 DEM fee is automatically deducted from sender's balance in addition to the transfer amount.
L2PS transactions go through multiple statuses:
[1] Submit β β‘ Executed (local validation passed)
β
[2] Wait ~10s β π¦ Batched (included in L1 batch)
β
[3] Consensus β β Confirmed (L1 block confirmed)
Every ~10 seconds, the node:
- Collects up to 10 pending L2PS transactions
- Aggregates their state changes (GCR edits)
- Generates ZK proof of validity
- Submits single batch transaction to L1
The History tab provides three views:
| Tab | Shows | Count |
|---|---|---|
| All | Combined and deduplicated | X |
| π L2PS | Only L2PS transactions | Y |
| π€ L1 | Only L1 transactions | Z |
| Type | Endpoint | Access |
|---|---|---|
| L1 History | getTransactionHistory |
Public (anyone) |
| L2PS History | getL2PSAccountTransactions |
Authenticated (owner only) |
L2PS Authentication Flow:
- Wallet signs:
getL2PSHistory:{address}:{timestamp} - Node verifies signature matches address
- If valid β returns private history
- If invalid β 403 Access Denied
The Learn tab provides interactive demonstrations:
- Fetch L2PS History button opens choice modal
- Skip Signing β Shows 403 ACCESS DENIED
- Sign Request β Shows successful authenticated access
- What is L2PS?
- Transaction Lifecycle visualization
- Fee explanation
- Key takeaways
| Component | Status | Notes |
|---|---|---|
| Client Encryption | β Ready | utils/l2ps.ts handles AES-256 |
| L2PS Decryption | β Ready | handleL2PS.ts decrypts transactions |
| Transaction Fee | β Ready | 1 DEM burned per L2PS transaction |
| GCR Edits | β Ready | State changes calculated and stored |
| Mempool | β Ready | Separate l2ps_mempool table |
| Batch Aggregator | β Ready | Runs every 10s, max 10 tx/batch |
| ZK Proofs | β Ready | PLONK proofs for batch validity |
| Consensus | β Ready | GCR edits applied per L1 block |
| Mempool Sync | β Ready | P2P sync between nodes |
| DTR Routing | β Ready | Hash relay to validators |
| History API | β Ready | Authenticated endpoint |
| Filter Tabs | β Ready | All/L2PS/L1 filtering |
l2ps-poc/
βββ src/
β βββ App.tsx # Main application logic
β βββ utils/
β β βββ l2ps.ts # Encryption & transaction building
β βββ index.css # Styling with animations
βββ .env # Configuration (create from example)
βββ index.html # Entry point
βββ vite.config.ts # Vite configuration
βββ package.json # Dependencies
- Ensure node is running at configured URL
- Check browser console for WebSocket errors
- Verify AES Key is 64 hex characters
- Verify IV is 32 hex characters
- This is expected for other users' addresses
- For your own address, signature verification should pass
- L2PS requires amount + 1 DEM fee
- Fund wallet using genesis configuration
- L2PS Overview - What is L2PS and how it works
- L2PS Quickstart - Get started with L2PS
- How L2PS Transactions Are Handled - Transaction lifecycle deep dive