coinview: refactor api.

This commit is contained in:
Christopher Jeffrey 2017-07-03 17:28:36 -07:00
parent f8deb0cdfd
commit 492c05c378
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
11 changed files with 181 additions and 124 deletions

View File

@ -2325,19 +2325,19 @@ Chain.prototype.getLocks = async function getLocks(prev, tx, view, flags) {
if (tx.isCoinbase() || tx.version < 2 || !hasFlag)
return [minHeight, minTime];
for (let input of tx.inputs) {
for (let {prevout, sequence} of tx.inputs) {
let height, time, entry;
if (input.sequence & disableFlag)
if (sequence & disableFlag)
continue;
height = view.getHeight(input);
height = view.getHeight(prevout);
if (height === -1)
height = this.height + 1;
if ((input.sequence & typeFlag) === 0) {
height += (input.sequence & mask) - 1;
if ((sequence & typeFlag) === 0) {
height += (sequence & mask) - 1;
minHeight = Math.max(minHeight, height);
continue;
}
@ -2347,7 +2347,7 @@ Chain.prototype.getLocks = async function getLocks(prev, tx, view, flags) {
assert(entry, 'Database is corrupt.');
time = await entry.getMedianTime();
time += ((input.sequence & mask) << granularity) - 1;
time += ((sequence & mask) << granularity) - 1;
minTime = Math.max(minTime, time);
}

View File

@ -1728,8 +1728,8 @@ ChainDB.prototype.connectBlock = async function connectBlock(entry, block, view)
let tx = block.txs[i];
if (i > 0) {
for (let input of tx.inputs)
this.pending.spend(view.getOutput(input));
for (let {prevout} of tx.inputs)
this.pending.spend(view.getOutput(prevout));
}
for (let output of tx.outputs) {
@ -1780,9 +1780,9 @@ ChainDB.prototype.disconnectBlock = async function disconnectBlock(entry, block)
if (i > 0) {
for (let j = tx.inputs.length - 1; j >= 0; j--) {
let input = tx.inputs[j];
undo.apply(view, input.prevout);
this.pending.add(view.getOutput(input));
let {prevout} = tx.inputs[j];
undo.apply(view, prevout);
this.pending.add(view.getOutput(prevout));
}
}
@ -1884,9 +1884,8 @@ ChainDB.prototype.indexTX = function indexTX(tx, view, entry, index) {
return;
if (!tx.isCoinbase()) {
for (let input of tx.inputs) {
let prevout = input.prevout;
let addr = view.getOutput(input).getHash();
for (let {prevout} of tx.inputs) {
let addr = view.getOutput(prevout).getHash();
if (!addr)
continue;
@ -1929,9 +1928,8 @@ ChainDB.prototype.unindexTX = function unindexTX(tx, view) {
return;
if (!tx.isCoinbase()) {
for (let input of tx.inputs) {
let prevout = input.prevout;
let addr = view.getOutput(input).getHash();
for (let {prevout} of tx.inputs) {
let addr = view.getOutput(prevout).getHash();
if (!addr)
continue;

View File

@ -205,73 +205,73 @@ CoinView.prototype.removeOutput = function removeOutput(prevout) {
};
/**
* Get a single entry by input.
* @param {Input} input
* @returns {CoinEntry}
*/
CoinView.prototype.getEntry = function getEntry(input) {
let coins = this.get(input.prevout.hash);
if (!coins)
return;
return coins.get(input.prevout.index);
};
/**
* Get a single coin by input.
* @param {Input} input
* @returns {Coin}
*/
CoinView.prototype.getCoin = function getCoin(input) {
let coins = this.get(input.prevout.hash);
if (!coins)
return;
return coins.getCoin(input.prevout);
};
/**
* Get a single output by input.
* @param {Input} input
* @returns {Output}
*/
CoinView.prototype.getOutput = function getOutput(input) {
let coins = this.get(input.prevout.hash);
if (!coins)
return;
return coins.getOutput(input.prevout.index);
};
/**
* Test whether the view has an entry by input.
* @param {Input} input
* Test whether the view has an entry by prevout.
* @param {Outpoint} prevout
* @returns {Boolean}
*/
CoinView.prototype.hasEntry = function hasEntry(input) {
let coins = this.get(input.prevout.hash);
CoinView.prototype.hasEntry = function hasEntry(prevout) {
let coins = this.get(prevout.hash);
if (!coins)
return false;
return coins.has(input.prevout.index);
return coins.has(prevout.index);
};
/**
* Get coins height by input.
* @param {Input} input
* Get a single entry by input.
* @param {Outpoint} prevout
* @returns {CoinEntry}
*/
CoinView.prototype.getEntry = function getEntry(prevout) {
let coins = this.get(prevout.hash);
if (!coins)
return;
return coins.get(prevout.index);
};
/**
* Get a single coin by prevout.
* @param {Outpoint} prevout
* @returns {Coin}
*/
CoinView.prototype.getCoin = function getCoin(prevout) {
let coins = this.get(prevout.hash);
if (!coins)
return;
return coins.getCoin(prevout);
};
/**
* Get a single output by prevout.
* @param {Outpoint} prevout
* @returns {Output}
*/
CoinView.prototype.getOutput = function getOutput(prevout) {
let coins = this.get(prevout.hash);
if (!coins)
return;
return coins.getOutput(prevout.index);
};
/**
* Get coins height by prevout.
* @param {Outpoint} prevout
* @returns {Number}
*/
CoinView.prototype.getHeight = function getHeight(input) {
let coin = this.getEntry(input);
CoinView.prototype.getHeight = function getHeight(prevout) {
let coin = this.getEntry(prevout);
if (!coin)
return -1;
@ -280,13 +280,13 @@ CoinView.prototype.getHeight = function getHeight(input) {
};
/**
* Get coins coinbase flag by input.
* @param {Input} input
* Get coins coinbase flag by prevout.
* @param {Outpoint} prevout
* @returns {Boolean}
*/
CoinView.prototype.isCoinbase = function isCoinbase(input) {
let coin = this.getEntry(input);
CoinView.prototype.isCoinbase = function isCoinbase(prevout) {
let coin = this.getEntry(prevout);
if (!coin)
return false;
@ -294,17 +294,76 @@ CoinView.prototype.isCoinbase = function isCoinbase(input) {
return coin.coinbase;
};
/**
* Test whether the view has an entry by input.
* @param {Input} input
* @returns {Boolean}
*/
CoinView.prototype.hasEntryFor = function hasEntryFor(input) {
return this.hasEntry(input.prevout);
};
/**
* Get a single entry by input.
* @param {Input} input
* @returns {CoinEntry}
*/
CoinView.prototype.getEntryFor = function getEntryFor(input) {
return this.getEntry(input.prevout);
};
/**
* Get a single coin by input.
* @param {Input} input
* @returns {Coin}
*/
CoinView.prototype.getCoinFor = function getCoinFor(input) {
return this.getCoin(input.prevout);
};
/**
* Get a single output by input.
* @param {Input} input
* @returns {Output}
*/
CoinView.prototype.getOutputFor = function getOutputFor(input) {
return this.getOutput(input.prevout);
};
/**
* Get coins height by input.
* @param {Input} input
* @returns {Number}
*/
CoinView.prototype.getHeightFor = function getHeightFor(input) {
return this.getHeight(input.prevout);
};
/**
* Get coins coinbase flag by input.
* @param {Input} input
* @returns {Boolean}
*/
CoinView.prototype.isCoinbaseFor = function isCoinbaseFor(input) {
return this.isCoinbase(input.prevout);
};
/**
* Retrieve coins from database.
* @method
* @param {ChainDB} db
* @param {Input} input
* @param {Outpoint} prevout
* @returns {Promise} - Returns {@link Coins}.
*/
CoinView.prototype.readCoin = async function readCoin(db, input) {
let coin = this.getEntry(input);
let prevout = input.prevout;
CoinView.prototype.readCoin = async function readCoin(db, prevout) {
let coin = this.getEntry(prevout);
if (coin)
return coin;
@ -330,8 +389,8 @@ CoinView.prototype.readCoin = async function readCoin(db, input) {
CoinView.prototype.readInputs = async function readInputs(db, tx) {
let found = true;
for (let input of tx.inputs) {
if (!(await this.readCoin(db, input)))
for (let {prevout} of tx.inputs) {
if (!(await this.readCoin(db, prevout)))
found = false;
}
@ -351,8 +410,8 @@ CoinView.prototype.spendInputs = async function spendInputs(db, tx) {
let jobs = [];
let coins;
for (let input of tx.inputs)
jobs.push(this.readCoin(db, input));
for (let {prevout} of tx.inputs)
jobs.push(this.readCoin(db, prevout));
coins = await Promise.all(jobs);
@ -367,8 +426,8 @@ CoinView.prototype.spendInputs = async function spendInputs(db, tx) {
return true;
}
for (let input of tx.inputs) {
let coin = await this.readCoin(db, input);
for (let {prevout} of tx.inputs) {
let coin = await this.readCoin(db, prevout);
if (!coin || coin.spent)
return false;

View File

@ -1691,8 +1691,8 @@ Mempool.prototype.getCoinView = async function getCoinView(tx) {
Mempool.prototype.findMissing = function findMissing(tx, view) {
let missing = [];
for (let input of tx.inputs) {
if (view.hasEntry(input))
for (let {prevout} of tx.inputs) {
if (view.hasEntry(prevout))
continue;
missing.push(input.prevout.hash);

View File

@ -99,8 +99,8 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
let fee = tx.getFee(view);
let dependencies = false;
for (let input of tx.inputs) {
if (view.getHeight(input) === -1) {
for (let {prevout} of tx.inputs) {
if (view.getHeight(prevout) === -1) {
dependencies = true;
break;
}

View File

@ -841,8 +841,8 @@ MTX.prototype.signVector = function signVector(prev, vector, sig, ring) {
MTX.prototype.isSigned = function isSigned() {
for (let i = 0; i < this.inputs.length; i++) {
let input = this.inputs[i];
let coin = this.view.getOutput(input);
let {prevout} = this.inputs[i];
let coin = this.view.getOutput(prevout);
if (!coin)
return false;
@ -963,8 +963,8 @@ MTX.prototype.template = function template(ring) {
}
for (let i = 0; i < this.inputs.length; i++) {
let input = this.inputs[i];
let coin = this.view.getOutput(input);
let {prevout} = this.inputs[i];
let coin = this.view.getOutput(prevout);
if (!coin)
continue;
@ -1002,8 +1002,8 @@ MTX.prototype.sign = function sign(ring, type) {
assert(ring.privateKey, 'No private key available.');
for (let i = 0; i < this.inputs.length; i++) {
let input = this.inputs[i];
let coin = this.view.getOutput(input);
let {prevout} = this.inputs[i];
let coin = this.view.getOutput(prevout);
if (!coin)
continue;
@ -1064,8 +1064,8 @@ MTX.prototype.estimateSize = async function estimateSize(estimate) {
total += 4;
// Add size for signatures and public keys
for (let input of this.inputs) {
let coin = this.view.getOutput(input);
for (let {prevout} of this.inputs) {
let coin = this.view.getOutput(prevout);
let size = 0;
let prev;

View File

@ -770,8 +770,8 @@ TX.prototype.check = function check(view, flags) {
return;
for (let i = 0; i < this.inputs.length; i++) {
let input = this.inputs[i];
let coin = view.getOutput(input);
let {prevout} = this.inputs[i];
let coin = view.getOutput(prevout);
if (!coin)
throw new ScriptError('UNKNOWN_ERROR', 'No coin available.');
@ -979,8 +979,8 @@ TX.prototype.getFee = function getFee(view) {
TX.prototype.getInputValue = function getInputValue(view) {
let total = 0;
for (let input of this.inputs) {
let coin = view.getOutput(input);
for (let {prevout} of this.inputs) {
let coin = view.getOutput(prevout);
if (!coin)
return 0;
@ -1020,7 +1020,7 @@ TX.prototype._getInputAddresses = function getInputAddresses(view) {
return [addrs, table];
for (let input of this.inputs) {
let coin = view ? view.getOutput(input) : null;
let coin = view ? view.getOutputFor(input) : null;
let addr = input.getAddress(coin);
let hash;
@ -1200,8 +1200,8 @@ TX.prototype.hasCoins = function hasCoins(view) {
if (this.inputs.length === 0)
return false;
for (let input of this.inputs) {
if (!view.hasEntry(input))
for (let {prevout} of this.inputs) {
if (!view.hasEntry(prevout))
return false;
}
@ -1342,7 +1342,7 @@ TX.prototype.getScripthashSigops = function getScripthashSigops(view) {
return 0;
for (let input of this.inputs) {
let coin = view.getOutput(input);
let coin = view.getOutputFor(input);
if (!coin)
continue;
@ -1380,7 +1380,7 @@ TX.prototype.getSigopsCost = function getSigopsCost(view, flags) {
return cost;
for (let input of this.inputs) {
let coin = view.getOutput(input);
let coin = view.getOutputFor(input);
if (!coin)
continue;
@ -1547,7 +1547,7 @@ TX.prototype.hasStandardInputs = function hasStandardInputs(view) {
return true;
for (let input of this.inputs) {
let coin = view.getOutput(input);
let coin = view.getOutputFor(input);
if (!coin)
return false;
@ -1587,7 +1587,7 @@ TX.prototype.hasStandardWitness = function hasStandardWitness(view) {
for (let input of this.inputs) {
let witness = input.witness;
let coin = view.getOutput(input);
let coin = view.getOutputFor(input);
let prev;
if (!coin)
@ -1730,8 +1730,8 @@ TX.prototype.checkInputs = function checkInputs(view, height) {
assert(typeof height === 'number');
for (let input of this.inputs) {
let coin = view.getEntry(input);
for (let {prevout} of this.inputs) {
let coin = view.getEntry(prevout);
if (!coin)
return [-1, 'bad-txns-inputs-missingorspent', 0];
@ -1741,7 +1741,7 @@ TX.prototype.checkInputs = function checkInputs(view, height) {
return [-1, 'bad-txns-premature-spend-of-coinbase', 0];
}
coin = view.getOutput(input);
coin = view.getOutput(prevout);
assert(coin);
if (coin.value < 0 || coin.value > consensus.MAX_MONEY)
@ -1813,14 +1813,14 @@ TX.prototype.getPriority = function getPriority(view, height, size) {
if (size == null)
size = this.getVirtualSize();
for (let input of this.inputs) {
let coin = view.getOutput(input);
for (let {prevout} of this.inputs) {
let coin = view.getOutput(prevout);
let coinHeight;
if (!coin)
continue;
coinHeight = view.getHeight(input);
coinHeight = view.getHeight(prevout);
if (coinHeight === -1)
continue;
@ -1846,14 +1846,14 @@ TX.prototype.getChainValue = function getChainValue(view) {
if (this.isCoinbase())
return value;
for (let input of this.inputs) {
let coin = view.getOutput(input);
for (let {prevout} of this.inputs) {
let coin = view.getOutput(prevout);
let coinHeight;
if (!coin)
continue;
coinHeight = view.getHeight(input);
coinHeight = view.getHeight(prevout);
if (coinHeight === -1)
continue;
@ -2118,7 +2118,7 @@ TX.prototype.format = function format(view, entry, index) {
version: this.version,
flag: this.flag,
inputs: this.inputs.map((input) => {
let coin = view ? view.getOutput(input) : null;
let coin = view ? view.getOutputFor(input) : null;
return input.format(coin);
}),
outputs: this.outputs,
@ -2183,7 +2183,7 @@ TX.prototype.getJSON = function getJSON(network, view, entry, index) {
version: this.version,
flag: this.flag,
inputs: this.inputs.map((input) => {
let coin = view ? view.getCoin(input) : null;
let coin = view ? view.getCoinFor(input) : null;
return input.getJSON(network, coin);
}),
outputs: this.outputs.map((output) => {

View File

@ -51,7 +51,7 @@ describe('Coins', function() {
assert(entry.output instanceof Output);
assert.equal(entry.spent, false);
output = view.getOutput(input);
output = view.getOutputFor(input);
assert(output);
deepCoinsEqual(entry, reserialize(entry));

View File

@ -77,7 +77,7 @@ function parseTest(data) {
view.addCoin(coin);
}
coin = view.getOutput(tx.inputs[0]);
coin = view.getOutputFor(tx.inputs[0]);
return {
tx: tx,
@ -204,7 +204,7 @@ describe('TX', function() {
});
it(`should verify high S value with only DERSIG enabled ${suffix}`, () => {
let coin = tx4.view.getOutput(tx4.tx.inputs[0]);
let coin = tx4.view.getOutputFor(tx4.tx.inputs[0]);
let flags = Script.flags.VERIFY_P2SH | Script.flags.VERIFY_DERSIG;
clearCache(tx4.tx, noCache);
assert(tx4.tx.verifyInput(0, coin, flags));

View File

@ -339,7 +339,7 @@ MemWallet.prototype.deriveInputs = function deriveInputs(mtx) {
for (i = 0; i < mtx.inputs.length; i++) {
input = mtx.inputs[i];
coin = mtx.view.getOutput(input);
coin = mtx.view.getOutputFor(input);
if (!coin)
continue;

View File

@ -1067,7 +1067,7 @@ describe('Wallet', function() {
found = false;
for (i = 0; i < t3.inputs.length; i++) {
coin = t3.view.getCoin(t3.inputs[i]);
coin = t3.view.getCoinFor(t3.inputs[i]);
if (coin.height === -1) {
assert(!found);
assert(coin.value < 5460);