Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

devp2p-dpt

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

devp2p-dpt - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

435

lib/index.js

@@ -11,21 +11,21 @@ /**

*/
const util = require('util');
const dgram = require('dgram');
const ethUtil = require('ethereumjs-util');
const KBucket = require('k-bucket');
const rlp = require('rlp');
const ecdsa = require('secp256k1');
const Semaphore = require('semaphore');
const EventEmitter = require('events').EventEmitter;
const dhtLogic = require('./logic.js');
const async = require('async');
const util = require('util')
const dgram = require('dgram')
const ethUtil = require('ethereumjs-util')
const KBucket = require('k-bucket')
const rlp = require('rlp')
const ecdsa = require('secp256k1')
const Semaphore = require('semaphore')
const EventEmitter = require('events').EventEmitter
const dhtLogic = require('./logic.js')
const async = require('async')
function parseIp(ip){
function parseIp (ip) {
return ip[0].toString() + '.' + ip[1].toString() + '.'
+ ip[2].toString() + '.' + ip[3].toString();
+ ip[2].toString() + '.' + ip[3].toString()
}
function createIp(str){
str = str.split('.');
return new Buffer(str);
function createIp (str) {
str = str.split('.')
return new Buffer(str)
}

@@ -37,8 +37,8 @@

const parse = {
//skip src packet
ping: function(payload) {
// skip src packet
ping: function (payload) {
return {
version: payload[0],
address: parseIp(payload[1][0]),
//TODO: set port to tcp
// TODO: set port to tcp
// udpPort: ethUtil.bufferToInt(payload[1][1]),

@@ -53,3 +53,3 @@ udpPort: ethUtil.bufferToInt(payload[1][2]),

},
pong: function(payload) {
pong: function (payload) {
return {

@@ -61,13 +61,13 @@ dstAddress: parseIp(payload[0][0]),

expiration: payload[2]
};
}
},
findNode: function(payload) {
findNode: function (payload) {
return {
id: payload[0],
expiration: payload[1]
};
}
},
neighbors: function(payload) {
var neighbors = [];
payload[0].forEach(function(n) {
neighbors: function (payload) {
var neighbors = []
payload[0].forEach(function (n) {
neighbors.push({

@@ -78,8 +78,8 @@ address: parseIp(n[0]),

id: n[3]
});
//TODO: parse expriration date
});
return neighbors;
})
// TODO: parse expriration date
})
return neighbors
}
};
}

@@ -91,137 +91,136 @@ var offsets = {

0x04: 'neighbors'
};
}
var DPT = module.exports = function(opts) {
var DPT = module.exports = function (opts) {
const self = this
EventEmitter.call(this)
const self = this;
EventEmitter.call(this);
// default settings defined by protocol
this.setMaxListeners(40)
this.version = 4
this.K = 16
this.concurrencySem = Semaphore(3)
//default settings defined by protocol
this.setMaxListeners(40);
this.version = 4;
this.K = 16;
this.concurrencySem = Semaphore(3);
//settings defined by `opts`
this.socket = dgram.createSocket('udp4') || opts.socket;
this.timeout = opts.timeout || 60000;
this.secKey = opts.secretKey;
this.address = opts.address;
this.udpPort = opts.udpPort || opts.tcpPort;
this.tcpPort = opts.tcpPort || opts.udpPort;
this.id = (ecdsa.createPublicKey(this.secKey)).slice(1);
this.refreshIntervial = 360000;
// settings defined by `opts`
this.socket = dgram.createSocket('udp4') || opts.socket
this.timeout = opts.timeout || 60000
this.secKey = opts.secretKey
this.address = opts.address
this.udpPort = opts.udpPort || opts.tcpPort
this.tcpPort = opts.tcpPort || opts.udpPort
this.id = (ecdsa.createPublicKey(this.secKey)).slice(1)
this.refreshIntervial = 360000
this.kBucket = new KBucket({
numberOfNodesPerKBucket: this.K,
localNodeId: this.id
});
})
this.socket.on("message", function(msg, rinfo) {
try{
self.parsePacket(msg, rinfo);
}catch(e){
console.log(e.stack);
self.emit('error', 'failed to parse message', e, rinfo);
this.socket.on('message', function (msg, rinfo) {
try {
self.parsePacket(msg, rinfo)
} catch(e) {
self.emit('error', 'failed to parse message', e, rinfo)
}
});
})
this.socket.on("error", function (e) {
self.emit('error', e);
});
this.socket.on('error', function (e) {
self.emit('error', e)
})
this._refreshId = setInterval(this.refresh.bind(this), this.refreshIntervial)
//attach logic
dhtLogic(this);
};
// attach logic
dhtLogic(this)
}
util.inherits(DPT, EventEmitter);
util.inherits(DPT, EventEmitter)
DPT.prototype.bind = function(port, address, cb){
this.udpPort = this.udpPort || port;
this.tcpPort = this.tcpPort || port;
this.address = this.address || address;
this.socket.bind({port: port, address: address}, cb);
DPT.prototype.bind = function (port, address, cb) {
this.udpPort = this.udpPort || port
this.tcpPort = this.tcpPort || port
this.address = this.address || address
this.socket.bind({port: port, address: address}, cb)
}
DPT.prototype.close = function(){
clearInterval(this._refreshId);
this.socket.close();
DPT.prototype.close = function () {
clearInterval(this._refreshId)
this.socket.close()
}
//parse a packet
DPT.prototype.parsePacket = function(raw, rinfo) {
const self = this;
const hash = raw.slice(0, 32);
const sig = raw.slice(32, 96);
const recvId = raw.slice(96, 97);
const type = raw.slice(97, 98);
// parse a packet
DPT.prototype.parsePacket = function (raw, rinfo) {
const self = this
const hash = raw.slice(0, 32)
const sig = {
signature: raw.slice(32, 96),
recovery: ethUtil.bufferToInt(raw.slice(96, 97))
}
const type = raw.slice(97, 98)
const rawData = raw.slice(98)
const data = rlp.decode(rawData);
const h = ethUtil.sha3(raw.slice(32));
const data = rlp.decode(rawData)
const h = ethUtil.sha3(raw.slice(32))
if(h.toString('hex') !== hash.toString('hex')){
this.emit('error', 'invalid hash; verification failed', rinfo);
}else{
const signHash = ethUtil.sha3(raw.slice(97));
rinfo.id = ecdsa.recoverCompact(signHash, sig, ethUtil.bufferToInt(recvId), false).slice(1);
if (h.toString('hex') !== hash.toString('hex')) {
this.emit('error', 'invalid hash verification failed', rinfo)
} else {
const signHash = ethUtil.sha3(raw.slice(97))
rinfo.id = ecdsa.recover(signHash, sig, false).slice(1)
const typeName = offsets[ethUtil.bufferToInt(type)]
const parsed = parse[typeName](data);
var contact = this.kBucket.get(rinfo.id);
//if we don't konw about the peer, ping it
if(!contact && typeName !== 'pong' && typeName !== 'ping' ){
this.ping(rinfo);
const parsed = parse[typeName](data)
var contact = this.kBucket.get(rinfo.id)
// if we don't konw about the peer, ping it
if (!contact && typeName !== 'pong' && typeName !== 'ping') {
this.ping(rinfo)
}
this.emit(typeName, parsed, rinfo, rawData);
this.emit(typeName, parsed, rinfo, hash)
}
}
//send a packet
DPT.prototype.sendPacket = function(type, data, peer, cb) {
//added expriation
const t = Math.floor(new Date() / 1000) + 60;
data.push(ethUtil.intToBuffer(t));
type = new Buffer([type]);
const typeData = Buffer.concat([type, rlp.encode(data)]);
const signHash = ethUtil.sha3(typeData);
const sig = ecdsa.signCompact(this.secKey, signHash);
const recvId = new Buffer([sig.recoveryId]);
const hashData = Buffer.concat([sig.signature, recvId, typeData]);
const hash = ethUtil.sha3(hashData);
const packet = Buffer.concat([hash, hashData]);
this.socket.send(packet, 0, packet.length, peer.port || peer.udpPort, peer.address, cb);
// send a packet
DPT.prototype.sendPacket = function (type, data, peer, cb) {
// added expriation
const t = Math.floor(new Date() / 1000) + 60
data.push(ethUtil.intToBuffer(t))
type = new Buffer([type])
const typeData = Buffer.concat([type, rlp.encode(data)])
const signHash = ethUtil.sha3(typeData)
const sig = ecdsa.sign(signHash, this.secKey)
const recvId = new Buffer([sig.recovery])
const hashData = Buffer.concat([sig.signature, recvId, typeData])
const hash = ethUtil.sha3(hashData)
const packet = Buffer.concat([hash, hashData])
this.socket.send(packet, 0, packet.length, peer.port || peer.udpPort, peer.address, cb)
return hash
}
//pings a peer and wait for the pong
DPT.prototype.ping = function(peer, cb) {
// pings a peer and wait for the pong
DPT.prototype.ping = function (peer, cb) {
if (!cb) cb = function () {}
if(!cb) cb = function(){};
peer.udpPort = peer.udpPort || peer.port
peer.tcpPort = peer.tcpPort || peer.port
peer.udpPort = peer.udpPort || peer.port;
peer.tcpPort = peer.tcpPort || peer.port;
const self = this
var toID
var hash
const self = this;
var toID;
var hash;
if(peer.address === '0.0.0.0'){
peer.address = '127.0.0.1';
if (peer.address === '0.0.0.0') {
peer.address = '127.0.0.1'
}
function recFunc(pong, rpeer) {
if(peer.udpPort === rpeer.port && peer.address === rpeer.address){
clearTimeout(toID);
self.removeListener('pong', recFunc);
function recFunc (pong, rpeer) {
if (peer.udpPort === rpeer.port && peer.address === rpeer.address) {
clearTimeout(toID)
self.removeListener('pong', recFunc)
if (pong.hash.toString('hex') !== hash.toString('hex')) {
cb(new Error('invalid hash in pong'), rpeer);
cb(new Error('invalid hash in pong'), rpeer)
} else {
//add peer to kBucket
rpeer.address = peer.address;
rpeer.udpPort = peer.udpPort;
rpeer.tcpPort = peer.udpPort;
self.kBucket.add(rpeer);
self.emit('newPeer', rpeer);
cb(undefined, rpeer);
// add peer to kBucket
rpeer.address = peer.address
rpeer.udpPort = peer.udpPort
rpeer.tcpPort = peer.udpPort
self.kBucket.add(rpeer)
self.emit('newPeer', rpeer)
cb(undefined, rpeer)
}

@@ -232,82 +231,80 @@ }

this.on('pong', recFunc)
hash = this._ping(peer);
hash = this._ping(peer)
toID = setTimeout(function() {
self.removeListener('pong', recFunc);
self.kBucket.remove(peer);
cb('peer timed out');
}, this.timeout);
toID = setTimeout(function () {
self.removeListener('pong', recFunc)
self.kBucket.remove(peer)
cb('peer timed out')
}, this.timeout)
}
DPT.prototype.findNodes = function(id, peer, cb) {
var self = this;
var toID;
var hash;
DPT.prototype.findNodes = function (id, peer, cb) {
var self = this
var toID
var hash
if(!cb) cb = function(){};
if (!cb) cb = function () {}
function recFunc(neighbors, rpeer) {
//dont talk about ourselves
neighbors = neighbors.filter(function(n, i){
return n.id.toString('hex') !== self.id.toString('hex')
});
function recFunc (neighbors, rpeer) {
// dont talk about ourselves
neighbors = neighbors.filter(function (n, i) {
return n.id.toString('hex') !== self.id.toString('hex')
})
clearTimeout(toID);
self.removeListener('neighbors', recFunc);
cb(null, neighbors, rpeer);
clearTimeout(toID)
self.removeListener('neighbors', recFunc)
cb(null, neighbors, rpeer)
}
this.on('neighbors', recFunc)
hash = this._findNodes(id, peer);
hash = this._findNodes(id, peer)
toID = setTimeout(function() {
self.removeListener('neighbors', recFunc);
self.kBucket.remove(peer);
cb('timed out', []);
}, this.timeout);
toID = setTimeout(function () {
self.removeListener('neighbors', recFunc)
self.kBucket.remove(peer)
cb('timed out', [])
}, this.timeout)
}
//send a ping
//returns that hash
DPT.prototype._ping = function(peer, cb) {
// send a ping
// returns that hash
DPT.prototype._ping = function (peer, cb) {
const data = [
new Buffer([this.version]),
[createIp(this.address), ethUtil.intToBuffer(this.udpPort), ethUtil.intToBuffer(this.tcpPort)],
//TODO: fix destination tcpPort if possible
// TODO: fix destination tcpPort if possible
[createIp(this.address), ethUtil.intToBuffer(peer.udpPort), ethUtil.intToBuffer(peer.udpPort)]
];
]
this.sendPacket(1, data, peer, cb);
return ethUtil.sha3(rlp.encode(data));
return this.sendPacket(1, data, peer, cb)
}
//send a pong given a ping
DPT.prototype._pong = function(raw, peer, cb) {
const hash = ethUtil.sha3(raw);
// send a pong given a ping
DPT.prototype._pong = function (hash, peer, cb) {
const data = [
[createIp(this.address), ethUtil.intToBuffer(peer.udpPort), ethUtil.intToBuffer(peer.udpPort)],
hash
];
this.sendPacket(2, data, peer, cb);
};
]
this.sendPacket(2, data, peer, cb)
}
//send the `findNode` message
DPT.prototype._findNodes = function(id, peer, cb) {
const data = [id];
this.sendPacket(3, data, peer, cb);
};
// send the `findNode` message
DPT.prototype._findNodes = function (id, peer, cb) {
const data = [id]
this.sendPacket(3, data, peer, cb)
}
//sends the neighbors packets given an array of neighbors
DPT.prototype._neighbors = function(neighbors, peer, cb) {
var ndata = [];
// sends the neighbors packets given an array of neighbors
DPT.prototype._neighbors = function (neighbors, peer, cb) {
var ndata = []
neighbors.forEach(function(n) {
neighbors.forEach(function (n) {
ndata.push([
createIp(n.address),
createIp(n.address),
ethUtil.intToBuffer(n.udpPort),
ethUtil.intToBuffer(n.tcpPort),
n.id])
});
})
this.sendPacket(4, [ndata], peer, cb);
this.sendPacket(4, [ndata], peer, cb)
}

@@ -321,40 +318,38 @@

*/
DPT.prototype.lookup = function(id, cb) {
DPT.prototype.lookup = function (id, cb) {
var queried = {}
var self = this
var queried = {};
var self = this;
lookup(cb)
lookup(cb);
function lookup(cb2) {
function lookup (cb2) {
var cpeer = self.kBucket.closest({
id: id
}, self.K).filter(function(contact) {
}, self.K).filter(function (contact) {
return !queried[contact.id.toString('hex')]
});
})
async.each(cpeer, function(peer, cb3){
query(peer, cb3);
}, cb2);
async.each(cpeer, function (peer, cb3) {
query(peer, cb3)
}, cb2)
}
function query(peer, cb2) {
queried[peer.id.toString('hex')] = true;
self.concurrencySem.take(function(){
self.findNodes(id, peer, function(err, neighbors) {
self.concurrencySem.leave();
async.each(neighbors, function(n, done){
if(self.kBucket.get(n.id)){
done();
}else{
self.ping(n, done)
function query (peer, cb2) {
queried[peer.id.toString('hex')] = true
self.concurrencySem.take(function () {
self.findNodes(id, peer, function (err, neighbors) {
self.concurrencySem.leave()
async.each(neighbors, function (n, done) {
if (self.kBucket.get(n.id)) {
done()
} else {
self.ping(n, done)
}
}, function(){
lookup(cb2);
});
});
});
}, function () {
lookup(cb2)
})
})
})
}
};
}

@@ -367,9 +362,9 @@ /**

*/
DPT.prototype.bootStrap = function(peers, cb){
var self = this;
async.each(peers, function(p, cb2){
self.ping(p, cb2);
}, function(){
self.lookup(self.id, cb);
});
DPT.prototype.bootStrap = function (peers, cb) {
var self = this
async.each(peers, function (p, cb2) {
self.ping(p, cb2)
}, function () {
self.lookup(self.id, cb)
})
}

@@ -380,8 +375,8 @@

*/
DPT.prototype.refresh = function(){
var self = this;
var peers = this.kBucket.toArray();
peers.forEach(function(p){
self.findNodes(p.id, p);
DPT.prototype.refresh = function () {
var self = this
var peers = this.kBucket.toArray()
peers.forEach(function (p) {
self.findNodes(p.id, p)
})
}

@@ -1,44 +0,44 @@

const async = require('async');
const pingSem = require('semaphore')(3);
const async = require('async')
const pingSem = require('semaphore')(3)
module.exports = function(dpt) {
dpt.on('ping', function(ping, peer, raw) {
ping.id = peer.id;
ping.port = ping.udpPort;
dpt.kBucket.add(ping);
dpt._pong(raw, ping);
});
module.exports = function (dpt) {
dpt.on('ping', function (ping, peer, raw) {
ping.id = peer.id
ping.port = ping.udpPort
dpt.kBucket.add(ping)
dpt._pong(raw, ping)
})
dpt.on('findNode', function(node, peer) {
var nodes = dpt.kBucket.closest(node, this.K);
dpt._neighbors(nodes, peer);
});
dpt.on('findNode', function (node, peer) {
var nodes = dpt.kBucket.closest(node, this.K)
dpt._neighbors(nodes, peer)
})
// dpt.on('neighbors', function(neighbors) {
// neighbors.forEach(function(n) {
// dpt.ping(n);
// });
// });
// dpt.ping(n)
// })
// })
dpt.kBucket.on('ping', function(oldContacts, newContact) {
dpt.kBucket.on('ping', function (oldContacts, newContact) {
var added = false
oldContacts.forEach(function(c) {
dpt.concurrencySem.take(function() {
oldContacts.forEach(function (c) {
dpt.concurrencySem.take(function () {
if (!added) {
dpt.ping(c, function(err) {
dpt.ping(c, function (err) {
if (err) {
dpt.kBucket.remove(c);
dpt.kBucket.add(newContact);
dpt.emit('removePeer', c);
dpt.emit('newPeer', newContact);
added = true;
dpt.kBucket.remove(c)
dpt.kBucket.add(newContact)
dpt.emit('removePeer', c)
dpt.emit('newPeer', newContact)
added = true
}
dpt.concurrencySem.leave();
});
dpt.concurrencySem.leave()
})
} else {
dpt.concurrencySem.leave();
dpt.concurrencySem.leave()
}
});
});
});
};
})
})
})
}
{
"name": "devp2p-dpt",
"version": "0.0.2",
"version": "0.0.3",
"description": "an implemention of ethereum's DHT",

@@ -19,7 +19,7 @@ "main": "index.js",

"dependencies": {
"async": "^0.9.0",
"ethereumjs-util": "0.1.0",
"k-bucket": "^0.4.2",
"rlp": "0.0.14",
"secp256k1": "0.0.15",
"async": "^1.4.2",
"ethereumjs-util": "2.0.2",
"k-bucket": "^0.4.4",
"rlp": "2.0.0",
"secp256k1": "1.1.3",
"semaphore": "^1.0.1"

@@ -26,0 +26,0 @@ },

@@ -1,11 +0,11 @@

const tape = require('tape');
const DHT = require('../index.js');
const crypto = require('crypto');
const async = require('async');
const port = 30306;
const numOfNode = 24;
const tape = require('tape')
const DHT = require('../index.js')
const crypto = require('crypto')
const async = require('async')
const port = 30306
const numOfNode = 15
var nodes = [];
var nodes = []
function setup(cb) {
function setup (cb) {
for (var i = 0; i < numOfNode; i++) {

@@ -16,43 +16,43 @@ var dht = new DHT({

secretKey: crypto.randomBytes(32)
});
nodes.push(dht);
})
nodes.push(dht)
}
async.each(nodes, function(node, done) {
node.bind(node.udpPort, '0.0.0.0', done);
}, cb);
async.each(nodes, function (node, done) {
node.bind(node.udpPort, '0.0.0.0', done)
}, cb)
}
function printNodes() {
console.log('------------');
nodes.forEach(function(node, i) {
console.log(i + ': ' + node.kBucket.count());
});
function printNodes () {
console.log('------------')
nodes.forEach(function (node, i) {
console.log(i + ': ' + node.kBucket.count())
})
}
function connect(cb) {
function connect (cb) {
nodes[0].ping({
address: '0.0.0.0',
port: port + 1
}, cb);
}, cb)
}
function bootStrap(cb) {
var bootNodes = nodes.slice(2);
var i = 1;
async.eachSeries(bootNodes, function(node, done) {
printNodes();
function bootStrap (cb) {
var bootNodes = nodes.slice(2)
var i = 1
async.eachSeries(bootNodes, function (node, done) {
printNodes()
node.bootStrap([{
address: '0.0.0.0',
port: port + i
}], function() {
}], function () {
setTimeout(done, 100)
})
}, cb);
}, cb)
}
function shutDown(cb){
async.each(nodes, function(n, done){
n.close(done);
}, cb);
function shutDown (cb) {
async.each(nodes, function (n, done) {
n.close(done)
}, cb)
}

@@ -64,5 +64,5 @@

bootStrap,
], function() {
printNodes();
shutDown();
], function () {
printNodes()
shutDown()
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc