Vesper · VESP · technical paper, draft 1

Vesper: a private-by-default ledger with provable ownership

October 2026 · draft 3 for review · describes phases 1 to 4 as built and measured (node v0.9.0, testnet-1); stage two of phase 3 as research

Abstract. Vesper is a proof-of-work cryptocurrency in which no transaction names its receiver or its amount, and in which the sender is hidden among a ring of 48 outputs today, three times Monero's ring, with membership among every output in the chain as the research target. On the network a payment travels node to node before any node broadcasts it, so the first announcer is a relay rather than the sender, and the remaining leak is measured and published rather than claimed away. Privacy is mandatory: there is no transparent transaction type. Each wallet holds a view key that can reveal that wallet's own history to a party of its choosing without revealing anyone else's, so the system is private by default and provable on demand. Development is funded by a protocol-enforced, publicly auditable share of the block reward that ends after a fixed number of blocks. This paper describes the ledger model, the cryptography of each phase, the consensus rules, and a threat model that states plainly what an observer can and cannot learn at each phase.

1The problem

A public blockchain is a permanent, searchable record of every payment ever made. On Bitcoin and Ethereum each transaction carries both addresses and the amount. One known address lets an analyst reconstruct a person's income, spending, counterparties and habits, and firms sell exactly that reconstruction to exchanges, governments and advertisers.

Two systems addressed this. Monero hides the receiver with stealth addresses, the amount with confidential transactions, and the sender by signing as one member of a ring of 16 possible spenders. Its weakness is the ring: 16 is a small anonymity set, decoy selection has been attacked statistically more than once, and the protocol is now replacing rings with full-chain membership proofs. Zcash hides all three with zero-knowledge proofs over a shielded pool, with the entire pool as the anonymity set. Its weakness was policy: shielded transactions were optional, most users chose transparent ones, and the shielded pool stayed small. Both leave the network layer, the IP address that first relays a transaction, to optional tooling.

2Design goals

  1. Mandatory privacy. Every transaction is private. There is nothing to opt into and nothing to leak by default.
  2. Hide receiver, amount, sender and network origin, in that order, each as a separately testable phase.
  3. Anonymity set equal to the chain for the sender, not a fixed-size ring.
  4. Provable on demand. A wallet can prove its own history to a chosen party without a trusted third party and without exposing any other wallet.
  5. Speed as a rule. Every phase publishes its cost in milliseconds; a payment that cannot be accepted by a node well under a second is not accepted as a design.
  6. Readable reference implementation. The protocol is defined by code a person can read in an afternoon, and every privacy claim is paired with a test that states what still leaks.
  7. Fair launch. No premine, no sale; development funded by a capped, public, protocol-enforced share of block rewards.

3Ledger model

Vesper has no accounts and no balances. The ledger state is the set of unspent outputs. An output is a one-time public key, its own ephemeral public key and a one-byte view tag that let the owner recognise it, a sealed anchor the owner checks it against, and a commitment to its amount with an encrypted copy of the value that only the owner's view key opens. A transfer creates new outputs and, for each input, proves ownership of one output among a ring of 48 without naming it, publishing a one-way spent marker (a key image, section 6.1) instead; a coinbase creates outputs from nothing according to the issuance rule in section 9. Nothing is ever removed: the ledger state is the set of all outputs plus the set of key images seen. A node knows that an output exists and whether a given marker has appeared, never which marker belongs to which output.

All arithmetic is on the Ed25519 group of prime order L, with generator G and a second, independently derived generator H whose discrete logarithm with respect to G is unknown. The reference implementation performs the group operations through libsodium.

4Phase 1: stealth addresses and view keys

A wallet holds two private scalars, the view key a and the spend key b (with B = b·G), and can hand out as many addresses as it likes. Address i is the pair (Di, Ci) with

Di = B + mi·G,   mi = Hs(a, i), m0 = 0       Ci = a·Di

so the main address (i = 0) has the same shape as every other, the addresses share no key, and nobody, not even several payers comparing notes, can tell that two of them belong to one wallet. To pay address i, a sender draws a random 16-byte anchor, derives a scalar r from it and the address, publishes R = r·Di with the output, seals the anchor into the output, and locks the output to the one-time key

P = Hs(r·Ci)·G + Di

