Use
A batch is several receipts in one link. Pass more than one--txid:
k=zip311k1…). Verifying the batch checks it:
examples/testnet/batch.txt, and one
with its same-payer proof is examples/testnet/batch-same-payer.txt.
How it works
Every receipt’s spend signs underrk_i = ak + [alpha_i]G. If all payments came from one key,
then rk_i − rk_0 = [alpha_i − alpha_0]G for every i. The proof is a Schnorr proof of knowledge
of each difference, made non-interactive by hashing the whole statement (every rk, the
receipts’ digests, the message) with the commitments.
- Sound: a valid proof means the prover knows every
alpha_i − alpha_0. For different keysx_i,x_0that difference isx_i − x_0, and knowing it without both secrets would solve a discrete log. - Zero knowledge:
(R_i, s_i)can be simulated fromrk_i − rk_0alone, so it reveals the relation it states and nothing aboutak. - Bound: the proof signs the receipts’ digests in order. It can’t be moved to other receipts, reordered or bent.
Limits
- It shows one signing key made the payments, or keys whose relation the maker knows. It doesn’t say which wallet, or who holds it.
- Two wallets that pool their keys can produce one.
- Payments made through sibling accounts have different keys; this proof does not link them.
crates/zceipt-core/src/link.rs. Test:
roundtrip.rs::same_payer_proof_links_one_key_and_nothing_else. The spec verifier checks the
testnet batch’s proof independently.