NDSR: the runtime
NDSR (Necter Distributed State Runtime) is the engine under everything on Necter. It loads .hbc
modules, executes one exported function per call, meters gas, keeps per-module persistent state, and signs
a receipt whose hash is identical on every honest node. Its consensus layer, SecureWeave, aggregates validator
votes into quorum-backed, final results.
The same code runs in three places:
| Where | How |
|---|---|
| Validators | ndsr serve: an HTTP node that executes consensus rounds, gossips votes, finalizes committee rounds, keeps module state and attests reward receipts. |
| Miners | The Necter Miner embeds NDSR as a library and runs committee tasks with exactly the code validators use to check them. |
| Your machine | ndsr run executes a module locally and prints the signed receipt, ndsr inspect validates an artifact. Every HiveKit hivec run calls it. |
What NDSR guarantees
Section titled “What NDSR guarantees”- Sandbox. A module sees only its own linear memory and a small set of host functions. There is no WASI, no clock, no randomness, no filesystem and no network. Every pointer is bounds-checked; memory, tables, call depth, inputs, outputs, events and state writes are capped.
- Determinism. NaN results are canonicalized, non-deterministic instruction-set features are disabled, the engine version is pinned, and a deterministic stack limit is injected into every module, so runaway recursion stops at the same gas on every machine. Details
- Same results on every CPU. On x86_64 and aarch64 NDSR runs modules on its native engine; on 32-bit ARM phones it uses its portable engine (an interpreter). Both consume the same fuel-instrumented code, so output, events, gas and receipt hash are identical. A network can mix both.
- Integrity. Modules are content-addressed and re-verified on every fetch and cache read. Receipts are signed with the node’s ed25519 key.
- Atomic state. State writes and events are committed only if the whole top-level call succeeds. State
Engines and speed
Section titled “Engines and speed”The portable engine is slower than the native engine. Measured on an Apple M-series host (release build, per call):
| Workload | native engine Mgas/s | portable engine Mgas/s |
|---|---|---|
| tight loop | 1 483 | 285 |
| integer mix | 2 978 | 250 |
| float mix with NaNs | 2 301 | 45 |
Go math.multiply |
92 | 54 |
AssemblyScript / Rust counter.increment |
87 / 46 | 40 / 35 |
Small calls are dominated by fixed per-call work (loading, receipt, signing), so the portable engine’s cost shows mainly in compute-heavy calls. A project can exclude slow engines in its scheduling requirements.
Try it
Section titled “Try it”ndsr inspect dist/my_module.hbc # manifest, address, function ids, ABI checkndsr run dist/my_module.hbc addNumbers --input '{"a":2,"b":3}'ndsr run dist/my_module.hbc increment --input '{"by":2}' --data-dir ./node # state persists in ./nodendsr run prints the result and the signed receipt (abridged):
{ "error": null, "gas_limit": 1000000, "gas_used": 10570, "output": "{\"total\":5}", "receipt": { "node_id": "ndsr-eedd6fd9d0db3736", "public_key": "0xfdc31b7a…7d39c96", "receipt": { "events": [], "events_hash": "0x518674ab…a73d70", "function": "addNumbers", "gas_used": 10570, "input_hash": "0x52377ca4…570060", "module_address": "0x9cf5a3ab…be6127", "output_hash": "0xd7b6e5ab…6029dd", "receipt_hash": "0x38b6fb0c…ffb69d", "success": true, "v": 1 }, "signature": "0x32beca0f…014b0c", "timestamp": 1791473539 }, "success": true}Getting NDSR
Section titled “Getting NDSR”See Install the tools. Validators run the same binary with ndsr serve; see
Run a validator.