Skip to content

Latest commit

 

History

72 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lapis Net

CI Kotlin 2.4.20 JDK 25 Apache 2.0

Lapis Net

Lapis Net is a fully decentralized peer-to-peer social network protocol on the Kotlin/JVM platform. It is part of the Lapis family of distributed systems, alongside Lapis Cloud.

The protocol combines:

  • Decentralized identity — secp256k1 keypairs, Bitcoin-compatible

  • Content-addressed storage — Nabu (IPFS-on-libp2p), DHT + Bitswap

  • Web-of-trust reputation — Veritas, a shortest-path trust graph

  • Gossip-based propagation — libp2p GossipSub

  • Bitcoin/Lightning-anchored micropayment relevance — Virtus (on-chain OP_RETURN and Lightning BOLT-11 payment proofs)

  • Sybil-resistant free "likes" — Karma, weighted by Veritas and a Bitcoin time anchor

  • Machine-to-machine infrastructure reputation — Madli, a five-metric weighted-median node-reputation layer

The protocol core is deliberately neutral about curation, sorting, and reputation models. Veritas, Karma, Virtus, and Madli (the scoring dimensions) are optional tools for browser/view implementations, not protocol requirements.

Status

Every wave through V0.9 is implemented and merged to master (V0.7 was never a standalone wave — its scope was folded into the incremental browser growth of V0.2–V0.5, see docs/roadmap.adoc). Full technical detail for each module is in the Modules table below; the full wave-by-wave history — including scope cuts and hardening follow-ups — is in docs/roadmap.adoc and docs/architecture.adoc.

Wave What it added Status

V0.1

Protocol core: secp256k1/Ed25519 identity, libp2p bootstrap, Nabu (DHT + Bitswap) storage, Veritas (web-of-trust)

V0.2

Virtus (LTR micropayment economy, on-chain OP_RETURN) + the first real client, the Minimal-Browser

V0.3

Karma (Sybil-resistant free "likes", Bitcoin time-anchored)

V0.4

Genesis-bootstrap, QR-code/deep-link identity linking, keystore encryption at rest (Argon2id + AES-256-GCM)

V0.5

Madli (machine-to-machine node reputation, weighted-median aggregation)

V0.6

Lightning payment-proof verification (LightningProof, a second LtrProof type alongside on-chain)

V0.7

(no standalone wave — folded into V0.2–V0.5’s incremental browser growth)

V0.8

Direct messages (X3DH/Double Ratchet, online + offline delivery, encrypted attachments, acceptance policy, browser UI) and 1:1 voice calls over WebRTC

V0.9

Asynchronous messages / mail replacement: encryption, threading, attachments, spam protection

Known, deliberate gaps — not oversights, each documented at the point it was cut:

  • No embedded Lightning node — proof verification only, no payment sending; no BOLT-12 offer publication.

  • NAT traversal is relay-only — no hole punching. A node behind NAT can now be reached: it reserves a slot on a Circuit-Relay-v2 relay and publishes the resulting /p2p-circuit address, and a peer that holds only that address dials it through the relay with an end-to-end Noise session the relay cannot read. Acting as a relay is opt-in and off by default. What is still missing is dcutr hole punching, which would let two NAT’d peers upgrade a relayed connection to a direct one: it is absent from jvm-libp2p entirely and would have to be implemented from scratch. Every relayed connection therefore stays relayed for its whole life, and relay operators are compensated only in reputation (Madli), not payment.

  • No browser control surface for calls (V0.8.7b) — a 1:1 call’s audio runs in the JVM node process; a browser page would only remote-control it, not carry browser-native WebRTC.

  • No group calls, video, multi-device messaging, or MLS — cut from the V0.8 arc’s scope entirely on 2026-08-04, not a partial or stubbed implementation.

  • No delivery receipts or typing indicators for direct messages — deliberately deferred, not built even as stubs.

  • No DHT-based peer/mailbox discovery in the messaging moduleslapis-net-directory, lapis-net-mail, lapis-net-dm and lapis-net-ratchet publish and discover over GossipSub. They were built that way because cross-node DHT provider discovery was broken from V0.1.4 onwards. V0.9.8 repaired that at the storage layer — NabuStorage.provide()/findProviders() now work across nodes, and get() fetches a block from a peer it learned about through the DHT alone (see docs/architecture.adoc) — but migrating those four modules onto it is a separate wave that has not happened yet.

Comparison

How Lapis Net stands next to the five closest decentralized social protocols — full methodology and sources at net.lapisproject.dev/comparison.

Feature Lapis Net Nostr Secure Scuttlebutt Farcaster Bluesky / AT Proto Mastodon / Fediverse

Genuine peer-to-peer (no relay, hub, or homeserver)

Cryptographic identity instead of an account

Weighted web of trust (transitive trust paths)

Bitcoin/Lightning-native value layer

Market-based visibility (real value at stake, not a black-box algorithm)

End-to-end encrypted voice calls

Asynchronous long-lived messaging (e-mail replacement)

Machine-to-machine node reputation (infrastructure, not opinions)

yes · partial · no

Honest caveat: Nostr, Mastodon, Bluesky and Farcaster each already have millions of users and mature client ecosystems. Lapis Net is, as of this comparison, a working multi-wave prototype (V0.1–V0.9 implemented) without a public network yet — a real trade-off against the table above, not a detail to gloss over.

Modules

Module Purpose

lapis-net-core

Base protocol abstractions shared by all other modules.

lapis-net-identity

secp256k1 identity keypairs, Ed25519 dual-key binding for the libp2p peer ID, keystore encryption at rest (Argon2id + AES-256-GCM), and multi-device/pseudonym self-trust linking.

lapis-net-storage

DHT + Bitswap content storage via Nabu.

lapis-net-trust

Veritas (web-of-trust): trust-edge data model, shortest-path scoring algorithm, GossipSub propagation, Nabu persistence.

lapis-net-networking

libp2p node bootstrap, peer identity derivation, mDNS discovery, GossipSub, and the Genesis-bootstrap/QR-code connection flow.

lapis-net-virtus

Virtus (the LTR micropayment economy): on-chain (OP_RETURN) and Lightning (BOLT-11) payment proofs, 10%/24h decay, view-specific accumulation.

lapis-net-karma

Karma (free likes): Bitcoin time-anchored, Veritas-weighted Sybil-resistant "like" scoring.

lapis-net-madli

Madli (machine-to-machine node reputation): five-metric observation vector with Veritas-weighted, manipulation-resistant weighted-median aggregation.

lapis-net-mail

Asynchronous messages (the e-mail replacement), fully implemented (V0.9.1–V0.9.4): a signed, addressed MessageEnvelope bound by CID to its own MessageBody blob, gossiped on one GossipSub topic per recipient identity, Nabu-persisted at both ends (V0.9.1); hybrid-ecies encryption (HKDF + AES-256-GCM over a secp256k1 ECDH exchange, V0.9.2); cycle-safe, receive-order-independent threading, encrypted attachments, a local sent-folder view, and a browser inbox UI with verified XSS protection (V0.9.3); and a Veritas/Karma scoring filter plus a Lightning first-contact deposit for spam resistance (V0.9.4). A follow-up security-hardening pass closed a critical unauthenticated remote memory-exhaustion bug found in this module and, on audit, in three other already-shipped modules (lapis-net-trust, lapis-net-virtus, lapis-net-karma) plus a fourth instance in lapis-net-browser.

lapis-net-policy

Acceptance-gate machinery extracted from lapis-net-mail in V0.8.6 so lapis-net-dm (direct messages) could share it rather than reimplement it: AcceptanceGate/AcceptanceGateEvaluator (the gate vocabulary and evaluation logic — Veritas distance, Karma threshold, Lightning first-contact deposit, explicit accept/deny lists) and VeritasPathCache (a bounded, LRU-evicting cache so a flood of never-repeating throwaway identities can’t force an unbounded-heap shortest-path search on the GossipSub validator hot path).

lapis-net-directory

