switch to fullchain for both spv and fullnode.

This commit is contained in:
Christopher Jeffrey 2016-01-04 20:13:06 -08:00
parent 582a21fd5a
commit 019ecf4f2a
6 changed files with 29235 additions and 16276 deletions

View File

@ -49,7 +49,7 @@ function Chain(options) {
this.request = new utils.RequestCache(); this.request = new utils.RequestCache();
this.fromJSON({ this.fromJSON({
v: 1, v: 2,
type: 'chain', type: 'chain',
network: network.type, network: network.type,
entries: [ entries: [
@ -64,6 +64,9 @@ function Chain(options) {
] ]
}); });
if (!this.options.fullNode)
this.fromJSON(network.preload);
this.tip = this.index.entries[this.index.entries.length - 1]; this.tip = this.index.entries[this.index.entries.length - 1];
// Last TS after preload, needed for fill percent // Last TS after preload, needed for fill percent
@ -183,13 +186,20 @@ Chain.prototype.resetHeight = function resetHeight(height) {
var self = this; var self = this;
var ahead = this.index.entries.slice(height + 1); var ahead = this.index.entries.slice(height + 1);
assert(height < this.index.entries - 1); assert(height <= this.index.entries.length - 1);
if (height === this.index.entries.length - 1)
return;
this.orphan.map = {}; this.orphan.map = {};
this.orphan.bmap = {}; this.orphan.bmap = {};
this.orphan.count = 0; this.orphan.count = 0;
this.index.entries.length = height + 1; this.index.entries.length = height + 1;
this.index.heights = this.index.entries.reduce(function(out, entry) { this.index.heights = this.index.entries.reduce(function(out, entry) {
if (!self.options.fullNode) {
if (!entry)
return out;
}
out[entry.hash] = entry.height; out[entry.hash] = entry.height;
return out; return out;
}, {}); }, {});
@ -204,6 +214,10 @@ Chain.prototype.resetHeight = function resetHeight(height) {
); );
ahead.forEach(function(entry) { ahead.forEach(function(entry) {
if (!self.options.fullNode) {
if (!entry)
return;
}
self._delete(entry.hash); self._delete(entry.hash);
}); });
}; };
@ -225,7 +239,6 @@ Chain.prototype.add = function add(block, peer) {
var initial = block; var initial = block;
var code = Chain.codes.unchanged; var code = Chain.codes.unchanged;
var length = this.index.entries.length;
var hash, prev, prevProbe, range, i, entry; var hash, prev, prevProbe, range, i, entry;
for (;;) { for (;;) {
@ -306,6 +319,12 @@ Chain.prototype.add = function add(block, peer) {
this.orphan.count = 0; this.orphan.count = 0;
} }
// No need to have a huge chain
// if (!this.options.fullNode) {
// if (this.size() > 100000)
// this.compact();
// }
return code; return code;
}; };
@ -342,6 +361,10 @@ Chain.prototype.byHash = function byHash(hash) {
Chain.prototype.byTime = function byTime(ts) { Chain.prototype.byTime = function byTime(ts) {
for (var i = this.index.entries.length - 1; i >= 0; i--) { for (var i = this.index.entries.length - 1; i >= 0; i--) {
if (!this.options.fullNode) {
if (!this.index.entries[i])
continue;
}
if (ts >= this.index.entries[i].ts) if (ts >= this.index.entries[i].ts)
return this.index.entries[i]; return this.index.entries[i];
} }
@ -356,10 +379,6 @@ Chain.prototype.hasOrphan = function hasOrphan(hash) {
return !!this.getOrphan(hash); return !!this.getOrphan(hash);
}; };
Chain.prototype.hasCache = function hasCache(hash) {
assert(false);
};
Chain.prototype.getBlock = function getBlock(hash) { Chain.prototype.getBlock = function getBlock(hash) {
if (typeof hash === 'number') if (typeof hash === 'number')
return this.byHeight(hash); return this.byHeight(hash);
@ -375,10 +394,6 @@ Chain.prototype.getOrphan = function getOrphan(hash) {
return this.orphan.bmap[hash] || null; return this.orphan.bmap[hash] || null;
}; };
Chain.prototype.getCache = function getCache(hash) {
assert(false);
};
Chain.prototype.getTip = function getTip() { Chain.prototype.getTip = function getTip() {
return this.index.entries[this.index.entries.length - 1]; return this.index.entries[this.index.entries.length - 1];
}; };
@ -406,11 +421,10 @@ Chain.prototype.hashRange = function hashRange(start, end) {
hashes = this.index.hashes.slice(start.height, end.height + 1); hashes = this.index.hashes.slice(start.height, end.height + 1);
return hashes; if (!this.options.fullNode)
}; hashes = hashes.filter(Boolean);
Chain.prototype.hashesInRange = function hashesInRange(start, end, cb) { return hashes;
assert(false);
}; };
Chain.prototype.getStartHeight = function getStartHeight() { Chain.prototype.getStartHeight = function getStartHeight() {
@ -450,7 +464,8 @@ Chain.prototype.locatorHashes = function locatorHashes(start) {
hashes.push(chain[i]); hashes.push(chain[i]);
i = i - step; i = i - step;
if (i <= 0) { if (i <= 0) {
hashes.push(chain[0]); if (i + step !== 0)
hashes.push(chain[0]);
break; break;
} }
if (hashes.length >= 10) if (hashes.length >= 10)
@ -565,8 +580,57 @@ Chain.prototype.retarget = function retarget(last, firstTs) {
return utils.toCompact(target); return utils.toCompact(target);
}; };
Chain.prototype.compact = function compact() { Chain.prototype.compact = function compact(keep) {
assert(false); var entries = this._compact(keep);
this.index.entries = {};
this.index.hashes = [];
this.index.heights = {};
json.entries.forEach(function(entry) {
this._addIndex(ChainBlock.fromJSON(this, entry));
}, this);
};
Chain.prototype._compact = function _compact(keep) {
var entries = this.index.entries.filter(Boolean);
if (!keep)
keep = 1000;
// Keep only last 1000 consequent blocks, dilate others at:
// 7 day range for blocks before 2013
// 12 hour for blocks before 2014
// 6 hour for blocks in 2014 and after it
// (or at maximum 250 block range)
var last = entries.slice(-keep);
var first = [];
var delta1 = 7 * 24 * 3600;
var delta2 = 12 * 3600;
var delta3 = 6 * 3600;
var lastTs = 0;
var lastHeight = -1000;
var i, ts, delta, hdelta;
for (i = 0; i < entries.length - keep; i++) {
ts = entries[i].ts;
delta = ts < 1356984000
? delta1
: ts < 1388520000 ? delta2 : delta3;
hdelta = entries[i].height - lastHeight;
if (ts - lastTs < delta && hdelta < 250)
continue;
lastTs = ts;
lastHeight = entries[i].height;
first.push(this.index.entries[i]);
}
return first.concat(last);
}; };
Chain.prototype._save = function(hash, obj) { Chain.prototype._save = function(hash, obj) {
@ -595,8 +659,12 @@ Chain.prototype._delete = function(hash) {
Chain.prototype.toJSON = function toJSON() { Chain.prototype.toJSON = function toJSON() {
var entries = this.index.entries; var entries = this.index.entries;
if (!this.options.fullNode)
entries = this._compact();
return { return {
v: 1, v: 2,
type: 'chain', type: 'chain',
network: network.type, network: network.type,
entries: entries.map(function(entry) { entries: entries.map(function(entry) {
@ -606,7 +674,7 @@ Chain.prototype.toJSON = function toJSON() {
}; };
Chain.prototype.fromJSON = function fromJSON(json) { Chain.prototype.fromJSON = function fromJSON(json) {
assert.equal(json.v, 1); assert.equal(json.v, 2);
assert.equal(json.type, 'chain'); assert.equal(json.type, 'chain');
assert.equal(json.network, network.type); assert.equal(json.network, network.type);

View File

@ -47,11 +47,11 @@ function Peer(pool, createSocket, options) {
if (this.options.backoff) { if (this.options.backoff) {
setTimeout(function() { setTimeout(function() {
self.socket = createSocket(self); self.socket = createSocket(self, pool);
self.emit('socket'); self.emit('socket');
}, this.options.backoff); }, this.options.backoff);
} else { } else {
this.socket = createSocket(this); this.socket = createSocket(this, pool);
} }
this._broadcast = { this._broadcast = {

View File

@ -46,7 +46,7 @@ function Pool(options) {
if (!this.options.fullNode) { if (!this.options.fullNode) {
if (this.options.headers == null) if (this.options.headers == null)
this.options.headers = false; this.options.headers = true;
if (this.options.multiplePeers == null) if (this.options.multiplePeers == null)
this.options.multiplePeers = true; this.options.multiplePeers = true;
} else { } else {
@ -56,6 +56,9 @@ function Pool(options) {
this.options.multiplePeers = false; this.options.multiplePeers = false;
} }
if (!this.options.headers)
this.options.multiplePeers = false;
this.backoff = { this.backoff = {
delta: options.backoffDelta || 500, delta: options.backoffDelta || 500,
max: options.backoffMax || 5000 max: options.backoffMax || 5000
@ -76,12 +79,11 @@ function Pool(options) {
this.maxRetries = options.maxRetries || 42; this.maxRetries = options.maxRetries || 42;
this.requestTimeout = options.requestTimeout || 10000; this.requestTimeout = options.requestTimeout || 10000;
Chain = this.options.fullNode Chain = bcoin.fullChain;
? bcoin.fullChain
: bcoin.spvChain;
this.chain = new Chain({ this.chain = new Chain({
storage: this.storage storage: this.storage,
fullNode: this.options.fullNode
}); });
this.watchMap = {}; this.watchMap = {};
@ -322,14 +324,14 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
assert(this.options.headers); assert(this.options.headers);
if (headers.length === 0)
return;
this.emit('debug', this.emit('debug',
'Recieved %s headers from %s', 'Recieved %s headers from %s',
headers.length, headers.length,
peer.address); peer.address);
if (headers.length === 0)
return;
if (headers.length > 2000) { if (headers.length > 2000) {
peer.destroy(); peer.destroy();
return; return;
@ -383,14 +385,14 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
assert(!this.options.headers); assert(!this.options.headers);
if (hashes.length === 0)
return;
this.emit('debug', this.emit('debug',
'Recieved %s block hashes from %s', 'Recieved %s block hashes from %s',
hashes.length, hashes.length,
peer.address); peer.address);
if (hashes.length === 0)
return;
if (hashes.length > 500) { if (hashes.length > 500) {
peer.destroy(); peer.destroy();
return; return;

View File

@ -106,7 +106,30 @@ main.genesis = {
main.magic = 0xd9b4bef9; main.magic = 0xd9b4bef9;
main.preload = require('./preload'); main.preload = {
v: 2,
type: 'chain',
network: main.type,
entries: [
{
hash: utils.toHex(main.genesis._hash),
version: main.genesis.version,
// prevBlock: utils.toHex(main.genesis.prevBlock),
ts: main.genesis.ts,
bits: main.genesis.bits,
height: 0
}
]
};
try {
main._preload = require('./preload');
utils.assert(main._preload.entries[0]);
main.preload = main._preload;
delete main._preload;
} catch (e) {
delete main._preload;
}
main.powLimit = new bn( main.powLimit = new bn(
'00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff', '00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
@ -191,11 +214,19 @@ testnet.genesis = {
testnet.magic = 0x0709110b; testnet.magic = 0x0709110b;
testnet.preload = { testnet.preload = {
'v': 1, v: 2,
'type': 'chain', type: 'chain',
'hashes': [utils.toHex(testnet.genesis._hash)], network: testnet.type,
'ts': [testnet.genesis.ts], entries: [
'heights': [0] {
hash: utils.toHex(testnet.genesis._hash),
version: testnet.genesis.version,
// prevBlock: utils.toHex(testnet.genesis.prevBlock),
ts: testnet.genesis.ts,
bits: testnet.genesis.bits,
height: 0
}
]
}; };
testnet.powLimit = new bn( testnet.powLimit = new bn(

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ var bcoin = require('../');
var addrs = bcoin.protocol.network.seeds.slice(); var addrs = bcoin.protocol.network.seeds.slice();
var pool = bcoin.pool({ var pool = bcoin.pool({
size: 32, size: 6,
redundancy: 1, redundancy: 1,
parallel: 4000, parallel: 4000,
loadWindow: 750, loadWindow: 750,