I'v seen `RangeError: index out of range` crashes from nodes that don't send it, when `bitcore-p2p` tries to `readUInt8()` the last bit. This also adds `relay` property to `Peer` objects that is respected when sending `Version` messages.
135 lines
4.4 KiB
JavaScript
135 lines
4.4 KiB
JavaScript
'use strict';
|
|
|
|
var chai = require('chai');
|
|
|
|
var should = chai.should();
|
|
|
|
var Buffers = require('buffers');
|
|
var bitcore = require('bitcore');
|
|
var Data = require('./data/messages');
|
|
var P2P = require('../');
|
|
var Messages = P2P.Messages;
|
|
var Networks = bitcore.Networks;
|
|
var BufferUtils = bitcore.util.buffer;
|
|
|
|
var network = Networks.livenet;
|
|
|
|
describe('Messages', function() {
|
|
|
|
var commands = {
|
|
Version: 'version',
|
|
VerAck: 'verack',
|
|
Inventory: 'inv',
|
|
Addresses: 'addr',
|
|
Ping: 'ping',
|
|
Pong: 'pong',
|
|
Alert: 'alert',
|
|
Reject: 'reject',
|
|
Block: 'block',
|
|
GetBlocks: 'getblocks',
|
|
GetHeaders: 'getheaders',
|
|
GetData: 'getdata',
|
|
GetAddresses: 'getaddr',
|
|
Headers: 'headers',
|
|
Transaction: 'tx',
|
|
NotFound: 'notfound'
|
|
};
|
|
// TODO: add data for these
|
|
var noPayload = ['Reject', 'GetBlocks', 'GetHeaders'];
|
|
var names = Object.keys(commands);
|
|
describe('named', function() {
|
|
names.forEach(function(name) {
|
|
var command = commands[name];
|
|
var data = Data[command.toUpperCase()];
|
|
it('should have data for ' + name, function() {
|
|
should.exist(data);
|
|
});
|
|
describe(name, function() {
|
|
var message = new Messages[name]();
|
|
it('should be able to create instance', function() {
|
|
message.command.should.equal(command);
|
|
});
|
|
|
|
it('should be able to serialize the payload', function() {
|
|
var payload = message.getPayload();
|
|
should.exist(payload);
|
|
});
|
|
|
|
it('should be able to serialize the message', function() {
|
|
var buffer = message.serialize(Networks.livenet);
|
|
should.exist(buffer);
|
|
});
|
|
|
|
if (noPayload.indexOf(name) === -1) {
|
|
it('should be able to parse payload', function() {
|
|
var payload = new Buffer(data.payload, 'hex');
|
|
var m = new Messages[name]().fromBuffer(payload);
|
|
should.exist(m);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
var buildMessage = function(hex) {
|
|
var m = Buffers();
|
|
m.push(new Buffer(hex, 'hex'));
|
|
return m;
|
|
};
|
|
it('fails with invalid command', function() {
|
|
var invalidCommand = 'f9beb4d96d616c6963696f757300000025000000bd5e830c' +
|
|
'0102000000ec3995c1bf7269ff728818a65e53af00cbbee6b6eca8ac9ce7bc79d87' +
|
|
'7041ed8';
|
|
var fails = function() {
|
|
Messages.parseMessage(network, buildMessage(invalidCommand));
|
|
};
|
|
fails.should.throw('Unsupported message command: malicious');
|
|
});
|
|
|
|
it('ignores malformed messages', function() {
|
|
var malformed1 = 'd8c4c3d976657273696f6e000000000065000000fc970f1772110' +
|
|
'1000100000000000000ba6288540000000001000000000000000000000000000000' +
|
|
'0000ffffba8886dceab0010000000000000000000000000000000000ffff0509552' +
|
|
'2208de7e1c1ef80a1cea70f2f5361746f7368693a302e392e312fa317050001';
|
|
var malformed2 = 'f9beb4d967657464617461000000000089000000d88134740102' +
|
|
'0000006308e4a380c949dbad182747b0f7b6a89e874328ca41f37287f74a81b8f84' +
|
|
'86d';
|
|
var malformed3 = 'f9beb4d967657464617461000000000025000000616263640102' +
|
|
'00000069ebcbc34a4f9890da9aea0f773beba883a9afb1ab9ad7647dd4a1cd346c3' +
|
|
'728';
|
|
[malformed1, malformed2, malformed3].forEach(function(malformed) {
|
|
var ret = Messages.parseMessage(network, buildMessage(malformed));
|
|
should.not.exist(ret);
|
|
});
|
|
});
|
|
|
|
it('Inventory#from family methods work', function() {
|
|
var hash = 'eb951630aba498b9a0d10f72b5ea9e39d5ff04b03dc2231e662f52057f948aa1';
|
|
[Messages.Inventory, Messages.GetData, Messages.NotFound].forEach(function(clazz) {
|
|
var b = clazz.forBlock(hash);
|
|
(b instanceof clazz).should.equal(true);
|
|
var t = clazz.forTransaction(hash);
|
|
(t instanceof clazz).should.equal(true);
|
|
clazz.forBlock(BufferUtils.reverse(new Buffer(hash, 'hex'))).should.deep.equal(b);
|
|
clazz.forTransaction(BufferUtils.reverse(new Buffer(hash, 'hex'))).should.deep.equal(t);
|
|
});
|
|
});
|
|
|
|
it('Version#fromBuffer works w/o fRelay arg', function() {
|
|
var messageHex = Data.VERSION_NO_FRELAY.payload;
|
|
var message = new Messages.Version()
|
|
.fromBuffer(new Buffer(messageHex, 'hex'));
|
|
});
|
|
|
|
it('Version#relay setting works', function() {
|
|
[true,false].forEach(function(relay) {
|
|
var message = new Messages.Version(null,null,relay);
|
|
message.relay.should.equal(relay);
|
|
var messageBuf = message.getPayload();
|
|
var newMessage = new Messages.Version().fromBuffer(messageBuf)
|
|
newMessage.relay.should.equal(relay);
|
|
});
|
|
});
|
|
|
|
});
|