SecureWeave consensus
SecureWeave is the consensus layer built into NDSR. Every validator runs it. It collects signed votes from validators, decides when a round is final, detects validators that vote two ways, and stores every vote so the decision can be checked and replayed later. Everything Necter treats as final goes through it.
What SecureWeave finalizes
Section titled “What SecureWeave finalizes”| Round | Vote kind | What validators agree on | Used for |
|---|---|---|---|
exec:0x… |
execution |
the receipt hash of a direct call (and the module state transition) | POST /v1/execute, validator fallback, escalated tasks |
task:0x… |
finality |
the finality record of a committee round (its correct receipt hash, gas and the miners who matched it) | mining projects (Finality) |
epoch:<project>:<epoch>:<attempt> |
epoch |
the per-project reward receipt v2 | miner payouts (Rewards) |
reward:… |
reward |
a v1 module reward receipt | legacy module vaults |
Execution votes can also carry module state transitions. When a quorum agrees on the same receipt and the same transition for a module, that is a state attestation: the proof validators use for state sync.
Committee miners vote too (task votes), but on the Hub, not through SecureWeave. SecureWeave is what
validators use to sign off on the committee’s result.
{ "round_id": "exec:0x…", "kind": "execution", "receipt_hash": "0x…", "node_id": "ndsr-…", "public_key": "0x…", "signature": "0x…", "round_signature": "0x…", "payout_address": "0x…", "round": { "module_address", "function", "input_hash", "gas_limit", "nonce", "issued_at" }, "receipt": { "v", "module_address", "function", "input_hash", "output_hash", "events_hash", "gas_used", "success" }, "state": [ { "module_address", "pre_seq", "pre_root", "post_seq", "post_root" } ]}Each vote has two ed25519 signatures from the validator’s node key:
-
signature: the protocol signature over the result, with a domain per kind:necter-receipt-v1:+ receipt hash (execution),necter-finality-v1:+ finality hash,necter-reward-v2:+ receipt hash (epoch),necter-reward-v1:+ receipt hash (v1 reward). -
round_signature: binds the vote to one round and one payout address:necter-vote-v1<kind><round_id><receipt_hash><payout_address or empty><state_hash or finality_hash> ← sixth line only when the vote carries state or a finality recordA protocol signature alone is not a vote, so a receipt signed for one round cannot be replayed in another or redirected to another payout address.
Receivers check both signatures, that node_id matches the public key, that the key is a current validator,
and recompute round_id from round and receipt_hash from receipt. Votes are self-authenticating:
anyone can verify them, and nodes can relay each other’s votes.
Quorum and finality
Section titled “Quorum and finality”With n current validators, a round is final on hash H when H has votes from
⌊2n/3⌋ + 1 distinct validators that did not equivocate. On the testnet n = 4, so the quorum is 3 and any
one validator can be down or faulty.
- Finalization is a pure function of the vote set. Given the same votes, every node, auditor or tool
computes the same state (
pending,finalized, orfailedwhen no hash can reach quorum any more), whatever order the votes arrived in. - Two different hashes can never both reach quorum while fewer than a third of validators are faulty: any two quorums share at least one honest validator.
- For finality votes, validators agree on the whole record (
finality_hash), not just the receipt hash, so they also agree on which miners were right.
Equivocation
Section titled “Equivocation”A validator that signs two different hashes in the same round is an equivocator. The two signed votes
are an EquivocationProof that anyone can verify. From then on, none of that validator’s votes count in
that round, and the proof is recorded (GET /consensus/evidence) for slashing. At most two votes per
validator per round are stored, so equivocation cannot be used to flood a node.
The same rule applies to miners on the committee level: two task votes by one key in one round are equivocation and slash the whole bond (Slashing).
Late votes
Section titled “Late votes”A vote that arrives after the round finalized is answered late, with whether it agrees with the final
hash. It does not change the decision. In reward rounds an agreeing late vote is still credited.
Gossip
Section titled “Gossip”sequenceDiagram
participant H as Hub
participant V1 as Validator 1
participant V2 as Validator 2
participant V3 as Validator 3
participant V4 as Validator 4
H->>V1: round (execute / task bundle / epoch proposal)
H->>V2: round
H->>V3: round
H->>V4: round
Note over V1,V4: each executes or verifies, signs a vote
V1->>V2: POST /consensus/votes (node-signed)
V1->>V3: POST /consensus/votes
V2->>V1: POST /consensus/votes
V3->>V1: POST /consensus/votes
Note over V1,V3: 3 of 4 agree → finalized on every node,<br/>computed from the same vote set
V4-->>V1: late vote → outcome "late"
H->>V1: GET /consensus/rounds/{round_id}
V1-->>H: tally, state, equivocators, dissenters
- Every validator
POSTs its vote to/consensus/voteson every other validator, node-signed, retrying with exponential backoff. The answer is{"outcome": "accepted" | "duplicate" | "equivocation" | "late", "state": …}, or 422 for an invalid vote. GET /consensus/rounds/{round_id}on any validator returns its view: tally per hash, state, quorum, equivocators and dissenters. It is open to anyone.
Persistence and replay
Section titled “Persistence and replay”Every accepted vote and its round context is written to the validator’s consensus.db and replayed on
restart, so a restarted validator reaches exactly the same decisions. Votes are kept for 7 days (finality
votes at least until their project epoch’s reward receipt is settled) and pruned hourly. The highest state
attestation per module is kept with its votes as proof.
The validator set
Section titled “The validator set”The set of keys SecureWeave counts comes from the Hub (GET /api/validators, refreshed every 60 s by
default, cached in consensus.db): approved validators, sorted by public key, with
quorum = ⌊2n/3⌋ + 1. Nodes can also be pinned to a static set with --validators. External validators are accepted only at mainnet; during the testnet the validator set is operated by the Necter team.
How it fits with committees, audits and slashing
Section titled “How it fits with committees, audits and slashing”flowchart LR
C[Committee of miners<br/>task votes] --> B[Hub bundles the votes]
B --> V[Validators verify,<br/>audit if contested or drawn]
V -- finality votes --> SW{{SecureWeave<br/>⌊2n/3⌋+1}}
SW -- finalized record --> U[Units for matching miners]
U --> E[Epoch receipt]
E -- epoch votes --> SW2{{SecureWeave}}
SW2 -- attested receipt --> PV[(Project vault)]
V -. wrong votes + audited finality .-> S[Slashing evidence]
- Committees decide who computes; SecureWeave decides what is final.
- Audits make finality records trustworthy even if a whole committee lies; the finality quorum is what turns an audit into a proof.
- Slashing evidence for invalid results is a miner’s wrong vote plus a SecureWeave finality quorum on an audited record. Validator equivocation proofs are recorded too.
- Payouts need an
epochquorum: the Hub cannot pay anyone without validator signatures.