implement all sighash types. add hasUnspent().
This commit is contained in:
parent
b0a3a0e853
commit
c68ab4ee7d
@ -135,7 +135,7 @@ exports.hashType = {
|
||||
all: 1,
|
||||
none: 2,
|
||||
single: 3,
|
||||
anyonecaypay: 0x80
|
||||
anyonecanpay: 0x80
|
||||
};
|
||||
|
||||
exports.rhashType = Object.keys(exports.hashType).reduce(function(out, type) {
|
||||
|
||||
@ -88,19 +88,21 @@ script.encode = function encode(s) {
|
||||
return res;
|
||||
};
|
||||
|
||||
script.subscript = function subscript(s) {
|
||||
script.subscript = function subscript(s, lastSep) {
|
||||
if (!s)
|
||||
return [];
|
||||
|
||||
var lastSep = -1;
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
if (s[i] === 'codesep')
|
||||
lastSep = i;
|
||||
else if (s[i] === 'checksig' ||
|
||||
s[i] === 'checksigverify' ||
|
||||
s[i] === 'checkmultisig' ||
|
||||
s[i] === 'checkmultisigverify') {
|
||||
break;
|
||||
if (lastSep == null) {
|
||||
lastSep = -1;
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
if (s[i] === 'codesep')
|
||||
lastSep = i;
|
||||
else if (s[i] === 'checksig' ||
|
||||
s[i] === 'checksigverify' ||
|
||||
s[i] === 'checkmultisig' ||
|
||||
s[i] === 'checkmultisigverify') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,13 +581,13 @@ script.execute = function execute(s, stack, tx, index) {
|
||||
var pub = stack.pop();
|
||||
var sig = stack.pop();
|
||||
var type = sig[sig.length - 1];
|
||||
if (!constants.rhashType[type & 0x7f])
|
||||
if (!constants.rhashType[type & 0x1f])
|
||||
return false;
|
||||
|
||||
if (!script.isValidSig(sig))
|
||||
return false;
|
||||
|
||||
var subscript = s.slice(lastSep + 1);
|
||||
var subscript = script.subscript(s, lastSep);
|
||||
var hash = tx.subscriptHash(index, subscript, type);
|
||||
|
||||
var res = script.verify(hash, sig.slice(0, -1), pub);
|
||||
@ -633,13 +635,13 @@ script.execute = function execute(s, stack, tx, index) {
|
||||
for (var i = 0; i < m; i++) {
|
||||
var sig = stack.pop();
|
||||
var type = sig[sig.length - 1];
|
||||
if (!constants.rhashType[type & 0x7f])
|
||||
if (!constants.rhashType[type & 0x1f])
|
||||
return false;
|
||||
|
||||
if (!script.isValidSig(sig))
|
||||
return false;
|
||||
|
||||
var subscript = s.slice(lastSep + 1);
|
||||
var subscript = script.subscript(s, lastSep);
|
||||
var hash = tx.subscriptHash(index, subscript, type);
|
||||
|
||||
// Strict order:
|
||||
|
||||
@ -207,6 +207,41 @@ TXPool.prototype.unspent = function unspent() {
|
||||
}, this);
|
||||
};
|
||||
|
||||
TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
|
||||
if (Array.isArray(hash) && hash.length && typeof hash[0] !== 'number') {
|
||||
unspent = this.unspent();
|
||||
var has = hash.map(function(hash) {
|
||||
var h = this.hasUnspent(hash, unspent);
|
||||
if (!h)
|
||||
return false;
|
||||
return h[0];
|
||||
}, this).filter(Boolean);
|
||||
if (has.length !== hash.length)
|
||||
return null;
|
||||
return has;
|
||||
}
|
||||
|
||||
if (Array.isArray(hash))
|
||||
hash = utils.toHex(hash);
|
||||
else if (hash.out)
|
||||
hash = hash.out.hash;
|
||||
else if (hash.tx)
|
||||
hash = hash.tx.hash('hex');
|
||||
else if (hash instanceof bcoin.tx)
|
||||
hash = hash.hash('hex');
|
||||
|
||||
unspent = unspent || this.unspent();
|
||||
|
||||
var has = unspent.filter(function(item) {
|
||||
return item.tx.hash('hex') === hash;
|
||||
});
|
||||
|
||||
if (!has.length)
|
||||
return null;
|
||||
|
||||
return has;
|
||||
};
|
||||
|
||||
TXPool.prototype.pending = function pending() {
|
||||
return Object.keys(this._all).map(function(key) {
|
||||
return this._all[key];
|
||||
|
||||
@ -417,8 +417,43 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
|
||||
copy.inputs.forEach(function(input, i) {
|
||||
input.script = index === i ? s : [];
|
||||
});
|
||||
|
||||
if ((type & 0x1f) === constants.hashType.all) {
|
||||
;
|
||||
} else if ((type & 0x1f) === constants.hashType.none) {
|
||||
copy.outputs = [];
|
||||
copy.inputs.forEach(function(input, i) {
|
||||
if (i !== index)
|
||||
input.seq = 0;
|
||||
});
|
||||
} else if ((type & 0x1f) === constants.hashType.single) {
|
||||
while (copy.outputs.length < index + 1)
|
||||
copy.outputs.push({});
|
||||
while (copy.outputs.length > index + 1)
|
||||
copy.outputs.pop();
|
||||
copy.outputs.forEach(function(output, i) {
|
||||
if (i !== index) {
|
||||
output.script = [];
|
||||
// output.value = new bn('ffffffffffffffff', 'hex');
|
||||
output.value = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
|
||||
output.value.toArray = function() { return this; };
|
||||
}
|
||||
});
|
||||
copy.inputs.forEach(function(input, i) {
|
||||
if (i !== index)
|
||||
input.seq = 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (type & constants.hashType.anyonecanpay) {
|
||||
copy.inputs.length = 1;
|
||||
copy.inputs[0].script = s;
|
||||
}
|
||||
|
||||
var verifyStr = copy.render();
|
||||
|
||||
utils.writeU32(verifyStr, type, verifyStr.length);
|
||||
|
||||
var hash = utils.dsha256(verifyStr);
|
||||
|
||||
return hash;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user