diff --git a/docs/Peer.md b/docs/Peer.md new file mode 100644 index 0000000..7bcbc39 --- /dev/null +++ b/docs/Peer.md @@ -0,0 +1,92 @@ +# Peer + +Represents a node from the p2p bitcoin network. The Peer class supports connecting directly to other nodes or through a socks5 proxy like Tor. + +The code to create a new peer looks like this: + +```javascript +var bitcore = require('bitcore'); +var Peer = bitcore.transport.Peer; + +// default port +var livenetPeer = new Peer('5.9.85.34'); +var testnetPeer = new Peer('5.9.85.34', bitcore.testnet); + +// custom port +var livenetPeer = new Peer('5.9.85.34', 8334); +var testnetPeer = new Peer('5.9.85.34', 18334, bitcore.testnet); + +// use sock5 proxy (Tor) +var peer = new Peer('5.9.85.34').setProxy('localhost', 9050); +``` + +A peer instance is always in one of the following states: + +* `disconnected`: No connection with the remote node. +* `connecting`: While establishing the connection. +* `connected`: Exchanging version packages. +* `ready`: Connection ready for sending and receiving messages. + +You can subscribe to the change of those states as follows: + +```javascript +var bitcore = require('bitcore'); +var Peer = bitcore.transport.Peer; + +var peer = new Peer('5.9.85.34'); + +peer.on('ready', function() { + // peer info + console.log(peer.version, peer.subversion, peer.bestHeight); +}); + +peer.on('disconnect', function() { + console.log('connection closed'); +}); + +peer.connect(); +``` + +Once connected, a peer instance can send and receive messages. Every time a message arrives it's emitted as a new event. Let's see an example of this: + +```javascript +var bitcore = require('bitcore'); +var peer = new bitcore.transport.Peer('5.9.85.34'); + +// handle events +peer.on('inv', function(message) { + // message.inventory[] +}); + +peer.on('tx', function(message) { + // message.transaction +}); + +peer.on('addr', function(message) { + // message.addresses[] +}); + +peer.connect(); +``` + +In order to send messages the Peer class offers the `sendMessage(message)` method, which receives an instance of a message. All supported messages can be found on the `bitcore.transport.Messages` module. For more information about messages refer to the [protocol specification](https://en.bitcoin.it/wiki/Protocol_specification). + +An example for requesting other connected nodes to a peers looks like this: + +```javascript +var bitcore = require('bitcore'); +var peer = new bitcore.transport.Peer('5.9.85.34'); + +peer.on('ready', function() { + var message = new bitcore.transport.Messages.GetAddresses(); + peer.sendMessage(message); +}); + +peer.on('addr', function(message) { + message.addresses.forEach(function(address) { + // do something + }); +}); + +peer.connect(); +``` diff --git a/index.js b/index.js index 627909f..b071aff 100644 --- a/index.js +++ b/index.js @@ -24,6 +24,11 @@ bitcore.util.bitcoin = require('./lib/util/bitcoin'); bitcore.util.buffer = require('./lib/util/buffer'); bitcore.util.js = require('./lib/util/js'); +// transport +bitcore.transport = {}; +bitcore.transport.Peer = require('./lib/transport/peer'); +bitcore.transport.Messages = require('./lib/transport/messages'); + // errors thrown by the library bitcore.errors = require('./lib/errors'); diff --git a/lib/networks.js b/lib/networks.js index 5e11d26..1452d7a 100644 --- a/lib/networks.js +++ b/lib/networks.js @@ -1,6 +1,8 @@ 'use strict'; var _ = require('lodash'); +var BufferUtil = require('./util/buffer'); + /** * A network is merely a map containing values that correspond to version * numbers for each bitcoin network. Currently only supporting "livenet" @@ -25,7 +27,17 @@ _.extend(livenet, { privatekey: 0x80, scripthash: 0x05, xpubkey: 0x0488b21e, - xprivkey: 0x0488ade4 + xprivkey: 0x0488ade4, + networkMagic: BufferUtil.integerAsBuffer(0xf9beb4d9), + port: 8333, + dnsSeeds: [ + 'seed.bitcoin.sipa.be', + 'dnsseed.bluematt.me', + 'dnsseed.bitcoin.dashjr.org', + 'seed.bitcoinstats.com', + 'seed.bitnodes.io', + 'bitseed.xf2.org' + ] }); /** @@ -40,16 +52,26 @@ _.extend(testnet, { privatekey: 0xef, scripthash: 0xc4, xpubkey: 0x043587cf, - xprivkey: 0x04358394 + xprivkey: 0x04358394, + networkMagic: BufferUtil.integerAsBuffer(0x0b110907), + port: 18333, + dnsSeeds: [ + 'testnet-seed.bitcoin.petertodd.org', + 'testnet-seed.bluematt.me' + ], }); var networkMaps = {}; _.each(_.values(livenet), function(value) { - networkMaps[value] = livenet; + if (!_.isObject(value)) { + networkMaps[value] = livenet; + } }); _.each(_.values(testnet), function(value) { - networkMaps[value] = testnet; + if (!_.isObject(value)) { + networkMaps[value] = testnet; + } }); /** diff --git a/lib/transport/messages.js b/lib/transport/messages.js new file mode 100644 index 0000000..5b0fb19 --- /dev/null +++ b/lib/transport/messages.js @@ -0,0 +1,554 @@ +'use strict'; +/* jshint curly: false */ + +var Buffers = require('buffers'); +var Put = require('bufferput'); +var util = require('util'); + +var BlockHeaderModel = require('../blockheader'); +var BlockModel = require('../block'); +var BufferReader = require('../encoding/bufferreader'); +var BufferUtil = require('../util/buffer'); +var Hash = require('../crypto/hash'); +var Random = require('../crypto/random'); +var TransactionModel = require('../transaction'); + +var CONNECTION_NONCE = Random.getPseudoRandomBuffer(8); +var PROTOCOL_VERSION = 70000; + +/** + * Static helper for consuming a data buffer until the next message. + * + * @param{Network} network - the network object + * @param{Buffer} dataBuffer - the buffer to read from + * @returns{Message|undefined} A message or undefined if there is nothing to read. + */ +var parseMessage = function(network, dataBuffer) { + if (dataBuffer.length < 20) return; + + // Search the next magic number + if (!discardUntilNextMessage(network, dataBuffer)) return; + + var PAYLOAD_START = 16; + var payloadLen = (dataBuffer.get(PAYLOAD_START)) + + (dataBuffer.get(PAYLOAD_START + 1) << 8) + + (dataBuffer.get(PAYLOAD_START + 2) << 16) + + (dataBuffer.get(PAYLOAD_START + 3) << 24); + + var messageLength = 24 + payloadLen; + if (dataBuffer.length < messageLength) return; + + var command = dataBuffer.slice(4, 16).toString('ascii').replace(/\0+$/, ''); + var payload = dataBuffer.slice(24, messageLength); + var checksum = dataBuffer.slice(20, 24); + + var checksumConfirm = Hash.sha256sha256(payload).slice(0, 4); + if (!BufferUtil.equals(checksumConfirm, checksum)) { + dataBuffer.skip(messageLength); + return; + } + + console.log(command, 'FULL MESSAGE', dataBuffer.slice(0, messageLength).toString('hex')); + console.log(command, 'PAYLOAD MESSAGE', payload.toString('hex')); + + dataBuffer.skip(messageLength); + return Message.buildMessage(command, payload); +}; + +module.exports.parseMessage = parseMessage; + +/** + * Internal function that discards data until founds the next message. + */ +function discardUntilNextMessage(network, dataBuffer) { + var magicNumber = network.networkMagic; + + var i = 0; + for (;;) { + // check if it's the beginning of a new message + var packageNumber = dataBuffer.slice(0, 4); + if (BufferUtil.equals(packageNumber, magicNumber)) { + dataBuffer.skip(i); + return true; + } + + // did we reach the end of the buffer? + if (i > (dataBuffer.length - 4)) { + dataBuffer.skip(i); + return false; + } + + i++; // continue scanning + } +} + +/** + * Abstract Message that knows how to parse and serialize itself. + * Concret subclases should implement {fromBuffer} and {getPayload} methods. + */ +function Message() {} + +Message.COMMANDS = {}; + +Message.buildMessage = function(command, payload) { + try { + var CommandClass = Message.COMMANDS[command]; + return new CommandClass().fromBuffer(payload); + } catch (err) { + console.log('Error while parsing message', err); + } +}; + +/** + * Parse instance state from buffer. + * + * @param{Buffer} payload - the buffer to read from + * @returns{Message} The same message instance + */ +Message.prototype.fromBuffer = function(payload) { + /* jshint unused: false */ + return this; +}; + +/** + * Serialize the payload into a buffer. + * + * @returns{Buffer} the serialized payload + */ +Message.prototype.getPayload = function() { + return BufferUtil.EMPTY_BUFFER; +}; + +/** + * Serialize the message into a buffer. + * + * @returns{Buffer} the serialized message + */ +Message.prototype.serialize = function(network) { + var magic = network.networkMagic; + var commandBuf = new Buffer(this.command, 'ascii'); + if (commandBuf.length > 12) throw 'Command name too long'; + + var payload = this.getPayload(); + var checksum = Hash.sha256sha256(payload).slice(0, 4); + + // -- HEADER -- + var message = new Put(); + message.put(magic); + message.put(commandBuf); + message.pad(12 - commandBuf.length); // zero-padded + message.word32le(payload.length); + message.put(checksum); + + // -- BODY -- + message.put(payload); + + return message.buffer(); +} + +/** + * Version Message + * + * @param{string} subversion - version of the client + * @param{Buffer} nonce - a random 8 bytes buffer + */ +function Version(subversion, nonce) { + this.command = 'version'; + this.version = PROTOCOL_VERSION; + this.subversion = subversion || '/BitcoinX:0.1/'; + this.nonce = nonce || CONNECTION_NONCE; +} +util.inherits(Version, Message); + +Version.prototype.fromBuffer = function(payload) { + var parser = new BufferReader(payload); + this.version = parser.readUInt32LE(); + this.services = parser.readUInt64LEBN(); + this.timestamp = parser.readUInt64LEBN(); + this.addr_me = parser.read(26); + this.addr_you = parser.read(26); + this.nonce = parser.read(8); + this.subversion = parser.readVarintBuf().toString(); + this.start_height = parser.readUInt32LE(); + + return this; +}; + +Version.prototype.getPayload = function() { + var put = new Put(); + 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(); +}; + +module.exports.Version = Message.COMMANDS.version = Version; + +/** + * Inv Message + * + * @param{Array} inventory - reported elements + */ +function Inventory(inventory) { + this.command = 'inv'; + this.inventory = inventory || []; +} +util.inherits(Inventory, Message); + +Inventory.prototype.fromBuffer = function(payload) { + var parser = new BufferReader(payload); + var count = parser.readVarintNum(); + for (var i = 0; i < count; i++) { + this.inventory.push({ + type: parser.readUInt32LE(), + hash: parser.read(32) + }); + } + + return this; +}; + +Inventory.prototype.getPayload = function() { + var put = new Put(); + + put.varint(this.inventory.length); + this.inventory.forEach(function(value) { + put.word32le(value.type); + put.put(value.hash); + }); + + return put.buffer(); +}; + +module.exports.Inventory = Message.COMMANDS.inv = Inventory; + +/** + * Getdata Message + * + * @param{Array} inventory - requested elements + */ +function GetData(inventory) { + this.command = 'getdata'; + this.inventory = inventory || []; +} + +util.inherits(GetData, Inventory); +module.exports.GetData = GetData; + +/** + * Ping Message + * + * @param{Buffer} nonce - a random 8 bytes buffer + */ +function Ping(nonce) { + this.command = 'ping'; + this.nonce = nonce || CONNECTION_NONCE; +} +util.inherits(Ping, Message); + +Ping.prototype.fromBuffer = function(payload) { + this.nonce = new BufferReader(payload).read(8); + return this; +}; + +Ping.prototype.getPayload = function() { + return this.nonce; +}; + +module.exports.Ping = Message.COMMANDS.ping = Ping; + +/** + * Pong Message + * + * @param{Buffer} nonce - a random 8 bytes buffer + */ +function Pong(nonce) { + this.command = 'pong'; + this.nonce = nonce || CONNECTION_NONCE; +} + +util.inherits(Pong, Ping); +module.exports.Pong = Message.COMMANDS.pong = Pong; + +/** + * Addr Message + * + * @param{Array} addresses - array of know addresses + */ +function Addresses(addresses) { + this.command = 'addr'; + this.addresses = addresses || []; +} +util.inherits(Addresses, Message); + +Addresses.prototype.fromBuffer = function(payload) { + var parser = new BufferReader(payload); + var addrCount = Math.min(parser.readVarintNum(), 1000); + + this.addresses = []; + for (var i = 0; i < addrCount; i++) { + // TODO: Time actually depends on the version of the other peer (>=31402) + this.addresses.push({ + time: parser.readUInt32LE(), + services: parser.readUInt64LEBN(), + ip: parser.read(16), + port: parser.readUInt16BE() + }); + } + + return this; +}; + +Addresses.prototype.getPayload = function() { + var put = new Put(); + put.varint(this.addresses.length); + + for (var i = 0; i < this.addresses.length; i++) { + put.word32le(this.addresses[i].time); + put.word64le(this.addresses[i].services); + put.put(this.addresses[i].ip); + put.word16be(this.addresses[i].port); + } + + return put.buffer(); +}; + +module.exports.Addresses = Message.COMMANDS.addr = Addresses; + +/** + * GetAddr Message + * + */ +function GetAddresses() { + this.command = 'getaddr'; +} + +util.inherits(GetAddresses, Message); +module.exports.GetAddresses = Message.COMMANDS.getaddr = GetAddresses; + +/** + * Verack Message + * + */ +function VerAck() { + this.command = 'verack'; +} + +util.inherits(VerAck, Message); +module.exports.VerAck = Message.COMMANDS.verack = VerAck; + +/** + * Reject Message + * + */ +function Reject() { + this.command = 'reject'; +} +util.inherits(Reject, Message); + +// TODO: Parse REJECT message + +module.exports.Reject = Message.COMMANDS.reject = Reject; + +/** + * Alert Message + * + */ +function Alert(payload, signature) { + this.command = 'alert'; + this.payload = payload || new Buffer(32); + this.signature = signature || new Buffer(32); +} +util.inherits(Alert, Message); + +Alert.prototype.fromBuffer = function(payload) { + var parser = new BufferReader(payload); + this.payload = parser.readVarintBuf(); // TODO: Use current format + this.signature = parser.readVarintBuf(); + return this; +}; + +Alert.prototype.getPayload = function() { + var put = new Put(); + put.varint(this.payload.length); + put.put(this.payload); + + put.varint(this.signature.length); + put.put(this.signature); + + return put.buffer(); +}; + +module.exports.Alert = Message.COMMANDS.alert = Alert; + +/** + * Headers Message + * + * @param{Array} blockheaders - array of block headers + */ +function Headers(blockheaders) { + this.command = 'headers'; + this.headers = blockheaders || []; +} +util.inherits(Headers, Message); + +Headers.prototype.fromBuffer = function(payload) { + var parser = new BufferReader(payload); + var count = parser.readVarintNum(); + + this.headers = []; + for (var i = 0; i < count; i++) { + var header = BlockHeaderModel._fromBufferReader(parser); + this.headers.push(header); + } + + return this; +}; + +Headers.prototype.getPayload = function() { + var put = new Put(); + put.varint(this.headers.length); + + for (var i = 0; i < this.headers.length; i++) { + var buffer = this.headers[i].toBuffer(); + put.put(buffer); + } + + return put.buffer(); +}; + +module.exports.Headers = Message.COMMANDS.headers = Headers; + +/** + * Block Message + * + * @param{Block} block + */ +function Block(block) { + this.command = 'block'; + this.block = block; +} +util.inherits(Block, Message); + +Block.prototype.fromBuffer = function(payload) { + this.block = BlockModel(payload); + return this; +}; + +Block.prototype.getPayload = function() { + return this.block.toBuffer(); +}; + +module.exports.Block = Message.COMMANDS.block = Block; + +/** + * Tx Message + * + * @param{Transaction} transaction + */ +function Transaction(transaction) { + this.command = 'tx'; + this.transaction = transaction; +} +util.inherits(Transaction, Message); + +Transaction.prototype.fromBuffer = function(payload) { + this.transaction = TransactionModel(payload); + return this; +}; + +Transaction.prototype.getPayload = function() { + return this.transaction.toBuffer(); +}; + +module.exports.Transaction = Message.COMMANDS.tx = Transaction; + +/** + * Getblocks Message + * + * @param{Array} starts - array of buffers with the starting block hashes + * @param{Buffer} [stop] - hash of the last block + */ +function GetBlocks(starts, stop) { + this.command = 'getblocks'; + this.version = PROTOCOL_VERSION; + this.starts = starts || []; + this.stop = stop || BufferUtil.NULL_HASH; +} +util.inherits(GetBlocks, Message); + +GetBlocks.prototype.fromBuffer = function(payload) { + var parser = new BufferReader(payload); + this.version = parser.readUInt32LE(); + + var startCount = Math.min(parser.readVarintNum(), 500); + this.starts = []; + for (var i = 0; i < startCount; i++) { + this.starts.push(parser.read(32)); + } + this.stop = parser.read(32); + + return this; +}; + +GetBlocks.prototype.getPayload = function() { + var put = new Put(); + put.word32le(this.version); + put.varint(this.starts.length); + + for (var i = 0; i < this.starts.length; i++) { + if (this.starts[i].length !== 32) { + throw new Error('Invalid hash length'); + } + put.put(this.starts[i]); + } + + if (this.stop.length !== 32) { + throw new Error('Invalid hash length'); + } + put.put(this.stop); + + return put.buffer(); +}; + +module.exports.GetBlocks = Message.COMMANDS.getblocks = GetBlocks; + +/** + * Getheaders Message + * + * @param{Array} starts - array of buffers with the starting block hashes + * @param{Buffer} [stop] - hash of the last block + */ +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 = Message.COMMANDS.getheaders = GetHeaders; + + +// TODO: Remove this PATCH (yemel) +Buffers.prototype.skip = function (i) { + if (i === 0) return; + + if (i === this.length) { + this.buffers = []; + this.length = 0; + return; + } + + var pos = this.pos(i); + this.buffers = this.buffers.slice(pos.buf); + this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset)); + this.length -= i; +}; diff --git a/lib/transport/peer.js b/lib/transport/peer.js new file mode 100644 index 0000000..724cd2e --- /dev/null +++ b/lib/transport/peer.js @@ -0,0 +1,192 @@ +'use strict'; + +var Buffers = require('buffers'); +var EventEmitter = require('events').EventEmitter; +var Net = require('net'); +var Socks5Client = require('socks5-client'); +var util = require('util'); + +var Networks = require('../networks'); +var Messages = require('./messages'); + +var MAX_RECEIVE_BUFFER = 10000000; + +/** + * A Peer instance represents a remote bitcoin node and allows to communicate + * with it using the standar messages of the bitcoin p2p protocol. + * + * @example + * + * var peer = new Peer('127.0.0.1').setProxy('127.0.0.1', 9050); + * peer.on('tx', function(tx) { + * console.log('New transaction: ', tx.id); + * }); + * peer.connect(); + * + * @param {String} host - IP address of the remote host + * @param {Number} [port] - Port number of the remote host + * @param {Network} [network] - The context for this communication + * @returns {Peer} A new instance of Peer. + * @constructor + */ +function Peer(host, port, network) { + if (!(this instanceof Peer)) { + return new Peer(host, port, network); + } + + // overloading stuff + if (port instanceof Object && !network) { + network = port; + port = undefined; + } + + this.host = host; + this.status = Peer.STATUS.DISCONNECTED; + this.network = network || Networks.livenet; + this.port = port || this.network.port; + + this.dataBuffer = new Buffers(); + + this.version = 0; + this.bestHeight = 0; + this.subversion = null; + + // set message handlers + var self = this; + this.on('verack', function() { + self.status = Peer.STATUS.READY; + self.emit('ready'); + }); + + this.on('version', function(message) { + self.version = message.version; + self.subversion = message.subversion; + self.bestHeight = message.start_height + }); + + this.on('ping', function(message) { + self.sendPong(message.nonce); + }); + +} +util.inherits(Peer, EventEmitter); + +Peer.STATUS = { + DISCONNECTED: 'disconnected', + CONNECTING: 'connecting', + CONNECTED: 'connected', + READY: 'ready' +}; + +/** + * Set a socks5 proxy for the connection. Enables the use of the TOR network. + * + * @param {String} host - IP address of the proxy + * @param {Number} port - Port number of the proxy + * @returns {Peer} The same Peer instance. + */ +Peer.prototype.setProxy = function(host, port) { + if (this.status != Peer.STATUS.DISCONNECTED) { + throw Error('Invalid State'); + } + + this.proxy = { + host: host, + port: port + }; + return this; +}; + +/** + * Init the connection with the remote peer. + * + * @returns {Socket} The same peer instance. + */ +Peer.prototype.connect = function() { + this.socket = this._getSocket(); + this.status = Peer.STATUS.CONNECTING; + + var self = this; + this.socket.on('connect', function(ev) { + self.status = Peer.STATUS.CONNECTED; + self.emit('connect'); + self._sendVersion(); + }); + + this.socket.on('error', self.disconnect.bind(this)); + this.socket.on('end', self.disconnect.bind(this)); + + this.socket.on('data', function(data) { + self.dataBuffer.push(data); + + if (self.dataBuffer.length > MAX_RECEIVE_BUFFER) return self.disconnect(); + self._readMessage(); + }); + + this.socket.connect(this.port, this.host); + return this; +}; + +/** + * Disconnects the remote connection. + * + * @returns {Socket} The same peer instance. + */ +Peer.prototype.disconnect = function() { + this.status = Peer.STATUS.DISCONNECTED; + this.socket.destroy(); + this.emit('disconnect'); + return this; +}; + +/** + * Send a Message to the remote peer. + * + * @param {Message} message - A message instance + */ +Peer.prototype.sendMessage = function(message) { + this.socket.write(message.serialize(this.network)); +}; + +/** + * Internal function that sends VERSION message to the remote peer. + */ +Peer.prototype._sendVersion = function() { + var message = new Messages.Version(); + this.sendMessage(message); +}; + +/** + * Send a PONG message to the remote peer. + */ +Peer.prototype._sendPong = function(nonce) { + var message = new Messages.Pong(nonce); + this.sendMessage(message); +}; + +/** + * Internal function that tries to read a message from the data buffer + */ +Peer.prototype._readMessage = function() { + var message = Messages.parseMessage(this.network, this.dataBuffer); + + if (message) { + this.emit(message.command, message); + this._readMessage(); + } +}; + +/** + * Internal function that creates a socket using a proxy if neccesary. + * + * @returns {Socket} A Socket instance not yet connected. + */ +Peer.prototype._getSocket = function() { + if (this.proxy) { + return new Socks5Client(this.proxy.host, this.proxy.port); + } + + return new Net.Socket(); +}; + +module.exports = Peer; diff --git a/lib/util/buffer.js b/lib/util/buffer.js index 73a60b3..f7de3cd 100644 --- a/lib/util/buffer.js +++ b/lib/util/buffer.js @@ -19,6 +19,21 @@ function equals(a, b) { } module.exports = { + /** + * Fill a buffer with a value. + * + * @param {Buffer} buffer + * @param {number} value + * @return {Buffer} + */ + fill: function fill(buffer, value) { + var length = buffer.length; + for (var i = 0; i < length; i++) { + buffer[i] = value; + } + return buffer; + }, + /** * Returns true if the given argument is an instance of a buffer. Tests for * both node's Buffer and Uint8Array @@ -136,3 +151,6 @@ module.exports = { return new buffer.Buffer(string, 'hex'); } }; + +module.exports.NULL_HASH = module.exports.fill(new Buffer(32), 0); +module.exports.EMPTY_BUFFER = new Buffer(0); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index cd8ea4c..1f09939 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -22,6 +22,16 @@ "from": "bs58@2.0.0", "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.0.tgz" }, + "bufferput": { + "version": "0.1.2", + "from": "bufferput@0.1.2", + "resolved": "https://registry.npmjs.org/bufferput/-/bufferput-0.1.2.tgz" + }, + "buffers": { + "version": "0.1.1", + "from": "buffers@0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz" + }, "elliptic": { "version": "0.15.12", "from": "elliptic@0.15.12", @@ -78,6 +88,11 @@ "version": "0.0.1", "from": "sha512@=0.0.1", "resolved": "https://registry.npmjs.org/sha512/-/sha512-0.0.1.tgz" + }, + "socks5-client": { + "version": "0.3.6", + "from": "socks5-client@0.3.6", + "resolved": "https://registry.npmjs.org/socks5-client/-/socks5-client-0.3.6.tgz" } } } diff --git a/package.json b/package.json index 8af7aab..bfe4649 100644 --- a/package.json +++ b/package.json @@ -74,13 +74,16 @@ "asn1.js": "=0.4.1", "bn.js": "=0.15.2", "bs58": "=2.0.0", + "bufferput": "^0.1.2", + "buffers": "^0.1.1", "elliptic": "=0.15.14", "hash.js": "=0.3.2", "inherits": "=2.0.1", "jsrsasign": "=0.0.3", "lodash": "=2.4.1", "protobufjs": "=3.0.0", - "sha512": "=0.0.1" + "sha512": "=0.0.1", + "socks5-client": "^0.3.6" }, "devDependencies": { "brfs": "1.2.0", @@ -97,9 +100,7 @@ "run-sequence": "^1.0.2", "karma": "^0.12.28", "karma-firefox-launcher": "^0.1.3", - "karma-mocha": "^0.1.9", - "mocha": "~2.0.1", - "run-sequence": "^1.0.2" + "karma-mocha": "^0.1.9" }, "license": "MIT" } diff --git a/test/data/messages.js b/test/data/messages.js new file mode 100644 index 0000000..d7d6e92 --- /dev/null +++ b/test/data/messages.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = { + VERSION: { + message: 'f9beb4d976657273696f6e000000000065000000fc970f17721101000100000000000000ba62885400000000010000000000000000000000000000000000ffffba8886dceab0010000000000000000000000000000000000ffff05095522208de7e1c1ef80a1cea70f2f5361746f7368693a302e392e312fa317050001', + payload: '721101000100000000000000ba62885400000000010000000000000000000000000000000000ffffba8886dceab0010000000000000000000000000000000000ffff05095522208de7e1c1ef80a1cea70f2f5361746f7368693a302e392e312fa317050001' + }, + VERACK: { + message: 'f9beb4d976657261636b000000000000000000005df6e0e2', + payload: '' + }, + INV: { + message: 'f9beb4d9696e76000000000000000000890200006e4f18431201000000f97347795bf7490ddeba98c129086f54e06633936a49a2a398defb49e5edbb00010000009cb17394db9280b2d5e7d9f01456358384e7453300d48138ca1590e8cd86632f010000000f810b6071b9808117c4b82619b4ae0a7994ed5a0f2c050e50fd5742c3b4e90901000000962798bce9cbfcee9a8c6b5df4cf8bed944eb31ec975e8c1be79b7ab010a1cb501000000baa905bcfc9d2641ecd759724f796a7614e91c7492507b418ba8e077a6e57054010000009a5ac6dae146392edf8b6e96c30951ed7752f9095fab61728207db0f135b18a30100000050e5f153e3f0d89ea432d9a26f088a89b3ca38dbf3f0247ddf15f80779915da801000000c255841510a284b88ba696ed9edfeb4cdb34966271c30bc3bce9fd881106850f0100000000e45af8455894f72cccc4053e1f5e6076a673982b1f4ca5b2abc7b6496823ab01000000c7e6dc049e5b0fdc0f8fac8934e84e9b2f0c3036c7c02638cc05ee2575d6be1701000000aef6435c03c99ee83702aaaf106dc853dee5bcb6025f3af67d1ec72202c437ad010000005369fc3dc81403fe52f766ef585245af908404be1b46e2ef67c93b748ef467e3010000002400f16a63c411ae5e336175afc26515e548c7267c0debdb6aa46830399ba35f01000000ceb4fa6a8ca2713baee2214422b73da47a20934c83d25017bd80053e65ef3091010000000d899968e591703ddd6fd6ce073837588209f8b3b245ecf1bf93e77b9806a6c501000000bddeb56581ad7882d8f2abc78e5a48b3de02d923cd1cfc7525d2dfe80470248a01000000f286188c0947b023f0ba5dd1ea596751d50f67fbe31e64ead39dd711d3585b5801000000e17ad100ebffd2d5a630d37fd2496b2f5ab6ae5c8812da3c642fb6b8dd37f5fd', + payload: '1201000000f97347795bf7490ddeba98c129086f54e06633936a49a2a398defb49e5edbb00010000009cb17394db9280b2d5e7d9f01456358384e7453300d48138ca1590e8cd86632f010000000f810b6071b9808117c4b82619b4ae0a7994ed5a0f2c050e50fd5742c3b4e90901000000962798bce9cbfcee9a8c6b5df4cf8bed944eb31ec975e8c1be79b7ab010a1cb501000000baa905bcfc9d2641ecd759724f796a7614e91c7492507b418ba8e077a6e57054010000009a5ac6dae146392edf8b6e96c30951ed7752f9095fab61728207db0f135b18a30100000050e5f153e3f0d89ea432d9a26f088a89b3ca38dbf3f0247ddf15f80779915da801000000c255841510a284b88ba696ed9edfeb4cdb34966271c30bc3bce9fd881106850f0100000000e45af8455894f72cccc4053e1f5e6076a673982b1f4ca5b2abc7b6496823ab01000000c7e6dc049e5b0fdc0f8fac8934e84e9b2f0c3036c7c02638cc05ee2575d6be1701000000aef6435c03c99ee83702aaaf106dc853dee5bcb6025f3af67d1ec72202c437ad010000005369fc3dc81403fe52f766ef585245af908404be1b46e2ef67c93b748ef467e3010000002400f16a63c411ae5e336175afc26515e548c7267c0debdb6aa46830399ba35f01000000ceb4fa6a8ca2713baee2214422b73da47a20934c83d25017bd80053e65ef3091010000000d899968e591703ddd6fd6ce073837588209f8b3b245ecf1bf93e77b9806a6c501000000bddeb56581ad7882d8f2abc78e5a48b3de02d923cd1cfc7525d2dfe80470248a01000000f286188c0947b023f0ba5dd1ea596751d50f67fbe31e64ead39dd711d3585b5801000000e17ad100ebffd2d5a630d37fd2496b2f5ab6ae5c8812da3c642fb6b8dd37f5fd' + }, + ADDR: { + message: 'f9beb4d9616464720000000000000000b93a0000480bab8afdf5016816fa53010000000000000000000000000000000000ffff51403eea208ddb2a8854010000000000000000000000000000000000ffff707c60d9208d31413a54010000000000000000000000000000000000ffff5ed5fd13208d182c8854010000000000000000000000000000000000ffff505f3f81208d65ecb853010000000000000000000000000000000000ffff54d72104208dcca94054010000000000000000000000000000000000ffff40bbe1f2208d73238854010000000000000000000000000000000000ffff55d683cd208d5d258854010000000000000000000000000000000000ffffd523a66d208dcbea87540100000000000000200100005ef579fd2c9d47be4b56d671208db3e58754010000000000000000000000000000000000ffffae373156208d11e58754810000000000000000000000000000000000ffff51071276208d38f48754010000000000000000000000000000000000ffff6d4372e0208d4f448854010000000000000000000000000000000000ffffc556cbea208deb208854010000000000000000000000000000000000ffff450eb059208d97336054010000000000000000000000000000000000ffff4d60444a208dad608754010000000000000000000000000000000000ffff01abd3c3208d2cbe8754010000000000000000000000000000000000ffff7963d8b8208d9dfa8754010000000000000000000000000000000000ffffcebe862c208da7f66554010000000000000000000000000000000000ffff62f2a82e208d430d8854010000000000000000000000000000000000ffff6deb6956208d08148854010000000000000000000000000000000000ffff4b9804ef208d950e8854010000000000000000000000000000000000ffff6b8dd2e1208d1cfc8754010000000000000000000000000000000000ffffb2fe1dab208de7458754010000000000000000000000000000000000ffff32cccb82208d12625654010000000000000000000000000000000000ffff55e6f35a208dd7908354010000000000000000000000000000000000ffff4c642e6f208d17398854010000000000000000000000000000000000ffff45ea14df208dc72d8854010000000000000000000000000000000000ffffdaa48b96208d57fb8654010000000000000000000000000000000000ffff5f0080a9208d4e9a6d54010000000000000000000000000000000000ffff6d94e741208d7a418854010000000000000000000000000000000000ffff6d43b0c1208d5c098854010000000000000000000000000000000000ffff9c11e7ea208d442d8854010000000000000000000000000000000000ffffd0424482208db142fb53010000000000000000000000000000000000ffff54344a4a208d70158854010000000000000000000000000000000000ffff538f8201208d39288854010000000000000000000000000000000000ffff57daab71208d262f8854010000000000000000000000000000000000ffff57e045b1208d91430654010000000000000000000000000000000000ffff4212def5208d7c468854010000000000000000000000000000000000ffff62a4f53b208d9c3e8854010000000000000000000000000000000000ffff5b736bcc208d4d074f54010000000000000000000000000000000000ffff43af9d9b208deaca8754010000000000000000000000000000000000ffff4a8084a0208d74f68754010000000000000000000000000000000000ffff46304541208d5d098854010000000000000000000000000000000000ffff6eabb626208d08228854010000000000000000000000000000000000ffff1f07b030208d959a8254010000000000000000000000000000000000ffff4fa996b3208d4bac8754010000000000000000000000000000000000ffff43a0605b208de4038854010000000000000000000000000000000000ffff4cb41a5b208ddc308854010000000000000000000000000000000000ffffb72e6072208deac86f54010000000000000000000000000000000000ffffd5b815e2208d1b118854010000000000000000000000000000000000ffff3ff8d0a4208db1258854010000000000000000000000000000000000ffff5edd3a6a208d20268754010000000000000000000000000000000000ffff59ed3cfc208d83ed8754010000000000000000000000000000000000ffff4460baea208d71278854010000000000000000000000000000000000ffff4583b547208da7968754010000000000000000000000000000000000ffffd1c34463208d9d428854010000000000000000000000000000000000ffff43c15bc5208d33448854010000000000000000000000000000000000ffff2e0d8a5c208dfa2e7154010000000000000000000000000000000000ffffceff2bca208d47288854010000000000000000000000000000000000ffff5b8d0190208d0e847954010000000000000000000000000000000000ffff5501b8c2208d552f8854010000000000000000000000000000000000ffff5cf3b604208d8c2e8854010000000000000000000000000000000000ffff58666b0d208dcbdd8754010000000000000000000000000000000000ffff59a85cf9208d04208854010000000000000000000000000000000000ffff5f60abe0208dba238854010000000000000000000000000000000000ffff2e77ce67208d62c68754010000000000000000000000000000000000ffffcbae5658208d41108854010000000000000000000000000000000000ffff49329ec8208ddf1d8854010000000000000000000000000000000000ffff603ada12208df90c8854010000000000000000000000000000000000ffff51e0c21c208d5dff8754010000000000000000000000000000000000ffff904ca539208de0118854010000000000000000000000000000000000ffff5c0cecf7208d1b2d88540100000000000000200100005ef579fb18f317b2aba4edfc208dfaa27f54010000000000000000000000000000000000ffff54c65a7c208dc2db8754010000000000000000000000000000000000ffffad0b7981208d88a58754010000000000000000000000000000000000ffff188a1995208de0d78754010000000000000000000000000000000000ffff62a7a6bd208d18f66b54010000000000000000000000000000000000ffffdb4fbe80208dfcf78754010000000000000000000000000000000000ffff67145102208d3d3a8854010000000000000000000000000000000000ffff64259bd6208dcaa98654010000000000000000000000000000000000ffff32c737e1208d3a6a5c54010000000000000000000000000000000000ffff6d793f75208d22d38754010000000000000000000000000000000000ffff0595cc0d208da9ea8754010000000000000000000000000000000000ffff62ca37d3208d440e8854010000000000000000000000000000000000ffff123e1c11208dab428854010000000000000000000000000000000000ffff461df51f208d0f0b8854010000000000000000000000000000000000ffff59d36752208d631f8854010000000000000000000000000000000000ffff5ef8c640208dbc1d8854010000000000000000000000000000000000ffff5f5dc582208d04bf8754010000000000000000000000000000000000ffff0e6797e3208db8028854010000000000000000000000000000000000ffff3cf0c4a1208d6a0c8854010000000000000000000000000000000000ffff58bb5c55208d4f438854010000000000000000000000000000000000ffff5d326005208df6068854010000000000000000000000000000000000ffff5d5a5850208d40eb8754010000000000000000000000000000000000ffff5751ed86208dbad18754010000000000000000000000000000000000ffff63e51608208d99108854010000000000000000000000000000000000ffff36e299cd208d9a1e88540100000000000000200100005ef579fd38a43785a5d441b7208d13258854010000000000000000000000000000000000ffffb90de279208db3778754010000000000000000000000000000000000ffff67fcc80c208d3d358854010000000000000000000000000000000000ffffd00c40fc208dfd0d8854010000000000000000000000000000000000ffff5e89c2f3208dd6428854010000000000000000000000000000000000ffff1863e14a208d89e78754010000000000000000000000000000000000ffff43a11d76208d89ce8754010000000000000000000000000000000000ffff3edb6281208d03298854010000000000000000000000000000000000ffff6d5b26dd208d16df6e54010000000000000000000000000000000000ffffd9c3d176208d7c028854010000000000000000000000000000000000ffffbcc2db1f208d67fc8754010000000000000000000000000000000000ffff59910667208d86b18754010000000000000000000000000000000000ffff6c1482b9208d790b8854010000000000000000000000000000000000ffff0263150d208d89c44554010000000000000000000000000000000000ffff72fcd6b8208d331c8854010000000000000000000000000000000000ffff4c7dcfa8208d9fe98754010000000000000000000000000000000000ffffad08fd05208d0ecd8754010000000000000000000000000000000000ffff7c0fec89208d4af98754010000000000000000000000000000000000ffff2ea6a167208d270b8854010000000000000000000000000000000000ffff59d40fca208d11cf4054010000000000000000000000000000000000ffffb52ac058208d63358254010000000000000000000000000000000000ffff6bd9a130208dbde48754010000000000000000000000000000000000ffff4f915dc7208dece78754010000000000000000000000000000000000ffff5f8423ef208dba308854010000000000000000000000000000000000ffff904cba8c208d953d8854010000000000000000000000000000000000ffff8d1421e5208d5f188854010000000000000000000000000000000000ffff4e1bbfb6208d36fc8754010000000000000000000000000000000000ffff3205cfb6208d5e458854010000000000000000000000000000000000ffff493092c2208dd0878754010000000000000000000000000000000000ffff97caacde208dd99d8754010000000000000000000000000000000000ffffc05f3c38208da7018854010000000000000000000000000000000000ffffdcf5f82d208df0f42254010000000000000000000000000000000000ffff58bf997f208d94228854010000000000000000000000000000000000ffffbc8ee72d208de3448854010000000000000000000000000000000000ffff6d780f99208d32448854010000000000000000000000000000000000ffffbc64c76e208d0b3d8854010000000000000000000000000000000000ffff6c414312208d49138854010000000000000000000000000000000000ffff407e52c6208d2d128854010000000000000000000000000000000000ffff6dc987d8208d4acf8754010000000000000000000000000000000000ffffae151a25208de9dd8754010000000000000000000000000000000000ffff522d2d10208d17df8754010000000000000000000000000000000000ffff4d294737208ddbd48754010000000000000000000000000000000000ffff443703fd208d79108854010000000000000000000000000000000000ffff4bb5a154208d1df28753010000000000000000000000000000000000ffff4c44fc51208d5d496a53010000000000000000000000000000000000ffff530924b0208d180b8854010000000000000000000000000000000000ffffc15fced3208d53128854010000000000000000000000000000000000ffff5bc5b9e4208de21f8854010000000000000000000000000000000000ffff2e05fe1f208d31ab6554010000000000000000000000000000000000ffffae865915208d09248854010000000000000000000000000000000000ffff7d71a4b0208d120b8854010000000000000000000000000000000000ffff93e40150208d25d98754010000000000000000000000000000000000ffffc19f7a86208d99e78754010000000000000000000000000000000000ffff4d675993208d2b218854010000000000000000000000000000000000ffff5144776c208d5a208854010000000000000000000000000000000000ffff2e1cce5820f69e8f8154010000000000000000000000000000000000ffff58718848208d9edd6554010000000000000000000000000000000000ffff2ea758c5208d28c98754010000000000000000000000000000000000ffffc60bd694208d181d8854010000000000000000000000000000000000ffffba6b689e208d77868754010000000000000000000000000000000000ffff182016aa208de1698054010000000000000000000000000000000000ffff5cf5daa9208d823d8854010000000000000000000000000000000000ffffbe4d61c8208d2c3b8854010000000000000000000000000000000000ffff71647df2208da2248854010000000000000000000000000000000000ffff4ff359ca208da2dd8754010000000000000000000000000000000000ffff59f1e52b208da6e60d54010000000000000000000000000000000000ffff579596231159ad218854010000000000000000000000000000000000ffff5895f42d208d5ba78754010000000000000000000000000000000000ffff458ae8b0208ddc9b8754010000000000000000000000000000000000ffff18b507a5208d20eb5754010000000000000000000000000000000000ffff5181a537208daf1d8854010000000000000000000000000000000000ffffd5f51eba208d07f58754010000000000000000000000000000000000ffff6dec54bc208d4b3b8854010000000000000000000000000000000000ffff5c3e1991208d13b54054010000000000000000000000000000000000ffffb273845a208d4f338854010000000000000000000000000000000000ffffcfac797b208d4d898754010000000000000000000000000000000000ffffadaf880d208de72f8854010000000000000000000000000000000000ffffd956ef58208dc1e98754010000000000000000000000000000000000ffff980711cf208dfd8f7154010000000000000000000000000000000000ffff50aba98f208d59fe8754010000000000000000000000000000000000ffff5f2ae582208d3ffa8754010000000000000000000000000000000000ffffbca836db208d389b0054010000000000000000000000000000000000ffffded10925208deb154354010000000000000000000000000000000000ffff717532da208dadde7654010000000000000000000000000000000000ffff93afd0e5208d40458854010000000000000000000000000000000000ffff54ee8cb0208d08fa8754010000000000000000000000000000000000ffff3658eba9208d0df58754010000000000000000000000000000000000ffff72c6876e208d5d408854010000000000000000000000000000000000ffffa7582d7c208de8338854010000000000000000000000000000000000ffffad40d7ad208d6c2a8854010000000000000000000000000000000000ffffbc1833a3208d0fc28754010000000000000000000000000000000000ffffcbceb676208d98448854010000000000000000000000000000000000ffff0121ce6e208d77b58754010000000000000000000000000000000000ffff4b40d938208d853b8854010000000000000000000000000000000000ffff5648d643208d1c9c7854010000000000000000000000000000000000ffff6c3230db208d4e028754010000000000000000000000000000000000ffffd8e33c5d208daf738754010000000000000000000000000000000000ffffad4e9d56208dca438854010000000000000000000000000000000000ffff4f8a0353208d7b408854010000000000000000000000000000000000ffff0599e92a208dc62f8854010000000000000000000000000000000000ffff46236049208dc4d58754010000000000000000000000000000000000ffff4400384d208d0ddb4c54010000000000000000000000000000000000ffff71653b5a208d53388854010000000000000000000000000000000000ffff43bddf66208d7c388854010000000000000000000000000000000000ffff47edca96208d8c068854010000000000000000000000000000000000ffffdded3c2c208d89f60554010000000000000000000000000000000000ffff4e60d8d6208da5ff1154010000000000000000000000000000000000ffff55983c68208d72f58754010000000000000000000000000000000000ffffce47f56a208d7e2d8854010000000000000000000000000000000000ffff17e25c12208da7ca8754010000000000000000000000000000000000ffff051d0baa208d19af8754010000000000000000000000000000000000ffffad42d883208dffd68754010000000000000000000000000000000000ffff5418ff88208d87bf8754010000000000000000000000000000000000ffff4c1fe0dc208deef18754010000000000000000000000000000000000ffff4c71d406208d25868754010000000000000000000000000000000000ffffda67a475208d4d348854010000000000000000000000000000000000ffff5d561269208da5918754010000000000000000000000000000000000ffff42b163b3208dbfac3754010000000000000000000000000000000000ffffad4e01eb208d5c408854010000000000000000000000000000000000ffffcc0bb91e208d4a928754010000000000000000000000000000000000ffff531dba30208db9fd8754010000000000000000000000000000000000ffffa3f72b33208dade58754010000000000000000000000000000000000ffffd8b93aeb208db75d4d54010000000000000000000000000000000000ffffae1d5595208de8d18754010000000000000000000000000000000000ffff4405665c208d88e78754010000000000000000000000000000000000ffff6b96180a208dae667354010000000000000000000000000000000000ffff531f490a208d92f98754010000000000000000000000000000000000ffffd447e857208db1428854010000000000000000000000000000000000ffff36c6b4bb208dd42c8854010000000000000000000000000000000000ffff4b4aff14208df71acd53010000000000000000000000000000000000ffff62d17930208da0b88754010000000000000000000000000000000000ffff974bf913208d5faa7953010000000000000000000000000000000000ffff7419d269208d6c1e8854010000000000000000000000000000000000ffff48a72343208d9c2b8854010000000000000000000000000000000000ffff64431e87208de8908754010000000000000000000000000000000000ffff44660d45208d410b7d54010000000000000000000000000000000000ffff43a3340d208d5b298854010000000000000000000000000000000000ffff9ffda678208de7238854010000000000000000000000000000000000ffff189a3759208da5745354010000000000000000000000000000000000ffff57026e31208df23c885401000000000000002a010488006710000523fbe100000001208dddf48754010000000000000000000000000000000000ffffc1531c5b208d61888754010000000000000000000000000000000000ffff42cd8bc1208df92e8854010000000000000000000000000000000000ffff36e1e970208d0cf75754010000000000000000000000000000000000ffffad4e2420208d0f028854010000000000000000000000000000000000ffff6ec61b02208de6228854010000000000000000000000000000000000ffffdcaa807c208d1cac8754010000000000000000000000000000000000ffff6179416c208db6068854010000000000000000000000000000000000ffffd46121e4208d7ea58754010000000000000000000000000000000000ffff80a41679208d91216254010000000000000000000000000000000000ffff69ece091208d0bf78754010000000000000000000000000000000000ffff45320c0b208dd03c8854010000000000000000000000000000000000ffff4859a2a5208d8e308854010000000000000000000000000000000000ffff2e1ce15a208d30f36354010000000000000000000000000000000000ffff4b61ee15208d7aa05553010000000000000000000000000000000000ffffb129186b208dbb238854010000000000000000000000000000000000ffff581a7f6f208d41248754010000000000000000000000000000000000ffffb009055b208dee218854010000000000000000000000000000000000ffff2e7771f9208db4e78754010000000000000000000000000000000000ffff411bf6ee208db5178854010000000000000000000000000000000000ffffacff001b208dbcf487540100000000000000200100009d386ab83061cfabfe3513a3208d76048854010000000000000000000000000000000000ffff2e35dbc2208d83d28754010000000000000000000000000000000000ffffd91bb1d5208d5c3d8854010000000000000000000000000000000000ffff32a47969208df4bd875401000000000000002a0104f8012032250000000000000002208d1bfa8754010000000000000000000000000000000000ffff53a2f4b6208d141c4554010000000000000000000000000000000000ffffb27b8281208d580c7e54010000000000000000000000000000000000ffffc9ea1340208df7228854010000000000000000000000000000000000ffffd90a268d208d41e18754010000000000000000000000000000000000ffff555b8809208d66358854010000000000000000000000000000000000ffff5280ff23208deecd8754010000000000000000000000000000000000ffff84c6a102208df9bc8754010000000000000000000000000000000000ffffbbc96dae208d9d0a8854010000000000000000000000000000000000ffffb2a2d18a208da9458854010000000000000000000000000000000000ffffca16c30e208d2ca88754010000000000000000000000000000000000ffff6baab63e208d923b8854010000000000000000000000000000000000ffffd5b87bee208d12258854010000000000000000000000000000000000ffff59ee408b208d980e8854010000000000000000000000000000000000ffff2edfb0c4208d33378854010000000000000000000000000000000000ffff6caa7b42208d41176d53010000000000000000000000000000000000ffff1fa2df68208dd1c57f54010000000000000000000000000000000000ffffbeab679a208d17c78754010000000000000000000000000000000000ffff3f983f51208dbb278854010000000000000000000000000000000000ffff568dbc28208d5d5ad953010000000000000000000000000000000000ffff0ec112b7208da1b78754010000000000000000000000000000000000ffffbc287698208d99348854010000000000000000000000000000000000ffff5ff1a302208d23ef8454010000000000000000000000000000000000ffff7ba55d22208d90e98754010000000000000000000000000000000000ffff5ae14503208d58f48754010000000000000000000000000000000000ffffd45a3cae208d530c8854010000000000000000000000000000000000ffff18fb80c4208dc6138854010000000000000000000000000000000000ffff4e2fd6eb208d97208854010000000000000000000000000000000000ffff55ddd5b8208d74f88654010000000000000000000000000000000000ffff1809ad86208dc0278854010000000000000000000000000000000000ffff6ef2dfb6208d84338854010000000000000000000000000000000000ffff58d8114e208dcae78754010000000000000000000000000000000000ffffc21c474c208d61e78754010000000000000000000000000000000000ffffd5b3fc7a208d7a078854010000000000000000000000000000000000ffff32740193208de7547b54010000000000000000000000000000000000ffff8046aac3208db5328854010000000000000000000000000000000000ffff5b0c5366208d5f208854010000000000000000000000000000000000ffff6caa054a208d1d682854010000000000000000000000000000000000ffff69e3eb9d208d179e6b54010000000000000000000000000000000000ffff54aac628208ded2e8854010000000000000000000000000000000000ffff4166d226208d8e148854010000000000000000000000000000000000ffff54305af6208d1ed88754010000000000000000000000000000000000ffff3ed2b2a4208d78ec8554010000000000000000000000000000000000ffff6dd2e575208ddd3e7854010000000000000000000000000000000000ffff1b83a102208d421e8854010000000000000000000000000000000000ffff2eb51bf1208dc01f8854010000000000000000000000000000000000ffff58c66033208d08ce8754010000000000000000000000000000000000ffff5d57b84c208df22e8854010000000000000000000000000000000000ffffbf213e3d208d89cb8754010000000000000000000000000000000000ffff53d7ece1208da9d68754010000000000000000000000000000000000ffff71bef412208d38268854010000000000000000000000000000000000ffff84fc8a6f208d4f107254010000000000000000000000000000000000ffff57a072d9208d990f88540100000000000000200100009d3890d71029db21863020f9208df3c36854010000000000000000000000000000000000ffffbba6a6c4208d3ea71f54010000000000000000000000000000000000ffff3e61237b208d60a18754010000000000000000000000000000000000ffff53a56b4b208db2328854010000000000000000000000000000000000ffff44eef265208d2c0f8854010000000000000000000000000000000000ffff566553c0208dec268854010000000000000000000000000000000000ffff57a69ecd208d93148854010000000000000000000000000000000000ffff9b8f4433208d741b8854010000000000000000000000000000000000ffffae17c74c208ddab94f54010000000000000000000000000000000000ffffab19c63a208d5e886f54010000000000000000000000000000000000ffffbc67a037208d5c3ccc53010000000000000000000000000000000000ffff0e77c86e208d26fb8754010000000000000000000000000000000000ffffc1eae172208d61278854010000000000000000000000000000000000ffff5ce15439208d60df8754010000000000000000000000000000000000ffff2599fb3b208d52418854010000000000000000000000000000000000ffff028710e6208dae448854010000000000000000000000000000000000ffff18152eee208d6ff18754010000000000000000000000000000000000ffff542e396d208d8c248854010000000000000000000000000000000000ffff5519d6d8208d01e33e54010000000000000000000000000000000000ffff5027d563208d05cd8754010000000000000000000000000000000000ffff45a5a9c5208d7c1e8854010000000000000000000000000000000000ffff68c813c8208d38a48754010000000000000000000000000000000000ffff3a60a934208d73ec8754010000000000000000000000000000000000ffffae3db8f3208d096c8754010000000000000000000000000000000000ffff4cb88802208d55d38754010000000000000000000000000000000000ffffd31f082e208d0d8a8754010000000000000000000000000000000000ffff6c22c9bb208d81ba7754010000000000000000000000000000000000ffffca5f88da208d5df88754010000000000000000000000000000000000ffffc31abc05208db1d58754010000000000000000000000000000000000ffff5cf614c8208d2b257c54010000000000000000000000000000000000ffff45f9baa0208d38d78754010000000000000000000000000000000000ffff490e0608208d27e88754010000000000000000000000000000000000ffff17f1ccd0208d501c8854010000000000000000000000000000000000ffff5be834a7208d860b8854010000000000000000000000000000000000ffff640173bc208deada8754010000000000000000000000000000000000ffffdc98f8db208d983d3c54010000000000000000000000000000000000ffff021ab398208d99f28754010000000000000000000000000000000000ffff59a9e417208d19468854010000000000000000000000000000000000ffff91ff01a1208ddbf68754010000000000000000000000000000000000ffff50048949208d89118854010000000000000000000000000000000000ffffc8366923208dea3b8854010000000000000000000000000000000000ffffbcbbb5a9208d364a8854010000000000000000000000000000000000ffffc654bd58208dd52ef953010000000000000000000000000000000000ffff7cabb7bc208db086cc53010000000000000000000000000000000000ffff6c4004ea208d0ff48754010000000000000000000000000000000000ffff0536a3cb208d1c0b8854010000000000000000000000000000000000ffffd90bfef3208dbf188854010000000000000000000000000000000000ffff0252431f208dd1c78754010000000000000000000000000000000000ffff25732b19208dd6fa3954010000000000000000000000000000000000ffff6c1131dc208da6108854010000000000000000000000000000000000ffff1fb9b748208daf368854010000000000000000000000000000000000ffff1f2a2981208d9e2f8854010000000000000000000000000000000000ffffbc658482208d6a458854010000000000000000000000000000000000ffff568b843a208dcd428854010000000000000000000000000000000000ffff5d820794208d38258854010000000000000000000000000000000000ffff6440c630208d1cda8754010000000000000000000000000000000000ffff6e9f7be5208ddd388854010000000000000000000000000000000000ffff9f080244208d2e2d8854010000000000000000000000000000000000ffffbb70cf3d208d3e0c8854010000000000000000000000000000000000ffff3ec27a16208d89098854010000000000000000000000000000000000ffffb55fb2fb208d13468854010000000000000000000000000000000000ffff180ab1e5208dfc2a8854010000000000000000000000000000000000ffffd58a5c0e208db9188854010000000000000000000000000000000000ffff81ce808d208d03d06b54010000000000000000000000000000000000ffff4b496858208d319e8454010000000000000000000000000000000000ffff531fac9f208dc8d98754010000000000000000000000000000000000ffffc113e4ea208d06395754010000000000000000000000000000000000ffff7cabf0d6208d722b8854010000000000000000000000000000000000ffff545db4cd208dd91f8854010000000000000000000000000000000000ffff5f12a597208dfbd57054010000000000000000000000000000000000ffff3cf654e6208dd7358854010000000000000000000000000000000000ffffb4998e79208dd7018854010000000000000000000000000000000000ffffb45cc220208d86df5554010000000000000000000000000000000000ffff7660d462208decd28754010000000000000000000000000000000000ffff5b7bdfe2208dafe28754010000000000000000000000000000000000ffff2e76899e208d0c318854010000000000000000000000000000000000ffffc7bcb183208d35258854010000000000000000000000000000000000ffff3ab2d076208db5c38754010000000000000000000000000000000000ffff48b24d30208ddfd18754010000000000000000000000000000000000ffff904cb00c208d40478854010000000000000000000000000000000000ffff02a3b787208deb318854010000000000000000000000000000000000ffffd2564026208de63f8854010000000000000000000000000000000000ffff615d16c0208dbf1d8854010000000000000000000000000000000000ffffc6fff6f0208d4aee8754010000000000000000000000000000000000ffff56c74bc8208d68bc8754010000000000000000000000000000000000ffff31b581f9208ddcca8754010000000000000000000000000000000000ffff0e97397a208db2318854010000000000000000000000000000000000ffffc766348d208de1bd8754010000000000000000000000000000000000ffffd5927a3d208d2aff8754010000000000000000000000000000000000ffff5152d0a5208da7feb753010000000000000000000000000000000000ffff53fe1694208de7418854010000000000000000000000000000000000ffff189f3d99208de7b38754010000000000000000000000000000000000ffff64004655208dacabb653010000000000000000000000000000000000ffff55413231208d43b88754010000000000000000000000000000000000ffff796e1029208d03788754010000000000000000000000000000000000ffff49b90ff6208d04be8754010000000000000000000000000000000000ffffc327ce1c208d33648254010000000000000000000000000000000000ffff2e896478208d9e308854010000000000000000000000000000000000ffffd395d9bf208df13e8854010000000000000000000000000000000000ffff51bb88ed208dec8c5653010000000000000000000000000000000000ffff557f146e208df4538854010000000000000000000000000000000000ffff48d05928208d41bd8154010000000000000000000000000000000000ffff47384162208df6428854010000000000000000000000000000000000ffffc1566314208d753e8854010000000000000000000000000000000000ffff440c9b4f208d2f078854010000000000000000000000000000000000ffff56021a19208d7b0f4754010000000000000000000000000000000000ffff71653a84208dcee88754010000000000000000000000000000000000ffff5401a332208df4db8754010000000000000000000000000000000000ffff5a9db0e3208df8e38754010000000000000000000000000000000000ffff5d5208fa208d2e298854010000000000000000000000000000000000ffff4c61c0bc208d42ea8754010000000000000000000000000000000000ffff4c405ae7208deade8754010000000000000000000000000000000000ffffc009c823208d99358854010000000000000000000000000000000000ffff6cc2b493208df3fd8754010000000000000000000000000000000000ffff904c6007208d1fde8754010000000000000000000000000000000000ffff92732ae8208d666e8354010000000000000000000000000000000000ffff6daa9d16208d18f78754010000000000000000000000000000000000ffff4d6d8d8a208ddea9ce53010000000000000000000000000000000000ffff17e26f7d208d1ae48754010000000000000000000000000000000000ffffc32ebb89208dee258854010000000000000000000000000000000000ffff4a0f10e1208d290a8854010000000000000000000000000000000000ffff42731593208d7cb33354010000000000000000000000000000000000ffff532e8b97208dfd1e8854010000000000000000000000000000000000ffff6ee91680208d480a1354010000000000000000000000000000000000ffff60f220f6208d55838754010000000000000000000000000000000000ffff1f36d48f208d247e8754010000000000000000000000000000000000ffff44b5a49a208d0efa4954010000000000000000000000000000000000ffff63890597208d862e8854010000000000000000000000000000000000ffffc14d8751208d443c8854010000000000000000000000000000000000ffff70d16dba208d72fe8754010000000000000000000000000000000000ffff55983dd3208d236b6854010000000000000000000000000000000000ffff7aea27f9208d67e08754010000000000000000000000000000000000ffff1b20750d208df10a7154010000000000000000000000000000000000ffff7b9fe56e208db32d8854010000000000000000000000000000000000ffff7ba42d54208db3f58754010000000000000000000000000000000000ffff027b4eba208d70d68754010000000000000000000000000000000000ffffbc1b62b9208d97951454010000000000000000000000000000000000ffffb4b6af10208d251288540100000000000000200100009d386ab800773149c4d7e673208d7b168854010000000000000000000000000000000000ffff58969392208d91d18754010000000000000000000000000000000000ffff9ffd6d4e208d19008854010000000000000000000000000000000000ffff4e926cb8208dd1c98754010000000000000000000000000000000000ffff546cdb77208d6a0a8854010000000000000000000000000000000000ffff6caa8c15208d3a3a8854010000000000000000000000000000000000ffff62e28d6a208d3fe48754010000000000000000000000000000000000ffffd9850be7208dcb438854010000000000000000000000000000000000ffff6c2444b3208d78338854010000000000000000000000000000000000ffffb2df574a208d3b2d3054010000000000000000000000000000000000ffff4b529e67208d5b988754010000000000000000000000000000000000ffff36e152e6208d01ab8754010000000000000000000000000000000000ffff58b531bf208d7b038854010000000000000000000000000000000000ffff54717a6f208db0388854010000000000000000000000000000000000ffff4a694e98208d65418854010000000000000000000000000000000000ffffcef84b25208dcf218854010000000000000000000000000000000000ffff5364fed9208db6c68754010000000000000000000000000000000000ffff4d03decd208dc6158854010000000000000000000000000000000000ffffb9044c79208d65418854010000000000000000000000000000000000ffff56b2192f208d23308754010000000000000000000000000000000000ffffd973f7a4208d05158854010000000000000000000000000000000000ffff1b6d9975208d52cd8754010000000000000000000000000000000000ffffdf5b92ad208d3a128854010000000000000000000000000000000000ffff6d93787e208d351e8854010000000000000000000000000000000000ffffb6a4336f208d9bd58754010000000000000000000000000000000000ffff3ba7f521208dc3288854010000000000000000000000000000000000ffff6bbf20cc208d68998754010000000000000000000000000000000000ffff63b30032208d86848754010000000000000000000000000000000000ffffb52ef15c208dff108854010000000000000000000000000000000000ffff4d06718b208d226f0754010000000000000000000000000000000000ffff44248ba1208da3af7354010000000000000000000000000000000000ffff86f9d72c208d9fd68754010000000000000000000000000000000000ffff521f2444208dae428854010000000000000000000000000000000000ffffd445b025208dfafc8754010000000000000000000000000000000000ffffd447fa84208dbb358854010000000000000000000000000000000000ffff3ee2d196208da01a8854010000000000000000000000000000000000ffff45a615b2208d32edb053010000000000000000000000000000000000ffff6d6494da208d77ed8754010000000000000000000000000000000000ffff555dcc44208d09608754010000000000000000000000000000000000ffff45a5d222208d84558754010000000000000000000000000000000000ffffb01c30ab208d71fe8754010000000000000000000000000000000000ffffae5f68c2208de0acdf53010000000000000000000000000000000000ffffae737936208d29e18754010000000000000000000000000000000000ffffb00a63cb208d220b8854010000000000000000000000000000000000ffff9ec4d12f208db4408854010000000000000000000000000000000000ffff4c6d9bcc208d65a58754010000000000000000000000000000000000ffff5962c453208d2d628854010000000000000000000000000000000000ffff257191d50000', + payload: 'fdf5016816fa53010000000000000000000000000000000000ffff51403eea208ddb2a8854010000000000000000000000000000000000ffff707c60d9208d31413a54010000000000000000000000000000000000ffff5ed5fd13208d182c8854010000000000000000000000000000000000ffff505f3f81208d65ecb853010000000000000000000000000000000000ffff54d72104208dcca94054010000000000000000000000000000000000ffff40bbe1f2208d73238854010000000000000000000000000000000000ffff55d683cd208d5d258854010000000000000000000000000000000000ffffd523a66d208dcbea87540100000000000000200100005ef579fd2c9d47be4b56d671208db3e58754010000000000000000000000000000000000ffffae373156208d11e58754810000000000000000000000000000000000ffff51071276208d38f48754010000000000000000000000000000000000ffff6d4372e0208d4f448854010000000000000000000000000000000000ffffc556cbea208deb208854010000000000000000000000000000000000ffff450eb059208d97336054010000000000000000000000000000000000ffff4d60444a208dad608754010000000000000000000000000000000000ffff01abd3c3208d2cbe8754010000000000000000000000000000000000ffff7963d8b8208d9dfa8754010000000000000000000000000000000000ffffcebe862c208da7f66554010000000000000000000000000000000000ffff62f2a82e208d430d8854010000000000000000000000000000000000ffff6deb6956208d08148854010000000000000000000000000000000000ffff4b9804ef208d950e8854010000000000000000000000000000000000ffff6b8dd2e1208d1cfc8754010000000000000000000000000000000000ffffb2fe1dab208de7458754010000000000000000000000000000000000ffff32cccb82208d12625654010000000000000000000000000000000000ffff55e6f35a208dd7908354010000000000000000000000000000000000ffff4c642e6f208d17398854010000000000000000000000000000000000ffff45ea14df208dc72d8854010000000000000000000000000000000000ffffdaa48b96208d57fb8654010000000000000000000000000000000000ffff5f0080a9208d4e9a6d54010000000000000000000000000000000000ffff6d94e741208d7a418854010000000000000000000000000000000000ffff6d43b0c1208d5c098854010000000000000000000000000000000000ffff9c11e7ea208d442d8854010000000000000000000000000000000000ffffd0424482208db142fb53010000000000000000000000000000000000ffff54344a4a208d70158854010000000000000000000000000000000000ffff538f8201208d39288854010000000000000000000000000000000000ffff57daab71208d262f8854010000000000000000000000000000000000ffff57e045b1208d91430654010000000000000000000000000000000000ffff4212def5208d7c468854010000000000000000000000000000000000ffff62a4f53b208d9c3e8854010000000000000000000000000000000000ffff5b736bcc208d4d074f54010000000000000000000000000000000000ffff43af9d9b208deaca8754010000000000000000000000000000000000ffff4a8084a0208d74f68754010000000000000000000000000000000000ffff46304541208d5d098854010000000000000000000000000000000000ffff6eabb626208d08228854010000000000000000000000000000000000ffff1f07b030208d959a8254010000000000000000000000000000000000ffff4fa996b3208d4bac8754010000000000000000000000000000000000ffff43a0605b208de4038854010000000000000000000000000000000000ffff4cb41a5b208ddc308854010000000000000000000000000000000000ffffb72e6072208deac86f54010000000000000000000000000000000000ffffd5b815e2208d1b118854010000000000000000000000000000000000ffff3ff8d0a4208db1258854010000000000000000000000000000000000ffff5edd3a6a208d20268754010000000000000000000000000000000000ffff59ed3cfc208d83ed8754010000000000000000000000000000000000ffff4460baea208d71278854010000000000000000000000000000000000ffff4583b547208da7968754010000000000000000000000000000000000ffffd1c34463208d9d428854010000000000000000000000000000000000ffff43c15bc5208d33448854010000000000000000000000000000000000ffff2e0d8a5c208dfa2e7154010000000000000000000000000000000000ffffceff2bca208d47288854010000000000000000000000000000000000ffff5b8d0190208d0e847954010000000000000000000000000000000000ffff5501b8c2208d552f8854010000000000000000000000000000000000ffff5cf3b604208d8c2e8854010000000000000000000000000000000000ffff58666b0d208dcbdd8754010000000000000000000000000000000000ffff59a85cf9208d04208854010000000000000000000000000000000000ffff5f60abe0208dba238854010000000000000000000000000000000000ffff2e77ce67208d62c68754010000000000000000000000000000000000ffffcbae5658208d41108854010000000000000000000000000000000000ffff49329ec8208ddf1d8854010000000000000000000000000000000000ffff603ada12208df90c8854010000000000000000000000000000000000ffff51e0c21c208d5dff8754010000000000000000000000000000000000ffff904ca539208de0118854010000000000000000000000000000000000ffff5c0cecf7208d1b2d88540100000000000000200100005ef579fb18f317b2aba4edfc208dfaa27f54010000000000000000000000000000000000ffff54c65a7c208dc2db8754010000000000000000000000000000000000ffffad0b7981208d88a58754010000000000000000000000000000000000ffff188a1995208de0d78754010000000000000000000000000000000000ffff62a7a6bd208d18f66b54010000000000000000000000000000000000ffffdb4fbe80208dfcf78754010000000000000000000000000000000000ffff67145102208d3d3a8854010000000000000000000000000000000000ffff64259bd6208dcaa98654010000000000000000000000000000000000ffff32c737e1208d3a6a5c54010000000000000000000000000000000000ffff6d793f75208d22d38754010000000000000000000000000000000000ffff0595cc0d208da9ea8754010000000000000000000000000000000000ffff62ca37d3208d440e8854010000000000000000000000000000000000ffff123e1c11208dab428854010000000000000000000000000000000000ffff461df51f208d0f0b8854010000000000000000000000000000000000ffff59d36752208d631f8854010000000000000000000000000000000000ffff5ef8c640208dbc1d8854010000000000000000000000000000000000ffff5f5dc582208d04bf8754010000000000000000000000000000000000ffff0e6797e3208db8028854010000000000000000000000000000000000ffff3cf0c4a1208d6a0c8854010000000000000000000000000000000000ffff58bb5c55208d4f438854010000000000000000000000000000000000ffff5d326005208df6068854010000000000000000000000000000000000ffff5d5a5850208d40eb8754010000000000000000000000000000000000ffff5751ed86208dbad18754010000000000000000000000000000000000ffff63e51608208d99108854010000000000000000000000000000000000ffff36e299cd208d9a1e88540100000000000000200100005ef579fd38a43785a5d441b7208d13258854010000000000000000000000000000000000ffffb90de279208db3778754010000000000000000000000000000000000ffff67fcc80c208d3d358854010000000000000000000000000000000000ffffd00c40fc208dfd0d8854010000000000000000000000000000000000ffff5e89c2f3208dd6428854010000000000000000000000000000000000ffff1863e14a208d89e78754010000000000000000000000000000000000ffff43a11d76208d89ce8754010000000000000000000000000000000000ffff3edb6281208d03298854010000000000000000000000000000000000ffff6d5b26dd208d16df6e54010000000000000000000000000000000000ffffd9c3d176208d7c028854010000000000000000000000000000000000ffffbcc2db1f208d67fc8754010000000000000000000000000000000000ffff59910667208d86b18754010000000000000000000000000000000000ffff6c1482b9208d790b8854010000000000000000000000000000000000ffff0263150d208d89c44554010000000000000000000000000000000000ffff72fcd6b8208d331c8854010000000000000000000000000000000000ffff4c7dcfa8208d9fe98754010000000000000000000000000000000000ffffad08fd05208d0ecd8754010000000000000000000000000000000000ffff7c0fec89208d4af98754010000000000000000000000000000000000ffff2ea6a167208d270b8854010000000000000000000000000000000000ffff59d40fca208d11cf4054010000000000000000000000000000000000ffffb52ac058208d63358254010000000000000000000000000000000000ffff6bd9a130208dbde48754010000000000000000000000000000000000ffff4f915dc7208dece78754010000000000000000000000000000000000ffff5f8423ef208dba308854010000000000000000000000000000000000ffff904cba8c208d953d8854010000000000000000000000000000000000ffff8d1421e5208d5f188854010000000000000000000000000000000000ffff4e1bbfb6208d36fc8754010000000000000000000000000000000000ffff3205cfb6208d5e458854010000000000000000000000000000000000ffff493092c2208dd0878754010000000000000000000000000000000000ffff97caacde208dd99d8754010000000000000000000000000000000000ffffc05f3c38208da7018854010000000000000000000000000000000000ffffdcf5f82d208df0f42254010000000000000000000000000000000000ffff58bf997f208d94228854010000000000000000000000000000000000ffffbc8ee72d208de3448854010000000000000000000000000000000000ffff6d780f99208d32448854010000000000000000000000000000000000ffffbc64c76e208d0b3d8854010000000000000000000000000000000000ffff6c414312208d49138854010000000000000000000000000000000000ffff407e52c6208d2d128854010000000000000000000000000000000000ffff6dc987d8208d4acf8754010000000000000000000000000000000000ffffae151a25208de9dd8754010000000000000000000000000000000000ffff522d2d10208d17df8754010000000000000000000000000000000000ffff4d294737208ddbd48754010000000000000000000000000000000000ffff443703fd208d79108854010000000000000000000000000000000000ffff4bb5a154208d1df28753010000000000000000000000000000000000ffff4c44fc51208d5d496a53010000000000000000000000000000000000ffff530924b0208d180b8854010000000000000000000000000000000000ffffc15fced3208d53128854010000000000000000000000000000000000ffff5bc5b9e4208de21f8854010000000000000000000000000000000000ffff2e05fe1f208d31ab6554010000000000000000000000000000000000ffffae865915208d09248854010000000000000000000000000000000000ffff7d71a4b0208d120b8854010000000000000000000000000000000000ffff93e40150208d25d98754010000000000000000000000000000000000ffffc19f7a86208d99e78754010000000000000000000000000000000000ffff4d675993208d2b218854010000000000000000000000000000000000ffff5144776c208d5a208854010000000000000000000000000000000000ffff2e1cce5820f69e8f8154010000000000000000000000000000000000ffff58718848208d9edd6554010000000000000000000000000000000000ffff2ea758c5208d28c98754010000000000000000000000000000000000ffffc60bd694208d181d8854010000000000000000000000000000000000ffffba6b689e208d77868754010000000000000000000000000000000000ffff182016aa208de1698054010000000000000000000000000000000000ffff5cf5daa9208d823d8854010000000000000000000000000000000000ffffbe4d61c8208d2c3b8854010000000000000000000000000000000000ffff71647df2208da2248854010000000000000000000000000000000000ffff4ff359ca208da2dd8754010000000000000000000000000000000000ffff59f1e52b208da6e60d54010000000000000000000000000000000000ffff579596231159ad218854010000000000000000000000000000000000ffff5895f42d208d5ba78754010000000000000000000000000000000000ffff458ae8b0208ddc9b8754010000000000000000000000000000000000ffff18b507a5208d20eb5754010000000000000000000000000000000000ffff5181a537208daf1d8854010000000000000000000000000000000000ffffd5f51eba208d07f58754010000000000000000000000000000000000ffff6dec54bc208d4b3b8854010000000000000000000000000000000000ffff5c3e1991208d13b54054010000000000000000000000000000000000ffffb273845a208d4f338854010000000000000000000000000000000000ffffcfac797b208d4d898754010000000000000000000000000000000000ffffadaf880d208de72f8854010000000000000000000000000000000000ffffd956ef58208dc1e98754010000000000000000000000000000000000ffff980711cf208dfd8f7154010000000000000000000000000000000000ffff50aba98f208d59fe8754010000000000000000000000000000000000ffff5f2ae582208d3ffa8754010000000000000000000000000000000000ffffbca836db208d389b0054010000000000000000000000000000000000ffffded10925208deb154354010000000000000000000000000000000000ffff717532da208dadde7654010000000000000000000000000000000000ffff93afd0e5208d40458854010000000000000000000000000000000000ffff54ee8cb0208d08fa8754010000000000000000000000000000000000ffff3658eba9208d0df58754010000000000000000000000000000000000ffff72c6876e208d5d408854010000000000000000000000000000000000ffffa7582d7c208de8338854010000000000000000000000000000000000ffffad40d7ad208d6c2a8854010000000000000000000000000000000000ffffbc1833a3208d0fc28754010000000000000000000000000000000000ffffcbceb676208d98448854010000000000000000000000000000000000ffff0121ce6e208d77b58754010000000000000000000000000000000000ffff4b40d938208d853b8854010000000000000000000000000000000000ffff5648d643208d1c9c7854010000000000000000000000000000000000ffff6c3230db208d4e028754010000000000000000000000000000000000ffffd8e33c5d208daf738754010000000000000000000000000000000000ffffad4e9d56208dca438854010000000000000000000000000000000000ffff4f8a0353208d7b408854010000000000000000000000000000000000ffff0599e92a208dc62f8854010000000000000000000000000000000000ffff46236049208dc4d58754010000000000000000000000000000000000ffff4400384d208d0ddb4c54010000000000000000000000000000000000ffff71653b5a208d53388854010000000000000000000000000000000000ffff43bddf66208d7c388854010000000000000000000000000000000000ffff47edca96208d8c068854010000000000000000000000000000000000ffffdded3c2c208d89f60554010000000000000000000000000000000000ffff4e60d8d6208da5ff1154010000000000000000000000000000000000ffff55983c68208d72f58754010000000000000000000000000000000000ffffce47f56a208d7e2d8854010000000000000000000000000000000000ffff17e25c12208da7ca8754010000000000000000000000000000000000ffff051d0baa208d19af8754010000000000000000000000000000000000ffffad42d883208dffd68754010000000000000000000000000000000000ffff5418ff88208d87bf8754010000000000000000000000000000000000ffff4c1fe0dc208deef18754010000000000000000000000000000000000ffff4c71d406208d25868754010000000000000000000000000000000000ffffda67a475208d4d348854010000000000000000000000000000000000ffff5d561269208da5918754010000000000000000000000000000000000ffff42b163b3208dbfac3754010000000000000000000000000000000000ffffad4e01eb208d5c408854010000000000000000000000000000000000ffffcc0bb91e208d4a928754010000000000000000000000000000000000ffff531dba30208db9fd8754010000000000000000000000000000000000ffffa3f72b33208dade58754010000000000000000000000000000000000ffffd8b93aeb208db75d4d54010000000000000000000000000000000000ffffae1d5595208de8d18754010000000000000000000000000000000000ffff4405665c208d88e78754010000000000000000000000000000000000ffff6b96180a208dae667354010000000000000000000000000000000000ffff531f490a208d92f98754010000000000000000000000000000000000ffffd447e857208db1428854010000000000000000000000000000000000ffff36c6b4bb208dd42c8854010000000000000000000000000000000000ffff4b4aff14208df71acd53010000000000000000000000000000000000ffff62d17930208da0b88754010000000000000000000000000000000000ffff974bf913208d5faa7953010000000000000000000000000000000000ffff7419d269208d6c1e8854010000000000000000000000000000000000ffff48a72343208d9c2b8854010000000000000000000000000000000000ffff64431e87208de8908754010000000000000000000000000000000000ffff44660d45208d410b7d54010000000000000000000000000000000000ffff43a3340d208d5b298854010000000000000000000000000000000000ffff9ffda678208de7238854010000000000000000000000000000000000ffff189a3759208da5745354010000000000000000000000000000000000ffff57026e31208df23c885401000000000000002a010488006710000523fbe100000001208dddf48754010000000000000000000000000000000000ffffc1531c5b208d61888754010000000000000000000000000000000000ffff42cd8bc1208df92e8854010000000000000000000000000000000000ffff36e1e970208d0cf75754010000000000000000000000000000000000ffffad4e2420208d0f028854010000000000000000000000000000000000ffff6ec61b02208de6228854010000000000000000000000000000000000ffffdcaa807c208d1cac8754010000000000000000000000000000000000ffff6179416c208db6068854010000000000000000000000000000000000ffffd46121e4208d7ea58754010000000000000000000000000000000000ffff80a41679208d91216254010000000000000000000000000000000000ffff69ece091208d0bf78754010000000000000000000000000000000000ffff45320c0b208dd03c8854010000000000000000000000000000000000ffff4859a2a5208d8e308854010000000000000000000000000000000000ffff2e1ce15a208d30f36354010000000000000000000000000000000000ffff4b61ee15208d7aa05553010000000000000000000000000000000000ffffb129186b208dbb238854010000000000000000000000000000000000ffff581a7f6f208d41248754010000000000000000000000000000000000ffffb009055b208dee218854010000000000000000000000000000000000ffff2e7771f9208db4e78754010000000000000000000000000000000000ffff411bf6ee208db5178854010000000000000000000000000000000000ffffacff001b208dbcf487540100000000000000200100009d386ab83061cfabfe3513a3208d76048854010000000000000000000000000000000000ffff2e35dbc2208d83d28754010000000000000000000000000000000000ffffd91bb1d5208d5c3d8854010000000000000000000000000000000000ffff32a47969208df4bd875401000000000000002a0104f8012032250000000000000002208d1bfa8754010000000000000000000000000000000000ffff53a2f4b6208d141c4554010000000000000000000000000000000000ffffb27b8281208d580c7e54010000000000000000000000000000000000ffffc9ea1340208df7228854010000000000000000000000000000000000ffffd90a268d208d41e18754010000000000000000000000000000000000ffff555b8809208d66358854010000000000000000000000000000000000ffff5280ff23208deecd8754010000000000000000000000000000000000ffff84c6a102208df9bc8754010000000000000000000000000000000000ffffbbc96dae208d9d0a8854010000000000000000000000000000000000ffffb2a2d18a208da9458854010000000000000000000000000000000000ffffca16c30e208d2ca88754010000000000000000000000000000000000ffff6baab63e208d923b8854010000000000000000000000000000000000ffffd5b87bee208d12258854010000000000000000000000000000000000ffff59ee408b208d980e8854010000000000000000000000000000000000ffff2edfb0c4208d33378854010000000000000000000000000000000000ffff6caa7b42208d41176d53010000000000000000000000000000000000ffff1fa2df68208dd1c57f54010000000000000000000000000000000000ffffbeab679a208d17c78754010000000000000000000000000000000000ffff3f983f51208dbb278854010000000000000000000000000000000000ffff568dbc28208d5d5ad953010000000000000000000000000000000000ffff0ec112b7208da1b78754010000000000000000000000000000000000ffffbc287698208d99348854010000000000000000000000000000000000ffff5ff1a302208d23ef8454010000000000000000000000000000000000ffff7ba55d22208d90e98754010000000000000000000000000000000000ffff5ae14503208d58f48754010000000000000000000000000000000000ffffd45a3cae208d530c8854010000000000000000000000000000000000ffff18fb80c4208dc6138854010000000000000000000000000000000000ffff4e2fd6eb208d97208854010000000000000000000000000000000000ffff55ddd5b8208d74f88654010000000000000000000000000000000000ffff1809ad86208dc0278854010000000000000000000000000000000000ffff6ef2dfb6208d84338854010000000000000000000000000000000000ffff58d8114e208dcae78754010000000000000000000000000000000000ffffc21c474c208d61e78754010000000000000000000000000000000000ffffd5b3fc7a208d7a078854010000000000000000000000000000000000ffff32740193208de7547b54010000000000000000000000000000000000ffff8046aac3208db5328854010000000000000000000000000000000000ffff5b0c5366208d5f208854010000000000000000000000000000000000ffff6caa054a208d1d682854010000000000000000000000000000000000ffff69e3eb9d208d179e6b54010000000000000000000000000000000000ffff54aac628208ded2e8854010000000000000000000000000000000000ffff4166d226208d8e148854010000000000000000000000000000000000ffff54305af6208d1ed88754010000000000000000000000000000000000ffff3ed2b2a4208d78ec8554010000000000000000000000000000000000ffff6dd2e575208ddd3e7854010000000000000000000000000000000000ffff1b83a102208d421e8854010000000000000000000000000000000000ffff2eb51bf1208dc01f8854010000000000000000000000000000000000ffff58c66033208d08ce8754010000000000000000000000000000000000ffff5d57b84c208df22e8854010000000000000000000000000000000000ffffbf213e3d208d89cb8754010000000000000000000000000000000000ffff53d7ece1208da9d68754010000000000000000000000000000000000ffff71bef412208d38268854010000000000000000000000000000000000ffff84fc8a6f208d4f107254010000000000000000000000000000000000ffff57a072d9208d990f88540100000000000000200100009d3890d71029db21863020f9208df3c36854010000000000000000000000000000000000ffffbba6a6c4208d3ea71f54010000000000000000000000000000000000ffff3e61237b208d60a18754010000000000000000000000000000000000ffff53a56b4b208db2328854010000000000000000000000000000000000ffff44eef265208d2c0f8854010000000000000000000000000000000000ffff566553c0208dec268854010000000000000000000000000000000000ffff57a69ecd208d93148854010000000000000000000000000000000000ffff9b8f4433208d741b8854010000000000000000000000000000000000ffffae17c74c208ddab94f54010000000000000000000000000000000000ffffab19c63a208d5e886f54010000000000000000000000000000000000ffffbc67a037208d5c3ccc53010000000000000000000000000000000000ffff0e77c86e208d26fb8754010000000000000000000000000000000000ffffc1eae172208d61278854010000000000000000000000000000000000ffff5ce15439208d60df8754010000000000000000000000000000000000ffff2599fb3b208d52418854010000000000000000000000000000000000ffff028710e6208dae448854010000000000000000000000000000000000ffff18152eee208d6ff18754010000000000000000000000000000000000ffff542e396d208d8c248854010000000000000000000000000000000000ffff5519d6d8208d01e33e54010000000000000000000000000000000000ffff5027d563208d05cd8754010000000000000000000000000000000000ffff45a5a9c5208d7c1e8854010000000000000000000000000000000000ffff68c813c8208d38a48754010000000000000000000000000000000000ffff3a60a934208d73ec8754010000000000000000000000000000000000ffffae3db8f3208d096c8754010000000000000000000000000000000000ffff4cb88802208d55d38754010000000000000000000000000000000000ffffd31f082e208d0d8a8754010000000000000000000000000000000000ffff6c22c9bb208d81ba7754010000000000000000000000000000000000ffffca5f88da208d5df88754010000000000000000000000000000000000ffffc31abc05208db1d58754010000000000000000000000000000000000ffff5cf614c8208d2b257c54010000000000000000000000000000000000ffff45f9baa0208d38d78754010000000000000000000000000000000000ffff490e0608208d27e88754010000000000000000000000000000000000ffff17f1ccd0208d501c8854010000000000000000000000000000000000ffff5be834a7208d860b8854010000000000000000000000000000000000ffff640173bc208deada8754010000000000000000000000000000000000ffffdc98f8db208d983d3c54010000000000000000000000000000000000ffff021ab398208d99f28754010000000000000000000000000000000000ffff59a9e417208d19468854010000000000000000000000000000000000ffff91ff01a1208ddbf68754010000000000000000000000000000000000ffff50048949208d89118854010000000000000000000000000000000000ffffc8366923208dea3b8854010000000000000000000000000000000000ffffbcbbb5a9208d364a8854010000000000000000000000000000000000ffffc654bd58208dd52ef953010000000000000000000000000000000000ffff7cabb7bc208db086cc53010000000000000000000000000000000000ffff6c4004ea208d0ff48754010000000000000000000000000000000000ffff0536a3cb208d1c0b8854010000000000000000000000000000000000ffffd90bfef3208dbf188854010000000000000000000000000000000000ffff0252431f208dd1c78754010000000000000000000000000000000000ffff25732b19208dd6fa3954010000000000000000000000000000000000ffff6c1131dc208da6108854010000000000000000000000000000000000ffff1fb9b748208daf368854010000000000000000000000000000000000ffff1f2a2981208d9e2f8854010000000000000000000000000000000000ffffbc658482208d6a458854010000000000000000000000000000000000ffff568b843a208dcd428854010000000000000000000000000000000000ffff5d820794208d38258854010000000000000000000000000000000000ffff6440c630208d1cda8754010000000000000000000000000000000000ffff6e9f7be5208ddd388854010000000000000000000000000000000000ffff9f080244208d2e2d8854010000000000000000000000000000000000ffffbb70cf3d208d3e0c8854010000000000000000000000000000000000ffff3ec27a16208d89098854010000000000000000000000000000000000ffffb55fb2fb208d13468854010000000000000000000000000000000000ffff180ab1e5208dfc2a8854010000000000000000000000000000000000ffffd58a5c0e208db9188854010000000000000000000000000000000000ffff81ce808d208d03d06b54010000000000000000000000000000000000ffff4b496858208d319e8454010000000000000000000000000000000000ffff531fac9f208dc8d98754010000000000000000000000000000000000ffffc113e4ea208d06395754010000000000000000000000000000000000ffff7cabf0d6208d722b8854010000000000000000000000000000000000ffff545db4cd208dd91f8854010000000000000000000000000000000000ffff5f12a597208dfbd57054010000000000000000000000000000000000ffff3cf654e6208dd7358854010000000000000000000000000000000000ffffb4998e79208dd7018854010000000000000000000000000000000000ffffb45cc220208d86df5554010000000000000000000000000000000000ffff7660d462208decd28754010000000000000000000000000000000000ffff5b7bdfe2208dafe28754010000000000000000000000000000000000ffff2e76899e208d0c318854010000000000000000000000000000000000ffffc7bcb183208d35258854010000000000000000000000000000000000ffff3ab2d076208db5c38754010000000000000000000000000000000000ffff48b24d30208ddfd18754010000000000000000000000000000000000ffff904cb00c208d40478854010000000000000000000000000000000000ffff02a3b787208deb318854010000000000000000000000000000000000ffffd2564026208de63f8854010000000000000000000000000000000000ffff615d16c0208dbf1d8854010000000000000000000000000000000000ffffc6fff6f0208d4aee8754010000000000000000000000000000000000ffff56c74bc8208d68bc8754010000000000000000000000000000000000ffff31b581f9208ddcca8754010000000000000000000000000000000000ffff0e97397a208db2318854010000000000000000000000000000000000ffffc766348d208de1bd8754010000000000000000000000000000000000ffffd5927a3d208d2aff8754010000000000000000000000000000000000ffff5152d0a5208da7feb753010000000000000000000000000000000000ffff53fe1694208de7418854010000000000000000000000000000000000ffff189f3d99208de7b38754010000000000000000000000000000000000ffff64004655208dacabb653010000000000000000000000000000000000ffff55413231208d43b88754010000000000000000000000000000000000ffff796e1029208d03788754010000000000000000000000000000000000ffff49b90ff6208d04be8754010000000000000000000000000000000000ffffc327ce1c208d33648254010000000000000000000000000000000000ffff2e896478208d9e308854010000000000000000000000000000000000ffffd395d9bf208df13e8854010000000000000000000000000000000000ffff51bb88ed208dec8c5653010000000000000000000000000000000000ffff557f146e208df4538854010000000000000000000000000000000000ffff48d05928208d41bd8154010000000000000000000000000000000000ffff47384162208df6428854010000000000000000000000000000000000ffffc1566314208d753e8854010000000000000000000000000000000000ffff440c9b4f208d2f078854010000000000000000000000000000000000ffff56021a19208d7b0f4754010000000000000000000000000000000000ffff71653a84208dcee88754010000000000000000000000000000000000ffff5401a332208df4db8754010000000000000000000000000000000000ffff5a9db0e3208df8e38754010000000000000000000000000000000000ffff5d5208fa208d2e298854010000000000000000000000000000000000ffff4c61c0bc208d42ea8754010000000000000000000000000000000000ffff4c405ae7208deade8754010000000000000000000000000000000000ffffc009c823208d99358854010000000000000000000000000000000000ffff6cc2b493208df3fd8754010000000000000000000000000000000000ffff904c6007208d1fde8754010000000000000000000000000000000000ffff92732ae8208d666e8354010000000000000000000000000000000000ffff6daa9d16208d18f78754010000000000000000000000000000000000ffff4d6d8d8a208ddea9ce53010000000000000000000000000000000000ffff17e26f7d208d1ae48754010000000000000000000000000000000000ffffc32ebb89208dee258854010000000000000000000000000000000000ffff4a0f10e1208d290a8854010000000000000000000000000000000000ffff42731593208d7cb33354010000000000000000000000000000000000ffff532e8b97208dfd1e8854010000000000000000000000000000000000ffff6ee91680208d480a1354010000000000000000000000000000000000ffff60f220f6208d55838754010000000000000000000000000000000000ffff1f36d48f208d247e8754010000000000000000000000000000000000ffff44b5a49a208d0efa4954010000000000000000000000000000000000ffff63890597208d862e8854010000000000000000000000000000000000ffffc14d8751208d443c8854010000000000000000000000000000000000ffff70d16dba208d72fe8754010000000000000000000000000000000000ffff55983dd3208d236b6854010000000000000000000000000000000000ffff7aea27f9208d67e08754010000000000000000000000000000000000ffff1b20750d208df10a7154010000000000000000000000000000000000ffff7b9fe56e208db32d8854010000000000000000000000000000000000ffff7ba42d54208db3f58754010000000000000000000000000000000000ffff027b4eba208d70d68754010000000000000000000000000000000000ffffbc1b62b9208d97951454010000000000000000000000000000000000ffffb4b6af10208d251288540100000000000000200100009d386ab800773149c4d7e673208d7b168854010000000000000000000000000000000000ffff58969392208d91d18754010000000000000000000000000000000000ffff9ffd6d4e208d19008854010000000000000000000000000000000000ffff4e926cb8208dd1c98754010000000000000000000000000000000000ffff546cdb77208d6a0a8854010000000000000000000000000000000000ffff6caa8c15208d3a3a8854010000000000000000000000000000000000ffff62e28d6a208d3fe48754010000000000000000000000000000000000ffffd9850be7208dcb438854010000000000000000000000000000000000ffff6c2444b3208d78338854010000000000000000000000000000000000ffffb2df574a208d3b2d3054010000000000000000000000000000000000ffff4b529e67208d5b988754010000000000000000000000000000000000ffff36e152e6208d01ab8754010000000000000000000000000000000000ffff58b531bf208d7b038854010000000000000000000000000000000000ffff54717a6f208db0388854010000000000000000000000000000000000ffff4a694e98208d65418854010000000000000000000000000000000000ffffcef84b25208dcf218854010000000000000000000000000000000000ffff5364fed9208db6c68754010000000000000000000000000000000000ffff4d03decd208dc6158854010000000000000000000000000000000000ffffb9044c79208d65418854010000000000000000000000000000000000ffff56b2192f208d23308754010000000000000000000000000000000000ffffd973f7a4208d05158854010000000000000000000000000000000000ffff1b6d9975208d52cd8754010000000000000000000000000000000000ffffdf5b92ad208d3a128854010000000000000000000000000000000000ffff6d93787e208d351e8854010000000000000000000000000000000000ffffb6a4336f208d9bd58754010000000000000000000000000000000000ffff3ba7f521208dc3288854010000000000000000000000000000000000ffff6bbf20cc208d68998754010000000000000000000000000000000000ffff63b30032208d86848754010000000000000000000000000000000000ffffb52ef15c208dff108854010000000000000000000000000000000000ffff4d06718b208d226f0754010000000000000000000000000000000000ffff44248ba1208da3af7354010000000000000000000000000000000000ffff86f9d72c208d9fd68754010000000000000000000000000000000000ffff521f2444208dae428854010000000000000000000000000000000000ffffd445b025208dfafc8754010000000000000000000000000000000000ffffd447fa84208dbb358854010000000000000000000000000000000000ffff3ee2d196208da01a8854010000000000000000000000000000000000ffff45a615b2208d32edb053010000000000000000000000000000000000ffff6d6494da208d77ed8754010000000000000000000000000000000000ffff555dcc44208d09608754010000000000000000000000000000000000ffff45a5d222208d84558754010000000000000000000000000000000000ffffb01c30ab208d71fe8754010000000000000000000000000000000000ffffae5f68c2208de0acdf53010000000000000000000000000000000000ffffae737936208d29e18754010000000000000000000000000000000000ffffb00a63cb208d220b8854010000000000000000000000000000000000ffff9ec4d12f208db4408854010000000000000000000000000000000000ffff4c6d9bcc208d65a58754010000000000000000000000000000000000ffff5962c453208d2d628854010000000000000000000000000000000000ffff257191d50000' + }, + PING: { + message: 'f9beb4d9706f6e67000000000000000008000000c6466f1e6b86480ae969867c', + payload: '6b86480ae969867c' + } +}; diff --git a/test/transport/messages.js b/test/transport/messages.js new file mode 100644 index 0000000..15325b3 --- /dev/null +++ b/test/transport/messages.js @@ -0,0 +1,353 @@ +'use strict'; + +var chai = require('chai'); + +var should = chai.should(); + +var bitcore = require('../..'); +var Data = require('../data/messages'); +var Messages = bitcore.transport.Messages; +var Networks = bitcore.Networks; + +describe('Messages', function() { + + describe('Version', function() { + it('should be able to create instance', function() { + var message = new Messages.Version(); + message.command.should.equal('version'); + message.version.should.equal(70000); + message.subversion.should.equal('/BitcoinX:0.1/'); + should.exist(message.nonce); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Version(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Version(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + + it('should be able to parse payload', function() { + var payload = new Buffer(Data.VERSION.payload, 'hex'); + new Messages.Version().fromBuffer(payload); + }); + }); + + describe('VerAck', function() { + it('should be able to create instance', function() { + var message = new Messages.VerAck(); + message.command.should.equal('verack'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.VerAck(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.VerAck(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + + it('should be able to parse payload', function() { + var payload = new Buffer(Data.VERACK.payload, 'hex'); + new Messages.VerAck().fromBuffer(payload); + }); + }); + + describe('Inventory', function() { + it('should be able to create instance', function() { + var message = new Messages.Inventory(); + message.command.should.equal('inv'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Inventory(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Inventory(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + + it('should be able to parse payload', function() { + var payload = new Buffer(Data.INV.payload, 'hex'); + new Messages.Inventory().fromBuffer(payload); + }); + }); + + describe('Addresses', function() { + it('should be able to create instance', function() { + var message = new Messages.Addresses(); + message.command.should.equal('addr'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Addresses(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Addresses(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + + it('should be able to parse payload', function() { + var payload = new Buffer(Data.ADDR.payload, 'hex'); + new Messages.Addresses().fromBuffer(payload); + }); + }); + + describe('Ping', function() { + it('should be able to create instance', function() { + var message = new Messages.Ping(); + message.command.should.equal('ping'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Ping(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Ping(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + + it('should be able to parse payload', function() { + var payload = new Buffer(Data.PING.payload, 'hex'); + new Messages.Ping().fromBuffer(payload); + }); + }); + + describe('Pong', function() { + it('should be able to create instance', function() { + var message = new Messages.Pong(); + message.command.should.equal('pong'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Pong(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Pong(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + + it('should be able to parse payload', function() { + var payload = new Buffer(Data.PING.payload, 'hex'); + new Messages.Pong().fromBuffer(payload); + }); + }); + + describe('Alert', function() { + it('should be able to create instance', function() { + var message = new Messages.Alert(); + message.command.should.equal('alert'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Alert(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Alert(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('Reject', function() { + it('should be able to create instance', function() { + var message = new Messages.Reject(); + message.command.should.equal('reject'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Reject(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Reject(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('Block', function() { + var blockHex = 'f9beb4d91d0100000100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'; + var block = new bitcore.Block(new Buffer(blockHex, 'hex')); + + it('should be able to create instance', function() { + var message = new Messages.Block(block); + message.command.should.equal('block'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Block(block); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Block(block); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('GetBlocks', function() { + it('should be able to create instance', function() { + var message = new Messages.GetBlocks(); + message.command.should.equal('getblocks'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.GetBlocks(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.GetBlocks(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('GetHeaders', function() { + it('should be able to create instance', function() { + var message = new Messages.GetHeaders(); + message.command.should.equal('getheaders'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.GetHeaders(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.GetHeaders(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('GetData', function() { + it('should be able to create instance', function() { + var message = new Messages.GetData(); + message.command.should.equal('getdata'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.GetData(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.GetData(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('GetData', function() { + it('should be able to create instance', function() { + var message = new Messages.GetData(); + message.command.should.equal('getdata'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.GetData(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.GetData(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('GetAddresses', function() { + it('should be able to create instance', function() { + var message = new Messages.GetAddresses(); + message.command.should.equal('getaddr'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.GetAddresses(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.GetAddresses(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('Headers', function() { + it('should be able to create instance', function() { + var message = new Messages.Headers(); + message.command.should.equal('headers'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Headers(); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Headers(); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); + + describe('Transaction', function() { + it('should be able to create instance', function() { + var message = new Messages.Transaction(new bitcore.Transaction()); + message.command.should.equal('tx'); + }); + + it('should be able to serialize the payload', function() { + var message = new Messages.Transaction(new bitcore.Transaction()); + var payload = message.getPayload(); + should.exist(payload); + }); + + it('should be able to serialize the message', function() { + var message = new Messages.Transaction(new bitcore.Transaction()); + var buffer = message.serialize(Networks.livenet); + should.exist(buffer); + }); + }); +}); diff --git a/test/transport/peer.js b/test/transport/peer.js new file mode 100644 index 0000000..9733a22 --- /dev/null +++ b/test/transport/peer.js @@ -0,0 +1,69 @@ +'use strict'; + +var chai = require('chai'); +var Net = require('net'); +var Socks5Client = require('socks5-client'); + +/* jshint unused: false */ +var should = chai.should(); +var expect = chai.expect; + +var bitcore = require('../..'); +var Peer = bitcore.transport.Peer; +var Networks = bitcore.Networks; + +describe('Peer', function() { + + it('should be able to create instance', function() { + var peer = new Peer('localhost'); + peer.host.should.equal('localhost'); + peer.network.should.equal(Networks.livenet); + peer.port.should.equal(Networks.livenet.port); + }); + + it('should be able to create instance setting a port', function() { + var peer = new Peer('localhost', 8111); + peer.host.should.equal('localhost'); + peer.network.should.equal(Networks.livenet); + peer.port.should.equal(8111); + }); + + it('should be able to create instance setting a network', function() { + var peer = new Peer('localhost', Networks.testnet); + peer.host.should.equal('localhost'); + peer.network.should.equal(Networks.testnet); + peer.port.should.equal(Networks.testnet.port); + }); + + it('should be able to create instance setting port and network', function() { + var peer = new Peer('localhost', 8111, Networks.testnet); + peer.host.should.equal('localhost'); + peer.network.should.equal(Networks.testnet); + peer.port.should.equal(8111); + }); + + it('should support creating instance without new', function() { + var peer = Peer('localhost', 8111, Networks.testnet); + peer.host.should.equal('localhost'); + peer.network.should.equal(Networks.testnet); + peer.port.should.equal(8111); + }); + + // only for node TODO: (yemel) + it.skip('should be able to set a proxy', function() { + var peer, peer2, socket; + + peer = new Peer('localhost'); + expect(peer.proxy).to.be.undefined(); + socket = peer._getSocket(); + socket.should.be.instanceof(Net.Socket); + + peer2 = peer.setProxy('127.0.0.1', 9050); + peer2.proxy.host.should.equal('127.0.0.1'); + peer2.proxy.port.should.equal(9050); + socket = peer2._getSocket(); + socket.should.be.instanceof(Socks5Client); + + peer.should.equal(peer2); + }); +});