SessionVM is an optional on-chain registry and coordination layer for the
Lux Session messenger — a Session/Oxen-style private messaging overlay with
post-quantum security (ML-KEM-768 + ML-DSA-65 + XChaCha20-Poly1305).
SessionVM is not part of the primary network (P / X / C). Most deployments
that want Session messenger can achieve the same result with three C-Chain
contracts (ServiceNodeRegistry, SwarmCoordinator, StorageCommitment),
since the on-chain piece is just state bookkeeping. The heavy lifting
(network, crypto, storage) always happens off-chain via libp2p.
Activate SessionVM on a dedicated track-chain (Inpars pattern) only when
you need faster coordination than C-Chain block time, or you want messaging
traffic isolated from DeFi / settlement traffic on C-Chain.
SessionVM does NOT implement the messaging protocol itself; that lives in
github.com/luxfi/session as a pluggable library. SessionVM provides:
Precompile address nibble: C=E (see LP-129 Registry) — only wired in when
the track-chain that activates SessionVM hosts an EVM companion chain.
SessionVM is one project, one place:
github.com/luxfi/session/
├── vm/ # VM implementation (package vm)
├── plugin/ # Plugin binary (package main)
├── crypto/ # ML-KEM + ML-DSA + AEAD
├── messaging/ # Message routing
├── network/ # libp2p overlay
├── protocol/ # Session wire protocol
├── swarm/ # Swarm assignment
└── storage/ # Inbox storage
The plugin binary builds from session/plugin/main.go directly. It is NOT
in chains/ — the Session project is self-contained and only loaded on
track-chains that activate it.
type ServiceNode struct {
NodeID ids.NodeID
PublicKey []byte // ML-DSA identity key
EncryptionKey []byte // ML-KEM-768 transport key
Stake uint64 // Minimum 100 LUX
SwarmID uint32 // Assigned swarm
Status Status // Active | Decommissioning | Retired
RegisteredAt uint64 // Block timestamp
LastPingAt uint64 // Block timestamp
UptimeScore uint32 // 0-10000 bps, rolling window
}
1. Node submits RegisterServiceNodeTx with stake
2. Node bootstraps Session protocol daemon
3. Chain assigns SwarmID via deterministic sampling
4. Node announces itself to swarm peers
Every epoch (~1 hour), each service node must submit a challenge response
proving:
min_peers other nodesNodes failing the challenge lose stake (0.5% per miss, up to 50% before
auto-decommission).
Swarms are groups of ~10 service nodes. Each inbox (derived from a recipient's
public key) maps to exactly one swarm via consistent hashing:
swarm_id = BLAKE3(recipient_pubkey) mod num_swarms
Messages for that recipient are stored on all nodes in the swarm
(replication factor ~10). This provides:
Each service node periodically commits to the Merkle root of its swarm
state. Commitments go on-chain via StorageCommitmentTx. Mismatched
commitments within a swarm trigger a reconciliation protocol (off-chain)
and potential slashing of deviant nodes.
SessionVM is NOT part of the primary-network VM set (P / X / C).
It activates only on track-chains that explicitly opt in — principally
the Inpars track-chain for deployments running Lux Session messenger.
Networks that do not run Session messenger simply never load this VM.
github.com/luxfi/session/ |github.com/luxfi/session/vm/ |github.com/luxfi/session/plugin/ |github.com/luxfi/session/docs/ |