2014-11-20 07:52:32 -08:00
|
|
|
'use strict';
|
|
|
|
|
2014-12-09 12:30:52 -08:00
|
|
|
var _ = require('lodash');
|
2014-12-11 08:27:42 -08:00
|
|
|
var $ = require('./util/preconditions');
|
2014-12-09 12:30:52 -08:00
|
|
|
|
2014-08-29 19:24:51 -07:00
|
|
|
function Opcode(num) {
|
2014-11-28 09:54:19 -08:00
|
|
|
if (!(this instanceof Opcode)) {
|
2014-08-29 19:24:51 -07:00
|
|
|
return new Opcode(num);
|
2014-11-28 09:54:19 -08:00
|
|
|
}
|
2014-08-31 20:38:39 -07:00
|
|
|
|
2014-12-11 16:12:26 -08:00
|
|
|
var value;
|
|
|
|
|
|
|
|
if (_.isNumber(num)) {
|
|
|
|
value = num;
|
|
|
|
} else if (_.isString(num)) {
|
|
|
|
value = Opcode.map[num];
|
|
|
|
} else {
|
|
|
|
throw new TypeError('Unrecognized num type: "' + typeof(num) + '" for Opcode');
|
2014-08-29 19:24:51 -07:00
|
|
|
}
|
|
|
|
|
2014-12-11 16:12:26 -08:00
|
|
|
Object.defineProperty(this, 'num', {
|
|
|
|
configurable: false,
|
|
|
|
value: value
|
|
|
|
});
|
2014-08-29 19:24:51 -07:00
|
|
|
|
2014-08-31 20:38:39 -07:00
|
|
|
return this;
|
2014-12-11 16:12:26 -08:00
|
|
|
}
|
2014-08-31 20:38:39 -07:00
|
|
|
|
2014-12-11 16:12:26 -08:00
|
|
|
Opcode.fromNumber = function(num) {
|
|
|
|
$.checkArgument(_.isNumber(num));
|
|
|
|
return new Opcode(num);
|
2014-08-31 20:38:39 -07:00
|
|
|
};
|
|
|
|
|
2014-12-11 16:12:26 -08:00
|
|
|
Opcode.fromString = function(str) {
|
2014-12-11 08:27:42 -08:00
|
|
|
$.checkArgument(_.isString(str));
|
2014-12-11 16:12:26 -08:00
|
|
|
var value = Opcode.map[str];
|
|
|
|
if (typeof value === 'undefined') {
|
|
|
|
throw new TypeError('Invalid opcodestr');
|
2014-12-11 08:27:42 -08:00
|
|
|
}
|
2014-12-11 16:12:26 -08:00
|
|
|
return new Opcode(value);
|
|
|
|
};
|
|
|
|
|
|
|
|
Opcode.prototype.toNumber = function() {
|
|
|
|
return this.num;
|
2014-08-31 20:38:39 -07:00
|
|
|
};
|
|
|
|
|
2014-08-29 19:24:51 -07:00
|
|
|
Opcode.prototype.toString = function() {
|
2014-09-01 20:00:54 -07:00
|
|
|
var str = Opcode.reverseMap[this.num];
|
2014-11-28 09:54:19 -08:00
|
|
|
if (typeof str === 'undefined') {
|
2014-09-01 20:00:54 -07:00
|
|
|
throw new Error('Opcode does not have a string representation');
|
2014-11-28 09:54:19 -08:00
|
|
|
}
|
2014-09-01 20:00:54 -07:00
|
|
|
return str;
|
2014-08-29 19:24:51 -07:00
|
|
|
};
|
|
|
|
|
2014-12-04 05:45:10 -08:00
|
|
|
Opcode.smallInt = function(n) {
|
2014-12-11 08:27:42 -08:00
|
|
|
$.checkArgument(n >= 0 && n <= 16, 'Invalid Argument: n must be between 0 and 16');
|
2014-12-04 05:45:10 -08:00
|
|
|
if (n === 0) {
|
|
|
|
return Opcode('OP_0');
|
|
|
|
}
|
|
|
|
return new Opcode(Opcode.map.OP_1 + n - 1);
|
|
|
|
};
|
|
|
|
|
2014-08-29 19:24:51 -07:00
|
|
|
Opcode.map = {
|
|
|
|
// push value
|
|
|
|
OP_FALSE: 0,
|
|
|
|
OP_0: 0,
|
|
|
|
OP_PUSHDATA1: 76,
|
|
|
|
OP_PUSHDATA2: 77,
|
|
|
|
OP_PUSHDATA4: 78,
|
|
|
|
OP_1NEGATE: 79,
|
|
|
|
OP_RESERVED: 80,
|
|
|
|
OP_TRUE: 81,
|
|
|
|
OP_1: 81,
|
|
|
|
OP_2: 82,
|
|
|
|
OP_3: 83,
|
|
|
|
OP_4: 84,
|
|
|
|
OP_5: 85,
|
|
|
|
OP_6: 86,
|
|
|
|
OP_7: 87,
|
|
|
|
OP_8: 88,
|
|
|
|
OP_9: 89,
|
|
|
|
OP_10: 90,
|
|
|
|
OP_11: 91,
|
|
|
|
OP_12: 92,
|
|
|
|
OP_13: 93,
|
|
|
|
OP_14: 94,
|
|
|
|
OP_15: 95,
|
|
|
|
OP_16: 96,
|
|
|
|
|
|
|
|
// control
|
|
|
|
OP_NOP: 97,
|
|
|
|
OP_VER: 98,
|
|
|
|
OP_IF: 99,
|
|
|
|
OP_NOTIF: 100,
|
|
|
|
OP_VERIF: 101,
|
|
|
|
OP_VERNOTIF: 102,
|
|
|
|
OP_ELSE: 103,
|
|
|
|
OP_ENDIF: 104,
|
|
|
|
OP_VERIFY: 105,
|
|
|
|
OP_RETURN: 106,
|
|
|
|
|
|
|
|
// stack ops
|
|
|
|
OP_TOALTSTACK: 107,
|
|
|
|
OP_FROMALTSTACK: 108,
|
|
|
|
OP_2DROP: 109,
|
|
|
|
OP_2DUP: 110,
|
|
|
|
OP_3DUP: 111,
|
|
|
|
OP_2OVER: 112,
|
|
|
|
OP_2ROT: 113,
|
|
|
|
OP_2SWAP: 114,
|
|
|
|
OP_IFDUP: 115,
|
|
|
|
OP_DEPTH: 116,
|
|
|
|
OP_DROP: 117,
|
|
|
|
OP_DUP: 118,
|
|
|
|
OP_NIP: 119,
|
|
|
|
OP_OVER: 120,
|
|
|
|
OP_PICK: 121,
|
|
|
|
OP_ROLL: 122,
|
|
|
|
OP_ROT: 123,
|
|
|
|
OP_SWAP: 124,
|
|
|
|
OP_TUCK: 125,
|
|
|
|
|
|
|
|
// splice ops
|
|
|
|
OP_CAT: 126,
|
|
|
|
OP_SUBSTR: 127,
|
|
|
|
OP_LEFT: 128,
|
|
|
|
OP_RIGHT: 129,
|
|
|
|
OP_SIZE: 130,
|
|
|
|
|
|
|
|
// bit logic
|
|
|
|
OP_INVERT: 131,
|
|
|
|
OP_AND: 132,
|
|
|
|
OP_OR: 133,
|
|
|
|
OP_XOR: 134,
|
|
|
|
OP_EQUAL: 135,
|
|
|
|
OP_EQUALVERIFY: 136,
|
|
|
|
OP_RESERVED1: 137,
|
|
|
|
OP_RESERVED2: 138,
|
|
|
|
|
|
|
|
// numeric
|
|
|
|
OP_1ADD: 139,
|
|
|
|
OP_1SUB: 140,
|
|
|
|
OP_2MUL: 141,
|
|
|
|
OP_2DIV: 142,
|
|
|
|
OP_NEGATE: 143,
|
|
|
|
OP_ABS: 144,
|
|
|
|
OP_NOT: 145,
|
|
|
|
OP_0NOTEQUAL: 146,
|
|
|
|
|
|
|
|
OP_ADD: 147,
|
|
|
|
OP_SUB: 148,
|
|
|
|
OP_MUL: 149,
|
|
|
|
OP_DIV: 150,
|
|
|
|
OP_MOD: 151,
|
|
|
|
OP_LSHIFT: 152,
|
|
|
|
OP_RSHIFT: 153,
|
|
|
|
|
|
|
|
OP_BOOLAND: 154,
|
|
|
|
OP_BOOLOR: 155,
|
|
|
|
OP_NUMEQUAL: 156,
|
|
|
|
OP_NUMEQUALVERIFY: 157,
|
|
|
|
OP_NUMNOTEQUAL: 158,
|
|
|
|
OP_LESSTHAN: 159,
|
|
|
|
OP_GREATERTHAN: 160,
|
|
|
|
OP_LESSTHANOREQUAL: 161,
|
|
|
|
OP_GREATERTHANOREQUAL: 162,
|
|
|
|
OP_MIN: 163,
|
|
|
|
OP_MAX: 164,
|
|
|
|
|
|
|
|
OP_WITHIN: 165,
|
|
|
|
|
|
|
|
// crypto
|
|
|
|
OP_RIPEMD160: 166,
|
|
|
|
OP_SHA1: 167,
|
|
|
|
OP_SHA256: 168,
|
|
|
|
OP_HASH160: 169,
|
|
|
|
OP_HASH256: 170,
|
|
|
|
OP_CODESEPARATOR: 171,
|
|
|
|
OP_CHECKSIG: 172,
|
|
|
|
OP_CHECKSIGVERIFY: 173,
|
|
|
|
OP_CHECKMULTISIG: 174,
|
|
|
|
OP_CHECKMULTISIGVERIFY: 175,
|
|
|
|
|
|
|
|
// expansion
|
|
|
|
OP_NOP1: 176,
|
|
|
|
OP_NOP2: 177,
|
|
|
|
OP_NOP3: 178,
|
|
|
|
OP_NOP4: 179,
|
|
|
|
OP_NOP5: 180,
|
|
|
|
OP_NOP6: 181,
|
|
|
|
OP_NOP7: 182,
|
|
|
|
OP_NOP8: 183,
|
|
|
|
OP_NOP9: 184,
|
|
|
|
OP_NOP10: 185,
|
|
|
|
|
|
|
|
// template matching params
|
|
|
|
OP_PUBKEYHASH: 253,
|
|
|
|
OP_PUBKEY: 254,
|
|
|
|
OP_INVALIDOPCODE: 255
|
|
|
|
};
|
|
|
|
|
|
|
|
Opcode.reverseMap = [];
|
|
|
|
|
|
|
|
for (var k in Opcode.map) {
|
2014-12-11 16:12:26 -08:00
|
|
|
Opcode.reverseMap[Opcode.map[k]] = k;
|
2014-08-29 19:24:51 -07:00
|
|
|
}
|
|
|
|
|
2014-12-09 12:30:52 -08:00
|
|
|
// Easier access to opcodes
|
|
|
|
_.extend(Opcode, Opcode.map);
|
|
|
|
|
2014-11-28 09:54:19 -08:00
|
|
|
/**
|
|
|
|
* @returns true if opcode is one of OP_0, OP_1, ..., OP_16
|
|
|
|
*/
|
|
|
|
Opcode.isSmallIntOp = function(opcode) {
|
|
|
|
if (opcode instanceof Opcode) {
|
|
|
|
opcode = opcode.toNumber();
|
|
|
|
}
|
|
|
|
return ((opcode === Opcode.map.OP_0) ||
|
|
|
|
((opcode >= Opcode.map.OP_1) && (opcode <= Opcode.map.OP_16)));
|
|
|
|
};
|
|
|
|
|
2014-12-11 19:27:37 -08:00
|
|
|
module.exports = Opcode;
|