Ligh𝞽ning
Rust QUIC transport layer for Bittensor
Persistent QUIC connections with sr25519 handshake authentication for validator-miner communication.
Python
pip install btlightning
from btlightning import Lightning
client = Lightning(wallet_hotkey="5GrwvaEF...")
client.set_python_signer(my_signer_callback)
client.initialize_connections([
{"hotkey": "5FHneW46...", "ip": "192.168.1.1", "port": 8443}
])
response = client.query_axon(
{"hotkey": "5FHneW46...", "ip": "192.168.1.1", "port": 8443},
{"synapse_type": "MyQuery", "data": {"key": "value"}}
)
Rust
[dependencies]
btlightning = { version = "0.1", features = ["subtensor"] }
With the subtensor feature, the client discovers miners from the metagraph and keeps connections in sync automatically:
use btlightning::{LightningClient, LightningClientConfig, Sr25519Signer, MetagraphMonitorConfig};
let config = LightningClientConfig {
metagraph: Some(MetagraphMonitorConfig::finney(YOUR_NETUID)),
..Default::default()
};
let mut client = LightningClient::with_config("5GrwvaEF...".into(), config)?;
client.set_signer(Box::new(Sr25519Signer::from_seed(seed)));
client.initialize_connections(vec![]).await?;
Without subtensor, pass miner addresses directly:
use btlightning::{LightningClient, Sr25519Signer, QuicAxonInfo};
let mut client = LightningClient::new("5GrwvaEF...".into());
client.set_signer(Box::new(Sr25519Signer::from_seed(seed)));
client.initialize_connections(vec![
QuicAxonInfo::new("5FHneW46...".into(), "192.168.1.1".into(), 8443, 4)
]).await?;
Query a single miner by axon info and deserialize the response:
use btlightning::QuicRequest;
use serde::{Serialize, Deserialize};
#[derive(Serialize)]
struct MyQuery { prompt: String }
#[derive(Deserialize)]
struct MyResult { answer: String }
let request = QuicRequest::from_typed("MyQuery", &MyQuery { prompt: "hello".into() })?;
let response = client.query_axon(axon_info, request).await?.into_result()?;
let result: MyResult = response.deserialize_data()?;
Fan out to every QUIC miner on the subnet concurrently:
use std::sync::Arc;
use tokio::task::JoinSet;
let client = Arc::new(client);
let miners = metagraph.quic_miners();
let mut tasks = JoinSet::new();
for miner in miners {
let req = QuicRequest::from_typed("MyQuery", &MyQuery { prompt: "hello".into() })?;
let client = Arc::clone(&client);
tasks.spawn(async move {
(miner.hotkey.clone(), client.query_axon(miner, req).await)
});
}
while let Some(Ok((hotkey, result))) = tasks.join_next().await {
match result {
Ok(resp) => { /* handle response from hotkey */ }
Err(e) => { /* miner failed */ }
}
}
Flood defense
The server applies two filters at the quinn::Incoming boundary, before any per-connection state is allocated. Both are operator-configurable on LightningServerConfig.
| Field | Default | Effect |
|---|---|---|
enforce_source_allowlist |
false |
When true, drops any connection whose source IP is not in the cached allowlist. Backed by the SourceAddressResolver trait; refresh interval source_allowlist_refresh_secs (default 300s). Drops use Incoming::ignore() so no response packet is emitted, eliminating reflection-amplification surface. |
require_address_validation |
true |
When true, unvalidated peers are answered with a QUIC Retry packet via Incoming::retry(), forcing a token round-trip before connection state is allocated. Defeats spoofed-source Initial floods. |
Observability:
info!Initial source-address allowlist resolution: N allowed IPson startupinfo!Refreshed source-address allowlist: N allowed IPsper refreshwarn!source-address allowlist is empty under enforce_source_allowlist=true; ALL connections will be silently droppedif the resolver returns empty or errors while enforcement is oninfo!QUIC address validation enabled -- all clients must complete a Retry round-tripon startup whenrequire_address_validationis onLightningServer::get_allowed_source_count()returns the size of the cached allowlist for embedding in operator dashboards
Pre-flight numbers, measured locally with a quinn-driven flood at concurrency 64 over 10s:
| Mode | accepts/s | handshakes_completed/s |
|---|---|---|
| no defenses | 8,420 | 8,420 |
| source allowlist only | 640 | 0 |
| address-validation only | 8,710 | 8,297 |
| both | 638 | 0 |
Address validation alone provides limited mitigation against attackers using real reachable source IPs (the Retry round-trip completes); it is decisive against spoofed-source floods. Source allowlist enforcement reduces application-layer cost on flood traffic to zero. Both together provide defense in depth across the metagraph cold-start and resolver-failure windows.
This filter does not reduce inbound bandwidth or kernel UDP buffer pressure. Operators on saturated uplinks must combine these with upstream scrubbing or a kernel-level allowlist (e.g. nftables).
Build from source
cargo build -p btlightning
maturin develop --manifest-path crates/btlightning-py/Cargo.toml
Performance
Benchmarked on Apple Silicon (M-series), macOS, loopback networking. Echo handler returns input unchanged. Connection setup includes first request-response round trip. Lightning authenticates once at connection time and amortizes over all subsequent requests; bittensor signs and verifies every request. Bittensor payloads are base64-encoded (JSON has no binary type), adding ~33% wire overhead beyond the nominal payload size. Source: benchmarks/.
| bittensor (dendrite/axon) | lightning | |
|---|---|---|
| Protocol | HTTP/1.1 | QUIC |
| Serialization | JSON | MessagePack |
| Transport encryption | None | TLS 1.3 |
| Auth model | Per-request | Per-connection |
| Metric | bittensor | lightning (Python) | lightning (Rust) |
|---|---|---|---|
| Connection setup (p50) | 114.46 ms | 2.68 ms | 0.71 ms |
| Latency p50 (1KB) | 24.01 ms | 0.08 ms | 0.05 ms |
| Latency p99 (1KB) | 28.80 ms | 0.09 ms | 0.07 ms |
| Throughput (1KB) | 41 req/s | 26,539 req/s | 68,650 req/s |
| Wire size (1KB payload) | 2,032 bytes | 1,052 bytes | 1,052 bytes |
| Color | System |
|---|---|
| bittensor | |
| lightning (Python) | |
| lightning (Rust) |
[!NOTE] Charts use log10 scale. Refer to the tables below for raw values.
Latency p50
---
config:
xyChart:
plotReservedSpacePercent: 60
themeVariables:
xyChart:
backgroundColor: "#000000"
plotColorPalette: "#808080, #FF8C00, #FFE000"
titleColor: "#ffffff"
xAxisLabelColor: "#aaaaaa"
xAxisTitleColor: "#cccccc"
xAxisTickColor: "#666666"
xAxisLineColor: "#444444"
yAxisLabelColor: "#aaaaaa"
yAxisTitleColor: "#cccccc"
yAxisTickColor: "#666666"
yAxisLineColor: "#444444"
---
xychart-beta
x-axis ["256B", "1KB", "10KB", "100KB", "1MB"]
y-axis "log10(us)" 0 --> 5
bar "bittensor" [4.39, 4.38, 4.39, 4.42, 4.61]
bar "lightning (Python)" [1.90, 1.90, 2.36, 3.27, 4.31]
bar "lightning (Rust)" [1.70, 1.70, 2.04, 2.84, 3.87]
Throughput (req/s)
---
config:
xyChart:
plotReservedSpacePercent: 60
themeVariables:
xyChart:
backgroundColor: "#000000"
plotColorPalette: "#FFE000, #FF8C00, #808080"
titleColor: "#ffffff"
xAxisLabelColor: "#aaaaaa"
xAxisTitleColor: "#cccccc"
xAxisTickColor: "#666666"
xAxisLineColor: "#444444"
yAxisLabelColor: "#aaaaaa"
yAxisTitleColor: "#cccccc"
yAxisTickColor: "#666666"
yAxisLineColor: "#444444"
---
xychart-beta
x-axis ["256B", "1KB", "10KB", "100KB", "1MB"]
y-axis "log10(req/s)" 0 --> 5
bar "lightning (Rust)" [4.92, 4.84, 4.27, 3.26, 2.26]
bar "lightning (Python)" [4.55, 4.42, 3.83, 2.94, 1.94]
bar "bittensor" [1.61, 1.61, 1.60, 1.57, 1.40]
Full results (all payload sizes)
Latency (ms)
| Payload | System | p50 | p95 | p99 |
|---|---|---|---|---|
| 256B | bittensor | 24.50 | 28.04 | 35.05 |
| lightning (py) | 0.08 | 0.19 | 0.23 | |
| lightning (rust) | 0.05 | 0.06 | 0.07 | |
| 1KB | bittensor | 24.01 | 25.57 | 28.80 |
| lightning (py) | 0.08 | 0.09 | 0.09 | |
| lightning (rust) | 0.05 | 0.06 | 0.07 | |
| 10KB | bittensor | 24.70 | 25.70 | 26.59 |
| lightning (py) | 0.23 | 0.24 | 0.26 | |
| lightning (rust) | 0.11 | 0.12 | 0.13 | |
| 100KB | bittensor | 26.13 | 27.31 | 29.42 |
| lightning (py) | 1.88 | 2.25 | 2.37 | |
| lightning (rust) | 0.69 | 0.73 | 0.75 | |
| 1MB | bittensor | 40.72 | 43.11 | 48.00 |
| lightning (py) | 20.55 | 22.48 | 23.31 | |
| lightning (rust) | 7.40 | 12.36 | 17.02 |
Throughput (req/s)
| Payload | bittensor | lightning (Python) | lightning (Rust) |
|---|---|---|---|
| 256B | 41 | 35,181 | 83,460 |
| 1KB | 41 | 26,539 | 68,650 |
| 10KB | 40 | 6,729 | 18,686 |
| 100KB | 38 | 875 | 1,819 |
| 1MB | 25 | 88 | 181 |
Wire overhead (bytes)
| Payload | bittensor | lightning |
|---|---|---|
| 256B | 1,008 | 284 |
| 1KB | 2,032 | 1,052 |
| 10KB | 14,321 | 10,268 |
| 100KB | 137,202 | 102,430 |
| 1MB | 1,398,771 | 1,048,606 |
Metadata
Release files for btlightning 0.2.15
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| btlightning-0.2.15.tar.gz | 127.8 kB | With provenance | Details |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| btlightning-0.2.15-cp312-cp312-manylinux_2_38_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.38+ x86-64 | Details |
| btlightning-0.2.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.17+ ARM64 | Details |
| btlightning-0.2.15-cp312-cp312-macosx_11_0_arm64.whl | CPython 3.12 | CPython 3.12 | macOS 11.0+ ARM64 | Details |
Total release size: 13.9 MB
Release files / btlightning-0.2.15.tar.gz
| Download URL | btlightning-0.2.15.tar.gz |
|---|---|
| Size | 127.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2a53b1577fa76a6b6940ceb9c63050169864e430ab68b809e4b04a5f11862d4e
|
|
BLAKE2b-256 checksum How to use checksums |
6e3925f908feca6b70d8c27dbd4aaa1c875d68c36350281434e8c5307072e54d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / btlightning-0.2.15-cp312-cp312-manylinux_2_38_x86_64.whl
| Download URL | btlightning-0.2.15-cp312-cp312-manylinux_2_38_x86_64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.12 Linux glibc 2.38+ x86-64 |
|
SHA-256 checksum How to use checksums |
11afb6cd780ff9fec40add28bdce82b23b80e99648c4fe26048a687d49b629b5
|
|
BLAKE2b-256 checksum How to use checksums |
42f8696eac8fd3ba44adcd8c72e4d02446de82cd4c871e10e0bb691d57caa275
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / btlightning-0.2.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | btlightning-0.2.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 4.4 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
d6369b7cc0deaf77bb318f44d20b70bba7c7696f4491905473dd17fbc70b6bf2
|
|
BLAKE2b-256 checksum How to use checksums |
55804a60084cd8c4571655c2a77e11019a4a11731bbfddd6e9e917408a1c595e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / btlightning-0.2.15-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | btlightning-0.2.15-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.5 MB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
113424f99d7e6ea19230a46dfaee23515a01d095a608cd4ca1af9e5b617a49c2
|
|
BLAKE2b-256 checksum How to use checksums |
a7a24a43ba7ba53086fdf0f5096178cd839908c74c003af9fa0bb6cdd80f7c5d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logSecurity for btlightning 0.2.15
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 4 files in this release have been uploaded with provenance metadata.
Attestation for btlightning-0.2.15.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.