Reference / Protocol
Ravelnonce testnet protocol
This page separates the issuance facts already present in the checked-in project tests from implementation choices made for the first runnable testnet node. The latter are testnet rules, not recovered report text or approved mainnet parameters.
Checked-in issuance facts
- Target block interval
- 2.5 minutes
- Initial subsidy
- 12.5 Ravelnonce / 1,250,000,000 atoms
- Atomic-unit conversion
- 100,000,000 atoms per Ravelnonce
- Halving interval
- Every 840,000 mined blocks
Genesis is height 0 and has no subsidy. Valid mined blocks begin at height 1. Heights 1 through 840,000 receive the initial subsidy; each following era begins after exactly 840,000 mined blocks.
Subsidies are floored to whole atoms. The rule is subsidy_atoms(h) = floor(1,250,000,000 / 2^floor((h-1)/840,000)) for h ≥ 1. When the result reaches zero, no subsidy is created; there is no tail emission.
Preserved boundary vectors
| Mined block height | Subsidy (atoms) |
|---|---|
| 1 and 840,000 | 1,250,000,000 |
| 840,001 | 625,000,000 |
| 1,680,001 | 312,500,000 |
| 6,720,001 | 4,882,812 |
| 25,200,001 and 26,040,000 | 1 |
| 26,040,001 | 0 |
Flooring each era produces exactly 2,099,999,990,760,000 atoms (20,999,999.9076 Ravelnonce), below the 21,000,000 nominal limit. The unit tests retain these boundary values and the full scheduled sum.
Ravelnonce testnet implementation choice
Network identity and keys
- Chain ID:
ravelnonce-testnet-v1. Genesis is configured, not mined: version 1, height 0, zero parent, timestamp 0, zero merkle root, target2^240 - 1, nonce 0, and no reward. Its canonical header ID is5d84ae0b8fb1ce6a22d5c851726be21c2a9ead8acb466e725a591e8fa52c93ff. - One Ed25519 public key controls each output. The address is
rvtest1+ the 32-byte public key in lowercase hex + the first four bytes ofSHA256(UTF8(chainId + "/address") || publicKey)in lowercase hex. This yields 79 ASCII bytes and exposes common network or typing mistakes. - Private keys are generated locally. Browser key generation remains disabled. The CLI demo uses ephemeral keys and does not print or persist private material. There is no recovery phrase, derivation path, script or multisig support, or production compatibility claim.
Canonical bytes and identifiers
All fixed-width unsigned integers and length prefixes use big-endian byte order. UTF-8 is used for the chain ID; API atom amounts are canonical base-10 integer strings. Unknown JSON fields, unknown type/version values, non-canonical integer strings, and malformed lengths are rejected.
| Encoding | Byte layout, in order |
|---|---|
| Transaction, regular | u8 type=1 | u16 version | u8 chain length + UTF-8 chain ID | u16 input count | inputs | u16 output count | outputs |
| Regular input | 32-byte txid | u32 output index | 32-byte Ed25519 public key | 64-byte Ed25519 signature |
| Transaction, coinbase | u8 type=0 | u16 version | u8 chain length + UTF-8 chain ID | u64 height | u64 extra nonce | u16 output count | outputs |
| Output | u64 atom amount | 79 ASCII bytes: rvtest1 + 32-byte public key as lowercase hex + 4-byte checksum as lowercase hex |
| Block header | u16 version | u8 chain length + UTF-8 chain ID | u64 height | 32-byte parent ID | u64 timestamp | 32-byte target | 32-byte merkle root | u64 nonce |
- A regular transaction input signs
UTF8("Ravelnonce/v1/tx-signature\0") || chainIdLength || chainId || regular body with every signature omitted || u32(inputIndex). The signed body commits to all inputs and outputs; chain ID and input index prevent cross-network replay and signature reassignment. - Transaction IDs and block IDs are lowercase hex of SHA-256 applied twice to the canonical bytes. Merkle leaves are txid bytes in block order; internal nodes are SHA-256d of the two child hashes. An odd final child is duplicated at each level.
- These hashing choices are not implied by the source material. NIST FIPS 180-4 specifies SHA-256; Bitcoin Core's hash code is comparison material for double-SHA use. Neither chooses a Ravelnonce rule.
Transactions and spendable outputs
- Regular transactions must contain 1–100 inputs and 1–100 outputs, encode to at most 64 KiB, use this chain ID, and have distinct outpoints. Every input must reference a confirmed, unspent output and provide its controlling public key and valid Ed25519 signature.
- Amounts must be positive for regular outputs, in range, and add up using integer atoms. Outputs may not exceed inputs; the difference is the fee. There is no minimum consensus fee. Pending mempool inputs are reserved, so a competing spend returns HTTP 409. Unconfirmed-parent packages are not supported.
- Coinbase outputs mature at the next block: they cannot be spent in the same block that creates them. A block may contain up to 1,000 transactions and 1 MiB of canonical transaction/header bytes. Individual transaction JSON bodies are capped at 256 KiB; block JSON bodies are capped at 2 MiB.
For comparison only, see Bitcoin Core's transaction structures and validation code. They are not normative Ravelnonce sources.
Blocks, timestamps, and proof of work
- Exactly one coinbase appears first and names its block height. Its outputs may claim at most the scheduled subsidy plus validated transaction fees. Miners can claim less.
- A submitted block must extend the current tip at height + 1. Timestamps must be greater than the upper-middle median of the previous up-to-11 timestamps. There is no wall-clock future-time rule, so a single node cannot prevent future timestamp manipulation.
- The 32-byte target is big-endian and must match node calculation. The SHA-256d header hash is interpreted as a big-endian integer and must be less than or equal to target. The initial PoW limit is
2^240 - 1, about 65,536 trials on average. - The first 2,016 mined heights use the PoW limit. For candidate height
h > 1with(h-1) mod 2,016 = 0, span is tip timestamp minus the timestamp atmax(0, tipHeight - 2,016), clamped to 75,600–1,209,600 seconds. The next target ismin(powLimit, floor(previousTarget × span / 302,400)).
The interval and retarget are Ravelnonce testnet choices tied to the 150-second target spacing, not approved mainnet values. Bitcoin Core's proof-of-work code is comparison material for bounds and hash checks only.
Node scope and reproducibility
The implementation maintains one append-only canonical chain in PostgreSQL. Accepted transactions and blocks use serializable database transactions, including active-tip comparison and UTXO updates. Rejected submissions leave persisted chain, reservations, and spendable outputs unchanged. Stale, competing, and side-branch blocks are rejected; this node has no peer discovery, P2P transport, synchronization, fork choice, or reorganizations.
The rule-level vectors, including the external Ed25519 vector from RFC 8032, live in tests/unit/ravelnonce-consensus.test.ts. The RFC defines Ed25519 and supplies vectors; selecting it for this testnet is an implementation choice. The local CLI uses the key, signing, and verification APIs documented for Node.js 20.18.1 and newer.
Run the node against a disposable PostgreSQL database with the commands on the mining and node guide. The public API reference lists state, block templates, submissions, explorer reads, limits, and rejection responses.