UNPKG

4.67 kBJavaScriptView Raw
1'use strict';
2
3var _ = require('lodash');
4var $ = require('./util/preconditions');
5var BufferUtil = require('./util/buffer');
6var JSUtil = require('./util/js');
7
8function Opcode(num) {
9 if (!(this instanceof Opcode)) {
10 return new Opcode(num);
11 }
12
13 var value;
14
15 if (_.isNumber(num)) {
16 value = num;
17 } else if (_.isString(num)) {
18 value = Opcode.map[num];
19 } else {
20 throw new TypeError('Unrecognized num type: "' + typeof(num) + '" for Opcode');
21 }
22
23 JSUtil.defineImmutable(this, {
24 num: value
25 });
26
27 return this;
28}
29
30Opcode.fromBuffer = function(buf) {
31 $.checkArgument(BufferUtil.isBuffer(buf));
32 return new Opcode(Number('0x' + buf.toString('hex')));
33};
34
35Opcode.fromNumber = function(num) {
36 $.checkArgument(_.isNumber(num));
37 return new Opcode(num);
38};
39
40Opcode.fromString = function(str) {
41 $.checkArgument(_.isString(str));
42 var value = Opcode.map[str];
43 if (typeof value === 'undefined') {
44 throw new TypeError('Invalid opcodestr');
45 }
46 return new Opcode(value);
47};
48
49Opcode.prototype.toHex = function() {
50 return this.num.toString(16);
51};
52
53Opcode.prototype.toBuffer = function() {
54 return Buffer.from(this.toHex(), 'hex');
55};
56
57Opcode.prototype.toNumber = function() {
58 return this.num;
59};
60
61Opcode.prototype.toString = function() {
62 var str = Opcode.reverseMap[this.num];
63 if (typeof str === 'undefined') {
64 throw new Error('Opcode does not have a string representation');
65 }
66 return str;
67};
68
69Opcode.smallInt = function(n) {
70 $.checkArgument(_.isNumber(n), 'Invalid Argument: n should be number');
71 $.checkArgument(n >= 0 && n <= 16, 'Invalid Argument: n must be between 0 and 16');
72 if (n === 0) {
73 return Opcode('OP_0');
74 }
75 return new Opcode(Opcode.map.OP_1 + n - 1);
76};
77
78Opcode.map = {
79 // push value
80 OP_FALSE: 0,
81 OP_0: 0,
82 OP_PUSHDATA1: 76,
83 OP_PUSHDATA2: 77,
84 OP_PUSHDATA4: 78,
85 OP_1NEGATE: 79,
86 OP_RESERVED: 80,
87 OP_TRUE: 81,
88 OP_1: 81,
89 OP_2: 82,
90 OP_3: 83,
91 OP_4: 84,
92 OP_5: 85,
93 OP_6: 86,
94 OP_7: 87,
95 OP_8: 88,
96 OP_9: 89,
97 OP_10: 90,
98 OP_11: 91,
99 OP_12: 92,
100 OP_13: 93,
101 OP_14: 94,
102 OP_15: 95,
103 OP_16: 96,
104
105 // control
106 OP_NOP: 97,
107 OP_VER: 98,
108 OP_IF: 99,
109 OP_NOTIF: 100,
110 OP_VERIF: 101,
111 OP_VERNOTIF: 102,
112 OP_ELSE: 103,
113 OP_ENDIF: 104,
114 OP_VERIFY: 105,
115 OP_RETURN: 106,
116
117 // stack ops
118 OP_TOALTSTACK: 107,
119 OP_FROMALTSTACK: 108,
120 OP_2DROP: 109,
121 OP_2DUP: 110,
122 OP_3DUP: 111,
123 OP_2OVER: 112,
124 OP_2ROT: 113,
125 OP_2SWAP: 114,
126 OP_IFDUP: 115,
127 OP_DEPTH: 116,
128 OP_DROP: 117,
129 OP_DUP: 118,
130 OP_NIP: 119,
131 OP_OVER: 120,
132 OP_PICK: 121,
133 OP_ROLL: 122,
134 OP_ROT: 123,
135 OP_SWAP: 124,
136 OP_TUCK: 125,
137
138 // splice ops
139 OP_CAT: 126,
140 OP_SUBSTR: 127,
141 OP_LEFT: 128,
142 OP_RIGHT: 129,
143 OP_SIZE: 130,
144
145 // bit logic
146 OP_INVERT: 131,
147 OP_AND: 132,
148 OP_OR: 133,
149 OP_XOR: 134,
150 OP_EQUAL: 135,
151 OP_EQUALVERIFY: 136,
152 OP_RESERVED1: 137,
153 OP_RESERVED2: 138,
154
155 // numeric
156 OP_1ADD: 139,
157 OP_1SUB: 140,
158 OP_2MUL: 141,
159 OP_2DIV: 142,
160 OP_NEGATE: 143,
161 OP_ABS: 144,
162 OP_NOT: 145,
163 OP_0NOTEQUAL: 146,
164
165 OP_ADD: 147,
166 OP_SUB: 148,
167 OP_MUL: 149,
168 OP_DIV: 150,
169 OP_MOD: 151,
170 OP_LSHIFT: 152,
171 OP_RSHIFT: 153,
172
173 OP_BOOLAND: 154,
174 OP_BOOLOR: 155,
175 OP_NUMEQUAL: 156,
176 OP_NUMEQUALVERIFY: 157,
177 OP_NUMNOTEQUAL: 158,
178 OP_LESSTHAN: 159,
179 OP_GREATERTHAN: 160,
180 OP_LESSTHANOREQUAL: 161,
181 OP_GREATERTHANOREQUAL: 162,
182 OP_MIN: 163,
183 OP_MAX: 164,
184
185 OP_WITHIN: 165,
186
187 // crypto
188 OP_RIPEMD160: 166,
189 OP_SHA1: 167,
190 OP_SHA256: 168,
191 OP_HASH160: 169,
192 OP_HASH256: 170,
193 OP_CODESEPARATOR: 171,
194 OP_CHECKSIG: 172,
195 OP_CHECKSIGVERIFY: 173,
196 OP_CHECKMULTISIG: 174,
197 OP_CHECKMULTISIGVERIFY: 175,
198
199 OP_CHECKLOCKTIMEVERIFY: 177,
200 OP_CHECKSEQUENCEVERIFY: 178,
201
202 // expansion
203 OP_NOP1: 176,
204 OP_NOP2: 177,
205 OP_NOP3: 178,
206 OP_NOP4: 179,
207 OP_NOP5: 180,
208 OP_NOP6: 181,
209 OP_NOP7: 182,
210 OP_NOP8: 183,
211 OP_NOP9: 184,
212 OP_NOP10: 185,
213
214 // template matching params
215 OP_PUBKEYHASH: 253,
216 OP_PUBKEY: 254,
217 OP_INVALIDOPCODE: 255
218};
219
220Opcode.reverseMap = [];
221
222for (var k in Opcode.map) {
223 Opcode.reverseMap[Opcode.map[k]] = k;
224}
225
226// Easier access to opcodes
227_.extend(Opcode, Opcode.map);
228
229/**
230 * @returns true if opcode is one of OP_0, OP_1, ..., OP_16
231 */
232Opcode.isSmallIntOp = function(opcode) {
233 if (opcode instanceof Opcode) {
234 opcode = opcode.toNumber();
235 }
236 return ((opcode === Opcode.map.OP_0) ||
237 ((opcode >= Opcode.map.OP_1) && (opcode <= Opcode.map.OP_16)));
238};
239
240/**
241 * Will return a string formatted for the console
242 *
243 * @returns {string} Script opcode
244 */
245Opcode.prototype.inspect = function() {
246 return '<Opcode: ' + this.toString() + ', hex: '+this.toHex()+', decimal: '+this.num+'>';
247};
248
249module.exports = Opcode;