bitcore/lib/transport/message.js

361 lines
8.2 KiB
JavaScript
Raw Normal View History

'use strict';
var Put = require('bufferput');
var Block = require('../block');
2014-12-09 06:21:11 -08:00
var BufferReader = require('../encoding/bufferreader');
var BufferUtil = require('../util/buffer');
var Random = require('../crypto/random');
var CONNECTION_NONCE = Random.getPseudoRandomBuffer(8);
var PROTOCOL_VERSION = 70000;
var MESSAGES = {
'version' : Version,
'verack': VerAck,
'inv': Inventory,
'ping': Ping,
2014-12-09 06:21:11 -08:00
'pong': Pong,
'addr': Addresses,
'getaddr': GetAddresses,
'reject': Reject
}
module.exports.buildMessage = function(command, payload) {
var Message = MESSAGES[command];
try {
console.log('Message Class', Message);
return new Message().fromBuffer(payload);
} catch (err) {
console.log('Error while parrsing message', command);
console.log(err);
}
}
// ====== VERSION MESSAGE ======
function Version(subversion, nonce) {
this.command = 'version';
2014-12-09 06:21:11 -08:00
this.version = PROTOCOL_VERSION;
this.subversion = subversion || '/BitcoinX:0.1/';
this.nonce = nonce || CONNECTION_NONCE;
2014-12-09 06:21:11 -08:00
};
Version.prototype.fromBuffer = function(payload) {
var message = new Version();
var parser = new BufferReader(payload);
message.version = parser.readUInt32LE();
message.services = parser.readUInt64LEBN();
message.timestamp = parser.readUInt64LEBN();
message.addr_me = parser.read(26);
message.addr_you = parser.read(26);
message.nonce = parser.read(8);
message.subversion = parser.readVarintBuf();
message.start_height = parser.readUInt32LE();
return message;
2014-12-09 06:21:11 -08:00
};
Version.prototype.serialize = function() {
var put = new Put();
2014-12-09 06:21:11 -08:00
put.word32le(this.version); // version
put.word64le(1); // services
put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp
put.pad(26); // addr_me
put.pad(26); // addr_you
put.put(this.nonce);
put.varint(this.subversion.length);
put.put(new Buffer(this.subversion, 'ascii'));
put.word32le(0);
return put.buffer();
2014-12-09 06:21:11 -08:00
};
module.exports.Version = Version;
// ====== INV MESSAGE ======
function Inventory(inventory) {
this.command = 'inv';
this.inventory = inventory || [];
}
Inventory.prototype.fromBuffer = function(payload) {
var message = new Inventory();
var parser = new BufferReader(payload);
var count = parser.readVarintNum();
for (var i = 0; i < count; i++) {
message.inventory.push({
type: parser.readUInt32LE(),
hash: parser.read(32)
});
}
return message;
2014-12-09 06:21:11 -08:00
};
Inventory.prototype.serialize = function() {
var put = new Put();
put.varint(this.inventory.length);
this.inventory.forEach(function(value) {
value instanceof Block ? put.word32le(2) : put.word32le(1);
put.put(value.getHash());
});
return put.buffer();
2014-12-09 06:21:11 -08:00
};
module.exports.Inventory = Inventory;
// ====== GETDATA MESSAGE ======
2014-12-09 06:21:11 -08:00
function GetData(inventory) {
this.command = 'getdata';
this.inventory = inventory || [];
}
util.inherits(GetData, Inventory);
module.exports.GetData = GetData;
// ====== PING MESSAGE ======
function Ping(nonce) {
this.command = 'ping';
this.nonce = nonce || CONNECTION_NONCE;
}
Ping.prototype.fromBuffer = function(payload) {
var nonce = new BufferReader(payload).read(8);
return new Ping(nonce);
2014-12-09 06:21:11 -08:00
};
Ping.prototype.serialize = function() {
return this.nonce;
2014-12-09 06:21:11 -08:00
};
module.exports.Ping = Ping;
// ====== PONG MESSAGE ======
function Pong(nonce) {
this.command = 'pong';
this.nonce = nonce || CONNECTION_NONCE;
}
util.inherits(Pong, Ping);
module.exports.Pong = Pong;
2014-12-09 06:21:11 -08:00
// ====== ADDR MESSAGE ======
function Addresses(nonce) {
this.command = 'addr';
this.addresses = [];
}
Address.prototype.fromBuffer = function(payload) {
2014-12-09 06:21:11 -08:00
var message = new Address();
var parser = new BufferReader(payload);
var addrCount = Math.min(parser.readVarintNum(), 1000);
message.addresses = [];
for (var i = 0; i < addrCount; i++) {
// TODO: Time actually depends on the version of the other peer (>=31402)
message.addresses.push({
time: parser.readUInt32LE(),
services: parser.readUInt64LEBN(),
ip: parser.read(16),
port: parser.readUInt16BE()
});
}
return message;
};
Address.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER; // TODO
};
module.exports.Address = Address;
2014-12-09 06:21:11 -08:00
// ====== GETADDR MESSAGE ======
function GetAddresses() {
this.command = 'getaddr';
}
GetAddresses.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
return new GetAddresses();
};
2014-12-09 06:21:11 -08:00
GetAddresses.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER;
};
module.exports.GetAddresses = GetAddresses;
2014-12-09 06:21:11 -08:00
// ====== VERACK MESSAGE ======
function VerAck() {
this.command = 'verack';
}
VerAck.prototype.fromBuffer = function() {
return new VerAck();
2014-12-09 06:21:11 -08:00
};
VerAck.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER;
};
module.exports.VerAck = VerAck;
2014-12-09 06:21:11 -08:00
// ====== REJECT MESSAGE ======
// TODO: Parse REJECT message
function Reject() {
this.command = 'reject';
}
Reject.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
return new Reject();
};
Reject.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER;
};
module.exports.Reject = Reject;
2014-12-09 06:21:11 -08:00
// ====== ALERT MESSAGE ======
function Alert(payload) {
this.command = 'reject';
}
Alert.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
var message = new Alert();
var parser = new BufferReader(payload);
2014-12-09 06:21:11 -08:00
message.payload = parser.readVarintBuf(); // TODO: Use current format
message.signature = parser.readVarintBuf();
return message;
};
2014-12-09 06:21:11 -08:00
Alert.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER; // TODO: Serialize
};
module.exports.Alert = Alert;
2014-12-09 06:21:11 -08:00
// ====== HEADERS MESSAGE ======
function Headers(blockheaders) {
this.command = 'headers';
this.headers = blockheaders || [];
}
Headers.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
var message = new Headers();
2014-12-09 06:21:11 -08:00
var parser = new BufferReader(payload);
var count = parser.readVarintNum();
message.headers = [];
for (i = 0; i < count; i++) {
var header = Block().fromBufferReader(parser);
message.headers.push(header);
}
2014-12-09 06:21:11 -08:00
return message;
};
Headers.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER; // TODO: Serialize
};
module.exports.Headers = Headers;
2014-12-09 06:21:11 -08:00
// ====== BLOCK MESSAGE ======
function Block(block) {
this.command = 'block';
this.block = block;
}
Block.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
var parser = new BufferReader(payload);
var block = Block().fromBufferReader(parser);
return new Block(block);
};
Block.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER; // TODO: Serialize
};
module.exports.Block = Block;
2014-12-09 06:21:11 -08:00
// ====== TX MESSAGE ======
function Transaction(transaction) {
this.command = 'tx';
this.transaction = transaction;
}
Transaction.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
var parser = new BufferReader(payload);
var transaction = Transaction().fromBufferReader(parser);
return new Transaction(transaction);
};
2014-12-09 06:21:11 -08:00
Transaction.prototype.serialize = function() {
return BufferUtil.EMPTY_BUFFER; // TODO: Serialize
};
module.exports.Transaction = Transaction;
// ====== GETBLOCKS MESSAGE ======
2014-12-09 06:21:11 -08:00
function GetBlocks(starts, stop) {
this.command = 'getblocks';
this.version = PROTOCOL_VERSION;
this.starts = starts || [];
this.stop = stop || BufferUtil.NULL_HASH;
}
GetBlocks.prototype.fromBuffer = function() {
2014-12-09 06:21:11 -08:00
var message = new GetBlocks();
var parser = new BufferReader(payload);
2014-12-09 06:21:11 -08:00
message.version = parser.readUInt32LE();
2014-12-09 06:21:11 -08:00
var startCount = Math.min(parser.readVarintNum(), 500);
message.starts = [];
for (var i = 0; i < startCount; i++) {
message.starts.push(parser.read(32));
}
message.stop = parser.read(32);
};
2014-12-09 06:21:11 -08:00
GetBlocks.prototype.serialize = function() {
var put = new Put();
put.word32le(this.version);
put.varint(this.starts.length);
for (var i = 0; i < starts.length; i++) {
if (this.starts[i].length != 32) {
throw new Error('Invalid hash length');
}
put.put(this.starts[i]);
}
2014-12-09 06:21:11 -08:00
if (this.stop.length != 32) {
throw new Error('Invalid hash length');
}
2014-12-09 06:21:11 -08:00
put.put(this.stop);
return put.buffer();
};
module.exports.GetBlocks = GetBlocks;
// ====== GETHEADERS MESSAGE ======
2014-12-09 06:21:11 -08:00
function GetHeaders(starts, stop) {
this.command = 'getheaders';
this.version = PROTOCOL_VERSION;
this.starts = starts || [];
this.stop = stop || BufferUtil.NULL_HASH;
}
util.inherits(GetHeaders, GetBlocks);
module.exports.GetHeaders = GetHeaders;