script standardness.

This commit is contained in:
Christopher Jeffrey 2016-01-14 11:45:33 -08:00
parent bfca638025
commit 282639b5b1
2 changed files with 46 additions and 63 deletions

View File

@ -942,6 +942,25 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
return true;
};
script.num = function num(value, useNum) {
if (utils.isFinite(value))
return useNum ? value : new bn(value, 'le');
assert(utils.isBuffer(value));
value = new bn(value, 'le');
if (useNum) {
try {
return value.toNumber();
} catch (e) {
return 0;
}
}
return value;
};
script.redeem = function redeem(keys, m, n) {
if (keys.length !== n)
throw new Error(n + ' keys are required to generate redeem script');
@ -1041,15 +1060,10 @@ script.spendable = function spendable(s, lockTime) {
script.isPubkey = function isPubkey(s, key) {
var res;
s = script.subscript(s);
if (script.lockTime(s))
s = s.slice(3);
if (s.length !== 2)
return false;
res = Array.isArray(s[0]) && s[1] === 'checksig';
res = script.isKey(s[0]) && s[1] === 'checksig';
if (!res)
return false;
@ -1063,17 +1077,12 @@ script.isPubkey = function isPubkey(s, key) {
script.isPubkeyhash = function isPubkeyhash(s, hash) {
var res;
s = script.subscript(s);
if (script.lockTime(s))
s = s.slice(3);
if (s.length !== 5)
return false;
res = s[0] === 'dup'
&& s[1] === 'hash160'
&& Array.isArray(s[2])
&& script.isHash(s[2])
&& s[3] === 'eqverify'
&& s[4] === 'checksig';
@ -1090,11 +1099,6 @@ script.isMultisig = function isMultisig(s, keys) {
var m, n, i, j;
var total = 0;
s = script.subscript(s);
if (script.lockTime(s))
s = s.slice(3);
if (s.length < 4)
return false;
@ -1103,23 +1107,14 @@ script.isMultisig = function isMultisig(s, keys) {
n = s[s.length - 2];
if (Array.isArray(n)) {
if (n.length !== 1)
return false;
n = n[0];
}
// Bitcoind technically doesn't check for the
// 15 limit here. It just counts the sigops
// later.
if (!(n >= 1 && n <= 15))
return false;
m = s[0];
if (Array.isArray(m)) {
if (m.length !== 1)
return false;
m = m[0];
}
if (!(m >= 1 && m <= n))
return false;
@ -1127,7 +1122,7 @@ script.isMultisig = function isMultisig(s, keys) {
return false;
for (i = 1; i < n + 1; i++) {
if (!Array.isArray(s[i]))
if (!script.isKey(s[i]))
return false;
}
@ -1151,17 +1146,11 @@ script.isMultisig = function isMultisig(s, keys) {
script.isScripthash = function isScripthash(s, hash) {
var res;
s = script.subscript(s);
if (script.lockTime(s))
s = s.slice(3);
if (s.length !== 3)
return false;
res = s[0] === 'hash160'
&& Array.isArray(s[1])
&& s[1].length === 20
&& script.isHash(s[1])
&& s[2] === 'eq';
if (!res)
@ -1174,8 +1163,6 @@ script.isScripthash = function isScripthash(s, hash) {
};
script.isNulldata = function isNulldata(s) {
s = script.subscript(s);
if (s.length !== 2)
return false;
@ -1188,7 +1175,7 @@ script.nulldata = function nulldata(s) {
if (!script.isNulldata(s))
return false;
return script.subscript(s)[1];
return s[1];
};
script.standardInput = function standardInput(s) {
@ -1200,8 +1187,6 @@ script.standardInput = function standardInput(s) {
};
script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
s = script.subscript(s);
if (s.length !== 1 || !Array.isArray(s[0]))
return false;
@ -1221,8 +1206,6 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
};
script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
s = script.subscript(s);
if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1]))
return false;
@ -1246,8 +1229,6 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
if (script.isScripthashInput(s))
return false;
s = script.subscript(s);
if (s.length < 3)
return false;
@ -1286,8 +1267,6 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
script.isScripthashInput = function isScripthashInput(s, data) {
var raw, redeem;
s = script.subscript(s);
// Grab the raw redeem script.
raw = s[s.length - 1];
@ -1303,7 +1282,7 @@ script.isScripthashInput = function isScripthashInput(s, data) {
// P2SH redeem scripts can be nonstandard: make
// it easier for other functions to parse this.
redeem = script.normalize(raw);
redeem = script.subscript(script.decode(raw));
// Get the "real" scriptSig
s = s.slice(0, -1);
@ -1429,6 +1408,13 @@ script.isCoinbase = function isCoinbase(s, block, strict) {
return coinbase;
};
script.isHash = function isHash(hash) {
if (!utils.isBuffer(hash))
return false;
return hash.length === 20;
};
script.isKey = function isKey(key) {
if (!utils.isBuffer(key))
return false;
@ -1636,7 +1622,9 @@ script.pushOnly = function pushOnly(s) {
var i, op;
for (i = 0; i < s.length; i++) {
op = s[i];
if (Array.isArray(op) || (op >= 1 && op <= 16))
// if (Array.isArray(op) || (constants.opcodes[op] <= constants.opcodes['16']))
// continue;
if (Array.isArray(op) || (op >= -1 && op <= 16))
continue;
if (constants.opcodes[op] == null)
return false;
@ -1678,7 +1666,7 @@ script.sigopsScripthash = function sigopsScripthash(s) {
if (!script.pushOnly(s))
return 0;
s = script.decode(s[s.length - 1]);
s = script.subscript(script.decode(s[s.length - 1]));
return script.sigops(s, true);
};
@ -1686,11 +1674,6 @@ script.sigopsScripthash = function sigopsScripthash(s) {
script.args = function args(s) {
var keys, m;
s = bcoin.script.subscript(s);
if (script.lockTime(s))
s = s.slice(3);
if (script.isPubkey(s))
return 1;

View File

@ -177,7 +177,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
// P2SH
if (bcoin.script.isScripthash(s)) {
assert(redeem);
s = bcoin.script.normalize(redeem);
s = bcoin.script.subscript(bcoin.script.decode(redeem));
} else {
redeem = null;
}
@ -268,7 +268,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
// P2SH
if (bcoin.script.isScripthash(s)) {
s = bcoin.script.normalize(redeem);
s = bcoin.script.subscript(redeem);
// Decrement `len` to avoid the redeem script
len--;
}
@ -325,7 +325,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
// Something is very wrong here. Abort.
if (len - 1 > n)
return;
return false;
// Count the number of current signatures.
signatures = 0;
@ -336,7 +336,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
// Signatures are already finalized.
if (signatures === m && len - 1 === m)
return;
return true;
// This can happen in a case where another
// implementation adds signatures willy-nilly
@ -362,7 +362,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
// script. We tried to sign a transaction
// that is not redeemable by us.
if (ki === keys.length)
return;
return false;
// Offset key index by one to turn it into
// "sig index". Accounts for OP_0 byte at
@ -740,7 +740,7 @@ TX.prototype.maxSize = function maxSize() {
// the isMultisig clause.
// OP_PUSHDATA2 [redeem]
size += 3 + s.length;
s = bcoin.script.normalize(s);
s = bcoin.script.subscript(bcoin.script.decode(s));
}
if (bcoin.script.isPubkey(s)) {
@ -1169,7 +1169,7 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) {
if (!Array.isArray(s))
return false;
s = bcoin.script.decode(s);
s = bcoin.script.subscript(bcoin.script.decode(s));
if (bcoin.script.standard(s)) {
targs = bcoin.script.args(s);