script: refactor execution.

This commit is contained in:
Christopher Jeffrey 2017-06-11 23:37:55 -07:00
parent 3fd229d9ee
commit a1e9999f29
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 51 additions and 39 deletions

View File

@ -814,7 +814,7 @@ exports.array = function(value) {
* @constructor
* @extends Error
* @param {String} code - Error code.
* @param {Number} op - Opcode.
* @param {Opcode} op - Opcode.
* @param {Number?} ip - Instruction pointer.
* @property {String} message - Error message.
* @property {String} code - Original code passed in.
@ -834,21 +834,16 @@ exports.ScriptError = function ScriptError(code, op, ip) {
this.type = 'ScriptError';
this.code = code;
this.message = code;
this.op = op != null ? op : -1;
this.ip = ip != null ? ip : -1;
this.op = -1;
this.ip = -1;
if (typeof op === 'number') {
if (exports.opcodesByVal[op])
op = exports.opcodesByVal[op];
else if (op !== -1)
op = util.hex8(op);
this.message += ' (op=' + op + ',';
this.message += ' ip=' + this.ip + ')';
} else if (typeof op === 'string') {
if (typeof op === 'string') {
this.message = op;
this.op = -1;
this.ip = -1;
} else if (op) {
this.op = op.value;
this.ip = ip;
this.message += ' (op=' + op.toSymbol() + ',';
this.message += ' ip=' + ip + ')';
}
};

View File

@ -388,6 +388,26 @@ Opcode.fromSymbol = function fromSymbol(name) {
return Opcode.fromOp(op);
};
/**
* Convert opcode to its symbolic representation.
* @returns {String}
*/
Opcode.prototype.toSymbol = function toSymbol() {
var op = this.value;
var symbol;
if (op === -1)
op = 0xff;
symbol = common.opcodesByVal[op];
if (symbol == null)
symbol = util.hex8(op);
return symbol;
};
/**
* Test whether an object an Opcode.
* @param {Object} obj

View File

@ -508,10 +508,9 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
var state = [];
var negate = 0;
var minimal = false;
var op, code, data;
var val, v1, v2, v3;
var num, n1, n2, n3;
var m, n, key, sig;
var op, m, n, key, sig;
var type, subscript, hash;
var ikey, isig, ikey2;
var i, j, res, locktime;
@ -529,29 +528,27 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
throw new ScriptError('SCRIPT_SIZE');
for (ip = 0; ip < this.code.length; ip++) {
code = this.code[ip];
op = code.value;
data = code.data;
op = this.code[ip];
if (op === -1)
if (op.value === -1)
throw new ScriptError('BAD_OPCODE', op, ip);
if (data) {
if (data.length > consensus.MAX_SCRIPT_PUSH)
if (op.data) {
if (op.data.length > consensus.MAX_SCRIPT_PUSH)
throw new ScriptError('PUSH_SIZE', op, ip);
// Note that minimaldata is not checked
// on unexecuted branches of code.
if (negate === 0) {
if (minimal && !code.isMinimal())
if (minimal && !op.isMinimal())
throw new ScriptError('MINIMALDATA', op, ip);
stack.push(data);
stack.push(op.data);
}
continue;
}
if (op > opcodes.OP_16 && ++opCount > consensus.MAX_SCRIPT_OPS)
if (op.value > opcodes.OP_16 && ++opCount > consensus.MAX_SCRIPT_OPS)
throw new ScriptError('OP_COUNT', op, ip);
// It's very important to make a distiction
@ -559,7 +556,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
// are in unexecuted branches of code_. Whereas
// a totally unknown opcode is fine as long as it
// is unexecuted.
switch (op) {
switch (op.value) {
case opcodes.OP_CAT:
case opcodes.OP_SUBSTR:
case opcodes.OP_LEFT:
@ -578,8 +575,8 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
throw new ScriptError('DISABLED_OPCODE', op, ip);
}
if (op >= opcodes.OP_IF && op <= opcodes.OP_ENDIF) {
switch (op) {
if (op.value >= opcodes.OP_IF && op.value <= opcodes.OP_ENDIF) {
switch (op.value) {
case opcodes.OP_IF:
case opcodes.OP_NOTIF: {
val = false;
@ -600,7 +597,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
val = Script.bool(val);
if (op === opcodes.OP_NOTIF)
if (op.value === opcodes.OP_NOTIF)
val = !val;
stack.pop();
@ -649,7 +646,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
if (negate !== 0)
continue;
switch (op) {
switch (op.value) {
case opcodes.OP_0: {
stack.push(STACK_FALSE);
break;
@ -677,7 +674,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
case opcodes.OP_14:
case opcodes.OP_15:
case opcodes.OP_16: {
stack.push(Buffer.from([op - 0x50]));
stack.push(Buffer.from([op.value - 0x50]));
break;
}
case opcodes.OP_NOP: {
@ -893,7 +890,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
val = stack.top(-num - 1);
if (op === opcodes.OP_ROLL)
if (op.value === opcodes.OP_ROLL)
stack.remove(-num - 1);
stack.push(val);
@ -939,7 +936,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
res = util.equal(v1, v2);
// if (op == opcodes.OP_NOTEQUAL)
// if (op.value == opcodes.OP_NOTEQUAL)
// res = !res;
stack.pop();
@ -947,7 +944,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
stack.push(res ? STACK_TRUE : STACK_FALSE);
if (op === opcodes.OP_EQUALVERIFY) {
if (op.value === opcodes.OP_EQUALVERIFY) {
if (!res)
throw new ScriptError('EQUALVERIFY', op, ip);
stack.pop();
@ -968,7 +965,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
num = Script.num(stack.top(-1), minimal);
switch (op) {
switch (op.value) {
case opcodes.OP_1ADD:
num.iaddn(1);
break;
@ -1030,7 +1027,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
n1 = Script.num(stack.top(-2), minimal);
n2 = Script.num(stack.top(-1), minimal);
switch (op) {
switch (op.value) {
case opcodes.OP_ADD:
num = n1.iadd(n2);
break;
@ -1103,7 +1100,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
stack.pop();
stack.push(Script.array(num));
if (op === opcodes.OP_NUMEQUALVERIFY) {
if (op.value === opcodes.OP_NUMEQUALVERIFY) {
if (!Script.bool(stack.top(-1)))
throw new ScriptError('NUMEQUALVERIFY', op, ip);
stack.pop();
@ -1203,7 +1200,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
stack.push(res ? STACK_TRUE : STACK_FALSE);
if (op === opcodes.OP_CHECKSIGVERIFY) {
if (op.value === opcodes.OP_CHECKSIGVERIFY) {
if (!res)
throw new ScriptError('CHECKSIGVERIFY', op, ip);
stack.pop();
@ -1305,7 +1302,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
stack.push(res ? STACK_TRUE : STACK_FALSE);
if (op === opcodes.OP_CHECKMULTISIGVERIFY) {
if (op.value === opcodes.OP_CHECKMULTISIGVERIFY) {
if (!res)
throw new ScriptError('CHECKMULTISIGVERIFY', op, ip);
stack.pop();