tx/script refactor and improvements.
This commit is contained in:
parent
0658444eb5
commit
0b7ca266ee
@ -152,8 +152,6 @@ function HDPrivateKey(options) {
|
|||||||
data = options;
|
data = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.master = options.master || this;
|
|
||||||
|
|
||||||
data = this._normalize(data, network.prefixes.xprivkey);
|
data = this._normalize(data, network.prefixes.xprivkey);
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
@ -347,7 +345,6 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||||||
|
|
||||||
return new HDPrivateKey({
|
return new HDPrivateKey({
|
||||||
version: null,
|
version: null,
|
||||||
master: this.master,
|
|
||||||
depth: new bn(this.depth).toNumber() + 1,
|
depth: new bn(this.depth).toNumber() + 1,
|
||||||
parentFingerPrint: this.fingerPrint,
|
parentFingerPrint: this.fingerPrint,
|
||||||
childIndex: index,
|
childIndex: index,
|
||||||
|
|||||||
@ -156,7 +156,7 @@ Miner.prototype.addTX = function addTX(tx) {
|
|||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!tx.verify())
|
if (!tx.verify(null, true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (tx.isCoinbase())
|
if (tx.isCoinbase())
|
||||||
|
|||||||
@ -248,7 +248,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
var v, v1, v2, v3, v4;
|
var v, v1, v2, v3, v4;
|
||||||
var n, n1, n2, n3;
|
var n, n1, n2, n3;
|
||||||
var res;
|
var res;
|
||||||
var pub, sig, type, subscript, hash;
|
var key, sig, type, subscript, hash;
|
||||||
var keys, i, j, key, m;
|
var keys, i, j, key, m;
|
||||||
var succ;
|
var succ;
|
||||||
var lock, threshold;
|
var lock, threshold;
|
||||||
@ -679,11 +679,11 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
if (!tx || stack.length < 2)
|
if (!tx || stack.length < 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pub = stack.pop();
|
key = stack.pop();
|
||||||
sig = stack.pop();
|
sig = stack.pop();
|
||||||
type = sig[sig.length - 1];
|
type = sig[sig.length - 1];
|
||||||
|
|
||||||
if (!constants.hashTypeByVal[type & 0x1f])
|
if (!script.isKey(key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (flags.strictder !== false) {
|
if (flags.strictder !== false) {
|
||||||
@ -694,10 +694,13 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!constants.hashTypeByVal[type & 0x1f])
|
||||||
|
return false;
|
||||||
|
|
||||||
subscript = script.subscript(s, lastSep);
|
subscript = script.subscript(s, lastSep);
|
||||||
hash = tx.subscriptHash(index, subscript, type);
|
hash = tx.subscriptHash(index, subscript, type);
|
||||||
|
|
||||||
res = script.verify(hash, sig.slice(0, -1), pub);
|
res = script.verify(hash, sig.slice(0, -1), key);
|
||||||
if (o === 'checksigverify') {
|
if (o === 'checksigverify') {
|
||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
@ -723,7 +726,7 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
keys = [];
|
keys = [];
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
key = stack.pop();
|
key = stack.pop();
|
||||||
if (!(33 <= key.length && key.length <= 65))
|
if (!script.isKey(key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
keys.push(key);
|
keys.push(key);
|
||||||
@ -745,9 +748,6 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
sig = stack.pop();
|
sig = stack.pop();
|
||||||
type = sig[sig.length - 1];
|
type = sig[sig.length - 1];
|
||||||
|
|
||||||
if (!constants.hashTypeByVal[type & 0x1f])
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (flags.strictder !== false) {
|
if (flags.strictder !== false) {
|
||||||
if (!script.isValidSig(sig))
|
if (!script.isValidSig(sig))
|
||||||
return false;
|
return false;
|
||||||
@ -756,6 +756,9 @@ script.execute = function execute(s, stack, tx, index, flags, recurse) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!constants.hashTypeByVal[type & 0x1f])
|
||||||
|
return false;
|
||||||
|
|
||||||
hash = tx.subscriptHash(index, subscript, type);
|
hash = tx.subscriptHash(index, subscript, type);
|
||||||
|
|
||||||
res = false;
|
res = false;
|
||||||
@ -1123,11 +1126,12 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
|||||||
if (s.length !== 1 || !Array.isArray(s[0]))
|
if (s.length !== 1 || !Array.isArray(s[0]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// res = script.isValidSig(s[0]);
|
if (!script.isSig(s[0]))
|
||||||
res = 9 <= s[0].length && s[0].length <= 73;
|
|
||||||
if (!res)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Execute the script against our key's
|
||||||
|
// checksig script to see if this is our input.
|
||||||
|
// This will only work if the script verifies.
|
||||||
if (key)
|
if (key)
|
||||||
return script.exec(s, [key, 'checksig'], tx, i);
|
return script.exec(s, [key, 'checksig'], tx, i);
|
||||||
|
|
||||||
@ -1135,20 +1139,15 @@ script.isPubkeyInput = function isPubkeyInput(s, key, tx, i) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
||||||
var res;
|
|
||||||
|
|
||||||
s = script.subscript(s);
|
s = script.subscript(s);
|
||||||
|
|
||||||
if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1]))
|
if (s.length !== 2 || !Array.isArray(s[0]) || !Array.isArray(s[1]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// res = script.isValidSig(s[0])
|
if (!script.isSig(s[0]))
|
||||||
// && 33 <= s[1].length && s[1].length <= 65;
|
return false;
|
||||||
|
|
||||||
res = 9 <= s[0].length && s[0].length <= 73
|
if (!script.isKey(s[1]))
|
||||||
&& 33 <= s[1].length && s[1].length <= 65;
|
|
||||||
|
|
||||||
if (!res)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (key)
|
if (key)
|
||||||
@ -1160,7 +1159,8 @@ script.isPubkeyhashInput = function isPubkeyhashInput(s, key) {
|
|||||||
script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) {
|
script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) {
|
||||||
var i, res, o;
|
var i, res, o;
|
||||||
|
|
||||||
// We need to rule out scripthash because it may look like multisig
|
// We need to rule out scripthash
|
||||||
|
// because it may look like multisig
|
||||||
if (script.isScripthashInput(s))
|
if (script.isScripthashInput(s))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1173,12 +1173,13 @@ script.isMultisigInput = function isMultisigInput(s, pubs, tx, i) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 1; i < s.length; i++) {
|
for (i = 1; i < s.length; i++) {
|
||||||
// res = script.isValidSig(s[i]);
|
if (!script.isSig(s[i]))
|
||||||
res = Array.isArray(s[i]) && 9 <= s[i].length && s[i].length <= 73;
|
|
||||||
if (!res)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute the script against our pubkeys'
|
||||||
|
// redeem script to see if this is our input.
|
||||||
|
// This will only work if the script verifies.
|
||||||
if (pubs && pubs.length >= 2) {
|
if (pubs && pubs.length >= 2) {
|
||||||
o = script.redeem(pubs, 2, pubs.length);
|
o = script.redeem(pubs, 2, pubs.length);
|
||||||
return script.exec(s, o, tx, i);
|
return script.exec(s, o, tx, i);
|
||||||
@ -1199,9 +1200,7 @@ script.isScripthashInput = function isScripthashInput(s, redeem) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 1; i < s.length - 1; i++) {
|
for (i = 1; i < s.length - 1; i++) {
|
||||||
// res = script.isValidSig(s[i]);
|
if (!script.isSig(s[i]))
|
||||||
res = Array.isArray(s[i]) && 9 <= s[i].length && s[i].length <= 73;
|
|
||||||
if (!res)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1320,6 +1319,13 @@ script.isCoinbase = function isCoinbase(s, block, strict) {
|
|||||||
return coinbase;
|
return coinbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script.isKey = function isKey(key) {
|
||||||
|
if (!utils.isBuffer(key))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return key.length >= 33 && key.length <= 65;
|
||||||
|
};
|
||||||
|
|
||||||
script.isSig = function isSig(sig, allowZero) {
|
script.isSig = function isSig(sig, allowZero) {
|
||||||
if (!utils.isBuffer(sig))
|
if (!utils.isBuffer(sig))
|
||||||
return false;
|
return false;
|
||||||
@ -1327,7 +1333,7 @@ script.isSig = function isSig(sig, allowZero) {
|
|||||||
if (allowZero && sig.length === 0)
|
if (allowZero && sig.length === 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return 9 <= sig.length && sig.length <= 73;
|
return sig.length >= 9 && sig.length <= 73;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
// https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
||||||
|
|||||||
@ -96,6 +96,9 @@ TXPool.prototype.add = function add(tx, noWrite) {
|
|||||||
key = input.out.hash + '/' + input.out.index;
|
key = input.out.hash + '/' + input.out.index;
|
||||||
unspent = this._unspent[key];
|
unspent = this._unspent[key];
|
||||||
|
|
||||||
|
if (!input.out.tx && this._all[input.out.hash])
|
||||||
|
input.out.tx = this._all[input.out.hash];
|
||||||
|
|
||||||
if (unspent) {
|
if (unspent) {
|
||||||
// Add TX to inputs and spend money
|
// Add TX to inputs and spend money
|
||||||
index = tx._inputIndex(unspent.tx.hash('hex'), unspent.index);
|
index = tx._inputIndex(unspent.tx.hash('hex'), unspent.index);
|
||||||
@ -121,7 +124,7 @@ TXPool.prototype.add = function add(tx, noWrite) {
|
|||||||
// we could in theory use ownInput here (and down below)
|
// we could in theory use ownInput here (and down below)
|
||||||
// instead.
|
// instead.
|
||||||
// if (this._wallet.ownInput(input.out.tx, input.out.index))
|
// if (this._wallet.ownInput(input.out.tx, input.out.index))
|
||||||
if (tx.inputs[i].out.tx) {
|
if (input.out.tx) {
|
||||||
if (!this._wallet.ownOutput(input.out.tx, input.out.index))
|
if (!this._wallet.ownOutput(input.out.tx, input.out.index))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,10 +157,18 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Build the scriptSigs for inputs, excluding the signatures
|
// Build the scriptSigs for inputs, excluding the signatures
|
||||||
TX.prototype.scriptInput = function scriptInput(input, pub) {
|
TX.prototype.scriptInput = function scriptInput(index, pub) {
|
||||||
|
var input, s, n, i, redeem;
|
||||||
|
|
||||||
|
if (typeof index !== 'number')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
|
// Get the input
|
||||||
|
input = this.inputs[index];
|
||||||
|
assert(input);
|
||||||
|
|
||||||
// Get the previous output's subscript
|
// Get the previous output's subscript
|
||||||
var s = input.out.tx.getSubscript(input.out.index);
|
s = input.out.tx.getSubscript(input.out.index);
|
||||||
var n, i, redeem;
|
|
||||||
|
|
||||||
// Already has a script template (at least)
|
// Already has a script template (at least)
|
||||||
if (input.script.length)
|
if (input.script.length)
|
||||||
@ -218,16 +226,23 @@ TX.prototype.scriptInput = function scriptInput(input, pub) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Sign the now-built scriptSigs
|
// Sign the now-built scriptSigs
|
||||||
TX.prototype.signInput = function signInput(input, key, type) {
|
TX.prototype.signInput = function signInput(index, key, type) {
|
||||||
var s, hash, signature;
|
var input, s, hash, signature;
|
||||||
var len, redeem, m, keys, pub, pubn, ki, totalSigs, i;
|
var len, redeem, m, keys, pub, pubn, ki, totalSigs, i;
|
||||||
|
|
||||||
|
if (typeof index !== 'number')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
type = 'all';
|
type = 'all';
|
||||||
|
|
||||||
if (typeof type === 'string')
|
if (typeof type === 'string')
|
||||||
type = constants.hashType[type];
|
type = constants.hashType[type];
|
||||||
|
|
||||||
|
// Get the input
|
||||||
|
input = this.inputs[index];
|
||||||
|
assert(input);
|
||||||
|
|
||||||
// Get the previous output's subscript
|
// Get the previous output's subscript
|
||||||
s = input.out.tx.getSubscript(input.out.index);
|
s = input.out.tx.getSubscript(input.out.index);
|
||||||
|
|
||||||
@ -239,7 +254,7 @@ TX.prototype.signInput = function signInput(input, key, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the hash of the current tx, minus the other inputs, plus the sighash.
|
// Get the hash of the current tx, minus the other inputs, plus the sighash.
|
||||||
hash = this.subscriptHash(this.inputs.indexOf(input), redeem, type);
|
hash = this.subscriptHash(index, redeem, type);
|
||||||
|
|
||||||
// Sign the transaction with our one input
|
// Sign the transaction with our one input
|
||||||
signature = bcoin.ecdsa.sign(hash, key.priv).toDER();
|
signature = bcoin.ecdsa.sign(hash, key.priv).toDER();
|
||||||
@ -324,23 +339,32 @@ TX.prototype.signInput = function signInput(input, key, type) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Build the scriptSig and sign it
|
// Build the scriptSig and sign it
|
||||||
TX.prototype.scriptSig = function scriptSig(input, key, pub, type) {
|
TX.prototype.scriptSig = function scriptSig(index, key, pub, type) {
|
||||||
|
var input;
|
||||||
|
|
||||||
if (!utils.isBuffer(pub)) {
|
if (!utils.isBuffer(pub)) {
|
||||||
type = pub;
|
type = pub;
|
||||||
pub = key.getPublic(true, 'array');
|
pub = key.getPublic(true, 'array');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof index !== 'number')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
|
// Get the input
|
||||||
|
input = this.inputs[index];
|
||||||
|
assert(input);
|
||||||
|
|
||||||
// Build script for input
|
// Build script for input
|
||||||
this.scriptInput(input, pub);
|
this.scriptInput(index, pub);
|
||||||
|
|
||||||
// Sign input
|
// Sign input
|
||||||
this.signInput(input, key, type);
|
this.signInput(index, key, type);
|
||||||
|
|
||||||
return input.script;
|
return input.script;
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.output = function output(obj, value) {
|
TX.prototype.output = function output(obj, value) {
|
||||||
var options;
|
var options, output;
|
||||||
|
|
||||||
if (obj instanceof bcoin.wallet)
|
if (obj instanceof bcoin.wallet)
|
||||||
obj = obj.getAddress();
|
obj = obj.getAddress();
|
||||||
@ -354,7 +378,7 @@ TX.prototype.output = function output(obj, value) {
|
|||||||
options = obj;
|
options = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
var output = bcoin.output({
|
output = bcoin.output({
|
||||||
tx: this,
|
tx: this,
|
||||||
value: options.value,
|
value: options.value,
|
||||||
script: options.script
|
script: options.script
|
||||||
@ -362,7 +386,7 @@ TX.prototype.output = function output(obj, value) {
|
|||||||
|
|
||||||
this.outputs.push(output);
|
this.outputs.push(output);
|
||||||
|
|
||||||
this.scriptOutput(output, options);
|
this.scriptOutput(this.outputs.length - 1, options);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -370,11 +394,19 @@ TX.prototype.output = function output(obj, value) {
|
|||||||
// compat
|
// compat
|
||||||
TX.prototype.out = TX.prototype.output;
|
TX.prototype.out = TX.prototype.output;
|
||||||
|
|
||||||
TX.prototype.scriptOutput = function scriptOutput(output, options) {
|
TX.prototype.scriptOutput = function scriptOutput(index, options) {
|
||||||
var script = output.script;
|
var output, script, keys, m, n, hash, locktime, flags;
|
||||||
var keys, m, n, hash, locktime, flags;
|
|
||||||
|
|
||||||
options = options || output;
|
if (typeof index !== 'number')
|
||||||
|
index = this.outputs.indexOf(index);
|
||||||
|
|
||||||
|
output = this.outputs[index];
|
||||||
|
assert(output);
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
options = output;
|
||||||
|
|
||||||
|
script = output.script;
|
||||||
|
|
||||||
if (options instanceof bcoin.output) {
|
if (options instanceof bcoin.output) {
|
||||||
options = Object.keys(options).reduce(function(out, key) {
|
options = Object.keys(options).reduce(function(out, key) {
|
||||||
@ -499,6 +531,9 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
|
|||||||
var copy = this.clone();
|
var copy = this.clone();
|
||||||
var verifyStr, hash;
|
var verifyStr, hash;
|
||||||
|
|
||||||
|
if (typeof index !== 'number')
|
||||||
|
index = this.inputs.indexOf(index);
|
||||||
|
|
||||||
if (typeof type === 'string')
|
if (typeof type === 'string')
|
||||||
type = constants.hashType[type];
|
type = constants.hashType[type];
|
||||||
|
|
||||||
@ -508,7 +543,7 @@ TX.prototype.subscriptHash = function subscriptHash(index, s, type) {
|
|||||||
return constants.oneHash.slice();
|
return constants.oneHash.slice();
|
||||||
|
|
||||||
copy.inputs.forEach(function(input, i) {
|
copy.inputs.forEach(function(input, i) {
|
||||||
input.script = index === i ? s : [];
|
input.script = i === index ? s : [];
|
||||||
});
|
});
|
||||||
|
|
||||||
if ((type & 0x1f) === constants.hashType.all) {
|
if ((type & 0x1f) === constants.hashType.all) {
|
||||||
@ -564,12 +599,18 @@ TX.prototype.verify = function verify(index, force, flags) {
|
|||||||
return this.inputs.every(function(input, i) {
|
return this.inputs.every(function(input, i) {
|
||||||
var stack, prev, push, res, redeem;
|
var stack, prev, push, res, redeem;
|
||||||
|
|
||||||
if (index !== undefined && index !== i)
|
if (index != null && index !== i)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!input.out.tx)
|
if (!input.out.tx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
assert.equal(input.out.tx.hash('hex'), input.out.hash);
|
||||||
|
|
||||||
|
// Transaction cannot reference itself
|
||||||
|
if (input.out.tx.hash('hex') === this.hash('hex'))
|
||||||
|
return false;
|
||||||
|
|
||||||
assert(input.out.tx.outputs.length > input.out.index);
|
assert(input.out.tx.outputs.length > input.out.index);
|
||||||
|
|
||||||
stack = [];
|
stack = [];
|
||||||
|
|||||||
@ -125,11 +125,6 @@ Wallet.prototype._init = function init() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// If we want to use p2sh addresses for the prefix:
|
|
||||||
// Wallet.prototype.__defineGetter__('prefix', function() {
|
|
||||||
// return 'bt/' + this.getFullAddress() + '/';
|
|
||||||
// });
|
|
||||||
|
|
||||||
Wallet.prototype.multisig = function multisig(options) {
|
Wallet.prototype.multisig = function multisig(options) {
|
||||||
var pub = this.getOwnPublicKey();
|
var pub = this.getOwnPublicKey();
|
||||||
|
|
||||||
@ -364,7 +359,7 @@ Wallet.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
var outputs = tx.outputs.filter(function(output, i) {
|
var outputs = tx.outputs.filter(function(output, i) {
|
||||||
var s = output.script;
|
var s = output.script;
|
||||||
|
|
||||||
if (index !== undefined && index !== i)
|
if (index != null && index !== i)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (bcoin.script.isPubkey(s, key))
|
if (bcoin.script.isPubkey(s, key))
|
||||||
@ -398,7 +393,10 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
|
|||||||
var inputs = tx.inputs.filter(function(input, i) {
|
var inputs = tx.inputs.filter(function(input, i) {
|
||||||
var s;
|
var s;
|
||||||
|
|
||||||
if (index !== undefined && index !== i)
|
if (!input.out.tx && this.tx._all[input.out.hash])
|
||||||
|
input.out.tx = this.tx._all[input.out.hash];
|
||||||
|
|
||||||
|
if (index != null && index !== i)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if (bcoin.script.isPubkeyInput(input.script, key, tx, i))
|
// if (bcoin.script.isPubkeyInput(input.script, key, tx, i))
|
||||||
@ -416,7 +414,7 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
|
|||||||
if (!input.out.tx)
|
if (!input.out.tx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
s = input.out.tx.outputs[input.out.index].script;
|
s = input.out.tx.getSubscript(input.out.index);
|
||||||
|
|
||||||
if (bcoin.script.isPubkey(s, key))
|
if (bcoin.script.isPubkey(s, key))
|
||||||
return true;
|
return true;
|
||||||
@ -456,12 +454,15 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx, inputs) {
|
|||||||
|
|
||||||
inputs = inputs || tx.inputs;
|
inputs = inputs || tx.inputs;
|
||||||
|
|
||||||
inputs = inputs.filter(function(input) {
|
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];
|
||||||
|
|
||||||
// Filter inputs that this wallet own
|
// Filter inputs that this wallet own
|
||||||
if (!input.out.tx || !this.ownOutput(input.out.tx))
|
if (!input.out.tx || !this.ownOutput(input.out.tx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tx.scriptInput(input, pub);
|
tx.scriptInput(i, pub);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, this);
|
}, this);
|
||||||
@ -477,11 +478,14 @@ Wallet.prototype.signInputs = function signInputs(tx, type, inputs) {
|
|||||||
|
|
||||||
inputs = inputs || tx.inputs;
|
inputs = inputs || tx.inputs;
|
||||||
|
|
||||||
inputs = inputs.filter(function(input) {
|
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];
|
||||||
|
|
||||||
if (!input.out.tx || !this.ownOutput(input.out.tx))
|
if (!input.out.tx || !this.ownOutput(input.out.tx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tx.signInput(input, key, type);
|
tx.signInput(i, key, type);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, this);
|
}, this);
|
||||||
@ -499,12 +503,15 @@ Wallet.prototype.sign = function sign(tx, type, inputs) {
|
|||||||
inputs = inputs || tx.inputs;
|
inputs = inputs || tx.inputs;
|
||||||
|
|
||||||
// Add signature script to each input
|
// Add signature script to each input
|
||||||
inputs = inputs.filter(function(input) {
|
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];
|
||||||
|
|
||||||
// Filter inputs that this wallet own
|
// Filter inputs that this wallet own
|
||||||
if (!input.out.tx || !this.ownOutput(input.out.tx))
|
if (!input.out.tx || !this.ownOutput(input.out.tx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tx.scriptSig(input, key, pub, type);
|
tx.scriptSig(i, key, pub, type);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}, this);
|
}, this);
|
||||||
@ -591,7 +598,7 @@ Wallet.prototype.toAddress = function toAddress() {
|
|||||||
|
|
||||||
Wallet.prototype.toJSON = function toJSON(encrypt) {
|
Wallet.prototype.toJSON = function toJSON(encrypt) {
|
||||||
return {
|
return {
|
||||||
v: 1,
|
v: 2,
|
||||||
type: 'wallet',
|
type: 'wallet',
|
||||||
network: network.type,
|
network: network.type,
|
||||||
encrypted: encrypt ? true : false,
|
encrypted: encrypt ? true : false,
|
||||||
@ -603,21 +610,9 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
|
|||||||
? encrypt(this.getPrivateKey('base58'))
|
? encrypt(this.getPrivateKey('base58'))
|
||||||
: this.getPrivateKey('base58'),
|
: this.getPrivateKey('base58'),
|
||||||
tx: this.tx.toJSON(),
|
tx: this.tx.toJSON(),
|
||||||
ntx: this.tx.all().length,
|
xprivkey: this.hd
|
||||||
hd: this.hd ? {
|
? (encrypt ? encrypt(this.hd.xprivkey) : this.hd.xprivkey)
|
||||||
seed: this.hd.seed ? {
|
: null,
|
||||||
mnemonic: encrypt
|
|
||||||
? encrypt(this.hd.seed.mnemonic)
|
|
||||||
: this.hd.seed.mnemonic,
|
|
||||||
passphrase: encrypt
|
|
||||||
? encrypt(this.hd.seed.passphrase)
|
|
||||||
: this.hd.seed.passphrase
|
|
||||||
} : undefined,
|
|
||||||
depth: new bn(this.hd.data.depth).toNumber(),
|
|
||||||
parentFingerPrint: utils.toHex(this.hd.data.parentFingerPrint),
|
|
||||||
childIndex: new bn(this.hd.data.childIndex).toNumber(),
|
|
||||||
chainCode: utils.toHex(this.hd.data.chainCode)
|
|
||||||
} : undefined,
|
|
||||||
multisig: this.n > 1 ? {
|
multisig: this.n > 1 ? {
|
||||||
type: this.type,
|
type: this.type,
|
||||||
keys: this.keys.map(utils.toBase58),
|
keys: this.keys.map(utils.toBase58),
|
||||||
@ -628,9 +623,13 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Wallet.fromJSON = function fromJSON(json, decrypt) {
|
Wallet.fromJSON = function fromJSON(json, decrypt) {
|
||||||
var priv, pub, compressed, key, w;
|
var compressed, key, w;
|
||||||
|
var priv = json.priv;
|
||||||
|
var pub = json.pub;
|
||||||
|
var xprivkey = json.xprivkey;
|
||||||
|
var multisig = json.multisig;
|
||||||
|
|
||||||
assert.equal(json.v, 1);
|
assert.equal(json.v, 2);
|
||||||
assert.equal(json.type, 'wallet');
|
assert.equal(json.type, 'wallet');
|
||||||
|
|
||||||
if (json.network)
|
if (json.network)
|
||||||
@ -639,11 +638,11 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
|||||||
if (json.encrypted && !decrypt)
|
if (json.encrypted && !decrypt)
|
||||||
throw new Error('Cannot decrypt wallet');
|
throw new Error('Cannot decrypt wallet');
|
||||||
|
|
||||||
if (json.encrypted)
|
if (priv) {
|
||||||
json.priv = decrypt(json.priv);
|
if (json.encrypted)
|
||||||
|
priv = decrypt(priv);
|
||||||
|
|
||||||
if (json.priv) {
|
key = bcoin.utils.fromBase58(priv);
|
||||||
key = bcoin.utils.fromBase58(json.priv);
|
|
||||||
assert(utils.isEqual(key.slice(-4), utils.checksum(key.slice(0, -4))));
|
assert(utils.isEqual(key.slice(-4), utils.checksum(key.slice(0, -4))));
|
||||||
assert.equal(key[0], network.prefixes.privkey);
|
assert.equal(key[0], network.prefixes.privkey);
|
||||||
|
|
||||||
@ -657,20 +656,23 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
|||||||
compressed = false;
|
compressed = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pub = bcoin.utils.fromBase58(json.pub);
|
pub = bcoin.utils.fromBase58(pub);
|
||||||
compressed = pub[0] !== 0x04;
|
compressed = pub[0] !== 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.multisig)
|
if (multisig) {
|
||||||
json.multisig.keys = json.multisig.keys.map(utils.fromBase58);
|
multisig = {
|
||||||
|
type: multisig.type,
|
||||||
|
keys: multisig.keys.map(utils.fromBase58),
|
||||||
|
m: multisig.m,
|
||||||
|
n: multisig.n
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (json.hd) {
|
if (xprivkey) {
|
||||||
json.hd.privateKey = priv;
|
if (json.encrypted)
|
||||||
if (json.encrypted && json.hd.seed) {
|
xprivkey = decrypt(xprivkey);
|
||||||
json.hd.seed.mnemonic = decrypt(json.hd.seed.mnemonic);
|
priv = bcoin.hd.priv(xprivkey);
|
||||||
json.hd.seed.passphrase = decrypt(json.hd.seed.passphrase);
|
|
||||||
}
|
|
||||||
priv = bcoin.hd.priv(json.hd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w = new Wallet({
|
w = new Wallet({
|
||||||
@ -678,7 +680,7 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
|
|||||||
priv: priv,
|
priv: priv,
|
||||||
pub: pub,
|
pub: pub,
|
||||||
compressed: compressed,
|
compressed: compressed,
|
||||||
multisig: json.multisig
|
multisig: multisig
|
||||||
});
|
});
|
||||||
|
|
||||||
w.tx.fromJSON(json.tx);
|
w.tx.fromJSON(json.tx);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user