where Hs hashes to a scalar. The receiver computes P − Hs(a·R)·G for each output and looks the result up among its own Di, which works because a·R = r·Ci: one multiplication per output however many addresses the wallet has, and a one-byte view tag lets it skip almost every output that is not its own after a single hash. Nobody without a or r can run that test. Before accepting an output the wallet re-derives R from the sealed anchor for the address the output landed on; an output built from one address's keys that lands on another is refused, which closes the "Janus" attack that Monero's subaddresses still carry. The owner spends by signing with the one-time private key

x = Hs(a·R) + b + mi

so a node confirms "the owner of this output authorised this spend" without learning who that is. Two payments to the same address produce unrelated one-time keys, every output has its own R, and no address ever appears on the chain. Change is paid to the sender's own wallet through the same mechanism, so change outputs are indistinguishable from payments. Addresses are 98 characters and start vesp2; a wallet is reconstructible from a 55-character recovery code shown once at creation.

The pair (a, B) is the view key: it derives every Di, runs the recognition test for all of them and, since phase 2, opens amounts, but it cannot produce x. Section 8 builds on this.

5Phase 2: hidden amounts

Each output's amount v is replaced on the chain by a Pedersen commitment

C = v·H + k·G

with a blinding scalar k known to the sender and recoverable by the receiver from the shared secret, alongside an encrypted copy of v that only the view key can open. Commitments are additively homomorphic, so a node checks that a transfer balances by checking that the sum of input commitments minus the sum of output commitments minus the fee commitment equals kexcess·G for some scalar the sender knows; the sender proves knowledge of that scalar with a Schnorr signature over the excess. No node ever sees v.

Homomorphic balance alone would allow a negative output that wraps around the group order and creates coins. Every output therefore comes with a range proof that its committed value lies in [0, 264). Vesper uses Bulletproofs, aggregated: one proof covers all of a payment's outputs (padded to a power of two with zero amounts that are never written down), 736 bytes for the usual two instead of 672 each, with no trusted setup. All the proofs in a block are verified as one combined equation, and a payment's proofs and signatures are checked once on arrival and never again. Every transfer has at least two outputs, shuffled, with a zero-valued change output created when there would otherwise be only one, so the number and order of outputs reveal nothing about the payment's structure. Inputs are listed in key-image order, a consensus rule, because wallets pick the largest coins first and the old order revealed which hidden input was bigger.

Coinbase outputs are the one exception: their amounts are public with a zero blinding factor, because the issuance rule must be checkable by everyone. This is the same choice Monero makes.

6Phase 3: hidden senders (stage one built, stage two research)

After phase 2 a transfer still named the outputs it spent, so an observer could draw the graph of outputs feeding outputs. Phase 3 removes that edge in three steps, in this order, so that each can be judged against the one before it. Steps A and B are built and tested; step C is not started.

6.1 Step A: key images (built)

Each output has a one-way spent marker, the key image I = x·Hp(txid:index, P), derived from the output's one-time private key and its position on the chain. Nodes keep the set of key images seen; spending the same output twice produces the same key image and is rejected, while the key image reveals nothing about which output produced it. Binding the marker to the position is a deliberate departure from Monero, where I = x·Hp(P): there, two payments to the same one-time key share one marker, so only one of them can ever be spent (the "burning bug"). In Vesper two outputs at the same key are two coins, each with its own marker; Zcash closed the same class of flaw ("Faerie Gold") the same way. This replaces "name the output you spend." It also lets a view-key holder be given the key images of specific outputs so they can see when those are spent (section 8).

6.2 Step B: ring signatures (built)

