diff --git a/lib/bcoin/abstractblock.js b/lib/bcoin/abstractblock.js index fd13e690..1b1a0272 100644 --- a/lib/bcoin/abstractblock.js +++ b/lib/bcoin/abstractblock.js @@ -31,6 +31,8 @@ function AbstractBlock(data) { this.valid = null; this._hash = null; + + this.txs = null; } AbstractBlock.prototype.hash = function hash(enc) { @@ -82,6 +84,18 @@ AbstractBlock.prototype.isGenesis = function isGenesis() { return this.hash('hex') === network.genesis.hash; }; +AbstractBlock.prototype.setHeight = function setHeight(height) { + var i; + + this.height = height; + + if (!this.txs) + return; + + for (i = 0; i < this.txs.length; i++) + this.txs[i].height = height; +}; + AbstractBlock.prototype.__defineGetter__('rhash', function() { return utils.revHex(this.hash('hex')); }); diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index 02fd07d4..25e8b386 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -16,6 +16,8 @@ var BufferReader = require('./reader'); */ function Address(options) { + var i; + if (!(this instanceof Address)) return new Address(options); @@ -51,9 +53,10 @@ function Address(options) { this.addKey(this.getPublicKey()); - (options.keys || []).forEach(function(key) { - this.addKey(key); - }, this); + if (options.keys) { + for (i = 0; i < options.keys.length; i++) + this.addKey(options.keys[i]); + } } Address.isAddress = function isAddress(obj) { @@ -284,30 +287,34 @@ Address.prototype.ownOutput = function ownOutput(tx, index) { }; Address.prototype.scriptInputs = function scriptInputs(tx, index) { - var self = this; + var total = 0; + var i, input; if (index && typeof index === 'object') index = tx.inputs.indexOf(index); - return tx.inputs.reduce(function(total, input, i) { + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; + if (index != null && index !== i) - return total; + continue; if (!input.coin) - return total; + continue; - if (!self.ownOutput(input.coin)) - return total; + if (!this.ownOutput(input.coin)) + continue; - if (tx.scriptInput(i, self)) + if (tx.scriptInput(i, this)) total++; + } - return total; - }, 0); + return total; }; Address.prototype.signInputs = function signInputs(tx, type, index) { - var self = this; + var total = 0; + var i, input; if (index && typeof index === 'object') index = tx.inputs.indexOf(index); @@ -315,25 +322,28 @@ Address.prototype.signInputs = function signInputs(tx, type, index) { if (!this.key.privateKey) return 0; - return tx.inputs.reduce(function(total, input, i) { + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; + if (index != null && index !== i) - return total; + continue; if (!input.coin) - return total; + continue; - if (!self.ownOutput(input.coin)) - return total; + if (!this.ownOutput(input.coin)) + continue; - if (tx.signInput(i, self, type)) + if (tx.signInput(i, this, type)) total++; + } - return total; - }, 0); + return total; }; Address.prototype.sign = function sign(tx, type, index) { - var self = this; + var total = 0; + var i, input; if (index && typeof index === 'object') index = tx.inputs.indexOf(index); @@ -341,23 +351,23 @@ Address.prototype.sign = function sign(tx, type, index) { if (!this.key.privateKey) return 0; - // Add signature script to each input - return tx.inputs.reduce(function(total, input, i) { + for (i = 0; i < tx.inputs.length; i++) { + input = tx.inputs[i]; + if (index != null && index !== i) - return total; + continue; - // Filter inputs that this wallet own if (!input.coin) - return total; + continue; - if (!self.ownOutput(input.coin)) - return total; + if (!this.ownOutput(input.coin)) + continue; - if (tx.sign(i, self, type)) + if (tx.sign(i, this, type)) total++; + } - return total; - }, 0); + return total; }; Address.prototype.__defineGetter__('privateKey', function() { diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 16d4a63c..0a8e74bf 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -461,6 +461,10 @@ Block.fromCompact = function fromCompact(buf) { }; }; +Block.prototype.toMerkle = function toMerkle(filter) { + return bcoin.merkleblock.fromBlock(this, filter); +}; + Block.isBlock = function isBlock(obj) { return obj && typeof obj.merkleRoot === 'string' diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 51558ec5..6618528d 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1183,10 +1183,7 @@ Chain.prototype.add = function add(block, callback, force) { // Update the block height early // Some things in verifyContext may // need access to height on txs. - block.height = height; - block.txs.forEach(function(tx) { - tx.height = height; - }); + block.setHeight(height); // Do "contextual" verification on our block // now that we're certain its previous @@ -1197,10 +1194,7 @@ Chain.prototype.add = function add(block, callback, force) { if (err) { // Couldn't verify block. // Revert the height. - block.height = -1; - block.txs.forEach(function(tx) { - tx.height = -1; - }); + block.setHeight(-1); if (err.type === 'VerifyError') { self.invalid[hash] = true; diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index 05e627c6..a38804fc 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -874,10 +874,18 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) { outputValue = tx.getOutputValue(); tryFree = options.free; + if (options.confirmed) { + coins = coins.filter(function(coin) { + return coin.height !== -1; + }); + } + if (!options.selection || options.selection === 'age') { // Oldest unspents first coins = coins.slice().sort(function(a, b) { - return a.height - b.height; + a = a.height === -1 ? 0x7fffffff : a.height; + b = b.height === -1 ? 0x7fffffff : b.height; + return a - b; }); } else if (options.selection === 'random' || options.selection === 'all') { // Random unspents diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index 9c927f30..cd274420 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -957,7 +957,7 @@ Peer.prototype._handleGetData = function handleGetData(items) { return next(); } - block = bcoin.merkleblock.fromBlock(block, self.filter); + block = block.toMerkle(self.filter); self._write(self.framer.merkleBlock(block)); diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index e45885af..959c904e 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -31,17 +31,12 @@ function Pool(node, options) { this.options = options; this.network = node.network; - options.spv = options.spv !== false; - - if (options.type === 'spv') - options.spv = true; - else if (options.type === 'full') - options.spv = false; - - options.headers = options.headers; - options.relay = options.relay == null - ? (!options.spv ? true : false) - : options.relay; + if (options.relay == null) { + if (options.spv) + options.relay = false; + else + options.relay = true; + } seeds = (options.seeds || network.seeds).slice(); diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 6cf17d59..7a1b1f08 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -16,6 +16,8 @@ var network = bcoin.protocol.network; */ function Wallet(options) { + var i; + if (!(this instanceof Wallet)) return new Wallet(options); @@ -87,9 +89,10 @@ function Wallet(options) { this.addKey(this.accountKey); - (options.keys || []).forEach(function(key) { - this.addKey(key); - }, this); + if (options.keys) { + for (i = 0; i < options.keys.length; i++) + this.addKey(options.keys[i]); + } } utils.inherits(Wallet, EventEmitter); @@ -184,7 +187,7 @@ Wallet.prototype.destroy = function destroy(callback) { }; Wallet.prototype.addKey = function addKey(key) { - var has; + var index, i; if (key instanceof bcoin.wallet) { assert(key.derivation === this.derivation); @@ -207,11 +210,14 @@ Wallet.prototype.addKey = function addKey(key) { throw new Error('Must add HD purpose keys to BIP45 wallet.'); } - has = this.keys.some(function(k) { - return k.xpubkey === key.xpubkey; - }); + for (i = 0; i < this.keys.length; i++) { + if (this.keys[i].xpubkey === key.xpubkey) { + index = i; + break; + } + } - if (has) + if (index != null) return; assert(!this._keysFinalized); @@ -223,7 +229,7 @@ Wallet.prototype.addKey = function addKey(key) { }; Wallet.prototype.removeKey = function removeKey(key) { - var index; + var index, i; assert(!this._keysFinalized); @@ -248,11 +254,12 @@ Wallet.prototype.removeKey = function removeKey(key) { throw new Error('Must add HD purpose keys to BIP45 wallet.'); } - index = this.keys.map(function(k, i) { - return k.xpubkey === key.xpubkey ? i : null; - }).filter(function(i) { - return i !== null; - })[0]; + for (i = 0; i < this.keys.length; i++) { + if (this.keys[i].xpubkey === key.xpubkey) { + index = i; + break; + } + } if (index == null) return; @@ -523,6 +530,8 @@ Wallet.prototype.fill = function fill(tx, options, callback) { try { tx.fill(coins, { selection: options.selection || 'age', + confirmed: options.confirmed, + free: options.free, fee: options.fee, subtractFee: options.subtractFee, changeAddress: self.changeAddress.getAddress(),