Bitcoin Script ASM Format
Every library prints Bitcoin script in a slightly different readable form, so output from one tool is not accepted by another. This fixes one form so scripts can be moved between tools and languages.
Summary
- Why
- Different code libraries produce inconsistent text representations of the same Bitcoin Script, which breaks comparisons and interoperability across tools.
- What
- BRC-106 is a standard that fixes exactly which text name each Bitcoin Script opcode must use when converted to and from its human-readable ASM form.
- How
- A library parses any valid alias of an opcode (such as OP_0 or OP_FALSE) into the same underlying byte, but always outputs the single designated human-readable name (such as OP_FALSE) when converting that byte back to ASM text.
What this lets you do
- Parse any known opcode alias into its correct byte value
- Serialize a script to ASM using one consistent name per opcode
- Compare ASM output from different libraries and expect a byte-for-byte match
- Look up any opcode's canonical ASM name and hex value in a shared table
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
Reference for an AI
Everything an assistant needs to answer questions about BRC-106 accurately, including what it depends on.
The specification
Abstract
This proposal introduces a standardised method of dealing with the ASM representation of Bitcoin Script across the ecosystem language libraries (Py-SDK, TS-SDK, Go-SDK, Teranode etc).
Motivation
The purpose of this proposal is to provide a generalised standard in order for deterministic translation of Bitcoin Script to and from ASM for cross-language compatibility.
Currently, different implementations may produce inconsistent ASM representations for the same script. For example, the boolean value false might be rendered as OP_0, OP_FALSE depending on the library used. This lack of standardisation creates interoperability issues when scripts are shared across different tools and platforms.
Specification
- It is important that ASM format scripts operate correctly regardless of where they were produced or processed.
- The Hexadecimal and Binary representations are defined in BRC-14.
- Since ASM format is primarily used for human-readability, op-codes with multiple representations like the boolean pair
[OP_0, OP_1]are to be represented as their english full-name counterpart e.g.[OP_FALSE, OP_TRUE]Example:
Hex: 0x00 0x51
ASM: OP_FALSE OP_TRUE
Not: OP_0 OP_1
- Other discrepancies were found and documented here and rules are set out below to deal with them.
Implementation
- The logic dealing with Bitcoin Script ASM is to be standardised across libraries and languages as described hereunder.
- Op-Codes with several names must be parsed into the correct hex/binary byte despite the chosen ASM format name. Example Input Parsing:
// All of these should parse to 0x00
parseASM("OP_0") // ✓ valid
parseASM("OP_FALSE") // ✓ valid
// Both should output the same hex
parseASM("OP_0") === parseASM("OP_FALSE") // true
- However op-codes with several names must be output into the most human-readable format (e.g.
OP_0will always output asOP_FALSE). Example Output Serialization:
// Input hex, always outputs human-readable form
toASM(0x00) // "OP_FALSE" (not "OP_0")
toASM(0x51) // "OP_TRUE" (not "OP_1")
- Full Op-Code to Hex Table With Statuses
| Index | Word | Hex | Legacy | Chronicles |
|---|---|---|---|---|
| 0 | OP_FALSE | 0x00 | ✅ | ✅ |
| 1-75 | OP_PUSHDATA | 0x01-0x4b | ✅ | ✅ |
| 76 | OP_PUSHDATA1 | 0x4c | ✅ | ✅ |
| 77 | OP_PUSHDATA2 | 0x4d | ✅ | ✅ |
| 78 | OP_PUSHDATA4 | 0x4e | ✅ | ✅ |
| 79 | OP_1NEGATE | 0x4f | ✅ | ✅ |
| 80 | OP_RESERVED | 0x50 | Reserved | Reserved |
| 81 | OP_TRUE | 0x51 | ✅ | ✅ |
| 82 | OP_2 | 0x52 | ✅ | ✅ |
| 83 | OP_3 | 0x53 | ✅ | ✅ |
| 84 | OP_4 | 0x54 | ✅ | ✅ |
| 85 | OP_5 | 0x55 | ✅ | ✅ |
| 86 | OP_6 | 0x56 | ✅ | ✅ |
| 87 | OP_7 | 0x57 | ✅ | ✅ |
| 88 | OP_8 | 0x58 | ✅ | ✅ |
| 89 | OP_9 | 0x59 | ✅ | ✅ |
| 90 | OP_10 | 0x5a | ✅ | ✅ |
| 91 | OP_11 | 0x5b | ✅ | ✅ |
| 92 | OP_12 | 0x5c | ✅ | ✅ |
| 93 | OP_13 | 0x5d | ✅ | ✅ |
| 94 | OP_14 | 0x5e | ✅ | ✅ |
| 95 | OP_15 | 0x5f | ✅ | ✅ |
| 96 | OP_16 | 0x60 | ✅ | ✅ |
| 97 | OP_NOP | 0x61 | ✅ | ✅ |
| 98 | OP_VER | 0x62 | ❌ | ✅ |
| 99 | OP_IF | 0x63 | ✅ | ✅ |
| 100 | OP_NOTIF | 0x64 | ✅ | ✅ |
| 101 | OP_VERIF | 0x65 | ❌ | ✅ |
| 102 | OP_VERNOTIF | 0x66 | ❌ | ✅ |
| 103 | OP_ELSE | 0x67 | ✅ | ✅ |
| 104 | OP_ENDIF | 0x68 | ✅ | ✅ |
| 105 | OP_VERIFY | 0x69 | ✅ | ✅ |
| 106 | OP_RETURN | 0x6a | ✅ | ✅ |
| 107 | OP_TOALTSTACK | 0x6b | ✅ | ✅ |
| 108 | OP_FROMALTSTACK | 0x6c | ✅ | ✅ |
| 109 | OP_2DROP | 0x6d | ✅ | ✅ |
| 110 | OP_2DUP | 0x6e | ✅ | ✅ |
| 111 | OP_3DUP | 0x6f | ✅ | ✅ |
| 112 | OP_2OVER | 0x70 | ✅ | ✅ |
| 113 | OP_2ROT | 0x71 | ✅ | ✅ |
| 114 | OP_2SWAP | 0x72 | ✅ | ✅ |
| 115 | OP_IFDUP | 0x73 | ✅ | ✅ |
| 116 | OP_DEPTH | 0x74 | ✅ | ✅ |
| 117 | OP_DROP | 0x75 | ✅ | ✅ |
| 118 | OP_DUP | 0x76 | ✅ | ✅ |
| 119 | OP_NIP | 0x77 | ✅ | ✅ |
| 120 | OP_OVER | 0x78 | ✅ | ✅ |
| 121 | OP_PICK | 0x79 | ✅ | ✅ |
| 122 | OP_ROLL | 0x7a | ✅ | ✅ |
| 123 | OP_ROT | 0x7b | ✅ | ✅ |
| 124 | OP_SWAP | 0x7c | ✅ | ✅ |
| 125 | OP_TUCK | 0x7d | ✅ | ✅ |
| 126 | OP_CAT | 0x7e | ✅ | ✅ |
| 127 | OP_SPLIT | 0x7f | ✅ | ✅ |
| 128 | OP_NUM2BIN | 0x80 | ✅ | ✅ |
| 129 | OP_BIN2NUM | 0x81 | ✅ | ✅ |
| 130 | OP_SIZE | 0x82 | ✅ | ✅ |
| 131 | OP_INVERT | 0x83 | ✅ | ✅ |
| 132 | OP_AND | 0x84 | ✅ | ✅ |
| 133 | OP_OR | 0x85 | ✅ | ✅ |
| 134 | OP_XOR | 0x86 | ✅ | ✅ |
| 135 | OP_EQUAL | 0x87 | ✅ | ✅ |
| 136 | OP_EQUALVERIFY | 0x88 | ✅ | ✅ |
| 137 | OP_RESERVED1 | 0x89 | Reserved | Reserved |
| 138 | OP_RESERVED2 | 0x8a | Reserved | Reserved |
| 139 | OP_1ADD | 0x8b | ✅ | ✅ |
| 140 | OP_1SUB | 0x8c | ✅ | ✅ |
| 141 | OP_2MUL | 0x8d | ❌ | ✅ |
| 142 | OP_2DIV | 0x8e | ❌ | ✅ |
| 143 | OP_NEGATE | 0x8f | ✅ | ✅ |
| 144 | OP_ABS | 0x90 | ✅ | ✅ |
| 145 | OP_NOT | 0x91 | ✅ | ✅ |
| 146 | OP_0NOTEQUAL | 0x92 | ✅ | ✅ |
| 147 | OP_ADD | 0x93 | ✅ | ✅ |
| 148 | OP_SUB | 0x94 | ✅ | ✅ |
| 149 | OP_MUL | 0x95 | ✅ | ✅ |
| 150 | OP_DIV | 0x96 | ✅ | ✅ |
| 151 | OP_MOD | 0x97 | ✅ | ✅ |
| 152 | OP_LSHIFT | 0x98 | ✅ | ✅ |
| 153 | OP_RSHIFT | 0x99 | ✅ | ✅ |
| 154 | OP_BOOLAND | 0x9a | ✅ | ✅ |
| 155 | OP_BOOLOR | 0x9b | ✅ | ✅ |
| 156 | OP_NUMEQUAL | 0x9c | ✅ | ✅ |
| 157 | OP_NUMEQUALVERIFY | 0x9d | ✅ | ✅ |
| 158 | OP_NUMNOTEQUAL | 0x9e | ✅ | ✅ |
| 159 | OP_LESSTHAN | 0x9f | ✅ | ✅ |
| 160 | OP_GREATERTHAN | 0xa0 | ✅ | ✅ |
| 161 | OP_LESSTHANOREQUAL | 0xa1 | ✅ | ✅ |
| 162 | OP_GREATERTHANOREQUAL | 0xa2 | ✅ | ✅ |
| 163 | OP_MIN | 0xa3 | ✅ | ✅ |
| 164 | OP_MAX | 0xa4 | ✅ | ✅ |
| 165 | OP_WITHIN | 0xa5 | ✅ | ✅ |
| 166 | OP_RIPEMD160 | 0xa6 | ✅ | ✅ |
| 167 | OP_SHA1 | 0xa7 | ✅ | ✅ |
| 168 | OP_SHA256 | 0xa8 | ✅ | ✅ |
| 169 | OP_HASH160 | 0xa9 | ✅ | ✅ |
| 170 | OP_HASH256 | 0xaa | ✅ | ✅ |
| 171 | OP_CODESEPARATOR | 0xab | ✅ | ✅ |
| 172 | OP_CHECKSIG | 0xac | ✅ | ✅ |
| 173 | OP_CHECKSIGVERIFY | 0xad | ✅ | ✅ |
| 174 | OP_CHECKMULTISIG | 0xae | ✅ | ✅ |
| 175 | OP_CHECKMULTISIGVERIFY | 0xaf | ✅ | ✅ |
| 176 | OP_NOP1 | 0xb0 | ✅ | ✅ |
| 177 | OP_NOP2 | 0xb1 | ✅ | ✅ |
| 178 | OP_NOP3 | 0xb2 | ✅ | ✅ |
| 179 | OP_SUBSTR | 0xb3 | ❌ | ✅ |
| 180 | OP_LEFT | 0xb4 | ❌ | ✅ |
| 181 | OP_RIGHT | 0xb5 | ❌ | ✅ |
| 182 | OP_NOP4 | 0xb6 | ✅ | ✅ |
| 183 | OP_NOP5 | 0xb7 | ✅ | ✅ |
| 184 | OP_NOP6 | 0xb8 | ✅ | ✅ |
| 185 | OP_NOP7 | 0xb9 | ✅ | ✅ |
| 186 | OP_NOP8 | 0xba | ✅ | ✅ |
| 187 | OP_NOP9 | 0xbb | ✅ | ✅ |
| 188 | OP_NOP10 | 0xbc | ✅ | ✅ |
| 253 | OP_PUBKEYHASH | 0xfd | Pseudo | Pseudo |
| 254 | OP_PUBKEY | 0xfe | Pseudo | Pseudo |
| 255 | OP_INVALIDOPCODE | 0xff | Invalid | Invalid |
References
- <a name="footnote-1">BRC-14</a>: Bitcoin Script Binary and Hex Formats - Ty Everett (ty@projectbabbage.com)