txdb: add block entries.
This commit is contained in:
parent
704d9e1783
commit
86e1e35f9a
9
bin/cli
9
bin/cli
@ -320,6 +320,12 @@ CLI.prototype.getDetails = co(function* getDetails() {
|
||||
this.log(details);
|
||||
});
|
||||
|
||||
CLI.prototype.getWalletBlock = co(function* getWalletBlock() {
|
||||
var height = this.argv[0] | 0;
|
||||
var details = yield this.wallet.getBlock(height);
|
||||
this.log(details);
|
||||
});
|
||||
|
||||
CLI.prototype.retoken = co(function* retoken() {
|
||||
var result = yield this.wallet.retoken();
|
||||
this.log(result);
|
||||
@ -480,6 +486,8 @@ CLI.prototype.handleWallet = co(function* handleWallet() {
|
||||
return yield this.zapWallet();
|
||||
case 'tx':
|
||||
return yield this.getDetails();
|
||||
case 'block':
|
||||
return yield this.getWalletBlock();
|
||||
case 'view':
|
||||
return yield this.viewTX();
|
||||
case 'import':
|
||||
@ -518,6 +526,7 @@ CLI.prototype.handleWallet = co(function* handleWallet() {
|
||||
this.log(' $ sign [tx-hex]: Sign transaction.');
|
||||
this.log(' $ zap [age?]: Zap pending wallet TXs.');
|
||||
this.log(' $ tx [hash]: View transaction details.');
|
||||
this.log(' $ block [height]: View wallet block.');
|
||||
this.log(' $ view [tx-hex]: Parse and view transaction.');
|
||||
this.log(' $ import [wif|hex]: Import private or public key.');
|
||||
this.log(' $ watch [address]: Import an address.');
|
||||
|
||||
@ -433,7 +433,7 @@ HTTPClient.prototype.none = function none() {
|
||||
* Request the raw wallet JSON (will create wallet if it does not exist).
|
||||
* @private
|
||||
* @param {Object} options - See {@link Wallet}.
|
||||
* @returns {Promise} - Returns Object.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createWallet = function createWallet(options) {
|
||||
@ -444,7 +444,7 @@ HTTPClient.prototype.createWallet = function createWallet(options) {
|
||||
* Get the raw wallet JSON.
|
||||
* @private
|
||||
* @param {WalletID} id
|
||||
* @returns {Promise} - Returns Object.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWallet = function getWallet(id) {
|
||||
@ -454,7 +454,7 @@ HTTPClient.prototype.getWallet = function getWallet(id) {
|
||||
/**
|
||||
* Get wallet transaction history.
|
||||
* @param {WalletID} id
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getHistory = function getHistory(id, account) {
|
||||
@ -465,7 +465,7 @@ HTTPClient.prototype.getHistory = function getHistory(id, account) {
|
||||
/**
|
||||
* Get wallet coins.
|
||||
* @param {WalletID} id
|
||||
* @returns {Promise} - Returns {@link Coin}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getCoins = function getCoins(id, account) {
|
||||
@ -476,7 +476,7 @@ HTTPClient.prototype.getCoins = function getCoins(id, account) {
|
||||
/**
|
||||
* Get all unconfirmed transactions.
|
||||
* @param {WalletID} id
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getPending = function getPending(id, account) {
|
||||
@ -487,7 +487,7 @@ HTTPClient.prototype.getPending = function getPending(id, account) {
|
||||
/**
|
||||
* Calculate wallet balance.
|
||||
* @param {WalletID} id
|
||||
* @returns {Promise} - Returns {@link Balance}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getBalance = function getBalance(id, account) {
|
||||
@ -499,7 +499,7 @@ HTTPClient.prototype.getBalance = function getBalance(id, account) {
|
||||
* Get last N wallet transactions.
|
||||
* @param {WalletID} id
|
||||
* @param {Number} limit - Max number of transactions.
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getLast = function getLast(id, account, limit) {
|
||||
@ -515,7 +515,7 @@ HTTPClient.prototype.getLast = function getLast(id, account, limit) {
|
||||
* @param {Number} options.end - End time.
|
||||
* @param {Number?} options.limit - Max number of records.
|
||||
* @param {Boolean?} options.reverse - Reverse order.
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getRange = function getRange(id, account, options) {
|
||||
@ -534,20 +534,31 @@ HTTPClient.prototype.getRange = function getRange(id, account, options) {
|
||||
* is available in the wallet history).
|
||||
* @param {WalletID} id
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise} - Returns {@link TX}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWalletTX = function getWalletTX(id, hash) {
|
||||
return this._get('/wallet/' + id + '/tx/' + hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get wallet block.
|
||||
* @param {WalletID} id
|
||||
* @param {Number} height
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWalletBlock = function getWalletBlock(id, height) {
|
||||
return this._get('/wallet/' + id + '/block/' + height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get unspent coin (only possible if the transaction
|
||||
* is available in the wallet history).
|
||||
* @param {WalletID} id
|
||||
* @param {Hash} hash
|
||||
* @param {Number} index
|
||||
* @returns {Promise} - Returns {@link Coin}[].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.getWalletCoin = function getWalletCoin(id, account, hash, index) {
|
||||
@ -562,7 +573,7 @@ HTTPClient.prototype.getWalletCoin = function getWalletCoin(id, account, hash, i
|
||||
* @param {Object} options
|
||||
* @param {Base58Address} options.address
|
||||
* @param {Amount} options.value
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.send = function send(id, options) {
|
||||
@ -611,7 +622,7 @@ HTTPClient.prototype.setPassphrase = function setPassphrase(id, old, new_) {
|
||||
* Create a transaction, fill.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createTX = function createTX(id, options) {
|
||||
@ -636,7 +647,7 @@ HTTPClient.prototype.createTX = function createTX(id, options) {
|
||||
* @param {WalletID} id
|
||||
* @param {TX} tx
|
||||
* @param {Object} options
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.sign = function sign(id, tx, options) {
|
||||
@ -654,7 +665,7 @@ HTTPClient.prototype.sign = function sign(id, tx, options) {
|
||||
/**
|
||||
* Fill a transaction with coins.
|
||||
* @param {TX} tx
|
||||
* @returns {Promise} - Returns {@link TX}.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.fillCoins = function fillCoins(id, tx) {
|
||||
@ -895,7 +906,7 @@ HTTPClient.prototype.createAccount = function createAccount(id, options) {
|
||||
* Create address.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @returns {Promise} - Returns Array.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createAddress = function createAddress(id, options) {
|
||||
@ -916,7 +927,7 @@ HTTPClient.prototype.createAddress = function createAddress(id, options) {
|
||||
* Create address.
|
||||
* @param {WalletID} id
|
||||
* @param {Object} options
|
||||
* @returns {Promise} - Returns Array.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.createNested = function createNested(id, options) {
|
||||
|
||||
@ -917,6 +917,21 @@ HTTPServer.prototype._init = function _init() {
|
||||
send(200, { success: true });
|
||||
}));
|
||||
|
||||
// Get Block Record
|
||||
this.get('/wallet/:id/block/:height', con(function* (req, res, send, next) {
|
||||
var height = req.options.height;
|
||||
var block;
|
||||
|
||||
enforce(height != null, 'Height is required.');
|
||||
|
||||
block = yield req.wallet.getBlock(height);
|
||||
|
||||
if (!block)
|
||||
return send(404);
|
||||
|
||||
send(200, block.toJSON());
|
||||
}));
|
||||
|
||||
// Add key
|
||||
this.put('/wallet/:id/shared-key', con(function* (req, res, send, next) {
|
||||
var options = req.options;
|
||||
|
||||
@ -198,6 +198,14 @@ HTTPWallet.prototype.getTX = function getTX(hash) {
|
||||
return this.client.getWalletTX(this.id, hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getBlock
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.getBlock = function getBlock(height) {
|
||||
return this.client.getWalletBlock(this.id, height);
|
||||
};
|
||||
|
||||
/**
|
||||
* @see Wallet#getCoin
|
||||
*/
|
||||
|
||||
@ -981,37 +981,38 @@ TXDB.prototype.removeBlockMap = co(function* removeBlockMap(tx, height) {
|
||||
*/
|
||||
|
||||
TXDB.prototype.getBlock = co(function* getBlock(height) {
|
||||
var data = yield this.db.get(layout.b(height));
|
||||
var data = yield this.get(layout.b(height));
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
return BlockRecord.fromRaw(data);
|
||||
});
|
||||
|
||||
/**
|
||||
* Append to the global block record.
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
* @param {BlockMeta} entry
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
TXDB.prototype.addBlock = co(function* addBlock(tx, entry) {
|
||||
var hash = tx.hash('hex');
|
||||
var block = yield this.getBlock(entry.height);
|
||||
var height = tx.height;
|
||||
var block = yield this.getBlock(height);
|
||||
|
||||
if (!block)
|
||||
block = new BlockRecord(entry.hash, entry.height, entry.ts);
|
||||
block = new BlockRecord(tx.block, tx.height, tx.ts);
|
||||
|
||||
if (block.hashes.indexOf(hash) !== -1)
|
||||
if (!block.add(hash))
|
||||
return;
|
||||
|
||||
block.hashes.push(hash);
|
||||
|
||||
this.put(layout.b(entry.height), block.toRaw());
|
||||
this.put(layout.b(height), block.toRaw());
|
||||
});
|
||||
|
||||
/**
|
||||
* Remove from the global block record.
|
||||
* @param {TX}
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -1019,18 +1020,13 @@ TXDB.prototype.addBlock = co(function* addBlock(tx, entry) {
|
||||
TXDB.prototype.removeBlock = co(function* removeBlock(tx, height) {
|
||||
var hash = tx.hash('hex');
|
||||
var block = yield this.getBlock(height);
|
||||
var index;
|
||||
|
||||
if (!block)
|
||||
return;
|
||||
|
||||
index = block.hashes.indexOf(hash);
|
||||
|
||||
if (index === -1)
|
||||
if (!block.remove(hash))
|
||||
return;
|
||||
|
||||
block.hashes.splice(index, 1);
|
||||
|
||||
if (block.hashes.length === 0) {
|
||||
this.del(layout.b(height));
|
||||
return;
|
||||
@ -1043,6 +1039,7 @@ TXDB.prototype.removeBlock = co(function* removeBlock(tx, height) {
|
||||
* Add transaction, potentially runs
|
||||
* `confirm()` and `removeConflicts()`.
|
||||
* @param {TX} tx
|
||||
* @param {BlockMeta} block
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
@ -1127,6 +1124,7 @@ TXDB.prototype._add = co(function* add(tx, block) {
|
||||
* Insert transaction.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {BlockMeta} block
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
@ -1267,8 +1265,10 @@ TXDB.prototype.insert = co(function* insert(tx, block) {
|
||||
this.put(layout.H(account, tx.height, hash), DUMMY);
|
||||
}
|
||||
|
||||
if (tx.height !== -1)
|
||||
if (tx.height !== -1) {
|
||||
yield this.addBlockMap(tx, tx.height);
|
||||
yield this.addBlock(tx, block);
|
||||
}
|
||||
|
||||
// Update the transaction counter and
|
||||
// commit the new state. This state will
|
||||
@ -1296,6 +1296,7 @@ TXDB.prototype.insert = co(function* insert(tx, block) {
|
||||
* Attempt to confirm a transaction.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {BlockMeta} block
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
@ -1333,6 +1334,7 @@ TXDB.prototype.confirm = co(function* confirm(hash, block) {
|
||||
* Attempt to confirm a transaction.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {BlockMeta} block
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
@ -1437,8 +1439,10 @@ TXDB.prototype._confirm = co(function* confirm(tx, block) {
|
||||
this.put(layout.H(account, tx.height, hash), DUMMY);
|
||||
}
|
||||
|
||||
if (tx.height !== -1)
|
||||
if (tx.height !== -1) {
|
||||
yield this.addBlockMap(tx, tx.height);
|
||||
yield this.addBlock(tx, block);
|
||||
}
|
||||
|
||||
// Commit the new state. The balance has updated.
|
||||
this.put(layout.R, this.pending.commit());
|
||||
@ -1567,8 +1571,10 @@ TXDB.prototype.erase = co(function* erase(tx) {
|
||||
this.del(layout.H(account, tx.height, hash));
|
||||
}
|
||||
|
||||
if (tx.height !== -1)
|
||||
if (tx.height !== -1) {
|
||||
yield this.removeBlockMap(tx, tx.height);
|
||||
yield this.removeBlock(tx, tx.height);
|
||||
}
|
||||
|
||||
// Update the transaction counter
|
||||
// and commit new state due to
|
||||
@ -1740,6 +1746,7 @@ TXDB.prototype.disconnect = co(function* disconnect(tx) {
|
||||
}
|
||||
|
||||
yield this.removeBlockMap(tx, height);
|
||||
yield this.removeBlock(tx, height);
|
||||
|
||||
// We need to update the now-removed
|
||||
// block properties and reindex due
|
||||
@ -3359,8 +3366,54 @@ function BlockRecord(hash, height, ts) {
|
||||
this.height = height != null ? height : -1;
|
||||
this.ts = ts || 0;
|
||||
this.hashes = [];
|
||||
this.index = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add transaction to block record.
|
||||
* @param {Hash} hash
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
BlockRecord.prototype.add = function add(hash) {
|
||||
if (this.index[hash])
|
||||
return false;
|
||||
|
||||
this.index[hash] = true;
|
||||
this.hashes.push(hash);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove transaction from block record.
|
||||
* @param {Hash} hash
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
BlockRecord.prototype.remove = function remove(hash) {
|
||||
var index;
|
||||
|
||||
if (!this.index[hash])
|
||||
return false;
|
||||
|
||||
delete this.index[hash];
|
||||
|
||||
// Fast case
|
||||
if (this.hashes[this.hashes.length - 1] === hash) {
|
||||
this.hashes.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
index = this.hashes.indexOf(hash);
|
||||
|
||||
assert(index !== -1);
|
||||
|
||||
this.hashes.splice(index, 1);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate wallet block from serialized tip data.
|
||||
* @private
|
||||
@ -3369,12 +3422,17 @@ function BlockRecord(hash, height, ts) {
|
||||
|
||||
BlockRecord.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
var hash;
|
||||
|
||||
this.hash = p.readHash('hex');
|
||||
this.height = p.readU32();
|
||||
this.ts = p.readU32();
|
||||
|
||||
while (p.left())
|
||||
this.hashes.push(p.readHash('hex'));
|
||||
while (p.left()) {
|
||||
hash = p.readHash('hex');
|
||||
this.index[hash] = true;
|
||||
this.hashes.push(hash);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -1984,6 +1984,16 @@ Wallet.prototype.getTX = function getTX(hash) {
|
||||
return this.txdb.getTX(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a block from the wallet.
|
||||
* @param {Number} height
|
||||
* @returns {Promise} - Returns {@link BlockRecord}.
|
||||
*/
|
||||
|
||||
Wallet.prototype.getBlock = function getBlock(height) {
|
||||
return this.txdb.getBlock(height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a transaction to the wallets TX history.
|
||||
* @param {TX} tx
|
||||
|
||||
@ -476,7 +476,7 @@ WalletDB.prototype.wipe = co(function* wipe() {
|
||||
this.logger.warning('Wiping WalletDB TXDB...');
|
||||
this.logger.warning('I hope you know what you\'re doing.');
|
||||
|
||||
iter = db.iterator({
|
||||
iter = this.db.iterator({
|
||||
gte: new Buffer([0x00]),
|
||||
lte: new Buffer([0xff])
|
||||
});
|
||||
@ -2002,15 +2002,15 @@ WalletDB.prototype.addTX = co(function* addTX(tx) {
|
||||
block = yield this.getBlock(tx.height);
|
||||
|
||||
if (!block)
|
||||
throw new Error('WDB: Inserting confirmed transaction.');
|
||||
throw new Error('WDB: Cannot insert tx from unknown chain.');
|
||||
|
||||
if (tx.block !== block.hash)
|
||||
throw new Error('WDB: Inserting confirmed transaction.');
|
||||
throw new Error('WDB: Cannot insert tx from alternate chain.');
|
||||
|
||||
this.logger.warning('WalletDB is inserting confirmed transaction.');
|
||||
}
|
||||
|
||||
return yield this._insert(tx);
|
||||
return yield this._insert(tx, block);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user