TAP on DogeBitcoin Universe

Conformance evidence

Test vectors

Cases an implementation must reproduce. The envelope vectors are derived from the parser in ord-dogecoin, the Doginals client the Dogecoin TAP specification names. The payload vectors follow the specification and the behaviour of the Bitcoin Universe Dogecoin TAP source.

How to read these

Every vector states an input, an expected outcome, and the rule number it exercises. "Nothing indexed" means no inscription, no TAP message, and no state change, not a partial result. Payload vectors can be pasted straight into the validator.

Envelope vectors

Each of these is the raw signature script of an input, as hexadecimal. The parser decodes push operations only, and reads the first input of the transaction.

E1: complete single-transaction envelope, accepted

input 0 scriptSig:
036f7264 51 18 746578742f706c61696e3b636861727365743d7574662d38 00 04 776f6f66

decoded pushes:
  "ord"                       protocol marker
  OP_1                        piece count = 1
  "text/plain;charset=utf-8"  content type
  OP_0                        countdown = 0, which is piece count minus one
  "woof"                      body chunk

Expected: complete inscription, content type text/plain;charset=utf-8, body woof. Exercises E-2 through E-7.

E2: a real TAP mint envelope, accepted

input 0 scriptSig:
036f7264 51 18 746578742f706c61696e3b636861727365743d7574662d38 00 37
7b2270223a22746170222c226f70223a22746f6b656e2d6d696e74222c227469
636b223a22746170222c22616d74223a2231303030227d

body, decoded as UTF-8:
{"p":"tap","op":"token-mint","tick":"tap","amt":"1000"}

Expected: complete inscription; the body parses as a TAP message and credits 1000 of ticker tap to the address holding the inscription output, provided the deployment permits it. The body is 55 bytes, so 0x37 is the push length and one chunk suffices. Exercises E-2 through E-7 and P-1 through P-3.

E3: countdown mismatch, rejected

input 0 scriptSig:
036f7264 52 18 746578742f706c61696e3b636861727365743d7574662d38 53 04 776f6f66 00 04 776f6f66

decoded pushes:
  "ord"     OP_2 (piece count = 2)     content type
  OP_3      "woof"    OP_0    "woof"
            ^ countdown is 3, but piece count minus one is 1

Expected: partial, therefore nothing indexed. The mismatch stops body accumulation, and because there is no following transaction the parse ends partial. Exercises E-6 and E-9.

E4: envelope in the second input, rejected

input 0 scriptSig: (empty)
input 1 scriptSig: 036f7264 51 18 746578742f706c61696e3b636861727365743d7574662d38 00 04 776f6f66

Expected: no inscription. A perfectly well formed envelope in any input other than input 0 is ignored. Exercises E-1.

E5: a ported Bitcoin witness envelope, rejected

scriptSig containing:  OP_FALSE OP_IF "ord" 01 <content type> OP_0 <body> OP_ENDIF

Expected: no inscription. OP_IF is 0x63, which is not a push opcode, so the decode ends immediately and yields no pushes at all. This is the single most likely failure for an inscriber ported from Bitcoin without changing the carrier. Exercises E-2.

E6: piece count of zero, rejected

input 0 scriptSig:
036f7264 00 18 746578742f706c61696e3b636861727365743d7574662d38 ...
                ^ OP_0 decodes to a piece count of 0

Expected: no inscription. A zero piece count is invalid. Exercises E-4.

E7: reveal chain that ends early, rejected

tx 1, input 0: "ord" OP_3 <content type> OP_2 <chunk> OP_1 <chunk>
tx 2:          does not exist

Expected: partial, therefore nothing indexed. Two of three chunks are present and the countdown never reaches zero. The fees for tx 1 are spent and the remaining chunk cannot be supplied later. Exercises E-9.

E8: reveal chain continued correctly, accepted

tx 1, input 0: "ord" OP_3 <content type> OP_2 <chunk A> OP_1 <chunk B>
tx 2, input 0: OP_0 <chunk C>

Expected: complete inscription with body A || B || C. The first push of tx 2's input 0 must be exactly the next countdown value. Exercises E-8.

Accepted payloads

Payloads that produce state. Each assumes the surrounding conditions its notes name.
VectorPayloadOutcome
A1
deploy
{"p":"tap","op":"token-deploy",
 "tick":"tap","max":"21000000",
 "lim":"1000"}
Creates ticker tap with maximum supply 21000000 and a per-mint limit of 1000, if the ticker is not already deployed. Rule D-1.
A2
deploy, no limit
{"p":"tap","op":"token-deploy",
 "tick":"doge","max":"1000000"}
