chain: refactor coinview.
This commit is contained in:
parent
9e4db47792
commit
8b99b5103b
@ -848,6 +848,34 @@ ChainDB.prototype.hasCoins = function hasCoins(hash) {
|
|||||||
return this.db.has(layout.c(hash));
|
return this.db.has(layout.c(hash));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get coin viewpoint.
|
||||||
|
* @param {TX} tx
|
||||||
|
* @returns {Promise} - Returns {@link CoinView}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ChainDB.prototype.getCoinView = co(function* getCoinView(tx, callback) {
|
||||||
|
var view = new CoinView();
|
||||||
|
var prevout = tx.getPrevout();
|
||||||
|
var i, prev, coins;
|
||||||
|
|
||||||
|
for (i = 0; i < prevout.length; i++) {
|
||||||
|
prev = prevout[i];
|
||||||
|
coins = yield this.getCoins(prev);
|
||||||
|
|
||||||
|
if (!coins) {
|
||||||
|
coins = new Coins();
|
||||||
|
coins.hash = prev.hash;
|
||||||
|
view.add(coins);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
view.add(coins);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coins necessary to be resurrected during a reorg.
|
* Get coins necessary to be resurrected during a reorg.
|
||||||
* @param {Hash} hash
|
* @param {Hash} hash
|
||||||
|
|||||||
@ -90,20 +90,39 @@ Coins.fromOptions = function fromOptions(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single output to the collection.
|
* Add a single entry to the collection.
|
||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
* @param {Output} output
|
* @param {CoinEntry} entry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.add = function add(index, output) {
|
Coins.prototype.add = function add(index, entry) {
|
||||||
assert(!output.script.isUnspendable());
|
|
||||||
|
|
||||||
while (this.outputs.length <= index)
|
while (this.outputs.length <= index)
|
||||||
this.outputs.push(null);
|
this.outputs.push(null);
|
||||||
|
|
||||||
assert(!this.outputs[index]);
|
assert(!this.outputs[index]);
|
||||||
|
|
||||||
this.outputs[index] = CoinEntry.fromOutput(output);
|
this.outputs[index] = entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a single output to the collection.
|
||||||
|
* @param {Number} index
|
||||||
|
* @param {Output} output
|
||||||
|
*/
|
||||||
|
|
||||||
|
Coins.prototype.addOutput = function addOutput(index, output) {
|
||||||
|
assert(!output.script.isUnspendable());
|
||||||
|
this.add(index, CoinEntry.fromOutput(output));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a single coin to the collection.
|
||||||
|
* @param {Coin} coin
|
||||||
|
*/
|
||||||
|
|
||||||
|
Coins.prototype.addCoin = function addCoin(coin) {
|
||||||
|
assert(!coin.script.isUnspendable());
|
||||||
|
this.add(coin.index, CoinEntry.fromCoin(coin));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,6 +151,21 @@ Coins.prototype.get = function get(index) {
|
|||||||
return this.outputs[index];
|
return this.outputs[index];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an output.
|
||||||
|
* @param {Number} index
|
||||||
|
* @returns {Output}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Coins.prototype.getOutput = function getOutput(index) {
|
||||||
|
var entry = this.get(index);
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return entry.toOutput();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a coin.
|
* Get a coin.
|
||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
@ -426,6 +460,7 @@ Coins.fromRaw = function fromRaw(data, hash) {
|
|||||||
* Inject properties from tx.
|
* Inject properties from tx.
|
||||||
* @private
|
* @private
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
|
* @param {Number} height
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.fromTX = function fromTX(tx, height) {
|
Coins.prototype.fromTX = function fromTX(tx, height) {
|
||||||
@ -457,6 +492,7 @@ Coins.prototype.fromTX = function fromTX(tx, height) {
|
|||||||
/**
|
/**
|
||||||
* Instantiate a coins object from a transaction.
|
* Instantiate a coins object from a transaction.
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
|
* @param {Number} height
|
||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -586,7 +622,7 @@ CoinEntry.fromReader = function fromReader(br) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate compressed coin from coin.
|
* Instantiate compressed coin from output.
|
||||||
* @param {Output} output
|
* @param {Output} output
|
||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
@ -597,6 +633,21 @@ CoinEntry.fromOutput = function fromOutput(output) {
|
|||||||
return entry;
|
return entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate compressed coin from coin.
|
||||||
|
* @param {Coin} coin
|
||||||
|
* @returns {CoinEntry}
|
||||||
|
*/
|
||||||
|
|
||||||
|
CoinEntry.fromCoin = function fromCoin(coin) {
|
||||||
|
var entry = new CoinEntry();
|
||||||
|
var output = new Output();
|
||||||
|
output.value = coin.value;
|
||||||
|
output.script = coin.script;
|
||||||
|
entry.output = output;
|
||||||
|
return entry;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -26,12 +26,22 @@ function CoinView() {
|
|||||||
this.undo = new UndoCoins();
|
this.undo = new UndoCoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get coins.
|
||||||
|
* @param {Hash} hash
|
||||||
|
* @returns {Coins} coins
|
||||||
|
*/
|
||||||
|
|
||||||
|
CoinView.prototype.get = function get(hash) {
|
||||||
|
return this.unspent[hash];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add coins to the collection.
|
* Add coins to the collection.
|
||||||
* @param {Coins} coins
|
* @param {Coins} coins
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addCoins = function addCoins(coins) {
|
CoinView.prototype.add = function add(coins) {
|
||||||
this.unspent[coins.hash] = coins;
|
this.unspent[coins.hash] = coins;
|
||||||
return coins;
|
return coins;
|
||||||
};
|
};
|
||||||
@ -39,76 +49,24 @@ CoinView.prototype.addCoins = function addCoins(coins) {
|
|||||||
/**
|
/**
|
||||||
* Add a tx to the collection.
|
* Add a tx to the collection.
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
|
* @param {Number} height
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addTX = function addTX(tx, height) {
|
CoinView.prototype.addTX = function addTX(tx, height) {
|
||||||
var coins = Coins.fromTX(tx, height);
|
var coins = Coins.fromTX(tx, height);
|
||||||
return this.addCoins(coins);
|
return this.add(coins);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a tx from the collection.
|
* Remove a tx from the collection.
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
|
* @param {Number} height
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.removeTX = function removeTX(tx, height) {
|
CoinView.prototype.removeTX = function removeTX(tx, height) {
|
||||||
var coins = Coins.fromTX(tx, height);
|
var coins = Coins.fromTX(tx, height);
|
||||||
coins.outputs.length = 0;
|
coins.outputs.length = 0;
|
||||||
return this.addCoins(coins);
|
return this.add(coins);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a coin.
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @param {Number} index
|
|
||||||
* @returns {Coin}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CoinView.prototype.get = function get(hash, index) {
|
|
||||||
var coins = this.unspent[hash];
|
|
||||||
var entry;
|
|
||||||
|
|
||||||
if (!coins)
|
|
||||||
return;
|
|
||||||
|
|
||||||
entry = coins.get(index);
|
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
return;
|
|
||||||
|
|
||||||
return entry.toCoin(coins, index);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the collection has a coin.
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @param {Number} index
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CoinView.prototype.has = function has(hash, index) {
|
|
||||||
var coins = this.unspent[hash];
|
|
||||||
|
|
||||||
if (!coins)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return coins.has(index);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a coin and return it.
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @param {Number} index
|
|
||||||
* @returns {Coin}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CoinView.prototype.spend = function spend(hash, index) {
|
|
||||||
var coins = this.unspent[hash];
|
|
||||||
|
|
||||||
if (!coins)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return this.spendFrom(coins, index);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,31 +116,6 @@ CoinView.prototype.getCoins = co(function* getCoins(db, hash) {
|
|||||||
return coins;
|
return coins;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether all inputs are available.
|
|
||||||
* @param {ChainDB} db
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Boolean} True if all inputs are available.
|
|
||||||
*/
|
|
||||||
|
|
||||||
CoinView.prototype.hasInputs = co(function* hasInputs(db, tx) {
|
|
||||||
var i, input, prevout, coins;
|
|
||||||
|
|
||||||
for (i = 0; i < tx.inputs.length; i++) {
|
|
||||||
input = tx.inputs[i];
|
|
||||||
prevout = input.prevout;
|
|
||||||
coins = yield this.getCoins(db, prevout.hash);
|
|
||||||
|
|
||||||
if (!coins)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!coins.has(prevout.index))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all input coins into unspent map.
|
* Read all input coins into unspent map.
|
||||||
* @param {ChainDB} db
|
* @param {ChainDB} db
|
||||||
@ -198,28 +131,6 @@ CoinView.prototype.ensureInputs = co(function* ensureInputs(db, tx) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Spend coins for transaction.
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
CoinView.prototype.spendCoins = function spendCoins(tx) {
|
|
||||||
var i, input, prevout;
|
|
||||||
|
|
||||||
for (i = 0; i < tx.inputs.length; i++) {
|
|
||||||
input = tx.inputs[i];
|
|
||||||
prevout = input.prevout;
|
|
||||||
|
|
||||||
input.coin = this.spend(prevout.hash, prevout.index);
|
|
||||||
|
|
||||||
if (!input.coin)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spend coins for transaction.
|
* Spend coins for transaction.
|
||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
|
|||||||
@ -148,7 +148,7 @@ UndoCoins.prototype.apply = function apply(view, outpoint) {
|
|||||||
assert(coins);
|
assert(coins);
|
||||||
}
|
}
|
||||||
|
|
||||||
coins.add(index, undo.toOutput());
|
coins.addOutput(index, undo.toOutput());
|
||||||
|
|
||||||
assert(coins.has(index));
|
assert(coins.has(index));
|
||||||
|
|
||||||
|
|||||||
@ -1574,6 +1574,32 @@ Mempool.prototype.fillAllCoins = co(function* fillAllCoins(tx) {
|
|||||||
return found;
|
return found;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get coin viewpoint.
|
||||||
|
* @param {TX} tx
|
||||||
|
* @returns {Promise} - Returns {@link CoinView}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Mempool.prototype.getCoinView = co(function* getCoinView(tx) {
|
||||||
|
var view = yield this.chain.db.getCoinView(tx);
|
||||||
|
var entries = view.toArray();
|
||||||
|
var i, coins, entry;
|
||||||
|
|
||||||
|
for (i = 0; i < entries.length; i++) {
|
||||||
|
coins = entries[i];
|
||||||
|
|
||||||
|
if (!coins.isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entry = this.getEntry(coins.hash);
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
view.addTX(entry.tx, entry.height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a snapshot of all transaction hashes in the mempool. Used
|
* Get a snapshot of all transaction hashes in the mempool. Used
|
||||||
* for generating INV packets in response to MEMPOOL packets.
|
* for generating INV packets in response to MEMPOOL packets.
|
||||||
|
|||||||
@ -152,7 +152,7 @@ var reserializeCoins = co(function* reserializeCoins() {
|
|||||||
output.value = coin.value;
|
output.value = coin.value;
|
||||||
|
|
||||||
if (!output.script.isUnspendable())
|
if (!output.script.isUnspendable())
|
||||||
coins.add(coin.index, output);
|
coins.addOutput(coin.index, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
coins.cleanup();
|
coins.cleanup();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user