1 | 'use strict';
|
2 |
|
3 | var _ = require('lodash');
|
4 | var $ = require('./util/preconditions');
|
5 | var BufferUtil = require('./util/buffer');
|
6 | var JSUtil = require('./util/js');
|
7 |
|
8 | function 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 |
|
30 | Opcode.fromBuffer = function(buf) {
|
31 | $.checkArgument(BufferUtil.isBuffer(buf));
|
32 | return new Opcode(Number('0x' + buf.toString('hex')));
|
33 | };
|
34 |
|
35 | Opcode.fromNumber = function(num) {
|
36 | $.checkArgument(_.isNumber(num));
|
37 | return new Opcode(num);
|
38 | };
|
39 |
|
40 | Opcode.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 |
|
49 | Opcode.prototype.toHex = function() {
|
50 | return this.num.toString(16);
|
51 | };
|
52 |
|
53 | Opcode.prototype.toBuffer = function() {
|
54 | return Buffer.from(this.toHex(), 'hex');
|
55 | };
|
56 |
|
57 | Opcode.prototype.toNumber = function() {
|
58 | return this.num;
|
59 | };
|
60 |
|
61 | Opcode.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 |
|
69 | Opcode.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 |
|
78 | Opcode.map = {
|
79 |
|
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 |
|
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 |
|
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 |
|
139 | OP_CAT: 126,
|
140 | OP_SUBSTR: 127,
|
141 | OP_LEFT: 128,
|
142 | OP_RIGHT: 129,
|
143 | OP_SIZE: 130,
|
144 |
|
145 |
|
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 |
|
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 |
|
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 |
|
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 |
|
215 | OP_PUBKEYHASH: 253,
|
216 | OP_PUBKEY: 254,
|
217 | OP_INVALIDOPCODE: 255
|
218 | };
|
219 |
|
220 | Opcode.reverseMap = [];
|
221 |
|
222 | for (var k in Opcode.map) {
|
223 | Opcode.reverseMap[Opcode.map[k]] = k;
|
224 | }
|
225 |
|
226 |
|
227 | _.extend(Opcode, Opcode.map);
|
228 |
|
229 |
|
230 |
|
231 |
|
232 | Opcode.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 |
|
242 |
|
243 |
|
244 |
|
245 | Opcode.prototype.inspect = function() {
|
246 | return '<Opcode: ' + this.toString() + ', hex: '+this.toHex()+', decimal: '+this.num+'>';
|
247 | };
|
248 |
|
249 | module.exports = Opcode;
|