more pool work. wallet.fill().
This commit is contained in:
parent
1e027220c3
commit
999cfefe54
@ -45,6 +45,10 @@ function Peer(pool, createConnection, options) {
|
||||
this.challenge = null;
|
||||
this.lastPong = 0;
|
||||
|
||||
this.banscore = 0;
|
||||
this.orphans = 0;
|
||||
this.orphanTime = 0;
|
||||
|
||||
this.socket = createConnection.call(pool, this, options);
|
||||
if (!this.socket)
|
||||
throw new Error('No socket');
|
||||
@ -103,7 +107,7 @@ Peer.prototype._init = function init() {
|
||||
|
||||
this.socket.once('error', function(err) {
|
||||
self._error(err);
|
||||
self.pool.misbehaving(self, 100);
|
||||
self.pool.setMisbehavior(self, 100);
|
||||
});
|
||||
|
||||
this.socket.once('close', function() {
|
||||
@ -123,7 +127,7 @@ Peer.prototype._init = function init() {
|
||||
self._error(err);
|
||||
// Something is wrong here.
|
||||
// Ignore this peer.
|
||||
self.pool.misbehaving(self, 100);
|
||||
self.pool.setMisbehavior(self, 100);
|
||||
});
|
||||
|
||||
if (this.pool.options.fullNode) {
|
||||
|
||||
@ -194,7 +194,7 @@ Pool.prototype._init = function _init() {
|
||||
|
||||
// If we failed a checkpoint, peer is misbehaving.
|
||||
if (data.checkpoint) {
|
||||
self.misbehaving(peer, 100);
|
||||
self.setMisbehavior(peer, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ Pool.prototype._init = function _init() {
|
||||
if (!peer)
|
||||
return;
|
||||
|
||||
self.misbehaving(peer, 100);
|
||||
self.setMisbehavior(peer, 100);
|
||||
});
|
||||
|
||||
this.options.wallets.forEach(function(w) {
|
||||
@ -292,7 +292,7 @@ Pool.prototype._stopInterval = function _stopInterval() {
|
||||
Pool.prototype.createConnection = function createConnection(peer, options) {
|
||||
var addr, net, socket;
|
||||
|
||||
addr = this.getSeed(options.priority, true);
|
||||
addr = this.getSeed(options.priority);
|
||||
|
||||
assert(addr);
|
||||
assert(addr.host);
|
||||
@ -441,7 +441,7 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
|
||||
peer.host);
|
||||
|
||||
if (headers.length > 2000) {
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ Pool.prototype._handleHeaders = function _handleHeaders(headers, peer) {
|
||||
// simply tries to find the latest block in
|
||||
// the peer's chain.
|
||||
if (last && headers.length === 2000)
|
||||
peer.loadHeaders(this.chain.locatorHashes(last), null);
|
||||
peer.loadHeaders(this.chain.getLocator(last), null);
|
||||
|
||||
// Reset interval to avoid calling getheaders unnecessarily
|
||||
this._startInterval();
|
||||
@ -499,7 +499,7 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
|
||||
peer.host);
|
||||
|
||||
if (hashes.length > 500) {
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -511,15 +511,15 @@ Pool.prototype._handleBlocks = function _handleBlocks(hashes, peer) {
|
||||
if (this.chain.hasOrphan(hash)) {
|
||||
// Make sure the peer doesn't send us
|
||||
// more than 200 orphans every 3 minutes.
|
||||
if (this.orphaning(peer)) {
|
||||
if (this.isOrphaning(peer)) {
|
||||
utils.debug('Peer is orphaning (%s)', peer.host);
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve orphan chain.
|
||||
peer.loadBlocks(
|
||||
this.chain.locatorHashes(),
|
||||
this.chain.getLocator(),
|
||||
this.chain.getOrphanRoot(hash)
|
||||
);
|
||||
continue;
|
||||
@ -553,7 +553,7 @@ Pool.prototype._handleInv = function _handleInv(hashes, peer) {
|
||||
hash = utils.toHex(hashes[i]);
|
||||
if (!this.chain.has(hash)) {
|
||||
if (this.options.headers)
|
||||
this.peers.load.loadHeaders(this.chain.locatorHashes(), hash);
|
||||
this.peers.load.loadHeaders(this.chain.getLocator(), hash);
|
||||
else
|
||||
this._request(peer, this.block.type, hash);
|
||||
}
|
||||
@ -579,7 +579,7 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
// Someone might be sending us bad blocks to DoS us.
|
||||
if (this.block.invalid[block.hash('hex')]) {
|
||||
utils.debug('Peer is sending an invalid chain (%s)', peer.host);
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -589,14 +589,14 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
utils.debug(
|
||||
'Peer is sending an invalid continuation chain (%s)',
|
||||
peer.host);
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore if we already have.
|
||||
if (this.chain.has(block)) {
|
||||
utils.debug('Already have block %s (%s)', block.height, peer.host);
|
||||
this.misbehaving(peer, 1);
|
||||
this.setMisbehavior(peer, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -606,7 +606,7 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
'Block verification failed for %s (%s)',
|
||||
block.rhash, peer.host);
|
||||
this.block.invalid[block.hash('hex')] = true;
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -627,9 +627,9 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
|
||||
// Make sure the peer doesn't send us
|
||||
// more than 200 orphans every 3 minutes.
|
||||
if (this.orphaning(peer)) {
|
||||
if (this.isOrphaning(peer)) {
|
||||
utils.debug('Peer is orphaning (%s)', peer.host);
|
||||
this.misbehaving(peer, 100);
|
||||
this.setMisbehavior(peer, 100);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -642,7 +642,7 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
|
||||
// Resolve orphan chain.
|
||||
this.peers.load.loadBlocks(
|
||||
this.chain.locatorHashes(),
|
||||
this.chain.getLocator(),
|
||||
this.chain.getOrphanRoot(block)
|
||||
);
|
||||
|
||||
@ -658,7 +658,7 @@ Pool.prototype._handleBlock = function _handleBlock(block, peer) {
|
||||
|
||||
// Increase banscore by 10 if we're using getheaders.
|
||||
if (!this.options.multiplePeers) {
|
||||
if (this.misbehaving(peer, 10))
|
||||
if (this.setMisbehavior(peer, 10))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -699,12 +699,15 @@ Pool.prototype._load = function _load() {
|
||||
}
|
||||
|
||||
if (this.options.headers)
|
||||
this.peers.load.loadHeaders(this.chain.locatorHashes(), null);
|
||||
this.peers.load.loadHeaders(this.chain.getLocator(), null);
|
||||
else
|
||||
this.peers.load.loadBlocks(this.chain.locatorHashes(), null);
|
||||
this.peers.load.loadBlocks(this.chain.getLocator(), null);
|
||||
};
|
||||
|
||||
Pool.prototype.loadMempool = function loadMempool() {
|
||||
if (this.peers.load)
|
||||
this.peers.load.loadMempool();
|
||||
|
||||
this.peers.block.forEach(function(peer) {
|
||||
peer.loadMempool();
|
||||
});
|
||||
@ -719,8 +722,6 @@ Pool.prototype._createPeer = function _createPeer(priority) {
|
||||
priority: priority
|
||||
});
|
||||
|
||||
peer._retry = 0;
|
||||
|
||||
peer.on('error', function(err) {
|
||||
self.emit('error', err, peer);
|
||||
});
|
||||
@ -747,12 +748,10 @@ Pool.prototype._createPeer = function _createPeer(priority) {
|
||||
});
|
||||
|
||||
peer.on('tx', function(tx) {
|
||||
var state = self.tx.state[tx.hash('hex')];
|
||||
var requested = self._response(tx);
|
||||
var added = self._addTX(tx, 1);
|
||||
|
||||
self._response(tx);
|
||||
self._addTX(tx, 1);
|
||||
|
||||
if (state !== 1 || tx.block)
|
||||
if (added || tx.block)
|
||||
self.emit('tx', tx, peer);
|
||||
|
||||
if (!self.options.fullNode && tx.block)
|
||||
@ -760,6 +759,9 @@ Pool.prototype._createPeer = function _createPeer(priority) {
|
||||
});
|
||||
|
||||
peer.on('addr', function(data) {
|
||||
if (self.options.discoverPeers === false)
|
||||
return;
|
||||
|
||||
if (self.seeds.length > 1000)
|
||||
self.setSeeds(self.seeds.slice(-500));
|
||||
|
||||
@ -1482,14 +1484,14 @@ Pool.prototype.getPeer = function getPeer(addr) {
|
||||
}
|
||||
};
|
||||
|
||||
Pool.prototype.getSeed = function getSeed(priority, connecting) {
|
||||
Pool.prototype.getSeed = function getSeed(priority) {
|
||||
var i, addr;
|
||||
var original = this.originalSeeds;
|
||||
var seeds = this.seeds;
|
||||
var all = original.concat(seeds);
|
||||
|
||||
// Hang back if we don't have a loader peer yet.
|
||||
if (!connecting && !priority && !this.peers.load)
|
||||
if (!priority && !this.peers.load)
|
||||
return;
|
||||
|
||||
// Randomize the non-original peers.
|
||||
@ -1551,7 +1553,7 @@ Pool.prototype.getSeed = function getSeed(priority, connecting) {
|
||||
// If we have no block peers, always return
|
||||
// an address.
|
||||
if (!priority) {
|
||||
if (all.length === 1 || connecting)
|
||||
if (all.length === 1)
|
||||
return all[Math.random() * (all.length - 1) | 0];
|
||||
}
|
||||
|
||||
@ -1561,22 +1563,13 @@ Pool.prototype.getSeed = function getSeed(priority, connecting) {
|
||||
utils.debug(
|
||||
'We had to connect to a random peer. Something is not right.');
|
||||
|
||||
return original[Math.random() * (original.length - 1) | 0];
|
||||
return all[Math.random() * (all.length - 1) | 0];
|
||||
}
|
||||
};
|
||||
|
||||
Pool.prototype.setSeeds = function setSeeds(seeds) {
|
||||
this.seeds = [];
|
||||
this.hosts = {};
|
||||
|
||||
// Remove all seeds from misbehaving aside
|
||||
// from original seeds that may be in it.
|
||||
// this.peers.misbehaving = this.originalSeeds.reduce(function(out, addr) {
|
||||
// if (this.peers.misbehaving[addr.host])
|
||||
// out[addr.host] = this.peers.misbehaving[addr.host];
|
||||
// return out;
|
||||
// }, {}, this);
|
||||
|
||||
seeds.forEach(function(seed) {
|
||||
this.addSeed(seed);
|
||||
}, this);
|
||||
@ -1593,7 +1586,7 @@ Pool.prototype.addSeed = function addSeed(seed) {
|
||||
port: seed.port
|
||||
});
|
||||
|
||||
this.hosts[seed.host] = this.seeds.length - 1;
|
||||
this.hosts[seed.host] = true;
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -1604,40 +1597,36 @@ Pool.prototype.removeSeed = function removeSeed(seed) {
|
||||
if (this.hosts[seed.host] == null)
|
||||
return false;
|
||||
|
||||
this.seeds.splice(this.hosts[seed.host], 1);
|
||||
for (i = 0; i < this.seeds.length; i++) {
|
||||
if (this.seeds[i].host === seed.host) {
|
||||
this.seeds.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete this.hosts[seed.host];
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Pool.prototype.orphaning = function orphaning(peer) {
|
||||
if (!peer._orphanTime)
|
||||
peer._orphanTime = utils.now();
|
||||
|
||||
if (!peer._orphans)
|
||||
peer._orphans = 0;
|
||||
|
||||
if (utils.now() > peer._orphanTime + 3 * 60) {
|
||||
peer._orphans = 0;
|
||||
peer._orphanTime = utils.now();
|
||||
Pool.prototype.isOrphaning = function isOrphaning(peer) {
|
||||
if (utils.now() > peer.orphanTime + 3 * 60) {
|
||||
peer.orphans = 0;
|
||||
peer.orphanTime = utils.now();
|
||||
}
|
||||
|
||||
peer._orphans += 1;
|
||||
peer.orphans += 1;
|
||||
|
||||
if (peer._orphans > 200)
|
||||
if (peer.orphans > 200)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Pool.prototype.misbehaving = function misbehaving(peer, dos) {
|
||||
if (!peer._banscore)
|
||||
peer._banscore = 0;
|
||||
Pool.prototype.setMisbehavior = function setMisbehavior(peer, dos) {
|
||||
peer.banscore += dos;
|
||||
|
||||
peer._banscore += dos;
|
||||
|
||||
if (peer._banscore >= constants.banScore) {
|
||||
if (peer.banscore >= constants.banScore) {
|
||||
this.peers.misbehaving[peer.host] = utils.now();
|
||||
utils.debug('Ban threshold exceeded for %s', peer.host);
|
||||
peer.destroy();
|
||||
@ -1660,7 +1649,7 @@ Pool.prototype.isMisbehaving = function isMisbehaving(host) {
|
||||
delete this.peers.misbehaving[host];
|
||||
peer = this.getPeer(host);
|
||||
if (peer)
|
||||
peer._banscore = 0;
|
||||
peer.banscore = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -594,30 +594,11 @@ Wallet.prototype.balance = function balance() {
|
||||
return this.tx.balance();
|
||||
};
|
||||
|
||||
Wallet.prototype.fill = function fill(tx, changeAddress, cb) {
|
||||
var result, err;
|
||||
|
||||
if (typeof changeAddress === 'function') {
|
||||
cb = changeAddress;
|
||||
changeAddress = null;
|
||||
}
|
||||
|
||||
cb = utils.asyncify(cb);
|
||||
|
||||
result = this.fillUnspent(tx, changeAddress);
|
||||
|
||||
if (!result.inputs) {
|
||||
err = new Error('Not enough funds');
|
||||
err.minBalance = result.total;
|
||||
cb(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
this.sign(tx);
|
||||
|
||||
cb(null, tx);
|
||||
|
||||
return tx;
|
||||
Wallet.prototype.fill = function fill(tx, changeAddress, fee) {
|
||||
var result = this.fillUnspent(tx, changeAddress, fee);
|
||||
if (!result.inputs)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
Wallet.prototype.toAddress = function toAddress() {
|
||||
|
||||
@ -181,25 +181,22 @@ describe('Wallet', function() {
|
||||
|
||||
// Create new transaction
|
||||
var t2 = bcoin.tx().out(w2, 5460);
|
||||
w1.fill(t2, function(err) {
|
||||
assert(!err);
|
||||
assert(t2.verify());
|
||||
assert(w1.fill(t2));
|
||||
w1.sign(t2);
|
||||
assert(t2.verify());
|
||||
|
||||
assert.equal(t2.funds('in').toString(10), 16380);
|
||||
// If change < dust and is added to outputs:
|
||||
// assert.equal(t2.funds('out').toString(10), 6380);
|
||||
// If change < dust and is added to fee:
|
||||
assert.equal(t2.funds('out').toString(10), 5460);
|
||||
assert.equal(t2.funds('in').toString(10), 16380);
|
||||
// If change < dust and is added to outputs:
|
||||
// assert.equal(t2.funds('out').toString(10), 6380);
|
||||
// If change < dust and is added to fee:
|
||||
assert.equal(t2.funds('out').toString(10), 5460);
|
||||
|
||||
// Create new transaction
|
||||
var t3 = bcoin.tx().out(w2, 15000);
|
||||
w1.fill(t3, function(err) {
|
||||
assert(err);
|
||||
assert.equal(err.minBalance.toString(10), 25000);
|
||||
// Create new transaction
|
||||
var t3 = bcoin.tx().out(w2, 15000);
|
||||
assert(!w1.fill(t3));
|
||||
assert.equal(t3.total.toString(10), 25000);
|
||||
|
||||
cb();
|
||||
});
|
||||
});
|
||||
cb();
|
||||
});
|
||||
|
||||
it('should sign multiple inputs using different keys', function(cb) {
|
||||
@ -335,6 +332,7 @@ describe('Wallet', function() {
|
||||
assert(!send.verify());
|
||||
var result = w1.fill(send);
|
||||
assert(result);
|
||||
w1.sign(send);
|
||||
|
||||
// printScript(send.inputs[0]);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user