more errors for scripting system.
This commit is contained in:
parent
ce0c6f4fc7
commit
50ab39aafb
@ -599,7 +599,7 @@ Stack.prototype.toalt = function toalt() {
|
||||
|
||||
Stack.prototype.fromalt = function fromalt() {
|
||||
if (this.alt.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', opcodes.OP_FROMALTSTACK);
|
||||
throw new ScriptError('INVALID_ALTSTACK_OPERATION', opcodes.OP_FROMALTSTACK);
|
||||
|
||||
this.push(this.alt.pop());
|
||||
};
|
||||
@ -1009,30 +1009,6 @@ Script.prototype.getSubscript = function getSubscript(lastSep) {
|
||||
return new Script(code);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute the script and return false on script execution errors.
|
||||
* @param {Stack} stack - Script execution stack.
|
||||
* @param {Number?} flags - Script standard flags.
|
||||
* @param {TX?} tx - Transaction being verified.
|
||||
* @param {Number?} index - Index of input being verified.
|
||||
* @param {Number?} version - Signature hash version (0=legacy, 1=segwit).
|
||||
* @returns {Boolean} Whether the execution was successful.
|
||||
*/
|
||||
|
||||
Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
try {
|
||||
return this.interpret(stack, flags, tx, index, version);
|
||||
} catch (e) {
|
||||
if (e.type === 'ScriptError') {
|
||||
bcoin.debug('Script error: %s.', e.message);
|
||||
} else {
|
||||
bcoin.debug('Script interpreter threw:');
|
||||
bcoin.debug(e.stack + '');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute and interpret the script.
|
||||
* @param {Stack} stack - Script execution stack.
|
||||
@ -1044,7 +1020,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
* @returns {Boolean} Whether the execution was successful.
|
||||
*/
|
||||
|
||||
Script.prototype.interpret = function interpret(stack, flags, tx, index, version) {
|
||||
Script.prototype.execute = function execute(stack, flags, tx, index, version) {
|
||||
var ip = 0;
|
||||
var lastSep = -1;
|
||||
var opCount = 0;
|
||||
@ -1064,7 +1040,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
stack.negate = 0;
|
||||
|
||||
if (this.getSize() > constants.script.MAX_SIZE)
|
||||
throw new ScriptError('SCRIPT_SIZE', null, -1);
|
||||
throw new ScriptError('SCRIPT_SIZE');
|
||||
|
||||
for (ip = 0; ip < this.code.length; ip++) {
|
||||
op = this.code[ip];
|
||||
@ -1200,7 +1176,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
}
|
||||
|
||||
if (!tx)
|
||||
throw new ScriptError('NO_TX', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
|
||||
|
||||
if (stack.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
||||
@ -1226,7 +1202,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
}
|
||||
|
||||
if (!tx)
|
||||
throw new ScriptError('NO_TX', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
|
||||
|
||||
if (stack.length === 0)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
||||
@ -1355,7 +1331,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
res = utils.equals(stack.pop(), stack.pop());
|
||||
if (op === opcodes.OP_EQUALVERIFY) {
|
||||
if (!res)
|
||||
throw new ScriptError('VERIFY', op, ip);
|
||||
throw new ScriptError('EQUALVERIFY', op, ip);
|
||||
} else {
|
||||
stack.push(res ? STACK_TRUE : STACK_FALSE);
|
||||
}
|
||||
@ -1466,12 +1442,12 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
break;
|
||||
case opcodes.OP_LSHIFT:
|
||||
if (n2.cmpn(0) < 0 || n2.cmpn(2048) > 0)
|
||||
throw new ScriptError('BAD_SHIFT', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'Bad shift.');
|
||||
n = n1.ushln(n2.toNumber());
|
||||
break;
|
||||
case opcodes.OP_RSHIFT:
|
||||
if (n2.cmpn(0) < 0 || n2.cmpn(2048) > 0)
|
||||
throw new ScriptError('BAD_SHIFT', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'Bad shift.');
|
||||
n = n1.ushrn(n2.toNumber());
|
||||
break;
|
||||
case opcodes.OP_BOOLAND:
|
||||
@ -1570,7 +1546,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
case opcodes.OP_CHECKSIGVERIFY:
|
||||
case opcodes.OP_CHECKSIG: {
|
||||
if (!tx)
|
||||
throw new ScriptError('NO_TX', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
|
||||
|
||||
if (stack.length < 2)
|
||||
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
|
||||
@ -1582,11 +1558,8 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
if (version === 0)
|
||||
subscript.removeData(sig);
|
||||
|
||||
if (!Script.isValidSignature(sig, flags))
|
||||
throw new ScriptError('SIG_DER_OR_HASHTYPE', op, ip);
|
||||
|
||||
if (!Script.isValidKey(key, flags))
|
||||
throw new ScriptError('PUBKEYTYPE', op, ip);
|
||||
Script.validateSignature(sig, flags);
|
||||
Script.validateKey(key, flags);
|
||||
|
||||
type = sig[sig.length - 1];
|
||||
|
||||
@ -1605,7 +1578,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
case opcodes.OP_CHECKMULTISIGVERIFY:
|
||||
case opcodes.OP_CHECKMULTISIG: {
|
||||
if (!tx)
|
||||
throw new ScriptError('NO_TX', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'No TX passed in.');
|
||||
|
||||
i = 1;
|
||||
if (stack.length < i)
|
||||
@ -1653,11 +1626,8 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
sig = stack.top(-isig);
|
||||
key = stack.top(-ikey);
|
||||
|
||||
if (!Script.isValidSignature(sig, flags))
|
||||
throw new ScriptError('SIG_DER_OR_HASHTYPE', op, ip);
|
||||
|
||||
if (!Script.isValidKey(key, flags))
|
||||
throw new ScriptError('PUBKEYTYPE', op, ip);
|
||||
Script.validateSignature(sig, flags);
|
||||
Script.validateKey(key, flags);
|
||||
|
||||
type = sig[sig.length - 1];
|
||||
hash = tx.signatureHash(index, subscript, type, version);
|
||||
@ -1682,7 +1652,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
|
||||
if (flags & constants.flags.VERIFY_NULLDUMMY) {
|
||||
if (!Script.isDummy(stack.top(-1)))
|
||||
throw new ScriptError('VERIFY_NULLDUMMY', op, ip);
|
||||
throw new ScriptError('SIG_NULLDUMMY', op, ip);
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
@ -1713,7 +1683,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
v2 = Script.num(stack.pop(), flags).toNumber(); // begin
|
||||
v1 = stack.pop(); // string
|
||||
if (v2 < 0 || v3 < v2)
|
||||
throw new ScriptError('STRING_OUT_OF_RANGE', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'String out of range.');
|
||||
if (v2 > v1.length)
|
||||
v2 = v1.length;
|
||||
if (v3 > v1.length)
|
||||
@ -1728,7 +1698,7 @@ Script.prototype.interpret = function interpret(stack, flags, tx, index, version
|
||||
v2 = Script.num(stack.pop(), flags).toNumber(); // size
|
||||
v1 = stack.pop(); // string
|
||||
if (v2 < 0)
|
||||
throw new ScriptError('STRING_OUT_OF_RANGE', op, ip);
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'String size out of range.');
|
||||
if (v2 > v1.length)
|
||||
v2 = v1.length;
|
||||
if (op === opcodes.OP_LEFT)
|
||||
@ -1905,7 +1875,7 @@ Script.num = function num(value, flags, size) {
|
||||
size = 4;
|
||||
|
||||
if (value.length > size)
|
||||
throw new ScriptError('Script number overflow.');
|
||||
throw new ScriptError('UNKNOWN_ERROR', 'Script number overflow.');
|
||||
|
||||
if ((flags & constants.flags.VERIFY_MINIMALDATA) && value.length > 0) {
|
||||
// If the low bits on the last byte are unset,
|
||||
@ -1917,8 +1887,11 @@ Script.num = function num(value, flags, size) {
|
||||
// to avoid negative zero (also avoids positive
|
||||
// zero).
|
||||
if (!(value[value.length - 1] & 0x7f)) {
|
||||
if (value.length === 1 || !(value[value.length - 2] & 0x80))
|
||||
throw new ScriptError('Non-minimally encoded Script number.');
|
||||
if (value.length === 1 || !(value[value.length - 2] & 0x80)) {
|
||||
throw new ScriptError(
|
||||
'UNKNOWN_ERROR',
|
||||
'Non-minimally encoded Script number.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3232,20 +3205,19 @@ Script.isZero = function isZero(op) {
|
||||
* @param {Buffer} key
|
||||
* @param {VerifyFlags?} flags
|
||||
* @returns {Boolean}
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.isValidKey = function isValidKey(key, flags) {
|
||||
Script.validateKey = function validateKey(key, flags) {
|
||||
if (flags == null)
|
||||
flags = constants.flags.STANDARD_VERIFY_FLAGS;
|
||||
|
||||
if (!Script.isPush(key))
|
||||
return false;
|
||||
throw new ScriptError('BAD_OPCODE');
|
||||
|
||||
if (flags & constants.flags.VERIFY_STRICTENC) {
|
||||
if (!Script.isKeyEncoding(key)) {
|
||||
bcoin.debug('Script failed key encoding test.');
|
||||
return false;
|
||||
}
|
||||
if (!Script.isKeyEncoding(key))
|
||||
throw new ScriptError('PUBKEYTYPE');
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3286,14 +3258,15 @@ Script.isKeyEncoding = function isKeyEncoding(key) {
|
||||
* @param {Buffer} sig
|
||||
* @param {VerifyFlags?} flags
|
||||
* @returns {Boolean}
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.isValidSignature = function isValidSignature(sig, flags) {
|
||||
Script.validateSignature = function validateSignature(sig, flags) {
|
||||
if (flags == null)
|
||||
flags = constants.flags.STANDARD_VERIFY_FLAGS;
|
||||
|
||||
if (!Script.isPush(sig))
|
||||
return false;
|
||||
throw new ScriptError('BAD_OPCODE');
|
||||
|
||||
// Allow empty sigs
|
||||
if (sig.length === 0)
|
||||
@ -3302,24 +3275,18 @@ Script.isValidSignature = function isValidSignature(sig, flags) {
|
||||
if ((flags & constants.flags.VERIFY_DERSIG)
|
||||
|| (flags & constants.flags.VERIFY_LOW_S)
|
||||
|| (flags & constants.flags.VERIFY_STRICTENC)) {
|
||||
if (!Script.isSignatureEncoding(sig)) {
|
||||
bcoin.debug('Script does not have a proper signature encoding.');
|
||||
return false;
|
||||
}
|
||||
if (!Script.isSignatureEncoding(sig))
|
||||
throw new ScriptError('SIG_DER');
|
||||
}
|
||||
|
||||
if (flags & constants.flags.VERIFY_LOW_S) {
|
||||
if (!Script.isLowDER(sig)) {
|
||||
bcoin.debug('Script does not have a low DER.');
|
||||
return false;
|
||||
}
|
||||
if (!Script.isLowDER(sig))
|
||||
throw new ScriptError('SIG_HIGH_S');
|
||||
}
|
||||
|
||||
if (flags & constants.flags.VERIFY_STRICTENC) {
|
||||
if (!Script.isHashType(sig)) {
|
||||
bcoin.debug('Script does not have a valid hash type.');
|
||||
return false;
|
||||
}
|
||||
if (!Script.isHashType(sig))
|
||||
throw new ScriptError('SIG_HASHTYPE');
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3809,10 +3776,11 @@ Script.fromSymbolic = function fromSymbolic(items) {
|
||||
* @param {Number} i
|
||||
* @param {VerifyFlags} flags
|
||||
* @returns {Boolean}
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
var copy, res, raw, redeem, hadWitness;
|
||||
var copy, raw, redeem, hadWitness;
|
||||
var stack = new Stack();
|
||||
|
||||
if (flags == null)
|
||||
@ -3820,36 +3788,32 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
|
||||
if (flags & constants.flags.VERIFY_SIGPUSHONLY) {
|
||||
if (!input.isPushOnly())
|
||||
return false;
|
||||
throw new ScriptError('SIG_PUSHONLY');
|
||||
}
|
||||
|
||||
// Execute the input script
|
||||
res = input.execute(stack, flags, tx, i, 0);
|
||||
|
||||
if (!res)
|
||||
return false;
|
||||
input.execute(stack, flags, tx, i, 0);
|
||||
|
||||
// Copy the stack for P2SH
|
||||
if (flags & constants.flags.VERIFY_P2SH)
|
||||
copy = stack.clone();
|
||||
|
||||
// Execute the previous output script
|
||||
res = output.execute(stack, flags, tx, i, 0);
|
||||
output.execute(stack, flags, tx, i, 0);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || !Script.bool(stack.pop()))
|
||||
return false;
|
||||
if (stack.length === 0 || !Script.bool(stack.pop()))
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
if ((flags & constants.flags.VERIFY_WITNESS) && output.isWitnessProgram()) {
|
||||
hadWitness = true;
|
||||
|
||||
// Input script must be empty.
|
||||
if (input.code.length !== 0)
|
||||
return false;
|
||||
throw new ScriptError('WITNESS_MALLEATED');
|
||||
|
||||
// Verify the program in the output script
|
||||
if (!Script.verifyProgram(witness, output, flags, tx, i))
|
||||
return false;
|
||||
Script.verifyProgram(witness, output, flags, tx, i);
|
||||
|
||||
// Force a cleanstack
|
||||
stack.length = 0;
|
||||
@ -3859,40 +3823,35 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
if ((flags & constants.flags.VERIFY_P2SH) && output.isScripthash()) {
|
||||
// P2SH can only have push ops in the scriptSig
|
||||
if (!input.isPushOnly())
|
||||
return false;
|
||||
throw new ScriptError('SIG_PUSHONLY');
|
||||
|
||||
// Reset the stack
|
||||
stack = copy;
|
||||
|
||||
// Stack should not be empty at this point
|
||||
if (stack.length === 0)
|
||||
return false;
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
// Grab the real redeem script
|
||||
raw = stack.pop();
|
||||
|
||||
if (!Script.isPush(raw))
|
||||
return false;
|
||||
|
||||
redeem = new Script(raw);
|
||||
|
||||
// Execute the redeem script
|
||||
res = redeem.execute(stack, flags, tx, i, 0);
|
||||
redeem.execute(stack, flags, tx, i, 0);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || !Script.bool(stack.pop()))
|
||||
return false;
|
||||
if (stack.length === 0 || !Script.bool(stack.pop()))
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
if ((flags & constants.flags.VERIFY_WITNESS) && redeem.isWitnessProgram()) {
|
||||
hadWitness = true;
|
||||
|
||||
// Input script must be exactly one push of the redeem script.
|
||||
if (!(input.code.length === 1 && utils.equals(input.code[0], raw)))
|
||||
return false;
|
||||
throw new ScriptError('WITNESS_MALLEATED');
|
||||
|
||||
// Verify the program in the redeem script
|
||||
if (!Script.verifyProgram(witness, redeem, flags, tx, i))
|
||||
return false;
|
||||
Script.verifyProgram(witness, redeem, flags, tx, i);
|
||||
|
||||
// Force a cleanstack
|
||||
stack.length = 0;
|
||||
@ -3904,14 +3863,14 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
assert((flags & constants.flags.VERIFY_P2SH) !== 0);
|
||||
// assert((flags & constants.flags.VERIFY_WITNESS) !== 0);
|
||||
if (stack.length !== 0)
|
||||
return false;
|
||||
throw new ScriptError('CLEANSTACK');
|
||||
}
|
||||
|
||||
// If we had a witness but no witness program, fail.
|
||||
if (flags & constants.flags.VERIFY_WITNESS) {
|
||||
assert((flags & constants.flags.VERIFY_P2SH) !== 0);
|
||||
if (!hadWitness && witness.length > 0)
|
||||
return false;
|
||||
throw new ScriptError('WITNESS_UNEXPECTED');
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -3926,23 +3885,38 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
|
||||
* @param {VerifyFlags} flags
|
||||
* @param {TX} tx
|
||||
* @param {Number} i
|
||||
* @throws {ScriptError}
|
||||
*/
|
||||
|
||||
Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
|
||||
var program, witnessScript, redeem, stack, j, res;
|
||||
var program = output.getWitnessProgram();
|
||||
var stack = witness.toStack();
|
||||
var witnessScript, redeem, j;
|
||||
|
||||
assert(program, 'verifyProgram called on non-witness-program.');
|
||||
assert((flags & constants.flags.VERIFY_WITNESS) !== 0);
|
||||
assert(output.isWitnessProgram());
|
||||
|
||||
program = output.getWitnessProgram();
|
||||
if (program.version === 0) {
|
||||
if (program.data.length === 32) {
|
||||
if (stack.length === 0)
|
||||
throw new ScriptError('WITNESS_PROGRAM_WITNESS_EMPTY');
|
||||
|
||||
// Failure on version=0 (bad program data length)
|
||||
if (!program.type) {
|
||||
bcoin.debug('Malformed witness program.');
|
||||
return false;
|
||||
}
|
||||
witnessScript = stack.pop();
|
||||
|
||||
if (program.version > 0) {
|
||||
if (!utils.equals(utils.sha256(witnessScript), program.data))
|
||||
throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
|
||||
|
||||
redeem = new Script(witnessScript);
|
||||
} else if (program.data.length === 20) {
|
||||
if (stack.length !== 2)
|
||||
throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
|
||||
|
||||
redeem = Script.createPubkeyhash(program.data);
|
||||
} else {
|
||||
// Failure on version=0 (bad program data length)
|
||||
throw new ScriptError('WITNESS_PROGRAM_WRONG_LENGTH');
|
||||
}
|
||||
} else {
|
||||
bcoin.debug('Unknown witness program version: %s', program.version);
|
||||
// Anyone can spend (we can return true here
|
||||
// if we want to always relay these transactions).
|
||||
@ -3952,45 +3926,24 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
|
||||
// succeed in a block, but fail in the mempool
|
||||
// due to VERIFY_CLEANSTACK.
|
||||
if (flags & constants.flags.VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
|
||||
return false;
|
||||
throw new ScriptError('DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
|
||||
return true;
|
||||
}
|
||||
|
||||
stack = witness.toStack();
|
||||
|
||||
if (program.type === 'witnesspubkeyhash') {
|
||||
if (stack.length !== 2)
|
||||
return false;
|
||||
|
||||
redeem = Script.createPubkeyhash(program.data);
|
||||
} else if (program.type === 'witnessscripthash') {
|
||||
if (stack.length === 0)
|
||||
return false;
|
||||
|
||||
witnessScript = stack.pop();
|
||||
|
||||
if (!utils.equals(utils.sha256(witnessScript), program.data))
|
||||
return false;
|
||||
|
||||
redeem = new Script(witnessScript);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
for (j = 0; j < stack.length; j++) {
|
||||
if (stack.get(j).length > constants.script.MAX_PUSH)
|
||||
return false;
|
||||
throw new ScriptError('PUSH_SIZE');
|
||||
}
|
||||
|
||||
res = redeem.execute(stack, flags, tx, i, 1);
|
||||
redeem.execute(stack, flags, tx, i, 1);
|
||||
|
||||
// Verify the script did not fail as well as the stack values
|
||||
if (!res || stack.length === 0 || !Script.bool(stack.pop()))
|
||||
return false;
|
||||
if (stack.length === 0 || !Script.bool(stack.pop()))
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
// Witnesses always require cleanstack
|
||||
if (stack.length !== 0)
|
||||
return false;
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -4310,25 +4263,31 @@ function ScriptError(code, op, ip) {
|
||||
this.type = 'ScriptError';
|
||||
this.code = code;
|
||||
|
||||
if (Buffer.isBuffer(op))
|
||||
op = 'PUSHDATA[' + op.length + ']';
|
||||
if (typeof op !== 'string') {
|
||||
if (Buffer.isBuffer(op))
|
||||
op = 'PUSHDATA[' + op.length + ']';
|
||||
|
||||
if (op || ip != null) {
|
||||
code += '(';
|
||||
if (op) {
|
||||
op = constants.opcodesByVal[op] || op;
|
||||
code += 'op=' + op;
|
||||
if (op || ip != null) {
|
||||
code += ' (';
|
||||
if (op) {
|
||||
op = constants.opcodesByVal[op] || op;
|
||||
code += 'op=' + op;
|
||||
if (ip != null)
|
||||
code += ', ';
|
||||
}
|
||||
if (ip != null)
|
||||
code += ', ';
|
||||
code += 'ip=' + ip;
|
||||
code += ')';
|
||||
}
|
||||
if (ip != null)
|
||||
code += 'ip=' + ip;
|
||||
code + ')';
|
||||
}
|
||||
|
||||
this.message = code;
|
||||
this.op = op;
|
||||
this.ip = ip;
|
||||
this.message = code;
|
||||
this.op = op || '';
|
||||
this.ip = ip != null ? ip : -1;
|
||||
} else {
|
||||
this.message = op;
|
||||
this.op = '';
|
||||
this.ip = -1;
|
||||
}
|
||||
}
|
||||
|
||||
utils.inherits(ScriptError, Error);
|
||||
|
||||
@ -515,7 +515,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
|
||||
*/
|
||||
|
||||
TX.prototype.verify = function verify(index, force, flags) {
|
||||
var i, input, res;
|
||||
var i, input;
|
||||
|
||||
// Valid if included in block
|
||||
if (!force && this.ts !== 0)
|
||||
@ -544,17 +544,23 @@ TX.prototype.verify = function verify(index, force, flags) {
|
||||
return false;
|
||||
}
|
||||
|
||||
res = Script.verify(
|
||||
input.script,
|
||||
input.witness,
|
||||
input.coin.script,
|
||||
this,
|
||||
i,
|
||||
flags
|
||||
);
|
||||
|
||||
if (!res)
|
||||
try {
|
||||
Script.verify(
|
||||
input.script,
|
||||
input.witness,
|
||||
input.coin.script,
|
||||
this,
|
||||
i,
|
||||
flags
|
||||
);
|
||||
} catch (e) {
|
||||
if (e.type === 'ScriptError') {
|
||||
bcoin.debug('Script verification error: %s', e.message);
|
||||
} else {
|
||||
bcoin.debug('Script interpreter threw: %s', e.stack + '');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1133,7 +1139,7 @@ TX.prototype.isStandard = function isStandard(flags, ret) {
|
||||
TX.prototype.hasStandardInputs = function hasStandardInputs(flags) {
|
||||
var maxSigops = constants.script.MAX_SCRIPTHASH_SIGOPS;
|
||||
var VERIFY_NONE = constants.flags.VERIFY_NONE;
|
||||
var i, input, stack, res, redeem;
|
||||
var i, input, stack, redeem;
|
||||
|
||||
if (flags == null)
|
||||
flags = constants.flags.STANDARD_VERIFY_FLAGS;
|
||||
@ -1160,10 +1166,11 @@ TX.prototype.hasStandardInputs = function hasStandardInputs(flags) {
|
||||
|
||||
stack = new Stack();
|
||||
|
||||
res = input.script.execute(stack, VERIFY_NONE, this, i, 0);
|
||||
|
||||
if (!res)
|
||||
try {
|
||||
input.script.execute(stack, VERIFY_NONE, this, i, 0);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stack.length === 0)
|
||||
return false;
|
||||
|
||||
@ -254,11 +254,20 @@ describe('Script', function() {
|
||||
delete input.raw;
|
||||
delete output.raw;
|
||||
}
|
||||
var res = Script.verify(input, witness, output, tx, 0, flags);
|
||||
if (expected === 'OK')
|
||||
assert.ok(res);
|
||||
else
|
||||
assert.ok(!res);
|
||||
var err, res;
|
||||
try {
|
||||
res = Script.verify(input, witness, output, tx, 0, flags);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
if (expected !== 'OK') {
|
||||
assert(!res);
|
||||
assert(err);
|
||||
assert.equal(err.code, expected);
|
||||
return;
|
||||
}
|
||||
utils.assert.noError(err);
|
||||
assert(res);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user