Valid. Without lim, the whole supply may be minted in a single mint. Rule D-1.
A3
mint
{"p":"tap","op":"token-mint",
 "tick":"tap","amt":"1000"}
Credits 1000 to the address holding the inscription, if supply remains and 1000 is within lim. Rules M-1 to M-3.
A4
transfer
{"p":"tap","op":"token-transfer",
 "tick":"tap","amt":"100"}
Moves 100 from available to transferable and creates a live transfer inscription. No recipient is named or needed. Rules X-1, X-2.
A5
cursed ticker
{"p":"tap","op":"token-mint",
 "tick":"-tap","amt":"1"}
Valid. -tap is a distinct ticker from tap, reached through a cursed inscription. Rule P-6.
A6
batch send
{"p":"tap","op":"token-send",
 "items":[{"tick":"tap","amt":"1",
 "address":
 "DHZqJo3DUyhQsrdR3Kcs8xvfaMzPkzE5gP"}]}
Syntactically valid. It moves nothing until it is inscribed to the sender's own address and tapped. Rules N-1 to N-5.
A7
block transferables
{"p":"tap",
 "op":"block-transferables"}
Valid with no other fields. Takes effect only once tapped. Rules B-1, B-2.
A8
DMT mint
{"p":"tap","op":"dmt-mint",
 "tick":"dogenat","blk":5000000,
 "dep":"825e287b…a3dci0"}
Valid. blk is a JSON integer, which is required from block 5,497,100 onward. Rules G-3, G-4.
A9
unknown field
{"p":"tap","op":"token-mint",
 "tick":"tap","amt":"1",
 "note":"hello"}
Valid. Unknown fields are ignored, never fatal and never meaningful. The validator raises a caution because an unknown field is often a misspelled required one. Rule P-4.

Rejected payloads

Payloads that create no state. Several of these confirm on chain and cost a full fee before doing nothing.
VectorPayloadWhy it is rejected
R1
DRC-20 operation name
{"p":"tap","op":"mint",
 "tick":"tap","amt":"1000"}
Inert. mint is the DRC-20 and BRC-20 spelling. TAP prefixes its token operations, so this should be token-mint. No TAP indexer recognises it, and no DRC-20 indexer claims it either because p is not drc-20. The inscription confirms, the fee is spent, and nothing else happens. Rule P-3.
R2
DRC-20 transfer name
{"p":"tap","op":"transfer",
 "tick":"tap","amt":"100"}
Inert. Same failure as R1. The correct operation is token-transfer. Rule P-3.
R3
recipient on a transfer
{"p":"tap","op":"token-transfer",
 "tick":"tap","amt":"100",
 "to":"DHZqJo3D…"}
Parks, does not send. to is not a field of token-transfer and is ignored. The amount is parked as a transfer inscription that you still hold. Anyone expecting the tokens to have arrived is wrong. Rules X-1, P-4.
R4
Bitcoin recipient
{"p":"tap","op":"token-send",
 "items":[{"tick":"tap","amt":"1",
 "address":"bc1p9lpne8pnzq87…"}]}
Invalid. The recipient is a Bitcoin bech32m address, which cannot exist on Dogecoin. Under N-3 a syntactically invalid item invalidates the whole inscription before tapping. Rules N-3, N-6, I-3.
R5
wrong protocol tag
{"p":"drc-20","op":"token-mint",
 "tick":"tap","amt":"1000"}
Inert. The reverse mistake. token-mint is not a DRC-20 operation, and the tag is not tap, so neither protocol reads it. Rule P-2.
R6
uppercase protocol tag
{"p":"TAP","op":"token-mint",
 "tick":"tap","amt":"1"}
Invalid. p must be exactly the lowercase string tap. Rule P-2.
R7
amount with separators
{"p":"tap","op":"token-mint",
 "tick":"tap","amt":"1,000"}
Invalid. Amounts are plain decimal strings: digits with at most one ., no separators, no sign, no exponent. Rule P-5.
R8
ticker of two symbols before the widening
{"p":"tap","op":"token-deploy",
 "tick":"ab","max":"100"}
Height dependent. Invalid below block 5,487,639, where only 3 or 5 to 32 symbols were allowed. Valid from that height onward. An indexer that applies today's rule to historical blocks produces wrong balances. Rule P-7.
R9
ticker of 33 symbols
{"p":"tap","op":"token-deploy",
 "tick":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
 "max":"100"}
