BRC-106 Scripts

Bitcoin Script ASM Format

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).

Freddie Honohan (freddie@yenpoint.jp)

How it connects

Relationships

Authoritative content mirror

Full upstream text

View source ↗
Rendered from scripts/0106.md at the indexed upstream commit

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

  1. It is important that ASM format scripts operate correctly regardless of where they were produced or processed.
  2. The Hexadecimal and Binary representations are defined in BRC-14.
  3. 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
  1. Other discrepancies were found and documented here and rules are set out below to deal with them.

Implementation

  1. The logic dealing with Bitcoin Script ASM is to be standardised across libraries and languages as described hereunder.
  2. 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
  1. However op-codes with several names must be output into the most human-readable format (e.g. OP_0 will always output as OP_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")
  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