โ† Dashboard ยท Docs ยทArchitecture

Grove Architecture

System Overview

Grove is a two-file system:

Both run on every cell. web.py imports from grove.py.


Encryption

File Encryption

1. Master key: 256-bit random key stored in ~/.grove/.key

2. Per-file key: derived via HKDF-SHA256 from master key + file hash

3. Chunk encryption: ChaCha20-Poly1305 (authenticated encryption)

4. Why ChaCha20: 5x faster than AES on ARM devices without AES-NI (tested: 279 vs 55 MB/s on Pi)

Chat Encryption

1. Key exchange: X25519 Diffie-Hellman

2. Message encryption: ChaCha20-Poly1305

3. Each message has a unique nonce

4. Forward secrecy per-message (random nonce)

Signing


Chunking


File (any size)
  โ†“ split into 4MB chunks
  โ†“ each chunk encrypted (ChaCha20-Poly1305)
  โ†“ chunk hash = SHA-256(encrypted_bytes)
  โ†“ stored as ~/.grove/chunks/{hash[:2]}/{hash}

Content-addressed storage (like git): identical chunks deduplicate automatically.


Placement & Replication

Placement Database

SQLite database (~/.grove/placement.db) tracking:

Replication Strategy

1. Desired factor โ€” target copies (default: 2)

2. Speed-ranked peers โ€” fastest peers get chunks first

3. Preferred peers โ€” favorites always get copies (up to desired factor)

4. Strict cap โ€” never exceed desired factor (no over-replication)

5. Self-healing โ€” if a peer goes offline, opp sync re-replicates to maintain factor

Route Selection

best_route() scores routes by: effective_score = latency - (throughput_MB/s ร— 0.1)

A route with higher throughput gets a bonus. Benchmarked every 6 hours with real 256KB transfers.


Sync Flow (Opportunistic Sync)

Runs every ~5 minutes:


1. Resolve peers (group routes by identity)
2. Benchmark routes (every 6h)
3. Probe each peer (best_route, record latency, health check)
4. For each reachable peer:
   a. Get their chunk inventory
   b. Pull chunks they have that we need
   c. Push chunks they need (speed-ranked placement)
   d. Sync manifests and grants
5. Check for updates (auto-update if newer build found)
6. Identify at-risk chunks and heal

Sharing Flow


Sharer:
1. User selects file + recipients in UI
2. For each recipient:
   a. Create ShareGrant(manifest_hash, encrypted_file_key, recipient_pubkey)
   b. Sign grant with Ed25519
   c. Push grant to recipient's cell via /api/receive-grant
3. Push manifest + chunks to recipient

Recipient:
1. Receives grant via API
2. Verifies Ed25519 signature
3. File appears in Feed tab
4. On view/download: decrypt file key from grant, decrypt chunks

Relay System

WebSocket relay for NAT-traversed cells:


Cell A โ†โ†’ Relay Server โ†โ†’ Cell B
         (WebSocket)

Web Dashboard

Single HTML page rendered by Flask render_template_string. Features:


Watchdog

Separate process (watchdog.py) for reliability:


Auto-Update

Cells can update each other:

1. During opp sync, cells compare build hashes

2. If a peer has a newer build (different hash + newer build_time), flag update

3. User can accept via dashboard notification

4. Update downloads grove.py and web.py from peer, restarts

Build time is deterministic (derived from content hash, not file mtime) so identical code always has identical build_time across cells.


Key Files

File Purpose Permissions
~/.grove/node.key Ed25519 private key (identity) 600
~/.grove/node_x25519.key X25519 private key (chat) 600
~/.grove/.key Master encryption key 600
~/.grove/peer_secret API auth secret 600
~/.grove/dashboard_auth Password hash (PBKDF2) 600
~/.grove/config.json Cell configuration 644
~/.grove/placement.db Chunk placement (SQLite) 644
~/.grove/peer_speeds.json Route speed records 644
~/.grove/peer_health.json Peer uptime records 644

Classes (grove.py)

FileManifest

Describes a chunked file: filename, source_path, chunks (list of hashes), total_size, encryption metadata, version, synced_at.

ShareGrant

Cryptographic sharing permission: manifest_hash, encrypted_file_key, creator_pubkey, recipient_pubkey, signature, granted_at, filename, file_type, total_size.

ChunkInfo

Metadata for a single chunk: hash, size, index.

DeleteRequest

Signed request to delete a file from peers (currently disabled for safety).

FileWatcher

Monitors watched directories for new/changed files, auto-chunks and syncs them.

GroveServiceListener

mDNS/Zeroconf listener for discovering peers on local network.