NDSR · Necter Distributed State Runtime
Follow one task
through NDSR.
The journey, step by step
01 · Write
A developer writes a module
Projects are built with HiveKit in Rust, Go, TypeScript, JavaScript or Python. A module is a set of named functions that take input bytes and return output bytes, with access to a small set of host functions and nothing else.
02 · Compile
Compiled to Hive Bytecode (.hbc), content-addressed
HiveKit compiles your code to Hive Bytecode (.hbc), which NDSR executes deterministically on any device. A .hbc holds the compiled code and a strict manifest (name, language, compiler, runtime, sorted functions). Its address is the Keccak-256 hash of the canonical manifest and the code, so the address is the code.
03 · Publish
Published: signed and registered on-chain
The developer signs the project manifest (EIP-191) and registers it in the ProjectRegistry contract on Ethereum Sepolia with its consensus hash, manifest hash and worker module. The store relays the registration, so developers need no ETH for it. Every node that fetches the module re-checks its address.
04 · Committee
A committee is drawn by deterministic sortition
For each task slot, a committee of miners is drawn from an attested snapshot of the project’s bonded miners. The seed mixes a Sepolia block hash beacon fixed before the epoch with the project, epoch, slot and snapshot hash. Weights are collateral (capped) times reputation. Anyone can recompute who was chosen.
05 · Execute
Each miner runs it in the NDSR sandbox
NDSR validates the module, adds a deterministic stack-height limiter and runs it with a fuel budget equal to the gas limit. The module can only call host functions: storage, events, cross-module calls, hashing and a debug log. There is no WASI. Float NaNs are canonicalized and non-deterministic instruction-set features are disabled.
06 · Receipt
Same input, same receipt, on every device
The result becomes an execution receipt: module, function, hashes of input, output and events, gas used and success. Its Keccak-256 hash is signed with the miner’s ed25519 key. A phone on NDSR’s portable engine, a Mac and a server produce the identical receipt hash for the same call, and that hash is the miner’s vote.
07 · SecureWeave
SecureWeave consensus: quorum, finality, audits
A round is clean when ⌊2k/3⌋+1 committee members agree on one receipt hash. Validators then sign a finality record and exchange it over SecureWeave, NDSR’s Byzantine-fault-tolerant consensus; ⌊2n/3⌋+1 matching signatures make it final. A random share of rounds, drawn from a block nobody knew when voting, plus every contested round, is re-executed by validators. Miners who voted for a different result are caught and the evidence goes to slashing.
08 · State
State roots and state sync
Committed module state is hashed into 4,096 buckets and one state root per module, advanced with a sequence number on every write. Validator votes on stateful rounds carry the before and after roots. A quorum on the same transition attests the state, and a validator that falls behind catches up from peers by diffs or snapshots, checking every root on the way.
09 · Settle
Epoch rewards: Merkle root, attested, settled
When a project’s epoch closes, a leader validator turns finalized rounds into compute units per miner, computes amounts and a Merkle root, and proposes it. Other validators recompute it and attest only on an exact match. The attested receipt is settled on the project’s vault on Sepolia, and miners claim with Merkle proofs, gaslessly through the relayer.
Runtime
Hive Bytecode in, a receipt out
NDSR runs Hive Bytecode through one small, fixed interface, so it does not care which language produced a module. A module exports its memory, an allocator and a single entry point; the host passes the function id and input bytes and gets back output bytes. Each call runs in a fresh instance with a fuel budget, and its state writes commit atomically only if the whole call succeeds.
A deterministic failure (trap, abort, out of gas) still produces a receipt that every honest node agrees on. A node error, such as a network failure fetching a called module, produces no receipt at all: a node never votes on a result it could not compute.
Entry points
memory, __alloc(len), __hive_entry(func_id, ptr, len) → packed i64
Enabled
multi-value, bulk memory, reference types, SIMD (NaN-canonicalized), tail calls
Disabled
threads, relaxed SIMD, 64-bit memory, multi-memory, GC, exceptions, stack switching
Pinned
one exact engine version network-wide; upgrading it is a protocol change
Gas and limits
Every instruction has a price
Gas is metered per instruction, roughly one unit each, plus a fixed cost for each host call charged before it does any work. The deterministic stack limiter adds 12 gas per function call. When a call runs out of gas, gas_used equals the gas limit. All limits below are consensus parameters: every node on a network enforces the same values.
| Limit | Default |
|---|---|
| .hbc file / compiled code / manifest | 16 MiB / 12 MiB / 64 KiB |
| Linear memory per instance | 64 MiB |
| Input / output | 1 MiB / 1 MiB |
| Events per call | 64 (name 64 B, data 16 KiB) |
| Storage key / value | 256 B / 64 KiB |
| State written per top-level call | 1 MiB |
| hive.call depth | 8 |
| Logical stack | 65,536 units per instance |
| gas_limit | 1 … max_gas_limit (default 10^10) |
Host functions
The only doors out of the sandbox
A module may import these functions and nothing else; any other import makes it invalid. Host functions that return data allocate it through the module’s own allocator, so the module pays for it.
| Import | What it does | Gas |
|---|---|---|
storage.get | Read a key of this module’s own state | 1,000 + 1/byte of key and value |
storage.set | Write a key (an empty value deletes it) | 5,000 + 10/byte of key + value |
storage.del | Delete a key | 2,000 + 1/byte of key |
hive.emit | Append an event {name, data}; data is canonical JSON, no floats | 500 + 2/byte |
hive.call | Call another module synchronously; its gas is charged to the caller | 10,000 + 1/byte + callee gas |
crypto.hash | Keccak-256 of bytes, returned as 0x… | 200 + 1/byte |
console.log | Debug log on the node, no consensus effect | 100 + 1/byte |
hive.abort | Fail the call with a message | — |
Receipts
A hash every honest node agrees on
A receipt holds only consensus fields: no timestamp and no node id. Its hash is Keccak-256 over canonical JSON (sorted keys, no whitespace, integers only), and each node signs "necter-receipt-v1:" + receipt_hash with its ed25519 key. Same module, input, gas limit and prior state give the same receipt hash on every node running the same NDSR version.
execution receipt (illustrative values)
{
"v": 1,
"module_address": "0x9f3a…c2e1",
"function": "increment",
"input_hash": "0x51d0…7a3b",
"output_hash": "0xc4e8…1f09",
"events_hash": "0x0a7f…e2d4",
"gas_used": 1204551,
"success": true
}Committees and audits
Redundant work, unpredictable checks
Each task slot gets a committee drawn from an attested snapshot of the project’s bonded miners, weighted by collateral (capped) times reputation. A round is clean when ⌊2k/3⌋+1 members agree, counting activated backups. Validators sign a finality record, final at ⌊2n/3⌋+1 validator signatures.
Validators re-execute every contested round and a random share of clean ones: 10% during the testnet, drawn from the first Sepolia block after the round deadline. A miner whose vote differs from an audited result, or who signs two different results for one round, leaves self-proving evidence. Slashing goes through a dispute window: up to 50% of the bond for an invalid result and 100% for equivocation. On the testnet, missed deadlines only cost reputation.
If a slot has too few eligible miners or no valid snapshot, the task runs on the validators instead (validator fallback): the client still gets a result, but no miner earns units for it.
sortition (PLATFORM §e.4)
seed = keccak256("necter-sortition-v1" ‖ beacon(E) ‖ project_id ‖ u64be(E) ‖ u64be(seq) ‖ set_hash)
L = snapshot entries, W = Σ weights
for j in 0 .. k + b − 1:
x = uint256(keccak256(seed ‖ u32be(j))) mod W
i = smallest index with w[0] + … + w[i] > x
draw[j] = L[i]; W −= w[i]; remove L[i]
draw[0 .. k−1] = primaries, draw[k ..] = backups, q = ⌊2k/3⌋ + 1SecureWeave
Signed votes, woven into finality
SecureWeave is NDSR’s Byzantine-fault-tolerant consensus layer. Validators sign their votes and exchange them node to node over authenticated gossip. A result is final when ⌊2n/3⌋+1 distinct current validators sign the same hash, and finalization is a pure function of the signed vote set: anyone holding the votes can check it.
What it finalizes
Committee task rounds, epoch reward receipts and module state attestations, which are the basis of state sync.
Equivocation
A validator that signs two different results in one round produces a verifiable proof against itself, and its votes stop counting.
Durable
Every accepted vote is persisted and replayed on restart; late votes are recorded and still credited in reward rounds.
Authenticated gossip
Votes travel as node-signed requests with replay protection, deduplication and backoff between validators.
On the testnet, validators are approved by the network operator; validator selection is planned to move to stake later.
Engines
Native or portable, the same receipt
NDSR has two engines. On x86_64 and aarch64 the native engine compiles each module to machine code; on iOS and on 32-bit ARM phones the portable engine interprets it. Both get the same fuel-instrumented, NaN-canonicalized code and the same deterministic stack limit, so outputs, events, gas and receipt hashes are identical, and a network can mix both. The test suite runs every fixture, the pinned test vectors and SDK-built modules on both engines and compares them.
| Workload | Native Mgas/s | Portable Mgas/s | Ratio |
|---|---|---|---|
| Tight loop (1 G gas) | 1,483 | 285 | 5× |
| Integer mix (187 M gas) | 2,978 | 250 | 12× |
| QuickJS counter.increment (3.2 M gas) | 475 | 135 | 3.5× |
| Go math.multiply (81 k gas) | 92 | 54 | 1.7× |
| AssemblyScript / Rust counter (12–14 k gas) | 87 / 46 | 40 / 35 | 1.3–2× |
Measured on an Apple M-series host, release build, per call, with the portable engine in its 64-bit form. On a 32-bit ARM core it is slower still. Under the hood, .hbc modules run on a hardened WebAssembly engine pinned to one exact version.
Security model
Trust the math, not the operator
SecureWeave finality
No result, state or payout is final without signatures from ⌊2n/3⌋+1 validators, and equivocating validators are excluded by proof.
No ambient authority
Modules can only call the Hive host functions. No system interface, no clock, randomness, filesystem or network; storage is namespaced by module address.
Code is its address
Every .hbc is re-verified against its Keccak-256 address wherever it crosses a trust boundary: upload, node fetch, cache read.
Bounded everything
Out-of-bounds pointers, over-limit lengths and bad UTF-8 trap the call; they never crash the host or allocate the requested size.
Signed and replay-protected
Node requests carry an ed25519 signature over method, path, time, nonce and body hash, rejected after 300 s or when a nonce repeats.
Unpredictable selection and audits
Committees come from a beacon fixed before the epoch; audits from a block produced after the round deadline, which miners cannot know when they vote.
Self-proving evidence
Equivocation and invalid results are proven by the offender’s own signatures plus a validator quorum, then go through a dispute window before slashing.
Validators guard payouts
Rewards settle only with an epoch receipt attested by ⌊2n/3⌋+1 validators; claims cannot exceed the epoch’s settled total.
Known testnet trade-offs: a Sepolia block producer could bias a beacon by withholding a block, which is accepted for the testnet; the audit rate is set high and will be lowered later.
Roadmap
What runs today, and what is next
- Deterministic work class with miner committees
- Validator finality, random audits and slashing evidence
- Per-project reward epochs settled on Ethereum Sepolia
- Native and portable engines; Rust, Go, TypeScript, JavaScript and Python SDKs
EVM compatibility
Solidity contracts and familiar EVM tooling on the Necter Network, next to NDSR workloads. Not live yet; details will be published before release.
- Resource-proof work: storage, bandwidth and uptime challenges
- Off-chain compute with redundant runs and spot checks
- Uptime SLAs and validator-recomputed reputation
- A lower audit rate once the network has history