RIP-25: Post-Quantum Signatures via ML-DSA-44 (Witness v2)#1281
Open
ALENOC wants to merge 12 commits intoRavenProject:masterfrom
Open
RIP-25: Post-Quantum Signatures via ML-DSA-44 (Witness v2)#1281ALENOC wants to merge 12 commits intoRavenProject:masterfrom
ALENOC wants to merge 12 commits intoRavenProject:masterfrom
Conversation
Proof-of-concept implementation for RIP-25: Post-Quantum Hybrid Signatures via ML-DSA-44 (FIPS 204). New files: - doc/RIP-0025-PQ-Hybrid-Signatures.md: Full RIP specification - src/crypto/mldsa.h/cpp: ML-DSA-44 wrapper (PoC simulation, production will use liboqs) - src/pqkey.h/cpp: CHybridKey and CHybridPubKey classes implementing AND-composition hybrid ECDSA+ML-DSA-44 signatures - src/test/pqkey_tests.cpp: 20 unit tests covering keygen, sign/verify roundtrip, wrong key/message/signature rejection, partial signature rejection, serialization, and determinism See: RavenProject#1280
…s rules Implements the complete RIP-25 specification across the Ravencoin codebase: - Consensus: BIP9 deployment (bit 11, 85% threshold) for mainnet/testnet/regtest, phased block weight increase (8→12→16 MWU), PQ witness discount (8x) - Script: Witness v2 validation in VerifyWitnessProgram with AND-composition (both ECDSA + ML-DSA-44 must verify), new SIGVERSION_WITNESS_V2_PQ - Policy: TX_WITNESS_V2_PQ_KEYHASH standard type, witness v2 standardness checks, PQ-aware dust threshold calculation - Network: NODE_PQ_HYBRID service flag (bit 5), increased protocol message size limit (16MB) for PQ witness data - Signing: Witness v2 signing framework in sign.cpp with hybrid key support - Build: Added mldsa.cpp/h to crypto library, pqkey.cpp to common library, pqkey_tests.cpp to test suite
Add overview section explaining the post-quantum hybrid signature implementation, key changes across consensus/script/policy/network layers, current PoC status, and link to full RIP specification.
Replace the HMAC-SHA512 proof-of-concept simulation in mldsa.cpp with real ML-DSA-44 (FIPS 204) calls via liboqs (Open Quantum Safe). Changes: - src/crypto/mldsa.cpp: Now uses OQS_SIG_ml_dsa_44 for keygen, sign, and verify. Includes compile-time static_asserts to ensure size constants match liboqs. Supports deterministic keygen from seed via OQS_SIG_ml_dsa_44_generate_keypair_from_seed when available. - src/crypto/mldsa.h: Updated documentation, removed PoC references. - configure.ac: Added --with-liboqs flag, PKG_CHECK_MODULES for liboqs with fallback to AC_CHECK_LIB/AC_CHECK_HEADER. - src/Makefile.am: Added LIBOQS_CFLAGS/LIBOQS_LIBS to crypto library and all binary link lines (ravend, raven-cli, raven-tx). - src/Makefile.test.include: Added LIBOQS_LIBS to test linker. - depends/packages/liboqs.mk: New depends package for cross-compilation. - depends/packages/packages.mk: Added liboqs to default packages. - README.md: Updated status to complete, added build instructions.
Witness v2 now uses ML-DSA-44 exclusively instead of requiring both ECDSA + ML-DSA-44. Old ECDSA addresses (witness v0) continue working unchanged. Users gradually migrate funds to quantum-resistant addresses. Key changes: - pqkey.h/cpp: Replace CHybridKey/CHybridPubKey with CPQKey/CPQPubKey - interpreter.cpp: 2-element witness stack [mldsa_sig, mldsa_pk] - script_error.h/cpp: PQ-specific error codes - bech32.h/cpp: New Bech32m encoding for witness v2 addresses (BIP350) - standard.h/cpp: WitnessV2PQDestination type, GetScriptForWitnessV2PQ - base58.cpp: EncodeDestination/DecodeDestination with bech32m support - chainparams: Bech32m HRP (rvn/trvn/rcrt) for PQ addresses - keystore.h: PQ key maps (PQKeyMap, PQPubKeyMap) in CBasicKeyStore - sign.h/cpp: ML-DSA signing via TransactionSignatureCreator - ismine.cpp: IsMine support for TX_WITNESS_V2_PQ_KEYHASH - policy.cpp: Update IsWitnessStandard for 2-element PQ stack - rpcwallet.cpp: Add getnewpqaddress RPC command - init.cpp: Advertise NODE_PQ_HYBRID service flag - Tests rewritten for ML-DSA-44 only design - RIP document and README updated
- Wallet DB: WritePQKey/WriteCryptedPQKey for persistent PQ key storage, ReadKeyValue handlers for "pqkey"/"cpqkey", IsKeyType updated - Encryption: CCryptoKeyStore PQ key encryption/decryption via mapCryptedPQKeys, AddCryptedPQKey, EncryptKeys handles PQ keys, Unlock verifies PQ keys for PQ-only wallets - Wallet: CWallet::AddPQKeyPubKey persists to disk, AddCryptedPQKey persists encrypted keys, LoadPQKey/LoadCryptedPQKey for DB loading - Sigops: WitnessSigOps returns 1 for witness v2 (32-byte program)
…gops files Sync section 6.3 to reflect all 45 modified files including wallet DB persistence (walletdb.h/cpp), wallet encryption (crypter.h/cpp), wallet integration (wallet.h/cpp), interpreter.h, versionbits.cpp, packages.mk, and Makefile.test.include.
Fix compilation errors: CAffectedKeysVisitor, Witnessifier, DescribeAddressVisitor, TestAddrTypeVisitor, and TestPayloadVisitor all need an operator() for the new WitnessV2PQDestination variant type.
- mldsa.cpp: Use liboqs internal keypair_internal() for deterministic keygen from seed via weak symbol linkage (FIPS 204 Section 6.1). All 20 PQ unit tests now pass. - init.cpp: Fix boost 1.83 signal disconnect incompatibility with function pointer (use connection object instead). - lockedpool.cpp: Add missing <stdexcept> include for gcc 13. - cuckoocache_tests.cpp: Add missing <deque> include for gcc 13.
SignatureHash must use SIGVERSION_WITNESS_V2_PQ (not SIGVERSION_WITNESS_V0) in both signing (sign.cpp) and verification (interpreter.cpp) paths. Also route SIGVERSION_WITNESS_V2_PQ through the BIP143-style sighash computation (same branch as witness v0). Verified end-to-end on regtest: ECDSA→PQ and PQ→ECDSA transactions both confirm successfully with ML-DSA-44 signatures.
Two fixes for PQ transactions being rejected with "min relay fee not met": 1. GetTransactionWeight (consensus/validation.h): Apply PQ_WITNESS_SCALE_FACTOR (8x) discount to ML-DSA-44 witness data. Standard segwit witness counts at 1 WU/byte; PQ witness v2 now counts at 0.5 WU/byte, halving the effective virtual size of PQ witness data (~588 vs ~1035 vbytes for a typical PQ tx). 2. DummySignTx (wallet/wallet.h): ProduceSignature fails for PQ inputs during dummy signing because VerifyScript cannot verify all-zeros ML-DSA data. The wallet fell back to a 256-byte scriptSig with no witness, severely underestimating PQ transaction size. Now detects witness v2 PQ outputs and inserts correctly-sized dummy witness (2420B sig + 1312B pk). Tested on regtest: ECDSA→PQ, PQ→ECDSA, PQ→PQ all relay and confirm with default fee settings (no manual settxfee required).
Update section 4.1 with weight calculation formula, effective virtual size table, and wallet fee estimation (DummySignTx) details. Add consensus/validation.h to the file table in section 6.3.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements RIP-25: post-quantum transaction signing for Ravencoin using ML-DSA-44 (NIST FIPS 204) via a new witness version 2 soft fork.
Changes (49 files, ~2200 lines)
crypto/mldsa.h/cpp— ML-DSA-44 wrapper around liboqs (FIPS 204), deterministic keygen from seedpqkey.h/cpp—CPQKey/CPQPubKeyclasses (1312B pubkey, 2560B privkey, 2420B signature)SIGVERSION_WITNESS_V2_PQ,WitnessSigOpsfor v2PQ_WITNESS_SCALE_FACTOR=8getnewpqaddressRPC, full PQ key persistence (WritePQKey/WriteCryptedPQKey), encryption support (mapCryptedPQKeys,EncryptKeys/Unlockfor PQ), PQ-aware fee estimationrvn1z...(mainnet),trvn1z...(testnet),rcrt1z...(regtest)TX_WITNESS_V2_PQ_KEYHASHstandard type, PQ-aware dust threshold, PQ weight discount (8x),IsWitnessStandard2-element checkNODE_PQ_HYBRIDservice flag (bit 5), 16 MB protocol message limitconfigure.ac --with-liboqs,depends/packages/liboqs.mk)test/pqkey_tests.cpp— all passingBuild & test
Regtest verification
Full regtest test suite — all scenarios passing:
ispqaddress:true,witness_version:2,spendable:trueFull specification:
doc/RIP-0025-PQ-Signatures.mdTest plan
pqkey_tests)ispqaddress,witness_version,witness_programspendable: true