use utxo object instead of tx refs.
This commit is contained in:
parent
26f1e44eb3
commit
274c6e6864
@ -338,14 +338,19 @@ Address.prototype.ownOutput = function ownOutput(tx, index) {
|
||||
var hash = this.getKeyHash();
|
||||
var key = this.getPublicKey();
|
||||
var keys = this.keys;
|
||||
var outputs;
|
||||
var outputs = tx.outputs;
|
||||
|
||||
outputs = tx.outputs.filter(function(output, i) {
|
||||
if ((tx instanceof bcoin.output) || (tx instanceof bcoin.output.prev))
|
||||
outputs = [tx];
|
||||
|
||||
outputs = outputs.filter(function(output, i) {
|
||||
var s = output.script;
|
||||
|
||||
if (index != null && index !== i)
|
||||
return false;
|
||||
|
||||
return output.testScript(key, hash, keys, scriptHash, null);
|
||||
|
||||
if (bcoin.script.isPubkey(s, key))
|
||||
return true;
|
||||
|
||||
@ -375,17 +380,24 @@ Address.prototype.ownInput = function ownInput(tx, index) {
|
||||
var key = this.getPublicKey();
|
||||
var redeem = this.getScript();
|
||||
var keys = this.keys;
|
||||
var inputs;
|
||||
var inputs = tx.inputs;
|
||||
|
||||
inputs = tx.inputs.filter(function(input, i) {
|
||||
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
|
||||
input.prevout.tx = this.tx._all[input.prevout.hash];
|
||||
if (tx instanceof bcoin.input) {
|
||||
inputs = [tx];
|
||||
tx = null;
|
||||
}
|
||||
|
||||
if (tx)
|
||||
this._wallet.fillPrevout(tx);
|
||||
|
||||
inputs = inputs.filter(function(input, i) {
|
||||
if (index != null && index !== i)
|
||||
return false;
|
||||
|
||||
if (input.prevout.tx)
|
||||
return !!this.ownOutput(input.prevout.tx, input.prevout.index);
|
||||
if (input.output)
|
||||
return !!this.ownOutput(input.output);
|
||||
|
||||
return input.testScript(key, redeem, null);
|
||||
|
||||
// if (bcoin.script.isPubkeyInput(input.script, key, tx, i))
|
||||
// return true;
|
||||
@ -416,10 +428,10 @@ Address.prototype.scriptInputs = function scriptInputs(tx) {
|
||||
var redeem = this.getScript();
|
||||
|
||||
return tx.inputs.reduce(function(total, input, i) {
|
||||
if (!input.prevout.tx)
|
||||
if (!input.output)
|
||||
return total;
|
||||
|
||||
if (!self.ownOutput(input.prevout.tx, input.prevout.index))
|
||||
if (!self.ownOutput(input.output))
|
||||
return total;
|
||||
|
||||
if (tx.scriptInput(i, publicKey, redeem))
|
||||
@ -438,10 +450,10 @@ Address.prototype.signInputs = function signInputs(tx, type) {
|
||||
return 0;
|
||||
|
||||
return tx.inputs.reduce(function(total, input, i) {
|
||||
if (!input.prevout.tx)
|
||||
if (!input.output)
|
||||
return total;
|
||||
|
||||
if (!self.ownOutput(input.prevout.tx, input.prevout.index))
|
||||
if (!self.ownOutput(input.output))
|
||||
return total;
|
||||
|
||||
if (tx.signInput(i, key, type))
|
||||
@ -463,10 +475,10 @@ Address.prototype.sign = function sign(tx, type) {
|
||||
// Add signature script to each input
|
||||
return tx.inputs.reduce(function(total, input, i) {
|
||||
// Filter inputs that this wallet own
|
||||
if (!input.prevout.tx)
|
||||
if (!input.output)
|
||||
return total;
|
||||
|
||||
if (!self.ownOutput(input.prevout.tx, input.prevout.index))
|
||||
if (!self.ownOutput(input.output))
|
||||
return total;
|
||||
|
||||
if (tx.scriptSig(i, key, publicKey, redeem, type))
|
||||
|
||||
@ -459,10 +459,10 @@ Block.prototype.verifyContext = function verifyContext() {
|
||||
|
||||
// We need the previous output in order
|
||||
// to verify the script.
|
||||
if (!input.prevout.tx)
|
||||
if (!input.output)
|
||||
continue;
|
||||
|
||||
assert(input.prevout.tx);
|
||||
assert(input.output);
|
||||
|
||||
// Verify the script
|
||||
if (!tx.verify(j, true, flags)) {
|
||||
|
||||
@ -22,17 +22,21 @@ function Input(options) {
|
||||
|
||||
prevout = options.prevout || options.out;
|
||||
|
||||
this.tx = options.tx;
|
||||
|
||||
this.prevout = {
|
||||
tx: prevout.tx || null,
|
||||
hash: prevout.hash,
|
||||
index: prevout.index
|
||||
index: prevout.index,
|
||||
rhash: prevout.rhash
|
||||
};
|
||||
|
||||
if (options.output)
|
||||
this.output = bcoin.output.prev(options.output);
|
||||
|
||||
if (utils.isBuffer(this.prevout.hash))
|
||||
this.prevout.hash = utils.toHex(this.prevout.hash);
|
||||
|
||||
if (!this.prevout.rhash)
|
||||
this.prevout.rhash = utils.toHex(this.prevout.hash);
|
||||
|
||||
this.script = options.script ? options.script.slice() : [];
|
||||
this.sequence = options.sequence == null ? 0xffffffff : options.sequence;
|
||||
|
||||
@ -91,7 +95,7 @@ Input.prototype.__defineGetter__('key', function() {
|
||||
return this.keys[0];
|
||||
});
|
||||
|
||||
Input.prototype.__defineGetter__('hash', function() {
|
||||
Input.prototype.__defineGetter__('hash160', function() {
|
||||
return this.data.scriptHash || this.hashes[0];
|
||||
});
|
||||
|
||||
@ -153,22 +157,12 @@ Input.prototype.__defineGetter__('text', function() {
|
||||
return this.data.text;
|
||||
});
|
||||
|
||||
Input.prototype.__defineGetter__('output', function() {
|
||||
if (!this.prevout.tx)
|
||||
return;
|
||||
return this.prevout.tx.outputs[this.prevout.index];
|
||||
});
|
||||
|
||||
Input.prototype.__defineGetter__('value', function() {
|
||||
if (!this.output)
|
||||
return;
|
||||
return this.output.value;
|
||||
});
|
||||
|
||||
Input.prototype.__defineGetter__('tx', function() {
|
||||
return this.prevout.tx;
|
||||
});
|
||||
|
||||
Input.prototype.__defineGetter__('addr', function() {
|
||||
return this.address;
|
||||
});
|
||||
@ -238,7 +232,7 @@ Input.getData = function getData(input) {
|
||||
def.prev = input.prevout.hash;
|
||||
def.index = input.prevout.index;
|
||||
|
||||
if (+input.prevout.hash === 0) {
|
||||
if (input.isCoinbase()) {
|
||||
data = bcoin.script.getCoinbaseData(input.script);
|
||||
return utils.merge(def, data, {
|
||||
type: 'coinbase',
|
||||
@ -307,45 +301,62 @@ Input.prototype.getLocktime = function getLocktime() {
|
||||
return bcoin.script.getLocktime(redeem);
|
||||
};
|
||||
|
||||
Input.prototype.createScript = function createScript(pub, redeem) {
|
||||
return this.tx.scriptInput(this, pub, redeem);
|
||||
};
|
||||
|
||||
Input.prototype.signatureHash = function signatureHash(s, type) {
|
||||
return this.tx.signatureHash(this, s, type);
|
||||
};
|
||||
|
||||
Input.prototype.createSignature = function createSignature(key, type) {
|
||||
return this.tx.createSignature(this, key, type);
|
||||
};
|
||||
|
||||
Input.prototype.sign = function sign(key, type) {
|
||||
return this.tx.signInput(this, key, type);
|
||||
};
|
||||
|
||||
Input.prototype.scriptSig = function scriptSig(key, pub, redeem, type) {
|
||||
return this.tx.scriptSig(this, key, pub, redeem, type);
|
||||
};
|
||||
|
||||
Input.prototype.isSigned = function isSigned(required) {
|
||||
return this.tx.isSigned(this, required);
|
||||
};
|
||||
|
||||
Input.prototype.verify = function verify(force, flags) {
|
||||
return this.tx.verify(this, force, flags);
|
||||
};
|
||||
|
||||
Input.prototype.isCoinbase = function isCoinbase() {
|
||||
return this.tx.isCoinbase();
|
||||
return +this.prevout.hash === 0;
|
||||
};
|
||||
|
||||
Input.prototype.test = function test(addressTable, collect) {
|
||||
return this.tx.testInputs(addressTable, this, collect);
|
||||
Input.prototype.testScript = function testScript(key, redeem, type) {
|
||||
// if (!type || type === 'pubkey') {
|
||||
// if (key) {
|
||||
// if (bcoin.script.isPubkeyInput(this.script, key, tx, i))
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!type || type === 'pubkeyhash') {
|
||||
if (key) {
|
||||
if (bcoin.script.isPubkeyhashInput(this.script, key))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// if (!type || type === 'multisig') {
|
||||
// if (keys) {
|
||||
// if (bcoin.script.isMultisigInput(input.script, keys, tx, i))
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!type || type === 'scripthash') {
|
||||
if (redeem) {
|
||||
if (bcoin.script.isScripthashInput(this.script, redeem))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Input.prototype.test = function test(addressTable) {
|
||||
var data = this.getData();
|
||||
var i;
|
||||
|
||||
if (data.scriptAddress) {
|
||||
if (addressTable[data.scriptAddress] != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < data.addresses.length; i++) {
|
||||
if (addressTable[data.addresses[i]] != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Input.prototype.getSigops = function getSigops(scriptHash, accurate) {
|
||||
var n = bcoin.script.getSigops(this.script, accurate);
|
||||
if (scriptHash && !this.tx.isCoinbase())
|
||||
if (scriptHash && !this.isCoinbase())
|
||||
n += bcoin.script.getScripthashSigops(this.script);
|
||||
return n;
|
||||
};
|
||||
@ -356,7 +367,7 @@ Input.prototype.inspect = function inspect() {
|
||||
: { type: 'unknown', value: '0.0' };
|
||||
|
||||
output.hash = this.prevout.hash;
|
||||
output.rhash = utils.revHex(this.prevout.hash);
|
||||
output.rhash = this.prevout.rhash;
|
||||
output.index = this.prevout.index;
|
||||
|
||||
return {
|
||||
|
||||
@ -142,7 +142,7 @@ Miner.prototype.addTX = function addTX(tx) {
|
||||
var full, ts;
|
||||
|
||||
full = this.index.inputs.every(function(input) {
|
||||
return !!input.prevout.tx;
|
||||
return !!input.output;
|
||||
});
|
||||
|
||||
// Cannot calculate fee if we don't have the prev_out.
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
var bn = require('bn.js');
|
||||
var bcoin = require('../bcoin');
|
||||
var inherits = require('inherits');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.protocol.constants;
|
||||
@ -25,7 +26,6 @@ function Output(options) {
|
||||
if (typeof value === 'number' && (value | 0) === value)
|
||||
value = new bn(value);
|
||||
|
||||
this.tx = options.tx;
|
||||
this.value = utils.satoshi(value || new bn(0));
|
||||
this.script = options.script ? options.script.slice() : [];
|
||||
|
||||
@ -66,7 +66,7 @@ Output.prototype.__defineGetter__('key', function() {
|
||||
return this.keys[0];
|
||||
});
|
||||
|
||||
Output.prototype.__defineGetter__('hash', function() {
|
||||
Output.prototype.__defineGetter__('hash160', function() {
|
||||
return this.data.scriptHash || this.hashes[0];
|
||||
});
|
||||
|
||||
@ -222,12 +222,53 @@ Output.prototype.getID = function getID() {
|
||||
return '[' + this.type + ':' + hash.slice(0, 7) + ']';
|
||||
};
|
||||
|
||||
Output.prototype.createScript = function createScript(options) {
|
||||
return this.tx.scriptOutput(this, options);
|
||||
Output.prototype.testScript = function testScript(key, hash, keys, scriptHash, type) {
|
||||
if (!type || type === 'pubkey') {
|
||||
if (key) {
|
||||
if (bcoin.script.isPubkey(this.script, key))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type || type === 'pubkeyhash') {
|
||||
if (hash) {
|
||||
if (bcoin.script.isPubkeyhash(this.script, hash))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type || type === 'multisig') {
|
||||
if (keys) {
|
||||
if (bcoin.script.isMultisig(this.script, keys))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type || type === 'scripthash') {
|
||||
if (scriptHash) {
|
||||
if (bcoin.script.isScripthash(this.script, scriptHash))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Output.prototype.test = function test(addressTable, collect) {
|
||||
return this.tx.testOutputs(addressTable, this, collect);
|
||||
Output.prototype.test = function test(addressTable) {
|
||||
var data = this.getData();
|
||||
var i;
|
||||
|
||||
if (data.scriptAddress) {
|
||||
if (addressTable[data.scriptAddress] != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < data.addresses.length; i++) {
|
||||
if (addressTable[data.addresses[i]] != null)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Output.prototype.getSigops = function getSigops(accurate) {
|
||||
@ -251,8 +292,111 @@ Output.prototype.inspect = function inspect() {
|
||||
};
|
||||
};
|
||||
|
||||
// This is basically a UTXO/Coin object. It is immutable once instantiated. It
|
||||
// needs to store 5 properties: the tx hash, output index, output value, output
|
||||
// script, and the block height the transaction was mined (to later calculate
|
||||
// age).
|
||||
|
||||
function Prevout(tx, index) {
|
||||
var options;
|
||||
|
||||
if (!(this instanceof Prevout))
|
||||
return new Prevout(tx, index);
|
||||
|
||||
if (tx instanceof Prevout)
|
||||
return tx;
|
||||
|
||||
if (tx instanceof bcoin.tx) {
|
||||
this.hash = tx.hash('hex');
|
||||
this.index = index;
|
||||
this.value = tx.outputs[index].value;
|
||||
this.script = tx.outputs[index].script;
|
||||
this.height = tx.getHeight();
|
||||
} else {
|
||||
options = tx;
|
||||
this.hash = options.hash;
|
||||
this.index = options.index;
|
||||
this.value = options.value;
|
||||
this.script = options.script;
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
if (utils.isBuffer(this.hash))
|
||||
this.hash = utils.toHex(this.hash);
|
||||
|
||||
assert(typeof this.hash === 'string');
|
||||
assert(utils.isFinite(this.index));
|
||||
assert(this.value instanceof bn);
|
||||
assert(Array.isArray(this.script));
|
||||
assert(utils.isFinite(this.height));
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
inherits(Prevout, Output);
|
||||
|
||||
Prevout.prototype.__defineGetter__('chain', function() {
|
||||
return this._chain || bcoin.chain.global;
|
||||
});
|
||||
|
||||
Prevout.prototype.getConfirmations = function getConfirmations() {
|
||||
var top;
|
||||
|
||||
if (!this.chain)
|
||||
return 0;
|
||||
|
||||
top = this.chain.height();
|
||||
|
||||
if (this.height === -1)
|
||||
return 0;
|
||||
|
||||
return top - this.height + 1;
|
||||
};
|
||||
|
||||
Prevout.prototype.__defineGetter__('confirmations', function() {
|
||||
return this.getConfirmations();
|
||||
});
|
||||
|
||||
Prevout.prototype.getAge = function getAge() {
|
||||
var age = this.getConfirmations();
|
||||
|
||||
if (age === -1)
|
||||
age = 0;
|
||||
|
||||
if (age !== 0)
|
||||
age += 1;
|
||||
|
||||
return age;
|
||||
};
|
||||
|
||||
Prevout.prototype.__defineGetter__('age', function() {
|
||||
return this.getAge();
|
||||
});
|
||||
|
||||
Prevout.prototype.toJSON = function toJSON() {
|
||||
return {
|
||||
hash: this.hash,
|
||||
index: this.index,
|
||||
value: utils.btc(this.value),
|
||||
script: utils.toHex(bcoin.script.encode(this.script)),
|
||||
height: this.height
|
||||
};
|
||||
};
|
||||
|
||||
Prevout.fromJSON = function fromJSON(json) {
|
||||
return new Prevout({
|
||||
hash: json.hash,
|
||||
index: json.index,
|
||||
value: utils.satoshi(json.value),
|
||||
script: bcoin.script.decode(utils.toArray(json.script, 'hex')),
|
||||
height: json.height
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = Output;
|
||||
exports = Output;
|
||||
exports.prev = Prevout;
|
||||
module.exports = exports;
|
||||
|
||||
@ -1307,12 +1307,16 @@ script.getInputData = function getData(s, prev) {
|
||||
// We could call _getInputData, but
|
||||
// we really only need the signatures.
|
||||
if (output.type === 'pubkey') {
|
||||
output.signatures = [s[0]];
|
||||
if (s.length >= 1)
|
||||
output.signatures = [s[0]];
|
||||
} else if (output.type === 'pubkeyhash') {
|
||||
output.signatures = [s[0]];
|
||||
output.keys = [s[1]];
|
||||
if (s.length >= 2) {
|
||||
output.signatures = [s[0]];
|
||||
output.keys = [s[1]];
|
||||
}
|
||||
} else if (output.type === 'multisig') {
|
||||
output.signatures = s.slice(1);
|
||||
if (s.length >= 2)
|
||||
output.signatures = s.slice(1);
|
||||
} else if (output.type === 'scripthash') {
|
||||
// Scripthash is the only case where
|
||||
// we get more data from the input
|
||||
@ -1345,6 +1349,13 @@ script._getInputData = function _getInputData(s, type) {
|
||||
assert(typeof type === 'string');
|
||||
|
||||
if (type === 'pubkey') {
|
||||
if (s.length < 1) {
|
||||
return {
|
||||
type: 'pubkey',
|
||||
side: 'input',
|
||||
none: true
|
||||
};
|
||||
}
|
||||
sig = s[0];
|
||||
return {
|
||||
type: 'pubkey',
|
||||
@ -1355,6 +1366,13 @@ script._getInputData = function _getInputData(s, type) {
|
||||
}
|
||||
|
||||
if (type === 'pubkeyhash') {
|
||||
if (s.length < 2) {
|
||||
return {
|
||||
type: 'pubkeyhash',
|
||||
side: 'input',
|
||||
none: true
|
||||
};
|
||||
}
|
||||
sig = s[0];
|
||||
key = s[1];
|
||||
hash = bcoin.wallet.key2hash(key);
|
||||
@ -1370,6 +1388,13 @@ script._getInputData = function _getInputData(s, type) {
|
||||
}
|
||||
|
||||
if (type === 'multisig') {
|
||||
if (s.length < 2) {
|
||||
return {
|
||||
type: 'multisig',
|
||||
side: 'input',
|
||||
none: true
|
||||
};
|
||||
}
|
||||
sig = s.slice(1);
|
||||
return {
|
||||
type: 'multisig',
|
||||
@ -1381,6 +1406,13 @@ script._getInputData = function _getInputData(s, type) {
|
||||
}
|
||||
|
||||
if (type === 'scripthash') {
|
||||
if (s.length < 1) {
|
||||
return {
|
||||
type: 'scripthash',
|
||||
side: 'input',
|
||||
none: true
|
||||
};
|
||||
}
|
||||
raw = s[s.length - 1];
|
||||
redeem = script.decode(raw);
|
||||
locktime = script.getLocktime(redeem);
|
||||
|
||||
@ -86,6 +86,8 @@ TXPool.prototype.add = function add(tx, noWrite, strict) {
|
||||
var i, input, key, unspent, index, orphan;
|
||||
var out, key, orphans, some;
|
||||
|
||||
this._wallet.fillPrevout(tx);
|
||||
|
||||
if (strict) {
|
||||
if (!this._wallet.ownInput(tx) && !this._wallet.ownOutput(tx))
|
||||
return false;
|
||||
@ -120,17 +122,14 @@ TXPool.prototype.add = function add(tx, noWrite, strict) {
|
||||
key = input.prevout.hash + '/' + input.prevout.index;
|
||||
unspent = this._unspent[key];
|
||||
|
||||
if (!input.prevout.tx && this._all[input.prevout.hash])
|
||||
input.prevout.tx = this._all[input.prevout.hash];
|
||||
|
||||
if (unspent) {
|
||||
// Add TX to inputs and spend money
|
||||
index = tx._inputIndex(unspent.tx.hash('hex'), unspent.index);
|
||||
index = tx._inputIndex(unspent.hash, unspent.index);
|
||||
assert(index !== -1);
|
||||
assert(tx.inputs[index] === input);
|
||||
assert(tx.inputs[index].prevout.hash === unspent.tx.hash('hex'));
|
||||
assert(tx.inputs[index].prevout.hash === unspent.hash);
|
||||
assert(tx.inputs[index].prevout.index === unspent.index);
|
||||
input.prevout.tx = unspent.tx;
|
||||
input.output = unspent;
|
||||
|
||||
// Skip invalid transactions
|
||||
if (!tx.verify(index))
|
||||
@ -149,8 +148,8 @@ TXPool.prototype.add = function add(tx, noWrite, strict) {
|
||||
// signature checking code to ownInput for p2sh and p2pk,
|
||||
// we could in theory use ownInput here (and down below)
|
||||
// instead.
|
||||
if (input.prevout.tx) {
|
||||
if (!this._wallet.ownOutput(input.prevout.tx, input.prevout.index))
|
||||
if (input.output) {
|
||||
if (!this._wallet.ownOutput(input.output))
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -177,7 +176,7 @@ TXPool.prototype.add = function add(tx, noWrite, strict) {
|
||||
assert(index !== -1);
|
||||
assert(orphan.tx.inputs[index].prevout.hash === tx.hash('hex'));
|
||||
assert(orphan.tx.inputs[index].prevout.index === i);
|
||||
orphan.tx.inputs[index].prevout.tx = tx;
|
||||
orphan.tx.inputs[index].output = bcoin.output.prev(tx, i);
|
||||
|
||||
// Verify that input script is correct, if not - add output to unspent
|
||||
// and remove orphan from storage
|
||||
@ -211,7 +210,7 @@ TXPool.prototype.add = function add(tx, noWrite, strict) {
|
||||
|
||||
delete this._orphans[key];
|
||||
if (!orphans) {
|
||||
this._unspent[key] = { tx: tx, index: i };
|
||||
this._unspent[key] = bcoin.output.prev(tx, i);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
@ -327,11 +326,11 @@ TXPool.prototype._addInput = function _addInput(tx, i, remove) {
|
||||
var input = tx.inputs[i];
|
||||
var prev, address;
|
||||
|
||||
if (!this._wallet.ownOutput(input.prevout.tx, input.prevout.index))
|
||||
return;
|
||||
|
||||
assert(input.output);
|
||||
|
||||
if (!this._wallet.ownOutput(input.output))
|
||||
return;
|
||||
|
||||
prev = input.output;
|
||||
address = prev.getAddress();
|
||||
|
||||
@ -378,7 +377,7 @@ TXPool.prototype.getUnspent = function getUnspent(address) {
|
||||
return Object.keys(this._unspent).map(function(key) {
|
||||
return this._unspent[key];
|
||||
}, this).filter(function(item) {
|
||||
return address.ownOutput(item.tx, item.index);
|
||||
return address.ownOutput(item);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
113
lib/bcoin/tx.js
113
lib/bcoin/tx.js
@ -128,14 +128,11 @@ TX.prototype.input = TX.prototype.addInput;
|
||||
TX.prototype._addInput = function _addInput(options, index) {
|
||||
var input, ex, i, prevout;
|
||||
|
||||
if (options instanceof TX)
|
||||
options = { prevout: { tx: options, index: index } };
|
||||
else if (typeof options === 'string' || utils.isBuffer(options))
|
||||
options = { prevout: { hash: options, index: index } };
|
||||
else if (!options.prevout)
|
||||
options = { prevout: options, script: options.script, sequence: options.sequence };
|
||||
else
|
||||
options = options;
|
||||
if (options instanceof TX) {
|
||||
options = { tx: options, index: index };
|
||||
} else if (typeof options === 'string' || utils.isBuffer(options)) {
|
||||
options = { hash: options, index: index };
|
||||
}
|
||||
|
||||
if (options.out)
|
||||
options.prevout = options.out;
|
||||
@ -143,16 +140,37 @@ TX.prototype._addInput = function _addInput(options, index) {
|
||||
if (options.seq != null)
|
||||
options.sequence = options.seq;
|
||||
|
||||
if (options.prevout.tx)
|
||||
options.prevout.hash = options.prevout.tx.hash('hex');
|
||||
if (!options.prevout) {
|
||||
if (options instanceof bcoin.output.prev) {
|
||||
options = {
|
||||
prevout: { hash: options.hash, index: options.index },
|
||||
output: options
|
||||
};
|
||||
} else if (options.tx) {
|
||||
var prev = bcoin.output.prev(options.tx, options.index);
|
||||
options = {
|
||||
prevout: { hash: prev.hash, index: prev.index },
|
||||
output: prev,
|
||||
script: options.script,
|
||||
sequence: options.sequence
|
||||
};
|
||||
} else if (options.hash) {
|
||||
options = {
|
||||
prevout: { hash: options.hash, index: options.index },
|
||||
output: options.output,
|
||||
script: options.script,
|
||||
sequence: options.sequence
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
input = bcoin.input({
|
||||
tx: this,
|
||||
prevout: {
|
||||
tx: options.prevout.tx,
|
||||
hash: options.prevout.hash,
|
||||
index: options.prevout.index
|
||||
},
|
||||
output: options.output,
|
||||
script: options.script,
|
||||
sequence: options.sequence
|
||||
});
|
||||
@ -161,8 +179,8 @@ TX.prototype._addInput = function _addInput(options, index) {
|
||||
i = this._inputIndex(input.prevout.hash, input.prevout.index);
|
||||
if (i !== -1) {
|
||||
ex = this.inputs[i];
|
||||
input.prevout.tx = input.prevout.tx || ex.prevout.tx;
|
||||
input.sequence = input.sequence || ex.sequence;
|
||||
input.output = input.output || ex.output;
|
||||
input.sequence = input.sequence != null ? input.sequence : ex.sequence;
|
||||
input.script = input.script.length ? input.script : ex.script;
|
||||
this.inputs[i] = input;
|
||||
} else {
|
||||
@ -886,10 +904,6 @@ TX.prototype.verify = function verify(index, force, flags) {
|
||||
if (!input.output)
|
||||
return false;
|
||||
|
||||
// Somethis is very wrong if this is
|
||||
// not the case.
|
||||
assert.equal(input.prevout.tx.hash('hex'), input.prevout.hash);
|
||||
|
||||
return bcoin.script.verify(input.script, input.output.script, this, i, flags);
|
||||
}, this);
|
||||
};
|
||||
@ -1015,7 +1029,7 @@ TX.prototype.getInputs = function getInputs(unspent, address, fee) {
|
||||
|
||||
// Oldest unspents first
|
||||
unspent = unspent.slice().sort(function(a, b) {
|
||||
return b.tx.getConfirmations() - a.tx.getConfirmations();
|
||||
return a.height - b.height;
|
||||
});
|
||||
|
||||
function addInput(unspent) {
|
||||
@ -1289,7 +1303,7 @@ TX.prototype.getTargetLocktime = function getTargetLocktime() {
|
||||
|
||||
TX.prototype.testInputs = function testInputs(addressTable, index, collect) {
|
||||
var inputs = [];
|
||||
var i, input, j, addresses, scriptAddress;
|
||||
var i, input;
|
||||
|
||||
if (typeof addressTable === 'string')
|
||||
addressTable = [addressTable];
|
||||
@ -1313,24 +1327,10 @@ TX.prototype.testInputs = function testInputs(addressTable, index, collect) {
|
||||
|
||||
input = this.inputs[i];
|
||||
|
||||
addresses = input.getAddresses();
|
||||
if (addresses) {
|
||||
for (j = 0; j < addresses.length; j++) {
|
||||
if (addressTable[addresses[j]] != null) {
|
||||
if (!collect)
|
||||
return true;
|
||||
inputs.push(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scriptAddress = input.getScriptAddress();
|
||||
if (scriptAddress) {
|
||||
if (addressTable[scriptAddress] != null) {
|
||||
if (!collect)
|
||||
return true;
|
||||
inputs.push(input);
|
||||
}
|
||||
if (input.test(addressTable)) {
|
||||
if (!collect)
|
||||
return true;
|
||||
inputs.push(input);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1345,7 +1345,7 @@ TX.prototype.testInputs = function testInputs(addressTable, index, collect) {
|
||||
|
||||
TX.prototype.testOutputs = function testOutputs(addressTable, index, collect) {
|
||||
var outputs = [];
|
||||
var i, output, data, j, addresses, scriptAddress;
|
||||
var i, output;
|
||||
|
||||
if (typeof addressTable === 'string')
|
||||
addressTable = [addressTable];
|
||||
@ -1369,24 +1369,10 @@ TX.prototype.testOutputs = function testOutputs(addressTable, index, collect) {
|
||||
|
||||
output = this.outputs[i];
|
||||
|
||||
addresses = output.getAddresses();
|
||||
if (addresses) {
|
||||
for (j = 0; j < addresses.length; j++) {
|
||||
if (addressTable[addresses[j]] != null) {
|
||||
if (!collect)
|
||||
return true;
|
||||
outputs.push(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scriptAddress = output.getScriptAddress();
|
||||
if (scriptAddress) {
|
||||
if (addressTable[scriptAddress] != null) {
|
||||
if (!collect)
|
||||
return true;
|
||||
outputs.push(output);
|
||||
}
|
||||
if (output.test(addressTable)) {
|
||||
if (!collect)
|
||||
return true;
|
||||
outputs.push(output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1438,7 +1424,7 @@ TX.prototype.hasPrevout = function hasPrevout() {
|
||||
return false;
|
||||
|
||||
return this.inputs.every(function(input) {
|
||||
return !!input.prevout.tx;
|
||||
return !!input.output;
|
||||
});
|
||||
};
|
||||
|
||||
@ -1458,9 +1444,9 @@ TX.prototype.fillPrevout = function fillPrevout(txs) {
|
||||
}
|
||||
|
||||
inputs = this.inputs.filter(function(input) {
|
||||
if (!input.prevout.tx && txs[input.prevout.hash])
|
||||
input.prevout.tx = txs[input.prevout.hash];
|
||||
return !!input.prevout.tx;
|
||||
if (!input.output && txs[input.prevout.hash])
|
||||
input.output = bcoin.output.prev(txs[input.prevout.hash], input.prevout.index);
|
||||
return !!input.output;
|
||||
}, this);
|
||||
|
||||
return inputs.length === this.inputs.length;
|
||||
@ -1646,10 +1632,10 @@ TX.prototype.getPriority = function getPriority() {
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
|
||||
if (!input.prevout.tx)
|
||||
if (!input.output)
|
||||
return constants.tx.freeThreshold.clone();
|
||||
|
||||
age = input.prevout.tx.getConfirmations();
|
||||
age = input.output.getConfirmations();
|
||||
|
||||
if (age === -1)
|
||||
age = 0;
|
||||
@ -1749,7 +1735,8 @@ TX.prototype.inspect = function inspect() {
|
||||
copy.fee = utils.btc(this.getFee());
|
||||
copy.height = this.getHeight();
|
||||
copy.confirmations = this.getConfirmations();
|
||||
// copy.priority = this.getPriority().toString(10);
|
||||
if (this.hasPrevout())
|
||||
copy.priority = this.getPriority().toString(10);
|
||||
copy.date = new Date((copy.ts || 0) * 1000).toISOString();
|
||||
if (copy.hardFee)
|
||||
copy.hardFee = utils.btc(copy.hardFee);
|
||||
|
||||
@ -813,11 +813,39 @@ Wallet.prototype.getAddress = function getAddress() {
|
||||
};
|
||||
|
||||
Wallet.prototype.ownInput = function ownInput(tx, index) {
|
||||
if (tx instanceof bcoin.input) {
|
||||
var input = tx;
|
||||
var scriptAddress = input.getScriptAddress();
|
||||
if (this._addressTable[scriptAddress] != null)
|
||||
return true;
|
||||
var addresses = input.getAddresses();
|
||||
var address;
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
address = addresses[i];
|
||||
if (this._addressTable[address] != null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this.fillPrevout(tx);
|
||||
return tx.testInputs(this._addressTable, index, true);
|
||||
};
|
||||
|
||||
Wallet.prototype.ownOutput = function ownOutput(tx, index) {
|
||||
if ((tx instanceof bcoin.output) || (tx instanceof bcoin.output.prev)) {
|
||||
var output = tx;
|
||||
var scriptAddress = output.getScriptAddress();
|
||||
if (this._addressTable[scriptAddress] != null)
|
||||
return true;
|
||||
var addresses = output.getAddresses();
|
||||
var address;
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
address = addresses[i];
|
||||
if (this._addressTable[address] != null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return tx.testOutputs(this._addressTable, index, true);
|
||||
};
|
||||
|
||||
@ -831,13 +859,11 @@ Wallet.prototype.fill = function fill(tx, address, fee) {
|
||||
|
||||
unspent = this.getUnspent();
|
||||
|
||||
items = unspent.filter(function(item) {
|
||||
var output = item.tx.outputs[item.index];
|
||||
|
||||
if (bcoin.script.isScripthash(output.script))
|
||||
items = unspent.filter(function(coin) {
|
||||
if (bcoin.script.isScripthash(coin.script))
|
||||
return this.type === 'scripthash';
|
||||
|
||||
if (bcoin.script.isMultisig(output.script))
|
||||
if (bcoin.script.isMultisig(coin.script))
|
||||
return this.type === 'multisig';
|
||||
|
||||
return true;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user