How NOCTIS works

protocol · api · faq

NOCTIS is a private proof-of-work chain. Senders, receivers and amounts are hidden by default on every transaction. This page explains each piece and the API the wallet uses.

Addresses

A wallet is one 32-byte seed. From it come a spend key and a view key (scalars on ristretto255) and an ML-KEM-768 key pair. Each wallet has two addresses:

noct1…   classic: spend public key + view public key (97 characters)
noctq1…  quantum: the same keys + an ML-KEM-768 public key (about 1,700 characters)

Both receive into the same wallet. The quantum address is long because post-quantum public keys are large.

Quantum addresses (ML-KEM-768)

An noctq1 address carries an ML-KEM-768 public key next to the normal spend and view keys. ML-KEM is NIST's standard key-encapsulation scheme (FIPS 203), built on lattice problems (Module-LWE). Shor's algorithm, the quantum attack that breaks elliptic-curve keys, has no known equivalent against these lattice problems.

Paying it: the sender runs ML-KEM encapsulation against your public key. That gives a fresh 32-byte shared secret and a 1,088-byte ciphertext. The secret derives the payment's one-time address and the key that encrypts the amount; the ciphertext rides on chain with the output. No address and no amount are ever written.

Detecting it: your wallet downloads outputs and runs ML-KEM decapsulation on each ciphertext with your secret key, locally in your browser. If the recovered secret derives the output's one-time address, the payment is yours, and the same secret decrypts the amount. Nobody else holds the secret key, so nobody else can tell which outputs are yours.

Why it matters: anyone can save a copy of a chain today and wait for a quantum computer. On classic ECDH addresses that copy could later be used to link payments to receivers. On noctq1 addresses the link sits behind ML-KEM, so the saved copy stays unlinkable. Code: makeOutput and scan in client/rct.js.

Stealth outputs

Nobody pays an address directly. For every payment the sender derives a fresh one-time address P = Hs(secret, i)·G + A. The shared secret comes from ECDH with the view key on classic addresses, or from ML-KEM-768 encapsulation on quantum addresses, in which case the 1,088-byte ciphertext rides with the output. The receiver checks every output with their view key or ML-KEM secret key. Nobody else can tell two payments to the same wallet are related.

Hidden amounts

Amounts are Pedersen commitments C = x·G + v·H. The blinding factor x and the amount travel encrypted to the receiver. Every output carries a 48-bit range proof: 48 bit commitments, each with a 2-member ring signature proving it opens to 0 or to 2^j. This stops anyone creating coins from negative amounts. Inputs and outputs balance as points: Σ pseudo-inputs = Σ outputs + fee·H.

Ring signatures and key images

Each input names 16 outputs from the chain: the real one and 15 decoys. An MLSAG signature over two rows proves that the signer owns one of the 16 one-time keys, and that its commitment matches the pseudo-input commitment, without saying which one. The signature publishes a key image I = x·Hp(P). One output always gives the same key image, so a second spend is rejected, yet nothing links the key image to the output.

Verify any transaction yourself

Every transaction page in the explorer has a verify in your browser button. Your browser fetches the transaction and its ring members from /api/rawtx/:id and runs the same verifyTx the node runs: every MLSAG ring signature, every 48-bit range proof and the balance of commitments. Nothing is taken on trust from the node. The code is public on GitHub, with a test suite that runs on every push.

Proof of proof

NOCTIS uses Nockchain's consensus idea: a block is won by proving a computation, not by grinding a hash. From the header and a nonce the miner derives two Goldilocks field elements (p = 2^64 − 2^32 + 1) and runs 1,023 rounds of a' = (a+b)^7 + c_i, b' = a with fixed round constants. All 1,024 states are Merkle-committed. The block is valid when sha256("noctis/pow|" root | header | nonce) × difficulty < 2^256 and the proof checks: the first state matches the seed, the last state is in the tree, and 32 steps drawn by Fiat–Shamir from the root open correctly, each with the step after it. Faking a fraction f of the trace survives with probability (1 − f)^32. Difficulty retargets every block toward 20 seconds. The reward is (2^32 − mined) / 2^19 with a 2 NOCT tail. Code: client/pop.js.

Light client: verify the chain yourself

