MezcalProtocol documentation

Conformance

Test vectors

Payloads with their exact hex encoding and the outcome each one must produce. The expected outcomes follow the rules on the specification page, which are taken from the reference implementation at revision 0f3323ff. Paste any of these into the validator to see the same checks applied field by field.

How to read a vector. The hex is the payload only: the bytes pushed after OP_RETURN, not the whole script. Prepend 0x6a and a push prefix to get the script. Outcomes that depend on the surrounding transaction state the shape they assume.

Valid payloads

Each of these parses, validates, and does exactly what it says. None of them burns anything the transaction did not aim at the OP_RETURN output.

V-1 · valid

Minimal transfer

{"p":"mezcal","edicts":[["899284:20","100",0]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b223839393238343a3230222c22313030222c305d5d7d

Transaction shape. 3 outputs: recipient, change, OP_RETURN

Expected outcome. 100 base units of 899284:20 to vout 0. The rest of the pool follows R-1 to vout 0 as well, because no pointer is given and vout 0 is the first non-OP_RETURN output.

V-2 · valid

Move the whole balance

{"p":"mezcal","edicts":[["899284:20","0",0]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b223839393238343a3230222c2230222c305d5d7d

Transaction shape. 2 outputs: recipient, OP_RETURN

Expected outcome. Amount 0 allocates everything remaining for that asset (A-5). Nothing is left for the remainder sweep.

V-3 · valid

Transfer with change

{"p":"https://mezcal.sh","edicts":[["899284:20","2500000000",0]],"pointer":1}

Payload hex
7b2270223a2268747470733a2f2f6d657a63616c2e7368222c22656469637473223a5b5b223839393238343a3230222c2232353030303030303030222c305d5d2c22706f696e746572223a317d

Transaction shape. 3 outputs: recipient, change, OP_RETURN

Expected outcome. 2500000000 base units to vout 0, everything left to vout 1 by the pointer (R-1).

V-4 · valid

Mint

{"p":"mezcal","mint":"899284:20"}

Payload hex
7b2270223a226d657a63616c222c226d696e74223a223839393238343a3230227d

Transaction shape. 2 outputs: receipt, OP_RETURN

Expected outcome. If the window is open, the cap allows it, and any price terms are paid, the minted units enter the pool and land on vout 0 by R-1.

V-5 · valid

Etch and allocate the premine

{"p":"mezcal","etching":{"mezcal":"agave-pot","symbol":"◉","divisibility":6,"premine":"1000000000","terms":null},"edicts":[["0:0","0",0]]}

Payload hex
7b2270223a226d657a63616c222c2265746368696e67223a7b226d657a63616c223a2261676176652d706f74222c2273796d626f6c223a22e29789222c2264697669736962696c697479223a362c227072656d696e65223a2231303030303030303030222c227465726d73223a6e756c6c7d2c22656469637473223a5b5b22303a30222c2230222c305d5d7d

Transaction shape. 2 outputs: receipt, OP_RETURN

Expected outcome. The asset is created with id block:tx of this transaction. 0:0 is rewritten to that id (I-4) and the amount 0 allocates the whole premine to vout 0. terms null makes the asset unmintable (E-11).

V-6 · valid

Instruction with no operation

{"p":"mezcal"}

Payload hex
7b2270223a226d657a63616c227d

Transaction shape. 2 outputs: recipient, OP_RETURN

Expected outcome. Valid and legal (P-6). Every balance on the inputs sweeps to vout 0.

V-7 · valid

Deliberate burn

{"p":"https://mezcal.sh","edicts":[["899284:20","1000000000",1]]}

Payload hex
7b2270223a2268747470733a2f2f6d657a63616c2e7368222c22656469637473223a5b5b223839393238343a3230222c2231303030303030303030222c315d5d7d

Transaction shape. 2 outputs: recipient, OP_RETURN at index 1

Expected outcome. 1000000000 base units are allocated to the OP_RETURN output and destroyed (A-8, B-1). The remainder sweeps to vout 0.

V-8 · valid

Object form edict

{"p":"mezcal","edicts":[{"id":"899284:20","amount":"100","output":0}]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b7b226964223a223839393238343a3230222c22616d6f756e74223a22313030222c226f7574707574223a307d5d7d

Transaction shape. 3 outputs

Expected outcome. Identical in effect to V-1. The object and tuple forms are equivalent (P-4), and the object form costs more bytes.

V-10 · valid

Over-allocation is clamped

{"p":"mezcal","edicts":[["899284:20","999999999999999",0]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b223839393238343a3230222c22393939393939393939393939393939222c305d5d7d

Transaction shape. 2 outputs: recipient, OP_RETURN

Expected outcome. If the pool holds less than the stated amount, the edict is reduced to the pool (A-6). The transaction is not a cenotaph.

Cenotaph payloads

Each of these makes the whole transaction a cenotaph. The Bitcoin transaction still confirms and still pays its fee; every Mezcal balance carried by its inputs is destroyed.

X-a · cenotaph

Not JSON

hello mezcal

Payload hex
68656c6c6f206d657a63616c

Rule. C-6

Expected outcome. Cenotaph. The payload decodes as UTF-8 but does not parse as JSON. Every Mezcal balance on the inputs is burnt.

X-b · cenotaph

Top level is an array

[{"p":"mezcal"}]

Payload hex
5b7b2270223a226d657a63616c227d5d

Rule. P-1

Expected outcome. Cenotaph. The parsed value must be an object.

X-c · cenotaph

Unknown top-level key

{"p":"mezcal","ops":[]}

Payload hex
7b2270223a226d657a63616c222c226f7073223a5b5d7d

Rule. P-2

Expected outcome. Cenotaph. Validation is strict; an unknown key is fatal.

X-d · cenotaph

Wrong protocol tag

{"p":"https://mezcal.sh/","edicts":[["1:0","1",0]]}

Payload hex
7b2270223a2268747470733a2f2f6d657a63616c2e73682f222c22656469637473223a5b5b22313a30222c2231222c305d5d7d

Rule. P-3

Expected outcome. Cenotaph. A trailing slash is not one of the three accepted literals.

X-e · cenotaph

Amount as a JSON number

{"p":"mezcal","edicts":[["899284:20",100,0]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b223839393238343a3230222c3130302c305d5d7d

Rule. U-1

Expected outcome. Cenotaph. Amounts must be strings.

X-f · cenotaph

Output index equal to the output count

{"p":"mezcal","edicts":[["899284:20","100",3]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b223839393238343a3230222c22313030222c335d5d7d

Rule. A-1, X-7

Expected outcome. Cenotaph. With 3 outputs the last index is 2. Index 3 is rejected before allocation runs.

X-g · cenotaph

Block zero id

{"p":"mezcal","edicts":[["0:5","100",0]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b22303a35222c22313030222c305d5d7d

Rule. I-5

Expected outcome. Cenotaph. 0:0 is the only permitted block-zero id.

X-h · cenotaph

Divisibility out of range

{"p":"mezcal","etching":{"mezcal":"over","symbol":"o","divisibility":19,"premine":"0","terms":null}}

Payload hex
7b2270223a226d657a63616c222c2265746368696e67223a7b226d657a63616c223a226f766572222c2273796d626f6c223a226f222c2264697669736962696c697479223a31392c227072656d696e65223a2230222c227465726d73223a6e756c6c7d7d

Rule. E-4

Expected outcome. Cenotaph. Divisibility must be 0 to 18.

X-i · cenotaph

Symbol of two code points

{"p":"mezcal","etching":{"mezcal":"two","symbol":"ab","divisibility":0,"premine":"0","terms":null}}

Payload hex
7b2270223a226d657a63616c222c2265746368696e67223a7b226d657a63616c223a2274776f222c2273796d626f6c223a226162222c2264697669736962696c697479223a302c227072656d696e65223a2230222c227465726d73223a6e756c6c7d7d

Rule. E-3

Expected outcome. Cenotaph. The symbol must be exactly one code point.

X-j · cenotaph

Name with an uppercase letter

{"p":"mezcal","etching":{"mezcal":"Agave","symbol":"a","divisibility":0,"premine":"0","terms":null}}

Payload hex
7b2270223a226d657a63616c222c2265746368696e67223a7b226d657a63616c223a224167617665222c2273796d626f6c223a2261222c2264697669736962696c697479223a302c227072656d696e65223a2230222c227465726d73223a6e756c6c7d7d

Rule. E-2

Expected outcome. Cenotaph. Names match ^[a-z0-9-]+$ only.

X-k · cenotaph

Missing protocol tag

{"edicts":[["899284:20","100",0]]}

Payload hex
7b22656469637473223a5b5b223839393238343a3230222c22313030222c305d5d7d

Rule. P-3

Expected outcome. Cenotaph. p is required.

Payloads that do nothing, safely

These are the cases most easily mistaken for cenotaphs. The instruction is valid, the operation simply has no effect, and no balance is burnt.

N-1 · ignored, not burnt

Mint of an unknown asset

{"p":"mezcal","mint":"999999:0"}

Payload hex
7b2270223a226d657a63616c222c226d696e74223a223939393939393a30227d

Rule. M-1

Expected outcome. Nothing is minted. The payload is valid, so nothing is burnt and balances sweep normally.

N-2 · ignored, not burnt

Etching a name already taken

{"p":"mezcal","etching":{"mezcal":"taco","symbol":"t","divisibility":0,"premine":"1000","terms":null}}

Payload hex
7b2270223a226d657a63616c222c2265746368696e67223a7b226d657a63616c223a227461636f222c2273796d626f6c223a2274222c2264697669736962696c697479223a302c227072656d696e65223a2231303030222c227465726d73223a6e756c6c7d7d

Rule. E-6

Expected outcome. The etching is ignored, including its premine. No cenotaph, no burn.

N-3 · ignored, not burnt

Edict for an asset with no balance here

{"p":"mezcal","edicts":[["1:0","100",0]]}

Payload hex
7b2270223a226d657a63616c222c22656469637473223a5b5b22313a30222c22313030222c305d5d7d

Rule. A-4

Expected outcome. The edict is skipped. Balances of other assets still sweep by R-1.

N-4 · ignored, not burnt

No OP_RETURN output at all

No OP_RETURN output.

Rule. C-2

Expected outcome. Not a cenotaph. Balances on the inputs sweep to the first output.

Using these in a test suite

  1. Build a transaction with the stated output shape, putting the payload in an OP_RETURN output with a single push.
  2. Assert the decoded result: a parsed mezcalstone, or a cenotaph flag.
  3. Assert the balance movement per output, in base units, as an exact integer.
  4. For the cenotaph cases, assert that every input balance is burnt, not merely unmoved.
  5. For the ignored cases, assert the opposite: nothing burnt, and the remainder swept by the pointer rule.

If your implementation disagrees with a vector, the specification page names the rule behind it. If you believe a vector is wrong, open an issue on this repository with the transaction you tested against.