http://docker:8085Register a node as a validator with ML-DSA-65 keypair. Validator address derived from SHA-256 of public key.
ML-DSA-65 (FIPS 204)Validator signs each block with provider.sign(blockHash, privKey). Signature embedded in block header.
ML-DSA-65 (FIPS 204)Any node can verify the full chain by calling provider.verify() on every block signature + checking hash linkage.
ML-DSA-65 (FIPS 204)Peer connections authenticated with validator keys. Quantum-safe node-to-node communication.
ML-DSA-65 (FIPS 204)This service demonstrates quantum-safe blockchain validation — the same patterns you'll implement using the Qudo JNI provider in your validator/node software.
Validator identity: provider.generateKeyPair("ML-DSA-65") — validator address from public key hash
Block production: provider.sign(blockHash, validatorPrivKey, "ML-DSA-65") on each block
Chain verification: provider.verify() on every block signature — immutable quantum-safe audit trail
P2P security: Peer connections authenticated with validator keys
/api/blockchain/register-node
Register a validator node
/api/blockchain/add-block
Sign and add a new block to the chain
/api/blockchain/chain
Get the full blockchain
/api/blockchain/verify-chain
Verify signatures on every block
/api/blockchain/connect-peer
Connect to a P2P peer
/api/blockchain/peers
List connected peers
/api/blockchain/health
Service health + chain length
Migrate your PoS validator node to quantum-safe block signing. Use this playground to try PQC validator operations, then use the Qudo JNI provider in your node software.
Validator Node Network Peers
| |
| 1. provider.generateKeyPair("ML-DSA-65") |
| -> validator identity (address from SHA-256) |
| |
| 2. Build block {index, prevHash, data, timestamp} |
| blockHash = SHA-256(serialized block) |
| sig = provider.sign(blockHash, privKey, |
| "ML-DSA-65") |
| |
|---- block + signature + validator address ---------->|
| |
| 3. Each peer verifies: |
| provider.verify(blockHash, sig, valPubKey, |
| "ML-DSA-65") -> must be true |
| Check block.prevHash matches tip of chain
Each validator has an ML-DSA-65 keypair. Address = SHA-256(publicKey)[0:20], 0x-prefixed. Replaces ECDSA secp256k1 / Ed25519 in PoS chains.
Every peer independently verifies every block's signature with provider.verify(). Chain is quantum-safe as long as validator keys are ML-DSA.
Replace ECDSA/Ed25519 block signing with Qudo JNI calls. Consensus protocol (PoS, PoW, BFT) stays the same.
import com.qudo.crypto.QudoCrypto;
import com.qudo.crypto.QudoKeyPair;
QudoCrypto provider = QudoCrypto.create();
// ============================================================
// 1. Validator setup (once at startup, or during registration)
// ============================================================
QudoKeyPair validatorKeys = provider.generateKeyPair("ML-DSA-65");
byte[] addrHash = provider.sha256(validatorKeys.getPublicKeyPem());
StringBuilder sb = new StringBuilder("0x");
for (int i = 0; i < 20; i++) sb.append(String.format("%02x", addrHash[i]));
String validatorAddress = sb.toString();
// ============================================================
// 2. Sign a new block (during block production)
// ============================================================
String blockData = "{\"index\":42,\"prevHash\":\"0xabc...\",\"txs\":[...]}";
byte[] blockBytes = blockData.getBytes();
byte[] blockHash = provider.sha256(blockBytes);
byte[] blockSig = provider.sign(blockHash, validatorKeys.getPrivateKeyPem(), "ML-DSA-65");
// Broadcast: block + blockSig + validatorAddress + validatorKeys.getPublicKeyPem()
// ============================================================
// 3. Verify an incoming block (during chain validation)
// ============================================================
byte[] receivedHash = provider.sha256(receivedBlockBytes);
boolean valid = provider.verify(receivedHash, receivedSig,
senderValidatorPubKey, "ML-DSA-65");
if (!valid) rejectBlock();
// Also check: block.prevHash == localChain.tip.hash
provider.close();
| Operation | ML-DSA-65 | Ed25519 (classical) |
|---|---|---|
| Block sign | ~10ms | <1ms |
| Block verify (per peer) | ~5ms | <1ms |
| Signature size per block | 3,309 bytes | 64 bytes |
| Validator public key size | ~2,726 bytes (PEM) | 32 bytes |
Cause: Each block signature is 3.3KB vs 64 bytes. A chain with 10M blocks stores ~33GB of signatures (vs 640MB classical).
Mitigation: Use light clients that don't store full signatures; archive old blocks; use ML-DSA-44 if throughput matters more than Level 3 security.
Cause: If a validator's private key is compromised, historical blocks remain signed by that key.
Fix: Rotate validator keys on-chain (governance tx). Chain verifiers check validator pubkey was active at the block's height.
A: No. PoS/PoW/BFT logic is independent of the signature algorithm. Only sign() and verify() call sites change.
A: During migration, yes — use dual signatures (see dApp simulator) or run a separate PQC-only chain with a bridge. Long-term, all validators should migrate to ML-DSA.
Analyze any endpoint's cryptographic configuration. Enter a host:port to scan its TLS setup and identify what's quantum-safe vs what needs migration.