script: refactor execution.
This commit is contained in:
parent
3fd229d9ee
commit
a1e9999f29
@ -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 + ')';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user