How it works · Command line

Check it yourself.

The vintage command checks any Zcash mainnet transaction from your own machine, against the public chain. It needs no account, no key and no server of ours. It also makes Vintage payments from a wallet.

A terminal running vintage verify on mainnet transaction da9017e0, which prints PASS: these coins existed before block 3,525,709, then vintage age on a stranger's transaction d3252057, which prints that its coins were in the pool by block 3,499,995 on 29 September 2026, before the Bitget hack.
Real output, 25 October 2026: our demo deposit passes, and a stranger's transaction from the day before the Bitget hack is dated to 29 September.
01 / Install

Build it.

Rust 1.89 or newer. The first build compiles the Zcash libraries, so it takes a while; later builds are quick.

Checking transactions needs nothing else. Sending (vintage send) also needs zcash-devtool with the two small patches in patches/, next to the vintage binary. Vintage never reads your seed: zcash-devtool signs.

Terminal
$ git clone https://github.com/Samuel-Chuku/vintage
$ cd vintage
$ cargo build --release
$ ./target/release/vintage --help
02 / Check any transaction

Three commands, no wallet.

vintage verify

Did every coin this transaction spends exist before an event, or before any block you name? Exit code 0 PASS, 1 FAIL, 2 not provable.

$ vintage verify <txid> --before bitget-2026-09
$ vintage verify <txid> --before 3501240 --json
PASS: These coins existed before block 3,525,709 (Vintage demo, a staged event, not a real hack).
evidence:    the anchor matched none of the 2890 distinct Ironwood roots at heights 3525709..=3530376; consensus requires it to be the root of an earlier block
vintage age

No event needed: the block by which every coin was in the pool, and which registered events that predates.

$ vintage age d3252057850259c86ffae437d0df207ff8b500e4d83dfe4409f585dcd6b441e4
age:         in the pool by block 3499995 (2026-09-29 06:15 UTC)
             ✓ bitget-2026-09         block   3501240  Bitget hot-wallet exploit: first shielding into Ironwood
             ✓ vintage-demo-2026-10   block   3525709  Vintage demo, a staged event, not a real hack
vintage sample

Lists real Ironwood transactions to try: from the last N blocks, or from any block with --from.

$ vintage sample --blocks 20
$ vintage sample --from 3500000 --blocks 1
3500000 d3252057850259c86ffae437d0df207ff8b500e4d83dfe4409f585dcd6b441e4
3500000 13ab80b092baae27d3c053bff2367d06e8a9e61e99f13eb907bd8c92825c78b8
3500000 eb9f4285d97744bc67409247ee7cb2d4cc50ac9ebb75c09c588e35224d3395b4
vintage tx

A transaction's Ironwood details: mined height and time, anchor, and what it spends.

$ vintage tx da9017e0fca0d8bd87def8e3faa7956067f2bd2234cfee91ca7ad4e67095e3a7
mined:         3527813  (2026-10-23 12:17:14 UTC)
ironwood:      3 action(s), spends enabled, outputs enabled
anchor:        855ccc99a779159d9d98664d1a09737814b930cc782b149660a94a3881d98502
03 / Send with an older anchor

Make a deposit that proves its age.

vintage status

For each registered event: how much of a wallet's ZEC a Vintage send can prove predates it.

$ vintage status --wallet <wallet-dir> --sync
vintage send

Sends with an anchor before the event, so the transaction proves its inputs predate it. Always --dry-run first: it shows which notes qualify and stops before signing.

$ vintage send --wallet <wallet-dir> -i <age-identity> \
    --to <address> --value <zatoshis> --before bitget-2026-09 --dry-run
04 / Coins received after the event

Ask, pay, link.

vintage request

Ask a payer for a Vintage payment. Prints a payment link (ZIP 321) whose memo names the event; the payer pays it with vintage send --uri.

$ vintage request --to <your address> --amount 0.5 --before bitget-2026-09
$ vintage send --wallet <payer-wallet> -i <age-identity> --uri '<URI>' --dry-run
vintage link

Link a deposit from a single-use receipt account to the Vintage payment that funded it. Discloses that one account's viewing key, nothing else. The rail can run link verify itself.

input 0:     0.00300000 ZEC from da9017e0fca0d8bd… output 1
input 1:     0.00300000 ZEC from da9017e0fca0d8bd… output 2
PASS: Every coin this deposit spends came from 1 payment whose coins existed before block 3,525,709 (Vintage demo, a staged event, not a real hack).
05 / The event registry

Signed dates.

The registry in registry/ is a list of dated events, signed with ed25519. check verifies the signature; the other two are for whoever maintains a registry.

vintage registry
$ vintage registry check
$ vintage registry keygen     # once: writes the private key and pubkey.hex
$ vintage registry sign       # after any edit to events.json
06 / Reference

Every command.

CommandWhat it doesNeeds
verify <txid> --before <H>PASS, FAIL or not provable against an event or block. --json, --received-by (a viewing key, checked locally).Nothing
age <txid>The coins' proven age, and every registered event it predates. --json.Nothing
tx <txid>A transaction's Ironwood details.Nothing
sampleReal Ironwood transactions to try. --blocks N, --from H.Nothing
status --walletHow much of a wallet's ZEC predates each event. --sync.A wallet
send --walletSend with an anchor before the event. --to, --value, --uri, --dry-run.A wallet, zcash-devtool
requestA payment link asking for a Vintage payment.Nothing
link prove / verifyThe receipt-account link for coins received after an event.Prove: the receipt wallet
witness --walletRead-only: which of a wallet's notes have a witness at a height.A wallet
registry check / keygen / signVerify or maintain the signed event registry.Sign: the private key

Options on every command: --network main|test (default main), --server host:port (any lightwalletd or Zaino server over TLS; default zec.rocks), --registry dir. Point --server at your own node and nobody else is involved. The same checks over HTTP: the API.