The Mathematics of Private Notes
A deep dive into Xythum's cryptographic note structure — the shielded UTXOs that power private trading on public blockchains.
The Mathematics of Private Notes
At the heart of every privacy-preserving protocol lies a fundamental challenge: how do you prove ownership and validity of assets without revealing what those assets are? In Xythum, the answer is the Note — our shielded UTXO primitive.
What is a Note?
A Note is the basic unit of value in Xythum's dark pool. It represents ownership of an asset amount but remains encrypted on-chain, revealing nothing about its contents.
The Note Structure
Every Note in Xythum contains the following components:
Where:
assetId— The token contract address (hidden on-chain)value— The amount of the asset (hidden on-chain)secret— A random blinding factorrecipientKey— The owner's public spending key
The secret acts as a cryptographic blind, preventing brute-force guessing attacks even if other note parameters were to leak.
Key Derivation
User keys in Xythum follow a hierarchical structure derived from a single root secret:
From this root, we derive the master spending and viewing keys:
interface DarkAccount {
skRoot: Uint8Array;
skSpend: Uint8Array;
skView: Uint8Array;
shieldingKey: Uint8Array;
}
function deriveKeys(signature: Uint8Array): DarkAccount {
const skRoot = hash("xythum.root", signature);
const skSpend = hash("xythum.spend", skRoot);
const skView = hash("xythum.view", skRoot);
const shieldingKey = hash("xythum.shieldingKey", skView);
return { skRoot, skSpend, skView, shieldingKey };
}Nullifier Generation
To prevent double-spending, each Note has a unique nullifier that is revealed when spent. Critically, the nullifier reveals nothing about which Note it corresponds to.
For the -th UTXO, the nullifier is computed as:
Security Property
Given a nullifier, an adversary cannot determine which on-chain Note it corresponds to. This breaks the link between deposit and withdrawal.
Note Commitments
Rather than storing Notes on-chain directly, we publish commitments — cryptographic hashes that bind to the Note's contents without revealing them:
The commitment is what gets stored in the on-chain Merkle tree. To spend a Note, the owner proves:
- They know a valid Note preimage for a commitment in the tree
- They possess the spending key for that Note
- The nullifier they're revealing corresponds to that Note
All without revealing the Note contents.
Balance Conservation
For any valid transaction consuming inputs and producing outputs:
Where represents value entering from (positive) or exiting to (negative) the public chain.
ZK Enforced
This balance equation is verified inside the ZK circuit. The prover must demonstrate conservation without revealing any actual values.
Threshold Decryption
Notes are encrypted using a hybrid scheme that enables both personal and authorized decryption:
| Party | Can Decrypt? | Method |
|---|---|---|
| Note Owner | ✅ Yes | Using their shielding key |
| Anyone Else | ❌ No | Encrypted |
| DAO Quorum | ✅ Conditional | Threshold decryption (m-of-n) |
This enables compliant privacy — users have full privacy, but a quorum of authorized parties can decrypt notes under legal order.
Implementation
Here's a simplified implementation of Note creation:
pub struct Note {
pub asset_id: [u8; 32],
pub value: u64,
pub secret: [u8; 32],
pub recipient_key: PublicKey,
}
impl Note {
pub fn commitment(&self) -> [u8; 32] {
hash(&[
&self.asset_id,
&self.value.to_le_bytes(),
&self.secret,
&self.recipient_key.as_bytes(),
])
}
pub fn nullifier(&self, sk_spend: &[u8], index: u64) -> [u8; 32] {
hash(&[
b"xythum.nullifier",
sk_spend,
&index.to_le_bytes(),
])
}
}What's Next?
In our next article, we'll explore how these Notes interact with the Solver Network to enable private order matching and settlement.
Xythum — Protocol-agnostic dark liquidity for the sovereign trader.