coinview: refactor api.
This commit is contained in:
parent
f8deb0cdfd
commit
492c05c378
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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) => {
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user