misc method improvements.
This commit is contained in:
parent
71557ba95c
commit
9bc3e44a7f
@ -347,20 +347,6 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||||||
return height;
|
return height;
|
||||||
};
|
};
|
||||||
|
|
||||||
Block.prototype.getNextBlock = function getNextBlock() {
|
|
||||||
var next;
|
|
||||||
|
|
||||||
if (!this.chain)
|
|
||||||
return utils.toHex(constants.zeroHash);
|
|
||||||
|
|
||||||
next = this.chain.getNextBlock(this.hash('hex'));
|
|
||||||
|
|
||||||
if (!next)
|
|
||||||
return utils.toHex(constants.zeroHash);
|
|
||||||
|
|
||||||
return next;
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.reward = function reward(height) {
|
Block.reward = function reward(height) {
|
||||||
var halvings = height / network.halvingInterval | 0;
|
var halvings = height / network.halvingInterval | 0;
|
||||||
var reward;
|
var reward;
|
||||||
@ -432,7 +418,7 @@ Block.prototype.getFee = function getFee() {
|
|||||||
Block.prototype.getEntry = function getEntry() {
|
Block.prototype.getEntry = function getEntry() {
|
||||||
if (!this.chain)
|
if (!this.chain)
|
||||||
return;
|
return;
|
||||||
return this.chain.getBlock(this);
|
return this.chain.getEntry(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Block.prototype.isOrphan = function isOrphan() {
|
Block.prototype.isOrphan = function isOrphan() {
|
||||||
@ -462,10 +448,6 @@ Block.prototype.__defineGetter__('rhash', function() {
|
|||||||
return utils.revHex(this.hash('hex'));
|
return utils.revHex(this.hash('hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
Block.prototype.__defineGetter__('nextBlock', function() {
|
|
||||||
return this.getNextBlock();
|
|
||||||
});
|
|
||||||
|
|
||||||
Block.prototype.__defineGetter__('reward', function() {
|
Block.prototype.__defineGetter__('reward', function() {
|
||||||
return this.getReward();
|
return this.getReward();
|
||||||
});
|
});
|
||||||
@ -493,7 +475,6 @@ Block.prototype.inspect = function inspect() {
|
|||||||
delete copy._chain;
|
delete copy._chain;
|
||||||
copy.hash = this.hash('hex');
|
copy.hash = this.hash('hex');
|
||||||
copy.rhash = this.rhash;
|
copy.rhash = this.rhash;
|
||||||
copy.nextBlock = this.getNextBlock();
|
|
||||||
copy.reward = utils.btc(this.getReward());
|
copy.reward = utils.btc(this.getReward());
|
||||||
copy.fee = utils.btc(this.getFee());
|
copy.fee = utils.btc(this.getFee());
|
||||||
copy.date = new Date((copy.ts || 0) * 1000).toISOString();
|
copy.date = new Date((copy.ts || 0) * 1000).toISOString();
|
||||||
|
|||||||
@ -737,7 +737,7 @@ BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback)
|
|||||||
if (data) {
|
if (data) {
|
||||||
try {
|
try {
|
||||||
tx = bcoin.tx.fromRaw(data);
|
tx = bcoin.tx.fromRaw(data);
|
||||||
entry = bcoin.chain.global.db.get(record.height);
|
entry = bcoin.chain.global.db.getSync(record.height);
|
||||||
assert(entry);
|
assert(entry);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return callback(e);
|
return callback(e);
|
||||||
@ -797,7 +797,7 @@ BlockDB.prototype.getTX = function getTX(hash, callback) {
|
|||||||
if (data) {
|
if (data) {
|
||||||
try {
|
try {
|
||||||
tx = bcoin.tx.fromRaw(data);
|
tx = bcoin.tx.fromRaw(data);
|
||||||
entry = bcoin.chain.global.db.get(record.height);
|
entry = bcoin.chain.global.db.getSync(record.height);
|
||||||
assert(entry);
|
assert(entry);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return callback(e);
|
return callback(e);
|
||||||
@ -847,7 +847,7 @@ BlockDB.prototype.getBlock = function getBlock(hash, callback) {
|
|||||||
block.height = record.height;
|
block.height = record.height;
|
||||||
if (self.options.paranoid) {
|
if (self.options.paranoid) {
|
||||||
if (typeof hash === 'number') {
|
if (typeof hash === 'number') {
|
||||||
hash = bcoin.chain.global.get(hash);
|
hash = bcoin.chain.global.db.getSync(hash);
|
||||||
if (!hash)
|
if (!hash)
|
||||||
return callback(null, block);
|
return callback(null, block);
|
||||||
hash = hash.hash;
|
hash = hash.hash;
|
||||||
@ -1051,7 +1051,7 @@ function BlockData(options) {
|
|||||||
if (!this.file)
|
if (!this.file)
|
||||||
this.file = process.env.HOME + '/bcoin-block-' + network.type + '.db';
|
this.file = process.env.HOME + '/bcoin-block-' + network.type + '.db';
|
||||||
|
|
||||||
this._bufferPool = { used: {} };
|
this.bufferPool = { used: {} };
|
||||||
this.size = 0;
|
this.size = 0;
|
||||||
this.fd = null;
|
this.fd = null;
|
||||||
|
|
||||||
@ -1076,7 +1076,7 @@ BlockData.prototype._init = function _init() {
|
|||||||
if (!this.exists())
|
if (!this.exists())
|
||||||
fs.writeFileSync(this.file, new Buffer([]));
|
fs.writeFileSync(this.file, new Buffer([]));
|
||||||
|
|
||||||
this.size = this.getSize();
|
this.size = this.getFileSize();
|
||||||
|
|
||||||
this.fd = fs.openSync(this.file, 'r+');
|
this.fd = fs.openSync(this.file, 'r+');
|
||||||
};
|
};
|
||||||
@ -1115,24 +1115,24 @@ BlockData.prototype._malloc = function _malloc(size) {
|
|||||||
if (size > 500)
|
if (size > 500)
|
||||||
return new Buffer(size);
|
return new Buffer(size);
|
||||||
|
|
||||||
if (!this._bufferPool[size])
|
if (!this.bufferPool[size])
|
||||||
this._bufferPool[size] = new Buffer(size);
|
this.bufferPool[size] = new Buffer(size);
|
||||||
|
|
||||||
if (this._bufferPool.used[size] === this._bufferPool[size])
|
if (this.bufferPool.used[size] === this.bufferPool[size])
|
||||||
return new Buffer(size);
|
return new Buffer(size);
|
||||||
|
|
||||||
this._bufferPool.used[size] = this._bufferPool[size];
|
this.bufferPool.used[size] = this.bufferPool[size];
|
||||||
|
|
||||||
return this._bufferPool[size];
|
return this.bufferPool[size];
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockData.prototype._free = function _free(buf) {
|
BlockData.prototype._free = function _free(buf) {
|
||||||
if (!this.options.usePool)
|
if (!this.options.usePool)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._bufferPool.used[buf.length] === buf) {
|
if (this.bufferPool.used[buf.length] === buf) {
|
||||||
assert(this._bufferPool[buf.length] === buf);
|
assert(this.bufferPool[buf.length] === buf);
|
||||||
delete this._bufferPool.used[buf.length];
|
delete this.bufferPool.used[buf.length];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1148,7 +1148,7 @@ BlockData.prototype.exists = function exists() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockData.prototype.getSize = function getSize() {
|
BlockData.prototype.getFileSize = function getFileSize() {
|
||||||
if (!bcoin.fs)
|
if (!bcoin.fs)
|
||||||
return this.ramdisk.size;
|
return this.ramdisk.size;
|
||||||
|
|
||||||
@ -1277,6 +1277,9 @@ BlockData.prototype._readAsync = function _readAsync(size, offset, callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bytes)
|
||||||
|
return callback(new Error('_readAsync() failed.'));
|
||||||
|
|
||||||
index += bytes;
|
index += bytes;
|
||||||
size -= bytes;
|
size -= bytes;
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
@ -1349,6 +1352,9 @@ BlockData.prototype._writeAsync = function _writeAsync(data, offset, callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bytes)
|
||||||
|
return callback(new Error('_writeAsync() failed.'));
|
||||||
|
|
||||||
index += bytes;
|
index += bytes;
|
||||||
size -= bytes;
|
size -= bytes;
|
||||||
offset += bytes;
|
offset += bytes;
|
||||||
|
|||||||
@ -233,7 +233,7 @@ Chain.prototype._preload = function _preload(callback) {
|
|||||||
utils.debug('Loading %s', url);
|
utils.debug('Loading %s', url);
|
||||||
|
|
||||||
stream = request.get(url);
|
stream = request.get(url);
|
||||||
chainHeight = this.db.count() - 1;
|
chainHeight = this.db.getSize() - 1;
|
||||||
height = 0;
|
height = 0;
|
||||||
buf = {
|
buf = {
|
||||||
data: [],
|
data: [],
|
||||||
@ -249,7 +249,7 @@ Chain.prototype._preload = function _preload(callback) {
|
|||||||
|
|
||||||
stream.on('error', function(err) {
|
stream.on('error', function(err) {
|
||||||
var start = Math.max(0, height - 2);
|
var start = Math.max(0, height - 2);
|
||||||
self.resetHeight(start);
|
self.resetHeightSync(start);
|
||||||
return callback(err, start + 1);
|
return callback(err, start + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ Chain.prototype._preload = function _preload(callback) {
|
|||||||
if (lastEntry && entry.prevBlock !== lastEntry.hash) {
|
if (lastEntry && entry.prevBlock !== lastEntry.hash) {
|
||||||
start = Math.max(0, height - 2);
|
start = Math.max(0, height - 2);
|
||||||
stream.destroy();
|
stream.destroy();
|
||||||
self.resetHeight(start);
|
self.resetHeightSync(start);
|
||||||
return callback(new Error('Corrupt headers.'), start + 1);
|
return callback(new Error('Corrupt headers.'), start + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ Chain.prototype._preload = function _preload(callback) {
|
|||||||
if (!block.verify()) {
|
if (!block.verify()) {
|
||||||
start = Math.max(0, height - 2);
|
start = Math.max(0, height - 2);
|
||||||
stream.destroy();
|
stream.destroy();
|
||||||
self.resetHeight(start);
|
self.resetHeightSync(start);
|
||||||
return callback(new Error('Bad headers.'), start + 1);
|
return callback(new Error('Bad headers.'), start + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,10 +311,12 @@ Chain.prototype._preload = function _preload(callback) {
|
|||||||
|
|
||||||
// Filthy hack to avoid writing
|
// Filthy hack to avoid writing
|
||||||
// redundant blocks to disk!
|
// redundant blocks to disk!
|
||||||
if (height < chainHeight)
|
if (height <= chainHeight) {
|
||||||
|
self.db._cache(entry);
|
||||||
self.db._populate(entry);
|
self.db._populate(entry);
|
||||||
else
|
} else {
|
||||||
self.db.save(entry);
|
self.db.saveAsync(entry);
|
||||||
|
}
|
||||||
|
|
||||||
height++;
|
height++;
|
||||||
|
|
||||||
@ -666,7 +668,7 @@ Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Duplicate height (do a sync call here since this is cached)
|
// Duplicate height (do a sync call here since this is cached)
|
||||||
existing = this.db.get(entry.height);
|
existing = this.db.getSync(entry.height);
|
||||||
if (existing && existing.hash === entry.hash)
|
if (existing && existing.hash === entry.hash)
|
||||||
return callback(null, false);
|
return callback(null, false);
|
||||||
|
|
||||||
@ -674,7 +676,7 @@ Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
self.db.save(entry, function(err) {
|
self.db.saveAsync(entry, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -694,7 +696,7 @@ Chain.prototype.resetHeight = function resetHeight(height) {
|
|||||||
if (height === count - 1)
|
if (height === count - 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.db.resetHeight(height);
|
this.db.resetHeightSync(height);
|
||||||
|
|
||||||
// Reset the orphan map completely. There may
|
// Reset the orphan map completely. There may
|
||||||
// have been some orphans on a forked chain we
|
// have been some orphans on a forked chain we
|
||||||
@ -753,7 +755,7 @@ Chain.prototype.revertHeight = function revertHeight(height, callback) {
|
|||||||
callback(err, result);
|
callback(err, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
chainHeight = this.db.count() - 1;
|
chainHeight = this.db.getSize() - 1;
|
||||||
|
|
||||||
if (chainHeight < 0)
|
if (chainHeight < 0)
|
||||||
return done(new Error('Bad chain height.'));
|
return done(new Error('Bad chain height.'));
|
||||||
@ -824,7 +826,7 @@ Chain.prototype.syncHeight = function syncHeight(callback) {
|
|||||||
callback(err, result);
|
callback(err, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
chainHeight = this.db.count() - 1;
|
chainHeight = this.db.getSize() - 1;
|
||||||
|
|
||||||
if (chainHeight < 0)
|
if (chainHeight < 0)
|
||||||
return done(new Error('Bad chain height.'));
|
return done(new Error('Bad chain height.'));
|
||||||
@ -867,7 +869,7 @@ Chain.prototype.resetTime = function resetTime(ts) {
|
|||||||
var entry = this.byTime(ts);
|
var entry = this.byTime(ts);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
return this.resetHeight(entry.height);
|
return this.resetHeightSync(entry.height);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.resetTimeAsync = function resetTimeAsync(ts, callback) {
|
Chain.prototype.resetTimeAsync = function resetTimeAsync(ts, callback) {
|
||||||
@ -1114,7 +1116,7 @@ Chain.prototype.add = function add(initial, peer, callback) {
|
|||||||
// Lookup previous entry.
|
// Lookup previous entry.
|
||||||
// We can do this synchronously:
|
// We can do this synchronously:
|
||||||
// it is already cached.
|
// it is already cached.
|
||||||
prev = self.db.get(prevHeight);
|
prev = self.db.getSync(prevHeight);
|
||||||
assert(prev);
|
assert(prev);
|
||||||
|
|
||||||
// Do "contextual" verification on our block
|
// Do "contextual" verification on our block
|
||||||
@ -1258,7 +1260,7 @@ Chain.prototype.byTime = function byTime(ts) {
|
|||||||
// timestamp.
|
// timestamp.
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
pos = (start + end) >> 1;
|
pos = (start + end) >> 1;
|
||||||
entry = this.db.get(pos);
|
entry = this.db.getSync(pos);
|
||||||
delta = Math.abs(ts - entry.ts);
|
delta = Math.abs(ts - entry.ts);
|
||||||
|
|
||||||
if (delta <= 60 * 60)
|
if (delta <= 60 * 60)
|
||||||
@ -1271,7 +1273,7 @@ Chain.prototype.byTime = function byTime(ts) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.db.get(start);
|
return this.db.getSync(start);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.byTimeAsync = function byTimeAsync(ts, callback) {
|
Chain.prototype.byTimeAsync = function byTimeAsync(ts, callback) {
|
||||||
@ -1349,19 +1351,19 @@ Chain.prototype.hasPending = function hasPending(hash) {
|
|||||||
return !!this.pendingBlocks[hash];
|
return !!this.pendingBlocks[hash];
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.getBlock = function getBlock(hash) {
|
Chain.prototype.getEntry = function getEntry(hash) {
|
||||||
if (typeof hash === 'number')
|
if (typeof hash === 'number')
|
||||||
return this.db.get(hash);
|
return this.db.getSync(hash);
|
||||||
|
|
||||||
if (utils.isBuffer(hash))
|
if (utils.isBuffer(hash))
|
||||||
hash = utils.toHex(hash);
|
hash = utils.toHex(hash);
|
||||||
else if (hash.hash)
|
else if (hash.hash)
|
||||||
hash = hash.hash('hex');
|
hash = hash.hash('hex');
|
||||||
|
|
||||||
return this.db.get(hash);
|
return this.db.getSync(hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.getBlockAsync = function getBlockAsync(hash, callback) {
|
Chain.prototype.getEntryAsync = function getEntryAsync(hash, callback) {
|
||||||
if (typeof hash === 'number')
|
if (typeof hash === 'number')
|
||||||
return this.db.getAsync(hash, callback);
|
return this.db.getAsync(hash, callback);
|
||||||
|
|
||||||
@ -1399,26 +1401,23 @@ Chain.prototype.getProgress = function getProgress() {
|
|||||||
return Math.min(1, this.tip.ts / (utils.now() - 40 * 60));
|
return Math.min(1, this.tip.ts / (utils.now() - 40 * 60));
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.hashRange = function hashRange(start, end) {
|
Chain.prototype.getHashRange = function getHashRange(start, end) {
|
||||||
var hashes = [];
|
var hashes = [];
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
start = this.byTime(start);
|
start = this.byTime(start);
|
||||||
end = this.byTime(end);
|
end = this.byTime(end);
|
||||||
|
|
||||||
if (!end)
|
|
||||||
end = this.tip;
|
|
||||||
|
|
||||||
if (!start || !end)
|
if (!start || !end)
|
||||||
return hashes;
|
return hashes;
|
||||||
|
|
||||||
for (i = start.height; i < end.height + 1; i++)
|
for (i = start.height; i < end.height + 1; i++)
|
||||||
hashes.push(this.db.get(i).hash);
|
hashes.push(this.db.getSync(i).hash);
|
||||||
|
|
||||||
return hashes;
|
return hashes;
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.hashRangeAsync = function hashRangeAsync(start, end, callback) {
|
Chain.prototype.getHashRangeAsync = function getHashRangeAsync(start, end, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var called;
|
var called;
|
||||||
|
|
||||||
@ -1441,9 +1440,6 @@ Chain.prototype.hashRangeAsync = function hashRangeAsync(start, end, callback) {
|
|||||||
|
|
||||||
hashes = [];
|
hashes = [];
|
||||||
|
|
||||||
if (!end)
|
|
||||||
end = self.tip;
|
|
||||||
|
|
||||||
if (!start || !end)
|
if (!start || !end)
|
||||||
return done(null, hashes);
|
return done(null, hashes);
|
||||||
|
|
||||||
@ -1460,7 +1456,7 @@ Chain.prototype.hashRangeAsync = function hashRangeAsync(start, end, callback) {
|
|||||||
if (!entry)
|
if (!entry)
|
||||||
return done(new Error('No entry for hash range.'));
|
return done(new Error('No entry for hash range.'));
|
||||||
|
|
||||||
hashes.push(entry.hash);
|
hashes[i - start.height] = entry.hash;
|
||||||
|
|
||||||
if (!--pending)
|
if (!--pending)
|
||||||
return done(null, hashes);
|
return done(null, hashes);
|
||||||
@ -1503,7 +1499,7 @@ Chain.prototype.getLocator = function getLocator(start) {
|
|||||||
|
|
||||||
i = top;
|
i = top;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
existing = this.db.get(i);
|
existing = this.db.getSync(i);
|
||||||
assert(existing);
|
assert(existing);
|
||||||
hashes.push(existing.hash);
|
hashes.push(existing.hash);
|
||||||
i = i - step;
|
i = i - step;
|
||||||
@ -1624,41 +1620,8 @@ Chain.prototype.getHeight = function getHeight(hash) {
|
|||||||
return this.db.getHeight(hash);
|
return this.db.getHeight(hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.getNextBlock = function getNextBlock(hash) {
|
|
||||||
var height = this.db.getHeight(hash);
|
|
||||||
var entry;
|
|
||||||
|
|
||||||
if (height === -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
entry = this.db.get(height + 1);
|
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
return;
|
|
||||||
|
|
||||||
return entry.hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
Chain.prototype.getNextBlockAsync = function getNextBlockAsync(hash, callback) {
|
|
||||||
var height = this.db.getHeight(hash);
|
|
||||||
|
|
||||||
if (height === -1)
|
|
||||||
return callback();
|
|
||||||
|
|
||||||
return this.db.getAsync(height + 1, function(err, entry) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
return callback();
|
|
||||||
|
|
||||||
return callback(null, entry.hash);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Chain.prototype.getSize = function getSize() {
|
Chain.prototype.getSize = function getSize() {
|
||||||
return this.db.count();
|
return this.db.getSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
@ -1702,7 +1665,7 @@ Chain.prototype.getTarget = function getTarget(last, block) {
|
|||||||
|
|
||||||
// Back 2 weeks
|
// Back 2 weeks
|
||||||
// NOTE: This is cached.
|
// NOTE: This is cached.
|
||||||
first = this.db.get(last.height - (network.powDiffInterval - 1));
|
first = this.db.getSync(last.height - (network.powDiffInterval - 1));
|
||||||
|
|
||||||
assert(first);
|
assert(first);
|
||||||
|
|
||||||
|
|||||||
@ -38,11 +38,11 @@ function ChainBlock(chain, data) {
|
|||||||
ChainBlock.BLOCK_SIZE = 112;
|
ChainBlock.BLOCK_SIZE = 112;
|
||||||
|
|
||||||
ChainBlock.prototype.__defineGetter__('prev', function() {
|
ChainBlock.prototype.__defineGetter__('prev', function() {
|
||||||
return this.chain.db.get(this.height - 1);
|
return this.chain.db.getSync(this.height - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
ChainBlock.prototype.__defineGetter__('next', function() {
|
ChainBlock.prototype.__defineGetter__('next', function() {
|
||||||
return this.chain.db.get(this.height + 1);
|
return this.chain.db.getSync(this.height + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
ChainBlock.prototype.getProof = function getProof() {
|
ChainBlock.prototype.getProof = function getProof() {
|
||||||
@ -53,13 +53,19 @@ ChainBlock.prototype.getProof = function getProof() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainBlock.prototype.getChainwork = function getChainwork() {
|
ChainBlock.prototype.getChainwork = function getChainwork() {
|
||||||
|
var prev;
|
||||||
|
|
||||||
|
// Workaround for genesis block
|
||||||
|
// being added _in_ chaindb.
|
||||||
if (!this.chain.db)
|
if (!this.chain.db)
|
||||||
return;
|
return;
|
||||||
var prev = this.prev;
|
|
||||||
|
prev = this.prev;
|
||||||
|
|
||||||
return (prev ? prev.chainwork : new bn(0)).add(this.getProof());
|
return (prev ? prev.chainwork : new bn(0)).add(this.getProof());
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainBlock.prototype.isGenesis = function isGenesis(version) {
|
ChainBlock.prototype.isGenesis = function isGenesis() {
|
||||||
return this.hash === network.genesis.hash;
|
return this.hash === network.genesis.hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -38,9 +38,9 @@ function ChainDB(chain, options) {
|
|||||||
this.file = process.env.HOME + '/bcoin-chain-' + network.type + '.db';
|
this.file = process.env.HOME + '/bcoin-chain-' + network.type + '.db';
|
||||||
|
|
||||||
this.heightLookup = {};
|
this.heightLookup = {};
|
||||||
this._queue = {};
|
this.queue = {};
|
||||||
this._cache = {};
|
this.cache = {};
|
||||||
this._bufferPool = { used: {} };
|
this.bufferPool = { used: {} };
|
||||||
this.highest = -1;
|
this.highest = -1;
|
||||||
this.tip = null;
|
this.tip = null;
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
@ -90,12 +90,12 @@ ChainDB.prototype._init = function _init() {
|
|||||||
if (!this.exists())
|
if (!this.exists())
|
||||||
fs.writeFileSync(this.file, new Buffer([]));
|
fs.writeFileSync(this.file, new Buffer([]));
|
||||||
|
|
||||||
this.size = this.getSize();
|
this.size = this.getFileSize();
|
||||||
|
|
||||||
if (this.size % BLOCK_SIZE !== 0) {
|
if (this.size % BLOCK_SIZE !== 0) {
|
||||||
utils.debug('Blockchain is at an odd length. Truncating.');
|
utils.debug('Blockchain is at an odd length. Truncating.');
|
||||||
fs.truncateSync(this.file, this.size - (this.size % BLOCK_SIZE));
|
fs.truncateSync(this.file, this.size - (this.size % BLOCK_SIZE));
|
||||||
this.size = this.getSize();
|
this.size = this.getFileSize();
|
||||||
assert(this.size % BLOCK_SIZE === 0);
|
assert(this.size % BLOCK_SIZE === 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ ChainDB.prototype._init = function _init() {
|
|||||||
|
|
||||||
ChainDB.prototype.load = function load(start, callback) {
|
ChainDB.prototype.load = function load(start, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var count = this.count();
|
var count = this.getSize();
|
||||||
var i = start || 0;
|
var i = start || 0;
|
||||||
var lastEntry;
|
var lastEntry;
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ ChainDB.prototype.load = function load(start, callback) {
|
|||||||
utils.debug(
|
utils.debug(
|
||||||
'Blockchain is corrupt after height %d. Resetting.',
|
'Blockchain is corrupt after height %d. Resetting.',
|
||||||
height);
|
height);
|
||||||
self.resetHeight(height);
|
self.resetHeightSync(height);
|
||||||
} else {
|
} else {
|
||||||
utils.debug('Chain successfully loaded.');
|
utils.debug('Chain successfully loaded.');
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ ChainDB.prototype.closeSync = function closeSync() {
|
|||||||
this.ramdisk = null;
|
this.ramdisk = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fs.closeSync(this.fd);
|
fs.close(this.fd);
|
||||||
this.fd = null;
|
this.fd = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -182,24 +182,24 @@ ChainDB.prototype._malloc = function _malloc(size) {
|
|||||||
if (!this.options.usePool)
|
if (!this.options.usePool)
|
||||||
return new Buffer(size);
|
return new Buffer(size);
|
||||||
|
|
||||||
if (!this._bufferPool[size])
|
if (!this.bufferPool[size])
|
||||||
this._bufferPool[size] = new Buffer(size);
|
this.bufferPool[size] = new Buffer(size);
|
||||||
|
|
||||||
if (this._bufferPool.used[size] === this._bufferPool[size])
|
if (this.bufferPool.used[size] === this.bufferPool[size])
|
||||||
return new Buffer(size);
|
return new Buffer(size);
|
||||||
|
|
||||||
this._bufferPool.used[size] = this._bufferPool[size];
|
this.bufferPool.used[size] = this.bufferPool[size];
|
||||||
|
|
||||||
return this._bufferPool[size];
|
return this.bufferPool[size];
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype._free = function _free(buf) {
|
ChainDB.prototype._free = function _free(buf) {
|
||||||
if (!this.options.usePool)
|
if (!this.options.usePool)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._bufferPool.used[buf.length] === buf) {
|
if (this.bufferPool.used[buf.length] === buf) {
|
||||||
assert(this._bufferPool[buf.length] === buf);
|
assert(this.bufferPool[buf.length] === buf);
|
||||||
delete this._bufferPool.used[buf.length];
|
delete this.bufferPool.used[buf.length];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ ChainDB.prototype.exists = function exists() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.getSize = function getSize() {
|
ChainDB.prototype.getFileSize = function getFileSize() {
|
||||||
if (!bcoin.fs)
|
if (!bcoin.fs)
|
||||||
return this.ramdisk.size;
|
return this.ramdisk.size;
|
||||||
|
|
||||||
@ -226,18 +226,18 @@ ChainDB.prototype.getSize = function getSize() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.count = function count() {
|
ChainDB.prototype.getSize = function getSize() {
|
||||||
var len = this.size / BLOCK_SIZE;
|
var len = this.size / BLOCK_SIZE;
|
||||||
assert(len % 1 === 0);
|
assert(len % 1 === 0);
|
||||||
return len;
|
return len;
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.cache = function cache(entry) {
|
ChainDB.prototype._cache = function _cache(entry) {
|
||||||
if (entry.height > this.highest) {
|
if (entry.height > this.highest) {
|
||||||
this.highest = entry.height;
|
this.highest = entry.height;
|
||||||
delete this._cache[entry.height - this._cacheWindow];
|
delete this.cache[entry.height - this._cacheWindow];
|
||||||
this._cache[entry.height] = entry;
|
this.cache[entry.height] = entry;
|
||||||
assert(Object.keys(this._cache).length <= this._cacheWindow);
|
assert(Object.keys(this.cache).length <= this._cacheWindow);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -260,21 +260,17 @@ ChainDB.prototype._populate = function _populate(entry) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.get = function get(height) {
|
|
||||||
return this.getSync(height);
|
|
||||||
};
|
|
||||||
|
|
||||||
ChainDB.prototype.getSync = function getSync(height) {
|
ChainDB.prototype.getSync = function getSync(height) {
|
||||||
var data, entry;
|
var data, entry;
|
||||||
|
|
||||||
if (typeof height === 'string')
|
if (typeof height === 'string')
|
||||||
height = this.heightLookup[height];
|
height = this.heightLookup[height];
|
||||||
|
|
||||||
if (this._cache[height])
|
if (this.cache[height])
|
||||||
return this._cache[height];
|
return this.cache[height];
|
||||||
|
|
||||||
if (this._queue[height])
|
if (this.queue[height])
|
||||||
return this._queue[height];
|
return this.queue[height];
|
||||||
|
|
||||||
if (height < 0 || height == null)
|
if (height < 0 || height == null)
|
||||||
return;
|
return;
|
||||||
@ -289,11 +285,12 @@ ChainDB.prototype.getSync = function getSync(height) {
|
|||||||
|
|
||||||
entry = bcoin.chainblock.fromRaw(this.chain, height, data);
|
entry = bcoin.chainblock.fromRaw(this.chain, height, data);
|
||||||
|
|
||||||
|
// Populate the entry.
|
||||||
this._populate(entry);
|
this._populate(entry);
|
||||||
|
|
||||||
// Cache the past 1001 blocks in memory
|
// Cache the past 1001 blocks in memory
|
||||||
// (necessary for isSuperMajority)
|
// (necessary for isSuperMajority)
|
||||||
this.cache(entry);
|
this._cache(entry);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
};
|
};
|
||||||
@ -306,11 +303,11 @@ ChainDB.prototype.getAsync = function getAsync(height, callback) {
|
|||||||
if (typeof height === 'string')
|
if (typeof height === 'string')
|
||||||
height = this.heightLookup[height];
|
height = this.heightLookup[height];
|
||||||
|
|
||||||
if (this._cache[height])
|
if (this.cache[height])
|
||||||
return callback(null, this._cache[height]);
|
return callback(null, this.cache[height]);
|
||||||
|
|
||||||
if (this._queue[height])
|
if (this.queue[height])
|
||||||
return callback(null, this._queue[height]);
|
return callback(null, this.queue[height]);
|
||||||
|
|
||||||
if (height < 0 || height == null)
|
if (height < 0 || height == null)
|
||||||
return callback();
|
return callback();
|
||||||
@ -321,31 +318,25 @@ ChainDB.prototype.getAsync = function getAsync(height, callback) {
|
|||||||
return this._readAsync(BLOCK_SIZE, height * BLOCK_SIZE, function(err, data) {
|
return this._readAsync(BLOCK_SIZE, height * BLOCK_SIZE, function(err, data) {
|
||||||
var entry;
|
var entry;
|
||||||
|
|
||||||
// We can't ensure the integrity of
|
|
||||||
// the chain if we get an error.
|
|
||||||
// Just throw.
|
|
||||||
if (err)
|
if (err)
|
||||||
throw err;
|
return callback(err);
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
entry = bcoin.chainblock.fromRaw(self.chain, height, data);
|
entry = bcoin.chainblock.fromRaw(self.chain, height, data);
|
||||||
|
|
||||||
|
// Populate the entry.
|
||||||
self._populate(entry);
|
self._populate(entry);
|
||||||
|
|
||||||
// Cache the past 1001 blocks in memory
|
// Cache the past 1001 blocks in memory
|
||||||
// (necessary for isSuperMajority)
|
// (necessary for isSuperMajority)
|
||||||
self.cache(entry);
|
self._cache(entry);
|
||||||
|
|
||||||
return callback(null, entry);
|
return callback(null, entry);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.save = function save(entry, callback) {
|
|
||||||
return this.saveAsync(entry, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ChainDB.prototype.saveSync = function saveSync(entry) {
|
ChainDB.prototype.saveSync = function saveSync(entry) {
|
||||||
var raw, offset;
|
var raw, offset;
|
||||||
|
|
||||||
@ -354,8 +345,9 @@ ChainDB.prototype.saveSync = function saveSync(entry) {
|
|||||||
|
|
||||||
// Cache the past 1001 blocks in memory
|
// Cache the past 1001 blocks in memory
|
||||||
// (necessary for isSuperMajority)
|
// (necessary for isSuperMajority)
|
||||||
this.cache(entry);
|
this._cache(entry);
|
||||||
|
|
||||||
|
// Populate the entry.
|
||||||
this._populate(entry);
|
this._populate(entry);
|
||||||
|
|
||||||
raw = entry.toRaw();
|
raw = entry.toRaw();
|
||||||
@ -375,34 +367,32 @@ ChainDB.prototype.saveAsync = function saveAsync(entry, callback) {
|
|||||||
|
|
||||||
// Cache the past 1001 blocks in memory
|
// Cache the past 1001 blocks in memory
|
||||||
// (necessary for isSuperMajority)
|
// (necessary for isSuperMajority)
|
||||||
this.cache(entry);
|
this._cache(entry);
|
||||||
|
|
||||||
|
// Populate the entry.
|
||||||
this._populate(entry);
|
this._populate(entry);
|
||||||
|
|
||||||
// Something is already writing. Cancel it
|
// Something is already writing. Cancel it
|
||||||
// and synchronously write the data after
|
// and synchronously write the data after
|
||||||
// it cancels.
|
// it cancels.
|
||||||
if (this._queue[entry.height]) {
|
if (this.queue[entry.height]) {
|
||||||
this._queue[entry.height] = entry;
|
this.queue[entry.height] = entry;
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Speed up writes by doing them asynchronously
|
// Speed up writes by doing them asynchronously
|
||||||
// and keeping the data to be written in memory.
|
// and keeping the data to be written in memory.
|
||||||
this._queue[entry.height] = entry;
|
this.queue[entry.height] = entry;
|
||||||
|
|
||||||
// Write asynchronously to the db.
|
// Write asynchronously to the db.
|
||||||
raw = entry.toRaw();
|
raw = entry.toRaw();
|
||||||
offset = entry.height * BLOCK_SIZE;
|
offset = entry.height * BLOCK_SIZE;
|
||||||
|
|
||||||
return this._writeAsync(raw, offset, function(err, success) {
|
return this._writeAsync(raw, offset, function(err, success) {
|
||||||
// We can't ensure the integrity of
|
|
||||||
// the chain if we get an error.
|
|
||||||
// Just throw.
|
|
||||||
if (err)
|
if (err)
|
||||||
throw err;
|
return callback(err);
|
||||||
|
|
||||||
var item = self._queue[entry.height];
|
var item = self.queue[entry.height];
|
||||||
|
|
||||||
// Something tried to write here but couldn't.
|
// Something tried to write here but couldn't.
|
||||||
// Synchronously write it and get it over with.
|
// Synchronously write it and get it over with.
|
||||||
@ -413,26 +403,26 @@ ChainDB.prototype.saveAsync = function saveAsync(entry, callback) {
|
|||||||
err = e;
|
err = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete self._queue[entry.height];
|
delete self.queue[entry.height];
|
||||||
|
|
||||||
return callback(null, success);
|
return callback(null, success);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.drop = function drop(height) {
|
ChainDB.prototype._drop = function _drop(height) {
|
||||||
assert(height >= 0);
|
assert(height >= 0);
|
||||||
|
|
||||||
// Potential race condition here. Not sure how
|
// Potential race condition here. Not sure how
|
||||||
// to handle this.
|
// to handle this.
|
||||||
if (this._queue[height]) {
|
if (this.queue[height]) {
|
||||||
utils.debug('Warning: write job in progress.');
|
utils.debug('Warning: write job in progress.');
|
||||||
delete this._queue[height];
|
delete this.queue[height];
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this._cache[height];
|
delete this.cache[height];
|
||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype.resetHeight = function resetHeight(height) {
|
ChainDB.prototype.resetHeightSync = function resetHeightSync(height) {
|
||||||
var size, count, existing;
|
var size, count, existing;
|
||||||
|
|
||||||
if (typeof height === 'string')
|
if (typeof height === 'string')
|
||||||
@ -441,7 +431,7 @@ ChainDB.prototype.resetHeight = function resetHeight(height) {
|
|||||||
assert(height >= 0);
|
assert(height >= 0);
|
||||||
|
|
||||||
size = (height + 1) * BLOCK_SIZE;
|
size = (height + 1) * BLOCK_SIZE;
|
||||||
count = this.count();
|
count = this.getSize();
|
||||||
|
|
||||||
if (height === count - 1)
|
if (height === count - 1)
|
||||||
return;
|
return;
|
||||||
@ -452,7 +442,7 @@ ChainDB.prototype.resetHeight = function resetHeight(height) {
|
|||||||
for (i = height + 1; i < count; i++) {
|
for (i = height + 1; i < count; i++) {
|
||||||
existing = this.get(i);
|
existing = this.get(i);
|
||||||
assert(existing);
|
assert(existing);
|
||||||
this.drop(i);
|
this._drop(i);
|
||||||
delete this.heightLookup[existing.hash];
|
delete this.heightLookup[existing.hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,7 +471,7 @@ ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback)
|
|||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
size = (height + 1) * BLOCK_SIZE;
|
size = (height + 1) * BLOCK_SIZE;
|
||||||
count = this.count() - 1;
|
count = this.getSize();
|
||||||
pending = count - (height + 1);
|
pending = count - (height + 1);
|
||||||
|
|
||||||
if (height === count - 1)
|
if (height === count - 1)
|
||||||
@ -499,7 +489,7 @@ ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback)
|
|||||||
return done(err);
|
return done(err);
|
||||||
|
|
||||||
assert(existing);
|
assert(existing);
|
||||||
self.drop(i);
|
self._drop(i);
|
||||||
delete self.heightLookup[existing.hash];
|
delete self.heightLookup[existing.hash];
|
||||||
if (!--pending)
|
if (!--pending)
|
||||||
done();
|
done();
|
||||||
@ -604,7 +594,7 @@ ChainDB.prototype._readAsync = function _readAsync(size, offset, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bytes)
|
if (!bytes)
|
||||||
throw new Error('_readAsync() failed.');
|
return callback(new Error('_readAsync() failed.'));
|
||||||
|
|
||||||
index += bytes;
|
index += bytes;
|
||||||
size -= bytes;
|
size -= bytes;
|
||||||
@ -679,7 +669,7 @@ ChainDB.prototype._writeAsync = function _writeAsync(data, offset, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bytes)
|
if (!bytes)
|
||||||
throw new Error('_writeAsync() failed.');
|
return callback(new Error('_writeAsync() failed.'));
|
||||||
|
|
||||||
index += bytes;
|
index += bytes;
|
||||||
size -= bytes;
|
size -= bytes;
|
||||||
|
|||||||
@ -129,7 +129,7 @@ Miner.prototype.addBlock = function addBlock(block) {
|
|||||||
// us, start over with the new target.
|
// us, start over with the new target.
|
||||||
if (block.height > this.last.height) {
|
if (block.height > this.last.height) {
|
||||||
this.last = block.type === 'block'
|
this.last = block.type === 'block'
|
||||||
? this.chain.getBlock(block)
|
? this.chain.getEntry(block)
|
||||||
: block;
|
: block;
|
||||||
assert(this.last);
|
assert(this.last);
|
||||||
this.start();
|
this.start();
|
||||||
@ -304,7 +304,7 @@ Miner.prototype.iterate = function iterate() {
|
|||||||
self.emit('block', self.block);
|
self.emit('block', self.block);
|
||||||
|
|
||||||
// Try to find a new block
|
// Try to find a new block
|
||||||
self.last = self.chain.getBlock(self.block);
|
self.last = self.chain.getEntry(self.block);
|
||||||
assert(self.last);
|
assert(self.last);
|
||||||
self.block = self.createBlock();
|
self.block = self.createBlock();
|
||||||
|
|
||||||
|
|||||||
@ -1465,6 +1465,9 @@ Pool.prototype._request = function _request(peer, type, hash, options, cb) {
|
|||||||
|
|
||||||
item = new LoadRequest(this, peer, type, hash, cb);
|
item = new LoadRequest(this, peer, type, hash, cb);
|
||||||
|
|
||||||
|
if (options.noQueue)
|
||||||
|
return;
|
||||||
|
|
||||||
if (item.type === 'tx') {
|
if (item.type === 'tx') {
|
||||||
if (peer._txQueue.length === 0) {
|
if (peer._txQueue.length === 0) {
|
||||||
utils.nextTick(function() {
|
utils.nextTick(function() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user