script: move static methods off of script constructor.

This commit is contained in:
Christopher Jeffrey 2017-06-08 19:47:38 -07:00
parent 49976e7d6f
commit 8893131e08
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 241 additions and 315 deletions

View File

@ -1300,6 +1300,9 @@ TX.prototype.getSigopsCost = function getSigopsCost(view, flags) {
if (flags & Script.flags.VERIFY_P2SH)
cost += this.getScripthashSigops(view) * scale;
if ((flags & Script.flags.VERIFY_WITNESS) === 0)
return cost;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
coin = view.getOutput(input);
@ -1307,11 +1310,7 @@ TX.prototype.getSigopsCost = function getSigopsCost(view, flags) {
if (!coin)
continue;
cost += Script.getWitnessSigops(
input.script,
coin.script,
input.witness,
flags);
cost += coin.script.getWitnessSigops(input.script, input.witness);
}
return cost;
@ -1326,10 +1325,6 @@ TX.prototype.getSigopsCost = function getSigopsCost(view, flags) {
TX.prototype.getSigops = function getSigops(view, flags) {
var scale = consensus.WITNESS_SCALE_FACTOR;
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
return (this.getSigopsCost(view, flags) + scale - 1) / scale | 0;
};

View File

@ -14,6 +14,7 @@
var assert = require('assert');
var BN = require('bn.js');
var util = require('../utils/util');
var ec = require('../crypto/ec');
/**
* Script opcodes.
@ -298,7 +299,7 @@ exports.typesByVal = util.revMap(exports.types);
* @const {Buffer}
*/
exports.STACK_FALSE = Buffer.alloc(0);
exports.STACK_FALSE = Buffer.from([]);
/**
* True stack return value.
@ -314,6 +315,59 @@ exports.STACK_TRUE = Buffer.from([0x01]);
exports.STACK_NEGATE = Buffer.from([0x81]);
/**
* Test a signature to see whether it contains a valid sighash type.
* @param {Buffer} sig
* @returns {Boolean}
*/
exports.isHashType = function isHashType(sig) {
var type;
assert(Buffer.isBuffer(sig));
if (sig.length === 0)
return false;
type = sig[sig.length - 1] & ~exports.hashType.ANYONECANPAY;
if (!(type >= exports.hashType.ALL && type <= exports.hashType.SINGLE))
return false;
return true;
};
/**
* Test a signature to see whether it contains a low S value.
* @param {Buffer} sig
* @returns {Boolean}
*/
exports.isLowDER = function isLowDER(sig) {
if (!exports.isSignatureEncoding(sig))
return false;
return ec.isLowS(sig.slice(0, -1));
};
/**
* Get a small integer from an opcode (OP_0-OP_16).
* @param {Number} index
* @returns {Number}
*/
exports.getSmall = function getSmall(op) {
assert(typeof op === 'number');
if (op === exports.opcodes.OP_0)
return 0;
if (op >= exports.opcodes.OP_1 && op <= exports.opcodes.OP_16)
return op - 0x50;
return -1;
};
/**
* Test whether the data element is a ripemd160 hash.
* @param {Buffer?} hash
@ -346,34 +400,6 @@ exports.isSignature = function isSignature(sig) {
return Buffer.isBuffer(sig) && sig.length >= 9 && sig.length <= 73;
};
/**
* Test whether the data element is a null dummy (a zero-length array).
* @param {Buffer?} data
* @returns {Boolean}
*/
exports.isDummy = function isDummy(data) {
return Buffer.isBuffer(data) && data.length === 0;
};
/**
* Test whether the data element is a compressed key.
* @param {Buffer} key
* @returns {Boolean}
*/
exports.isCompressedEncoding = function isCompressedEncoding(key) {
assert(Buffer.isBuffer(key));
if (key.length !== 33)
return false;
if (key[0] !== 0x02 && key[0] !== 0x03)
return false;
return true;
};
/**
* Test whether the data element is a valid key.
* @param {Buffer} key
@ -399,6 +425,24 @@ exports.isKeyEncoding = function isKeyEncoding(key) {
return true;
};
/**
* Test whether the data element is a compressed key.
* @param {Buffer} key
* @returns {Boolean}
*/
exports.isCompressedEncoding = function isCompressedEncoding(key) {
assert(Buffer.isBuffer(key));
if (key.length !== 33)
return false;
if (key[0] !== 0x02 && key[0] !== 0x03)
return false;
return true;
};
/**
* Test a signature to see if it abides by BIP66.
* @see https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki

View File

@ -34,6 +34,36 @@ function Opcode(value, data) {
this.data = data || null;
}
/**
* Check to see if a pushdata abides by minimaldata.
* @returns {Boolean}
*/
Opcode.prototype.isMinimal = function isMinimal() {
if (!this.data)
return true;
if (this.data.length === 0)
return this.value === opcodes.OP_0;
if (this.data.length === 1 && this.data[0] >= 1 && this.data[0] <= 16)
return false;
if (this.data.length === 1 && this.data[0] === 0x81)
return false;
if (this.data.length <= 75)
return this.value === this.data.length;
if (this.data.length <= 255)
return this.value === opcodes.OP_PUSHDATA1;
if (this.data.length <= 65535)
return this.value === opcodes.OP_PUSHDATA2;
return true;
};
/**
* Encode the opcode to a buffer writer.
* @param {BufferWriter} bw

View File

@ -507,6 +507,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
var alt = [];
var state = [];
var negate = 0;
var minimal = false;
var op, code, data;
var val, v1, v2, v3;
var num, n1, n2, n3;
@ -518,6 +519,12 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (version == null)
version = 0;
if (flags & common.flags.VERIFY_MINIMALDATA)
minimal = true;
if (this.getSize() > consensus.MAX_SCRIPT_SIZE)
throw new ScriptError('SCRIPT_SIZE');
@ -536,7 +543,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
// Note that minimaldata is not checked
// on unexecuted branches of code.
if (negate === 0) {
if (!Script.isMinimal(data, op, flags))
if (minimal && !code.isMinimal())
throw new ScriptError('MINIMALDATA', op, ip);
stack.push(data);
}
@ -1180,8 +1187,8 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
if (version === 0)
subscript.removeData(sig);
Script.validateSignature(sig, flags);
Script.validateKey(key, flags, version);
validateSignature(sig, flags);
validateKey(key, flags, version);
if (sig.length > 0) {
type = sig[sig.length - 1];
@ -1259,8 +1266,8 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
sig = stack.top(-isig);
key = stack.top(-ikey);
Script.validateSignature(sig, flags);
Script.validateKey(key, flags, version);
validateSignature(sig, flags);
validateKey(key, flags, version);
if (sig.length > 0) {
type = sig[sig.length - 1];
@ -1293,7 +1300,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, value, vers
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
if (flags & Script.flags.VERIFY_NULLDUMMY) {
if (!Script.isDummy(stack.top(-1)))
if (stack.top(-1).length !== 0)
throw new ScriptError('SIG_NULLDUMMY', op, ip);
}
@ -1526,7 +1533,7 @@ Script.prototype.removeData = function removeData(data) {
if (!op.data)
continue;
if (!Script.isMinimal(op.data, op.value))
if (!op.isMinimal())
continue;
if (util.equal(op.data, data))
@ -1571,57 +1578,16 @@ Script.prototype.indexOf = function indexOf(data) {
};
/**
* Check to see if a pushdata Buffer abides by minimaldata.
* @param {Buffer} data
* @param {Number} opcode
* @param {Number?} flags
* @returns {Boolean}
*/
Script.isMinimal = function isMinimal(data, opcode, flags) {
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (!(flags & Script.flags.VERIFY_MINIMALDATA))
return true;
if (!data)
return true;
if (data.length === 0)
return opcode === opcodes.OP_0;
if (data.length === 1 && data[0] >= 1 && data[0] <= 16)
return false;
if (data.length === 1 && data[0] === 0x81)
return false;
if (data.length <= 75)
return opcode === data.length;
if (data.length <= 255)
return opcode === opcodes.OP_PUSHDATA1;
if (data.length <= 65535)
return opcode === opcodes.OP_PUSHDATA2;
return true;
};
/**
* Test a buffer to see if it is valid
* Test a script to see if it is valid
* script code (no non-existent opcodes).
* @param {Buffer} raw
* @returns {Boolean}
*/
Script.isCode = function isCode(raw) {
var script = Script.fromRaw(raw);
Script.prototype.isCode = function isCode() {
var i, op;
for (i = 0; i < script.code.length; i++) {
op = script.code[i];
for (i = 0; i < this.code.length; i++) {
op = this.code[i];
if (op.data)
continue;
@ -2093,7 +2059,7 @@ Script.prototype.isPubkey = function isPubkey(minimal) {
}
return this.code.length === 2
&& Script.isKey(this.code[0].data)
&& common.isKey(this.code[0].data)
&& this.code[1].value === opcodes.OP_CHECKSIG;
};
@ -2116,7 +2082,7 @@ Script.prototype.isPubkeyhash = function isPubkeyhash(minimal) {
return this.code.length === 5
&& this.code[0].value === opcodes.OP_DUP
&& this.code[1].value === opcodes.OP_HASH160
&& Script.isHash(this.code[2].data)
&& common.isHash(this.code[2].data)
&& this.code[3].value === opcodes.OP_EQUALVERIFY
&& this.code[4].value === opcodes.OP_CHECKSIG;
};
@ -2136,12 +2102,12 @@ Script.prototype.isMultisig = function isMultisig(minimal) {
if (this.raw[this.raw.length - 1] !== opcodes.OP_CHECKMULTISIG)
return false;
n = Script.getSmall(this.raw[this.raw.length - 2]);
n = common.getSmall(this.raw[this.raw.length - 2]);
if (n < 1)
return false;
m = Script.getSmall(this.raw[0]);
m = common.getSmall(this.raw[0]);
if (!(m >= 1 && m <= n))
return false;
@ -2152,11 +2118,11 @@ Script.prototype.isMultisig = function isMultisig(minimal) {
for (i = 1; i < n + 1; i++) {
op = this.code[i];
if (!Script.isKey(op.data))
if (!common.isKey(op.data))
return false;
if (minimal) {
if (!Script.isMinimal(op.data, op.value))
if (!op.isMinimal())
return false;
}
}
@ -2202,7 +2168,7 @@ Script.prototype.isNulldata = function isNulldata(minimal) {
return false;
if (this.raw.length === 2)
return Script.getSmall(this.raw[1]) !== -1;
return common.getSmall(this.raw[1]) !== -1;
if (this.raw[1] >= 0x01 && this.raw[1] <= 0x4b)
return this.raw[1] + 2 === this.raw.length;
@ -2287,7 +2253,7 @@ Script.prototype.toProgram = function toProgram() {
if (!this.isProgram())
return;
version = Script.getSmall(this.raw[0]);
version = common.getSmall(this.raw[0]);
data = this.raw.slice(2);
return new Program(version, data);
@ -2412,7 +2378,7 @@ Script.prototype.isPubkeyInput = function isPubkeyInput() {
if (this.raw[0] > opcodes.OP_PUSHDATA4)
return false;
return this.code.length === 1 && Script.isSignature(this.code[0].data);
return this.code.length === 1 && common.isSignature(this.code[0].data);
};
/**
@ -2432,8 +2398,8 @@ Script.prototype.isPubkeyhashInput = function isPubkeyhashInput() {
return false;
return this.code.length === 2
&& Script.isSignature(this.code[0].data)
&& Script.isKey(this.code[1].data);
&& common.isSignature(this.code[0].data)
&& common.isKey(this.code[1].data);
};
/**
@ -2463,7 +2429,7 @@ Script.prototype.isMultisigInput = function isMultisigInput() {
return false;
for (i = 1; i < this.code.length; i++) {
if (!Script.isSignature(this.code[i].data))
if (!common.isSignature(this.code[i].data))
return false;
}
@ -2477,7 +2443,7 @@ Script.prototype.isMultisigInput = function isMultisigInput() {
*/
Script.prototype.isScripthashInput = function isScripthashInput() {
var op;
var op, redeem;
if (this.raw.length < 2)
return false;
@ -2499,16 +2465,18 @@ Script.prototype.isScripthashInput = function isScripthashInput() {
// key, and we ensure that it is at least
// a script that does not use undefined
// opcodes.
if (Script.isDummy(op.data))
if (op.data.length === 0)
return false;
if (Script.isSignatureEncoding(op.data))
if (common.isSignatureEncoding(op.data))
return false;
if (Script.isKeyEncoding(op.data))
if (common.isKeyEncoding(op.data))
return false;
if (!Script.isCode(op.data))
redeem = Script.fromRaw(op.data);
if (!redeem.isCode())
return false;
return true;
@ -2537,7 +2505,7 @@ Script.getCoinbaseHeight = function getCoinbaseHeight(raw) {
return -1;
// Small ints are allowed.
height = Script.getSmall(raw[0]);
height = common.getSmall(raw[0]);
if (height !== -1)
return height;
@ -2623,25 +2591,29 @@ Script.prototype.push = function push(data) {
/**
* Shift an item off of the `code` array.
* @returns {Buffer|Number}
* @returns {Buffer}
*/
Script.prototype.shift = function shift() {
var op = this.code.shift();
if (!op)
return;
return null;
return op.data || op.value;
};
/**
* Pop an item off of the `code` array.
* @returns {Buffer|Number}
* @returns {Buffer}
*/
Script.prototype.pop = function push(data) {
var op = this.code.pop();
if (!op)
return;
return null;
return op.data || op.value;
};
@ -2653,8 +2625,10 @@ Script.prototype.pop = function push(data) {
Script.prototype.remove = function remove(i) {
var op = this.code.splice(i, 1)[0];
if (!op)
return;
return null;
return op.data || op.value;
};
@ -2666,19 +2640,21 @@ Script.prototype.remove = function remove(i) {
Script.prototype.insert = function insert(i, data) {
assert(i <= this.code.length, 'Index out of bounds.');
this.code.splice(i, 0, Opcode.from(data))[0];
this.code.splice(i, 0, Opcode.from(data));
};
/**
* Get an item from the `code` array.
* @param {Number} index
* @returns {Buffer|Number}
* @returns {Buffer}
*/
Script.prototype.get = function get(i) {
var op = this.code[i];
if (!op)
return;
return null;
return op.data || op.value;
};
@ -2690,9 +2666,11 @@ Script.prototype.get = function get(i) {
Script.prototype.getSmall = function getSmall(i) {
var op = this.code[i];
if (!op)
return -1;
return Script.getSmall(op.value);
return common.getSmall(op.value);
};
/**
@ -2709,7 +2687,7 @@ Script.prototype.getNumber = function getNumber(i) {
return new BN(small);
if (!op || !op.data || op.data.length > 5)
return;
return null;
return Script.num(op.data, Script.flags.VERIFY_NONE, 5);
};
@ -2722,8 +2700,10 @@ Script.prototype.getNumber = function getNumber(i) {
Script.prototype.getString = function getString(i) {
var op = this.code[i];
if (!op || !op.data)
return;
return null;
return op.data.toString('utf8');
};
@ -2746,16 +2726,6 @@ Script.prototype.set = function set(i, data) {
this.code[i] = Opcode.from(data);
};
/**
* Test whether the data element is a ripemd160 hash.
* @param {Buffer?} hash
* @returns {Boolean}
*/
Script.isHash = function isHash(hash) {
return common.isHash(hash);
};
/**
* Test whether the data element is a public key. Note that
* this does not verify the format of the key, only the length.
@ -2778,153 +2748,6 @@ Script.isSignature = function isSignature(sig) {
return common.isSignature(sig);
};
/**
* Test whether the data element is a null dummy (a zero-length array).
* @param {Buffer?} data
* @returns {Boolean}
*/
Script.isDummy = function isDummy(data) {
return common.isDummy(data);
};
/**
* Test whether the data element is a valid key if VERIFY_STRICTENC is enabled.
* @param {Buffer} key
* @param {VerifyFlags?} flags
* @returns {Boolean}
* @throws {ScriptError}
*/
Script.validateKey = function validateKey(key, flags, version) {
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
assert(Buffer.isBuffer(key));
if (flags & Script.flags.VERIFY_STRICTENC) {
if (!Script.isKeyEncoding(key))
throw new ScriptError('PUBKEYTYPE');
}
if (version === 1) {
if (flags & Script.flags.VERIFY_WITNESS_PUBKEYTYPE) {
if (!Script.isCompressedEncoding(key))
throw new ScriptError('WITNESS_PUBKEYTYPE');
}
}
return true;
};
/**
* Test whether the data element is a compressed key.
* @param {Buffer} key
* @returns {Boolean}
*/
Script.isCompressedEncoding = function isCompressedEncoding(key) {
return common.isCompressedEncoding(key);
};
/**
* Test whether the data element is a valid key.
* @param {Buffer} key
* @returns {Boolean}
*/
Script.isKeyEncoding = function isKeyEncoding(key) {
return common.isKeyEncoding(key);
};
/**
* Test whether the data element is a valid signature based
* on the encoding, S value, and sighash type. Requires
* VERIFY_DERSIG|VERIFY_LOW_S|VERIFY_STRICTENC, VERIFY_LOW_S
* and VERIFY_STRING_ENC to be enabled respectively. Note that
* this will allow zero-length signatures.
* @param {Buffer} sig
* @param {VerifyFlags?} flags
* @returns {Boolean}
* @throws {ScriptError}
*/
Script.validateSignature = function validateSignature(sig, flags) {
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
assert(Buffer.isBuffer(sig));
// Allow empty sigs
if (sig.length === 0)
return true;
if ((flags & Script.flags.VERIFY_DERSIG)
|| (flags & Script.flags.VERIFY_LOW_S)
|| (flags & Script.flags.VERIFY_STRICTENC)) {
if (!Script.isSignatureEncoding(sig))
throw new ScriptError('SIG_DER');
}
if (flags & Script.flags.VERIFY_LOW_S) {
if (!Script.isLowDER(sig))
throw new ScriptError('SIG_HIGH_S');
}
if (flags & Script.flags.VERIFY_STRICTENC) {
if (!Script.isHashType(sig))
throw new ScriptError('SIG_HASHTYPE');
}
return true;
};
/**
* Test a signature to see if it abides by BIP66.
* @see https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
* @param {Buffer} sig
* @returns {Boolean}
*/
Script.isSignatureEncoding = function isSignatureEncoding(sig) {
return common.isSignatureEncoding(sig);
};
/**
* Test a signature to see whether it contains a valid sighash type.
* @param {Buffer} sig
* @returns {Boolean}
*/
Script.isHashType = function isHashType(sig) {
var type;
assert(Buffer.isBuffer(sig));
if (sig.length === 0)
return false;
type = sig[sig.length - 1] & ~Script.hashType.ANYONECANPAY;
if (!(type >= Script.hashType.ALL && type <= Script.hashType.SINGLE))
return false;
return true;
};
/**
* Test a signature to see whether it contains a low S value.
* @param {Buffer} sig
* @returns {Boolean}
*/
Script.isLowDER = function isLowDER(sig) {
if (!Script.isSignatureEncoding(sig))
return false;
return ec.isLowS(sig.slice(0, -1));
};
/**
* Test the script to see if it contains only push ops.
* Push ops are: OP_1NEGATE, OP_0-OP_16 and all PUSHDATAs.
@ -3031,16 +2854,12 @@ Script.prototype.getScripthashSigops = function getScripthashSigops(input) {
* Count the sigops for a program.
* @param {Program} program
* @param {Witness} witness
* @param {VerifyFlags} flags
* @returns {Number} sigop count
*/
Script.witnessSigops = function witnessSigops(program, witness, flags) {
Script.witnessSigops = function witnessSigops(program, witness) {
var redeem;
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if (program.version === 0) {
if (program.data.length === 20)
return 1;
@ -3057,25 +2876,15 @@ Script.witnessSigops = function witnessSigops(program, witness, flags) {
/**
* Count the sigops in a script, taking into account witness programs.
* @param {Script} input
* @param {Script} output
* @param {Witness} witness
* @param {VerifyFlags} flags
* @returns {Number} sigop count
*/
Script.getWitnessSigops = function getWitnessSigops(input, output, witness, flags) {
Script.prototype.getWitnessSigops = function getWitnessSigops(input, witness) {
var redeem;
if (flags == null)
flags = Script.flags.STANDARD_VERIFY_FLAGS;
if ((flags & Script.flags.VERIFY_WITNESS) === 0)
return 0;
assert((flags & Script.flags.VERIFY_P2SH) !== 0);
if (output.isProgram())
return Script.witnessSigops(output.toProgram(), witness, flags);
if (this.isProgram())
return Script.witnessSigops(this.toProgram(), witness);
// This is a unique situation in terms of consensus
// rules. We can just grab the redeem script without
@ -3084,10 +2893,10 @@ Script.getWitnessSigops = function getWitnessSigops(input, output, witness, flag
// which checks for parse errors and will return
// false if one is found. Even the bitcoind code
// does not check the return value of GetOp.
if (output.isScripthash() && input.isPushOnly()) {
if (this.isScripthash() && input.isPushOnly()) {
redeem = input.getRedeem();
if (redeem && redeem.isProgram())
return Script.witnessSigops(redeem.toProgram(), witness, flags);
return Script.witnessSigops(redeem.toProgram(), witness);
}
return 0;
@ -3164,25 +2973,6 @@ Script.fromString = function fromString(code) {
return new Script().fromString(code);
};
/**
* Get a small integer from an opcode (OP_0-OP_16).
* @param {Number} index
* @returns {Number}
*/
Script.getSmall = function getSmall(op) {
if (typeof op !== 'number')
return -1;
if (op === opcodes.OP_0)
return 0;
if (op >= opcodes.OP_1 && op <= opcodes.OP_16)
return op - 0x50;
return -1;
};
/**
* Verify an input and output script, and a witness if present.
* @param {Script} input
@ -3633,6 +3423,73 @@ function sortKeys(keys) {
});
}
/**
* Test whether the data element is a valid key if VERIFY_STRICTENC is enabled.
* @param {Buffer} key
* @param {VerifyFlags?} flags
* @returns {Boolean}
* @throws {ScriptError}
*/
function validateKey(key, flags, version) {
assert(Buffer.isBuffer(key));
assert(typeof flags === 'number');
if (flags & Script.flags.VERIFY_STRICTENC) {
if (!common.isKeyEncoding(key))
throw new ScriptError('PUBKEYTYPE');
}
if (version === 1) {
if (flags & Script.flags.VERIFY_WITNESS_PUBKEYTYPE) {
if (!common.isCompressedEncoding(key))
throw new ScriptError('WITNESS_PUBKEYTYPE');
}
}
return true;
}
/**
* Test whether the data element is a valid signature based
* on the encoding, S value, and sighash type. Requires
* VERIFY_DERSIG|VERIFY_LOW_S|VERIFY_STRICTENC, VERIFY_LOW_S
* and VERIFY_STRING_ENC to be enabled respectively. Note that
* this will allow zero-length signatures.
* @param {Buffer} sig
* @param {VerifyFlags?} flags
* @returns {Boolean}
* @throws {ScriptError}
*/
function validateSignature(sig, flags) {
assert(Buffer.isBuffer(sig));
assert(typeof flags === 'number');
// Allow empty sigs
if (sig.length === 0)
return true;
if ((flags & Script.flags.VERIFY_DERSIG)
|| (flags & Script.flags.VERIFY_LOW_S)
|| (flags & Script.flags.VERIFY_STRICTENC)) {
if (!common.isSignatureEncoding(sig))
throw new ScriptError('SIG_DER');
}
if (flags & Script.flags.VERIFY_LOW_S) {
if (!common.isLowDER(sig))
throw new ScriptError('SIG_HIGH_S');
}
if (flags & Script.flags.VERIFY_STRICTENC) {
if (!common.isHashType(sig))
throw new ScriptError('SIG_HASHTYPE');
}
return true;
}
/*
* Expose
*/