Invalid. 32 Unicode symbols is the ceiling at every height. Rule P-7.
R10
seq as a string
{"p":"tap","op":"privilege-auth",
 …,"verify":"…","col":"","seq":"111"}
Invalid. The specification states explicitly that a string seq fails the verification. It must be a JSON integer. This is the opposite of the convention for amounts, which is why it is easy to get wrong. Rule V-4.
R11
trade filled with a token not offered
{"p":"tap","op":"token-trade",
 "side":"1","trade":"…i0",
 "tick":"other","amt":"1"}
Invalid. tick and amt must match exactly one entry of the referenced trade's accept array. Rule R-8.
R12
inscription number instead of id
{"p":"tap","op":"token-trade",
 "side":"0","trade":"12345"}
Invalid. Reference fields take the inscription id, <64 hex txid>i<index>, never the inscription number. Rule I-1.
R13
JSON array
[{"p":"tap","op":"token-mint",
 "tick":"tap","amt":"1"}]
Invalid. A TAP message is exactly one JSON object. Batching is done with token-send, not with an array of messages. Rule P-1.
R14
reused authority hash
{"p":"tap","op":"token-auth",
 "sig":{…},"hash":"<already used>",
 "salt":"…","auth":["gib"]}
Invalid. A hash may be used once across the entire protocol state. This is why the authority must vary its salt. Rule A-3.

Address vectors

These exist because the published Dogecoin specification carries Bitcoin address wording and Bitcoin example addresses. The two valid addresses below are documentation examples with correct checksums; no one holds their keys.

Address forms and their outcome in a Dogecoin TAP payload.
AddressDecodes toOutcome
DHZqJo3DUyhQsrdR3Kcs8xvfaMzPkzE5gP25 bytes, version 0x1eValid Dogecoin mainnet pay-to-public-key-hash.
AEjn4gLcgt9FydZmPEx7qRWi68AtuF9YPH25 bytes, version 0x16Valid Dogecoin mainnet pay-to-script-hash. Note that the Bitcoin Universe marketplace surface accepts 0x1e only, per I-5.
DHZqJo3DUyhQsrdR3Kcs8xvfaMzPkzE5gQ25 bytes, bad checksumInvalid. One changed character breaks the base58check checksum.
dHZqJo3DUyhQsrdR3Kcs8xvfaMzPkzE5gPfailsInvalid. Dogecoin base58 addresses are case-sensitive. The Bitcoin rule about lowercasing bc1 addresses has no counterpart here. Rule I-4.
bc1p9lpne8pnzq87dpygtqdd9vd3w28fknwwgv362xff9zv4ewxg6was504w20not base58Invalid. A Bitcoin bech32m address, copied from the published examples. Rule Q-2.
1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2version 0x00Invalid. A Bitcoin base58 address. Correct checksum, wrong chain.

State transition vectors

Balances after each step. Start from address D1 holding 500 of ticker tap, all available.

A transfer, end to end. Total balance is unchanged by step 2, which is where most confusion begins.
StepActionD1 availableD1 transferableD2 available
0Starting state50000
1D1 inscribes token-transfer for 100, unconfirmed50000
2That inscription confirms4001000
3D1 sends the inscription to D2, confirmed4000100
4D2 tries to send that same inscription onward4000100

Step 4 changes nothing: the transfer inscription was consumed at step 3 and can never move tokens again. D2 owns 100 tokens as available balance and must inscribe its own token-transfer to move them. Rules W-3 and X-3.

A batch send that is partly unfunded. Syntax is atomic; semantics are not.
StepActionResult
0D1 holds 50 available, 0 transferableStarting state.
1D1 inscribes a token-send with two items: 30 to D2 and 40 to D3Both items are syntactically valid, so the inscription is valid. Nothing has moved. Rule N-3.
2D1 taps itThe 30 to D2 executes. The 40 to D3 is skipped: only 20 remains available. D1 ends with 20 available, D2 gains 30, D3 gains nothing. Rule N-4.
Tapping. An internal operation that is never tapped has no effect at all.
StepActionResult
1D1 inscribes block-transferables to itself, confirmedNo effect. The address still accepts inbound transfers. Rule T-2.
2D1 sends that inscription to D2Still no effect, and the opportunity is gone: the inscription is no longer at the address it was meant to protect. Rule T-1.
3Alternative: D1 sends it to D1 insteadTapped. Inbound inscribe transfers to D1 are now skipped. Existing live transfer inscriptions elsewhere remain usable. Rule B-2.