From 7583cb0103b17951f5bf619ddf29499057e8c8ad Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 13 Jan 2014 15:17:34 -0300 Subject: [PATCH 1/2] p2p integration into the express webapp --- lib/PeerSync.js | 121 +++++++++++++++++++++++++++++++++++++++++++++ lib/Sync.js | 5 +- p2p.js | 127 ------------------------------------------------ server.js | 34 ++++++++----- util/p2p.js | 20 ++++++++ 5 files changed, 166 insertions(+), 141 deletions(-) create mode 100644 lib/PeerSync.js delete mode 100755 p2p.js create mode 100755 util/p2p.js diff --git a/lib/PeerSync.js b/lib/PeerSync.js new file mode 100644 index 0000000..ba0d743 --- /dev/null +++ b/lib/PeerSync.js @@ -0,0 +1,121 @@ +'use strict'; +require('classtool'); + +function spec() { + var fs = require('fs'); + var CoinConst = require('bitcore/const'); + var coinUtil = require('bitcore/util/util'); + var Sync = require('./Sync').class(); + var Peer = require('bitcore/Peer').class(); + + var peerdb_fn = 'peerdb.json'; + + function PeerSync() {} + PeerSync.prototype.init = function(config) { + + var network = config && (config.network || "testnet"); + + this.peerdb = undefined; + this.sync = new Sync({ + networkName: network + }); + this.sync.init(config); + + this.PeerManager = require('bitcore/PeerManager').createClass({ + config: { + network: network + } + }); + this.load_peers(); + + }; + + PeerSync.prototype.load_peers = function() { + try { + this.peerdb = JSON.parse(fs.readFileSync(peerdb_fn)); + } catch(d) { + console.warn('Unable to read peer db', peerdb_fn, 'creating new one.'); + this.peerdb = [{ + ipv4: '127.0.0.1', + port: 18333 + }, + ]; + + fs.writeFileSync(this.peerdb_fn, JSON.stringify(this.peerdb)); + } + }; + + PeerSync.prototype.handle_inv = function(info) { + // TODO: should limit the invs to objects we haven't seen yet + var invs = info.message.invs; + invs.forEach(function(inv) { + console.log('[p2p_sync] Handle inv for a ' + CoinConst.MSG.to_str(inv.type)); + }); + // this is not needed right now, but it's left in case + // we need to store more info in the future + info.conn.sendGetData(invs); + }; + + PeerSync.prototype.handle_tx = function(info) { + var tx = info.message.tx.getStandardizedObject(); + console.log('[p2p_sync] Handle tx: ' + tx.hash); + this.sync.storeTxs([tx.hash], function(err) { + if (err) { + console.log('[p2p_sync] Error in handle TX: ' + err); + } + }); + }; + + PeerSync.prototype.handle_block = function(info) { + var self = this; + var block = info.message.block; + var now = Math.round(new Date().getTime() / 1000); + var blockHash = coinUtil.formatHashFull(block.calcHash()); + console.log('[p2p_sync] Handle block: ' + blockHash); + this.sync.storeBlock({ + 'hash': blockHash, + 'time': now + }, + function(err) { + if (err) { + console.log('[p2p_sync] Error in handle Block: ' + err); + } else { + // if no errors importing block, import the transactions + var hashes = block.txs.map(function(tx) { + return coinUtil.formatHashFull(tx.hash); + }); + self.sync.storeTxs(hashes, function() {}); + } + }); + + }; + + PeerSync.prototype.handle_connected = function(data) { + var peerman = data.pm; + var peers_n = peerman.peers.length; + console.log('[p2p_sync] Connected to ' + peers_n + ' peer' + (peers_n !== 1 ? 's': '')); + }; + + PeerSync.prototype.run = function() { + var self = this; + var peerman = new this.PeerManager(); + + this.peerdb.forEach(function(datum) { + var peer = new Peer(datum.ipv4, datum.port); + peerman.addPeer(peer); + }); + + peerman.on('connection', function(conn) { + conn.on('inv', function(x){self.handle_inv(x);}); + conn.on('block', function(x){self.handle_block(x);}); + conn.on('tx', function(x){self.handle_tx(x);}); + }); + peerman.on('connect', function(x){self.handle_connected(x);}); + + peerman.start(); + }; + return PeerSync; + +} +module.defineClass(spec); + diff --git a/lib/Sync.js b/lib/Sync.js index af05493..0fcdc8f 100644 --- a/lib/Sync.js +++ b/lib/Sync.js @@ -152,8 +152,9 @@ function spec() { }; Sync.prototype.init = function(opts) { - - mongoose.connect(config.db); + if (!(opts && opts.skip_db_connection)) { + mongoose.connect(config.db); + } this.db = mongoose.connection; this.rpc = new RpcClient(config.bitcoind); diff --git a/p2p.js b/p2p.js deleted file mode 100755 index e6ee4a0..0000000 --- a/p2p.js +++ /dev/null @@ -1,127 +0,0 @@ -#! /usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var fs = require('fs'); -var HeaderDB = require('./HeaderDB').class(); -var Block = require('bitcore/Block').class(); -var CoinConst = require('bitcore/const'); -var coinUtil = require('bitcore/util/util'); -var networks = require('bitcore/networks'); -var Parser = require('bitcore/util/BinaryParser').class(); -var Sync = require('./lib/Sync').class(); -var Peer = require('bitcore/Peer').class(); - -var peerdb_fn = 'peerdb.json'; -var peerdb = undefined; - -var PROGRAM_VERSION = '0.1'; -var program = require('commander'); - -program - .version(PROGRAM_VERSION) - .option('-N --network [testnet]', 'Set bitcoin network [testnet]', 'testnet') - .parse(process.argv); - -var sync = new Sync({ - networkName: program.network -}); -sync.init(); - -var PeerManager = require('bitcore/PeerManager').createClass({ - config: { - network: program.network - } -}); - -function peerdb_load() { - try { - peerdb = JSON.parse(fs.readFileSync(peerdb_fn)); - } catch(d) { - console.warn('Unable to read peer db', peerdb_fn, 'creating new one.'); - peerdb = [{ - ipv4: '127.0.0.1', - port: 18333 - }, - ]; - - fs.writeFileSync(peerdb_fn, JSON.stringify(peerdb)); - } -} - -function handle_inv(info) { - // TODO: should limit the invs to objects we haven't seen yet - var invs = info.message.invs; - invs.forEach(function(inv) { - console.log('Handle inv for a ' + CoinConst.MSG.to_str(inv.type)); - }); - // this is not needed right now, but it's left in case - // we need to store more info in the future - info.conn.sendGetData(invs); -} - -function handle_tx(info) { - var tx = info.message.tx.getStandardizedObject(); - console.log('Handle tx: ' + tx.hash); - sync.storeTxs([tx.hash], function(err) { - if (err) { - console.log('Error in handle TX: ' + err); - } - }); -} - -function handle_block(info) { - var block = info.message.block; - var now = Math.round(new Date().getTime() / 1000); - var blockHash = coinUtil.formatHashFull(block.calcHash()); - console.log('Handle block: ' + blockHash); - sync.storeBlock({ - 'hash': blockHash, - 'time': now - }, - function(err) { - if (err) { - console.log('Error in handle Block: ' + err); - } else { - // if no errors importing block, import the transactions - var hashes = block.txs.map(function(tx) { - return coinUtil.formatHashFull(tx.hash); - }); - sync.storeTxs(hashes, function() {}); - } - }); - -} - -function handle_connected(data) { - var peerman = data.pm; - var peers_n = peerman.peers.length; - console.log('p2psync: Connected to ' + peers_n + ' peer' + (peers_n !== 1 ? 's': '')); -} - -function p2psync() { - var peerman = new PeerManager(); - - peerdb.forEach(function(datum) { - var peer = new Peer(datum.ipv4, datum.port); - peerman.addPeer(peer); - }); - - peerman.on('connection', function(conn) { - conn.on('inv', handle_inv); - conn.on('block', handle_block); - conn.on('tx', handle_tx); - }); - peerman.on('connect', handle_connected); - - peerman.start(); -} - -function main() { - peerdb_load(); - p2psync(); -} - -main(); - diff --git a/server.js b/server.js index de2a349..b12373a 100644 --- a/server.js +++ b/server.js @@ -1,23 +1,25 @@ 'use strict'; -/** - * Module dependencies. - */ -var express = require('express'), - fs = require('fs'); - -/** - * Main application entry file. - */ - //Load configurations //Set the node enviornment variable if not set before process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -//Initializing system variables -var config = require('./config/config'), +/** + * Module dependencies. + */ +var express = require('express'), + fs = require('fs'), + PeerSync = require('./lib/PeerSync').class(), mongoose = require('mongoose'); +/** + * Main application entry file. + */ + + +//Initializing system variables +var config = require('./config/config'); + //Bootstrap db connection var db = mongoose.connect(config.db); @@ -38,6 +40,14 @@ var walk = function(path) { }; walk(models_path); +// p2p_sync process +var ps = new PeerSync(); +ps.init({ + skip_db_connection: true +}); +ps.run(); + +// express app var app = express(); //express settings diff --git a/util/p2p.js b/util/p2p.js new file mode 100755 index 0000000..91ead1b --- /dev/null +++ b/util/p2p.js @@ -0,0 +1,20 @@ +#! /usr/bin/env node +'use strict'; + +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + +var PeerSync = require('../lib/PeerSync').class(); + +var PROGRAM_VERSION = '0.1'; +var program = require('commander'); + +program + .version(PROGRAM_VERSION) + .option('-N --network [testnet]', 'Set bitcoin network [testnet]', 'testnet') + .parse(process.argv); + +var ps = new PeerSync(); +ps.init(program); +ps.run(); + + From 788f9ecedcf15f5ffa0169a1b89783722b60c65a Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 13 Jan 2014 15:43:40 -0300 Subject: [PATCH 2/2] using bind to pass object methods as callbacks --- lib/PeerSync.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/PeerSync.js b/lib/PeerSync.js index ba0d743..4fe2248 100644 --- a/lib/PeerSync.js +++ b/lib/PeerSync.js @@ -106,11 +106,11 @@ function spec() { }); peerman.on('connection', function(conn) { - conn.on('inv', function(x){self.handle_inv(x);}); - conn.on('block', function(x){self.handle_block(x);}); - conn.on('tx', function(x){self.handle_tx(x);}); + conn.on('inv', self.handle_inv.bind(self)); + conn.on('block', self.handle_block.bind(self)); + conn.on('tx', self.handle_tx.bind(self)); }); - peerman.on('connect', function(x){self.handle_connected(x);}); + peerman.on('connect', self.handle_connected.bind(self)); peerman.start(); };