Skip to main content

bitcoin_primitives/
opcodes.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Bitcoin script opcodes.
4//!
5//! Bitcoin's script uses a stack-based assembly language. This module defines
6//! all of the opcodes for that language.
7
8#![allow(non_camel_case_types)]
9
10#[cfg(feature = "alloc")]
11use core::fmt;
12
13/// A script opcode.
14///
15/// We do not implement `Ord` on this type because there is no natural ordering on opcodes, but there
16/// may appear to be one (e.g. because all the push opcodes appear in a consecutive block) and we
17/// don't want to encourage subtly buggy code.
18///
19/// <details>
20///   <summary>Example of Core bug caused by assuming ordering</summary>
21///
22///   Bitcoin Core's `IsPushOnly` considers `OP_RESERVED` to be a "push code", allowing this opcode
23///   in contexts where only pushes are supposed to be allowed.
24/// </details>
25#[derive(Debug, Copy, Clone, PartialEq, Eq)]
26pub struct Opcode {
27    code: u8,
28}
29
30impl Opcode {
31    /// Encodes [`Opcode`] as a byte.
32    #[inline]
33    pub const fn to_u8(self) -> u8 { self.code }
34
35    /// Constructs an [`Opcode`] from a byte.
36    #[inline]
37    pub const fn from_u8(b: u8) -> Self { Self { code: b } }
38}
39
40impl From<u8> for Opcode {
41    #[inline]
42    fn from(b: u8) -> Self { Self::from_u8(b) }
43}
44
45impl From<Opcode> for u8 {
46    #[inline]
47    fn from(op: Opcode) -> Self { op.to_u8() }
48}
49
50macro_rules! all_opcodes {
51    ($($op:ident => $val:expr, $doc:expr);* $(;)?) => {
52        /// Enables wildcard imports to bring into scope all opcodes and nothing else.
53        ///
54        /// The `all` module is provided so one can use a wildcard import `use primitives::opcodes::all::*`
55        /// to get all the `OP_FOO` opcodes without getting other types defined in `opcodes` (e.g. `Opcode`).
56        ///
57        /// This module is guaranteed to never contain anything except opcode constants and all opcode
58        /// constants are guaranteed to begin with `OP_`.
59        pub mod all {
60            use super::Opcode;
61            $(
62                #[doc = $doc]
63                pub const $op: Opcode = Opcode::from_u8($val);
64            )*
65        }
66    }
67}
68
69all_opcodes! {
70    OP_1NEGATE => 0x4f, "Push the array `0x81` onto the stack.";
71    OP_1 => 0x51, "Push the array `0x01` onto the stack.";
72    OP_2 => 0x52, "Push the array `0x02` onto the stack.";
73    OP_3 => 0x53, "Push the array `0x03` onto the stack.";
74    OP_4 => 0x54, "Push the array `0x04` onto the stack.";
75    OP_5 => 0x55, "Push the array `0x05` onto the stack.";
76    OP_6 => 0x56, "Push the array `0x06` onto the stack.";
77    OP_7 => 0x57, "Push the array `0x07` onto the stack.";
78    OP_8 => 0x58, "Push the array `0x08` onto the stack.";
79    OP_9 => 0x59, "Push the array `0x09` onto the stack.";
80    OP_10 => 0x5a, "Push the array `0x0a` onto the stack.";
81    OP_11 => 0x5b, "Push the array `0x0b` onto the stack.";
82    OP_12 => 0x5c, "Push the array `0x0c` onto the stack.";
83    OP_13 => 0x5d, "Push the array `0x0d` onto the stack.";
84    OP_14 => 0x5e, "Push the array `0x0e` onto the stack.";
85    OP_15 => 0x5f, "Push the array `0x0f` onto the stack.";
86    OP_16 => 0x60, "Push the array `0x10` onto the stack.";
87    OP_NOP => 0x61, "Does nothing.";
88    OP_IF => 0x63, "Pop and execute the next statements if a nonzero element was popped.";
89    OP_NOTIF => 0x64, "Pop and execute the next statements if a zero element was popped.";
90    OP_ELSE => 0x67, "Execute statements if those after the previous `OP_IF` were not, and vice-versa. \
91             If there is no previous `OP_IF`, this acts as a RETURN.";
92    OP_ENDIF => 0x68, "Pop and execute the next statements if a zero element was popped.";
93    OP_VERIFY => 0x69, "If the top value is zero or the stack is empty, fail; otherwise, pop the stack.";
94    OP_RETURN => 0x6a, "Fail the script immediately. (Must be executed.).";
95    OP_TOALTSTACK => 0x6b, "Pop one element from the main stack onto the alt stack.";
96    OP_FROMALTSTACK => 0x6c, "Pop one element from the alt stack onto the main stack.";
97    OP_2DROP => 0x6d, "Drops the top two stack items.";
98    OP_2DUP => 0x6e, "Duplicates the top two stack items as `AB` -> `ABAB`.";
99    OP_3DUP => 0x6f, "Duplicates the top three stack items as `ABC` -> `ABCABC`.";
100    OP_2OVER => 0x70, "Duplicates the third and fourth items from the top of the stack.";
101    OP_2ROT => 0x71, "Moves the two stack items four spaces back to the front, as `xxxxAB` -> `ABxxxx`.";
102    OP_2SWAP => 0x72, "Swaps the top two pairs, as `ABCD` -> `CDAB`.";
103    OP_IFDUP => 0x73, "Duplicate the top stack element unless it is zero.";
104    OP_DEPTH => 0x74, "Push the current number of stack items onto the stack.";
105    OP_DROP => 0x75, "Drops the top stack item.";
106    OP_DUP => 0x76, "Duplicates the top stack item.";
107    OP_NIP => 0x77, "Drops the second-to-top stack item.";
108    OP_OVER => 0x78, "Copies the second-to-top stack item, as `xA` -> `AxA`.";
109    OP_PICK => 0x79, "Pop the top stack element as N. Copy the Nth stack element to the top.";
110    OP_ROLL => 0x7a, "Pop the top stack element as N. Move the Nth stack element to the top.";
111    OP_ROT => 0x7b, "Rotate the top three stack items, as `[top next1 next2]` -> `[next2 top next1]`.";
112    OP_SWAP => 0x7c, "Swap the top two stack items.";
113    OP_TUCK => 0x7d, "Copy the top stack item to before the second item, as `[top next]` -> `[top next top]`.";
114    OP_SIZE => 0x82, "Pushes the length of the top stack item onto the stack.";
115    OP_EQUAL => 0x87, "Pushes 1 if the inputs are exactly equal, 0 otherwise.";
116    OP_EQUALVERIFY => 0x88, "Returns success if the inputs are exactly equal, failure otherwise.";
117    OP_1ADD => 0x8b, "Increment the top stack element in place.";
118    OP_1SUB => 0x8c, "Decrement the top stack element in place.";
119    OP_NEGATE => 0x8f, "Multiply the top stack item by -1 in place.";
120    OP_ABS => 0x90, "Absolute value the top stack item in place.";
121    OP_NOT => 0x91, "Map 0 to 1 and everything else to 0, in place.";
122    OP_0NOTEQUAL => 0x92, "Map 0 to 0 and everything else to 1, in place.";
123    OP_ADD => 0x93, "Pop two stack items and push their sum.";
124    OP_SUB => 0x94, "Pop two stack items and push the second minus the top.";
125    OP_BOOLAND => 0x9a, "Pop the top two stack items and push 1 if both are nonzero, else push 0.";
126    OP_BOOLOR => 0x9b, "Pop the top two stack items and push 1 if either is nonzero, else push 0.";
127    OP_NUMEQUAL => 0x9c, "Pop the top two stack items and push 1 if both are numerically equal, else push 0.";
128    OP_NUMEQUALVERIFY => 0x9d, "Pop the top two stack items and return success if both are numerically equal, else return failure.";
129    OP_NUMNOTEQUAL => 0x9e, "Pop the top two stack items and push 0 if both are numerically equal, else push 1.";
130    OP_LESSTHAN  => 0x9f, "Pop the top two items; push 1 if the second is less than the top, 0 otherwise.";
131    OP_GREATERTHAN  => 0xa0, "Pop the top two items; push 1 if the second is greater than the top, 0 otherwise.";
132    OP_LESSTHANOREQUAL  => 0xa1, "Pop the top two items; push 1 if the second is <= the top, 0 otherwise.";
133    OP_GREATERTHANOREQUAL  => 0xa2, "Pop the top two items; push 1 if the second is >= the top, 0 otherwise.";
134    OP_MIN => 0xa3, "Pop the top two items; push the smaller.";
135    OP_MAX => 0xa4, "Pop the top two items; push the larger.";
136    OP_WITHIN => 0xa5, "Pop the top three items; if the top is >= the second and < the third, push 1, otherwise push 0.";
137    OP_RIPEMD160 => 0xa6, "Pop the top stack item and push its RIPEMD160 hash.";
138    OP_SHA1 => 0xa7, "Pop the top stack item and push its SHA1 hash.";
139    OP_SHA256 => 0xa8, "Pop the top stack item and push its SHA256 hash.";
140    OP_HASH160 => 0xa9, "Pop the top stack item and push its RIPEMD(SHA256) hash.";
141    OP_HASH256 => 0xaa, "Pop the top stack item and push its SHA256(SHA256) hash.";
142    OP_CODESEPARATOR => 0xab, "Ignore this and everything preceding when deciding what to sign when signature-checking.";
143    OP_CHECKSIG => 0xac, "<https://en.bitcoin.it/wiki/OP_CHECKSIG> pushing 1/0 for success/failure.";
144    OP_CHECKSIGVERIFY => 0xad, "<https://en.bitcoin.it/wiki/OP_CHECKSIG> returning success/failure.";
145    OP_CHECKMULTISIG => 0xae, "Pop N, N pubkeys, M, M signatures, a dummy (due to bug in reference code), \
146                      and verify that all M signatures are valid. Push 1 for 'all valid', 0 otherwise.";
147    OP_CHECKMULTISIGVERIFY => 0xaf, "Like the above but return success/failure.";
148    OP_CHECKSIGADD => 0xba, "`OP_CHECKSIGADD` post tapscript.";
149}
150
151/// Read the following byte as a length, and read the following
152/// bytes as a push of that length.
153#[cfg(feature = "alloc")]
154pub(crate) const OP_PUSHDATA1: u8 = 0x4c;
155
156/// Read the following 2 bytes as a little-endian length, and read the following
157/// bytes as a push of that length.
158#[cfg(feature = "alloc")]
159pub(crate) const OP_PUSHDATA2: u8 = 0x4d;
160
161/// Read the following 4 bytes as a little-endian length, and read the following
162/// bytes as a push of that length.
163#[cfg(any(feature = "alloc", test))]
164pub(crate) const OP_PUSHDATA4: u8 = 0x4e;
165
166/// Push an empty array onto the stack.
167pub(crate) const OP_PUSHBYTES_0: Opcode = Opcode::from_u8(0x00);
168
169/// Push the next 2 bytes as an array onto the stack.
170#[cfg(feature = "alloc")]
171pub(crate) const OP_PUSHBYTES_2: Opcode = Opcode::from_u8(0x02);
172
173/// Push the next 20 bytes as an array onto the stack.
174#[cfg(feature = "alloc")]
175pub(crate) const OP_PUSHBYTES_20: Opcode = Opcode::from_u8(0x14);
176
177/// Push the next 32 bytes as an array onto the stack.
178#[cfg(feature = "alloc")]
179pub(crate) const OP_PUSHBYTES_32: Opcode = Opcode::from_u8(0x20);
180
181/// Format a byte as a script opcode.
182#[cfg(feature = "alloc")]
183pub(crate) fn fmt_opcode(op: u8, f: &mut fmt::Formatter) -> fmt::Result {
184    match op {
185        0x00 => f.write_str("OP_0"),
186        0x01..=0x4b => write!(f, "OP_PUSHBYTES_{}", op),
187        0x4c => f.write_str("OP_PUSHDATA1"),
188        0x4d => f.write_str("OP_PUSHDATA2"),
189        0x4e => f.write_str("OP_PUSHDATA4"),
190        0x4f => f.write_str("OP_1NEGATE"),
191        0x50 => f.write_str("OP_RESERVED"),
192        0x51..=0x60 => write!(f, "OP_{}", op - 0x50),
193        0x61 => f.write_str("OP_NOP"),
194        0x62 => f.write_str("OP_VER"),
195        0x63 => f.write_str("OP_IF"),
196        0x64 => f.write_str("OP_NOTIF"),
197        0x65 => f.write_str("OP_VERIF"),
198        0x66 => f.write_str("OP_VERNOTIF"),
199        0x67 => f.write_str("OP_ELSE"),
200        0x68 => f.write_str("OP_ENDIF"),
201        0x69 => f.write_str("OP_VERIFY"),
202        0x6a => f.write_str("OP_RETURN"),
203        0x6b => f.write_str("OP_TOALTSTACK"),
204        0x6c => f.write_str("OP_FROMALTSTACK"),
205        0x6d => f.write_str("OP_2DROP"),
206        0x6e => f.write_str("OP_2DUP"),
207        0x6f => f.write_str("OP_3DUP"),
208        0x70 => f.write_str("OP_2OVER"),
209        0x71 => f.write_str("OP_2ROT"),
210        0x72 => f.write_str("OP_2SWAP"),
211        0x73 => f.write_str("OP_IFDUP"),
212        0x74 => f.write_str("OP_DEPTH"),
213        0x75 => f.write_str("OP_DROP"),
214        0x76 => f.write_str("OP_DUP"),
215        0x77 => f.write_str("OP_NIP"),
216        0x78 => f.write_str("OP_OVER"),
217        0x79 => f.write_str("OP_PICK"),
218        0x7a => f.write_str("OP_ROLL"),
219        0x7b => f.write_str("OP_ROT"),
220        0x7c => f.write_str("OP_SWAP"),
221        0x7d => f.write_str("OP_TUCK"),
222        0x7e => f.write_str("OP_CAT"),
223        0x7f => f.write_str("OP_SUBSTR"),
224        0x80 => f.write_str("OP_LEFT"),
225        0x81 => f.write_str("OP_RIGHT"),
226        0x82 => f.write_str("OP_SIZE"),
227        0x83 => f.write_str("OP_INVERT"),
228        0x84 => f.write_str("OP_AND"),
229        0x85 => f.write_str("OP_OR"),
230        0x86 => f.write_str("OP_XOR"),
231        0x87 => f.write_str("OP_EQUAL"),
232        0x88 => f.write_str("OP_EQUALVERIFY"),
233        0x89 => f.write_str("OP_RESERVED1"),
234        0x8a => f.write_str("OP_RESERVED2"),
235        0x8b => f.write_str("OP_1ADD"),
236        0x8c => f.write_str("OP_1SUB"),
237        0x8d => f.write_str("OP_2MUL"),
238        0x8e => f.write_str("OP_2DIV"),
239        0x8f => f.write_str("OP_NEGATE"),
240        0x90 => f.write_str("OP_ABS"),
241        0x91 => f.write_str("OP_NOT"),
242        0x92 => f.write_str("OP_0NOTEQUAL"),
243        0x93 => f.write_str("OP_ADD"),
244        0x94 => f.write_str("OP_SUB"),
245        0x95 => f.write_str("OP_MUL"),
246        0x96 => f.write_str("OP_DIV"),
247        0x97 => f.write_str("OP_MOD"),
248        0x98 => f.write_str("OP_LSHIFT"),
249        0x99 => f.write_str("OP_RSHIFT"),
250        0x9a => f.write_str("OP_BOOLAND"),
251        0x9b => f.write_str("OP_BOOLOR"),
252        0x9c => f.write_str("OP_NUMEQUAL"),
253        0x9d => f.write_str("OP_NUMEQUALVERIFY"),
254        0x9e => f.write_str("OP_NUMNOTEQUAL"),
255        0x9f => f.write_str("OP_LESSTHAN"),
256        0xa0 => f.write_str("OP_GREATERTHAN"),
257        0xa1 => f.write_str("OP_LESSTHANOREQUAL"),
258        0xa2 => f.write_str("OP_GREATERTHANOREQUAL"),
259        0xa3 => f.write_str("OP_MIN"),
260        0xa4 => f.write_str("OP_MAX"),
261        0xa5 => f.write_str("OP_WITHIN"),
262        0xa6 => f.write_str("OP_RIPEMD160"),
263        0xa7 => f.write_str("OP_SHA1"),
264        0xa8 => f.write_str("OP_SHA256"),
265        0xa9 => f.write_str("OP_HASH160"),
266        0xaa => f.write_str("OP_HASH256"),
267        0xab => f.write_str("OP_CODESEPARATOR"),
268        0xac => f.write_str("OP_CHECKSIG"),
269        0xad => f.write_str("OP_CHECKSIGVERIFY"),
270        0xae => f.write_str("OP_CHECKMULTISIG"),
271        0xaf => f.write_str("OP_CHECKMULTISIGVERIFY"),
272        0xb1 => f.write_str("OP_CLTV"),
273        0xb2 => f.write_str("OP_CSV"),
274        0xb0..=0xb9 => write!(f, "OP_NOP{}", op - 0xb0 + 1),
275        0xba => f.write_str("OP_CHECKSIGADD"),
276        0xbb..=0xfe => write!(f, "OP_RETURN_{}", op),
277        0xff => f.write_str("OP_INVALIDOPCODE"),
278    }
279}
280
281#[cfg(test)]
282mod tests {
283    use super::*;
284
285    #[test]
286    fn opcode_to_u8_from_u8_roundtrip() {
287        for b in 0..=u8::MAX {
288            let op = Opcode::from_u8(b);
289            assert_eq!(op.to_u8(), b);
290
291            let op = Opcode::from(b);
292            assert_eq!(u8::from(op), b);
293        }
294    }
295}