philargyry stores a compressed image in the satoshi values of spendable Bitcoin outputs. The picture is the money. You read it back from a transaction id with nothing but this library.
These are live on signet. Open them on an explorer, then decode them with the library and watch the image appear.
- Flagship:
f1b1da17…3360e - Mint:
ef35c320…7b7b53 - Transfer:
0939ca6b…5da5a
uv sync
uv run philargyry decode \
f1b1da174bfa6f316d7ece7f49d250013089b7436f48abef0547f61e9c43360e \
--network signet \
--canvas tb1qcu70080fvd3zf0v85ww9gxsgcdslfapvushfws \
--out flagship.png
That fetches the transaction, reads the output values, and writes the image to
flagship.png.
- Each data output is worth the dust floor plus one byte, so the amount is the data.
- One byte per output, read in vout order.
- The codec id and the square side ride in the nLockTime, the Lockchain Protocol beacon, which also keeps the transaction final.
- All data outputs pay one canvas address while change goes elsewhere, so the canvas address marks the data.
- The number of canvas outputs is the file length, so nothing else is stored.
The project is managed by uv with a pinned Python and locked dependencies.
uv sync
That reaches a working state from a clean clone. Python is pinned in
.python-version.
The pure parts have no network or disk IO. The IO parts take a Config.
from philargyry import Config, Network, estimate, build_mint, decode_from_txid
cfg = Config(network=Network.SIGNET, btc_usd=73800.0)
# Cost and capacity, exact locked capital, fees, and feasibility.
print(estimate("art.png", cfg=cfg).report())
# Build a mint, then validate, sign with a wallet, and broadcast.
built = build_mint(
"art.png",
canvas_address=canvas,
change_address=change,
funding_utxos=utxos,
cfg=cfg,
)
# Read it back from the chain with only a txid and the canvas address.
image = decode_from_txid(txid, canvas_address=canvas, cfg=cfg)The change address must differ from the canvas address. Version 1 is a single standard transaction, square images, CCITT Group 4. All outputs are standard P2WPKH, so the transaction relays and confirms on testnet, signet, and mainnet.
A single immutable Config carries the network. The default is signet. Mainnet
is gated: it is reachable only when allow_mainnet is true on the Config and
confirm=True is passed to the broadcast call. Broadcast and fetch use
bitcoinlib's native providers for testnet, mainnet, and regtest, and a mempool
style esplora endpoint for signet. There is no local node and there are no RPC
calls.
The code is released under the MIT license, see LICENSE.md.
The license covers the source code only. Artworks encoded or minted with it are not licensed and remain the property of their authors.
The author, Nikodem Tomczak, first disclosed this method on 2026-06-04 through this repository and on chain transactions that anyone can decode. A technical paper follows. No earlier work is known to the author that treats the monetary value of spendable Bitcoin outputs as the carrier of an overt and recoverable artwork.