misc. alert.
This commit is contained in:
parent
85af68d2ef
commit
e1fd556ff6
@ -1231,8 +1231,10 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
self.total += total;
|
self.total += total;
|
||||||
|
|
||||||
// Take heap snapshot for debugging.
|
// Take heap snapshot for debugging.
|
||||||
if (self.total % 20 === 0)
|
if (self.total % 20 === 0) {
|
||||||
bcoin.profiler.snapshot();
|
bcoin.profiler.snapshot();
|
||||||
|
utils.gc();
|
||||||
|
}
|
||||||
|
|
||||||
utils.nextTick(function() {
|
utils.nextTick(function() {
|
||||||
if (self.isFull())
|
if (self.isFull())
|
||||||
|
|||||||
@ -411,6 +411,9 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
|||||||
if (cmd === 'reject')
|
if (cmd === 'reject')
|
||||||
return this._handleReject(payload);
|
return this._handleReject(payload);
|
||||||
|
|
||||||
|
if (cmd === 'alert')
|
||||||
|
return this._handleAlert(payload);
|
||||||
|
|
||||||
if (cmd === 'block') {
|
if (cmd === 'block') {
|
||||||
payload = bcoin.compactblock(payload);
|
payload = bcoin.compactblock(payload);
|
||||||
} else if (cmd === 'merkleblock') {
|
} else if (cmd === 'merkleblock') {
|
||||||
@ -589,29 +592,23 @@ Peer.prototype._handleInv = function handleInv(items) {
|
|||||||
|
|
||||||
this.emit('inv', items);
|
this.emit('inv', items);
|
||||||
|
|
||||||
// Always request advertised TXs
|
|
||||||
txs = items.filter(function(item) {
|
txs = items.filter(function(item) {
|
||||||
return item.type === 'tx';
|
return item.type === 'tx';
|
||||||
});
|
}).map(function(item) {
|
||||||
|
|
||||||
// Emit new blocks to schedule them between multiple peers
|
|
||||||
blocks = items.filter(function(item) {
|
|
||||||
return item.type === 'block';
|
|
||||||
}, this).map(function(item) {
|
|
||||||
return item.hash;
|
return item.hash;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (blocks.length === 1)
|
blocks = items.filter(function(item) {
|
||||||
this.bestHash = utils.toHex(blocks[0]);
|
return item.type === 'block';
|
||||||
|
}).map(function(item) {
|
||||||
|
return item.hash;
|
||||||
|
});
|
||||||
|
|
||||||
this.emit('blocks', blocks);
|
if (blocks.length > 0)
|
||||||
|
this.emit('blocks', blocks);
|
||||||
|
|
||||||
if (txs.length === 0)
|
if (txs.length > 0)
|
||||||
return;
|
this.emit('txs', txs);
|
||||||
|
|
||||||
this.emit('txs', txs.map(function(tx) {
|
|
||||||
return tx.hash;
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Peer.prototype._handleHeaders = function handleHeaders(headers) {
|
Peer.prototype._handleHeaders = function handleHeaders(headers) {
|
||||||
@ -634,14 +631,20 @@ Peer.prototype._handleReject = function handleReject(payload) {
|
|||||||
entry.e.emit('reject', payload);
|
entry.e.emit('reject', payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Peer.prototype._handleAlert = function handleAlert(payload) {
|
||||||
|
this.emit('alert', payload);
|
||||||
|
};
|
||||||
|
|
||||||
Peer.prototype.getHeaders = function getHeaders(hashes, stop) {
|
Peer.prototype.getHeaders = function getHeaders(hashes, stop) {
|
||||||
utils.debug(
|
utils.debug(
|
||||||
'Requesting headers packet from %s with getheaders',
|
'Requesting headers packet from %s with getheaders',
|
||||||
this.host);
|
this.host);
|
||||||
|
|
||||||
utils.debug('Height: %s, Hash: %s, Stop: %s',
|
utils.debug('Height: %s, Hash: %s, Stop: %s',
|
||||||
this.pool.chain.getHeight(hashes[0]),
|
this.pool.chain.getHeight(hashes[0]),
|
||||||
hashes ? utils.revHex(hashes[0]) : 0,
|
hashes ? utils.revHex(hashes[0]) : 0,
|
||||||
stop ? utils.revHex(stop) : 0);
|
stop ? utils.revHex(stop) : 0);
|
||||||
|
|
||||||
this._write(this.framer.getHeaders(hashes, stop));
|
this._write(this.framer.getHeaders(hashes, stop));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -649,10 +652,12 @@ Peer.prototype.getBlocks = function getBlocks(hashes, stop) {
|
|||||||
utils.debug(
|
utils.debug(
|
||||||
'Requesting inv packet from %s with getblocks',
|
'Requesting inv packet from %s with getblocks',
|
||||||
this.host);
|
this.host);
|
||||||
|
|
||||||
utils.debug('Height: %s, Hash: %s, Stop: %s',
|
utils.debug('Height: %s, Hash: %s, Stop: %s',
|
||||||
this.pool.chain.getHeight(hashes[0]),
|
this.pool.chain.getHeight(hashes[0]),
|
||||||
hashes ? utils.revHex(hashes[0]) : 0,
|
hashes ? utils.revHex(hashes[0]) : 0,
|
||||||
stop ? utils.revHex(stop) : 0);
|
stop ? utils.revHex(stop) : 0);
|
||||||
|
|
||||||
this._write(this.framer.getBlocks(hashes, stop));
|
this._write(this.framer.getBlocks(hashes, stop));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -660,6 +665,7 @@ Peer.prototype.getMempool = function getMempool() {
|
|||||||
utils.debug(
|
utils.debug(
|
||||||
'Requesting inv packet from %s with mempool',
|
'Requesting inv packet from %s with mempool',
|
||||||
this.host);
|
this.host);
|
||||||
|
|
||||||
this._write(this.framer.mempool());
|
this._write(this.framer.mempool());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -679,8 +685,8 @@ Peer.prototype.setMisbehavior = function setMisbehavior(dos) {
|
|||||||
return this.pool.setMisbehavior(this, dos);
|
return this.pool.setMisbehavior(this, dos);
|
||||||
};
|
};
|
||||||
|
|
||||||
Peer.prototype.sendReject = function sendReject(obj, code, reason, dos) {
|
Peer.prototype.sendReject = function sendReject(obj, code, reason, score) {
|
||||||
return this.pool.reject(this, obj, code, reason, dos);
|
return this.pool.reject(this, obj, code, reason, score);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -804,6 +804,12 @@ Pool.prototype._createPeer = function _createPeer(options) {
|
|||||||
self.emit('reject', payload, peer);
|
self.emit('reject', payload, peer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
peer.on('alert', function(payload) {
|
||||||
|
utils.debug('Received alert from: %s', peer.host);
|
||||||
|
utils.debug(payload);
|
||||||
|
self.emit('alert', payload, peer);
|
||||||
|
});
|
||||||
|
|
||||||
peer.on('notfound', function(items) {
|
peer.on('notfound', function(items) {
|
||||||
items.forEach(function(item) {
|
items.forEach(function(item) {
|
||||||
var req = self.request.map[utils.toHex(item.hash)];
|
var req = self.request.map[utils.toHex(item.hash)];
|
||||||
@ -1850,8 +1856,8 @@ Pool.prototype.removeSeed = function removeSeed(seed) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
Pool.prototype.setMisbehavior = function setMisbehavior(peer, dos) {
|
Pool.prototype.setMisbehavior = function setMisbehavior(peer, score) {
|
||||||
peer.banScore += dos;
|
peer.banScore += score;
|
||||||
|
|
||||||
if (peer.banScore >= constants.banScore) {
|
if (peer.banScore >= constants.banScore) {
|
||||||
this.peers.misbehaving[peer.host] = utils.now();
|
this.peers.misbehaving[peer.host] = utils.now();
|
||||||
@ -1885,9 +1891,9 @@ Pool.prototype.isMisbehaving = function isMisbehaving(host) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Pool.prototype.reject = function reject(peer, obj, code, reason, dos) {
|
Pool.prototype.reject = function reject(peer, obj, code, reason, score) {
|
||||||
if (dos != null)
|
if (score != null)
|
||||||
peer.setMisbehavior(dos);
|
peer.setMisbehavior(score);
|
||||||
|
|
||||||
utils.debug('Rejecting %s %s: ccode=%s reason=%s',
|
utils.debug('Rejecting %s %s: ccode=%s reason=%s',
|
||||||
obj.type, obj.hash('hex'), code, reason);
|
obj.type, obj.hash('hex'), code, reason);
|
||||||
|
|||||||
@ -624,6 +624,49 @@ Framer.mempool = function mempool() {
|
|||||||
return new Buffer([]);
|
return new Buffer([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Framer.alert = function alert(data, writer) {
|
||||||
|
var p, i, payload;
|
||||||
|
|
||||||
|
if (!data.payload) {
|
||||||
|
p = new BufferWriter();
|
||||||
|
p.write32(data.version);
|
||||||
|
p.write64(data.relayUntil);
|
||||||
|
p.write64(data.expiration);
|
||||||
|
p.write32(data.id);
|
||||||
|
p.write32(data.cancel);
|
||||||
|
p.writeVarint(data.cancels.length);
|
||||||
|
for (i = 0; i < data.cancels.length; i++)
|
||||||
|
p.write32(data.cancels[i]);
|
||||||
|
p.write32(data.minVer);
|
||||||
|
p.write32(data.maxVer);
|
||||||
|
p.writeVarint(data.subVers.length);
|
||||||
|
for (i = 0; i < data.subVers.length; i++)
|
||||||
|
p.writeVarString(data.subVers[i], 'ascii');
|
||||||
|
p.write32(data.priority);
|
||||||
|
p.writeVarString(data.comment, 'ascii');
|
||||||
|
p.writeVarString(data.statusBar, 'ascii');
|
||||||
|
p.writeVarString('', 'ascii');
|
||||||
|
payload = p.render();
|
||||||
|
} else {
|
||||||
|
payload = data.payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = new BufferWriter(writer);
|
||||||
|
p.writeVarBytes(payload);
|
||||||
|
|
||||||
|
if (data.signature)
|
||||||
|
p.writeVarBytes(data.signature);
|
||||||
|
else if (data.key)
|
||||||
|
p.writeVarBytes(bcoin.ec.sign(payload, data.key));
|
||||||
|
else
|
||||||
|
assert(false, 'No key or signature.');
|
||||||
|
|
||||||
|
if (!writer)
|
||||||
|
p = p.render();
|
||||||
|
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -26,6 +26,7 @@ function Parser() {
|
|||||||
this.pendingTotal = 0;
|
this.pendingTotal = 0;
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.packet = null;
|
this.packet = null;
|
||||||
|
this.version = constants.minVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.inherits(Parser, EventEmitter);
|
utils.inherits(Parser, EventEmitter);
|
||||||
@ -64,6 +65,35 @@ Parser.prototype.feed = function feed(data) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.prototype._feed = function feed(data) {
|
||||||
|
var chunk;
|
||||||
|
|
||||||
|
while (data) {
|
||||||
|
this.pendingTotal += data.length;
|
||||||
|
this.pending.push(data);
|
||||||
|
|
||||||
|
if (this.pendingTotal < this.waiting)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.pending.length === 1)
|
||||||
|
chunk = this.pending[0];
|
||||||
|
else
|
||||||
|
chunk = Buffer.concat(this.pending);
|
||||||
|
|
||||||
|
if (chunk.length > this.waiting) {
|
||||||
|
data = chunk.slice(this.waiting);
|
||||||
|
chunk = chunk.slice(0, this.waiting);
|
||||||
|
//chunk = utils.slice(chunk, 0, this.waiting);
|
||||||
|
} else {
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pending.length = 0;
|
||||||
|
this.pendingTotal = 0;
|
||||||
|
this.parse(chunk);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Parser.prototype.parse = function parse(chunk) {
|
Parser.prototype.parse = function parse(chunk) {
|
||||||
if (chunk.length > constants.maxMessage)
|
if (chunk.length > constants.maxMessage)
|
||||||
return this._error('Packet too large: %dmb.', utils.mb(chunk.length));
|
return this._error('Packet too large: %dmb.', utils.mb(chunk.length));
|
||||||
@ -149,6 +179,9 @@ Parser.prototype.parsePayload = function parsePayload(cmd, p) {
|
|||||||
if (cmd === 'pong')
|
if (cmd === 'pong')
|
||||||
return Parser.parsePong(p);
|
return Parser.parsePong(p);
|
||||||
|
|
||||||
|
if (cmd === 'alert')
|
||||||
|
return Parser.parseAlert(p);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,11 +220,10 @@ Parser.parseVersion = function parseVersion(p) {
|
|||||||
agent = p.readVarString('ascii');
|
agent = p.readVarString('ascii');
|
||||||
height = p.read32();
|
height = p.read32();
|
||||||
|
|
||||||
try {
|
if (p.left() > 0)
|
||||||
relay = p.readU8() === 1;
|
relay = p.readU8() === 1;
|
||||||
} catch (e) {
|
else
|
||||||
relay = true;
|
relay = true;
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ts = ts.toNumber();
|
ts = ts.toNumber();
|
||||||
@ -209,6 +241,8 @@ Parser.parseVersion = function parseVersion(p) {
|
|||||||
assert(ts >= 0, 'Timestamp is negative.');
|
assert(ts >= 0, 'Timestamp is negative.');
|
||||||
assert(height >= 0, 'Height is negative.');
|
assert(height >= 0, 'Height is negative.');
|
||||||
|
|
||||||
|
this.version = version;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version: version,
|
version: version,
|
||||||
services: services,
|
services: services,
|
||||||
@ -322,8 +356,8 @@ Parser.parseBlock = function parseBlock(p) {
|
|||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
version = p.read32();
|
version = p.read32();
|
||||||
prevBlock = p.readHash();
|
prevBlock = p.readHash('hex');
|
||||||
merkleRoot = p.readHash();
|
merkleRoot = p.readHash('hex');
|
||||||
ts = p.readU32();
|
ts = p.readU32();
|
||||||
bits = p.readU32();
|
bits = p.readU32();
|
||||||
nonce = p.readU32();
|
nonce = p.readU32();
|
||||||
@ -358,8 +392,8 @@ Parser.parseBlockCompact = function parseBlockCompact(p) {
|
|||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
version = p.read32();
|
version = p.read32();
|
||||||
prevBlock = p.readHash();
|
prevBlock = p.readHash('hex');
|
||||||
merkleRoot = p.readHash();
|
merkleRoot = p.readHash('hex');
|
||||||
ts = p.readU32();
|
ts = p.readU32();
|
||||||
bits = p.readU32();
|
bits = p.readU32();
|
||||||
nonce = p.readU32();
|
nonce = p.readU32();
|
||||||
@ -404,7 +438,7 @@ Parser.parseInput = function parseInput(p) {
|
|||||||
p = new BufferReader(p);
|
p = new BufferReader(p);
|
||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
hash = p.readHash();
|
hash = p.readHash('hex');
|
||||||
index = p.readU32();
|
index = p.readU32();
|
||||||
script = new bcoin.script(p.readVarBytes());
|
script = new bcoin.script(p.readVarBytes());
|
||||||
sequence = p.readU32();
|
sequence = p.readU32();
|
||||||
@ -661,7 +695,7 @@ Parser.parseAddress = function parseAddress(p, full) {
|
|||||||
p = new BufferReader(p);
|
p = new BufferReader(p);
|
||||||
p.start();
|
p.start();
|
||||||
|
|
||||||
if (full)
|
if (full && this.version >= 31402)
|
||||||
ts = p.readU32();
|
ts = p.readU32();
|
||||||
else
|
else
|
||||||
ts = 0;
|
ts = 0;
|
||||||
@ -675,7 +709,7 @@ Parser.parseAddress = function parseAddress(p, full) {
|
|||||||
try {
|
try {
|
||||||
services = services.toNumber();
|
services = services.toNumber();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
services = 0;
|
services = services.uand(utils.MAX_SAFE_BN).toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -713,6 +747,65 @@ Parser.parseMempool = function parseMempool(p) {
|
|||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.parseAlert = function parseAlert(p) {
|
||||||
|
var version, relayUntil, expiration, id, cancel;
|
||||||
|
var cancels, count, i, minVer, maxVer, subVers;
|
||||||
|
var priority, comment, statusBar, msg;
|
||||||
|
var payload, p2, size;
|
||||||
|
|
||||||
|
p = new BufferReader(p);
|
||||||
|
p.start();
|
||||||
|
|
||||||
|
payload = p.readVarBytes();
|
||||||
|
signature = p.readVarBytes();
|
||||||
|
size = p.end();
|
||||||
|
|
||||||
|
assert(
|
||||||
|
bcoin.ec.verify(payload, signature, network.alertKey),
|
||||||
|
'Alert does not verify.');
|
||||||
|
|
||||||
|
p = new BufferReader(payload);
|
||||||
|
p.start();
|
||||||
|
version = p.read32();
|
||||||
|
relayUntil = p.read64();
|
||||||
|
expiration = p.read64();
|
||||||
|
id = p.read32();
|
||||||
|
cancel = p.read32();
|
||||||
|
cancels = [];
|
||||||
|
count = p.readVarint();
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
cancels.push(p.read32());
|
||||||
|
minVer = p.read32();
|
||||||
|
maxVer = p.read32();
|
||||||
|
subVers = [];
|
||||||
|
count = p.readVarint();
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
subVers.push(p.readVarString('ascii'));
|
||||||
|
priority = p.read32();
|
||||||
|
comment = p.readVarString('ascii');
|
||||||
|
statusBar = p.readVarString('ascii');
|
||||||
|
p.readVarString('ascii');
|
||||||
|
p.end();
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: version,
|
||||||
|
relayUntil: relayUntil,
|
||||||
|
expiration: expiration,
|
||||||
|
id: id,
|
||||||
|
cancel: cancel,
|
||||||
|
cancels: cancels,
|
||||||
|
minVer: minVer,
|
||||||
|
maxVer: maxVer,
|
||||||
|
subVers: subVers,
|
||||||
|
priority: priority,
|
||||||
|
comment: comment,
|
||||||
|
statusBar: statusBar,
|
||||||
|
payload: payload,
|
||||||
|
signature: signature,
|
||||||
|
_size: size
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -54,6 +54,9 @@ BufferReader.prototype.endData = function endData() {
|
|||||||
if (size === data.length)
|
if (size === data.length)
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
|
// if (this.zeroCopy)
|
||||||
|
// return data.slice(start, end);
|
||||||
|
|
||||||
return utils.slice(data, start, end);
|
return utils.slice(data, start, end);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -258,6 +261,7 @@ BufferReader.prototype.getSize = function getSize() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
BufferReader.prototype.seek = function seek(off) {
|
BufferReader.prototype.seek = function seek(off) {
|
||||||
|
assert(this.offset + off >= 0);
|
||||||
assert(this.offset + off <= this.data.length);
|
assert(this.offset + off <= this.data.length);
|
||||||
this.offset += off;
|
this.offset += off;
|
||||||
return off;
|
return off;
|
||||||
|
|||||||
@ -25,6 +25,11 @@ else
|
|||||||
|
|
||||||
utils.nop = function() {};
|
utils.nop = function() {};
|
||||||
|
|
||||||
|
utils.gc = !utils.isBrowser && typeof gc === 'function' ? gc : utils.nop;
|
||||||
|
|
||||||
|
if (utils.gc !== utils.nop)
|
||||||
|
console.error('bcoin started with --expose-gc enabled.');
|
||||||
|
|
||||||
utils.slice = function slice(buf, start, end) {
|
utils.slice = function slice(buf, start, end) {
|
||||||
var clone;
|
var clone;
|
||||||
|
|
||||||
@ -974,6 +979,7 @@ utils.host = function host(addr) {
|
|||||||
return addr.split(':')[0];
|
return addr.split(':')[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
utils.U32 = new bn(0xffffffff);
|
||||||
utils.U64 = new bn('ffffffffffffffff', 'hex');
|
utils.U64 = new bn('ffffffffffffffff', 'hex');
|
||||||
|
|
||||||
utils.nonce = function nonce() {
|
utils.nonce = function nonce() {
|
||||||
@ -1209,6 +1215,7 @@ utils.writeU64NBE = function writeU64NBE(dst, num, off) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
utils.MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
utils.MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
||||||
|
utils.MAX_SAFE_BN = new bn(utils.MAX_SAFE_INTEGER);
|
||||||
utils.MAX_SAFE_HI = 0x1fffff;
|
utils.MAX_SAFE_HI = 0x1fffff;
|
||||||
|
|
||||||
utils.write64N = function write64N(dst, num, off) {
|
utils.write64N = function write64N(dst, num, off) {
|
||||||
|
|||||||
@ -177,6 +177,7 @@ BufferWriter.prototype.writeVarint = function writeVarint(value) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
BufferWriter.prototype.fill = function fill(value, size) {
|
BufferWriter.prototype.fill = function fill(value, size) {
|
||||||
|
assert(size >= 0);
|
||||||
var buf = new Buffer(size);
|
var buf = new Buffer(size);
|
||||||
buf.fill(value);
|
buf.fill(value);
|
||||||
this.written += buf.length;
|
this.written += buf.length;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user