coins: get rid of return value polymorphism.
This commit is contained in:
parent
50c75aeea8
commit
0805babec1
@ -13,13 +13,12 @@ const CoinEntry = require('./coinentry');
|
||||
* Represents the outputs for a single transaction.
|
||||
* @alias module:coins.Coins
|
||||
* @constructor
|
||||
* @property {Hash} hash - Transaction hash.
|
||||
* @property {CoinEntry[]} outputs - Coins.
|
||||
* @property {Map[]} outputs - Coins.
|
||||
*/
|
||||
|
||||
function Coins(options) {
|
||||
function Coins() {
|
||||
if (!(this instanceof Coins))
|
||||
return new Coins(options);
|
||||
return new Coins();
|
||||
|
||||
this.outputs = new Map();
|
||||
}
|
||||
@ -28,35 +27,39 @@ function Coins(options) {
|
||||
* Add a single entry to the collection.
|
||||
* @param {Number} index
|
||||
* @param {CoinEntry} coin
|
||||
* @returns {CoinEntry}
|
||||
*/
|
||||
|
||||
Coins.prototype.add = function add(index, coin) {
|
||||
assert(index >= 0);
|
||||
|
||||
assert(!this.outputs.has(index));
|
||||
|
||||
this.outputs.set(index, coin);
|
||||
|
||||
return coin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a single output to the collection.
|
||||
* @param {Number} index
|
||||
* @param {Output} output
|
||||
* @returns {CoinEntry}
|
||||
*/
|
||||
|
||||
Coins.prototype.addOutput = function addOutput(index, output) {
|
||||
assert(!output.script.isUnspendable());
|
||||
this.add(index, CoinEntry.fromOutput(output));
|
||||
return this.add(index, CoinEntry.fromOutput(output));
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a single coin to the collection.
|
||||
* @param {Coin} coin
|
||||
* @returns {CoinEntry}
|
||||
*/
|
||||
|
||||
Coins.prototype.addCoin = function addCoin(coin) {
|
||||
assert(!coin.script.isUnspendable());
|
||||
this.add(coin.index, CoinEntry.fromCoin(coin));
|
||||
return this.add(coin.index, CoinEntry.fromCoin(coin));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -87,24 +90,24 @@ Coins.prototype.isUnspent = function isUnspent(index) {
|
||||
/**
|
||||
* Get a coin entry.
|
||||
* @param {Number} index
|
||||
* @returns {CoinEntry}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
Coins.prototype.get = function get(index) {
|
||||
return this.outputs.get(index);
|
||||
return this.outputs.get(index) || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get an output.
|
||||
* @param {Number} index
|
||||
* @returns {Output}
|
||||
* @returns {Output|null}
|
||||
*/
|
||||
|
||||
Coins.prototype.getOutput = function getOutput(index) {
|
||||
let coin = this.outputs.get(index);
|
||||
|
||||
if (!coin)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return coin.output;
|
||||
};
|
||||
@ -112,14 +115,14 @@ Coins.prototype.getOutput = function getOutput(index) {
|
||||
/**
|
||||
* Get a coin.
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {Coin}
|
||||
* @returns {Coin|null}
|
||||
*/
|
||||
|
||||
Coins.prototype.getCoin = function getCoin(prevout) {
|
||||
let coin = this.outputs.get(prevout.index);
|
||||
|
||||
if (!coin)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return coin.toCoin(prevout);
|
||||
};
|
||||
@ -127,14 +130,14 @@ Coins.prototype.getCoin = function getCoin(prevout) {
|
||||
/**
|
||||
* Spend a coin entry and return it.
|
||||
* @param {Number} index
|
||||
* @returns {CoinEntry}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
Coins.prototype.spend = function spend(index) {
|
||||
let coin = this.get(index);
|
||||
|
||||
if (!coin || coin.spent)
|
||||
return;
|
||||
return null;
|
||||
|
||||
coin.spent = true;
|
||||
|
||||
@ -144,38 +147,20 @@ Coins.prototype.spend = function spend(index) {
|
||||
/**
|
||||
* Remove a coin entry and return it.
|
||||
* @param {Number} index
|
||||
* @returns {CoinEntry}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
Coins.prototype.remove = function remove(index) {
|
||||
let coin = this.get(index);
|
||||
|
||||
if (!coin)
|
||||
return false;
|
||||
return null;
|
||||
|
||||
this.outputs.delete(index);
|
||||
|
||||
return coin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate unspent length of coins.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
Coins.prototype.length = function length() {
|
||||
let len = -1;
|
||||
|
||||
for (let [index, coin] of this.outputs) {
|
||||
if (!coin.spent) {
|
||||
if (index > len)
|
||||
len = index;
|
||||
}
|
||||
}
|
||||
|
||||
return len + 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the coins are fully spent.
|
||||
* @returns {Boolean}
|
||||
@ -190,6 +175,7 @@ Coins.prototype.isEmpty = function isEmpty() {
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
* @returns {Coins}
|
||||
*/
|
||||
|
||||
Coins.prototype.fromTX = function fromTX(tx, height) {
|
||||
|
||||
@ -51,6 +51,7 @@ CoinView.prototype.has = function has(hash) {
|
||||
* Add coins to the collection.
|
||||
* @param {Hash} hash
|
||||
* @param {Coins} coins
|
||||
* @returns {Coins}
|
||||
*/
|
||||
|
||||
CoinView.prototype.add = function add(hash, coins) {
|
||||
@ -61,49 +62,55 @@ CoinView.prototype.add = function add(hash, coins) {
|
||||
/**
|
||||
* Remove coins from the collection.
|
||||
* @param {Coins} coins
|
||||
* @returns {Boolean}
|
||||
* @returns {Coins|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.remove = function remove(hash) {
|
||||
if (!this.map.has(hash))
|
||||
return false;
|
||||
let coins = this.map.get(hash);
|
||||
|
||||
if (!coins)
|
||||
return null;
|
||||
|
||||
this.map.delete(hash);
|
||||
|
||||
return true;
|
||||
return coins;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a tx to the collection.
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
* @returns {Coins}
|
||||
*/
|
||||
|
||||
CoinView.prototype.addTX = function addTX(tx, height) {
|
||||
let hash = tx.hash('hex');
|
||||
let coins = Coins.fromTX(tx, height);
|
||||
return this.add(tx.hash('hex'), coins);
|
||||
return this.add(hash, coins);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a tx from the collection.
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
* @returns {Coins}
|
||||
*/
|
||||
|
||||
CoinView.prototype.removeTX = function removeTX(tx, height) {
|
||||
let hash = tx.hash('hex');
|
||||
let coins = Coins.fromTX(tx, height);
|
||||
|
||||
for (let coin of coins.outputs.values())
|
||||
coin.spent = true;
|
||||
|
||||
return this.add(tx.hash('hex'), coins);
|
||||
return this.add(hash, coins);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an entry to the collection.
|
||||
* @param {Outpoint} prevout
|
||||
* @param {CoinEntry} coin
|
||||
* @returns {Coins|null}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.addEntry = function addEntry(prevout, coin) {
|
||||
@ -116,17 +123,18 @@ CoinView.prototype.addEntry = function addEntry(prevout, coin) {
|
||||
}
|
||||
|
||||
if (coin.output.script.isUnspendable())
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!coins.has(index))
|
||||
coins.add(index, coin);
|
||||
if (coins.has(index))
|
||||
return null;
|
||||
|
||||
return coins;
|
||||
return coins.add(index, coin);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a coin to the collection.
|
||||
* @param {Coin} coin
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.addCoin = function addCoin(coin) {
|
||||
@ -139,18 +147,19 @@ CoinView.prototype.addCoin = function addCoin(coin) {
|
||||
}
|
||||
|
||||
if (coin.script.isUnspendable())
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!coins.has(index))
|
||||
coins.addCoin(coin);
|
||||
if (coins.has(index))
|
||||
return null;
|
||||
|
||||
return coins;
|
||||
return coins.addCoin(coin);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an output to the collection.
|
||||
* @param {Outpoint} prevout
|
||||
* @param {Output} output
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.addOutput = function addOutput(prevout, output) {
|
||||
@ -163,16 +172,18 @@ CoinView.prototype.addOutput = function addOutput(prevout, output) {
|
||||
}
|
||||
|
||||
if (output.script.isUnspendable())
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!coins.has(index))
|
||||
coins.addOutput(index, output);
|
||||
if (coins.has(index))
|
||||
return null;
|
||||
|
||||
return coins.addOutput(index, output);
|
||||
};
|
||||
|
||||
/**
|
||||
* Spend an output.
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {Boolean}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.spendOutput = function spendOutput(prevout) {
|
||||
@ -181,22 +192,22 @@ CoinView.prototype.spendOutput = function spendOutput(prevout) {
|
||||
let coin;
|
||||
|
||||
if (!coins)
|
||||
return false;
|
||||
return null;
|
||||
|
||||
coin = coins.spend(index);
|
||||
|
||||
if (!coin)
|
||||
return false;
|
||||
return null;
|
||||
|
||||
this.undo.push(coin);
|
||||
|
||||
return true;
|
||||
return coin;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an output.
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {Boolean}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.removeOutput = function removeOutput(prevout) {
|
||||
@ -204,7 +215,7 @@ CoinView.prototype.removeOutput = function removeOutput(prevout) {
|
||||
let coins = this.get(hash);
|
||||
|
||||
if (!coins)
|
||||
return false;
|
||||
return null;
|
||||
|
||||
return coins.remove(index);
|
||||
};
|
||||
@ -226,9 +237,9 @@ CoinView.prototype.hasEntry = function hasEntry(prevout) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a single entry by input.
|
||||
* Get a single entry by prevout.
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {CoinEntry}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.getEntry = function getEntry(prevout) {
|
||||
@ -236,7 +247,7 @@ CoinView.prototype.getEntry = function getEntry(prevout) {
|
||||
let coins = this.get(hash);
|
||||
|
||||
if (!coins)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return coins.get(index);
|
||||
};
|
||||
@ -244,14 +255,14 @@ CoinView.prototype.getEntry = function getEntry(prevout) {
|
||||
/**
|
||||
* Get a single coin by prevout.
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {Coin}
|
||||
* @returns {Coin|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.getCoin = function getCoin(prevout) {
|
||||
let coins = this.get(prevout.hash);
|
||||
|
||||
if (!coins)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return coins.getCoin(prevout);
|
||||
};
|
||||
@ -259,7 +270,7 @@ CoinView.prototype.getCoin = function getCoin(prevout) {
|
||||
/**
|
||||
* Get a single output by prevout.
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {Output}
|
||||
* @returns {Output|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.getOutput = function getOutput(prevout) {
|
||||
@ -267,7 +278,7 @@ CoinView.prototype.getOutput = function getOutput(prevout) {
|
||||
let coins = this.get(hash);
|
||||
|
||||
if (!coins)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return coins.getOutput(index);
|
||||
};
|
||||
@ -315,7 +326,7 @@ CoinView.prototype.hasEntryFor = function hasEntryFor(input) {
|
||||
/**
|
||||
* Get a single entry by input.
|
||||
* @param {Input} input
|
||||
* @returns {CoinEntry}
|
||||
* @returns {CoinEntry|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.getEntryFor = function getEntryFor(input) {
|
||||
@ -325,7 +336,7 @@ CoinView.prototype.getEntryFor = function getEntryFor(input) {
|
||||
/**
|
||||
* Get a single coin by input.
|
||||
* @param {Input} input
|
||||
* @returns {Coin}
|
||||
* @returns {Coin|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.getCoinFor = function getCoinFor(input) {
|
||||
@ -335,7 +346,7 @@ CoinView.prototype.getCoinFor = function getCoinFor(input) {
|
||||
/**
|
||||
* Get a single output by input.
|
||||
* @param {Input} input
|
||||
* @returns {Output}
|
||||
* @returns {Output|null}
|
||||
*/
|
||||
|
||||
CoinView.prototype.getOutputFor = function getOutputFor(input) {
|
||||
@ -367,7 +378,7 @@ CoinView.prototype.isCoinbaseFor = function isCoinbaseFor(input) {
|
||||
* @method
|
||||
* @param {ChainDB} db
|
||||
* @param {Outpoint} prevout
|
||||
* @returns {Promise} - Returns {@link Coins}.
|
||||
* @returns {Promise} - Returns {@link CoinEntry}.
|
||||
*/
|
||||
|
||||
CoinView.prototype.readCoin = async function readCoin(db, prevout) {
|
||||
@ -381,9 +392,7 @@ CoinView.prototype.readCoin = async function readCoin(db, prevout) {
|
||||
if (!coin)
|
||||
return null;
|
||||
|
||||
this.addEntry(prevout, coin);
|
||||
|
||||
return coin;
|
||||
return this.addEntry(prevout, coin);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -66,7 +66,7 @@ describe('Coins', function() {
|
||||
|
||||
coins = view.get(hash);
|
||||
assert(coins);
|
||||
length = coins.length();
|
||||
length = coins.outputs.size;
|
||||
|
||||
view.spendOutput(new Outpoint(hash, 0));
|
||||
|
||||
@ -78,7 +78,7 @@ describe('Coins', function() {
|
||||
assert(entry.spent);
|
||||
|
||||
deepCoinsEqual(entry, reserialize(entry));
|
||||
assert.strictEqual(coins.length(), length);
|
||||
assert.strictEqual(coins.outputs.size, length);
|
||||
|
||||
assert.equal(view.undo.items.length, 1);
|
||||
});
|
||||
@ -102,8 +102,8 @@ describe('Coins', function() {
|
||||
prev = tx1.inputs[0].prevout;
|
||||
coins = res.get(prev.hash);
|
||||
|
||||
assert.strictEqual(coins.length(), 2);
|
||||
assert.strictEqual(coins.get(0), undefined);
|
||||
assert.strictEqual(coins.outputs.size, 1);
|
||||
assert.strictEqual(coins.get(0), null);
|
||||
deepCoinsEqual(coins.get(1), reserialize(coins.get(1)));
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user