fixes and improvements. allow arbitrary redeem scripts for wallet.

This commit is contained in:
Christopher Jeffrey 2016-01-11 00:10:31 -08:00
parent 442c984c12
commit cf5a117a3e
3 changed files with 33 additions and 36 deletions

View File

@ -739,7 +739,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
key = stack.pop();
sig = stack.pop();
type = sig[sig.length - 1];
if (!script.isKey(key))
return false;
@ -752,11 +751,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
return false;
}
type = sig[sig.length - 1];
if (!constants.hashTypeByVal[type & 0x1f])
return false;
subscript = script.subscript(s, lastSep);
hash = tx.subscriptHash(index, subscript, type);
hash = tx.signatureHash(index, subscript, type);
res = script.checksig(hash, sig.slice(0, -1), key);
if (o === 'checksigverify') {
@ -804,7 +805,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
succ = 0;
for (i = 0, j = 0; i < m && j < n; i++) {
sig = stack.pop();
type = sig[sig.length - 1];
if (flags.strictder !== false) {
if (!script.isValidSig(sig))
@ -814,10 +814,12 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
return false;
}
type = sig[sig.length - 1];
if (!constants.hashTypeByVal[type & 0x1f])
return false;
hash = tx.subscriptHash(index, subscript, type);
hash = tx.signatureHash(index, subscript, type);
res = false;
for (; !res && j < n; j++)
@ -830,15 +832,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
// Extra value
if (stack.length < 1)
return false;
val = stack.pop();
if (flags.verifynulldummy !== false) {
if (stack[stack.length - 1].length > 0)
if (!Array.isArray(val) || val.length > 0)
return false;
}
stack.pop();
// Too many signatures on stack
// if (stack.length > 0)
// return false;
res = succ >= m;
if (o === 'checkmultisigverify') {
@ -982,16 +982,16 @@ script.size = function size(s) {
return bcoin.script.encode(s).length;
};
script.normalize = function normalize(s) {
var bytes = true;
var i;
for (i = 0; bytes && i < s.length; i++) {
script.isEncoded = function(s) {
for (var i = 0; i < s.length; i++) {
if (typeof s[i] !== 'number')
bytes = false;
return false;
}
return true;
};
if (bytes)
script.normalize = function normalize(s) {
if (script.isEncoded(s))
s = script.decode(s);
s = script.subscript(s);
@ -1632,10 +1632,10 @@ script.args = function args(s) {
return m + 1;
}
if (this.type === 'scripthash')
if (type === 'scripthash')
return 1;
if (this.type === 'nulldata')
if (type === 'nulldata')
return -1;
return -1;

View File

@ -217,7 +217,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
if (typeof index !== 'number')
index = this.inputs.indexOf(index);
if (!type)
if (type == null)
type = 'all';
if (typeof type === 'string')
@ -238,7 +238,7 @@ TX.prototype.signInput = function signInput(index, key, type) {
}
// Get the hash of the current tx, minus the other inputs, plus the sighash.
hash = this.subscriptHash(index, redeem, type);
hash = this.signatureHash(index, redeem, type);
// Sign the transaction with our one input
signature = bcoin.ecdsa.sign(hash, key.priv).toDER();
@ -315,7 +315,6 @@ TX.prototype.signInput = function signInput(index, key, type) {
}
};
// Build the scriptSig and sign it
TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
var input;
@ -363,7 +362,6 @@ TX.prototype.output = function output(obj, value) {
return this;
};
// compat
TX.prototype.out = TX.prototype.output;
TX.prototype.scriptOutput = function scriptOutput(index, options) {
@ -493,7 +491,7 @@ TX.prototype.getSubscript = function getSubscript(index) {
return bcoin.script.subscript(script);
};
TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
TX.prototype.signatureHash = function signatureHash(index, s, type) {
var copy = this.clone();
var msg, hash;
@ -503,6 +501,8 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
if (typeof type === 'string')
type = constants.hashType[type];
assert(type != null);
// bitcoind used to return 1 as an error code:
// it ended up being treated like a hash.
if (index >= copy.inputs.length)
@ -538,6 +538,8 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
if (i !== index)
input.seq = 0;
});
} else {
assert(false);
}
if (type & constants.hashType.anyonecanpay) {
@ -562,9 +564,6 @@ TX.prototype.verify = function verify(index, force, flags) {
if (this.inputs.length === 0)
return false;
if (!flags)
flags = {};
return this.inputs.every(function(input, i) {
var output;
@ -1011,8 +1010,6 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) {
return false;
args += targs;
} else {
// Bitcoind returns here whether true
// or false... strange behavior (bug?)
return script.sigops(s, true) <= constants.script.maxScripthashSigops;
}
}

View File

@ -42,6 +42,7 @@ function Wallet(options, passphrase) {
this.loaded = false;
this.lastTs = 0;
this.changeAddress = options.changeAddress || null;
this.redeem = options.redeem || options.script;
if (options.priv instanceof bcoin.hd.priv) {
this.hd = options.priv;
@ -85,6 +86,12 @@ function Wallet(options, passphrase) {
this.multisig(options.multisig || {});
if (this.redeem) {
if (!bcoin.script.isEncoded(this.redeem))
this.redeem = bcoin.script.encode(this.redeem);
this.type = 'scripthash';
}
this.tx = new bcoin.txPool(this);
this._init();
@ -450,7 +457,6 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx) {
if (!input.out.tx && this.tx._all[input.out.hash])
input.out.tx = this.tx._all[input.out.hash];
// Filter inputs that this wallet own
if (!input.out.tx || !this.ownOutput(input.out.tx))
return false;
@ -466,9 +472,6 @@ Wallet.prototype.signInputs = function signInputs(tx, type) {
var key = this.key;
var inputs = tx.inputs;
if (!type)
type = 'all';
inputs = inputs.filter(function(input, i) {
if (!input.out.tx && this.tx._all[input.out.hash])
input.out.tx = this.tx._all[input.out.hash];
@ -485,9 +488,6 @@ Wallet.prototype.signInputs = function signInputs(tx, type) {
};
Wallet.prototype.sign = function sign(tx, type) {
if (!type)
type = 'all';
var pub = this.getPublicKey();
var redeem = this.getScript();
var key = this.key;