A native Pi payment carries no observable per-unit mining origin on the Pi Mainnet ledger.
This file is the direct answer to the one concrete question: buy on an exchange → put it in the same wallet as your mined Pi → send Pi to someone. Can the recipient see which coins were mined and which were bought?
Short answer: No — and this is a deterministic property of the protocol, not a loophole.
m Pi (say 5) → your wallet S.e Pi on an exchange (say 10) → withdraw to the same wallet S.m + e = 15 Pi.a = 3 Pi to a friend F.F tell whether those 3 Pi were mined or bought?Answer: No. Neither F, nor the exchange, nor a block explorer, nor the Pi Core Team — from the ledger data.
Not because of secrecy, but because the protocol does not represent “coins” at all: the only state is a
scalar balance per (account, asset). “Which coin did I send?” is not a question the ledger can answer.
Analogy: a jug holds 5 L of water you fetched from the well + 10 L you bought. It now holds 15 L. When you pour 3 L, no one can say whether those 3 L were the “well water” or the “bought water”. That is not hiding — the distinction stopped existing the moment they mixed.
Define an account’s state as a function:
bal : (Account × Asset) → ℕ (non-negative integers, in stroops; 1 Pi = 10,000,000)
For the native asset, the only relevant value is bal(A, native). The state has no per-unit structure.
On the wire it is literally:
{ "balance": "15.0000000", "asset_type": "native" }
A payment is defined purely on scalars:
payment(S, D, a) : bal(S) -= a ; bal(D) += a
Consider two different histories that end in the same state:
H1 : mine 5 → S ; buy 10 → S ⇒ bal(S) = 15
H2 : buy 15 → S ⇒ bal(S) = 15
Both produce the identical ledger state and therefore the identical set of observables.
Formally: the map history → ledger state is not injective, and “origin” is not in its image.
No observable derived from the state can distinguish H1 from H2. This is an information-theoretic
statement (the distinguishing information was never recorded), not a probabilistic one.
send 3 : S → F ⇒ bal(S) = 12, bal(F) += 3
F receives the record: { amount: 3, asset_type: "native", from: S, to: F, memo, txid }.
There is no origin field, and there is no inverse function to recover which deposits financed those 3 Pi.
If your wallet held 5 mined + 10 bought and you send 3, the ledger has no FIFO/LIFO rule and no
“coin selection”. It simply subtracts 3. So the statement “I sent the mined ones” is not even
representable in the protocol. The sender’s intent is not part of the data.
This answers the fair objection: “the absence of an origin field doesn’t prove tracing is impossible — you can follow transactions between addresses.” Partly true — but it proves a different thing.
| Level | What it is | Observable? |
|---|---|---|
| Unit-level provenance | which π units are mined / bought | ❌ Undefined — the model has no units |
| Account-level history | which accounts a given account transacted with | ✅ Observable from the tx graph |
| Identity (KYC) | who owns an account | ⚠️ Off-chain, partial |
Yes, an analyst can see: “account S received from exchange hot-wallet X at time t” — if X
is publicly labeled. That is a fact about the account S over time, not about the coins S sends.
Why it does not restore per-coin origin:
amount/from/to/memo/txid — not
the sender’s past deposits.This is exactly how a bank account works. The statement lists deposits and withdrawals, but no bank records which specific banknote you withdrew. Cash is fungible structurally, not by policy — same for Pi.
What it proves ✅
What it does NOT prove ❌
FAQ-FUNGIBILITY-VS-PRICE.md — fungibility ≠ price.)Precise statement: “A payment carries no observable per-coin origin.” That is what is proven — no more, no less. This explicit scope answers the critique that “some conclusions are broader than the proof.”
node examples/mixing-check.mjs
node examples/mixing-check.mjs <SENDER_ACCOUNT>
It shows, on the live chain:
Real output is in examples/mixing-check-output.txt.
The default account received 5.0 + 1.0 + … yet its balance is 2.0 — proving you cannot reconstruct
which inflow financed which outflow.
Nothing here relies on trusting the author. Every claim is checkable:
SOURCES.md.history → ledger state is NOT injective
"origin" ∉ image of that map
⇒ per-coin origin is not an observable
⇒ the recipient CANNOT see the difference
Mined Pi and exchange-bought Pi are the same native asset. Mix them in one wallet and the distinction is not hidden — it is undefined. π = π.
PaymentDTO): https://github.com/pi-apps/pi-platform-docs/blob/master/platform_API.mdexamples/mixing-check.mjs