Who’s willing to help make this happen?
This builds on the blog post from 2 days ago. That could be HF13:
https://nerva.one/nerva-changes-with-ai-agent/
No actual code for potential HF14 and HF15 yet. Just a plan for now.
Conversation with AI agent:
Can you look at the privacy setting that Nerva currently offers and compare it to Monero?
Let me explore the codebase to understand Nerva’s privacy implementation.
Agent: Nerva vs Monero privacy feature analysis
Analyze the Nerva cryptocurrency codebase at d:\Code\Crypto\Nerva\nerva for privacy features. I need a thorough comparison vs Monero. Specifically look for:
- 1. RingCT implementation — what ring size is used? Where is it configured? (look in cryptonote_config.h, src/ringct/, any MIN_MIXIN or ring size constants)
- 2. Stealth addresses — is one-time address generation present? (src/crypto/crypto.cpp, crypto.h)
- 3. Bulletproofs — are range proofs present and what version? (src/ringct/rctTypes.h, rctSigs.cpp)
- 4. Dandelion++ — is tx propagation privacy present? (search for “dandelion” in src/)
- 5. View keys / spend keys — standard dual-key model? (src/crypto/)
- 6. Any Nerva-specific privacy changes vs vanilla Monero (search for “NERVA” or “XNV” comments near privacy code)
- 7. Transaction output structure — MLSAG vs CLSAG? (src/ringct/)
- 8. Any removed or disabled privacy features compared to Monero baseline
Search thoroughly — check config files, ringct/, crypto/, cryptonote_core/, p2p/ directories. Report what’s present, what’s absent, and any relevant constants/line numbers.
Nerva vs Monero Privacy Comparison
What Nerva Has (Same as Monero)
| Feature | Nerva | Monero (current) | Notes |
|---|---|---|---|
| Stealth addresses | Yes | Yes | Identical implementation |
| RingCT | Yes | Yes | All non-coinbase txs mandatory |
| Range proofs | Bulletproofs v1 & v2 | Bulletproofs+ | Nerva lacks the optimized v3 |
| Dandelion++ | Yes | Yes | Same network-layer tx privacy |
| View keys / spend keys | Yes | Yes | Dual-key model, watch-only wallets |
| Subaddresses | Yes | Yes | |
| Payment ID encryption | Yes | Yes |
Key Gaps vs Current Monero
1. Ring size: 5 vs 16
Nerva’s DEFAULT_MIXIN = 4 gives ring size 5. Monero upgraded to ring size 16 in 2022. A larger ring makes statistical decoy analysis harder — with ring size 5, tracing heuristics are significantly more effective.
2. MLSAG instead of CLSAG
Nerva still uses the older MLSAG signature scheme. Monero migrated to CLSAG (Concise Linkable Spontaneous Anonymous Group) in October 2020. CLSAG reduces tx size by ~25% and is considered more efficient, but both provide the same theoretical privacy guarantee.
3. Bulletproofs v2 instead of Bulletproofs+
Monero upgraded to Bulletproofs+ in August 2022, which are ~5–7% faster to verify and ~6% smaller. Nerva is on the older v2.
4. No Triptych / Seraphis roadmap features
Monero is working toward Seraphis/Jamtis which would further increase ring sizes and improve privacy. Nerva has no equivalent research effort.
Bottom Line
Nerva’s privacy model is solid but dated — roughly equivalent to Monero circa 2020. The stealth address + RingCT + Dandelion++ foundation is sound. The practical weaknesses are the small ring size (5) and MLSAG vs CLSAG. These are the highest-leverage improvements if you wanted to close the gap with Monero’s current privacy posture.
What changes would you make to update/improve Nerva’s privacy?
Three changes, ranked by impact:
1. Ring size 5 → 16 (highest priority)
This is the single biggest practical privacy improvement. Small rings are vulnerable to EAE (Eve-Alice-Eve) tracing and chain-reaction deanonymization. Monero’s analysis showed ring size 11+ breaks most known heuristics; they settled on 16. The cost is ~3x larger ring signature data per tx, which increases blockchain growth rate and sync time — already a concern for Nerva given the post-930k slowdown.
2. MLSAG → CLSAG
Well-proven migration — Monero did it in October 2020, the code is battle-tested. You’d get ~25% smaller ring signatures and faster verification. This partially offsets the size increase from a larger ring. The implementation effort is moderate: the Monero CLSAG code could be backported directly since Nerva is a fork.
3. Bulletproofs+ (replacing v2)
Smallest gain of the three — roughly 6% smaller range proofs, 5–7% faster verification. Worth doing if you’re already touching the ringct layer for CLSAG, since it’s a contained change with no protocol-level downside.
The natural order would be: CLSAG + Bulletproofs+ together (they touch the same layer), then ring size increase as a separate hardfork since it has the largest chain-size impact and needs its own performance analysis against Nerva’s already-slow sync.
Want me to sketch out what the implementation would look like, or discuss the sync impact first?
Sketch out the implementation.
Good — CLSAG doesn’t exist in this codebase at all, which means it’s a full backport, not a modification. Here’s the complete implementation sketch:
Implementation Plan: 3 Privacy Upgrades
Overview
These are delivered as two sequential hardforks to keep each change isolated and auditable:
- HF14 — CLSAG + Bulletproofs+
- HF15 — Ring size 16 (separate fork because it has chain-size implications that deserve independent community discussion)
Change 1: CLSAG (replaces MLSAG for new transactions)
CLSAG doesn’t exist here. The full implementation lives in Monero’s src/ringct/clsag.h and clsag.cpp as of their October 2020 hardfork. This is a direct file copy + wiring job.
New files to add:
src/ringct/clsag.hsrc/ringct/clsag.cpp
The Monero implementation exports four functions — these are exactly what you’d copy:
// clsag.hnamespace rct {clsag proveRctCLSAGSimple(const key &message, const ctkeyV &pubs,const ctkey &inSk, const key &a,const key &Cout, const keyV *mscout,const keyV *mspk, const multisig_kLRki *kLRki,key *mscout_key, unsigned int index,hw::device &hwdev);bool verRctCLSAGSimple(const key &message, const clsag &sig,const ctkeyV &pubs, const key &C_offset);}
src/ringct/rctTypes.h changes:
Add the new RCT type (after line 236) and the clsag struct:
// After RCTTypeBulletproof2 = 5RCTTypeCLSAG = 6, // HF14: CLSAG + Bulletproofs+
Add the clsag struct alongside mgSig:
struct clsag {keyV s; // scalarskey c1; // initial challengekey I; // key imagekey D; // auxiliary key image};
Update serialize_rctsig_base to accept RCTTypeCLSAG in the type validation check (line 259-261).
src/ringct/rctSigs.h changes:
Add the clsag struct serialization and wire proveRctCLSAGSimple / verRctCLSAGSimple into the existing genRctSimple / verRctNonSemanticsSimple dispatch:
// In genRctSimple — add CLSAG branchif (rct_config.clsag) {rv.p.CLSAGs.push_back(proveRctCLSAGSimple(...));} else {rv.p.MGs.push_back(MLSAG_Gen(...));}// In verRctNonSemanticsSimple — add CLSAG branchif (rv.type == RCTTypeCLSAG) {return verRctCLSAGSimple(message, rv.p.CLSAGs[i], rv.mixRing[i], ...);}
src/ringct/CMakeLists.txt: Add clsag.cpp to sources.
Change 2: Bulletproofs+ (replaces Bulletproofs v2 range proofs)
Same story — backport from Monero’s bulletproofs_plus.h / bulletproofs_plus.cc (added August 2022).
New files:
src/ringct/bulletproofs_plus.hsrc/ringct/bulletproofs_plus.cc
The interface mirrors existing bulletproofs:
// bulletproofs_plus.hnamespace rct {BulletproofPlus bulletproof_plus_PROVE(const std::vector<uint64_t> &v,const rct::keyV &gamma);bool bulletproof_plus_VERIFY(const std::vector<const BulletproofPlus*> &proofs);}
src/ringct/rctTypes.h: Add the BulletproofPlus struct (structurally similar to Bulletproof but with different field counts — copy exactly from Monero).
src/ringct/rctSigs.cpp: In genRctSimple, wire the range proof type selection:
if (rct_config.range_proof_type == RangeProofPaddedBulletproofPlus) {rv.p.bulletproofs_plus = bulletproof_plus_PROVE(outamounts, outSk_masks);} else {// existing bulletproof v2 path}
In verRctSemanticsSimple, add the corresponding verify dispatch.
src/cryptonote_config.h: Add the activation height:
#define CLSAG_BULLETPROOFPLUS_FORK_HEIGHT <HF14_height>Change 3: Ring size 16
This is the simplest code change but has the largest chain impact.
// Keep old values for historical validation#define DEFAULT_MIXIN 4 // pre-HF15#define DEFAULT_RINGSIZE DEFAULT_MIXIN + 1// HF15 values#define DEFAULT_MIXIN_HF15 15#define DEFAULT_RINGSIZE_HF15 DEFAULT_MIXIN_HF15 + 1#define RING_SIZE_FORK_HEIGHT <HF15_height>
src/wallet/wallet2.cpp — the two DEFAULT_MIXIN + 1 histogram calls at lines 9992/9998 need to become height-aware:
const uint64_t min_ring = height >= RING_SIZE_FORK_HEIGHT? DEFAULT_MIXIN_HF15 + 1 : DEFAULT_MIXIN + 1;return select_available_outputs_from_histogram(min_ring, ...);
src/wallet/wallet_rpc_server.cpp — the 5 DEFAULT_MIXIN calls at lines 956, 1008, 1426, 1480 need the same height-aware mixin value passed in.
src/cryptonote_core/blockchain.cpp — check_tx_inputs needs a minimum ring size enforcement gate at HF15:
if (hf_version >= HF15_VERSION) {if (key_offsets.size() < DEFAULT_RINGSIZE_HF15) {MERROR_VER("Ring size too small for HF15: " << key_offsets.size());return false;}}
Hardfork table additions in src/cryptonote_config.h
// existing: {13, 1100000} -- CryptoNight-NX{14, <height>}, // CLSAG + Bulletproofs+{15, <height>}, // Ring size 16
Effort estimate
| Change | Complexity | Notes |
|---|---|---|
| CLSAG | High | ~700 lines of crypto code to backport; must match Monero’s exact hash domain separation or verification breaks |
| Bulletproofs+ | Medium-High | ~1200 lines; the inner product argument changes significantly from v2 |
| Ring size 16 | Low | Config + 6 call sites; chain-size modeling needed before picking activation height |
The natural order is to do CLSAG and Bulletproofs+ together as one PR (they activate at the same hardfork and both touch rctSigs), then ring size as a follow-on.
Want me to implement this?
Yesterday, you did CryptoNight-NX algo change to make Nerva’s algo more ASIC/GPU resistant. Where would you put that in the hard forks?
It’s already slotted as HF13 from the previous session — the hardfork table in src/cryptonote_config.h has {13, 1100000} as a placeholder.
The full sequence would be:
| HF | Change | Height |
|---|---|---|
| HF12 | Last existing Nerva fork | ~930,000 |
| HF13 | CryptoNight-NX (ASIC/GPU resistance) | 1,100,000 (placeholder) |
| HF14 | CLSAG + Bulletproofs+ (privacy upgrade) | TBD |
| HF15 | Ring size 16 (anonymity set) | TBD |
The ordering makes sense for two reasons: mining algorithm changes should stabilize before touching the transaction signing layer, and CLSAG needs to be live before increasing ring size so the larger rings don’t make tx size even worse with MLSAG.
The 1,100,000 height for HF13 is still a placeholder — you’d want to confirm what the current chain height is and give the community enough lead time (typically 2-4 weeks) before setting it in stone.












