add notfound message

This commit is contained in:
Manuel Araoz 2015-02-02 15:56:32 -03:00
parent 1937abac11
commit 087c57e077
2 changed files with 78 additions and 29 deletions

View File

@ -18,6 +18,7 @@ var Pool = p2p.Pool;
var Networks = bitcore.Networks; var Networks = bitcore.Networks;
var Messages = p2p.Messages; var Messages = p2p.Messages;
var Block = bitcore.Block; var Block = bitcore.Block;
var Transaction = bitcore.Transaction;
// config // config
var network = Networks.livenet; var network = Networks.livenet;
@ -25,6 +26,10 @@ var blockHash = {
'livenet': '000000000000000013413cf2536b491bf0988f52e90c476ffeb701c8bfdb1db9', 'livenet': '000000000000000013413cf2536b491bf0988f52e90c476ffeb701c8bfdb1db9',
'testnet': '0000000058cc069d964711cd25083c0a709f4df2b34c8ff9302ce71fe5b45786' 'testnet': '0000000058cc069d964711cd25083c0a709f4df2b34c8ff9302ce71fe5b45786'
}; };
var txHash = {
'livenet': '22231e8219a0617a0ded618b5dc713fdf9b0db8ebd5bb3322d3011a703119d3b',
'testnet': '22231e8219a0617a0ded618b5dc713fdf9b0db8ebd5bb3322d3011a703119d3b'
};
// These tests require a running bitcoind instance // These tests require a running bitcoind instance
describe('Integration with ' + network.name + ' bitcoind', function() { describe('Integration with ' + network.name + ' bitcoind', function() {
@ -126,15 +131,25 @@ describe('Integration with ' + network.name + ' bitcoind', function() {
}); });
it('can request block data', function(cb) { it('can request block data', function(cb) {
connect(function(peer) { connect(function(peer) {
peer.on('block', function(message) { peer.once('block', function(message) {
(message.block instanceof Block).should.equal(true); (message.block instanceof Block).should.equal(true);
cb(); cb();
}); });
// TODO: replace this for a new Messages.GetData.forTransaction(hash) // TODO: replace this for a new Messages.GetData.forBlock(hash)
var message = new Messages.GetData([{ var message = Messages.GetData.forBlock(blockHash[network.name]);
type: Messages.Inventory.TYPE.BLOCK, peer.sendMessage(message);
hash: BufferUtil.reverse(new Buffer(blockHash[network.name], 'hex')) });
}]); });
it('can handle request tx data not found', function(cb) {
connect(function(peer) {
var hash = 'e2dfb8afe1575bfacae1a0b4afc49af7ddda69285857267bae0e22be15f74a3a';
var expected = Messages.NotFound.forTransaction(hash);
peer.once('notfound', function(message) {
(message instanceof Messages.NotFound).should.equal(true);
message.should.deep.equal(expected);
cb();
});
var message = Messages.GetData.forTransaction(hash);
peer.sendMessage(message); peer.sendMessage(message);
}); });
}); });

View File

@ -19,7 +19,6 @@ var $ = bitcore.util.preconditions;
var Hash = bitcore.crypto.Hash; var Hash = bitcore.crypto.Hash;
var Random = bitcore.crypto.Random; var Random = bitcore.crypto.Random;
var TransactionModel = bitcore.Transaction; var TransactionModel = bitcore.Transaction;
var errors = bitcore.Errors;
var CONNECTION_NONCE = Random.getPseudoRandomBuffer(8); var CONNECTION_NONCE = Random.getPseudoRandomBuffer(8);
var PROTOCOL_VERSION = 70000; var PROTOCOL_VERSION = 70000;
@ -130,7 +129,7 @@ Message.buildMessage = function(command, payload) {
*/ */
Message.prototype.fromBuffer = function(payload) { Message.prototype.fromBuffer = function(payload) {
/* jshint unused: false */ /* jshint unused: false */
throw new errors.NotImplemented(); return this;
}; };
/** /**
@ -264,6 +263,13 @@ module.exports.Version = Message.COMMANDS.version = Version;
* @param{Array} inventory - reported elements * @param{Array} inventory - reported elements
*/ */
function Inventory(inventory) { function Inventory(inventory) {
$.checkArgument(_.isUndefined(inventory) ||
_.isArray(inventory), 'Inventory for ' +
this.constructor.name + ' must be an array of objects');
$.checkArgument(_.isUndefined(inventory) ||
inventory.length === 0 ||
(inventory[0] && !_.isUndefined(inventory[0].type) && !_.isUndefined(inventory[0].hash)),
'Inventory for ' + this.constructor.name + ' must be an array of objects');
this.command = 'inv'; this.command = 'inv';
/** /**
* @name P2P.Message.Inventory.inventory * @name P2P.Message.Inventory.inventory
@ -287,16 +293,26 @@ Inventory.TYPE_NAME = [
'FILTERED_BLOCK' 'FILTERED_BLOCK'
]; ];
Inventory.forItem = function(type, hash) {
$.checkArgument(hash);
if (_.isString(hash)) {
hash = new Buffer(hash, 'hex');
hash = BufferUtil.reverse(hash);
}
return {
type: type,
typeName: Inventory.TYPE_NAME[type],
hash: hash
};
};
Inventory.prototype.fromBuffer = function(payload) { Inventory.prototype.fromBuffer = function(payload) {
var parser = new BufferReader(payload); var parser = new BufferReader(payload);
var count = parser.readVarintNum(); var count = parser.readVarintNum();
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
var type = parser.readUInt32LE(); var type = parser.readUInt32LE();
this.inventory.push({ var hash = parser.read(32);
type: type, this.inventory.push(Inventory.forItem(type, hash));
typeName: Inventory.TYPE_NAME[type],
hash: parser.read(32)
});
} }
return this; return this;
@ -314,8 +330,32 @@ Inventory.prototype.getPayload = function() {
return put.buffer(); return put.buffer();
}; };
var creatorForItem = function(clazz, type) {
return function(hash) {
return new clazz([Inventory.forItem(type, hash)]);
};
};
module.exports.Inventory = Message.COMMANDS.inv = Inventory; module.exports.Inventory = Message.COMMANDS.inv = Inventory;
/**
* notfound is a response to a getdata, sent if any requested data
* items could not be relayed, for example, because the requested
* transaction was not in the memory pool or relay set.
*
* (from bitcoin's protocol spec)
*
* @name P2P.Message.NotFound
* @param{Array} inventory - not found elements
*/
function NotFound(inventory) {
Inventory.call(this, inventory);
this.command = 'notfound';
}
util.inherits(NotFound, Inventory);
module.exports.NotFound = Message.COMMANDS.notfound = NotFound;
/** /**
* getdata is used in response to inv, to retrieve the content of a specific * 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 * object, and is usually sent after receiving an inv packet, after filtering
@ -324,22 +364,18 @@ module.exports.Inventory = Message.COMMANDS.inv = Inventory;
* chain is not allowed to avoid having clients start to depend on nodes having * chain is not allowed to avoid having clients start to depend on nodes having
* full transaction indexes (which modern nodes do not). * full transaction indexes (which modern nodes do not).
* *
* (taken from bitcoin's protocol spec) * (from bitcoin's protocol spec)
* *
* @name P2P.Message.GetData * @name P2P.Message.GetData
* @param{Array} inventory - requested elements * @param{Array} inventory - requested elements
*/ */
function GetData(inventory) { function GetData(inventory) {
$.checkArgument(_.isUndefined(inventory) || Inventory.call(this, inventory);
_.isArray(inventory), 'Inventory for GetData must be an array of objects');
$.checkArgument(_.isUndefined(inventory) ||
inventory.length === 0 ||
(inventory[0] && !_.isUndefined(inventory[0].type) && !_.isUndefined(inventory[0].hash)),
'Inventory for GetData must be an array of objects');
this.command = 'getdata'; this.command = 'getdata';
this.inventory = inventory || []; this.inventory = inventory || [];
} }
util.inherits(GetData, Inventory); util.inherits(GetData, Inventory);
module.exports.GetData = Message.COMMANDS.getdata = GetData; module.exports.GetData = Message.COMMANDS.getdata = GetData;
@ -480,9 +516,6 @@ function GetAddresses() {
} }
util.inherits(GetAddresses, Message); util.inherits(GetAddresses, Message);
GetAddresses.prototype.fromBuffer = function() {
return new GetAddresses();
};
module.exports.GetAddresses = Message.COMMANDS.getaddr = GetAddresses; module.exports.GetAddresses = Message.COMMANDS.getaddr = GetAddresses;
/** /**
@ -495,9 +528,6 @@ function VerAck() {
} }
util.inherits(VerAck, Message); util.inherits(VerAck, Message);
VerAck.prototype.fromBuffer = function() {
return new VerAck();
};
module.exports.VerAck = Message.COMMANDS.verack = VerAck; module.exports.VerAck = Message.COMMANDS.verack = VerAck;
/** /**
@ -737,9 +767,6 @@ function GetHeaders(starts, stop) {
} }
util.inherits(GetHeaders, GetBlocks); util.inherits(GetHeaders, GetBlocks);
GetHeaders.prototype.fromBuffer = function() {
return new GetHeaders();
};
module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders; module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders;
/** /**
@ -769,3 +796,10 @@ Buffers.prototype.skip = function(i) {
this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset)); this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset));
this.length -= i; this.length -= i;
}; };
[Inventory, GetData, NotFound].forEach(function(clazz) {
clazz.forBlock = creatorForItem(clazz, Inventory.TYPE.BLOCK);
clazz.forTransaction = creatorForItem(clazz, Inventory.TYPE.TX);
});