Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Installation

Requirements

  • Rust stable toolchain
  • Git

Optional, depending on what you want to test:

  • Python 3 (for interop tests)
  • Docker (for integration tests)
  • 2-4 RNode modems via USB (for LoRa integration tests)

No system C libraries are required. All cryptography is compiled from Rust source.

Debian/Ubuntu setup

# Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# Interop tests
sudo apt install python3

# Integration tests
sudo apt install docker.io
sudo usermod -aG docker $USER

# LoRa tests and embedded firmware (USB serial access)
sudo usermod -aG dialout $USER

Build from source

git clone https://codeberg.org/Lew_Palm/leviculum.git
cd leviculum
cargo build --release --bin lnsd --bin lns --bin lncp

The binaries are in target/release/.

Running the daemon

./target/release/lnsd -v

Reads its config from ~/.reticulum/config, the same location as Python Reticulum.

Development

Cargo aliases

Common workflows are available as cargo aliases (defined in .cargo/config.toml):

CommandWhat it does
cargo test-coreRun all reticulum-core unit tests
cargo test-stdRun all reticulum-std unit tests
cargo test-interopRun interop tests against Python Reticulum
cargo test-integRun Docker-based integration tests
cargo lintRun clippy on all crates
cargo fmt --all -- --checkCheck formatting

Test levels

Tests are organized by what they require:

Unit tests – just Rust, no extra dependencies:

cargo test-core
cargo test-std

Interop tests – require Python 3 and the vendored Reticulum:

git submodule update --init vendor/Reticulum
cargo test-interop

Integration tests – require Docker and pre-built release binaries:

cargo build --release --bin lnsd --bin lns --bin lncp
cargo test-integ

LoRa integration tests – require physical RNode modems connected via USB:

LoRa tests are #[ignore]d by default and must be run explicitly. They exercise real over-the-air transfers between RNode radios running Reticulum firmware. Tests are skipped automatically if the required devices are not connected.

Devices neededTest countExamples
2 RNodes40lora_link_rust, lora_lncp_push, lora_ratchet_basic
3 RNodes3lora_3node_transfer, lora_3node_contention
4 RNodes7lora_4node_contention_rust, lora_multihop_transfer

Hardware setup:

  • Connect RNodes via USB. They appear as /dev/ttyACM0, /dev/ttyACM1, etc.
  • Your user must be in the dialout group: sudo usermod -aG dialout $USER
  • Override device paths with environment variables if needed: LEVICULUM_RNODE_0=/dev/ttyUSB0 LEVICULUM_RNODE_1=/dev/ttyUSB1

Running LoRa tests:

# Single test
cargo test -p reticulum-integ -- --exact executor::tests::lora_link_rust --ignored --nocapture

# All 2-device tests
cargo test -p reticulum-integ -- lora_ --ignored --nocapture --test-threads=1

# Override radio parameters (bandwidth in Hz)
LORA_BANDWIDTH=125000 cargo test -p reticulum-integ -- --exact executor::tests::lora_lncp_push --ignored --nocapture

Each LoRa test must pass on all three bandwidth profiles (62.5 kHz, 125 kHz, 250 kHz). The TOML files define 62.5 kHz; use LORA_BANDWIDTH to switch.

Some tests use the lora-proxy binary for fault injection (dropping frames to test retransmit recovery). Build it before running proxy tests:

cargo build --release --bin lora-proxy

Embedded cross-compilation

Embedded targets are not downloaded automatically. Install them when needed:

rustup target add thumbv7em-none-eabihf   # nRF52840
rustup target add thumbv6m-none-eabi       # RP2040
cargo check-nrf52
cargo check-embedded

Before submitting changes

cargo fmt --all -- --check
cargo lint
cargo test-core
cargo test-interop