PIXPSH/1 — a shared pixel canvas written on Dogecoin
Status: draft-1, 2026-08-08. Chain: Dogecoin. Push transport: OP_RETURN (nulldata), ≤ 80 bytes. Canvas transport: doginal (ord-style) inscription, text/plain;charset=utf-8.
0. Why this exists
A shared pixel canvas is normally a row in somebody's database. The canvas exists because a company is paying for a server, and it stops existing when they stop. Everything ever painted on it is held hostage to a hosting bill that the people who painted it do not pay and cannot see.
PIXPSH moves the canvas to a place with no landlord. A pixel is a few dozen bytes of plain text in an OP_RETURN on an ordinary Dogecoin transaction. It is not an NFT, it does not need an inscription, and it costs about what a transaction costs. Anyone can write one. Anyone can read one off a block explorer with their eyes, no tooling. Anyone can rebuild the whole canvas — every pixel, in the right order, with the right winner for every contested square — from the chain alone, in a few hundred lines of code, in any language.
This project runs an indexer and a website. Both are caches. Neither is the canvas. If both disappear tomorrow, §7 and §10 are enough for a stranger to rebuild them.
The protocol is multi-instance from the first line. The magic is immediately followed by which canvas the push is addressed to, so one protocol carries many independent canvases that never collide.
1. Design rules
- Plain text, brace-delimited. No JSON, no length prefixes, no binary packing. If you can read the
OP_RETURN, you can read the edit. - One push must fit in one
OP_RETURN— 80 bytes, no continuation, no reassembly across transactions. An edit either happened or it didn't. - Forward compatible. An unknown field is ignored, never an error. A malformed tail never voids the pixels already parsed ahead of it.
- The chain is the canvas. Indexers, APIs and websites are caches.
- Deterministic. Two independent indexers reading the same chain MUST produce the identical canvas, pixel for pixel (§8).
- Authority comes from custody of the canvas inscription (§5), not from an account on a server.
2. Encoding
- US-ASCII. (The payload is bytes; no field in PIXPSH/1 needs anything else.)
- A push is a sequence of fields. A field is
{, a body,}. - Bytes outside a field are ignored — leading/trailing whitespace between fields
is legal and carries no meaning.
- Field bodies are matched case-insensitively; readers write them back in the
canonical case shown here.
- The
OP_RETURNpayload is the bytes pushed by the nulldata output. If a
transaction carries more than one OP_RETURN, they are considered in output order and each is parsed as a separate push.
3. The push
{PixPsh}{ID:1}{421,837}{FF00AA}
Fields, in order:
| # | Field | Form | Meaning |
|---|---|---|---|
| 1 | magic | {PixPsh} | This is a PIXPSH/1 push. Required, must be first. {pxlpsh} is an accepted alias (§3.2) |
| 2 | instance | {ID:<id>} | Which canvas this push is addressed to (§5). Required, must be second. |
| 3 | op | see §4 | What to paint |
| 4 | color | {<RRGGBB>} | Six hexadecimal digits, RRGGBB. Required after every op. |
| … | Further op/color pairs may follow |
<id> matches [A-Za-z0-9._-]{1,16}.
A payload that does not begin with the magic is not a PIXPSH push and is ignored entirely — this is the discovery rule, and it is the whole of it.
3.1 Size
80 bytes is the ceiling and it is the real design constraint. The canonical single-pixel push above is 31 bytes; each additional {x,y}{RRGGBB} pair costs up to 17 more, so three pixels fit a worst-case push and more fit when the coordinates have fewer digits. The limit is bytes, never a pixel count: a reader parses pairs until the payload runs out.
A payload longer than 80 bytes is not standard on Dogecoin and will not relay. A writer MUST NOT build one; a reader that somehow encounters one parses what it can (rule 3).
3.2 The magic, and its alias
The magic is matched case-insensitively against two spellings, pixpsh and pxlpsh. Writers MUST emit {PixPsh}; readers MUST accept both.
The alias is not indecision. The protocol is named PixPsh, and the canvas it was built for lives at pxlpsh.hankelsner.tech — so both spellings are already in circulation among exactly the people most likely to hand-write a push. A reader that accepted only one would reject the others silently, and a silently rejected push is indistinguishable, to the person who paid for it, from a pixel that simply never arrived. Six bytes of parser is a cheap price for never having to explain that.
No third spelling will be added. {PixPsh2} stays reserved for a version bump (§12).
4. Ops
4.1 Point — {<x>,<y>}
Decimal, no leading +, no spaces. x is the column and y is the row, both 0-based from the top-left, both 0–999 on a 1000×1000 canvas. Leading zeros are permitted and ignored ({0421,0837} == {421,837}).
A coordinate outside the canvas is dropped individually — that pair is skipped and parsing continues with the next one. It does not void the push.
4.2 Rectangle — {R:<x>,<y>,<w>,<h>}
Fills w × h pixels with the origin at x,y, clipped to the canvas edges. w and h are ≥ 1. A rectangle entirely off-canvas is dropped like an out-of-range point.
A rectangle costs 25 bytes including its color, so a large area costs one transaction instead of thousands. Without it, repainting a 1000×1000 canvas one point at a time would take over 300,000 transactions.
4.3 Fill — {F}
Fills the entire canvas with the color that follows. Honoured only from the canvas authority (§6); from anyone else it is recorded and ignored. A stranger being able to erase a shared canvas with 11 bytes is not a feature.
4.4 Unknown fields
A field whose body is not a recognised op is skipped on its own, and parsing continues with the next field. A color field is consumed only immediately after a recognised op; encountered anywhere else it is itself an unrecognised op and is skipped.
That pair of rules is what makes the format safely extensible. A future op is skipped, and then the color that trailed it is skipped too — because six hex digits can never be mistaken for a point (no comma), a rectangle (no R:) or a fill (F is exactly one character). The parse stream re-synchronises on its own, so an old reader meeting a PIXPSH/1 push full of ops it has never heard of still lands every pixel it does understand, in the right place.
A recognised op whose following field is missing or is not a valid color is dropped along with that field. Pixels parsed earlier in the push are unaffected.
5. Instances — a canvas is an inscription
A canvas is created once, by inscribing a plain-text record as an ordinary doginal. The reveal txid is the canvas's permanent identity.
PIXPSH/1 CANVAS
ID:1
N:Genesis
S:1000x1000
BG:101820
W:OPEN
INK:D8Ea1s9dQ4hQ7tR2vB5nK3mW6xY9zA1cF2
FEE:100000000
| Key | Req | Meaning |
|---|---|---|
ID | yes | The instance id pushes address. [A-Za-z0-9._-]{1,16} |
N | yes | Display name |
S | yes | <width>x<height>, each 1–4096. PIXPSH/1's reference canvas is 1000x1000 |
BG | no | Background color RRGGBB for never-painted pixels. Default 000000 |
W | no | Write policy (§6). Default OPEN |
INK | yes | The ink address (§7) |
FEE | no | Minimum ink payment per push, in koinu. Default 100000000 (1 DOGE) |
A | no | Delegated authority address (§6) |
U | no | A URL for more information |
Line 1 MUST be exactly PIXPSH/1 CANVAS. Subsequent lines are KEY:VALUE; unknown keys are preserved and ignored; the first occurrence of a duplicate key wins; # comments and blank lines are skipped. (This is BEACON/1 §2's line format, deliberately — the two protocols are meant to be read by the same eyes.)
5.1 Claiming an id, without a registrar
Two people can inscribe a canvas claiming ID:1. The tie is broken from the chain alone, by rule, with nobody arbitrating:
The earliest confirmed canvas genesis claiming an id owns that id. Ties within a block are broken by ascending txid.
A later claim to a taken id is recorded and reported as disputed, never silently dropped — a contested canvas should be visible as contested. Pushes addressed to that id apply to the winning canvas only.
Readers that want no ambiguity at all may address a canvas by its genesis txid instead of its id; an indexer MUST accept both.
6. Authority — who may paint
The holder of the canvas inscription output is the canvas authority. A doginal is a specific 0.001-DOGE output; whoever controls the address holding it controls the canvas. Transferring the inscription transfers the canvas. There is no account and no password.
The genesis W key sets who may paint:
W | Meaning |
|---|---|
OPEN | Anyone who pays the ink (§8). The default. |
OWNER | Only the canvas authority, or the address in A |
LIST | Only addresses named in L: lines in the genesis, plus the authority |
The pusher is the address controlling input 0 of the push transaction.
A push that violates the write policy is recorded and not applied — shown as unauthorised rather than discarded, so a disputed canvas is visible rather than invisible. Same principle as BEACON/1 §8.
{F} (§4.3) is always authority-only regardless of W.
7. The ink output — and why it is mandatory
A push MUST also pay at least FEE koinu to the canvas's INK address, in the same transaction. A push without it is not a valid push and is not applied.
This is load-bearing, not a toll. Dogecoin offers no way to search for an OP_RETURN by its content. Without an anchor, an indexer would have to fetch and scan every block, forever — about 1,440 block fetches a day, growing without end, before it can render a single pixel. With the ink output, every push to a canvas is reachable by querying one address, which is a paginated call every chain indexer already supports. That difference is what makes an independent third-party indexer a few hundred lines instead of an infrastructure project, and rule 4 is worthless if only the well-resourced can exercise it.
That it also prices spam, and funds whoever runs the canvas, is a convenience. The reason it is in the protocol is discoverability.
The ink address is an ordinary address. It has no special powers; it is not required to be the authority's address, and paying it grants nothing beyond having paid it.
8. Ordering — resolving two people painting one pixel
Last write wins, over the total order:
(block height, position within block, output index within transaction, pair index within push)
ascending; later beats earlier. Unconfirmed pushes are not part of the canvas — an indexer MAY show them as pending, but MUST NOT let them affect the committed state, because they can still be reordered or dropped.
Every term is observable by anyone with a chain, which is the point: two indexers applying this rule to the same chain produce the identical canvas. That determinism is what makes the canvas a fact rather than an opinion, and it is what makes a trustworthy replay of the canvas's history possible at all.
9. What must not be painted
Permanent and public are the same sentence here. A push is a public, permanent statement by an address you control. Pixels do not seem like speech until enough of them are next to each other; assume everything ever painted stays readable and attributable forever, including by people who dislike it.
10. Reading a canvas from nothing
An implementer with a Dogecoin chain or any Blockbook-style indexer needs only:
- Find the canvas genesis: an inscription whose content type is
text/plain*and whose first line isPIXPSH/1 CANVAS. ReadID,S,BG,W,INK,FEE. Apply §5.1 if the id is contested. - List transactions paying the
INKaddress. - For each, in the §8 order: check the ink payment ≥
FEE; read eachOP_RETURN; require the magic and a matching{ID:…}; parse ops (§4); check the write policy against input 0's address (§6). - Apply each op to a
width × heightarray initialised toBG.
The result is the canvas. Nothing in that list requires this project's server, this project's website, or this project's permission.
11. Worked examples
One pixel:
{PixPsh}{ID:1}{421,837}{FF00AA}
Three pixels, one transaction (65 bytes):
{PixPsh}{ID:1}{421,837}{FF00AA}{422,837}{FF00AA}{423,837}{00FF88}
A 64×64 block at 100,100 (39 bytes):
{PixPsh}{ID:1}{R:100,100,64,64}{FF3300}
Clear the canvas to dark blue — authority only (25 bytes):
{PixPsh}{ID:1}{F}{101820}
Tolerated by rule 3 — the unknown {Z:…} op and its color are skipped, the out-of-range point is dropped, and the last pixel still lands:
{PixPsh}{ID:1}{Z:9}{000000}{5000,1}{FFFFFF}{7,7}{00FF88}
12. Versioning
The magic carries the version: {PixPsh2} would be a new magic and a new document. Within PIXPSH/1, new ops, new canvas keys and new write policies may be added without a version bump, because rule 3 guarantees an old reader survives meeting them.