Privacy & Confidential Transfers
Scan Tags
Efficient note filtering for recipient scanning
Scan Tags
Scan tags are 4-byte fingerprints that enable efficient server-side scanning of shielded notes without trial decryption.
Derivation
recipientX25519Pub (32 bytes)
→ keccak256(recipientX25519Pub)
→ first 4 bytes
→ scanTag (e.g., "0x1a2b3c4d")On-Chain Usage
The NoteCreated event includes scanTag as an indexed parameter:
event NoteCreated(
uint256 indexed commitment,
uint256 leafIndex,
bytes4 indexed scanTag,
bytes32 ephemeralPubKey,
bytes encryptedNote
);This allows the Goldsky indexer to filter events by scan tag at the database level, and the scanning cron to query confidential_events with a simple WHERE clause.
Privacy Trade-off
| Aspect | Detail |
|---|---|
| Linkability | All notes to the same recipient share the same scan tag |
| Identity | Scan tags do not reveal the recipient's identity or public key |
| Collision | ~1 in 4 billion chance of two recipients sharing a tag |
| Reversibility | Cannot derive the X25519 public key from a scan tag |
The linkability trade-off is acceptable because the confidential ledger already associates notes with stealth addresses, which are per-recipient.
Server-Side Scanning
The scanning cron (/api/cron/scan-incoming-notes) uses scan tags to filter events:
SELECT * FROM confidential_events
WHERE scan_tag = $1
AND id > $2 -- cursor
ORDER BY id ASCThis reduces the scanning workload from O(total_notes × wallets) to O(notes_per_wallet).