more script data extraction improvements.
This commit is contained in:
parent
b389dd1b5f
commit
ebbb417283
@ -909,7 +909,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
|
|||||||
val = stack.pop();
|
val = stack.pop();
|
||||||
|
|
||||||
if (flags.verifynulldummy !== false) {
|
if (flags.verifynulldummy !== false) {
|
||||||
if (!Array.isArray(val) || val.length > 0)
|
if (!script.isDummy(val))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,6 +1170,15 @@ script.createMultisig = function createMultisig(keys, m, n) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.createScripthash = function createScripthash(s) {
|
||||||
|
assert(Array.isArray(s));
|
||||||
|
return [
|
||||||
|
'hash160',
|
||||||
|
utils.ripesha(script.encode(s)),
|
||||||
|
'equal'
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
script.redeem = function redeem(s) {
|
script.redeem = function redeem(s) {
|
||||||
if (!Array.isArray(s[s.length - 1]))
|
if (!Array.isArray(s[s.length - 1]))
|
||||||
return;
|
return;
|
||||||
@ -1249,13 +1258,13 @@ script.spendable = function spendable(s, lockTime) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
script.getInputData = function getData(s, prev) {
|
script.getInputData = function getData(s, prev) {
|
||||||
var output;
|
var output, type;
|
||||||
|
|
||||||
if (prev && !script.isScripthash(prev)) {
|
if (prev && !script.isScripthash(prev)) {
|
||||||
output = script.getOutputData(prev);
|
output = script.getOutputData(prev);
|
||||||
output.side = 'input';
|
output.side = 'input';
|
||||||
|
|
||||||
// We could call getInputData, but
|
// We could call _getInputData, but
|
||||||
// we really only need the signatures.
|
// we really only need the signatures.
|
||||||
if (output.type === 'pubkey') {
|
if (output.type === 'pubkey') {
|
||||||
output.signatures = [s[0]];
|
output.signatures = [s[0]];
|
||||||
@ -1264,6 +1273,11 @@ script.getInputData = function getData(s, prev) {
|
|||||||
output.keys = [s[1]];
|
output.keys = [s[1]];
|
||||||
} else if (output.type === 'multisig') {
|
} else if (output.type === 'multisig') {
|
||||||
output.signatures = s.slice(1);
|
output.signatures = s.slice(1);
|
||||||
|
} else if (output.type === 'scripthash') {
|
||||||
|
// Scripthash is the only case where
|
||||||
|
// we get more data from the input
|
||||||
|
// than the output.
|
||||||
|
output = script._getInputData(s, output.type);
|
||||||
} else {
|
} else {
|
||||||
output.signatures = script.getUnknownData(s).signatures;
|
output.signatures = script.getUnknownData(s).signatures;
|
||||||
}
|
}
|
||||||
@ -1271,13 +1285,24 @@ script.getInputData = function getData(s, prev) {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
return script._getInputData(s);
|
if (script.isPubkeyInput(s))
|
||||||
|
type = 'pubkey';
|
||||||
|
else if (script.isPubkeyhashInput(s))
|
||||||
|
type = 'pubkeyhash';
|
||||||
|
else if (script.isMultisigInput(s))
|
||||||
|
type = 'multisig';
|
||||||
|
else if (script.isScripthashInput(s))
|
||||||
|
type = 'scripthash';
|
||||||
|
|
||||||
|
return script._getInputData(s, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
script._getInputData = function _getInputData(s) {
|
script._getInputData = function _getInputData(s, type) {
|
||||||
var sig, key, hash, raw, redeem, lock, hash, address, input, output;
|
var sig, key, hash, raw, redeem, lock, hash, address, input, output;
|
||||||
|
|
||||||
if (script.isPubkeyInput(s)) {
|
assert(typeof type === 'string');
|
||||||
|
|
||||||
|
if (type === 'pubkey') {
|
||||||
sig = s[0];
|
sig = s[0];
|
||||||
return {
|
return {
|
||||||
type: 'pubkey',
|
type: 'pubkey',
|
||||||
@ -1287,7 +1312,7 @@ script._getInputData = function _getInputData(s) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script.isPubkeyhashInput(s)) {
|
if (type === 'pubkeyhash') {
|
||||||
sig = s[0];
|
sig = s[0];
|
||||||
key = s[1];
|
key = s[1];
|
||||||
hash = bcoin.wallet.key2hash(key);
|
hash = bcoin.wallet.key2hash(key);
|
||||||
@ -1302,7 +1327,7 @@ script._getInputData = function _getInputData(s) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script.isMultisigInput(s)) {
|
if (type === 'multisig') {
|
||||||
sig = s.slice(1);
|
sig = s.slice(1);
|
||||||
return {
|
return {
|
||||||
type: 'multisig',
|
type: 'multisig',
|
||||||
@ -1313,15 +1338,15 @@ script._getInputData = function _getInputData(s) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (script.isScripthashInput(s)) {
|
if (type === 'scripthash') {
|
||||||
raw = s[s.length - 1];
|
raw = s[s.length - 1];
|
||||||
redeem = script.decode(raw);
|
redeem = script.decode(raw);
|
||||||
lock = script.lockTime(redeem);
|
lock = script.lockTime(redeem);
|
||||||
hash = bcoin.wallet.key2hash(raw);
|
hash = bcoin.wallet.key2hash(raw);
|
||||||
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
address = bcoin.wallet.hash2addr(hash, 'scripthash');
|
||||||
input = script.getInputData(s.slice(0, -1));
|
|
||||||
delete input.none;
|
|
||||||
output = script.getOutputData(script.subscript(redeem));
|
output = script.getOutputData(script.subscript(redeem));
|
||||||
|
input = script._getInputData(s.slice(0, -1), output.type);
|
||||||
|
delete input.none;
|
||||||
return utils.merge(input, output, {
|
return utils.merge(input, output, {
|
||||||
type: 'scripthash',
|
type: 'scripthash',
|
||||||
side: 'input',
|
side: 'input',
|
||||||
@ -1620,8 +1645,10 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
|||||||
script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
||||||
var i, o;
|
var i, o;
|
||||||
|
|
||||||
// We need to rule out scripthash
|
// We need to rule out scripthash because
|
||||||
// because it may look like multisig
|
// it may look like multisig. This is
|
||||||
|
// strange because it's technically a
|
||||||
|
// recursive call.
|
||||||
if (script.isScripthashInput(s))
|
if (script.isScripthashInput(s))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1664,7 +1691,7 @@ script.isMultisigInput = function isMultisigInput(s, keys, tx, i) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isScripthashInput = function isScripthashInput(s, data) {
|
script.isScripthashInput = function isScripthashInput(s, data, strict) {
|
||||||
var raw, redeem;
|
var raw, redeem;
|
||||||
|
|
||||||
// Grab the raw redeem script.
|
// Grab the raw redeem script.
|
||||||
@ -1680,6 +1707,25 @@ script.isScripthashInput = function isScripthashInput(s, data) {
|
|||||||
if (!Array.isArray(raw))
|
if (!Array.isArray(raw))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// If the last data element is a valid
|
||||||
|
// signature or key, it's _extremely_
|
||||||
|
// unlikely this is a scripthash.
|
||||||
|
if (script.isSignatureEncoding(raw))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (script.isKeyEncoding(raw))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check data against last array in case
|
||||||
|
// a raw redeem script was passed in.
|
||||||
|
if (data && utils.isEqual(data, raw))
|
||||||
|
return raw;
|
||||||
|
|
||||||
|
// Return here if we do not want to check
|
||||||
|
// against standard transaction types.
|
||||||
|
if (!strict)
|
||||||
|
return raw;
|
||||||
|
|
||||||
// P2SH redeem scripts can be nonstandard: make
|
// P2SH redeem scripts can be nonstandard: make
|
||||||
// it easier for other functions to parse this.
|
// it easier for other functions to parse this.
|
||||||
redeem = script.subscript(script.decode(raw));
|
redeem = script.subscript(script.decode(raw));
|
||||||
@ -1694,11 +1740,6 @@ script.isScripthashInput = function isScripthashInput(s, data) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check data against last array in case
|
|
||||||
// a raw redeem script was passed in.
|
|
||||||
if (data && utils.isEqual(data, raw))
|
|
||||||
return raw;
|
|
||||||
|
|
||||||
// Test against all other script types
|
// Test against all other script types
|
||||||
if (!script.isPubkey(redeem, data)
|
if (!script.isPubkey(redeem, data)
|
||||||
&& !script.isPubkeyhash(redeem, data)
|
&& !script.isPubkeyhash(redeem, data)
|
||||||
@ -1840,7 +1881,7 @@ script.isSignature = function isSignature(sig) {
|
|||||||
return sig.length >= 9 && sig.length <= 73;
|
return sig.length >= 9 && sig.length <= 73;
|
||||||
};
|
};
|
||||||
|
|
||||||
script.isEmpty = function isEmpty(data) {
|
script.isDummy = function isDummy(data) {
|
||||||
if (!utils.isBuffer(data))
|
if (!utils.isBuffer(data))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@ -423,7 +423,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
// and increment the total number of
|
// and increment the total number of
|
||||||
// signatures.
|
// signatures.
|
||||||
if (ki < len && signatures < m) {
|
if (ki < len && signatures < m) {
|
||||||
if (bcoin.script.isEmpty(input.script[ki])) {
|
if (bcoin.script.isDummy(input.script[ki])) {
|
||||||
input.script[ki] = signature;
|
input.script[ki] = signature;
|
||||||
signatures++;
|
signatures++;
|
||||||
}
|
}
|
||||||
@ -433,7 +433,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
|
|||||||
if (signatures >= m) {
|
if (signatures >= m) {
|
||||||
// Remove empty slots left over.
|
// Remove empty slots left over.
|
||||||
for (i = len - 1; i >= 1; i--) {
|
for (i = len - 1; i >= 1; i--) {
|
||||||
if (bcoin.script.isEmpty(input.script[i])) {
|
if (bcoin.script.isDummy(input.script[i])) {
|
||||||
input.script.splice(i, 1);
|
input.script.splice(i, 1);
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user