Add FilterLoad, FilterAdd, and FilterClear Messages + BloomFilter
This commit is contained in:
parent
e19734593e
commit
abbe63666f
47
lib/bloomfilter.js
Normal file
47
lib/bloomfilter.js
Normal file
@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
var bitcore = require('bitcore');
|
||||
var BloomFilter = require('bloom-filter');
|
||||
var BufferReader = bitcore.encoding.BufferReader;
|
||||
var BufferWriter = bitcore.encoding.BufferWriter;
|
||||
var $ = bitcore.util.preconditions;
|
||||
|
||||
|
||||
BloomFilter.fromBuffer = function fromBuffer(payload) {
|
||||
var parser = new BufferReader(payload);
|
||||
var data = parser.readVarLengthBuffer();
|
||||
$.checkState(data.length <= BloomFilter.MAX_BLOOM_FILTER_SIZE,
|
||||
'Filter data must be <= MAX_BLOOM_FILTER_SIZE bytes');
|
||||
var nHashFuncs = parser.readUInt32LE();
|
||||
$.checkState(nHashFuncs <= BloomFilter.MAX_HASH_FUNCS,
|
||||
'Filter nHashFuncs must be <= MAX_HASH_FUNCS');
|
||||
var nTweak = parser.readUInt32LE();
|
||||
var nFlags = parser.readUInt8();
|
||||
|
||||
var vData = [];
|
||||
var dataParser = new BufferReader(data);
|
||||
for(var i = 0; i < data.length; i++) {
|
||||
vData.push(dataParser.readUInt8());
|
||||
}
|
||||
|
||||
return new BloomFilter({
|
||||
vData: vData,
|
||||
nHashFuncs: nHashFuncs,
|
||||
nTweak: nTweak,
|
||||
nFlags: nFlags
|
||||
});
|
||||
}
|
||||
|
||||
BloomFilter.prototype.toBuffer = function toBuffer() {
|
||||
var bw = new BufferWriter();
|
||||
bw.writeVarintNum(this.vData.length);
|
||||
for(var i = 0; i < this.vData.length; i++) {
|
||||
bw.writeUInt8(this.vData[i]);
|
||||
}
|
||||
bw.writeUInt32LE(this.nHashFuncs);
|
||||
bw.writeUInt32LE(this.nTweak);
|
||||
bw.writeUInt8(this.nFlags);
|
||||
return bw.concat();
|
||||
};
|
||||
|
||||
module.exports = BloomFilter;
|
||||
@ -4,5 +4,6 @@
|
||||
module.exports = {
|
||||
Messages: require('./messages'),
|
||||
Peer: require('./peer'),
|
||||
Pool: require('./pool')
|
||||
Pool: require('./pool'),
|
||||
BloomFilter: require('./bloomfilter')
|
||||
};
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
var Buffers = require('buffers');
|
||||
var Put = require('bufferput');
|
||||
var util = require('util');
|
||||
var BloomFilter = require('./bloomfilter');
|
||||
|
||||
var bitcore = require('bitcore');
|
||||
var _ = bitcore.deps._;
|
||||
@ -14,6 +15,7 @@ var _ = bitcore.deps._;
|
||||
var BlockHeaderModel = bitcore.BlockHeader;
|
||||
var BlockModel = bitcore.Block;
|
||||
var BufferReader = bitcore.encoding.BufferReader;
|
||||
var BufferWriter = bitcore.encoding.BufferWriter;
|
||||
var BufferUtil = bitcore.util.buffer;
|
||||
var $ = bitcore.util.preconditions;
|
||||
var Hash = bitcore.crypto.Hash;
|
||||
@ -826,6 +828,80 @@ function GetHeaders(starts, stop) {
|
||||
util.inherits(GetHeaders, GetBlocks);
|
||||
module.exports.GetHeaders = Message.COMMANDS.getheaders = GetHeaders;
|
||||
|
||||
/**
|
||||
* Request peer to apply a bloom filter to 'inv' messages sent back
|
||||
*
|
||||
* @name P2P.Message.filterload
|
||||
* @param{BloomFilter} filter - a BloomFilter object
|
||||
*/
|
||||
function FilterLoad(filter) {
|
||||
this.command = 'filterload';
|
||||
$.checkArgument(_.isUndefined() || filter instanceof BloomFilter,
|
||||
'BloomFilter object or undefined required for FilterLoad');
|
||||
this.filter = filter;
|
||||
return this;
|
||||
}
|
||||
util.inherits(FilterLoad, Message);
|
||||
|
||||
FilterLoad.prototype.fromBuffer = function(payload) {
|
||||
this.filter = BloomFilter.fromBuffer(payload);
|
||||
return this;
|
||||
};
|
||||
|
||||
FilterLoad.prototype.getPayload = function() {
|
||||
if(this.filter) {
|
||||
return this.filter.toBuffer()
|
||||
} else {
|
||||
return BufferUtil.EMPTY_BUFFER;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.FilterLoad = Message.COMMANDS.filterload = FilterLoad;
|
||||
|
||||
/**
|
||||
* Request peer to add data to a bloom filter already set by 'filterload'
|
||||
*
|
||||
* @name P2P.Message.filteradd
|
||||
* @param{Buffer} data - Array of bytes representing bloom filter data
|
||||
*/
|
||||
function FilterAdd(data) {
|
||||
this.command = 'filteradd';
|
||||
this.data = data || new Buffer(0,'hex');
|
||||
return this;
|
||||
}
|
||||
util.inherits(FilterAdd, Message);
|
||||
|
||||
FilterAdd.prototype.fromBuffer = function(payload) {
|
||||
$.checkArgument(payload);
|
||||
var parser = new BufferReader(payload);
|
||||
this.data = parser.readVarLengthBuffer();
|
||||
$.checkState(this.data.length <= BloomFilter.MAX_BLOOM_FILTER_SIZE,
|
||||
'FilterAdd data must be <= 520 bytes');
|
||||
this._checkFinished(parser);
|
||||
return this;
|
||||
};
|
||||
|
||||
FilterAdd.prototype.getPayload = function() {
|
||||
var bw = new BufferWriter();
|
||||
bw.writeVarintNum(this.data.length);
|
||||
bw.write(this.data);
|
||||
return bw.concat();
|
||||
};
|
||||
|
||||
module.exports.FilterAdd = Message.COMMANDS.filterload = FilterAdd;
|
||||
|
||||
/**
|
||||
* Request peer to apply a bloom filter to 'inv' messages sent back
|
||||
*
|
||||
* @name P2P.Message.filterclear
|
||||
*/
|
||||
function FilterClear() {
|
||||
this.command = 'filterclear';
|
||||
}
|
||||
util.inherits(FilterClear, Message);
|
||||
|
||||
module.exports.FilterClear = Message.COMMANDS.filterclear = FilterClear;
|
||||
|
||||
/**
|
||||
* Request for transactions on the mempool
|
||||
*
|
||||
|
||||
@ -86,7 +86,8 @@ Pool.MaxConnectedPeers = 8;
|
||||
Pool.RetrySeconds = 30;
|
||||
Pool.PeerEvents = ['version', 'inv', 'getdata', 'ping', 'pong', 'addr',
|
||||
'getaddr', 'verack', 'reject', 'alert', 'headers', 'block',
|
||||
'tx', 'getblocks', 'getheaders', 'error'
|
||||
'tx', 'getblocks', 'getheaders', 'error', 'filterload', 'filteradd',
|
||||
'filterclear'
|
||||
];
|
||||
|
||||
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"bitcore": "^0.10.2",
|
||||
"bloom-filter": "^0.1.1",
|
||||
"bufferput": "^0.1.2",
|
||||
"buffers": "^0.1.1",
|
||||
"socks5-client": "^0.3.6"
|
||||
|
||||
17
test/bloomfilter.js
Normal file
17
test/bloomfilter.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
var chai = require('chai');
|
||||
|
||||
var Data = require('./data/messages');
|
||||
var P2P = require('../');
|
||||
var BloomFilter = P2P.BloomFilter;
|
||||
|
||||
|
||||
describe('BloomFilter', function() {
|
||||
it('BloomFilter#fromBuffer and toBuffer methods work', function() {
|
||||
var testPayload = Data.FILTERLOAD.payload;
|
||||
var filter = new BloomFilter.fromBuffer(new Buffer(testPayload, 'hex'));
|
||||
filter.toBuffer().toString('hex').should.equal(testPayload);
|
||||
});
|
||||
|
||||
});
|
||||
@ -62,5 +62,17 @@
|
||||
"PONG": {
|
||||
"message": "f9beb4d9706f6e67000000000000000008000000c6466f1e6b86480ae969867c",
|
||||
"payload": "6b86480ae969867c"
|
||||
},
|
||||
"FILTERLOAD": {
|
||||
"message": "f9beb4d966696c7465726c6f61640000210000002ef97a71170000000000000000000000000000000000000000000000060000000000000000",
|
||||
"payload": "170000000000000000000000000000000000000000000000060000000000000000"
|
||||
},
|
||||
"FILTERADD": {
|
||||
"message": "f9beb4d966696c7465726c6f61640000150000009727ea0a1499108ad8ed9bb6274d3980bab5a85c048f0950c8",
|
||||
"payload": "1499108ad8ed9bb6274d3980bab5a85c048f0950c8"
|
||||
},
|
||||
"FILTERCLEAR": {
|
||||
"message": "f9beb4d966696c7465726c6365617200000000005df6e0e2",
|
||||
"payload": ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ var Buffers = require('buffers');
|
||||
var bitcore = require('bitcore');
|
||||
var Data = require('./data/messages');
|
||||
var P2P = require('../');
|
||||
var BloomFilter = P2P.BloomFilter;
|
||||
var Messages = P2P.Messages;
|
||||
var Networks = bitcore.Networks;
|
||||
var BufferUtils = bitcore.util.buffer;
|
||||
@ -26,6 +27,9 @@ describe('Messages', function() {
|
||||
Alert: 'alert',
|
||||
Reject: 'reject',
|
||||
Block: 'block',
|
||||
FilterLoad: 'filterload',
|
||||
FilterAdd: 'filteradd',
|
||||
FilterClear: 'filterclear',
|
||||
GetBlocks: 'getblocks',
|
||||
GetHeaders: 'getheaders',
|
||||
GetData: 'getdata',
|
||||
@ -34,7 +38,7 @@ describe('Messages', function() {
|
||||
Transaction: 'tx',
|
||||
NotFound: 'notfound'
|
||||
};
|
||||
// TODO: add data for these
|
||||
// TODO: add data for these
|
||||
var noPayload = ['Reject', 'GetBlocks', 'GetHeaders'];
|
||||
var names = Object.keys(commands);
|
||||
describe('named', function() {
|
||||
@ -116,4 +120,10 @@ describe('Messages', function() {
|
||||
|
||||
});
|
||||
|
||||
it('FilterLoad#fromBuffer method works', function() {
|
||||
var testPayload = Data.FILTERLOAD.payload;
|
||||
var msg = new Messages.FilterLoad().fromBuffer(new Buffer(testPayload, 'hex'));
|
||||
msg.getPayload().toString('hex').should.equal(testPayload);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user