The API is under active development and subject to breaking changes until
v1.0.0. The crates are not on crates.io yet, so depend on them by git for
now.
cargo doc --open in the repository is always the authoritative
reference; this page is an orientation.The one thing to know first
ntl-core is synchronous. It contains no async functions at all, holds no
async runtime, and reaches for no ambient clock or randomness — those arrive
through the injected Clock and Rng traits. That
is what keeps the crate building for wasm32-unknown-unknown, which CI
enforces on every commit.
So there is no .await anywhere in the samples below. Async lives one layer
out, in ntl-net, which owns the transport and the task that drives it.
Crate Structure
The crate isntl_core — note the underscore in Rust paths.
Quick Reference
Every sample here is compiled and executed byruntime/ntl-core/tests/api_reference_samples.rs. If the API changes, that
test stops building — which is the only way documentation like this stays true.
Creating a node
A node needs a store. There is no default: a node that silently kept its state in memory when you meant to persist it would lose every learned weight on restart without saying so.NodeBuilder also takes with_config, with_config_file, with_identity,
with_clock and with_rng. There is no with_crypto_module: the module is
named in configuration (crypto_module), and a node asked for one this build
cannot provide fails to start rather than substituting another.
Emitting signals
The builder is handed to the node. The node stamps origin, identifier and timestamp, so there is noemit on the builder itself.
Signal::event and Signal::command are the other constructors. The builder
also carries with_ttl, with_scope, with_correlation and with_delivery.
Receiving signals
There is no handler-registration API. A node is driven by whoever owns the transport: you hand it a signal and it returns aDisposition describing what
it did — queued, fired, evicted, or refused.
receive is the peer-facing form, which additionally verifies the origin
signature and clamps inbound headers. poll_activation drains whatever the
gate has released.
Managing synapses
Synapses are store state, read through a filter rather than a method on the node.SynapseFilter::eligible() over active() for anything routing-related.
eligible includes Weakening, and excluding it would make weight recovery
impossible — a synapse that failed once could never earn its way back. That is
a normative requirement in
synapse-lifecycle, not a preference.
The store’s errors are StoreError, which does not convert into
ntl_core::Error. A function returning ntl_core::Result cannot use ? on a
store call.
Module References
Node
Node initialization, lifecycle, and management
Signal
Signal creation, types, and encoding
Synapse
Synapse management and configuration
Adapter
Adapter trait and built-in implementations
Every sample on all five pages is compiled and run by the test suite. Each
page has a test file that holds its samples verbatim, so a sample that stops
matching the code fails CI rather than quietly misleading a reader:
Before this, none of it compiled: the pages carried
use ntl:: for a crate
named ntl_core, .await on a crate with no async fn, and identifiers that
never existed (SignalHandler, register_handler, with_crypto_module,
node.synapses()). Closes
openNTL/ntl#21.