02 — Wasm Storage (Browser Extension Fallback)
Crate: kinetic-storage
Stage: 4 of 10
Reading time: ~6 minutes
Depends on: kinetic-core
Source files: kinetic-storage/src/lib.rs (Lines 174 to 266)
What Is This?
This is the second half of the kinetic-storage crate. It provides an entirely in-memory, zero-disk Key-Value database that automatically replaces the sled database whenever the Kinetic codebase is compiled for a Web browser (WASM).
Why Kinetic Needs This
Important
The
sleddatabase requires direct access to a computer’s file system (hard drive). When Kinetic is compiled as a Wasm browser extension, it runs inside a strict security sandbox that physically cannot touch the host computer’s hard drive. If you try to compilesledto Wasm, the compiler will violently reject it. By using conditional compilation, Kinetic can ship the exact same node architecture to the browser without crashing the compiler.
How It Works
#![allow(unused)]
fn main() {
-> See: `kinetic-storage/src/lib.rs` — Lines 174 to 266
}
When the target_arch = "wasm32" compiler flag is active, the native module is ignored and this wasm module is activated. It creates a mocked SledStorage struct that looks exactly like the real one from the outside, but operates completely differently on the inside.
The Internal Engine (BTreeMap):
Instead of a database file, the data is stored in a RwLock<BTreeMap<Vec<u8>, Vec<u8>>>.
Note
-> See
RUST_CONCEPTS.mdfor an explanation ofBTreeMapand why it is used for fast prefix scanning.
Memory Constraints (DoS Protection):
#![allow(unused)]
fn main() {
-> See: `kinetic-storage/src/lib.rs` — Lines 240 to 242
}
Warning
Because this database lives entirely in RAM (memory), there is a severe risk of a browser tab crashing if the node downloads too much data. To prevent this, the
put()function includes a hardcoded limit:#![allow(unused)] fn main() { if db.len() >= 10_000 && !db.contains_key(key) { return Err(...); } }If the database reaches 10,000 keys, it refuses to insert any new ones (though it allows updating existing keys).
Prefix Scanning:
#![allow(unused)]
fn main() {
-> See: `kinetic-storage/src/lib.rs` — Lines 218 to 229
}
Because a BTreeMap is naturally sorted, scanning for a prefix is extremely fast. The code uses db.range(prefix.to_vec()..) to instantly jump to the first key that matches the prefix, and then iterates forward. As soon as it hits a key that doesn’t start with the prefix, it breaks the loop early.
Key Pieces
#[cfg(target_arch = "wasm32")]
- Location:
lib.rs:174
Note
-> See
RUST_CONCEPTS.mdfor an explanation of conditional compilation. This separates the browser build from the desktop build.
RwLock
- Location:
lib.rs:182
Note
-> See
RUST_CONCEPTS.mdfor an explanation ofRwLock<T>. This allows concurrent reads while safely locking for writes.
How This Connects to the Rest of Kinetic
- CROSS-CRATE: This allows the entire
kinetic-networkP2P layer to run seamlessly in the browser. The networking code just callsstorage.put(), completely unaware that it is writing to RAM instead of a hard drive.
Quick Reference
| Property | Value |
|---|---|
| WASM Engine: | BTreeMap (In-memory). |
| Concurrency: | Guarded by std::sync::RwLock. |
| Hard Limit: | 10,000 keys max to prevent browser OOM crashes. |
| Persistence: | None. Wiped clean when the browser tab closes. |
Open Questions / Things to Revisit
- True Browser Persistence: Right now, the WASM storage is entirely ephemeral — all data is lost when the user closes the browser. For a real Kinetic wallet extension, this should ideally be upgraded to use the browser’s IndexedDB API (via
web-sys) so that keys and peer tables survive tab closures. The10,000key limit is a stopgap for RAM exhaustion, but a persistent IndexedDB solution is the correct long-term architecture.