Each input is signed as one member of a ring of exactly 48 existing outputs, the real one plus 47 decoys, listed in sorted order so the position of the real one carries no information. The signature is a linkable ring signature of the CLSAG family over (one-time key, commitment) pairs: one challenge, 48 responses and one auxiliary point, 1,600 bytes with the key image and the pseudo-output commitment. The pseudo-output commitment per input keeps the balance equation of section 5 intact without revealing which ring member is real. Consensus rules added with this step: a ring must contain exactly 48 distinct existing outputs; key images and one-time keys must be canonical and pass prime-order checks; a repeated one-time key is allowed and is simply two coins (a uniqueness rule was tried and removed in review: it let a stranger cancel a waiting payment by getting a copy of its key mined first, and position-bound key images make it unnecessary); the ring size is hashed into the genesis block with every other rule; and an output, whether a mining reward or a payment, may be spent or used as a decoy only once it is 10 blocks old (consensus.output_lock_blocks), so a fresh chain needs about 58 blocks before its first payment. Wallets build a ring by fetching all 48 members from a node, their own coin among them, so the node cannot tell which member is real; if a reorganisation removes a decoy from a remembered ring, only that decoy is replaced. Decoys are drawn as ages from a measured spending distribution (the log of the age in seconds follows Gamma(19.28, 1.61), fitted to real Monero spends by Möser et al. 2018, the rule Monero's wallets use) and placed in the line of outputs with the chain's recent pace, a public number every wallet shares. Measured at a ring of 16 against an attacker who knows both the rule and the distribution, the real coin was named 7.2% of the time on a young chain and 6.1 to 6.5% on a busy one, where 6.2% is fair; the earlier rank-based rule leaked 7.3% to 22.1%. At the ring of 48 that testnet-1 runs, the same attacker names the real coin 2.09% of the time, where 2.08% is fair (3.0% at 32). The honest limit: those numbers assume Vesper's users spend like Monero's, and are to be re-measured on testnet-1. This is the Monero-equivalent stage with three times Monero's ring, and its known weakness is stated here and on every page: a ring is a small crowd. The ring size is one number in the consensus settings and is hashed into the genesis block; 48 was chosen for testnet-1 on 19 October 2026 (a node accepts a payment in 64 ms and a payment is 9.5 kB, against 45 ms and 5.1 kB at 16 and 54 ms and 7.3 kB at 32), and 64 was measured as well (82 ms, 11.7 kB, 1.8%) and judged not worth the extra cost until stage two's shape is known.

6.3 Step C: full-chain membership, a research milestone (not started)

The target is to replace the ring with a zero-knowledge proof that "I know the private key and opening of some unspent output in the set of all outputs," so the anonymity set is the whole chain and decoy selection ceases to exist as an attack surface. The key-image rule is unchanged. The proof system is not chosen. The candidates and their costs: curve-tree membership proofs, the direction Monero is moving in, which need no trusted setup but require additional curves and are the heaviest to implement; or a Merkle tree of outputs with a SNARK, where Groth16 needs a trusted setup per circuit and PLONK-family systems need only a universal one, and either changes the output format to SNARK-friendly commitments. Selection criteria, in order: verification time per input within the phase-2 budget, an implementation that can be audited, and the smallest trust assumption that satisfies the first two. No proof size, setup property or date is promised for this step until a candidate has been implemented and measured.

7Phase 4: network privacy (built, measured)

A perfect ledger still leaks at the door: the node that first relays a transaction is usually the sender's. In Vesper a wallet's payment is handed to its node and travels along a stem, one node to one other node, before any node broadcasts it, in the manner of Dandelion++, the design Monero has run since 2020. Each node keeps its role and two relays for 10-minute epochs, with a 10% chance per epoch of ending stems; each incoming peer is tied to one relay; a stem never goes straight back; a node's own payments always go on a stem, and only to peers the node chose itself, never to peers it merely heard about. Every stem node runs a timer (relays 30 s plus a random wait averaging 15 s, the sender 60 s plus) and broadcasts the payment itself if it has not come back as a broadcast by then, so a peer that swallows stems can delay a payment but cannot make one disappear. Every stem hand-off is answered at once and in the same words, before anything is checked; a payment the node already holds is dropped without a word; a stem that comes round in a circle ends by timer. Those three rules exist because the first build answered a repeated stem with "loop", which let anyone holding a payment ask every node and learn which nodes were on its stem: a trace-back of up to 38% of payments with 5% of nodes, found in review the day it was built, before any network ran it.

Measured, not claimed. leaktest.py runs the node's own routing code in a simulated network of 200 nodes and lets an attacker who controls some of them name, for each payment, the first node that handed it to one of the attacker's nodes:

Attacker's share of nodesGuess right, plain broadcastGuess right, stem then broadcast
5%15%7%
10%25%11%
20%39%23%
30%51%32%

That is what Dandelion++ promises: the guess is right about as often as the attacker's share of the nodes, and no better. The simulation does not model traffic watching, since nothing between nodes is encrypted, nor linking many payments from one sender within one epoch. In a very small network a payment can take 30 to 75 seconds to be broadcast.

Each node's own address. The stem hides which node broadcast first; it does not hide a node's internet address from the peers it talks to. python node.py --proxy socks5h://127.0.0.1:9050 sends every connection to a peer through Tor or another SOCKS5 proxy, name lookups included, with direct connections switched off; behind a proxy the node stops announcing its own address. Tor is not bundled: the Tor Browser (port 9150) or the Tor service (9050) provides it, and --host stays at 127.0.0.1 to remain hidden. The same flag on coin.py hides a wallet's address from the node it talks to.

Limits per peer. Requests are rate-limited per internet address and per kind; an address that sends blocks or payments that break the rules is ignored for an hour; at most 64 requests are served at once and 8 from any one address; a connection that goes silent is closed after 20 seconds; request bodies are capped at 8 MB, a peer's answer at 16 MB, a block at 4,000,000 bytes (a consensus rule) and the mempool at 32 MB. Addresses that peers pass around are only candidates: a node checks two a round, takes at most 8 new ones from any one peer's list, keeps at most 2 peers per network block, and never takes home-network addresses from gossip, so one party cannot fill a node's peer table and become the first hop of every payment. All of this has been exercised in simulation and on one computer, not against the open internet; the public test network is that test.

8Provable ownership: view keys and attestation

Privacy systems fail commercially when no one can prove anything to anyone. Vesper's answer is the view key, extended into an attestation: a wallet can produce, for a chosen party, a key or a bundle of per-output openings that reveals its own incoming outputs and amounts, and nothing about any other wallet, sender, or the rest of the chain. The holder of an attestation can verify it against the public chain without trusting the wallet's word. Use cases: an accountant preparing taxes, an exchange performing due diligence on a deposit, a court order limited to one party, an auditor of the development fund.

For a single payment there is a narrower instrument, the payment proof. The payer keeps each payment's secret r, encrypted beside the wallet, and proof pay publishes the shared point S = r·C with a Chaum–Pedersen proof that R = r·D and S share the same r; the receiver can produce the same kind of proof from its view key (proof receive), since S = a·R. Whoever holds the file runs proof check against their own node, redoes the receiver's recognition with S, and learns that one output of that payment paid one address a stated amount, and nothing else. The self-test tries six forgeries. Monero's transaction proofs serve the same purpose.

Attestations are produced off-chain and handed over privately. The protocol deliberately has no on-chain flag for "this payment is auditable," since any optional marker would make unmarked transactions a smaller crowd. The single exception is the development fund's income (section 9), which is public by construction.

A view key sees incoming outputs and their amounts. Spends are visible to a view-key holder only through key images: a view-key file exported by the wallet carries the key images of the outputs it held at export time, so the holder can see when those are spent; outputs that arrive later show as "spent status unknown" until the owner exports a fresh file. A view key therefore gives an exact balance as of its export and a lower bound after it. Wallets scan by reading only new blocks and keep an encrypted notebook of what they found beside the wallet file, re-reading the newest 20 blocks each time because those could still be reorganised; a re-check when nothing is new takes about 15 ms.

9Consensus, issuance and the development fund

Blocks are produced by proof of work using Argon2id over the block header, with 32 MiB of memory and one pass per attempt, both consensus parameters. Difficulty adjusts every block: the previous difficulty is multiplied by 2 raised to (target interval minus the last block's actual interval) divided by a 600-second half-life, the step form of ASERT, with any one block limited to doubling or quartering. In simulation against the previous 30-block average, average block time held at 30.0 s, difficulty wander fell from 18% to 13%, honest miners kept 90 to 99% of fair pay against a hit-and-run miner (85 to 95% before), and recovery from losing 99% of miners took 106 minutes instead of 279. The honest limit: if 90% of miners leave at once, blocks are slow for about 40 minutes; after a full day's outage difficulty falls to at most a quarter, so there is no flood of cheap blocks. The function is memory-hard by design: Bitcoin's mining hardware computes SHA-256 roughly a hundred million times faster than a laptop and cannot run Argon2id at all, which is what keeps a small chain from being overrun by rented hashrate on its first day. It is hostile to purpose-built chips, not to graphics cards, which retain an edge over CPUs; it is an interim choice, with RandomX the likely production algorithm, to be settled before any public network. A block's identifier is a plain hash of its header; the proof of work is a separate value, checked with a single Argon2id evaluation of about 11 ms. The miner runs on worker processes, half the cores by default (300 to 420 tries per second on eight), and every find is re-checked by the chain. A block holds at most 200 payments and 4,000,000 bytes, and miners fill blocks only up to that, so every valid block can be relayed. Nodes follow the chain with the most cumulative work. The complete consensus parameter set, proof-of-work parameters included, is hashed into the genesis block, so a node running different rules rejects the chain at height 0 rather than diverging later.

The block reward halves on a fixed schedule. For the first 4,204,800 blocks the reward is split 90% to the miner, at a private one-time key, and 10% to the development fund, at a one-time key whose derivation secret is published in the block. Any observer can recompute that key from the published secret and the fund's public address, verify the output exists with exactly the required amount, and sum the fund's income over the chain. A block that pays the fund less, more, or at any other key is invalid. Transaction fees are paid to the miner in full. The fund is a glass box in both directions: its outputs are never used as ring members by anyone, and the fund spends them by naming them openly with an ordinary signature, so its income and its spending are both public on chain while what it pays out to is a sealed output like any other. From block 4,204,801 the fund's share is zero and the rule cannot be re-enabled without a change of consensus rules adopted by node operators.

There is no premine and no sale. The genesis block contains no outputs. Mainnet block interval, initial reward, halving schedule and resulting supply are published with the genesis block and the audited code; values used by the test network are demonstration settings. Launch procedure, so that no miner can start early: the genesis message must contain data nobody could know in advance (for example the newest Bitcoin block identifier at the launch moment), the genesis timestamp is the launch moment, and the initial difficulty is set from the test network's measured hashrate rather than from a trivial value.

Testnet-1 (node v0.9.0) is the first network run by this procedure. launch_genesis.py writes a genesis message naming the newest Bitcoin block at the launch moment, after two independent block explorers agree on it, takes the launch time as the genesis timestamp, and sets the initial difficulty to 4,096 tries from measured test mining; the exact Bitcoin block and the resulting genesis block ID are in README.md and are printed by every node, and a node with a different genesis rejects the chain at height 0. Each network has its own ticker and address prefix: testnet-1 pays tVESP to addresses that start tvsp2, and those coins have no value, ever. A real network, if one follows, has its own genesis, ticker and addresses, so a test coin can never be mistaken for a real one.

Two block identifiers can never collide (the Merkle-tree duplication flaw of Bitcoin's CVE-2012-2459 is designed out), and a node records a block only under an identifier it computed itself after accepting the block, so a peer that has merely seen a block cannot delay the real one by sending junk under its identifier. A reorganisation costs the two branches involved, not the whole chain, and a branch offered by a peer is checked block by block as it downloads.

10Threat model

What each adversary can learn, by phase. "Yes" means the information is protected; "no" means it is visible; "phase n" means it becomes protected when that phase ships.

Adversary wants to learnPhase 1Phase 2Phase 3Phase 4 (today)
Who received a paymenthiddenhiddenhiddenhidden
Whether two payments went to the same personhiddenhiddenhiddenhidden
The amount of a paymentvisiblehiddenhiddenhidden
A wallet's balancederivablehiddenhiddenhidden
Which earlier output a payment spentvisiblevisibleone of 48one of 48
Who sent a payment (via the spend graph)inferableinferableone of 48one of 48
The sender's crowd is the whole chain, not 48 (decoy statistics no longer apply)nonono, stage two is researchno, stage two is research
The total of a payment that spends a mining reward (reward amounts are public, so the input sum is known; only the split is hidden)visiblevisiblehiddenhidden
That the sender's own earlier output has now been spent (the sender knows its opening forever)visible to that sendervisible to that senderhiddenhidden
Number of inputs and outputs, transaction size, and which outputs were created by the same paymentpublicpublicpublicpublic
The IP address that originated a paymentvisible to peersvisible to peersvisible to peersfirst broadcast is a relay's; an attacker with x% of nodes guesses right about x% of the time; Tor hides each node's address
Mining reward amountspublic by designpublic by designpublic by designpublic by design
Transaction fees (the same minimum for every wallet) and block timestamps; a payment carries no timestamp of its ownpublicpublicpublicpublic
The development fund's incomepublic by designpublic by designpublic by designpublic by design

10.1 Adversaries considered

10.2 Explicitly out of scope today

10.3 Cryptographic assumptions

Every construction rests on the hardness of the discrete logarithm problem in Ed25519's prime-order group, on SHA-512 behaving as a random oracle where it is used to turn interactive proofs into signatures (Fiat–Shamir), and on nobody knowing the discrete-log relation between G, H and the range-proof generators, which are derived by hashing. These are the same assumptions Monero makes. The system is not post-quantum: Pedersen commitments are perfectly hiding, so sealed amounts would stay sealed even against a quantum computer, but soundness would fall. Such an attacker could forge coins and could recover private view keys from published addresses, which would link every recorded one-time key to its address retroactively.

11Performance

Measured on an ordinary laptop with phases 1 to 4 active at testnet-1's ring size of 48 (values at 16 and 32 in brackets where they differ), Python with libsodium:

OperationCostWho pays it
Build a payment, including the range proof and ring signatureabout half a second at a ring of 48 on a PC that is also mining (204 ms at 16 on an idle PC)the sender, once
Node accepts a payment into the mempool64 ms (45 at 16, 54 at 32)every node, once (a lone joint range proof spans 128 bit positions, so a single payment costs more than the sum of its parts in a block)
Validate a block of 20 payments, fresh node33 ms per payment (15.1 at 16, 23 at 32)every node; range proofs batch-verified, ring signatures not
Restart a node on blocks it already checked0.035 ms per block, about 40 s for a year of 30-second blocksevery node, at start
Memorythe newest 1,000 blocks whole, older ones read back from disk; about 0.65 kB per output for the ledgerevery node
Mining on 8 cores (worker processes)300 to 420 tries per secondthe miner
Ring signature, per input26 ms to sign, 26 ms to verify at a ring of 48 (9 and 10 ms at 16, 18 and 17 at 32; the cost grows with the ring)sender / every node
Mine a block of already-seen payments (assembling, not the proof of work)4 msthe miner
Proof-of-work attempt (Argon2id, 32 MiB)10.9 ms, about 90 tries per second per corethe miner
Check a block's proof of work11 ms, one evaluationevery node, once per block
Scan one output with a view key0.11 ms for someone else's output, 0.7 ms for one of its ownthe wallet, per new output only
Wallet re-check when nothing is new15 msthe wallet, each time it opens
Switch branches (undo a block of 20 payments) on a 200,000-output ledger1.5 msevery node, on a reorganisation
Size of one paymentabout 4 kB binary (9.5 kB as JSON): 1,600 bytes ring signature with key image and pseudo-output, one 736-byte range proof for two outputs (2.2 kB and 5.1 kB at 16; 3.1 and 7.3 at 32)storage and bandwidth

Cost on a node per payment, by layer, at a ring of 16: about 4 ms with receivers hidden, 8.4 ms with amounts sealed, 18.6 ms with senders hidden, and 15.1 ms once a payment's range proofs became one proof; a ring of 32 takes it to 23 ms and the ring of 48 to 33 ms. Stage two of phase 3 is budgeted against the ring's 26 ms per input at 48: a membership proof whose verification is slower by more than an order of magnitude is rejected in favour of a cheaper system.

12Limitations and the road to genesis

This implementation is unaudited and is a reference, not a production node. The cryptographic constructions are standard and well studied; their implementation here is not. Privacy failures are silent: the chain functions while leaking. Nothing in this paper should be read as a claim that Vesper is untraceable today.

The reference node is Python. It demonstrates the protocol and is fast enough for a test network. A mainnet carrying value requires a hardened node with denial-of-service defences, bounded memory, and a reviewed network layer, built from this reference once the protocol is frozen.

Genesis is gated, in order, by: a public test network with a standing bounty for anyone who can trace a payment (testnet-1, launching with this publication); an independent cryptographic audit of the protocol and the reference implementation; the hardened node; and legal advice on the launch in the jurisdictions of the people running it. Stage two of phase 3 is desirable before genesis but is not a gate: a ring of 48 is three times the sender privacy Monero runs on today, and still a crowd of 48. No date is published for genesis because none of those steps has a fixed duration, and a date without them would be a promise the code cannot keep.

Still open, with reasons recorded in the project's decisions log: stage two membership proofs; an on-disk ledger (today about 0.65 kB per output in memory) and headers-first sync for faster new nodes; Bulletproofs+ for smaller proofs; encryption between peers and reachability as a Tor onion service; re-measuring decoy selection against Vesper's own spending once a network exists; and a longer lock on mining rewards than the single 10-block lock if mainnet wants one. A line-by-line re-read of the cryptography files in the second review pass found nothing new to fix, which is not an audit.

Everything claimed in sections 4, 5, 6.1, 6.2 and 7 is covered by the 44-check self-test suite that ships with the code, including a test named for what the chain still leaks, so that this paper and the implementation cannot drift apart without a test failing.