Overview
| Consensus | Greatest sum of verified per-block difficulty; equal work keeps the current branch |
| Proof of work | RandomX-v1 (randomx-rs 1.6.0), light-mode verification ≈ 256 MiB |
| Shielded protocol | Ironwood-v3 bundles, Halo 2 proofs, 32-level note commitment tree |
| Block target | 60 seconds, per-block LWMA-style retarget |
| Block limits | 2,000,000 bytes; ≤ 64 ordinary transfers plus miner and treasury issuance |
| Transaction limits | 200,000 bytes; 2–16 actions (coinbase classes exactly 1) |
| Supply | 21,000,000 GNR in u128 gori (1 GNR = 10¹² gori) |
| Emission | Blocks 1–500: 1,000 GNR early subsidy each (500,000 GNR, ~2.38%; fees extra). From block 501: normal subsidy of 4.825437595129 GNR halving every 2,102,400 blocks, plus 1 GNR treasury per block for heights 501–210,500, burned on mainnet. Monetary Policy & Emission Schedule |
| Genesis message | "Privacy is not a feature. Privacy is the default." |
Consensus
Nodes select the valid branch with the greatest cumulative work, where work is the sum of each block's verified integer difficulty. Height 1 follows a deterministic, network-specific, zero-issuance genesis record. The Mainnet 1.0 genesis (genoryn-mainnet-1.0, tag 2026-10-10-mainnet-1.0, hash 2b27dda9…6b2e) was finalized in release 1.0.0; every program defaults to Mainnet 1.0, while devnet and testnet remain for development labs. The earlier network genoryn-mainnet-v1 (releases 0.4–0.6) is retired and its coins do not carry over.
A block's timestamp must exceed the median of up to 11 preceding timestamps and be at most 120 seconds ahead of the node's UTC clock. Reorganisations replay maturity, anchors and nullifiers from the competing branch and then reconsider mempool transactions.
Block header
The header commits to every consensus-relevant field. Its hash is the block hash.
struct Header {
version: u16, // 1
network: Network, // Devnet | Testnet | Mainnet (u32 tag)
height: u64,
previous: [u8; 32], // parent block hash
timestamp: u64, // Unix seconds
difficulty: u64, // integer difficulty for this block
pow_seed: [u8; 32], // RandomX epoch key
nonce: u64,
body_hash: [u8; 32], // H("GENORYN/body/v1", body)
notes_root: [u8; 32], // matured note-commitment root
nullifiers_root: [u8; 32],
}Block body
struct Body {
miner: ShieldedTx, // kind 1, exact scheduled issuance
treasury: Option<ShieldedTx>, // kind 2, heights 501..=210,500
transactions: Vec<ShieldedTx>, // kind 0, at most 64
}Only coinbase classes may have a negative value balance. Their exact amounts, height, parent, network, spend-disabled flags and treasury receiver are validated. All ordinary transfers have positive public fees and no transparent value output.
Transactions
Each transaction contains a signed context and one Ironwood-v3 bundle. The context binds protocol version, network, kind, height, expiry and a nonce; cross-network signature reuse is rejected. Transfers use kind 0, height 0, a random nonce and a bounded expiry. Issuance uses kind 1 or 2, its actual height, no expiry and the previous block hash as nonce.
struct ShieldedTx { context: TxContext, bundle: BundleWire }
struct TxContext { protocol: u16, network: Network, kind: u8, height: u64, expires: u64, nonce: [u8; 32] }
struct BundleWire {
actions: Vec<ActionWire>, flags: u8,
value_balance: i64, // public fee (>0) or issuance (<0)
anchor: [u8; 32], proof: Vec<u8>, binding_signature: Vec<u8>,
}
struct ActionWire {
nullifier: [u8; 32], rk: [u8; 32], cmx: [u8; 32], ephemeral_key: [u8; 32],
encrypted_note: Vec<u8>, outgoing_ciphertext: Vec<u8>,
value_commitment: [u8; 32], signature: Vec<u8>,
}There is no username, ordinary receiver, transfer amount or plaintext memo field anywhere in the wire transaction. Validation checks all signatures, the proof, flag and amount constraints, a recognized mature anchor, duplicate nullifiers and chain/mempool conflicts.
Encoding and hashing
Consensus objects use canonical bincode 1 with fixed-width little-endian integers. Decoding rejects trailing bytes and must round-trip byte for byte. Every hash is SHA-256 with explicit domain separation and length prefixes:
| Object | Domain | Preimage |
|---|---|---|
| Block hash | GENORYN/block/v1 | encoded header |
| Body commitment | GENORYN/body/v1 | encoded body |
| Transaction ID | GENORYN/transaction/v1 | entire authorized encoded transaction |
| Genesis | GENORYN/genesis/v1 | canonical genesis preimage |
The genoryn.io explorer re-implements exactly this encoding in TypeScript to derive block hashes and transaction IDs, and checks its result against the node's best hash on every sync.
State and maturity
- Mature note commitments form the upstream 32-level tree. Only recent admitted roots (a 120-block window) may anchor transfers.
- Mining outputs wait 60 blocks on mainnet and testnet (2 on the devnet lab) before they enter spendable trees.
- On mainnet the treasury receiver is the burn address: a full viewing key whose
akis a hash-to-curve point with no known discrete logarithm, so no spend authorization can ever exist. Test networks keep a public test key with the year-10–19 vesting schedule. - Nullifiers are unique across all accepted actions.
- SQLite (WAL) atomically stores blocks and the best-tip change; a process lock prevents two writers; schema, network and genesis checks reject incompatible databases.
Peer protocol
TCP frames start with four-byte network magic (GNR + 0x10 + network id; Mainnet 1.0 is 0x474e5213), a little-endian u32 length and a canonical typed message; frames over 2,100,000 bytes are rejected before allocation. The handshake validates version, network, genesis and peer identity.
- Messages: block locators, one-block responses, announcements, shielded-transaction relay, peer exchange, ping/pong.
- Limits: 16 connections, 8 outbound; outbound peers rotate after 15–30 minutes while another validated peer remains.
- Discovery: explicit peers, a 128-entry persistent cache, peer exchange, operator DNS seeds and the published seed list. Seeds are never consensus authorities.
- Misbehaviour earns strikes, disconnection and temporary bans.
- Built-in Tor with Direct, Hybrid and Tor-only modes, v3 onion services, AddrV2/Announce extension messages for onion addresses (negotiated, so v1 peers are unaffected), and a one-hop stem for locally created payments. See Tor & privacy.
Run your own node: Nodes.
On-chain usernames
Names are derived state computed while applying each fully validated block. A registration is an ordinary kind-0 transfer with one output paying at least the price to the burn address; its 512-byte memo carries a signed record (magic GNRNAME\x01, operation, name, 43-byte receiver, Ed25519 owner, sequence, signature). Names are not committed in headers, never make a block invalid, and are recomputed on reorganizations — so no activation height or network split is needed.
Prices burned: 1,000 GNR (3–4 characters), 100 GNR (5–6), 10 GNR (7+); updating the receiver burns 1 GNR. Details on the Names page.
RPC
Versioned HTTP RPC (/v1). The administrative listener binds to loopback only and requires a capability token; the optional public listener is read-only. No endpoint returns a balance for an address, a wallet history, a rich list or a price. See the API reference.
Versions and upgrades
Current release 1.0.0 (Mainnet 1.0). Versions: consensus 1, block 1, transaction 1, P2P 1, RPC /v1, wallet file 1, database schema 1, name record 1, payment URI 1 (experimental). Unsupported versions fail closed. Future consensus upgrades must publish a specification and activation height, review new proving keys and monetary invariants, generate cross-platform vectors, and require explicitly compatible software. There is no founder override and no remotely signed exception.
Full source of truth: docs/protocol and the architecture decision records.