Signed peer/presence directory records (PeerRecord): identity bound to its current network addresses and libp2p peer identity, with a monotonic sequence number and a heartbeat TTL, gossiped and Nabu-persisted — the foundational discovery layer V0.8’s later sub-waves (online DM addressing) resolve recipients through (V0.8.1). Also carries PrekeyBundle gossip/indexing (PrekeyBundleGossip/PrekeyBundleIndex) for `lapis-net-ratchet’s prekey bundles (V0.8.2).

lapis-net-ratchet

X25519 encryption sub-key and the X3DH handshake (Signal’s Extended Triple Diffie-Hellman, reimplemented from the public specification): PrekeyBundle/PrekeyBundleCodec, PrekeyStore (durable one-time-prekey consumption), and the X3dh handshake itself. Deliberately network-free (V0.8.2). Plus the Double Ratchet itself: DoubleRatchetSession (forward-secret, post-compromise-secure 1:1 sessions over an HKDF root chain and HMAC symmetric chains), RatchetMessage/RatchetMessageCodec, a bounded evicting SkippedMessageKeyStore, and DoubleRatchetSessionCodec for encrypted-at-rest session persistence, including the encodeWithKey/decodeWithKey Argon2id-bypass pair lapis-net-dm uses for per-message persistence (V0.8.3).

lapis-net-dm

The custom /lapis/dm/1.1.0 libp2p stream protocol wiring lapis-net-ratchet’s X3DH/Double-Ratchet primitives into a live network path: `DmProtocol/DmProtocolHandler (stream-protocol binding, the first raw-libp2p-stream parser in this codebase — length-validated-before-allocation frame decoding, slowloris/absolute-lifetime timeouts, per-peer stream cap), DmEnvelope/DmEnvelopeCodec (the outer wire frame), DmSessionManager (first-contact/resumed session state machine, durable session persistence, the identity-authority-safe inbound handler), and DmStore (in-memory-only conversation history) — online 1:1 direct messages between directly-dialable peers (V0.8.4), plus V0.8.5’s offline Nabu mailbox (MailboxPointer/MailboxGossip/MailboxPoller/MailboxRedeliveryScheduler, DmSessionManager.sendOffline) for offline delivery via a Bitswap-fetched, periodically re-announced signed pointer.

lapis-net-call

1:1 audio calls over WebRTC (V0.8.7): CallManager (the call-control state machine — INVITE/ACCEPT/REJECT/HANGUP, a three-executor concurrency model, invite-flood rate limiting), CallSignal/CallSignalCodec (the wire frame carried as a DmMessageType.CALL_SIGNAL envelope’s ratchet plaintext), CallSdpPolicy (SSRF-class defenses against a peer-supplied SDP), and WebRtcCallMediaEngine (the sole dev.onvoid.webrtc:webrtc-java consumer — host-ICE-candidates only, no STUN/TURN). Depends on lapis-net-dm for signaling transport and DTLS-fingerprint identity binding; lapis-net-dm itself stays entirely WebRTC-free.

lapis-net-browser

Minimal-Browser — the first real Lapis Net client, exposing Veritas/Virtus/Karma/Madli data, the LTR record-authoring endpoints, a mail inbox UI (V0.9.3), and a direct-message UI (V0.8.6b).

lapis-net-cli

Entry point / multi-node demo harness proving trust propagation end to end.

Building

./gradlew clean check   # compiles, runs tests, runs ktlint
./gradlew :lapis-net-cli:run

Requires JDK 25.

Development conventions

  • Code style is enforced by ktlint and checked in CI.

  • Logging uses kotlin-logging: private val logger = KotlinLogging.logger {} in every file that logs.

  • Documentation is written in AsciiDoc; diagrams (once introduced) use kUML via the kuml Asciidoctor macro — no PlantUML, Mermaid, or hand-drawn diagrams.

  • All identifiers (classes, interfaces, packages) are named in English. Domain terms (Veritas, Karma, Virtus, Madli) are the one exception, as they are Latin proper nouns used directly as identifiers.

License

Apache License 2.0 — see LICENSE.

Contributing

About

Fully decentralized P2P social network protocol (Kotlin/JVM) — web-of-trust reputation, Bitcoin/Lightning-anchored micropayments, and machine-to-machine node reputation, with no central servers or platform tokens

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages