Coin Shuffling & Privacy Subsystem
The Shamwari Coin Shuffling & Privacy Subsystem (nxt.shuffling) provides a protocol-native, decentralized non-custodial coin mixing and account identity anonymization framework built directly into the core Shamwari ledger engine.
By executing coin shuffling directly within nxt.shuffling and managing automated client daemon participation via nxt.shuffling.Shuffler—rather than relying on centralized mixers, trusted intermediaries, or external virtual machine smart contracts—Shamwari achieves zero-counterparty risk, mathematically provable transaction unlinkability, post-quantum key transition, and robust blame management for malicious or non-responsive participants across BetaChains.
Core Capabilities & Architecture
- Protocol-Native Non-Custodial Anonymization: Shuffling transactions run natively inside the ledger core (
nxt.shuffling), eliminating central mixer fees, reentrancy vulnerabilities, and custodial theft risks. - Post-Quantum Recipient Key Decoupling: Integrates hybrid post-quantum keypairs (CRYSTALS-Kyber and CRYSTALS-Dilithium via
ShamwariQKP), outputting unlinked funds to fresh, un-published recipient public keys (recipientPublicKey). - Automated Shuffler Client Engine (
nxt.shuffling.Shuffler): Node-level daemon that automatically tracks shuffling state transitions, registers accounts, executes key exchanges/shuffles, verifies stage validity, and submits transaction attachments without manual user intervention. - Multi-Stage Mix State Machine: Operates across six distinct stages—
REGISTRATION,PROCESSING,VERIFICATION,BLAME,DONE, andCANCELLED—to guarantee participant consensus and early deterministic fault detection. - Strict Recipient Integrity Safeguards: Enforces strict checks requiring recipient accounts to be brand-new (unregistered on-chain) to prevent address re-use and cross-chain transaction graph analysis.
- Fault Tolerance & Resilient Re-Broadcasting: Includes a self-healing background retry engine (
failedTransaction) that re-broadcasts transiently rejected shuffling attachments during block application cycles.
Shuffling Lifecycle & Stage Architecture
A coin shuffling operation progresses through a deterministic, multi-stage state machine driven by ShufflingHome event triggers and processed automatically by active Shuffler daemons:
┌───────────────────────────────────────────────┐
│ Shuffling Created / Issuer │
└───────────────────────┬──────────────── ───────┘
│
▼
┌───────────────────────────────────────┐
│ REGISTRATION │
│ Participants join (submitRegister) │
└───────┬───────────────┬───────────────┘
│ │
Participant Quorum Met / │ │ Timeout / Cancellation
Full Registration │ │
▼ ▼
┌───────────────┐ ┌───────────────────────┐
│ PROCESSING │ │ CANCELLED │
│ Assignee Shift│ └───────────────────────┘
└───────┬───────┘
│
All Participants Shuffle │ Blame Triggered
& Pass Encrypted Inputs │ (Malicious/No-Show)
▼ ▼
┌───────────────┐ ┌───────────────────────┐
│ VERIFICATION │──────>│ BLAME │
└───────┬───────┘ └───────────────────────┘
│
All Signatures Validated │
▼
┌───────────────┐
│ DONE │
└───────────────┘
Shuffling Stage Descriptions
| Stage Enum | Functional Purpose | Automated Shuffler Action (Shuffler) |
|---|---|---|
REGISTRATION | Initial pooling phase where accounts join the shuffling instance. | Non-issuer participant daemons evaluate eligibility and invoke submitRegister(). |
PROCESSING | Sequential decryption and permutation phase assigned to participant sequence. | The assigned account (assigneeAccountId) shuffles key payloads and submits submitProcess(). |
VERIFICATION | Output verification where participants validate final target recipient addresses. | Every participant daemon verifies output hashes via verify() and signs the final state. |
BLAME | Fault identification protocol triggered upon non-compliance or bad data. | Participants isolate failing keys, initiate cancel(), and attribute blame to offending accounts. |
DONE | Successful completion; funds distributed to recipient accounts. | Schedules cleanup expiration (SHUFFLER_EXPIRATION_DELAY_BLOCKS) and stops daemon. |
CANCELLED | Aborted shuffling sequence; locked funds unlocked and returned to participants. | Schedules cleanup expiration (SHUFFLER_EXPIRATION_DELAY_BLOCKS) and releases resources. |
Automated Shuffler Execution Engine (nxt.shuffling.Shuffler)
The Shuffler class acts as an automated background agent running on node instances. Once initiated by an account owner, it monitors the ledger for relevant shuffling events and constructs the required cryptographic proofs and transaction attachments.
1. Shuffler Instance Parameters
| Parameter | Type | Operational Role |
|---|---|---|
betaChain | BetaChain | Target BetaChain context hosting the active shuffling pool. |
accountId | long | 64-bit account identifier of the participant. |
shamwariQKP | ShamwariQKP | Hybrid post-quantum keypair supplying signing and key-encapsulation functions. |
recipientPublicKey | ShamwariPublicKey | Fresh, previously unused public key where shuffled funds will be delivered. |
shufflingFullHash | byte[] | 32-byte cryptographic hash uniquely identifying the targeted shuffling instance. |
feeRateQNTPerFXT | long | Dynamic transaction fee rate allocated for automated attachment submissions. |
failedTransaction | Transaction | Transient transaction reference held for automatic re-broadcasting upon failure. |
Operational Safeguards & Exception Hierarchy
To preserve network efficiency, protect privacy guarantees, and defend against denial-of-service (DoS) attacks, Shuffler.addOrGetShuffler() enforces strict operational guards prior to instantiation:
┌───────────────────────────────────┐
│ Shuffler Add Request Received │
└─────────────────┬─────────────────┘
│
▼
┌───────────────────────────────────┐
│ Node Shuffler Capacity Check │
│ (Count <= MAX_SHUFFLERS Limit) │
└─────────────────┬─────────────────┘
│
▼
┌───────────────────────────────────┐
│ Fresh Recipient Verification │
│ (Account.getAccount(key) == null)│
└─────────────────┬─────────────────┘
│
▼
┌───────────────────────────────────┐
│ Account Control Policy Check │
│ (!contains(PHASING_ONLY) Control)│
└─────────────────┬─────────────────┘
│
▼
┌───────────────────────────────────┐
│ Shuffler Daemon Activated │
└───────────────────────────────────┘
Key Security Safeguards
-
Node Shuffler Cap (
ShufflerLimitException): Prevents a single node from exceeding resource thresholds. The aggregate active shufflers across all mappings cannot exceedMAX_SHUFFLERS: -
Fresh Recipient Account Rule (
InvalidRecipientException): To prevent linkability and graph analysis, the outputrecipientPublicKeymust not belong to an existing on-chain account: If an account with history or balance already exists forrecipientPublicKey, initialization fails immediately. -
Recipient Uniqueness Guard (
InvalidRecipientException): No two active shuffler daemons running on the node may share the same recipient account identifier: -
Phasing Control Restriction (
ControlledAccountException): Accounts subject to mandatory transaction phasing control (Account.ControlType.PHASING_ONLY) are prohibited from running automated shuffler daemons, as their outgoing attachments require deferred multi-signature approvals incompatible with real-time shuffling rounds.
Mathematical Mechanics & Expiration Logic
1. Participant Quorum Bounds
A shuffling instance operates with a bounded number of participants (), defined between network protocol limits and the specific shuffling parameter:
2. Expiration Delay Calculation
When a shuffling sequence reaches a terminal state (DONE or CANCELLED), the background daemon schedules automatic memory cleanup and listener unregistration at a target block height ():
The block application listener (AFTER_BLOCK_APPLY) evaluates expiration sets at every block:
Upon expiration, the internal shufflingsMap removes the registered hash, emitting Event.SHUFFLER_STOPPED.
Lifecycle Event Matrix & Listener Architecture
Shuffler registers listeners on ShufflingHome and BlockchainProcessor to automate state transitions:
| System Submodule | Listened Event | Internal Operational Handler |
|---|---|---|
ShufflingHome | SHUFFLING_CREATED | Evaluates new shuffling instance; non-issuer accounts submit registration (submitRegister). |
ShufflingHome | SHUFFLING_PROCESSING_ASSIGNED | Detects when the local account is chosen as assigneeAccountId; executes vector permutation (submitProcess). |
ShufflingHome | SHUFFLING_PROCESSING_FINISHED | Triggers output verification across all participants (verify). |
ShufflingHome | SHUFFLING_BLAME_STARTED | Initiates fault localization sequence (cancel) to expose non-compliant nodes. |
ShufflingHome | SHUFFLING_DONE | Schedules expiration block cleanup via scheduleExpiration(). |
ShufflingHome | SHUFFLING_CANCELLED | Schedules expiration block cleanup via scheduleExpiration(). |
BlockchainProcessor | AFTER_BLOCK_APPLY | Purges expired shufflers matching the current block height. |
BlockchainProcessor | AFTER_BLOCK_ACCEPT | Attempts automatic re-broadcasting of cached failedTransaction instances. |
BlockchainProcessor | RESCAN_BEGIN | Immediately stops all running shuffler daemons (stopAllShufflers) to protect state consistency during chain rescans. |
Resilience & Failed Transaction Engine
In peer-to-peer network environments, temporary validation errors or unconfirmed memory pool congestion can cause transaction broadcast rejections. Shuffler implements a self-healing retry mechanism:
// Logic from Shuffler static initializer
BlockchainProcessorImpl.getInstance().addListener(block ->
shufflingsMap.values().forEach(shufflerMap ->
shufflerMap.values().forEach(shuffler -> {
if (shuffler.failedTransaction != null) {
try {
TransactionProcessorImpl.getInstance().broadcast(shuffler.failedTransaction);
shuffler.failedTransaction = null;
shuffler.failureCause = null;
} catch (NxtException.ValidationException ignore) {
// Retry deferred to next block confirmation cycle
}
}
})
), BlockchainProcessor.Event.AFTER_BLOCK_ACCEPT
);
When an automated submission fails, the failedTransaction and failureCause references are retained. At each accepted block (AFTER_BLOCK_ACCEPT), the node automatically re-attempts broadcasting, ensuring participant daemons do not stall active shuffling pools due to transient network drops.
Related APIs
| API | Description |
|---|---|
| ShufflingCreate | Create shuffle |
| ShufflingRegister | Register for shuffle |
| ShufflingProcess | Process shuffle |
| ShufflingVerify | Verify shuffle |
| ShufflingCancel | Cancel shuffle |
| GetShuffling | Get shuffle info |
| GetShufflingParticipants | Get participants |
| GetAllShufflings | List all shuffles |
| GetAccountShufflings | Get account shuffles |
| GetAssignedShufflings | Get assigned shuffles |
| GetHoldingShufflings | Get holding shuffles |
| StartShuffler | Start shuffler daemon |
| StopShuffler | Stop shuffler daemon |
Primary Institutional & Commercial Use Cases
- Post-Quantum Account Anonymization: Users move funds from legacy or public addresses into fresh post-quantum keypairs without leaving a traceable transaction graph on-chain.
- Enterprise Treasury Privacy: Financial institutions shuffle internal operational funds before disbursing payroll or vendor payments, masking commercial liquidities from public inspection.
- Merchant Payment Privacy: Point-of-sale vendors receive shuffled settlement outputs, preventing third-party observers from tracking daily sales volumes or customer payment histories.
- Cross-Chain Liquidity Anonymization: Integrates with monetary system currencies (
CURRENCY) and custom assets (TOTEM), allowing users to break ownership links prior to executing cross-chain atomic swaps.