walletdb: pruning.

This commit is contained in:
Christopher Jeffrey 2016-10-22 14:17:27 -07:00
parent 4128ddba36
commit debe2e4ec7
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 70 additions and 18 deletions

View File

@ -147,13 +147,10 @@ if (utils.isBrowser)
* @param {Boolean?} options.prune - Whether to prune the chain.
* @param {Boolean?} options.spv - SPV-mode, will not save block
* data, only entries.
* @param {Number?} [options.keepBlocks=288] - Number of
* blocks to keep when pruning.
* @param {String?} options.name - Database name
* @param {String?} options.location - Database location
* @param {String?} options.db - Database backend name
* @property {Boolean} prune
* @property {Number} keepBlocks
* @emits ChainDB#open
* @emits ChainDB#error
*/
@ -229,8 +226,13 @@ ChainDB.prototype._open = co(function* open() {
state = yield this.getState();
options = yield this.getOptions();
if (options)
if (options) {
// Verify the options haven't changed.
this.options.verify(options);
this.options = options;
} else {
yield this.db.put(layout.O, this.options.toRaw());
}
if (state) {
// Grab the chainstate if we have one.
@ -1575,7 +1577,7 @@ ChainDB.prototype.pruneBlock = co(function* pruneBlock(block) {
if (!this.options.prune && !this.options.spv)
return;
height = block.height - this.options.keepBlocks;
height = block.height - this.network.block.keepBlocks;
if (height <= this.network.block.pruneAfterHeight)
return;
@ -1603,7 +1605,6 @@ function ChainOptions(options) {
this.prune = false;
this.indexTX = false;
this.indexAddress = false;
this.keepBlocks = 288;
if (options)
this.fromOptions(options);
@ -1615,14 +1616,24 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) {
this.spv = options.spv;
}
if (options.witness != null) {
assert(typeof options.witness === 'boolean');
this.witness = options.witness;
}
if (options.prune != null) {
assert(typeof options.prune === 'boolean');
this.prune = options.prune;
}
if (options.keepBlocks != null) {
assert(utils.isUInt32(options.keepBlocks));
this.keepBlocks = options.keepBlocks;
if (options.indexTX != null) {
assert(typeof options.indexTX === 'boolean');
this.indexTX = options.indexTX;
}
if (options.indexAddress != null) {
assert(typeof options.indexAddress === 'boolean');
this.indexAddress = options.indexAddress;
}
return this;
@ -1662,9 +1673,6 @@ ChainOptions.prototype.verify = function verify(options) {
if (!this.indexAddress && options.indexAddress)
throw new Error('Cannot retroactively disable address indexing.');
if (this.keepBlocks !== options.keepBlocks)
throw new Error('Cannot change keepBlocks option retroactively.');
};
ChainOptions.prototype.toRaw = function toRaw() {
@ -1687,7 +1695,6 @@ ChainOptions.prototype.toRaw = function toRaw() {
flags |= 1 << 4;
p.writeU32(flags);
p.writeU32(this.keepBlocks);
p.writeU32(0);
return p.render();
@ -1701,7 +1708,6 @@ ChainOptions.prototype.fromRaw = function fromRaw(data) {
this.prune = (flags & 4) !== 0;
this.indexTX = (flags & 8) !== 0;
this.indexAddress = (flags & 16) !== 0;
this.keepBlocks = p.readU32();
return this;
};

View File

@ -269,7 +269,13 @@ main.block = {
* Safe height to start pruning.
*/
pruneAfterHeight: 100000,
pruneAfterHeight: 1000,
/**
* Safe number of blocks to keep.
*/
keepBlocks: 288,
/**
* Age used for the time delta to
@ -530,6 +536,7 @@ testnet.block = {
bip66height: 330776,
bip66hash: '82a14b9e5ea81d4832b8e2cd3c2a6092b5a3853285a8995ec4c8042100000000',
pruneAfterHeight: 1000,
keepBlocks: 10000,
// maxTipAge: 0x7fffffff
maxTipAge: 24 * 60 * 60,
slowHeight: 750000
@ -674,6 +681,7 @@ regtest.block = {
bip66height: 1251,
bip66hash: null,
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 24 * 60 * 60,
slowHeight: 0x7fffffff
};
@ -817,6 +825,7 @@ segnet3.block = {
bip141height: 8,
bip141hash: '1c2a2898cebca152f872fa71b756903711ad778c7d63ba6b73c140f800000000',
pruneAfterHeight: 1000,
keepBlocks: 10000,
// maxTipAge: 0x7fffffff,
maxTipAge: 24 * 60 * 60,
slowHeight: 0x7fffffff
@ -934,6 +943,7 @@ segnet4.block = {
bip66height: 8,
bip66hash: '6c48386dc7c460defabb5640e28b6510a5f238cdbe6756c2976a7e0913000000',
pruneAfterHeight: 1000,
keepBlocks: 10000,
// maxTipAge: 0x7fffffff,
maxTipAge: 24 * 60 * 60,
slowHeight: 0x7fffffff
@ -1073,6 +1083,7 @@ simnet.block = {
bip66height: 0,
bip66hash: 'f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68',
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 0x7fffffff,
slowHeight: 0
};

View File

@ -148,6 +148,7 @@ function WalletDB(options) {
AsyncObject.call(this);
this.options = options;
this.prune = options.prune !== false;
this.network = Network.get(options.network);
this.fees = options.fees;
this.logger = options.logger || Logger.global;
@ -1142,7 +1143,7 @@ WalletDB.prototype.rescan = co(function* rescan(chaindb, height) {
WalletDB.prototype._rescan = co(function* rescan(chaindb, height) {
var self = this;
var hashes;
var hashes, blocks;
if (height == null) {
height = this.height - 36;
@ -1150,7 +1151,15 @@ WalletDB.prototype._rescan = co(function* rescan(chaindb, height) {
height = 0;
}
yield this.rollback(height);
blocks = this.height - height;
assert(blocks >= 0);
if (this.prune) {
if (blocks <= this.network.block.keepBlocks)
yield this.rollback(height);
} else {
yield this.rollback(height);
}
hashes = yield this.getHashes();
@ -1416,11 +1425,18 @@ WalletDB.prototype.setTip = function setTip(hash, height, ts) {
WalletDB.prototype.setBlock = co(function* setBlock(block) {
var batch = this.db.batch();
var height;
batch.del(layout.b(block.height + 1));
batch.put(layout.b(block.height), block.toRaw());
batch.put(layout.R, U32(block.height));
if (this.prune) {
height = block.height - this.network.block.keepBlocks;
if (height > this.network.block.pruneAfterHeight)
batch.del(layout.b(height));
}
yield batch.write();
this.tip = block;
@ -1435,8 +1451,16 @@ WalletDB.prototype.setBlock = co(function* setBlock(block) {
WalletDB.prototype.writeBlock = function writeBlock(wallet, block) {
var batch = this.batch(wallet);
var height = block.height - this.network.block.keepBlocks;
batch.put(layout.b(block.height), block.toRaw());
batch.put(layout.R, U32(block.height));
if (this.prune) {
height = block.height - this.network.block.keepBlocks;
if (height > this.network.block.pruneAfterHeight)
batch.del(layout.b(height));
}
};
/**
@ -1521,7 +1545,18 @@ WalletDB.prototype.rollback = co(function* rollback(height) {
while (this.height > height) {
block = yield this.getBlock(this.height);
assert(block);
if (!block) {
if (this.prune) {
height = this.network.blocks.pruneAfterHeight;
block = yield this.getBlock(height);
assert(block);
yield this.setBlock(block);
throw new Error('Wallet reorgd beyond safe height. Rescan required.');
}
assert(false, 'Database corruption.');
}
yield this._removeBlock(block);
}
});