Skip to main content

Private Order Flow

Overview

Private Order Flow is Winnr's privacy layer for on-chain trading. It combines stealth addresses, shielded wallets, and ZK (Zero-Knowledge) circuits to ensure that a trader's identity, strategies, and trading history cannot be correlated or traced by external observers—without compromising execution speed or settlement guarantees.

Core Concepts

Stealth Addresses

For every order placed in private mode, Winnr generates a fresh stealth address. This one-time address acts as the ephemeral identity for that specific order. Because each order originates from a unique, unlinkable address, external observers cannot correlate orders to a single user or build a picture of their trading activity.

Stealth addresses are derived deterministically from the user's shielded wallet keys using a monotonically incrementing nonce (a global u64 that increments per order). The stealth address is an Ed25519 public key — a valid Solana pubkey — and is used as the order owner on-chain.

Shielded Wallet & Key Derivation

A shielded wallet is derived from a single signature of the user's main Solana wallet. The derivation is deterministic and non-interactive — the same main wallet always produces the same shielded keypair. Keys are derived using HKDF with a fixed domain "winnr-shielded-v1".

  • Creation: On first use, the user signs a registration message. The signature is used as HKDF input key material.
  • Funding: Users transfer funds from their public balance into the shielded wallet. These transfers are visible on-chain, but subsequent activity from the shielded wallet is not linkable to the origin.
  • Balance: The shielded balance is tracked as UTXO notes in the off-chain execution layer and settled on-chain.

The diagram below shows how keys are derived from the user's main wallet to produce the shielded wallet keypair and, from there, the per-order stealth addresses:

Shielded wallet and stealth address key derivation

The shielded wallet keys are derived once during registration. A fresh stealth address is then derived for each individual order.

Derivation Scheme

All key derivation uses HKDF-SHA256 with domain "winnr-shielded-v1".

// 1 — Registration message signed by main wallet
msg = "Winnr Shielded Wallet Registration\nmain wallet: {address}\nversion: 1"
signature = wallet.signMessage(msg) // 64-byte Ed25519 signature

// 2 — Master secret (root of all derived keys)
master_secret = HKDF(IKM=signature, salt=DOMAIN, info="master", len=32)

// 3 — Shielded wallet keypair
spend_key = HKDF(IKM=master_secret, salt=DOMAIN, info="spend", len=48) mod r
view_key = HKDF(IKM=master_secret, salt=DOMAIN, info="view", len=48) mod r
stealth_secret = HKDF(IKM=spend_key, salt=DOMAIN, info="stealth", len=32)

// 4 — Per-order stealth address (nonce = global u64, increments per order)
stealth_seed_N = HKDF(IKM=stealth_secret, salt=DOMAIN, info=nonce, len=32)
stealth_key_N = ed25519_keypair(stealth_seed_N)
stealth_address = stealth_key_N.publicKey // Solana pubkey, used as order owner

// 5 — Detection tag (allows owner to scan for their orders without revealing identity)
detection_tag = HMAC-SHA256(key=view_key, data=market_id || nonce) // 32 bytes

The view_key and detection_tag are the privacy-preserving scanning mechanism: the owner can recompute detection tags for every (market_id, nonce) pair and query the indexer for matches — without exposing their stealth addresses to anyone else.

ZK Circuits

Winnr uses custom ZK circuits written in Circom 2 to prove the validity of private orders without revealing the trader's identity or order details to the public.

The core circuit is a single-note-spend UTXO circuit (Transact). It takes a private input note from the shielded pool and produces a new output note, proving the following in zero-knowledge:

  • Note commitment validity: The input note commitment is correctly formed as Poseidon(owner, amount, salt, nonce).
  • Nullifier validity: The nullifier is Poseidon(commitment, leaf_index) — prevents double-spend without revealing which note is being spent.
  • Merkle inclusion: The input note exists in the on-chain commitment Merkle tree (via a Merkle proof of configurable depth).
  • Output note integrity: The output note commitment is correctly formed with output_nonce = nonce + 1.
  • Owner continuity: Input and output note owner must match.
  • Amount conservation: input_amount + public_deposit = output_amount + public_withdraw. This allows transparent deposits and withdrawals while keeping internal balances private.

Public signals (revealed on-chain): root, nullifier, output_commitment, public_deposit_amount, public_withdraw_amount.
Private signals (kept hidden): owner, amount, salt, nonce, Merkle path elements.

Order Lifecycle

The following describes the end-to-end flow of a private order:

  1. Private Mode Activation — The user enables Private Mode. The client resolves or registers the user's shielded wallet.
  2. Stealth Address Generation — For each order, the client derives a fresh stealth address from the shielded wallet's keys.
  3. Order Construction — The order is constructed using the stealth address as the signer identity, rather than the user's public wallet.
  4. ZK Proof Generation — A ZK proof is generated client-side, attesting to balance sufficiency and ownership without revealing sensitive data.
  5. Order Submission — The order, along with its ZK proof, is submitted to the off-chain execution layer.
  6. Matching & Execution — The order is matched in Winnr's order book. The execution layer verifies the ZK proof before accepting the order.
  7. On-chain Settlement — Settled trades are committed on-chain. The settlement references the stealth address, keeping the user's main wallet address fully decoupled from market activity.
info

Further technical details on the ZK circuit specifications, proof formats, and on-chain program interfaces will be published as the implementation is finalized.