walletdb: cleanup.
This commit is contained in:
parent
3a89e627b8
commit
60575c0ea0
9
bin/cli
9
bin/cli
@ -323,12 +323,6 @@ CLI.prototype.resendWallet = co(function* resendWallet() {
|
|||||||
this.log('Resending...');
|
this.log('Resending...');
|
||||||
});
|
});
|
||||||
|
|
||||||
CLI.prototype.zap = co(function* zap() {
|
|
||||||
var age = +this.argv[0] || 72 * 3600;
|
|
||||||
yield this.client.zap(age);
|
|
||||||
this.log('Zapped.');
|
|
||||||
});
|
|
||||||
|
|
||||||
CLI.prototype.backup = co(function* backup() {
|
CLI.prototype.backup = co(function* backup() {
|
||||||
var path = this.argv[0];
|
var path = this.argv[0];
|
||||||
|
|
||||||
@ -529,8 +523,6 @@ CLI.prototype.handleNode = co(function* handleNode() {
|
|||||||
return yield this.rescan();
|
return yield this.rescan();
|
||||||
case 'resend':
|
case 'resend':
|
||||||
return yield this.resend();
|
return yield this.resend();
|
||||||
case 'zap':
|
|
||||||
return yield this.zap();
|
|
||||||
case 'backup':
|
case 'backup':
|
||||||
return yield this.backup();
|
return yield this.backup();
|
||||||
case 'rpc':
|
case 'rpc':
|
||||||
@ -547,7 +539,6 @@ CLI.prototype.handleNode = co(function* handleNode() {
|
|||||||
this.log(' $ block [hash/height]: View block.');
|
this.log(' $ block [hash/height]: View block.');
|
||||||
this.log(' $ rescan [height/hash]: Rescan for transactions.');
|
this.log(' $ rescan [height/hash]: Rescan for transactions.');
|
||||||
this.log(' $ resend: Resend pending transactions.');
|
this.log(' $ resend: Resend pending transactions.');
|
||||||
this.log(' $ zap [age?]: Zap stale transactions from walletdb.');
|
|
||||||
this.log(' $ backup [path]: Backup the wallet db.');
|
this.log(' $ backup [path]: Backup the wallet db.');
|
||||||
this.log(' $ rpc [command] [args]: Execute RPC command.');
|
this.log(' $ rpc [command] [args]: Execute RPC command.');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -362,17 +362,6 @@ HTTPClient.prototype.resend = function resend() {
|
|||||||
return this._post('/resend', {});
|
return this._post('/resend', {});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Zap stale transactions.
|
|
||||||
* @param {Number} age
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
HTTPClient.prototype.zap = function zap(age) {
|
|
||||||
var options = { age: age };
|
|
||||||
return this._post('/zap', options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Backup the walletdb.
|
* Backup the walletdb.
|
||||||
* @param {String} path
|
* @param {String} path
|
||||||
|
|||||||
@ -740,18 +740,6 @@ HTTPServer.prototype._init = function _init() {
|
|||||||
send(200, { success: true });
|
send(200, { success: true });
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Zap
|
|
||||||
this.post('/zap', con(function* (req, res, send, next) {
|
|
||||||
var options = req.options;
|
|
||||||
var age = options.age;
|
|
||||||
|
|
||||||
enforce(age != null, 'Age is required.');
|
|
||||||
|
|
||||||
yield this.walletdb.zap(age);
|
|
||||||
|
|
||||||
send(200, { success: true });
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Backup WalletDB
|
// Backup WalletDB
|
||||||
this.post('/backup', con(function* (req, res, send, next) {
|
this.post('/backup', con(function* (req, res, send, next) {
|
||||||
var options = req.options;
|
var options = req.options;
|
||||||
|
|||||||
@ -45,11 +45,8 @@ layout.walletdb = {
|
|||||||
return [+key.slice(1, 11), key.slice(11)];
|
return [+key.slice(1, 11), key.slice(11)];
|
||||||
},
|
},
|
||||||
R: 'R',
|
R: 'R',
|
||||||
c: function c(height) {
|
h: function c(height) {
|
||||||
return 'c' + pad32(height);
|
return 'h' + pad32(height);
|
||||||
},
|
|
||||||
cc: function cc(key) {
|
|
||||||
return +key.slice(1);
|
|
||||||
},
|
},
|
||||||
b: function b(height) {
|
b: function b(height) {
|
||||||
return 'b' + pad32(height);
|
return 'b' + pad32(height);
|
||||||
@ -57,12 +54,6 @@ layout.walletdb = {
|
|||||||
bb: function bb(key) {
|
bb: function bb(key) {
|
||||||
return +key.slice(1);
|
return +key.slice(1);
|
||||||
},
|
},
|
||||||
e: function e(hash) {
|
|
||||||
return 'e' + hash;
|
|
||||||
},
|
|
||||||
ee: function ee(key) {
|
|
||||||
return key.slice(1);
|
|
||||||
},
|
|
||||||
o: function o(hash) {
|
o: function o(hash) {
|
||||||
return 'o' + hash + pad32(index);
|
return 'o' + hash + pad32(index);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -362,19 +362,6 @@ TXMapRecord.prototype.remove = function remove(wid) {
|
|||||||
return utils.binaryRemove(this.wids, wid, cmp);
|
return utils.binaryRemove(this.wids, wid, cmp);
|
||||||
};
|
};
|
||||||
|
|
||||||
TXMapRecord.prototype.toRaw = function toRaw() {
|
|
||||||
return serializeWallets(this.wids);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXMapRecord.prototype.fromRaw = function fromRaw(data) {
|
|
||||||
this.wids = parseWallets(data);
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
TXMapRecord.fromRaw = function fromRaw(hash, data) {
|
|
||||||
return new TXMapRecord(hash).fromRaw(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outpoint Map
|
* Outpoint Map
|
||||||
* @constructor
|
* @constructor
|
||||||
|
|||||||
@ -19,7 +19,6 @@ var Coin = require('../primitives/coin');
|
|||||||
var Outpoint = require('../primitives/outpoint');
|
var Outpoint = require('../primitives/outpoint');
|
||||||
var records = require('./records');
|
var records = require('./records');
|
||||||
var BlockMapRecord = records.BlockMapRecord;
|
var BlockMapRecord = records.BlockMapRecord;
|
||||||
var TXMapRecord = records.TXMapRecord;
|
|
||||||
var OutpointMapRecord = records.OutpointMapRecord;
|
var OutpointMapRecord = records.OutpointMapRecord;
|
||||||
var DUMMY = new Buffer([0]);
|
var DUMMY = new Buffer([0]);
|
||||||
|
|
||||||
@ -887,49 +886,6 @@ TXDB.prototype.isSpent = function isSpent(hash, index) {
|
|||||||
return this.has(layout.s(hash, index));
|
return this.has(layout.s(hash, index));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Append to the global tx record.
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
TXDB.prototype.addTXMap = co(function* addTXMap(tx) {
|
|
||||||
var hash = tx.hash('hex');
|
|
||||||
var map = yield this.walletdb.getTXMap(hash);
|
|
||||||
|
|
||||||
if (!map)
|
|
||||||
map = new TXMapRecord(hash);
|
|
||||||
|
|
||||||
if (!map.add(this.wallet.wid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.walletdb.writeTXMap(this.wallet, hash, map);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove from the global tx record.
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
TXDB.prototype.removeTXMap = co(function* removeTXMap(tx) {
|
|
||||||
var hash = tx.hash('hex');
|
|
||||||
var map = yield this.walletdb.getTXMap(hash);
|
|
||||||
|
|
||||||
if (!map)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!map.remove(this.wallet.wid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (map.wids.length === 0) {
|
|
||||||
this.walletdb.unwriteTXMap(this.wallet, hash);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.walletdb.writeTXMap(this.wallet, hash, map);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append to the global unspent record.
|
* Append to the global unspent record.
|
||||||
* @param {Hash} hash
|
* @param {Hash} hash
|
||||||
@ -1311,8 +1267,6 @@ TXDB.prototype.insert = co(function* insert(tx, block) {
|
|||||||
this.put(layout.H(account, tx.height, hash), DUMMY);
|
this.put(layout.H(account, tx.height, hash), DUMMY);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield this.addTXMap(tx);
|
|
||||||
|
|
||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
yield this.addBlockMap(tx, tx.height);
|
yield this.addBlockMap(tx, tx.height);
|
||||||
|
|
||||||
@ -1483,8 +1437,6 @@ TXDB.prototype._confirm = co(function* confirm(tx, block) {
|
|||||||
this.put(layout.H(account, tx.height, hash), DUMMY);
|
this.put(layout.H(account, tx.height, hash), DUMMY);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield this.addTXMap(tx);
|
|
||||||
|
|
||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
yield this.addBlockMap(tx, tx.height);
|
yield this.addBlockMap(tx, tx.height);
|
||||||
|
|
||||||
@ -1615,8 +1567,6 @@ TXDB.prototype.erase = co(function* erase(tx) {
|
|||||||
this.del(layout.H(account, tx.height, hash));
|
this.del(layout.H(account, tx.height, hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
yield this.removeTXMap(tx);
|
|
||||||
|
|
||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
yield this.removeBlockMap(tx, tx.height);
|
yield this.removeBlockMap(tx, tx.height);
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,6 @@ var ChainState = records.ChainState;
|
|||||||
var BlockMapRecord = records.BlockMapRecord;
|
var BlockMapRecord = records.BlockMapRecord;
|
||||||
var BlockMeta = records.BlockMeta;
|
var BlockMeta = records.BlockMeta;
|
||||||
var PathMapRecord = records.PathMapRecord;
|
var PathMapRecord = records.PathMapRecord;
|
||||||
var TXMapRecord = records.TXMapRecord;
|
|
||||||
var OutpointMapRecord = records.OutpointMapRecord;
|
var OutpointMapRecord = records.OutpointMapRecord;
|
||||||
var TXDB = require('./txdb');
|
var TXDB = require('./txdb');
|
||||||
var U32 = utils.U32;
|
var U32 = utils.U32;
|
||||||
@ -43,10 +42,10 @@ var U32 = utils.U32;
|
|||||||
* a[wid][index] -> account
|
* a[wid][index] -> account
|
||||||
* i[wid][name] -> account index
|
* i[wid][name] -> account index
|
||||||
* t[wid]* -> txdb
|
* t[wid]* -> txdb
|
||||||
* R -> tip height
|
* R -> chain sync state
|
||||||
* c[height] -> chain header
|
* h[height] -> recent block hash
|
||||||
* b[height] -> block->wid map
|
* b[height] -> block->wid map
|
||||||
* e[hash] -> tx->wid map
|
* o[hash][index] -> outpoint->wid map
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var layout = {
|
var layout = {
|
||||||
@ -109,15 +108,12 @@ var layout = {
|
|||||||
return [key.readUInt32BE(1, true), key.toString('ascii', 5)];
|
return [key.readUInt32BE(1, true), key.toString('ascii', 5)];
|
||||||
},
|
},
|
||||||
R: new Buffer([0x52]),
|
R: new Buffer([0x52]),
|
||||||
c: function c(height) {
|
h: function h(height) {
|
||||||
var key = new Buffer(5);
|
var key = new Buffer(5);
|
||||||
key[0] = 0x63;
|
key[0] = 0x68;
|
||||||
key.writeUInt32BE(height, 1, true);
|
key.writeUInt32BE(height, 1, true);
|
||||||
return key;
|
return key;
|
||||||
},
|
},
|
||||||
cc: function cc(key) {
|
|
||||||
return key.readUInt32BE(1, true);
|
|
||||||
},
|
|
||||||
b: function b(height) {
|
b: function b(height) {
|
||||||
var key = new Buffer(5);
|
var key = new Buffer(5);
|
||||||
key[0] = 0x62;
|
key[0] = 0x62;
|
||||||
@ -127,18 +123,9 @@ var layout = {
|
|||||||
bb: function bb(key) {
|
bb: function bb(key) {
|
||||||
return key.readUInt32BE(1, true);
|
return key.readUInt32BE(1, true);
|
||||||
},
|
},
|
||||||
e: function e(hash) {
|
|
||||||
var key = new Buffer(33);
|
|
||||||
key[0] = 0x65;
|
|
||||||
key.write(hash, 1, 'hex');
|
|
||||||
return key;
|
|
||||||
},
|
|
||||||
ee: function ee(key) {
|
|
||||||
return key.toString('hex', 1);
|
|
||||||
},
|
|
||||||
o: function o(hash, index) {
|
o: function o(hash, index) {
|
||||||
var key = new Buffer(37);
|
var key = new Buffer(37);
|
||||||
key[0] = 0x01;
|
key[0] = 0x6f;
|
||||||
key.write(hash, 1, 'hex');
|
key.write(hash, 1, 'hex');
|
||||||
key.writeUInt32BE(index, 33, true);
|
key.writeUInt32BE(index, 33, true);
|
||||||
return key;
|
return key;
|
||||||
@ -266,17 +253,30 @@ WalletDB.prototype._close = co(function* close() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect and sync with the chain server (without a lock).
|
* Watch addresses and outpoints.
|
||||||
* @private
|
* @private
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.watch = co(function* watch() {
|
WalletDB.prototype.watch = co(function* watch() {
|
||||||
var data = yield this.getFilterData();
|
var hashes = yield this.getHashes();
|
||||||
|
var outpoints = yield this.getOutpoints();
|
||||||
|
var chunks = [];
|
||||||
|
var i, hash, outpoint;
|
||||||
|
|
||||||
this.logger.info('Adding %d hashes to WalletDB filter.', data.length);
|
for (i = 0; i < hashes.length; i++) {
|
||||||
|
hash = hashes[i];
|
||||||
|
chunks.push(hash);
|
||||||
|
}
|
||||||
|
|
||||||
this.addFilter(data);
|
for (i = 0; i < outpoints.length; i++) {
|
||||||
|
outpoint = outpoints[i];
|
||||||
|
chunks.push(outpoint.toRaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.info('Adding %d chunks to WalletDB filter.', chunks.length);
|
||||||
|
|
||||||
|
this.addFilter(chunks);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,6 +460,7 @@ WalletDB.prototype.wipe = co(function* wipe() {
|
|||||||
this.logger.warning('Wiping WalletDB TXDB...');
|
this.logger.warning('Wiping WalletDB TXDB...');
|
||||||
this.logger.warning('I hope you know what you\'re doing.');
|
this.logger.warning('I hope you know what you\'re doing.');
|
||||||
|
|
||||||
|
// All TXDB records
|
||||||
keys = yield this.db.keys({
|
keys = yield this.db.keys({
|
||||||
gte: TXDB.layout.prefix(0x00000000, dummy),
|
gte: TXDB.layout.prefix(0x00000000, dummy),
|
||||||
lte: TXDB.layout.prefix(0xffffffff, dummy)
|
lte: TXDB.layout.prefix(0xffffffff, dummy)
|
||||||
@ -470,6 +471,62 @@ WalletDB.prototype.wipe = co(function* wipe() {
|
|||||||
batch.del(key);
|
batch.del(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All recent block hashes
|
||||||
|
keys = yield this.db.keys({
|
||||||
|
gte: layout.h(0),
|
||||||
|
lte: layout.h(0xffffffff)
|
||||||
|
});
|
||||||
|
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
key = keys[i];
|
||||||
|
batch.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The state record
|
||||||
|
batch.del(layout.R);
|
||||||
|
|
||||||
|
// All block maps
|
||||||
|
keys = yield this.db.keys({
|
||||||
|
gte: layout.b(0),
|
||||||
|
lte: layout.b(0xffffffff)
|
||||||
|
});
|
||||||
|
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
key = keys[i];
|
||||||
|
batch.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All outpoint maps
|
||||||
|
keys = yield this.db.keys({
|
||||||
|
gte: layout.o(constants.NULL_HASH, 0),
|
||||||
|
lte: layout.o(constants.HIGH_HASH, 0xffffffff)
|
||||||
|
});
|
||||||
|
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
key = keys[i];
|
||||||
|
batch.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All TX maps (e -- old)
|
||||||
|
gte = new Buffer(33);
|
||||||
|
gte.fill(0);
|
||||||
|
gte[0] = 0x65;
|
||||||
|
|
||||||
|
lte = new Buffer(33);
|
||||||
|
lte.fill(255);
|
||||||
|
lte[0] = 0x65;
|
||||||
|
|
||||||
|
keys = yield this.db.keys({
|
||||||
|
gte: gte,
|
||||||
|
lte: lte
|
||||||
|
});
|
||||||
|
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
key = keys[i];
|
||||||
|
batch.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All block maps (b -- 32 byte old)
|
||||||
gte = new Buffer(33);
|
gte = new Buffer(33);
|
||||||
gte.fill(0);
|
gte.fill(0);
|
||||||
gte[0] = 0x62;
|
gte[0] = 0x62;
|
||||||
@ -488,9 +545,18 @@ WalletDB.prototype.wipe = co(function* wipe() {
|
|||||||
batch.del(key);
|
batch.del(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All block records (c -- old)
|
||||||
|
gte = new Buffer(33);
|
||||||
|
gte.fill(0);
|
||||||
|
gte[0] = 0x63;
|
||||||
|
|
||||||
|
lte = new Buffer(33);
|
||||||
|
lte.fill(255);
|
||||||
|
lte[0] = 0x63;
|
||||||
|
|
||||||
keys = yield this.db.keys({
|
keys = yield this.db.keys({
|
||||||
gte: layout.b(0),
|
gte: gte,
|
||||||
lte: layout.b(0xffffffff)
|
lte: lte
|
||||||
});
|
});
|
||||||
|
|
||||||
for (i = 0; i < keys.length; i++) {
|
for (i = 0; i < keys.length; i++) {
|
||||||
@ -498,28 +564,6 @@ WalletDB.prototype.wipe = co(function* wipe() {
|
|||||||
batch.del(key);
|
batch.del(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = yield this.db.keys({
|
|
||||||
gte: layout.c(0),
|
|
||||||
lte: layout.c(0xffffffff)
|
|
||||||
});
|
|
||||||
|
|
||||||
for (i = 0; i < keys.length; i++) {
|
|
||||||
key = keys[i];
|
|
||||||
batch.del(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = yield this.db.keys({
|
|
||||||
gte: layout.e(constants.NULL_HASH),
|
|
||||||
lte: layout.e(constants.HIGH_HASH)
|
|
||||||
});
|
|
||||||
|
|
||||||
for (i = 0; i < keys.length; i++) {
|
|
||||||
key = keys[i];
|
|
||||||
batch.del(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
batch.del(layout.R);
|
|
||||||
|
|
||||||
yield batch.write();
|
yield batch.write();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1201,30 +1245,6 @@ WalletDB.prototype.getOutpoints = function getOutpoints() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get hashes required for rescan filter.
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getFilterData = co(function* getFilterData() {
|
|
||||||
var chunks = [];
|
|
||||||
var hashes = yield this.getHashes();
|
|
||||||
var unspent = yield this.getOutpoints();
|
|
||||||
var i, hash, outpoint;
|
|
||||||
|
|
||||||
for (i = 0; i < hashes.length; i++) {
|
|
||||||
hash = hashes[i];
|
|
||||||
chunks.push(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < unspent.length; i++) {
|
|
||||||
outpoint = unspent[i];
|
|
||||||
chunks.push(outpoint.toRaw());
|
|
||||||
}
|
|
||||||
|
|
||||||
return chunks;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all address hashes.
|
* Get all address hashes.
|
||||||
* @param {WalletID} wid
|
* @param {WalletID} wid
|
||||||
@ -1358,7 +1378,7 @@ WalletDB.prototype.getPendingKeys = co(function* getPendingKeys() {
|
|||||||
var keys = [];
|
var keys = [];
|
||||||
var iter, item;
|
var iter, item;
|
||||||
|
|
||||||
iter = yield this.db.iterator({
|
iter = this.db.iterator({
|
||||||
gte: layout.prefix(0x00000000, dummy),
|
gte: layout.prefix(0x00000000, dummy),
|
||||||
lte: layout.prefix(0xffffffff, dummy)
|
lte: layout.prefix(0xffffffff, dummy)
|
||||||
});
|
});
|
||||||
@ -1407,34 +1427,6 @@ WalletDB.prototype.getPendingTX = co(function* getPendingTX() {
|
|||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all wallet IDs with pending txs in them.
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getPendingWallets = co(function* getPendingWallets() {
|
|
||||||
var layout = TXDB.layout;
|
|
||||||
var keys = yield this.getPendingKeys();
|
|
||||||
var uniq = {};
|
|
||||||
var result = [];
|
|
||||||
var i, key, wid;
|
|
||||||
|
|
||||||
for (i = 0; i < keys.length; i++) {
|
|
||||||
key = keys[i];
|
|
||||||
|
|
||||||
wid = layout.pre(key);
|
|
||||||
|
|
||||||
if (uniq[wid])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uniq[wid] = true;
|
|
||||||
|
|
||||||
result.push(wid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resend all pending transactions.
|
* Resend all pending transactions.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
@ -1602,8 +1594,8 @@ WalletDB.prototype.resetState = co(function* resetState(tip) {
|
|||||||
var iter, item;
|
var iter, item;
|
||||||
|
|
||||||
iter = this.db.iterator({
|
iter = this.db.iterator({
|
||||||
gte: layout.c(0),
|
gte: layout.h(0),
|
||||||
lte: layout.c(0xffffffff),
|
lte: layout.h(0xffffffff),
|
||||||
values: false
|
values: false
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1625,7 +1617,7 @@ WalletDB.prototype.resetState = co(function* resetState(tip) {
|
|||||||
state.startHash = tip.hash;
|
state.startHash = tip.hash;
|
||||||
state.height = tip.height;
|
state.height = tip.height;
|
||||||
|
|
||||||
batch.put(layout.c(tip.height), tip.toHash());
|
batch.put(layout.h(tip.height), tip.toHash());
|
||||||
batch.put(layout.R, state.toRaw());
|
batch.put(layout.R, state.toRaw());
|
||||||
|
|
||||||
yield batch.write();
|
yield batch.write();
|
||||||
@ -1654,7 +1646,7 @@ WalletDB.prototype.syncState = co(function* syncState(tip) {
|
|||||||
blocks = this.keepBlocks;
|
blocks = this.keepBlocks;
|
||||||
|
|
||||||
for (i = 0; i < blocks; i++) {
|
for (i = 0; i < blocks; i++) {
|
||||||
batch.del(layout.c(height));
|
batch.del(layout.h(height));
|
||||||
height--;
|
height--;
|
||||||
}
|
}
|
||||||
} else if (tip.height > state.height) {
|
} else if (tip.height > state.height) {
|
||||||
@ -1664,13 +1656,13 @@ WalletDB.prototype.syncState = co(function* syncState(tip) {
|
|||||||
height = tip.height - this.keepBlocks;
|
height = tip.height - this.keepBlocks;
|
||||||
|
|
||||||
if (height >= 0)
|
if (height >= 0)
|
||||||
batch.del(layout.c(height));
|
batch.del(layout.h(height));
|
||||||
}
|
}
|
||||||
|
|
||||||
state.height = tip.height;
|
state.height = tip.height;
|
||||||
|
|
||||||
// Save tip and state.
|
// Save tip and state.
|
||||||
batch.put(layout.c(tip.height), tip.toHash());
|
batch.put(layout.h(tip.height), tip.toHash());
|
||||||
batch.put(layout.R, state.toRaw());
|
batch.put(layout.R, state.toRaw());
|
||||||
|
|
||||||
yield batch.write();
|
yield batch.write();
|
||||||
@ -1702,32 +1694,6 @@ WalletDB.prototype.unwriteBlockMap = function unwriteBlockMap(wallet, height) {
|
|||||||
batch.del(layout.b(height));
|
batch.del(layout.b(height));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a transaction to global tx map.
|
|
||||||
* @param {Wallet} wallet
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @param {TXMapRecord} map
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.writeTXMap = function writeTXMap(wallet, hash, map) {
|
|
||||||
var batch = this.batch(wallet);
|
|
||||||
batch.put(layout.e(hash), map.toRaw());
|
|
||||||
this.addFilter(hash);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a transaction from global tx map.
|
|
||||||
* @param {Wallet} wallet
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.unwriteTXMap = function unwriteTXMap(wallet, hash) {
|
|
||||||
var batch = this.batch(wallet);
|
|
||||||
batch.del(layout.e(hash));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an outpoint to global unspent map.
|
* Add an outpoint to global unspent map.
|
||||||
* @param {Wallet} wallet
|
* @param {Wallet} wallet
|
||||||
@ -1739,8 +1705,10 @@ WalletDB.prototype.unwriteTXMap = function unwriteTXMap(wallet, hash) {
|
|||||||
|
|
||||||
WalletDB.prototype.writeOutpointMap = function writeOutpointMap(wallet, hash, i, map) {
|
WalletDB.prototype.writeOutpointMap = function writeOutpointMap(wallet, hash, i, map) {
|
||||||
var batch = this.batch(wallet);
|
var batch = this.batch(wallet);
|
||||||
batch.put(layout.o(hash, i), map.toRaw());
|
|
||||||
this.addFilter(new Outpoint(hash, i).toRaw());
|
this.addFilter(new Outpoint(hash, i).toRaw());
|
||||||
|
|
||||||
|
batch.put(layout.o(hash, i), map.toRaw());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1778,7 +1746,7 @@ WalletDB.prototype.getBlockMap = co(function* getBlockMap(height) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.getBlock = co(function* getBlock(height) {
|
WalletDB.prototype.getBlock = co(function* getBlock(height) {
|
||||||
var data = yield this.db.get(layout.c(height));
|
var data = yield this.db.get(layout.h(height));
|
||||||
var block;
|
var block;
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
@ -1806,21 +1774,6 @@ WalletDB.prototype.getTip = co(function* getTip() {
|
|||||||
return tip;
|
return tip;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a TX->Wallet map.
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getTXMap = co(function* getTXMap(hash) {
|
|
||||||
var data = yield this.db.get(layout.e(hash));
|
|
||||||
|
|
||||||
if (!data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
return TXMapRecord.fromRaw(hash, data);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a Unspent->Wallet map.
|
* Get a Unspent->Wallet map.
|
||||||
* @param {Hash} hash
|
* @param {Hash} hash
|
||||||
@ -1889,12 +1842,13 @@ WalletDB.prototype.rollback = co(function* rollback(height) {
|
|||||||
|
|
||||||
WalletDB.prototype.revert = co(function* revert(height) {
|
WalletDB.prototype.revert = co(function* revert(height) {
|
||||||
var total = 0;
|
var total = 0;
|
||||||
var i, iter, item, block, tx;
|
var i, iter, item, height, block, tx;
|
||||||
|
|
||||||
iter = this.db.iterator({
|
iter = this.db.iterator({
|
||||||
gte: layout.b(height + 1),
|
gte: layout.b(height + 1),
|
||||||
lte: layout.b(0xffffffff),
|
lte: layout.b(0xffffffff),
|
||||||
reverse: true
|
reverse: true,
|
||||||
|
values: true
|
||||||
});
|
});
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -1904,7 +1858,8 @@ WalletDB.prototype.revert = co(function* revert(height) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
block = BlockMapRecord.fromRaw(item.value);
|
height = layout.bb(item.key);
|
||||||
|
block = BlockMapRecord.fromRaw(height, item.value);
|
||||||
total += block.txs.length;
|
total += block.txs.length;
|
||||||
|
|
||||||
for (i = block.txs.length - 1; i >= 0; i--) {
|
for (i = block.txs.length - 1; i >= 0; i--) {
|
||||||
@ -2143,40 +2098,6 @@ WalletDB.prototype._unconfirm = co(function* unconfirm(tx) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Zap stale transactions.
|
|
||||||
* @param {Number} age
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.zap = co(function* zap(age) {
|
|
||||||
var unlock = yield this.txLock.lock();
|
|
||||||
try {
|
|
||||||
return yield this._zap(age);
|
|
||||||
} finally {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zap stale transactions without a lock.
|
|
||||||
* @private
|
|
||||||
* @param {Number} age
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype._zap = co(function* zap(age) {
|
|
||||||
var wids = yield this.getPendingWallets();
|
|
||||||
var i, wid, wallet;
|
|
||||||
|
|
||||||
for (i = 0; i < wids.length; i++) {
|
|
||||||
wid = wids[i];
|
|
||||||
wallet = yield this.get(wid);
|
|
||||||
assert(wallet);
|
|
||||||
yield wallet.zap(age);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user