From af6ac736bfbb497ec8d1b154230ab179c078dc59 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 28 Mar 2016 13:20:00 -0700 Subject: [PATCH] consistent naming. --- lib/bcoin/address.js | 12 ++-- lib/bcoin/chain.js | 10 ++-- lib/bcoin/chaindb.js | 36 ++++++------ lib/bcoin/coins.js | 8 +-- lib/bcoin/fullnode.js | 10 ++-- lib/bcoin/http/provider.js | 2 +- lib/bcoin/input.js | 45 +++++--------- lib/bcoin/mempool.js | 18 +++--- lib/bcoin/miner.js | 4 +- lib/bcoin/mtx.js | 112 +++++++++++------------------------ lib/bcoin/pool.js | 4 +- lib/bcoin/script.js | 43 ++------------ lib/bcoin/tx-pool.js | 70 ++++++++++------------ lib/bcoin/tx.js | 116 ++++++++++++++++++------------------- lib/bcoin/txdb.js | 28 ++++----- lib/bcoin/wallet.js | 6 +- lib/bcoin/walletdb.js | 8 +-- test/node-test.js | 4 +- test/tx-test.js | 2 +- test/wallet-test.js | 2 +- 20 files changed, 217 insertions(+), 323 deletions(-) diff --git a/lib/bcoin/address.js b/lib/bcoin/address.js index 4a8e1685..e1330273 100644 --- a/lib/bcoin/address.js +++ b/lib/bcoin/address.js @@ -297,10 +297,10 @@ Address.prototype.scriptInputs = function scriptInputs(tx, index) { if (index != null && index !== i) return total; - if (!input.output) + if (!input.coin) return total; - if (!self.ownOutput(input.output)) + if (!self.ownOutput(input.coin)) return total; if (tx.scriptInput(i, self)) @@ -323,10 +323,10 @@ Address.prototype.signInputs = function signInputs(tx, type, index) { if (index != null && index !== i) return total; - if (!input.output) + if (!input.coin) return total; - if (!self.ownOutput(input.output)) + if (!self.ownOutput(input.coin)) return total; if (tx.signInput(i, self, type)) @@ -351,10 +351,10 @@ Address.prototype.sign = function sign(tx, type, index) { return total; // Filter inputs that this wallet own - if (!input.output) + if (!input.coin) return total; - if (!self.ownOutput(input.output)) + if (!self.ownOutput(input.coin)) return total; if (tx.sign(i, self, type)) diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index c82c23b3..5f4ee2d9 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -645,7 +645,7 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, peer, c input = tx.inputs[j]; // Ensure tx is not double spending an output - if (!input.output) { + if (!input.coin) { utils.debug('Block is using spent inputs: %s (tx: %s, output: %s)', block.rhash, tx.rhash, utils.revHex(input.prevout.hash) + '/' + input.prevout.index); @@ -668,13 +668,13 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, peer, c block.rhash, tx.rhash, j); utils.debug(input); utils.debug('Signature Hash v0: %s', - utils.toHex(tx.signatureHash(j, input.output.script, 'all', 0))); + utils.toHex(tx.signatureHash(j, input.coin.script, 'all', 0))); utils.debug('Signature Hash v1: %s', - utils.toHex(tx.signatureHash(j, input.output.script, 'all', 1))); + utils.toHex(tx.signatureHash(j, input.coin.script, 'all', 1))); utils.debug('Raw Script: %s', - utils.toHex(input.output.script.encode())); + utils.toHex(input.coin.script.encode())); utils.debug('Reserialized Script: %s', - utils.toHex(input.output.script.clone().encode())); + utils.toHex(input.coin.script.clone().encode())); if (height < network.checkpoints.lastHeight) throw new Error('BUG: Bad inputs in historical data!'); return callback(null, false); diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index 6d372d1a..d5d511af 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -587,7 +587,7 @@ ChainDB.prototype.connectBlock = function connectBlock(block, batch, callback) { if (tx.isCoinbase()) return; - assert(input.output); + assert(input.coin); if (self.options.indexAddress) { address = input.getAddress(); @@ -659,7 +659,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(hash, batch, callba if (tx.isCoinbase()) return; - assert(input.output); + assert(input.coin); if (self.options.indexAddress) { address = input.getAddress(); @@ -680,7 +680,7 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(hash, batch, callba batch.put('u/t/' + input.prevout.hash + '/' + input.prevout.index, - input.output.toRaw()); + input.coin.toRaw()); }); tx.outputs.forEach(function(output, i) { @@ -708,14 +708,14 @@ ChainDB.prototype.disconnectBlock = function disconnectBlock(hash, batch, callba }); }; -ChainDB.prototype.fillCoin = function fillCoin(tx, callback) { +ChainDB.prototype.fillCoins = function fillCoins(tx, callback) { var self = this; callback = utils.asyncify(callback); if (Array.isArray(tx)) { return utils.forEachSerial(tx, function(tx, next) { - self.fillCoin(tx, next); + self.fillCoins(tx, next); }, function(err) { if (err) return callback(err); @@ -727,7 +727,7 @@ ChainDB.prototype.fillCoin = function fillCoin(tx, callback) { return callback(null, tx); utils.forEachSerial(tx.inputs, function(input, next) { - if (input.output) + if (input.coin) return next(); self.getCoin(input.prevout.hash, input.prevout.index, function(err, coin) { @@ -735,7 +735,7 @@ ChainDB.prototype.fillCoin = function fillCoin(tx, callback) { return callback(err); if (coin) - input.output = coin; + input.coin = coin; next(); }); @@ -766,7 +766,7 @@ ChainDB.prototype.fillTX = function fillTX(tx, callback) { if (this.prune) { return utils.forEachSerial(tx.inputs, function(input, next) { - if (input.output) + if (input.coin) return next(); self._getPruneCoin(input.prevout.hash, input.prevout.index, function(err, coin) { @@ -774,7 +774,7 @@ ChainDB.prototype.fillTX = function fillTX(tx, callback) { return callback(err); if (coin) - input.output = coin; + input.coin = coin; next(); }); @@ -786,7 +786,7 @@ ChainDB.prototype.fillTX = function fillTX(tx, callback) { } utils.forEachSerial(tx.inputs, function(input, next) { - if (input.output) + if (input.coin) return next(); self.getTX(input.prevout.hash, function(err, tx) { @@ -794,7 +794,7 @@ ChainDB.prototype.fillTX = function fillTX(tx, callback) { return next(err); if (tx) - input.output = bcoin.coin(tx, input.prevout.index); + input.coin = bcoin.coin(tx, input.prevout.index); next(); }); @@ -1076,7 +1076,7 @@ ChainDB.prototype._getTXBlock = function _getTXBlock(hash, callback) { }; ChainDB.prototype.fillBlock = function fillBlock(block, callback) { - return this.fillCoin(block.txs, function(err) { + return this.fillCoins(block.txs, function(err) { var coins, i, tx, hash, j, input, id; if (err) @@ -1091,8 +1091,8 @@ ChainDB.prototype.fillBlock = function fillBlock(block, callback) { for (j = 0; j < tx.inputs.length; j++) { input = tx.inputs[j]; id = input.prevout.hash + '/' + input.prevout.index; - if (!input.output && coins[id]) { - input.output = coins[id]; + if (!input.coin && coins[id]) { + input.coin = coins[id]; delete coins[id]; } } @@ -1121,8 +1121,8 @@ ChainDB.prototype.fillTXBlock = function fillTXBlock(block, callback) { for (j = 0; j < tx.inputs.length; j++) { input = tx.inputs[j]; id = input.prevout.hash + '/' + input.prevout.index; - if (!input.output && coins[id]) { - input.output = coins[id]; + if (!input.coin && coins[id]) { + input.coin = coins[id]; delete coins[id]; } } @@ -1258,12 +1258,12 @@ ChainDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) { return; tx.inputs.forEach(function(input) { - assert(input.output); + assert(input.coin); batch.put('u/x/' + input.prevout.hash + '/' + input.prevout.index, - input.output.toRaw()); + input.coin.toRaw()); batch.put('u/q/' + futureHeight diff --git a/lib/bcoin/coins.js b/lib/bcoin/coins.js index 668e6f34..06cd6617 100644 --- a/lib/bcoin/coins.js +++ b/lib/bcoin/coins.js @@ -101,13 +101,13 @@ Coins.prototype.fill = function fill(tx, spend) { if (input.prevout.hash !== this.hash) continue; - if (!input.output) { + if (!input.coin) { if (spend) - input.output = this.spend(input.prevout.index); + input.coin = this.spend(input.prevout.index); else - input.output = this.get(input.prevout.index); + input.coin = this.get(input.prevout.index); - if (!input.output) + if (!input.coin) res = false; } } diff --git a/lib/bcoin/fullnode.js b/lib/bcoin/fullnode.js index c4584174..9ad12c96 100644 --- a/lib/bcoin/fullnode.js +++ b/lib/bcoin/fullnode.js @@ -349,17 +349,17 @@ Fullnode.prototype.getTXByAddress = function getTXByAddress(addresses, callback) }); }; -Fullnode.prototype.fillCoin = function fillCoin(tx, callback) { +Fullnode.prototype.fillCoins = function fillCoins(tx, callback) { var self = this; - this.mempool.fillCoin(tx, function(err) { + this.mempool.fillCoins(tx, function(err) { if (err) return callback(err); - if (tx.hasPrevout()) + if (tx.hasCoins()) return callback(null, tx); - self.chain.db.fillCoin(tx, callback); + self.chain.db.fillCoins(tx, callback); }); }; @@ -370,7 +370,7 @@ Fullnode.prototype.fillTX = function fillTX(tx, callback) { if (err) return callback(err); - if (tx.hasPrevout()) + if (tx.hasCoins()) return callback(null, tx); self.chain.db.fillTX(tx, callback); diff --git a/lib/bcoin/http/provider.js b/lib/bcoin/http/provider.js index b034c68a..e04833f0 100644 --- a/lib/bcoin/http/provider.js +++ b/lib/bcoin/http/provider.js @@ -103,7 +103,7 @@ Provider.prototype.fillTX = function fillTX(tx, callback) { assert(false); }; -Provider.prototype.fillCoin = function fillCoin(tx, callback) { +Provider.prototype.fillCoins = function fillCoins(tx, callback) { assert(false); }; diff --git a/lib/bcoin/input.js b/lib/bcoin/input.js index 64304225..270139f3 100644 --- a/lib/bcoin/input.js +++ b/lib/bcoin/input.js @@ -26,8 +26,8 @@ function Input(options, tx) { this.witness = options.witness || new bcoin.script.witness([]); this._mutable = !tx || (tx instanceof bcoin.mtx); - if (options.output) - this.output = bcoin.coin(options.output); + if (options.coin) + this.coin = bcoin.coin(options.coin); if (Buffer.isBuffer(this.prevout.hash)) this.prevout.hash = utils.toHex(this.prevout.hash); @@ -47,8 +47,8 @@ Input.prototype.getType = function getType() { if (this.isCoinbase()) return 'coinbase'; - if (this.output) - return this.output.getType(); + if (this.coin) + return this.coin.getType(); if (this._type) return this._type; @@ -106,8 +106,8 @@ Input.prototype.getAddress = function getAddress() { if (this.isCoinbase()) return; - if (this.output) - return this.output.getAddress(); + if (this.coin) + return this.coin.getAddress(); if (this._address) return this._address; @@ -132,23 +132,6 @@ Input.prototype.isFinal = function isFinal() { return this.sequence === 0xffffffff; }; -Input.prototype.getLocktime = function getLocktime() { - var output, redeem; - - assert(this.output); - - output = this.output; - redeem = output.script; - - if (redeem.isScripthash()) - redeem = this.script.getRedeem(); - - if (redeem[1] !== 'checklocktimeverify') - return; - - return redeem.getLocktime(); -}; - Input.prototype.isCoinbase = function isCoinbase() { return +this.prevout.hash === 0; }; @@ -183,12 +166,12 @@ Input.prototype.getID = function getID() { Input.prototype.inspect = function inspect() { var redeem = this.getRedeem(); - var output; + var coin; - if (this.output) { - output = this.output.inspect(); + if (this.coin) { + coin = this.coin.inspect(); } else { - output = { + coin = { type: 'unknown', version: 1, height: -1, @@ -205,12 +188,12 @@ Input.prototype.inspect = function inspect() { type: this.getType(), subtype: this.getSubtype(), address: this.getAddress(), - value: utils.btc(output.value), + value: utils.btc(coin.value), script: bcoin.script.format(this.script), witness: bcoin.script.format(this.witness), redeem: redeem ? bcoin.script.format(redeem) : null, sequence: this.sequence, - output: output + coin: coin }; }; @@ -220,7 +203,7 @@ Input.prototype.toJSON = function toJSON() { hash: utils.revHex(this.prevout.hash), index: this.prevout.index }, - output: this.output ? this.output.toJSON() : null, + coin: this.coin ? this.coin.toJSON() : null, script: utils.toHex(this.script.encode()), witness: utils.toHex(this.witness.encode()), sequence: this.sequence @@ -233,7 +216,7 @@ Input._fromJSON = function _fromJSON(json) { hash: utils.revHex(json.prevout.hash), index: json.prevout.index }, - output: json.output ? bcoin.coin._fromJSON(json.output) : null, + coin: json.coin ? bcoin.coin._fromJSON(json.coin) : null, script: new bcoin.script(new Buffer(json.script, 'hex')), witness: new bcoin.script.witness(new Buffer(json.witness, 'hex')), sequence: json.sequence diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index ae27ebd5..9a5d9692 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -260,8 +260,8 @@ Mempool.prototype.fillTX = function fillTX(tx, callback) { return this.tx.fillTX(tx, callback); }; -Mempool.prototype.fillCoin = function fillCoin(tx, callback) { - return this.tx.fillCoin(tx, callback); +Mempool.prototype.fillCoins = function fillCoins(tx, callback) { + return this.tx.fillCoins(tx, callback); }; Mempool.prototype.has = @@ -340,11 +340,11 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback, force) { 0)); } - self.node.fillCoin(tx, function(err) { + self.node.fillCoins(tx, function(err) { if (err) return callback(err); - if (!tx.hasPrevout()) { + if (!tx.hasCoins()) { if (self.size > Mempool.MAX_MEMPOOL_SIZE) { return callback(new VerifyError( 'insufficientfee', @@ -458,7 +458,7 @@ Mempool.prototype.verify = function verify(tx, callback) { total = new bn(0); for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; - coin = input.output; + coin = input.coin; if (coin.coinbase) { if (self.chain.height - coin.height < constants.tx.coinbaseMaturity) { @@ -642,7 +642,7 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, callback, force) { for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; - if (!input.output) + if (!input.coin) outputs[input.prevout.hash] = true; } @@ -726,11 +726,11 @@ Mempool.prototype.resolveOrphans = function resolveOrphans(tx, callback, force) } orphan.inputs.forEach(function(input) { - if (!input.output && input.prevout.hash === hash) - input.output = bcoin.coin(tx, input.prevout.index); + if (!input.coin && input.prevout.hash === hash) + input.coin = bcoin.coin(tx, input.prevout.index); }); - if (orphan.hasPrevout()) { + if (orphan.hasCoins()) { batch.del('m/D/' + orphanHash); return self.verify(orphan, function(err) { if (err) { diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index 1efe3270..bc2088da 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -158,7 +158,7 @@ Miner.prototype.addTX = function addTX(tx) { // Cannot calculate fee if we don't have the prev_out. // Could possibly just burn some coins. if (this.options.burn === false) { - if (!tx.hasPrevout()) + if (!tx.hasCoins()) return false; } @@ -189,7 +189,7 @@ Miner.prototype.addTX = function addTX(tx) { this.block.txs.push(tx); // Calculate our new reward fee - if (tx.hasPrevout()) + if (tx.hasCoins()) this.fee.iadd(tx.getFee()); // Update coinbase value diff --git a/lib/bcoin/mtx.js b/lib/bcoin/mtx.js index c1e6f5bb..a4470a75 100644 --- a/lib/bcoin/mtx.js +++ b/lib/bcoin/mtx.js @@ -129,7 +129,7 @@ MTX.prototype.addInput = function addInput(options, index) { if (options instanceof bcoin.coin) { options = { prevout: { hash: options.hash, index: options.index }, - output: options + coin: options }; } @@ -162,7 +162,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) { assert(input); // We should have previous outputs by now. - assert(input.output); + assert(input.coin); // Optimization: Don't bother with any below // calculation if the output is already templated. @@ -174,11 +174,11 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) { // address map to avoid unnecessary calculation. // A hash table lookup may be faster than all // the nonsense below. - if (!addr.ownOutput(input.output)) + if (!addr.ownOutput(input.coin)) return false; // Get the previous output's script - prev = input.output.script; + prev = input.coin.script; // This is easily the hardest part about building a transaction // with segwit: figuring out where the redeem script and witness @@ -353,10 +353,10 @@ MTX.prototype.signInput = function signInput(index, addr, type) { assert(input); // We should have previous outputs by now. - assert(input.output); + assert(input.coin); // Get the previous output's subscript - prev = input.output.script; + prev = input.coin.script; vector = input.script.code; len = vector.length; @@ -543,11 +543,11 @@ MTX.prototype.isSigned = function isSigned(m) { // We can't check for signatures unless // we have the previous output. - if (!input.output) + if (!input.coin) return false; // Get the prevout's subscript - prev = input.output.script; + prev = input.coin.script; // Script length, needed for multisig vector = input.script.code; @@ -660,7 +660,7 @@ MTX.prototype.addOutput = function addOutput(obj, value) { }; MTX.prototype.scriptOutput = function scriptOutput(index, options) { - var output, script, keys, m, n, hash, flags, address, redeem; + var output; if (options instanceof bcoin.output) return; @@ -696,10 +696,10 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) { size = 0; witness = false; - assert(input.output); + assert(input.coin); // Get the previous output's subscript - prev = input.output.script; + prev = input.coin.script; // If we have access to the redeem script, // we can use it to calculate size much easier. @@ -793,7 +793,7 @@ MTX.prototype.maxSize = function maxSize(maxM, maxN) { return total; }; -MTX.prototype.selectCoins = function selectCoins(unspent, options) { +MTX.prototype.selectCoins = function selectCoins(coins, options) { var tx = this.clone(); var outputValue = tx.getOutputValue(); var totalkb = 1; @@ -815,12 +815,12 @@ MTX.prototype.selectCoins = function selectCoins(unspent, options) { if (!options.selection || options.selection === 'age') { // Oldest unspents first - unspent = unspent.slice().sort(function(a, b) { + coins = coins.slice().sort(function(a, b) { return a.height - b.height; }); } else if (options.selection === 'random' || options.selection === 'all') { // Random unspents - unspent = unspent.slice().sort(function() { + coins = coins.slice().sort(function() { return Math.random() > 0.5 ? 1 : -1; }); } @@ -838,12 +838,12 @@ MTX.prototype.selectCoins = function selectCoins(unspent, options) { function addCoins() { var i, index; - for (i = lastAdded; i < unspent.length; i++) { + for (i = lastAdded; i < coins.length; i++) { // Add new inputs until MTX will have enough // funds to cover both minimum post cost // and fee. - tx.addInput(unspent[i]); - chosen.push(unspent[i]); + tx.addInput(coins[i]); + chosen.push(coins[i]); lastAdded++; if (options.wallet) @@ -887,14 +887,20 @@ MTX.prototype.selectCoins = function selectCoins(unspent, options) { // break; // } - newkb = Math.ceil(size / 1024) - totalkb; - fee.iaddn(newkb * minFee); - totalkb += newkb; + if (options.accurate) { + newkb = size / 1024; + fee = new bn(newkb * minFee | 0); + totalkb = newkb; + } else { + newkb = Math.ceil(size / 1024) - totalkb; + fee.iaddn(newkb * minFee); + totalkb += newkb; + } // Failed to get enough funds, add more inputs. if (!isFull()) addCoins(); - } while (!isFull() && lastAdded < unspent.length); + } while (!isFull() && lastAdded < coins.length); } if (!isFull()) { @@ -937,7 +943,8 @@ MTX.prototype.selectCoins = function selectCoins(unspent, options) { }; }; -MTX.prototype.fill = function fill(unspent, options) { +MTX.prototype.fill = function fill(coins, options) { + var self = this; var result, err; if (!options || typeof options !== 'object') { @@ -947,10 +954,10 @@ MTX.prototype.fill = function fill(unspent, options) { }; } - assert(unspent); + assert(coins); assert(options.changeAddress); - result = this.selectCoins(unspent, options); + result = this.selectCoins(coins, options); if (!result.coins) { err = new Error('Could not fill transaction'); @@ -959,8 +966,8 @@ MTX.prototype.fill = function fill(unspent, options) { } result.coins.forEach(function(coin) { - this.addInput(coin); - }, this); + self.addInput(coin); + }); if (result.change.cmpn(constants.tx.dustThreshold) < 0) { // Do nothing. Change is added to fee. @@ -1014,34 +1021,6 @@ MTX.prototype.sortMembers = function sortMembers() { } }; -MTX.prototype.getTargetLocktime = function getTargetLocktime() { - var bestValue = 0; - var i, locktime, bestType; - - for (i = 0; i < this.inputs.length; i++) { - locktime = this.inputs[i].getLocktime(); - - if (!locktime) - continue; - - // Incompatible types - if (bestType && bestType !== locktime.type) - return; - - bestType = locktime.type; - - if (locktime.value < bestValue) - continue; - - bestValue = locktime.value; - } - - return { - type: bestType || 'height', - value: bestValue - }; -}; - MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) { if (height == null) { if (!this.chain) @@ -1062,34 +1041,13 @@ MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) { MTX.prototype.setLocktime = function setLocktime(locktime) { var i, input; - this.locktime = locktime; - for (i = 0; i < this.inputs.length; i++) { input = this.inputs[i]; if (input.sequence === 0xffffffff) - input.sequence = 0; - } -}; - -MTX.prototype.increaseFee = function increaseFee(unspent, address, fee) { - var i, input; - - this.inputs.length = 0; - - if (this.changeIndex !== -1) { - this.outputs.splice(this.changeIndex, 1); - this.changeIndex = -1; + input.sequence = 0xffffffff - 1; } - if (!fee) - fee = this.getFee().add(new bn(10000)); - - this.fill(unspent, address, fee); - - for (i = 0; i < this.inputs.length; i++) { - input = this.inputs[i]; - input.sequence = 0xffffffff - 1; - } + this.locktime = locktime; }; MTX._fromJSON = bcoin.tx._fromJSON; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index b59e1a72..0446cd0c 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -1233,8 +1233,8 @@ Pool.prototype.isWatched = function(tx, bloom) { return true; // Test the prev_out script - if (input.output) { - if (testScript(input.output.script.code)) + if (input.coin) { + if (testScript(input.coin.script.code)) return true; } diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 2bee8eda..cf1ce5c7 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -1376,41 +1376,6 @@ Script.prototype.getSize = function getSize() { return this.encode().length; }; -Script.prototype._locktime = function _locktime() { - if (this.code.length < 2) - return; - - if (!Buffer.isBuffer(this.code[0])) - return; - - if (this.code[1] !== 'checklocktimeverify') - return; - - return this.code[0]; -}; - -Script.prototype.isLocktime = function isLocktime() { - return this._locktime() != null; -}; - -Script.prototype.getLocktime = function getLocktime() { - var locktime = this._locktime(); - - if (!locktime) - return; - - try { - locktime = Script.num(locktime, null, 4).toNumber(); - } catch (e) { - locktime = 0; - } - - if (locktime < constants.locktimeThreshold) - return { type: 'height', value: locktime }; - - return { type: 'time', value: locktime }; -}; - Script.prototype.getInputAddress = function getInputAddress(prev) { return Script.getInputAddress(this.code, prev, false); }; @@ -2238,10 +2203,10 @@ Script.format = function format(code) { scripts.push(code.script); if (code.witness.length > 0) scripts.push({ code: code.witness.items }); - if (code.output) { - scripts.push(code.output.script); - if (code.output.script.isScripthash()) - scripts.push(code.output.script.getRedeem()); + if (code.coin) { + scripts.push(code.coin.script); + if (code.coin.script.isScripthash()) + scripts.push(code.coin.script.getRedeem()); } } else if (code instanceof bcoin.output) { scripts.push(code.script); diff --git a/lib/bcoin/tx-pool.js b/lib/bcoin/tx-pool.js index f62fdf81..32848f19 100644 --- a/lib/bcoin/tx-pool.js +++ b/lib/bcoin/tx-pool.js @@ -22,7 +22,7 @@ function TXPool(wallet, txs) { this._wallet = wallet; this._all = {}; - this._unspent = {}; + this._coins = {}; this._orphans = {}; this._lastTs = 0; this._lastHeight = 0; @@ -57,10 +57,10 @@ TXPool.prototype.populate = function populate(txs) { TXPool.prototype.add = function add(tx, noWrite) { var hash = tx.hash('hex'); var updated = false; - var i, j, input, output, coin, unspent, orphan; + var i, j, input, output, coin, orphan; var key, orphans, some; - this._wallet.fillPrevout(tx); + this._wallet.fillCoins(tx); if (!this._wallet.ownInput(tx) && !this._wallet.ownOutput(tx)) return false; @@ -84,8 +84,8 @@ TXPool.prototype.add = function add(tx, noWrite) { this._all[hash].index = tx.index; this._all[hash].outputs.forEach(function(output, i) { var key = hash + '/' + i; - if (this._unspent[key]) - this._unspent[key].height = tx.height; + if (this._coins[key]) + this._coins[key].height = tx.height; }, this); this._storeTX(hash, tx, noWrite); this._lastTs = Math.max(tx.ts, this._lastTs); @@ -102,14 +102,14 @@ TXPool.prototype.add = function add(tx, noWrite) { for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; key = input.prevout.hash + '/' + input.prevout.index; - unspent = this._unspent[key]; + coin = this._coins[key]; - if (unspent) { + if (coin) { // Add TX to inputs and spend money - input.output = unspent; + input.coin = coin; - assert(input.prevout.hash === unspent.hash); - assert(input.prevout.index === unspent.index); + assert(input.prevout.hash === coin.hash); + assert(input.prevout.index === coin.index); // Skip invalid transactions if (!tx.verify(i)) @@ -117,7 +117,7 @@ TXPool.prototype.add = function add(tx, noWrite) { this._addInput(tx, i); - delete this._unspent[key]; + delete this._coins[key]; updated = true; continue; } @@ -155,7 +155,7 @@ TXPool.prototype.add = function add(tx, noWrite) { for (j = 0; j < orphans.length; j++) { orphan = orphans[j]; - orphan.tx.inputs[orphan.index].output = coin; + orphan.tx.inputs[orphan.index].coin = coin; assert(orphan.tx.inputs[orphan.index].prevout.hash === hash); assert(orphan.tx.inputs[orphan.index].prevout.index === i); @@ -178,7 +178,7 @@ TXPool.prototype.add = function add(tx, noWrite) { delete this._orphans[key]; if (!orphans) { - this._unspent[key] = coin; + this._coins[key] = coin; updated = true; } } @@ -203,7 +203,7 @@ TXPool.prototype.getTX = function getTX(hash) { }; TXPool.prototype.getCoin = function getCoin(hash, index) { - return this._unspent[hash + '/' + index]; + return this._coins[hash + '/' + index]; }; TXPool.prototype._storeTX = function _storeTX(hash, tx, noWrite) { @@ -225,8 +225,8 @@ TXPool.prototype._removeTX = function _removeTX(tx, noWrite) { for (i = 0; i < tx.outputs.length; i++) { key = hash + '/' + i; - if (this._unspent[key]) { - delete this._unspent[key]; + if (this._coins[key]) { + delete this._coins[key]; this._removeOutput(tx, i); } } @@ -259,13 +259,13 @@ TXPool.prototype.removeTX = function removeTX(hash) { for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; - if (!input.output || !this._wallet.ownOutput(input.output)) + if (!input.coin || !this._wallet.ownOutput(input.coin)) continue; this._removeInput(input); key = input.prevout.hash + '/' + input.prevout.index; - this._unspent[key] = input.output; + this._coins[key] = input.coin; updated = true; } @@ -297,8 +297,8 @@ TXPool.prototype.unconfirm = function unconfirm(hash) { tx.index = -1; tx.outputs.forEach(function(output, i) { var key = hash + '/' + i; - if (this._unspent[key]) - this._unspent[key].height = -1; + if (this._coins[key]) + this._coins[key].height = -1; }, this); this._storeTX(hash, tx); this._lastTs = Math.max(tx.ts, this._lastTs); @@ -357,12 +357,12 @@ TXPool.prototype._addInput = function _addInput(tx, i, remove) { else input = tx.inputs[i]; - assert(input.output); + assert(input.coin); - if (!this._wallet.ownOutput(input.output)) + if (!this._wallet.ownOutput(input.coin)) return; - prev = input.output; + prev = input.coin; address = prev.getAddress(); if (!this._addresses[address]) { @@ -406,12 +406,12 @@ TXPool.prototype.getAll = function getAll(address) { }); }; -TXPool.prototype.getUnspent = function getUnspent(address) { - return Object.keys(this._unspent).map(function(key) { - return this._unspent[key]; - }, this).filter(function(unspent) { +TXPool.prototype.getCoins = function getCoins(address) { + return Object.keys(this._coins).map(function(key) { + return this._coins[key]; + }, this).filter(function(coin) { if (address) { - if (!unspent.test(address)) + if (!coin.test(address)) return false; } return true; @@ -457,23 +457,17 @@ TXPool.prototype.getBalance = function getBalance(address) { return this._balance.clone(); }; -TXPool.prototype.getBalanceUnspent = function getBalanceUnspent(address) { +TXPool.prototype.getBalanceCoins = function getBalanceCoins(address) { var acc = new bn(0); - var unspent = this.getUnspent(address); - if (unspent.length === 0) + var coin = this.getCoins(address); + if (coin.length === 0) return acc; - return unspent.reduce(function(acc, coin) { + return coin.reduce(function(acc, coin) { return acc.iadd(coin.value); }, acc); }; -// Legacy -TXPool.prototype.all = TXPool.prototype.getAll; -TXPool.prototype.unspent = TXPool.prototype.getUnspent; -TXPool.prototype.pending = TXPool.prototype.getPending; -TXPool.prototype.balance = TXPool.prototype.getBalance; - /** * Expose */ diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index d167c90a..98cfd511 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -332,7 +332,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) { p.writeHash(this.inputs[index].prevout.hash); p.writeU32(this.inputs[index].prevout.index); p.writeVarBytes(prev.encode()); - p.write64(this.inputs[index].output.value); + p.write64(this.inputs[index].coin.value); p.writeU32(this.inputs[index].sequence); p.writeBytes(hashOutputs); p.writeU32(this.locktime); @@ -362,7 +362,7 @@ TX.prototype.verify = function verify(index, force, flags) { if (index != null && i !== index) return true; - if (!input.output) { + if (!input.coin) { utils.debug('Warning: Not all outputs available for tx.verify().'); return false; } @@ -370,7 +370,7 @@ TX.prototype.verify = function verify(index, force, flags) { return bcoin.script.verify( input.script, input.witness, - input.output.script, + input.coin.script, this, i, flags @@ -396,7 +396,7 @@ TX.prototype.isCoinbase = function isCoinbase() { }; TX.prototype.getFee = function getFee() { - if (!this.hasPrevout()) + if (!this.hasCoins()) return new bn(0); return this.getInputValue().sub(this.getOutputValue()); @@ -408,11 +408,11 @@ TX.prototype.getInputValue = function getInputValue() { if (this.inputs.length === 0) return acc; - if (!this.hasPrevout()) + if (!this.hasCoins()) return acc; return this.inputs.reduce(function(acc, input) { - return acc.iadd(input.output.value); + return acc.iadd(input.coin.value); }, acc); }; @@ -549,61 +549,55 @@ TX.prototype.testOutputs = function testOutputs(addressTable, index) { return false; }; -TX.prototype.hasPrevout = function hasPrevout() { +TX.prototype.hasCoins = function hasCoins() { if (this.inputs.length === 0) return false; + // if (this.isCoinbase()) + // return true; + return this.inputs.every(function(input) { - return !!input.output; + return !!input.coin; }); }; -TX.prototype.fillPrevout = function fillPrevout(txs, unspent) { - var inputs; +TX.prototype.fillCoins = function fillCoins(coins) { + var total = 0; + var inputs, txs, key, i, input; - if (txs instanceof TX) { - txs = [txs]; - unspent = null; - } else if (txs instanceof bcoin.coin) { - unspent = [txs]; - txs = null; - } else if (txs instanceof bcoin.txpool) { - unspent = txs._unspent; - txs = txs._all; - } else if (txs instanceof bcoin.wallet && txs.tx) { - unspent = txs.tx._unspent; - txs = txs.tx._all; - } + if (!Array.isArray(coins)) + coins = [coins]; - if (Array.isArray(txs)) { - txs = txs.reduce(function(out, tx) { - out[tx.hash('hex')] = tx; + if (Array.isArray(coins)) { + coins = coins.reduce(function(out, coin) { + if (coin instanceof TX) { + out[coin.hash('hex')] = coin; + } else { + assert(typeof coin.hash === 'string'); + out[coin.hash + '/' + coin.index] = coin; + } return out; }, {}); } - if (Array.isArray(unspent)) { - unspent = unspent.reduce(function(out, coin) { - out[coin.hash + '/' + coin.index] = coin; - return out; - }, {}); - } + for (i = 0; i < this.inputs.length; i++) { + input = this.inputs[i]; - inputs = this.inputs.filter(function(input) { - var key; - - if (!input.output) { - key = input.prevout.hash + '/' + input.prevout.index; - if (unspent && unspent[key]) - input.output = unspent[key]; - else if (txs && txs[input.prevout.hash]) - input.output = bcoin.coin(txs[input.prevout.hash], input.prevout.index); + if (!input.coin) { + if (coins[input.prevout.hash]) { + input.coin = bcoin.coin(coins[input.prevout.hash], input.prevout.index); + } else { + key = input.prevout.hash + '/' + input.prevout.index; + if (coins[key]) + input.coin = coins[key]; + } } - return !!input.output; - }, this); + if (input.coin) + total++; + } - return inputs.length === this.inputs.length; + return total === this.inputs.length; }; TX.prototype.isFinal = function isFinal(height, ts) { @@ -630,10 +624,10 @@ TX.prototype._getSigops = function _getSigops(scriptHash, accurate) { this.inputs.forEach(function(input) { var prev; - if (!input.output) + if (!input.coin) return; - prev = input.output.script; + prev = input.coin.script; total += input.script.getSigops(accurate); @@ -666,10 +660,10 @@ TX.prototype.getSigops = function getSigops(scriptHash, accurate) { this.inputs.forEach(function(input) { var prev; - if (!input.output) + if (!input.coin) return; - prev = input.output.script; + prev = input.coin.script; if (prev.isScripthash()) prev = input.script.getRedeem(); @@ -791,10 +785,10 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) { for (i = 0; i < this.inputs.length; i++) { input = this.inputs[i]; - if (!input.output) + if (!input.coin) return false; - args = input.output.script.getArgs(); + args = input.coin.script.getArgs(); if (args < 0) return false; @@ -813,7 +807,7 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) { return false; if ((flags & constants.flags.VERIFY_WITNESS) - && input.output.isWitnessProgram()) { + && input.coin.isWitnessProgram()) { hadWitness = true; // Input script must be empty. @@ -821,12 +815,12 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) { return false; // Verify the program in the output script - if (!this.isStandardProgram(input.witness, input.output.script, flags)) + if (!this.isStandardProgram(input.witness, input.coin.script, flags)) return false; } if ((flags & constants.flags.VERIFY_P2SH) - && input.output.script.isScripthash()) { + && input.coin.script.isScripthash()) { if (stack.length === 0) return false; @@ -925,7 +919,7 @@ TX.prototype.getPriority = function getPriority(height, size) { if (height === -1) height = null; - if (!this.hasPrevout()) + if (!this.hasCoins()) return new bn(0); if (size == null) @@ -936,10 +930,10 @@ TX.prototype.getPriority = function getPriority(height, size) { for (i = 0; i < this.inputs.length; i++) { input = this.inputs[i]; - if (!input.output) + if (!input.coin) return new bn(0); - age = input.output.getConfirmations(height); + age = input.coin.getConfirmations(height); if (age === -1) age = 0; @@ -947,7 +941,7 @@ TX.prototype.getPriority = function getPriority(height, size) { if (age !== 0) age += 1; - sum.iadd(input.output.value.muln(age)); + sum.iadd(input.coin.value.muln(age)); } return sum.divn(size); @@ -956,7 +950,7 @@ TX.prototype.getPriority = function getPriority(height, size) { TX.prototype.isFree = function isFree(height, size) { var priority; - if (!this.hasPrevout()) + if (!this.hasCoins()) return false; if (height == null) @@ -1200,12 +1194,12 @@ TX.prototype.toExtended = function toExtended(saveCoins) { if (saveCoins) { p.writeVarint(this.inputs.length); this.inputs.forEach(function(input) { - if (!input.output) { + if (!input.coin) { p.writeVarint(0); return; } - p.writeVarBytes(bcoin.protocol.framer.coin(input.output, false)); + p.writeVarBytes(bcoin.protocol.framer.coin(input.coin, false)); }); } @@ -1249,7 +1243,7 @@ TX._fromExtended = function _fromExtended(buf, saveCoins) { coin.hash = tx.inputs[i].prevout.hash; coin.index = tx.inputs[i].prevout.index; coin.coinbase = false; - tx.inputs[i].output = new bcoin.coin(coin); + tx.inputs[i].coin = new bcoin.coin(coin); } } diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index 299a9d48..42fee2b6 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -314,7 +314,7 @@ TXPool.prototype._add = function add(tx, map, callback, force) { if (coin) { // Add TX to inputs and spend money - input.output = coin; + input.coin = coin; // Skip invalid transactions if (self.options.verify) { @@ -336,7 +336,7 @@ TXPool.prototype._add = function add(tx, map, callback, force) { return next(); } - input.output = null; + input.coin = null; self.isSpent(input.prevout.hash, input.prevout.index, function(err, spentBy) { if (err) @@ -352,7 +352,7 @@ TXPool.prototype._add = function add(tx, map, callback, force) { if (!prev) return callback(new Error('Could not find double-spent coin.')); - input.output = bcoin.coin(prev, input.prevout.index); + input.coin = bcoin.coin(prev, input.prevout.index); // Skip invalid transactions if (self.options.verify) { @@ -422,7 +422,7 @@ TXPool.prototype._add = function add(tx, map, callback, force) { if (!orphan.tx) return next(); - orphan.tx.inputs[orphan.index].output = coin; + orphan.tx.inputs[orphan.index].coin = coin; assert(orphan.tx.inputs[orphan.index].prevout.hash === hash); assert(orphan.tx.inputs[orphan.index].prevout.index === i); @@ -766,7 +766,7 @@ TXPool.prototype._remove = function remove(tx, map, callback, force) { if (tx.isCoinbase()) return; - if (!input.output) + if (!input.coin) return; if (self.options.mapAddress) { @@ -786,7 +786,7 @@ TXPool.prototype._remove = function remove(tx, map, callback, force) { batch.put(prefix + 'u/t/' + input.prevout.hash + '/' + input.prevout.index, - input.output.toRaw()); + input.coin.toRaw()); batch.del(prefix + 's/t/' + input.prevout.hash @@ -1390,7 +1390,7 @@ TXPool.prototype.fillTX = function fillTX(tx, callback) { return callback(null, tx); utils.forEach(tx.inputs, function(input, next) { - if (input.output) + if (input.coin) return next(); self.getTX(input.prevout.hash, function(err, tx) { @@ -1398,7 +1398,7 @@ TXPool.prototype.fillTX = function fillTX(tx, callback) { return next(err); if (tx) - input.output = bcoin.coin(tx, input.prevout.index); + input.coin = bcoin.coin(tx, input.prevout.index); next(); }); @@ -1409,12 +1409,12 @@ TXPool.prototype.fillTX = function fillTX(tx, callback) { }); }; -TXPool.prototype.fillCoin = function fillCoin(tx, callback) { +TXPool.prototype.fillCoins = function fillCoins(tx, callback) { var self = this; if (Array.isArray(tx)) { return utils.forEachSerial(tx, function(tx, next) { - self.fillCoin(tx, function(err) { + self.fillCoins(tx, function(err) { if (err) return next(err); @@ -1429,7 +1429,7 @@ TXPool.prototype.fillCoin = function fillCoin(tx, callback) { return callback(null, tx); utils.forEach(tx.inputs, function(input, next) { - if (input.output) + if (input.coin) return next(); self.getCoin(input.prevout.hash, input.prevout.index, function(err, coin) { @@ -1437,7 +1437,7 @@ TXPool.prototype.fillCoin = function fillCoin(tx, callback) { return callback(err); if (coin) - input.output = coin; + input.coin = coin; next(); }); @@ -1559,7 +1559,7 @@ TXPool.prototype.addUnchecked = function addUnchecked(tx, callback, force) { if (tx.isCoinbase()) return; - assert(input.output); + assert(input.coin); address = input.getAddress(); batch.del(prefix + 'u/t/' + key); @@ -1625,7 +1625,7 @@ TXPool.prototype.removeUnchecked = function removeUnchecked(hash, callback, forc if (tx.isCoinbase()) return; - if (!input.output) + if (!input.coin) return; address = input.getAddress(); diff --git a/lib/bcoin/wallet.js b/lib/bcoin/wallet.js index 5aaca8ee..ff39d551 100644 --- a/lib/bcoin/wallet.js +++ b/lib/bcoin/wallet.js @@ -524,7 +524,7 @@ Wallet.prototype.fill = function fill(tx, options, callback) { }); }; -Wallet.prototype.fillPrevout = function fillPrevout(tx, callback) { +Wallet.prototype.fillCoins = function fillCoins(tx, callback) { if (!this.provider) return callback(new Error('No wallet provider available.')); @@ -615,7 +615,7 @@ Wallet.prototype.getInputPaths = function getInputPaths(tx) { var i, input, output, address, path; if (tx instanceof bcoin.input) { - path = this.getPath(tx.output.getAddress()); + path = this.getPath(tx.coin.getAddress()); if (path) paths.push(path); return paths; @@ -623,7 +623,7 @@ Wallet.prototype.getInputPaths = function getInputPaths(tx) { for (i = 0; i < tx.inputs.length; i++) { input = tx.inputs[i]; - output = input.output; + output = input.coin; assert(output); address = output.getAddress(); diff --git a/lib/bcoin/walletdb.js b/lib/bcoin/walletdb.js index 55904db7..b72d0c09 100644 --- a/lib/bcoin/walletdb.js +++ b/lib/bcoin/walletdb.js @@ -543,8 +543,8 @@ WalletDB.prototype.fillTX = function fillTX(tx, callback) { return this.tx.fillTX(tx, callback); }; -WalletDB.prototype.fillCoin = function fillCoin(tx, callback) { - return this.tx.fillCoin(tx, callback); +WalletDB.prototype.fillCoins = function fillCoins(tx, callback) { + return this.tx.fillCoins(tx, callback); }; WalletDB.prototype.removeBlockSPV = function removeBlockSPV(block, callback) { @@ -708,8 +708,8 @@ Provider.prototype.fillTX = function fillTX(tx, callback) { return this.db.fillTX(tx, callback); }; -Provider.prototype.fillCoin = function fillCoin(tx, callback) { - return this.db.fillCoin(tx, callback); +Provider.prototype.fillCoins = function fillCoins(tx, callback) { + return this.db.fillCoins(tx, callback); }; Provider.prototype.addTX = function addTX(tx, callback) { diff --git a/test/node-test.js b/test/node-test.js index 9d54a8a3..c5441e62 100644 --- a/test/node-test.js +++ b/test/node-test.js @@ -36,7 +36,7 @@ describe('Wallet', function() { hash: constants.oneHash, index: 0 }, - output: { + coin: { version: 1, height: 0, value: new bn(70000), @@ -82,7 +82,7 @@ describe('Wallet', function() { // balance: 11000 [t2, t3, t4, f1, fake].forEach(function(tx) { tx.inputs.forEach(function(input) { - delete input.output; + delete input.coin; }); }); diff --git a/test/tx-test.js b/test/tx-test.js index 2cc703ee..00366ae4 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -49,7 +49,7 @@ describe('TX', function() { it('should be verifiable', function() { var tx = bcoin.tx(parser.parseTX(new Buffer(raw, 'hex'))); var p = bcoin.tx(parser.parseTX(new Buffer(inp, 'hex'))); - tx.fillPrevout(p); + tx.fillCoins(p); assert(tx.verify()); }); diff --git a/test/wallet-test.js b/test/wallet-test.js index fa2cab82..720a54c0 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -9,7 +9,7 @@ var dummyInput = { hash: constants.zeroHash, index: 0 }, - output: { + coin: { version: 1, height: 0, value: constants.maxMoney.clone(),