The auditor-side AML engine for Solana Token-2022 Confidential Transfers — how it runs, what it detects, the cryptography, and the API.
Confidential Transfers encrypt amounts on-chain with twisted-ElGamal + ZK proofs — exactly what regulated payments need, and exactly what blocks them, because a regulator can't see amounts. Solana ships the answer: a mint can carry a global auditor ElGamal key whose holder can decrypt every transfer amount for that mint. This skill is the tooling that operates that key: key setup → continuous decryption loop → AML engine → hashed reports. Privacy stays the default for everyone else, by cryptography, not policy.
The compliance loop is observe → decrypt → assess → report → repeat:
Termination is guaranteed by a BudgetLedger (caps + circuit breaker).
These are precisely the patterns confidential transfers hide from the public chain — so only the auditor key holder can detect them. Pure functions of (transfer, rolling state, config); every rule ships an offline test.
Real twisted-ElGamal over Ristretto255 (Solana's group), with a baby-step-giant-step discrete-log solver. The encrypt→decrypt round-trip is tested across the full 48-bit range, with semantic security and wrong-key-fails.
It decrypts real @solana/zk-sdk ciphertext: select convention: "solana" for Solana's exact scheme (amount·G = C − s·D) and layout: "lohi" for the production 16-bit-low + 32-bit-high split. Verified against bytes produced by the real Solana library — byte-identical to on-chain — using only this engine's crypto.
import {
ConfidentialComplianceLoop, ComplianceEngine, BudgetLedger,
defaultConfig, SplAuditorDecryptor,
} from "solana-confidential-compliance";
const loop = new ConfidentialComplianceLoop({
mint, auditorPubkey,
decryptor: new SplAuditorDecryptor({
auditorElGamalSecret, // from your HSM / TEE
layout: "lohi", convention: "solana", // real on-chain ciphertext
}),
engine: new ComplianceEngine(defaultConfig(6)),
budget: new BudgetLedger({ maxDurationMs: 8 * 3600_000, maxConsecutiveErrors: 5 }),
observe: fetchNewConfidentialTransfers, // RPC / Helius, oldest-first
onFlags: alertSink,
onReport: persistImmutable,
});
await loop.run();The skill is progressive — skill/SKILL.md routes to a module only when it's needed.