From 333fb4f7871c38e59596eda5012cf6b11c836888 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 20 Jan 2015 10:12:42 -0300 Subject: [PATCH 1/6] Improved jsdocs and documentation --- docs/messages.md | 50 ++++++++++++++++++ lib/messages.js | 135 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 docs/messages.md diff --git a/docs/messages.md b/docs/messages.md new file mode 100644 index 0000000..0f757ed --- /dev/null +++ b/docs/messages.md @@ -0,0 +1,50 @@ +title: Messages +description: A superclass for the messages of the bitcoin network +--- +# Messages + +The bitcoin protocol specifies a set of [messages](https://en.bitcoin.it/wiki/Protocol_specification) that can be sent from peer to peer. `bitcore-p2p` provides partial support for some of these messages. + +## List of Messages + +### Version + +The version message (`ver`) is used on connection creation, to advertise the type of node. The remote node will respond with its version, and no communication is possible until both peers have exchanged their versions. By default, bitcore advertises itself as named `bitcore:0.8`. + +### VerAck + +Finishes the connection handshake started by the `ver` message. + +### Inventory + +From the bitcoin protocol spec: "Allows a node to advertise its knowledge of one or more objects. It can be received unsolicited, or in reply to getblocks.". + +### GetData + +From the bitcoin protocol spec: `getdata` is used in response to `inv`, to retrieve the content of a specific object, and is usually sent after receiving an `inv` packet, after filtering known elements. It can be used to retrieve transactions, but only if they are in the memory pool or relay set - arbitrary access to transactions in the chain is not allowed to avoid having clients start to depend on nodes having full transaction indexes (which modern nodes do not). + +GetData inherits from Inventory, as they both have the same structure. + +### Ping + +Sent to another peer mainly to check the connection is still alive. + +### Pong + +Sent in response to a `ping` message. + +### Address and GetAddresses + +Provides information on known nodes of the network. `GetAddresses` is used to query another peer for known addresses. + +### GetHeaders and Headers + +`getheaders` allows a peer to query another about blockheaders. `headers` is sent in response to a `getheaders` message, containing information about block headers. + +### GetBlocks and Block + +Same as `getheaders` and `headers`, but the response comes one block at the time. + +### Transaction + +Message that contains a transaction. diff --git a/lib/messages.js b/lib/messages.js index c7a60f1..6d55a03 100644 --- a/lib/messages.js +++ b/lib/messages.js @@ -61,7 +61,7 @@ var parseMessage = function(network, dataBuffer) { module.exports.parseMessage = parseMessage; /** - * @desc Internal function that discards data until founds the next message. + * @desc Internal function that discards data until another message is found. * @name P2P.Message#discardUntilNextMessage */ function discardUntilNextMessage(network, dataBuffer) { @@ -162,7 +162,10 @@ Message.prototype.serialize = function(network) { module.exports.Message = Message; /** - * Version Message + * The version message(`ver`) is used on connection creation, to advertise + * the type of node.The remote node will respond with its version, and no + * communication is possible until both peers have exchanged their versions. + * By default, bitcore advertises itself as named `bitcore:0.8`. * * @name P2P.Message.Version * @param{string} subversion - version of the client @@ -171,20 +174,53 @@ module.exports.Message = Message; function Version(subversion, nonce) { this.command = 'version'; this.version = PROTOCOL_VERSION; - this.subversion = subversion || '/BitcoinX:0.1/'; + this.subversion = subversion || '/bitcore:0.8/'; this.nonce = nonce || CONNECTION_NONCE; } util.inherits(Version, Message); Version.prototype.fromBuffer = function(payload) { var parser = new BufferReader(payload); + + /** + * @type {number} + * @desc The version of the bitcoin protocol + */ this.version = parser.readUInt32LE(); + /** + * @type {BN} + * @desc A mapbit with service bits: what features are supported by the peer + */ this.services = parser.readUInt64LEBN(); + /** + * @type {BN} + * @desc The time this message was sent + */ this.timestamp = parser.readUInt64LEBN(); + /** + * @type {Buffer} + * @desc IPv4/6 address of the interface used to connect to this peer + */ this.addr_me = parser.read(26); + /** + * @type {Buffer} + * @desc IPv4/6 address of the peer + */ this.addr_you = parser.read(26); + /** + * @type {Buffer} + * @desc A random number + */ this.nonce = parser.read(8); + /** + * @desc A random number + * @type {string} + */ this.subversion = parser.readVarintBuf().toString(); + /** + * @desc The height of the last block accepted in the blockchain by this peer + * @type {number} + */ this.start_height = parser.readUInt32LE(); return this; @@ -208,13 +244,20 @@ Version.prototype.getPayload = function() { module.exports.Version = Message.COMMANDS.version = Version; /** - * Inv Message + * From the bitcoin protocol spec: "Allows a node to advertise its knowledge of + * one or more objects. It can be received unsolicited, or in reply to + * getblocks.". * * @name P2P.Message.Inventory * @param{Array} inventory - reported elements */ function Inventory(inventory) { this.command = 'inv'; + /** + * @name P2P.Message.Inventory.inventory + * @desc An array of objects with `{type: int, hash: buffer}` signature + * @type {Array.Buffer} + */ this.inventory = inventory || []; } util.inherits(Inventory, Message); @@ -247,7 +290,14 @@ Inventory.prototype.getPayload = function() { module.exports.Inventory = Message.COMMANDS.inv = Inventory; /** - * Getdata Message + * getdata is used in response to inv, to retrieve the content of a specific + * object, and is usually sent after receiving an inv packet, after filtering + * known elements. It can be used to retrieve transactions, but only if they + * are in the memory pool or relay set - arbitrary access to transactions in the + * chain is not allowed to avoid having clients start to depend on nodes having + * full transaction indexes (which modern nodes do not). + * + * (taken from bitcoin's protocol spec) * * @name P2P.Message.GetData * @param{Array} inventory - requested elements @@ -261,13 +311,17 @@ util.inherits(GetData, Inventory); module.exports.GetData = GetData; /** - * Ping Message + * Sent to another peer mainly to check the connection is still alive. * * @name P2P.Message.Ping * @param{Buffer} nonce - a random 8 bytes buffer */ function Ping(nonce) { this.command = 'ping'; + /** + * @desc A random number that should be returned by the peer in a pong message + * @type {number} + */ this.nonce = nonce || CONNECTION_NONCE; } util.inherits(Ping, Message); @@ -284,13 +338,17 @@ Ping.prototype.getPayload = function() { module.exports.Ping = Message.COMMANDS.ping = Ping; /** - * Pong Message + * Sent in response to a Ping message * * @name P2P.Message.Pong * @param{Buffer} nonce - a random 8 bytes buffer */ function Pong(nonce) { this.command = 'pong'; + /** + * @desc A random number that must match the one sent in the corresponding `ping` message + * @type {number} + */ this.nonce = nonce || CONNECTION_NONCE; } @@ -298,13 +356,17 @@ util.inherits(Pong, Ping); module.exports.Pong = Message.COMMANDS.pong = Pong; /** - * Addr Message + * Message used to notify about known addresses. * * @name P2P.Message.Addressess * @param{Array} addresses - array of know addresses */ function Addresses(addresses) { this.command = 'addr'; + /** + * @type {Array.Buffer} + * @desc An array of ipv4/6 addresses + */ this.addresses = addresses || []; } util.inherits(Addresses, Message); @@ -364,7 +426,7 @@ Addresses.prototype.getPayload = function() { module.exports.Addresses = Message.COMMANDS.addr = Addresses; /** - * GetAddr Message + * Query another node for known IPV4/6 addresses. * * @name P2P.Message.GetAddresses */ @@ -376,7 +438,7 @@ util.inherits(GetAddresses, Message); module.exports.GetAddresses = Message.COMMANDS.getaddr = GetAddresses; /** - * Verack Message + * Finishes the connection handshake started by the `ver` message. * * @name P2P.Message.VerAck */ @@ -388,7 +450,8 @@ util.inherits(VerAck, Message); module.exports.VerAck = Message.COMMANDS.verack = VerAck; /** - * Reject Message + * A reject message should be sent when a message is not supported or + * interpreted as invalid. * * @name P2P.Message.Reject */ @@ -402,7 +465,7 @@ util.inherits(Reject, Message); module.exports.Reject = Message.COMMANDS.reject = Reject; /** - * Alert Message + * Used to send a message signed by a developer of the bitcoin project. * * @name P2P.Message.Alert */ @@ -434,13 +497,18 @@ Alert.prototype.getPayload = function() { module.exports.Alert = Message.COMMANDS.alert = Alert; /** - * Headers Message + * Sent in response to a `getheaders` message. It contains information about + * block headers. * * @name P2P.Message.Headers * @param{Array} blockheaders - array of block headers */ function Headers(blockheaders) { this.command = 'headers'; + /** + * @type {Array.BlockHeader} + * @desc An array of `BlockHeader` + */ this.headers = blockheaders || []; } util.inherits(Headers, Message); @@ -473,13 +541,18 @@ Headers.prototype.getPayload = function() { module.exports.Headers = Message.COMMANDS.headers = Headers; /** - * Block Message + * Contains information about a Block * * @name P2P.Message.Block - * @param{Block} block + * @param {Block} block */ function Block(block) { this.command = 'block'; + + /** + * @type {Block} + * The + */ this.block = block; } util.inherits(Block, Message); @@ -496,13 +569,16 @@ Block.prototype.getPayload = function() { module.exports.Block = Message.COMMANDS.block = Block; /** - * Tx Message + * Contains information about a transaction * * @name P2P.Message.Transaction * @param{Transaction} transaction */ function Transaction(transaction) { this.command = 'tx'; + /** + * @type {Transaction} + */ this.transaction = transaction; } util.inherits(Transaction, Message); @@ -519,7 +595,9 @@ Transaction.prototype.getPayload = function() { module.exports.Transaction = Message.COMMANDS.tx = Transaction; /** - * Getblocks Message + * Query another peer about blocks. It can query for multiple block hashes, + * and the response will contain all the chains of blocks starting from those + * hashes. * * @name P2P.Message.GetBlocks * @param{Array} starts - array of buffers with the starting block hashes @@ -527,8 +605,18 @@ module.exports.Transaction = Message.COMMANDS.tx = Transaction; */ function GetBlocks(starts, stop) { this.command = 'getblocks'; + /** + * @type {number} + */ this.version = PROTOCOL_VERSION; + /** + * @type {Array.Buffer} + */ this.starts = starts || []; + /** + * @type {Array.Buffer} + * @desc Hashes to limit the amount of blocks to be sent + */ this.stop = stop || BufferUtil.NULL_HASH; } util.inherits(GetBlocks, Message); @@ -570,7 +658,7 @@ GetBlocks.prototype.getPayload = function() { module.exports.GetBlocks = Message.COMMANDS.getblocks = GetBlocks; /** - * Getheaders Message + * Request block headers starting from a hash * * @name P2P.Message.GetHeaders * @param{Array} starts - array of buffers with the starting block hashes @@ -578,8 +666,17 @@ module.exports.GetBlocks = Message.COMMANDS.getblocks = GetBlocks; */ function GetHeaders(starts, stop) { this.command = 'getheaders'; + /** + * @type {number} + */ this.version = PROTOCOL_VERSION; + /** + * @type {Array.Buffer} + */ this.starts = starts || []; + /** + * @type {Array.Buffer} + */ this.stop = stop || BufferUtil.NULL_HASH; } @@ -587,7 +684,7 @@ util.inherits(GetHeaders, GetBlocks); module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders; /** - * GetMempool Message + * Request for transactions on the mempool * * @name P2P.Message.GetMempool */ From 74b7571517e522bed2a71a9e2c468695e9432fc0 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 20 Jan 2015 11:08:16 -0300 Subject: [PATCH 2/6] Update version --- docs/messages.md | 2 +- lib/messages.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/messages.md b/docs/messages.md index 0f757ed..550ebee 100644 --- a/docs/messages.md +++ b/docs/messages.md @@ -9,7 +9,7 @@ The bitcoin protocol specifies a set of [messages](https://en.bitcoin.it/wiki/Pr ### Version -The version message (`ver`) is used on connection creation, to advertise the type of node. The remote node will respond with its version, and no communication is possible until both peers have exchanged their versions. By default, bitcore advertises itself as named `bitcore:0.8`. +The version message (`ver`) is used on connection creation, to advertise the type of node. The remote node will respond with its version, and no communication is possible until both peers have exchanged their versions. By default, bitcore advertises itself as named `bitcore` with the current version of the `bitcore-p2p` package. ### VerAck diff --git a/lib/messages.js b/lib/messages.js index 6d55a03..2e704bd 100644 --- a/lib/messages.js +++ b/lib/messages.js @@ -172,9 +172,10 @@ module.exports.Message = Message; * @param{Buffer} nonce - a random 8 bytes buffer */ function Version(subversion, nonce) { + var packageInfo = require('../package.json'); this.command = 'version'; this.version = PROTOCOL_VERSION; - this.subversion = subversion || '/bitcore:0.8/'; + this.subversion = subversion || '/bitcore:' + packageInfo.version + '/'; this.nonce = nonce || CONNECTION_NONCE; } util.inherits(Version, Message); From 8588ddae7fb3c1bf46715b88a6d3a996c5e00e23 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 20 Jan 2015 11:08:57 -0300 Subject: [PATCH 3/6] Fixes wording --- docs/messages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/messages.md b/docs/messages.md index 550ebee..39124c6 100644 --- a/docs/messages.md +++ b/docs/messages.md @@ -3,7 +3,7 @@ description: A superclass for the messages of the bitcoin network --- # Messages -The bitcoin protocol specifies a set of [messages](https://en.bitcoin.it/wiki/Protocol_specification) that can be sent from peer to peer. `bitcore-p2p` provides partial support for some of these messages. +The bitcoin protocol specifies a set of [messages](https://en.bitcoin.it/wiki/Protocol_specification) that can be sent from peer to peer. `bitcore-p2p` provides support for some of these messages. ## List of Messages From 6550bba657c33bd11c7105c80c2a3bef6c7bbb80 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 20 Jan 2015 11:13:14 -0300 Subject: [PATCH 4/6] Fix test for version --- test/messages.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/messages.js b/test/messages.js index d95378a..1bdf1d0 100644 --- a/test/messages.js +++ b/test/messages.js @@ -17,7 +17,8 @@ describe('Messages', function() { var message = new Messages.Version(); message.command.should.equal('version'); message.version.should.equal(70000); - message.subversion.should.equal('/BitcoinX:0.1/'); + var version = require('../package.json').version; + message.subversion.should.equal('/bitcore:' + version + '/'); should.exist(message.nonce); }); From b47526fb4299a1d0df6708ccbdab94029a564bc9 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 20 Jan 2015 11:16:15 -0300 Subject: [PATCH 5/6] Use the new error building system --- lib/errors.js | 8 ++++++++ lib/errors/build.js | 47 --------------------------------------------- lib/errors/spec.js | 13 ------------- package.json | 2 +- 4 files changed, 9 insertions(+), 61 deletions(-) create mode 100644 lib/errors.js delete mode 100644 lib/errors/build.js delete mode 100644 lib/errors/spec.js diff --git a/lib/errors.js b/lib/errors.js new file mode 100644 index 0000000..aa461a5 --- /dev/null +++ b/lib/errors.js @@ -0,0 +1,8 @@ +'use strict'; + +var spec = { + name: 'P2P', + message: 'Internal Error on bitcore-p2p Module {0}' +}; + +module.exports = require('bitcore').errors.extend(spec); diff --git a/lib/errors/build.js b/lib/errors/build.js deleted file mode 100644 index fe9dc8a..0000000 --- a/lib/errors/build.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -var _ = require('lodash'); -var fs = require('fs'); - -var defineElement = function(fullName, baseClass, message) { - return fullName + ' = function() {\n' + - ' this.message = ' + message + ';\n' + - ' this.stack = this.message + \'\\n\' + (new Error()).stack;\n' + - '};\n' + - fullName + '.prototype = Object.create(' + baseClass + '.prototype);\n' + - fullName + '.prototype.name = "' + fullName + '";\n\n'; -}; - -var traverseNode = function(baseClass, errorDefinition) { - var className = baseClass + '.' + errorDefinition.name; - var generated = defineElement(className, baseClass, errorDefinition.message); - if (errorDefinition.errors) { - generated += childDefinitions(className, errorDefinition.errors); - } - return generated; -}; - -/* jshint latedef: false */ -var childDefinitions = function(parent, childDefinitions) { - var generated = ''; - _.each(childDefinitions, function(childDefinition) { - generated += traverseNode(parent, childDefinition); - }); - return generated; -}; -/* jshint latedef: true */ - -var traverseRoot = function(errorsDefinition) { - var fullName = 'bitcore.errors'; - var generated = '\'use strict\';\n\n'; - generated += '/* jshint maxlen: 300 */\n'; - generated += '/* jshint quotmark: false */\n'; - generated += '/* AUTOGENERATED FILE. DON\'T EDIT, MODIFY "lib/errors/spec.js" INSTEAD */\n\n'; - generated += 'var bitcore = require(\'bitcore\');\n\n'; - generated += childDefinitions(fullName, errorsDefinition); - generated += 'module.exports = bitcore.errors;\n'; - return generated; -}; - -var data = require('./spec'); -fs.writeFileSync(__dirname + '/index.js', traverseRoot(data)); diff --git a/lib/errors/spec.js b/lib/errors/spec.js deleted file mode 100644 index d49c0ac..0000000 --- a/lib/errors/spec.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -function format(arg) { - return '\'' + arg - .replace('{0}', '\' + arguments[0] + \'') - .replace('{1}', '\' + arguments[1] + \'') - .replace('{2}', '\' + arguments[2] + \'') + '\''; -} - -module.exports = [{ - name: 'P2P', - message: format('Internal Error on bitcore-p2p Module {0}') -}]; diff --git a/package.json b/package.json index 38981ce..a8382bf 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "socks5-client": "^0.3.6" }, "devDependencies": { - "bitcore-build": "=0.4.2", + "bitcore-build": "^0.4.2", "brfs": "^1.2.0", "chai": "~1.10.0", "gulp": "^3.8.10", From 0f7b1a41fe1c9482a9e411805194f0c84a0d6e04 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 20 Jan 2015 11:19:39 -0300 Subject: [PATCH 6/6] Drop unused gitignores --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index cf634a9..0a13115 100644 --- a/.gitignore +++ b/.gitignore @@ -2,12 +2,8 @@ coverage node_modules -lib/errors/index.js npm-debug.log -bitcore-p2p.js -bitcore-p2p.min.js tests.js -bower_components report .DS_Store