net: remove alert system.
This commit is contained in:
parent
e407c08668
commit
b6593adf75
@ -39,7 +39,6 @@ exports.types = {
|
||||
VERACK: 1,
|
||||
PING: 2,
|
||||
PONG: 3,
|
||||
ALERT: 4,
|
||||
GETADDR: 5,
|
||||
ADDR: 6,
|
||||
INV: 7,
|
||||
@ -589,337 +588,6 @@ PongPacket.fromRaw = function fromRaw(data, enc) {
|
||||
return new PongPacket().fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alert Packet
|
||||
* @exports AlertPacket
|
||||
* @constructor
|
||||
* @param {Object} options
|
||||
* @property {Number} version
|
||||
* @property {Number} relayUntil
|
||||
* @property {Number} expiration
|
||||
* @property {Number} id
|
||||
* @property {Number} cancel
|
||||
* @property {Number[]} cancels
|
||||
* @property {Number} minVer
|
||||
* @property {Number} maxVer
|
||||
* @property {String[]} subVers
|
||||
* @property {Number} priority
|
||||
* @property {String} comment
|
||||
* @property {String} statusBar
|
||||
* @property {String?} reserved
|
||||
* @property {Buffer?} signature - Payload signature.
|
||||
*/
|
||||
|
||||
function AlertPacket(options) {
|
||||
var ts;
|
||||
|
||||
if (!(this instanceof AlertPacket))
|
||||
return new AlertPacket(options);
|
||||
|
||||
Packet.call(this);
|
||||
|
||||
ts = util.now() + 7 * 86400;
|
||||
|
||||
this.version = 1;
|
||||
this.relayUntil = ts;
|
||||
this.expiration = ts;
|
||||
this.id = 1;
|
||||
this.cancel = 0;
|
||||
this.cancels = [];
|
||||
this.minVer = 10000;
|
||||
this.maxVer = common.PROTOCOL_VERSION;
|
||||
this.subVers = [];
|
||||
this.priority = 100;
|
||||
this.comment = '';
|
||||
this.statusBar = '';
|
||||
this.reserved = '';
|
||||
this.signature = null;
|
||||
|
||||
this.payload = null;
|
||||
this._hash = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
util.inherits(AlertPacket, Packet);
|
||||
|
||||
AlertPacket.prototype.cmd = 'alert';
|
||||
AlertPacket.prototype.type = exports.types.ALERT;
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.version != null)
|
||||
this.version = options.version;
|
||||
|
||||
if (options.relayUntil != null)
|
||||
this.relayUntil = options.relayUntil;
|
||||
|
||||
if (options.expiration != null)
|
||||
this.expiration = options.expiration;
|
||||
|
||||
if (options.id != null)
|
||||
this.id = options.id;
|
||||
|
||||
if (options.cancel != null)
|
||||
this.cancel = options.cancel;
|
||||
|
||||
if (options.cancels)
|
||||
this.cancels = options.cancels;
|
||||
|
||||
if (options.minVer != null)
|
||||
this.minVer = options.minVer;
|
||||
|
||||
if (options.maxVer != null)
|
||||
this.maxVer = options.maxVer;
|
||||
|
||||
if (options.subVers)
|
||||
this.subVers = options.subVers;
|
||||
|
||||
if (options.priority != null)
|
||||
this.priority = options.priority;
|
||||
|
||||
if (options.comment != null)
|
||||
this.comment = options.comment;
|
||||
|
||||
if (options.statusBar != null)
|
||||
this.statusBar = options.statusBar;
|
||||
|
||||
if (options.reserved != null)
|
||||
this.reserved = options.reserved;
|
||||
|
||||
this.signature = options.signature;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate alert packet from options.
|
||||
* @param {Object} options
|
||||
* @returns {AlertPacket}
|
||||
*/
|
||||
|
||||
AlertPacket.fromOptions = function fromOptions(options) {
|
||||
return new AlertPacket().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the hash256 of the alert payload.
|
||||
* @param {String?} enc
|
||||
* @returns {Hash}
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.hash = function hash(enc) {
|
||||
if (!this._hash)
|
||||
this._hash = crypto.hash256(this.toPayload());
|
||||
return enc === 'hex' ? this._hash.toString('hex') : this._hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the packet to its payload.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.toPayload = function toPayload() {
|
||||
if (!this.payload)
|
||||
this.payload = this.framePayload();
|
||||
|
||||
return this.payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign the alert packet payload.
|
||||
* @param {Buffer} key - Private key.
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.sign = function sign(key) {
|
||||
this.signature = ec.sign(this.hash(), key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify the alert packet.
|
||||
* @param {Buffer} key - Public key.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.verify = function verify(key) {
|
||||
return ec.verify(this.hash(), this.signature, key);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write the alert packet to a buffer writer.
|
||||
* @param {BufferWriter} bw
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.getSize = function getSize() {
|
||||
var size = 0;
|
||||
size += encoding.sizeVarlen(this.getPayloadSize());
|
||||
size += encoding.sizeVarBytes(this.signature);
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write the alert packet to a buffer writer.
|
||||
* @param {BufferWriter} bw
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.toWriter = function toWriter(bw) {
|
||||
bw.writeVarBytes(this.toPayload());
|
||||
bw.writeVarBytes(this.signature);
|
||||
return bw;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the alert packet (includes
|
||||
* payload _and_ signature).
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.toRaw = function toRaw() {
|
||||
var size = this.getSize();
|
||||
return this.toWriter(new StaticWriter(size)).render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get serialization size.
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.getPayloadSize = function getPayloadSize() {
|
||||
var size = 0;
|
||||
var i;
|
||||
|
||||
size += 28;
|
||||
size += encoding.sizeVarint(this.cancels.length);
|
||||
size += this.cancels.length * 4;
|
||||
size += 8;
|
||||
|
||||
size += encoding.sizeVarint(this.subVers.length);
|
||||
for (i = 0; i < this.subVers.length; i++)
|
||||
size += encoding.sizeVarString(this.subVers[i], 'ascii');
|
||||
|
||||
size += 4;
|
||||
|
||||
size += encoding.sizeVarString(this.comment, 'ascii');
|
||||
size += encoding.sizeVarString(this.statusBar, 'ascii');
|
||||
size += encoding.sizeVarString(this.reserved, 'ascii');
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize the alert packet payload.
|
||||
* @private
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.framePayload = function framePayload() {
|
||||
var size = this.getPayloadSize();
|
||||
var bw = new StaticWriter(size);
|
||||
var i;
|
||||
|
||||
bw.write32(this.version);
|
||||
bw.write64(this.relayUntil);
|
||||
bw.write64(this.expiration);
|
||||
bw.write32(this.id);
|
||||
bw.write32(this.cancel);
|
||||
|
||||
bw.writeVarint(this.cancels.length);
|
||||
for (i = 0; i < this.cancels.length; i++)
|
||||
bw.write32(this.cancels[i]);
|
||||
|
||||
bw.write32(this.minVer);
|
||||
bw.write32(this.maxVer);
|
||||
|
||||
bw.writeVarint(this.subVers.length);
|
||||
for (i = 0; i < this.subVers.length; i++)
|
||||
bw.writeVarString(this.subVers[i], 'ascii');
|
||||
|
||||
bw.write32(this.priority);
|
||||
bw.writeVarString(this.comment, 'ascii');
|
||||
bw.writeVarString(this.statusBar, 'ascii');
|
||||
bw.writeVarString(this.reserved, 'ascii');
|
||||
|
||||
return bw.render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from buffer reader.
|
||||
* @private
|
||||
* @param {BufferReader} br
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.fromReader = function fromReader(br) {
|
||||
var i, count;
|
||||
|
||||
this.payload = br.readVarBytes();
|
||||
this.signature = br.readVarBytes();
|
||||
|
||||
br = new BufferReader(this.payload);
|
||||
|
||||
this.version = br.read32();
|
||||
this.relayUntil = br.read53();
|
||||
this.expiration = br.read53();
|
||||
this.id = br.read32();
|
||||
this.cancel = br.read32();
|
||||
|
||||
count = br.readVarint();
|
||||
for (i = 0; i < count; i++)
|
||||
this.cancels.push(br.read32());
|
||||
|
||||
this.minVer = br.read32();
|
||||
this.maxVer = br.read32();
|
||||
|
||||
count = br.readVarint();
|
||||
for (i = 0; i < count; i++)
|
||||
this.subVers.push(br.readVarString('ascii'));
|
||||
|
||||
this.priority = br.read32();
|
||||
this.comment = br.readVarString('ascii');
|
||||
this.statusBar = br.readVarString('ascii');
|
||||
this.reserved = br.readVarString('ascii');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
return this.fromReader(new BufferReader(data));
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate alert packet from buffer reader.
|
||||
* @param {BufferReader} br
|
||||
* @returns {AlertPacket}
|
||||
*/
|
||||
|
||||
AlertPacket.fromReader = function fromReader(br) {
|
||||
return new AlertPacket().fromReader(br);
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate alert packet from serialized data.
|
||||
* @param {Buffer} data
|
||||
* @param {String?} enc
|
||||
* @returns {AlertPacket}
|
||||
*/
|
||||
|
||||
AlertPacket.fromRaw = function fromRaw(data, enc) {
|
||||
if (typeof data === 'string')
|
||||
data = new Buffer(data, enc);
|
||||
return new AlertPacket().fromRaw(data, enc);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a `getaddr` packet.
|
||||
* @exports GetAddrPacket
|
||||
@ -3561,7 +3229,6 @@ exports.VersionPacket = VersionPacket;
|
||||
exports.VerackPacket = VerackPacket;
|
||||
exports.PingPacket = PingPacket;
|
||||
exports.PongPacket = PongPacket;
|
||||
exports.AlertPacket = AlertPacket;
|
||||
exports.GetAddrPacket = GetAddrPacket;
|
||||
exports.AddrPacket = AddrPacket;
|
||||
exports.InvPacket = InvPacket;
|
||||
|
||||
@ -1450,9 +1450,6 @@ Peer.prototype.handlePacket = co(function* handlePacket(packet) {
|
||||
case packetTypes.PONG:
|
||||
yield this.handlePong(packet);
|
||||
break;
|
||||
case packetTypes.ALERT:
|
||||
yield this.handleAlert(packet);
|
||||
break;
|
||||
case packetTypes.GETADDR:
|
||||
yield this.handleGetAddr(packet);
|
||||
break;
|
||||
@ -2472,17 +2469,6 @@ Peer.prototype.handleReject = co(function* handleReject(reject) {
|
||||
entry.reject(this);
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle `alert` packet.
|
||||
* @private
|
||||
* @param {AlertPacket}
|
||||
*/
|
||||
|
||||
Peer.prototype.handleAlert = co(function* handleAlert(alert) {
|
||||
this.invFilter.add(alert.hash());
|
||||
this.emit('alert', alert);
|
||||
});
|
||||
|
||||
/**
|
||||
* Handle `encinit` packet.
|
||||
* @private
|
||||
@ -2765,21 +2751,6 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(packet) {
|
||||
yield this.emitBlock(block.toBlock());
|
||||
});
|
||||
|
||||
/**
|
||||
* Send an `alert` to peer.
|
||||
* @param {AlertPacket} alert
|
||||
*/
|
||||
|
||||
Peer.prototype.sendAlert = function sendAlert(alert) {
|
||||
if (!this.handshake)
|
||||
return;
|
||||
|
||||
if (!this.invFilter.added(alert.hash()))
|
||||
return;
|
||||
|
||||
this.send(alert);
|
||||
};
|
||||
|
||||
/**
|
||||
* Send `getheaders` to peer. Note that unlike
|
||||
* `getblocks`, `getheaders` can have a null locator.
|
||||
|
||||
@ -77,7 +77,6 @@ var VerifyError = errors.VerifyError;
|
||||
* @emits Pool#blocks
|
||||
* @emits Pool#txs
|
||||
* @emits Pool#chain-progress
|
||||
* @emits Pool#alert
|
||||
* @emits Pool#reject
|
||||
* @emits Pool#addr
|
||||
* @emits Pool#version
|
||||
@ -628,18 +627,6 @@ Pool.prototype.sendGetAddr = function sendGetAddr() {
|
||||
peer.sendGetAddr();
|
||||
};
|
||||
|
||||
/**
|
||||
* Send `alert` to all peers.
|
||||
* @param {AlertPacket} alert
|
||||
*/
|
||||
|
||||
Pool.prototype.sendAlert = function sendAlert(alert) {
|
||||
var peer;
|
||||
|
||||
for (peer = this.peers.head(); peer; peer = peer.next)
|
||||
peer.sendAlert(alert);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an outbound peer with no special purpose.
|
||||
* @private
|
||||
@ -716,10 +703,6 @@ Pool.prototype.bindPeer = function bindPeer(peer) {
|
||||
peer.on('notfound', function(items) {
|
||||
self.handleNotFound(peer, items);
|
||||
});
|
||||
|
||||
peer.on('alert', function(packet) {
|
||||
self.handleAlert(peer, packet);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1341,66 +1324,6 @@ Pool.prototype.handleNotFound = function handleNotFound(peer, items) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle an alert packet.
|
||||
* @private
|
||||
* @param {Peer} peer
|
||||
* @param {AlertPacket} alert
|
||||
*/
|
||||
|
||||
Pool.prototype.handleAlert = function handleAlert(peer, alert) {
|
||||
var now = this.network.now();
|
||||
|
||||
if (!alert.verify(this.network.alertKey)) {
|
||||
this.logger.warning('Peer sent a phony alert packet (%s).', peer.hostname);
|
||||
// Let's look at it because why not?
|
||||
this.logger.debug(alert);
|
||||
peer.increaseBan(100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (now >= alert.expiration) {
|
||||
this.logger.warning(
|
||||
'Peer sent an expired alert packet (%s).',
|
||||
peer.hostname);
|
||||
this.logger.debug(alert);
|
||||
return;
|
||||
}
|
||||
|
||||
if (alert.id === 0x7fffffff) {
|
||||
if (!(alert.expiration === 0x7fffffff
|
||||
&& alert.cancel === 0x7fffffff - 1
|
||||
&& alert.minVer === 0
|
||||
&& alert.maxVer === 0x7fffffff
|
||||
&& alert.subVers.length === 0
|
||||
&& alert.priority === 0x7fffffff
|
||||
&& alert.statusBar === 'URGENT: Alert key compromised, upgrade required')) {
|
||||
this.logger.warning('Misuse of last alert ID (%s).', peer.hostname);
|
||||
this.logger.debug(alert);
|
||||
peer.increaseBan(100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep alert disabled on main.
|
||||
if (this.network === Network.main) {
|
||||
// https://github.com/bitcoin/bitcoin/pull/7692#issuecomment-197967429
|
||||
this.logger.warning('The Japanese government sent an alert packet.');
|
||||
this.logger.warning('Here is their IP: %s.', peer.hostname);
|
||||
this.logger.info(alert);
|
||||
peer.increaseBan(100);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.warning('Received alert from peer (%s).', peer.hostname);
|
||||
this.logger.warning(alert);
|
||||
|
||||
if (now < alert.relayUntil)
|
||||
this.sendAlert(alert);
|
||||
|
||||
this.emit('alert', alert, peer);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an inbound peer from an existing socket.
|
||||
* @private
|
||||
|
||||
@ -49,7 +49,6 @@ var policy = require('../protocol/policy');
|
||||
* @property {HTTPServer} http
|
||||
* @emits FullNode#block
|
||||
* @emits FullNode#tx
|
||||
* @emits FullNode#alert
|
||||
* @emits FullNode#error
|
||||
*/
|
||||
|
||||
@ -188,10 +187,6 @@ FullNode.prototype._init = function _init() {
|
||||
if (this.http)
|
||||
this.http.on('error', onError);
|
||||
|
||||
this.pool.on('alert', function(alert) {
|
||||
self.emit('alert', alert);
|
||||
});
|
||||
|
||||
this.mempool.on('tx', function(tx) {
|
||||
self.miner.notifyEntry();
|
||||
self.emit('tx', tx);
|
||||
|
||||
@ -35,7 +35,6 @@ var HTTPServer = require('../http/server');
|
||||
* @property {HTTPServer} http
|
||||
* @emits SPVNode#block
|
||||
* @emits SPVNode#tx
|
||||
* @emits SPVNode#alert
|
||||
* @emits SPVNode#error
|
||||
*/
|
||||
|
||||
@ -136,10 +135,6 @@ SPVNode.prototype._init = function _init() {
|
||||
if (this.http)
|
||||
this.http.on('error', onError);
|
||||
|
||||
this.pool.on('alert', function(alert) {
|
||||
self.emit('alert', alert);
|
||||
});
|
||||
|
||||
this.pool.on('tx', function(tx) {
|
||||
if (self.rescanJob)
|
||||
return;
|
||||
|
||||
@ -30,7 +30,6 @@ function Network(options) {
|
||||
this.seeds = options.seeds;
|
||||
this.magic = options.magic;
|
||||
this.port = options.port;
|
||||
this.alertKey = options.alertKey;
|
||||
this.checkpoints = options.checkpoints;
|
||||
this.lastCheckpoint = options.lastCheckpoint;
|
||||
this.halvingInterval = options.halvingInterval;
|
||||
|
||||
@ -72,18 +72,6 @@ main.magic = 0xd9b4bef9;
|
||||
|
||||
main.port = 8333;
|
||||
|
||||
/**
|
||||
* Public key for verifying alert packets.
|
||||
* @const {Buffer}
|
||||
*/
|
||||
|
||||
main.alertKey = new Buffer(''
|
||||
+ '04fc9702847840aaf195de8442ebecedf5b095c'
|
||||
+ 'dbb9bc716bda9110971b28a49e0ead8564ff0db'
|
||||
+ '22209e0374782c093bb899692d524e9d6a6956e'
|
||||
+ '7c5ecbcd68284',
|
||||
'hex');
|
||||
|
||||
/**
|
||||
* Checkpoint block list.
|
||||
* @const {Object}
|
||||
@ -509,13 +497,6 @@ testnet.magic = 0x0709110b;
|
||||
|
||||
testnet.port = 18333;
|
||||
|
||||
testnet.alertKey = new Buffer(''
|
||||
+ '04302390343f91cc401d56d68b123028bf52e5f'
|
||||
+ 'ca1939df127f63c6467cdf9c8e2c14b61104cf8'
|
||||
+ '17d0b780da337893ecc4aaff1309e536162dabb'
|
||||
+ 'db45200ca2b0a',
|
||||
'hex');
|
||||
|
||||
testnet.checkpoints = {
|
||||
546: '70cb6af7ebbcb1315d3414029c556c55f3e2fc353c4c9063a76c932a00000000',
|
||||
// Custom checkpoints
|
||||
@ -687,14 +668,6 @@ regtest.magic = 0xdab5bffa;
|
||||
|
||||
regtest.port = 48444;
|
||||
|
||||
regtest.alertPrivateKey = new Buffer(
|
||||
'b866c595a088e2d9ea87ff4df173dd5990b1331fa9acff6aa82cc04162a63f91',
|
||||
'hex');
|
||||
|
||||
regtest.alertKey = new Buffer(
|
||||
'032b7c336bc802421f38063251a6230cc3cd3a9c4282d1673fbb037a4fd4f7408c',
|
||||
'hex');
|
||||
|
||||
regtest.checkpoints = {};
|
||||
regtest.lastCheckpoint = 0;
|
||||
|
||||
@ -846,10 +819,6 @@ segnet4.magic = 0xc4a1abdc;
|
||||
|
||||
segnet4.port = 28901;
|
||||
|
||||
segnet4.alertKey = new Buffer(
|
||||
'0300000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63',
|
||||
'hex');
|
||||
|
||||
segnet4.checkpoints = {};
|
||||
segnet4.lastCheckpoint = 0;
|
||||
|
||||
@ -994,13 +963,6 @@ simnet.magic = 0x12141c16;
|
||||
|
||||
simnet.port = 18555;
|
||||
|
||||
simnet.alertKey = new Buffer(''
|
||||
+ '04302390343f91cc401d56d68b123028bf52e5f'
|
||||
+ 'ca1939df127f63c6467cdf9c8e2c14b61104cf8'
|
||||
+ '17d0b780da337893ecc4aaff1309e536162dabb'
|
||||
+ 'db45200ca2b0a',
|
||||
'hex');
|
||||
|
||||
simnet.checkpoints = {};
|
||||
|
||||
simnet.lastCheckpoint = 0;
|
||||
|
||||
Binary file not shown.
@ -12,8 +12,6 @@ var Parser = require('../lib/net/parser');
|
||||
var packets = require('../lib/net/packets');
|
||||
var network = Network.get('main');
|
||||
|
||||
var alertData = fs.readFileSync(__dirname + '/data/alertTests.raw');
|
||||
|
||||
describe('Protocol', function() {
|
||||
var version = require('../package.json').version;
|
||||
var agent = '/bcoin:' + version + '/';
|
||||
@ -210,20 +208,4 @@ describe('Protocol', function() {
|
||||
|
||||
assert.deepEqual(tx.toRaw(), rawFirstTx);
|
||||
});
|
||||
|
||||
it('should parse, reserialize, and verify alert packets', function() {
|
||||
var br = new BufferReader(alertData);
|
||||
var alert, data;
|
||||
|
||||
while (br.left()) {
|
||||
alert = packets.AlertPacket.fromReader(br);
|
||||
assert(alert.verify(network.alertKey));
|
||||
alert._payload = null;
|
||||
alert._hash = null;
|
||||
|
||||
data = alert.toRaw();
|
||||
alert = packets.AlertPacket.fromRaw(data);
|
||||
assert(alert.verify(network.alertKey));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user