misc fixes.
This commit is contained in:
parent
56f68983d3
commit
a9ec49f954
@ -187,11 +187,14 @@ Chain.prototype.__defineGetter__('height', function() {
|
||||
|
||||
Chain.prototype._lock = function _lock(func, args, force) {
|
||||
var self = this;
|
||||
var block;
|
||||
var block, called;
|
||||
|
||||
if (force) {
|
||||
assert(this.busy);
|
||||
return function() {};
|
||||
return function unlock() {
|
||||
assert(!called);
|
||||
called = true;
|
||||
};
|
||||
}
|
||||
|
||||
if (this.busy) {
|
||||
@ -214,6 +217,9 @@ Chain.prototype._lock = function _lock(func, args, force) {
|
||||
return function unlock() {
|
||||
var item, block;
|
||||
|
||||
assert(!called);
|
||||
called = true;
|
||||
|
||||
self.busy = false;
|
||||
|
||||
if (func === Chain.prototype.add) {
|
||||
@ -584,9 +590,6 @@ Chain.prototype._checkDuplicates = function _checkDuplicates(block, prev, callba
|
||||
|
||||
// BIP30 - Ensure there are no duplicate txids
|
||||
self.blockdb.hasTX(hash, function(err, result) {
|
||||
if (called)
|
||||
return;
|
||||
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
@ -759,8 +762,6 @@ Chain.prototype.resetHeight = function resetHeight(height, force) {
|
||||
// no longer need.
|
||||
this.purgeOrphans();
|
||||
this.purgePending();
|
||||
|
||||
unlock();
|
||||
};
|
||||
|
||||
Chain.prototype.resetHeightAsync = function resetHeightAsync(height, callback, force) {
|
||||
@ -1262,6 +1263,9 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
if (self.orphan.size > self.orphanLimit)
|
||||
self.pruneOrphans();
|
||||
|
||||
// Keep track of total blocks handled.
|
||||
self.total += total;
|
||||
|
||||
// We intentionally did not asyncify the
|
||||
// callback so if it calls chain.add, it
|
||||
// still gets added to the queue. The
|
||||
@ -1269,15 +1273,11 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
// so we don't cause a stack overflow if
|
||||
// these end up being all sync chain.adds.
|
||||
utils.nextTick(function() {
|
||||
// XXX Possibly put `unlock()` above callback!
|
||||
unlock();
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
callback(null, total);
|
||||
|
||||
self.total += total;
|
||||
|
||||
unlock();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -123,8 +123,7 @@ ChainDB.prototype.load = function load(start, callback) {
|
||||
utils.debug(
|
||||
'Blockchain is corrupt after height %d. Resetting.',
|
||||
height);
|
||||
self.resetHeightAsync(height, callback);
|
||||
return;
|
||||
return self.resetHeightAsync(height, callback);
|
||||
}
|
||||
utils.debug('Chain successfully loaded.');
|
||||
callback();
|
||||
@ -157,6 +156,7 @@ ChainDB.prototype.closeSync = function closeSync() {
|
||||
this.ramdisk = null;
|
||||
return;
|
||||
}
|
||||
|
||||
fs.close(this.fd);
|
||||
this.fd = null;
|
||||
};
|
||||
@ -174,6 +174,7 @@ ChainDB.prototype.closeAsync = function closeAsync(callback) {
|
||||
fs.close(this.fd, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.fd = null;
|
||||
return callback();
|
||||
});
|
||||
@ -349,7 +350,7 @@ ChainDB.prototype.saveSync = function saveSync(entry) {
|
||||
|
||||
if (entry.height * BLOCK_SIZE !== this.size) {
|
||||
utils.debug('Warning attempt to write to height: %d/%d', this.height);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache the past 1001 blocks in memory
|
||||
@ -402,8 +403,10 @@ ChainDB.prototype.saveAsync = function saveAsync(entry, callback) {
|
||||
return callback(err);
|
||||
|
||||
assert(self.queue[entry.height]);
|
||||
|
||||
delete self.queue[entry.height];
|
||||
self.queueSize--;
|
||||
|
||||
if (self.queueSize === 0)
|
||||
self.emit('flush');
|
||||
|
||||
@ -411,44 +414,39 @@ ChainDB.prototype.saveAsync = function saveAsync(entry, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
ChainDB.prototype._drop = function _drop(height) {
|
||||
assert(height >= 0);
|
||||
|
||||
// Potential race condition here. Not sure how
|
||||
// to handle this.
|
||||
if (this.queue[height]) {
|
||||
utils.debug('Warning: write job in progress.');
|
||||
// delete this.queue[height];
|
||||
}
|
||||
|
||||
delete this.cache[height];
|
||||
};
|
||||
|
||||
ChainDB.prototype.resetHeightSync = function resetHeightSync(height) {
|
||||
var self = this;
|
||||
var size, count, existing;
|
||||
var osize = this.size;
|
||||
var ohighest = this.highest;
|
||||
var otip = this.tip;
|
||||
var size, count, existing;
|
||||
|
||||
if (typeof height === 'string')
|
||||
height = this.heightLookup[height];
|
||||
|
||||
assert(height >= 0);
|
||||
assert(this.tip);
|
||||
|
||||
size = (height + 1) * BLOCK_SIZE;
|
||||
count = this.getSize();
|
||||
|
||||
if (height > count - 1)
|
||||
throw new Error('Height too high.');
|
||||
|
||||
if (height === count - 1)
|
||||
return;
|
||||
|
||||
assert(height <= count - 1);
|
||||
assert(this.tip);
|
||||
|
||||
for (i = height + 1; i < count; i++) {
|
||||
existing = this.getSync(i);
|
||||
|
||||
assert(existing);
|
||||
this._drop(i);
|
||||
|
||||
// Warn of potential race condition
|
||||
// (handled with _onFlush).
|
||||
if (this.queue[i])
|
||||
utils.debug('Warning: write job in progress.');
|
||||
|
||||
delete this.cache[i];
|
||||
delete this.heightLookup[existing.hash];
|
||||
}
|
||||
|
||||
@ -481,28 +479,29 @@ ChainDB.prototype.resetHeightSync = function resetHeightSync(height) {
|
||||
|
||||
ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback) {
|
||||
var self = this;
|
||||
var size, count, pending, called;
|
||||
var osize = this.size;
|
||||
var ohighest = this.highest;
|
||||
var otip = this.tip;
|
||||
var size, count, pending, called;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (typeof height === 'string')
|
||||
height = this.heightLookup[height];
|
||||
|
||||
assert(height >= 0);
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
assert(this.tip);
|
||||
|
||||
size = (height + 1) * BLOCK_SIZE;
|
||||
count = this.getSize();
|
||||
pending = count - (height + 1);
|
||||
|
||||
if (height > count - 1)
|
||||
return callback(new Error('Height too high'));
|
||||
|
||||
if (height === count - 1)
|
||||
return callback();
|
||||
|
||||
assert(height <= count - 1);
|
||||
assert(this.tip);
|
||||
|
||||
// Prevent any more writes
|
||||
// by setting this early.
|
||||
this.size = size;
|
||||
@ -527,8 +526,14 @@ ChainDB.prototype.resetHeightAsync = function resetHeightAsync(height, callback)
|
||||
|
||||
assert(existing);
|
||||
|
||||
self._drop(i);
|
||||
// Warn of potential race condition
|
||||
// (handled with _onFlush).
|
||||
if (self.queue[i])
|
||||
utils.debug('Warning: write job in progress.');
|
||||
|
||||
delete self.cache[i];
|
||||
delete self.heightLookup[existing.hash];
|
||||
|
||||
if (!--pending)
|
||||
done();
|
||||
}, true);
|
||||
|
||||
@ -19,7 +19,7 @@ var fs = bcoin.fs;
|
||||
* Mempool
|
||||
*/
|
||||
|
||||
function Mempool(pool, options) {
|
||||
function Mempool(node, options) {
|
||||
if (!(this instanceof Mempool))
|
||||
return new Mempool(pool, options);
|
||||
|
||||
@ -27,8 +27,8 @@ function Mempool(pool, options) {
|
||||
options = {};
|
||||
|
||||
this.options = options;
|
||||
this.pool = pool;
|
||||
this.blockdb = pool.blockdb;
|
||||
this.node = node;
|
||||
this.blockdb = node.blockdb;
|
||||
|
||||
this.txs = {};
|
||||
this.spent = {};
|
||||
@ -235,7 +235,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
data: tx.hash(),
|
||||
reason: 'non-standard'
|
||||
});
|
||||
pool.setMisbehavior(peer, 100);
|
||||
self.node.pool.setMisbehavior(peer, 100);
|
||||
return callback(new Error('TX is not standard.'));
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
data: tx.hash(),
|
||||
reason: 'non-standard-inputs'
|
||||
});
|
||||
pool.setMisbehavior(peer, 100);
|
||||
self.node.pool.setMisbehavior(peer, 100);
|
||||
return callback(new Error('TX inputs are not standard.'));
|
||||
}
|
||||
|
||||
@ -255,11 +255,11 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
data: tx.hash(),
|
||||
reason: 'nonexistent-coins'
|
||||
});
|
||||
pool.setMisbehavior(peer, 100);
|
||||
self.node.pool.setMisbehavior(peer, 100);
|
||||
return callback(new Error('TX is spending coins that it does not have.'));
|
||||
}
|
||||
|
||||
height = self.pool.chain.height + 1;
|
||||
height = self.node.pool.chain.height + 1;
|
||||
ts = utils.now();
|
||||
if (!tx.isFinal(height, ts)) {
|
||||
return callback(new Error('TX is not final.'));
|
||||
@ -267,7 +267,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
data: tx.hash(),
|
||||
reason: 'not-final'
|
||||
});
|
||||
pool.setMisbehavior(peer, 100);
|
||||
self.node.pool.setMisbehavior(peer, 100);
|
||||
return callback(new Error('TX is not final.'));
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
data: tx.hash(),
|
||||
reason: 'negative-value'
|
||||
});
|
||||
pool.setMisbehavior(peer, 100);
|
||||
self.node.pool.setMisbehavior(peer, 100);
|
||||
return callback(new Error('TX is spending negative coins.'));
|
||||
}
|
||||
}
|
||||
@ -310,7 +310,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
data: tx.hash(),
|
||||
reason: 'script-failed'
|
||||
});
|
||||
pool.setMisbehavior(peer, 100);
|
||||
self.node.pool.setMisbehavior(peer, 100);
|
||||
return callback(new Error('TX did not verify.'));
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ var EventEmitter = require('events').EventEmitter;
|
||||
* Miner
|
||||
*/
|
||||
|
||||
function Miner(options) {
|
||||
function Miner(pool, options) {
|
||||
if (!(this instanceof Miner))
|
||||
return new Miner(options);
|
||||
|
||||
@ -30,15 +30,17 @@ function Miner(options) {
|
||||
this.address = this.options.address;
|
||||
this.msg = this.options.msg || 'mined by bcoin';
|
||||
|
||||
this.pool = options.pool || bcoin.pool.global;
|
||||
this.chain = options.chain || this.pool.chain || bcoin.chain.global;
|
||||
this.pool = pool || bcoin.pool.global;
|
||||
this.chain = this.pool.chain;
|
||||
this.mempool = this.pool.mempool;
|
||||
this.blockdb = this.pool.blockdb;
|
||||
|
||||
this.running = false;
|
||||
this.timeout = null;
|
||||
this.interval = null;
|
||||
|
||||
this.fee = new bn(0);
|
||||
this.last = this.chain.getTip();
|
||||
this.last = this.chain.tip;
|
||||
this.block = null;
|
||||
this.iterations = 0;
|
||||
this._begin = utils.now();
|
||||
@ -51,18 +53,26 @@ inherits(Miner, EventEmitter);
|
||||
Miner.prototype._init = function _init() {
|
||||
var self = this;
|
||||
|
||||
this.pool.on('tx', function(tx) {
|
||||
self.addTX(tx);
|
||||
});
|
||||
if (this.mempool) {
|
||||
this.mempool.on('tx', function(tx) {
|
||||
if (!self.running)
|
||||
return;
|
||||
self.addTX(tx);
|
||||
});
|
||||
} else {
|
||||
this.pool.on('tx', function(tx) {
|
||||
if (!self.running)
|
||||
return;
|
||||
self.addTX(tx);
|
||||
});
|
||||
}
|
||||
|
||||
this.chain.on('block', function(block) {
|
||||
this.chain.on('add block', function(block) {
|
||||
if (!self.running)
|
||||
return;
|
||||
self.addBlock(block);
|
||||
});
|
||||
|
||||
// this.chain.on('tip', function(entry) {
|
||||
// self.addBlock(entry);
|
||||
// });
|
||||
|
||||
this.on('block', function(block) {
|
||||
utils.debug(
|
||||
'Found block: %d (%s)',
|
||||
@ -123,7 +133,10 @@ Miner.prototype.add = function add(msg) {
|
||||
|
||||
Miner.prototype.addBlock = function addBlock(block) {
|
||||
if (!block)
|
||||
block = this.chain.getTip();
|
||||
block = this.chain.tip;
|
||||
|
||||
if (!this.last)
|
||||
this.last = this.chain.tip;
|
||||
|
||||
// Somebody found the next block before
|
||||
// us, start over with the new target.
|
||||
@ -222,7 +235,7 @@ Miner.prototype.createBlock = function createBlock(tx) {
|
||||
seq: 0xffffffff
|
||||
});
|
||||
|
||||
if (script.getSize(coinbase.inputs[0].script) > 100)
|
||||
if (bcoin.script.getSize(coinbase.inputs[0].script) > 100)
|
||||
throw new Error('Coinbase script is too large');
|
||||
|
||||
coinbase.addOutput({
|
||||
|
||||
@ -39,6 +39,7 @@ function Node(options) {
|
||||
this.mempool = null;
|
||||
this.pool = null;
|
||||
this.chain = null;
|
||||
this.miner = null;
|
||||
|
||||
Node.global = this;
|
||||
|
||||
@ -50,18 +51,19 @@ inherits(Node, EventEmitter);
|
||||
Node.prototype._init = function _init() {
|
||||
var self = this;
|
||||
|
||||
this.blockdb = new bcoin.blockdb(this.options.blockdb);
|
||||
this.mempool = new bcoin.mempool(this, this.options.mempool);
|
||||
|
||||
if (!this.options.pool)
|
||||
this.options.pool = {};
|
||||
|
||||
this.blockdb = new bcoin.blockdb(this.options.blockdb);
|
||||
this.mempool = new bcoin.mempool(this, this.options.mempool);
|
||||
|
||||
this.options.pool.spv = false;
|
||||
this.options.pool.blockdb = this.blockdb;
|
||||
this.options.pool.mempool = this.mempool;
|
||||
|
||||
this.pool = new bcoin.pool(this.options.pool);
|
||||
this.chain = this.pool.chain;
|
||||
this.miner = new bcoin.miner(this.pool, this.options.miner);
|
||||
|
||||
this.mempool.on('error', function(err) {
|
||||
self.emit('error', err);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user