Open /verify and press verify the chain. Your browser downloads the raw block headers and rebuilds every block hash from block 0, checking that each block points at the one before it. It re-runs the proof of proof on recent blocks against the headers it rebuilt, then reads every anchor calldata straight from a Robinhood Chain RPC and checks that Robinhood Chain recorded the same hash. The node only supplies data; every check runs on your device. Code: client/light.js.

Watchtowers

A watchtower is anyone who has verified the chain and signed for it. After a full check, /verify signs noctis-1/attest|height|hash|proofs|anchors|kind|time with an ed25519 key kept in your browser and posts it to POST /api/attest. The node refuses an attestation whose hash is not its own block at that height, so every entry on the board is an independent party agreeing on the same chain. To run one on a server: node verifier/watch.js. It re-checks new headers, recent proofs and new Robinhood Chain anchors every minute and attests the tip. If anything ever fails to match, it prints VERIFICATION FAILED and stops attesting.

Robinhood Chain anchors

Every 100 blocks the node writes noctis-1:<height>:<block hash> to Robinhood Chain as the calldata of a Robinhood Chain transaction, signed by the anchor key. The explorer links each anchored block to its the Robinhood Chain explorer transaction, and /api/anchors lists them all.

Totality

Totality is the quantum upgrade. ML-KEM payment detection is live today on noctq1 addresses. Two parts are still ahead. Spends move from elliptic-curve ring signatures to hash-based proofs. The anonymity set grows from 16 outputs to the whole chain. Coins move to the new format once, and the wallet does it for you.

API

GET  /api/work?address=A            block template paying the coinbase to A
POST /api/work   {id, proof}         submit a proof (re-checked by the node)
GET  /api/proof/:height             header, difficulty and proof of a recent block
GET  /api/anchors?all               Robinhood Chain anchors (height, hash, signature)
GET  /api/headers?from=N&limit=1000 raw header fields for light clients
POST /api/attest  {height,hash,proofs,anchors,kind,ts,pub,sig}  watchtower attestation
GET  /api/attest                    watchtower board
GET  /api/stats                     chain height, difficulty, outputs, key images, emission
GET  /api/blocks?limit=15&before=N  recent blocks
GET  /api/block/:height|:hash       one block with its transactions
GET  /api/txs                       mempool + recent private transactions
GET  /api/tx/:id                    rings, key images, commitments, ML-KEM ciphertexts
GET  /api/rawtx/:id                 full transaction + ring members, for independent verification
GET  /api/search?q=                 height, block hash, tx id or key image
GET  /api/outputs?from=G&limit=2000 outputs for wallet scanning
POST /api/spent   {kis:[…]}         which key images are spent
GET  /api/decoys?n=15&avoid=a,b     random ring members
POST /api/tx      {tx}              submit a private transaction
POST /api/faucet  {address}         25 NOCT, once an hour

Run a node

git clone https://github.com/NoctisChain/noctis
cd noctis && npm i && npm start      # http://localhost:8274

Environment: PORT, DATA_PATH (chain file), BLOCK_SEC (target block time), RH_KEY (anchor signer, base58 or JSON array), RH_RPC, ANCHOR_EVERY, NOCTIS_MINT (the $NOCT token address shown on the site).

FAQ

How do NOCTIS and $NOCT relate? NOCTIS is the private chain: its coins are proved into existence by miners. $NOCT is the network's token on Robinhood Chain, and the chain's history is anchored to Robinhood Chain every 100 blocks.

Where are my keys? In your browser's local storage, created on your device. The node never sees your seed, view key or ML-KEM secret key. Back up the seed. Clearing site data without it loses the wallet.

Why does sending take a few seconds? Your browser builds the ring signature, 48-bit range proofs for every output and, for quantum addresses, an ML-KEM encapsulation. That work happens on your device so nothing private is sent to the node.

Can the explorer see my balance? No. It shows rings, key images, commitments and ciphertexts. Only the wallet holding the view key or ML-KEM secret key can open an output.

What does a quantum computer break today? Elliptic-curve keys, so it could in theory unmask ECDH payment detection on classic addresses. Payments to noctq1 addresses use ML-KEM-768, a NIST-standard lattice scheme designed to resist that. Totality extends the same protection to spends.

Why 16? A ring of 16 is a practical size for proof time and transaction size. Totality removes the limit by hiding each spend among every output.