From c39749c58e28af069257173de9521f05e22431a5 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 29 Jul 2014 17:28:15 -0300 Subject: [PATCH 01/16] add MessageDb --- config/config.js | 39 ------ insight.js | 57 +++++++-- lib/MessageDb.js | 57 +++++++++ lib/TransactionDb.js | 265 +++++++++++++++++++++-------------------- package.json | 2 +- test/lib/PeerSync.js | 3 +- test/test.MessageDb.js | 19 +++ 7 files changed, 264 insertions(+), 178 deletions(-) create mode 100644 lib/MessageDb.js create mode 100644 test/test.MessageDb.js diff --git a/config/config.js b/config/config.js index dfe1bc48..0b811fe0 100644 --- a/config/config.js +++ b/config/config.js @@ -76,45 +76,6 @@ var bitcoindConf = { disableAgent: true }; -/*jshint multistr: true */ -console.log( - '\n\ - ____ _ __ __ ___ _ \n\ - / _/___ _____(_)___ _/ /_ / /_ / | ____ (_)\n\ - / // __ \\/ ___/ / __ `/ __ \\/ __/ / /\| \| / __ \\/ / \n\ - _/ // / / (__ ) / /_/ / / / / /_ / ___ |/ /_/ / / \n\ -/___/_/ /_/____/_/\\__, /_/ /_/\\__/ /_/ |_/ .___/_/ \n\ - /____/ /_/ \n\ -\n\t\t\t\t\t\tv%s\n\ - # Configuration:\n\ -\t\tNetwork: %s\tINSIGHT_NETWORK\n\ -\t\tDatabase Path: %s\tINSIGHT_DB\n\ -\t\tSafe Confirmations: %s\tINSIGHT_SAFE_CONFIRMATIONS\n\ -\t\tIgnore Cache: %s\tINSIGHT_IGNORE_CACHE\n\ - # Bicoind Connection configuration:\n\ -\t\tRPC Username: %s\tBITCOIND_USER\n\ -\t\tRPC Password: %s\tBITCOIND_PASS\n\ -\t\tRPC Protocol: %s\tBITCOIND_PROTO\n\ -\t\tRPC Host: %s\tBITCOIND_HOST\n\ -\t\tRPC Port: %s\tBITCOIND_PORT\n\ -\t\tP2P Host: %s\tBITCOIND_P2P_HOST\n\ -\t\tP2P Port: %s\tBITCOIND_P2P_PORT\n\ -\t\tData Dir: %s\tBITCOIND_DATADIR\n\ -\t\t%s\n\ -\nChange setting by assigning the enviroment variables in the last column. Example:\n\ - $ INSIGHT_NETWORK="testnet" BITCOIND_HOST="123.123.123.123" ./insight.js\ -\n\n', - version, - network, home, safeConfirmations, ignoreCache ? 'yes' : 'no', - bitcoindConf.user, - bitcoindConf.pass ? 'Yes(hidden)' : 'No', - bitcoindConf.protocol, - bitcoindConf.host, - bitcoindConf.port, - bitcoindConf.p2pHost, - bitcoindConf.p2pPort, - dataDir + (network === 'testnet' ? '*' : ''), (network === 'testnet' ? '* (/testnet3 is added automatically)' : '') -); if (!fs.existsSync(db)) { diff --git a/insight.js b/insight.js index 87c84a64..338f3a1e 100755 --- a/insight.js +++ b/insight.js @@ -15,6 +15,45 @@ var express = require('express'), //Initializing system variables var config = require('./config/config'); +// text title +/*jshint multistr: true */ +console.log( + '\n\ + ____ _ __ __ ___ _ \n\ + / _/___ _____(_)___ _/ /_ / /_ / | ____ (_)\n\ + / // __ \\/ ___/ / __ `/ __ \\/ __/ / /\| \| / __ \\/ / \n\ + _/ // / / (__ ) / /_/ / / / / /_ / ___ |/ /_/ / / \n\ +/___/_/ /_/____/_/\\__, /_/ /_/\\__/ /_/ |_/ .___/_/ \n\ + /____/ /_/ \n\ +\n\t\t\t\t\t\tv%s\n\ + # Configuration:\n\ +\t\tNetwork: %s\tINSIGHT_NETWORK\n\ +\t\tDatabase Path: %s\tINSIGHT_DB\n\ +\t\tSafe Confirmations: %s\tINSIGHT_SAFE_CONFIRMATIONS\n\ +\t\tIgnore Cache: %s\tINSIGHT_IGNORE_CACHE\n\ + # Bicoind Connection configuration:\n\ +\t\tRPC Username: %s\tBITCOIND_USER\n\ +\t\tRPC Password: %s\tBITCOIND_PASS\n\ +\t\tRPC Protocol: %s\tBITCOIND_PROTO\n\ +\t\tRPC Host: %s\tBITCOIND_HOST\n\ +\t\tRPC Port: %s\tBITCOIND_PORT\n\ +\t\tP2P Port: %s\tBITCOIND_P2P_PORT\n\ +\t\tData Dir: %s\tBITCOIND_DATADIR\n\ +\t\t%s\n\ +\nChange setting by assigning the enviroment variables in the last column. Example:\n\ + $ INSIGHT_NETWORK="testnet" BITCOIND_HOST="123.123.123.123" ./insight.js\ +\n\n', + version, + network, home, safeConfirmations, ignoreCache ? 'yes' : 'no', + bitcoindConf.user, + bitcoindConf.pass ? 'Yes(hidden)' : 'No', + bitcoindConf.protocol, + bitcoindConf.host, + bitcoindConf.port, + bitcoindConf.p2pPort, + dataDir + (network === 'testnet' ? '*' : ''), (network === 'testnet' ? '* (/testnet3 is added automatically)' : '') +); + /** * express app */ @@ -32,8 +71,7 @@ var walk = function(path) { if (/(.*)\.(js$)/.test(file)) { require(newPath); } - } - else if (stat.isDirectory()) { + } else if (stat.isDirectory()) { walk(newPath); } }); @@ -45,7 +83,9 @@ walk(models_path); * p2pSync process */ -var peerSync = new PeerSync({shouldBroadcast: true}); +var peerSync = new PeerSync({ + shouldBroadcast: true +}); if (!config.disableP2pSync) { peerSync.run(); @@ -60,16 +100,15 @@ var historicSync = new HistoricSync({ peerSync.historicSync = historicSync; if (!config.disableHistoricSync) { - historicSync.start({}, function(err){ + historicSync.start({}, function(err) { if (err) { var txt = 'ABORTED with error: ' + err.message; console.log('[historic_sync] ' + txt); } if (peerSync) peerSync.allowReorgs = true; }); -} -else - if (peerSync) peerSync.allowReorgs = true; +} else +if (peerSync) peerSync.allowReorgs = true; //express settings @@ -84,8 +123,8 @@ var ios = require('socket.io')(server); require('./app/controllers/socket.js').init(expressApp, ios); //Start the app by listening on -server.listen(config.port, function(){ - console.log('insight server listening on port %d in %s mode', server.address().port, process.env.NODE_ENV); +server.listen(config.port, function() { + console.log('insight server listening on port %d in %s mode', server.address().port, process.env.NODE_ENV); }); //expose app diff --git a/lib/MessageDb.js b/lib/MessageDb.js new file mode 100644 index 00000000..0dc502e8 --- /dev/null +++ b/lib/MessageDb.js @@ -0,0 +1,57 @@ +'use strict'; +var imports = require('soop').imports(); +var levelup = require('levelup'); +var config = require('../config/config'); +var Rpc = imports.rpc || require('./Rpc'); +var async = require('async'); +var logger = require('./logger').logger; + +var MESSAGE_PREFIX = 'msg-'; // msg-- => + +var MAX_OPEN_FILES = 500; +var CONCURRENCY = 5; + +var db = imports.db || levelup(config.leveldb + '/messages', { + maxOpenFiles: MAX_OPEN_FILES +}); + +var d = logger.log; +var info = logger.info; + + +var MessageDb = function() { + db.on('put', function(key, value) { + console.log(key + '=>' + value); + }); + db.on('ready', function() { + console.log('Database ready!'); + }); +}; + +MessageDb.prototype.close = function(cb) { + db.close(cb); +}; + + +var messageKey = function(from, to, ts) { + if (!ts) ts = Math.round(new Date().getTime() / 1000); + return MESSAGE_PREFIX + from.toString() + '-' + to.toString() + '-' + ts; +}; + +MessageDb.prototype.addMessage = function(m, from, to, cb) { + var key = messageKey(from, to); + var value = m; + db.put(key, value, cb); +}; + +MessageDb.prototype.getMessages = function(from, to, from_ts, to_ts, cb) { + // TODO + db.get(messageKey(from, to), function(err, val) { + if (err && err.notFound) return cb(); + if (err) return cb(err); + + return cb(null, val); + }); +}; + +module.exports = require('soop')(MessageDb); diff --git a/lib/TransactionDb.js b/lib/TransactionDb.js index b61976b1..cc1ff7de 100644 --- a/lib/TransactionDb.js +++ b/lib/TransactionDb.js @@ -1,6 +1,6 @@ 'use strict'; -var imports = require('soop').imports(); +var imports = require('soop').imports(); @@ -20,40 +20,42 @@ var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda var CONCURRENCY = 10; var DEFAULT_SAFE_CONFIRMATIONS = 6; -var MAX_OPEN_FILES = 500; -var END_OF_WORLD_TS = 1e13; +var MAX_OPEN_FILES = 500; +var END_OF_WORLD_TS = 1e13; // var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend /** - * Module dependencies. - */ + * Module dependencies. + */ -var bitcore = require('bitcore'), - Rpc = imports.rpc || require('./Rpc'), - util = bitcore.util, - networks = bitcore.networks, - levelup = require('levelup'), - async = require('async'), - config = require('../config/config'), - assert = require('assert'), - Script = bitcore.Script, - bitcoreUtil = bitcore.util, - buffertools = require('buffertools'); +var bitcore = require('bitcore'), + Rpc = imports.rpc || require('./Rpc'), + util = bitcore.util, + networks = bitcore.networks, + levelup = require('levelup'), + async = require('async'), + config = require('../config/config'), + assert = require('assert'), + Script = bitcore.Script, + bitcoreUtil = bitcore.util, + buffertools = require('buffertools'); var logger = require('./logger').logger; -var inf = logger.info; +var inf = logger.info; -var db = imports.db || levelup(config.leveldb + '/txs',{maxOpenFiles: MAX_OPEN_FILES} ); -var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch',config); +var db = imports.db || levelup(config.leveldb + '/txs', { + maxOpenFiles: MAX_OPEN_FILES +}); +var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch', config); // This is 0.1.2 = > c++ version of base58-native - var base58 = require('base58-native').base58Check; - var encodedData = require('soop').load('bitcore/util/EncodedData',{ - base58: base58 - }); - var versionedData= require('soop').load('bitcore/util/VersionedData',{ - parent: encodedData - }); +var base58 = require('base58-native').base58Check; +var encodedData = require('soop').load('bitcore/util/EncodedData', { + base58: base58 +}); +var versionedData = require('soop').load('bitcore/util/VersionedData', { + parent: encodedData +}); -var Address = require('soop').load('bitcore/lib/Address',{ +var Address = require('soop').load('bitcore/lib/Address', { parent: versionedData }); @@ -76,7 +78,9 @@ TransactionDb.prototype.drop = function(cb) { var path = config.leveldb + '/txs'; db.close(function() { require('leveldown').destroy(path, function() { - db = levelup(path, {maxOpenFiles: 500}); + db = levelup(path, { + maxOpenFiles: 500 + }); return cb(); }); }); @@ -278,13 +282,14 @@ TransactionDb.prototype.fromTxIdN = function(txid, n, cb) { var k = OUTS_PREFIX + txid + '-' + n; db.get(k, function(err, val) { - var ret; + var ret; if (!val || (err && err.notFound)) { - err=null; - ret= { unconfirmedInput: 1 }; - } - else { + err = null; + ret = { + unconfirmedInput: 1 + }; + } else { var a = val.split(':'); ret = { addr: a[0], @@ -312,7 +317,7 @@ TransactionDb.prototype.fromTxIdN = function(txid, n, cb) { }; -TransactionDb.prototype.deleteCacheForAddress = function(addr,cb) { +TransactionDb.prototype.deleteCacheForAddress = function(addr, cb) { var k = ADDR_PREFIX + addr + '-'; var dbScript = []; db.createReadStream({ @@ -330,17 +335,17 @@ TransactionDb.prototype.deleteCacheForAddress = function(addr,cb) { .on('error', function(err) { return cb(err); }) - .on('end', function (){ - db.batch(dbScript,cb); + .on('end', function() { + db.batch(dbScript, cb); }); }; -TransactionDb.prototype.cacheConfirmations = function(txouts,cb) { +TransactionDb.prototype.cacheConfirmations = function(txouts, cb) { var self = this; - var dbScript=[]; - for(var ii in txouts){ - var txout=txouts[ii]; + var dbScript = []; + for (var ii in txouts) { + var txout = txouts[ii]; //everything already cached? if (txout.spentIsConfirmedCached) { @@ -354,15 +359,14 @@ TransactionDb.prototype.cacheConfirmations = function(txouts,cb) { // if spent, we overwrite scriptPubKey cache (not needed anymore) // First 1 = txout.isConfirmedCached (must be equal to 1 at this point) infoToCache = [1, 1, txout.spentTxId, txout.spentIndex, txout.spentTs]; - } - else { - if (!txout.isConfirmedCached) { + } else { + if (!txout.isConfirmedCached) { infoToCache.push(1); - txout.confirmedWillBeCached=1; + txout.confirmedWillBeCached = 1; } } -//console.log('[TransactionDb.js.352:infoToCache:]',infoToCache); //TODO - if (infoToCache.length){ + //console.log('[TransactionDb.js.352:infoToCache:]',infoToCache); //TODO + if (infoToCache.length) { infoToCache.unshift(txout.value_sat); dbScript.push({ @@ -374,25 +378,24 @@ TransactionDb.prototype.cacheConfirmations = function(txouts,cb) { } } -//console.log('[TransactionDb.js.339:dbScript:]',dbScript); //TODO - db.batch(dbScript,cb); + //console.log('[TransactionDb.js.339:dbScript:]',dbScript); //TODO + db.batch(dbScript, cb); }; -TransactionDb.prototype.cacheScriptPubKey = function(txouts,cb) { -// console.log('[TransactionDb.js.381:cacheScriptPubKey:]'); //TODO +TransactionDb.prototype.cacheScriptPubKey = function(txouts, cb) { + // console.log('[TransactionDb.js.381:cacheScriptPubKey:]'); //TODO var self = this; - var dbScript=[]; - for(var ii in txouts){ - var txout=txouts[ii]; + var dbScript = []; + for (var ii in txouts) { + var txout = txouts[ii]; //everything already cached? if (txout.scriptPubKeyCached || txout.spentTxId) { continue; } if (txout.scriptPubKey) { - var infoToCache = [txout.value_sat, - (txout.isConfirmedCached || txout.confirmedWillBeCached)?1:0, txout.scriptPubKey]; + var infoToCache = [txout.value_sat, (txout.isConfirmedCached || txout.confirmedWillBeCached) ? 1 : 0, txout.scriptPubKey]; dbScript.push({ type: 'put', key: txout.key, @@ -400,7 +403,7 @@ TransactionDb.prototype.cacheScriptPubKey = function(txouts,cb) { }); } } - db.batch(dbScript,cb); + db.batch(dbScript, cb); }; @@ -424,12 +427,12 @@ TransactionDb.prototype._parseAddrData = function(k, data, ignoreCache) { // v[1]== isConfirmedCached // v[2]=== '1' -> is SpendCached -> [4]=spendTxId [5]=spentIndex [6]=spendTs // v[2]!== '1' -> is ScriptPubkey -> [[2] = scriptPubkey - if (v[1]==='1'){ + if (v[1] === '1') { item.isConfirmed = 1; item.isConfirmedCached = 1; // console.log('[TransactionDb.js.356] CACHE HIT CONF:', item.key); // Sent, confirmed - if (v[2] === '1'){ + if (v[2] === '1') { // console.log('[TransactionDb.js.356] CACHE HIT SPENT:', item.key); item.spentIsConfirmed = 1; item.spentIsConfirmedCached = 1; @@ -441,7 +444,7 @@ TransactionDb.prototype._parseAddrData = function(k, data, ignoreCache) { else if (v[2]) { item.scriptPubKey = v[2]; item.scriptPubKeyCached = 1; -// console.log('[TransactionDb.js.356] CACHE HIT SCRIPTPUBKEY:', item.key, v, item.scriptPubKey); + // console.log('[TransactionDb.js.356] CACHE HIT SCRIPTPUBKEY:', item.key, v, item.scriptPubKey); } } return item; @@ -452,24 +455,26 @@ TransactionDb.prototype.fromAddr = function(addr, opts, cb) { var self = this; var k = ADDR_PREFIX + addr + '-'; var ret = []; - var unique={}; + var unique = {}; db.createReadStream({ start: k, end: k + '~', - limit: opts.txLimit>0 ? opts.txLimit: -1, // -1 means not limit + limit: opts.txLimit > 0 ? opts.txLimit : -1, // -1 means not limit }) .on('data', function(data) { var k = data.key.split('-'); - var index = k[3]+k[4]; + var index = k[3] + k[4]; if (!unique[index]) { - unique[index]=1; + unique[index] = 1; ret.push(self._parseAddrData(k, data, opts.ignoreCache)); } }) .on('error', cb) .on('end', function() { - async.eachLimit(ret.filter(function(x){return !x.spentIsConfirmed;}), CONCURRENCY, function(o, e_c) { + async.eachLimit(ret.filter(function(x) { + return !x.spentIsConfirmed; + }), CONCURRENCY, function(o, e_c) { var k = SPENT_PREFIX + o.txid + '-' + o.index + '-'; db.createReadStream({ start: k, @@ -488,18 +493,20 @@ TransactionDb.prototype.fromAddr = function(addr, opts, cb) { }); }; -TransactionDb.prototype._fromBuffer = function (buf) { - var buf2 = buffertools.reverse(buf); - return parseInt(buf2.toString('hex'), 16); +TransactionDb.prototype._fromBuffer = function(buf) { + var buf2 = buffertools.reverse(buf); + return parseInt(buf2.toString('hex'), 16); }; -TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) { +TransactionDb.prototype.getStandardizedTx = function(tx, time, isCoinBase) { var self = this; tx.txid = bitcoreUtil.formatHashFull(tx.getHash()); - var ti=0; + var ti = 0; tx.vin = tx.ins.map(function(txin) { - var ret = {n: ti++}; + var ret = { + n: ti++ + }; if (isCoinBase) { ret.isCoinBase = true; } else { @@ -517,7 +524,9 @@ TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) { var addrs = new Address.fromScriptPubKey(s, config.network); // support only for p2pubkey p2pubkeyhash and p2sh if (addrs && addrs.length === 1) { - val = {addresses: [addrs[0].toString() ] }; + val = { + addresses: [addrs[0].toString()] + }; } } return { @@ -532,22 +541,23 @@ TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) { TransactionDb.prototype.fillScriptPubKey = function(txouts, cb) { - var self=this; + var self = this; // Complete utxo info - async.eachLimit(txouts, CONCURRENCY, function (txout, a_c) { + async.eachLimit(txouts, CONCURRENCY, function(txout, a_c) { self.fromIdInfoSimple(txout.txid, function(err, info) { if (!info || !info.vout) return a_c(err); txout.scriptPubKey = info.vout[txout.index].scriptPubKey.hex; return a_c(); }); - }, function(){ + }, function() { self.cacheScriptPubKey(txouts, cb); }); }; TransactionDb.prototype.removeFromTxId = function(txid, cb) { async.series([ + function(c) { db.createReadStream({ start: OUTS_PREFIX + txid + '-', @@ -579,15 +589,15 @@ TransactionDb.prototype.removeFromTxId = function(txid, cb) { // relatedAddrs is an optional hash, to collect related addresses in the transaction TransactionDb.prototype._addScript = function(tx, relatedAddrs) { - var dbScript = []; - var ts = tx.time; - var txid = tx.txid || tx.hash; -// var u=require('util'); -// console.log('[TransactionDb.js.518]', u.inspect(tx,{depth:10})); //TODO + var dbScript = []; + var ts = tx.time; + var txid = tx.txid || tx.hash; + // var u=require('util'); + // console.log('[TransactionDb.js.518]', u.inspect(tx,{depth:10})); //TODO // Input Outpoints (mark them as spent) - for(var ii in tx.vin) { + for (var ii in tx.vin) { var i = tx.vin[ii]; - if (i.txid){ + if (i.txid) { var k = SPENT_PREFIX + i.txid + '-' + i.vout + '-' + txid + '-' + i.n; dbScript.push({ type: 'put', @@ -597,27 +607,27 @@ TransactionDb.prototype._addScript = function(tx, relatedAddrs) { } } - for(var ii in tx.vout) { + for (var ii in tx.vout) { var o = tx.vout[ii]; - if ( o.scriptPubKey && o.scriptPubKey.addresses && - o.scriptPubKey.addresses[0] && !o.scriptPubKey.addresses[1] // TODO : not supported=> standard multisig - ) { - var addr = o.scriptPubKey.addresses[0]; - var sat = o.valueSat || ((o.value||0) * util.COIN).toFixed(0); + if (o.scriptPubKey && o.scriptPubKey.addresses && + o.scriptPubKey.addresses[0] && !o.scriptPubKey.addresses[1] // TODO : not supported=> standard multisig + ) { + var addr = o.scriptPubKey.addresses[0]; + var sat = o.valueSat || ((o.value || 0) * util.COIN).toFixed(0); - if (relatedAddrs) relatedAddrs[addr]=1; - var k = OUTS_PREFIX + txid + '-' + o.n; - var tsr = END_OF_WORLD_TS - ts; - dbScript.push({ - type: 'put', - key: k, - value: addr + ':' + sat, - },{ - type: 'put', - key: ADDR_PREFIX + addr + '-' + tsr + '-'+ txid + '-' + o.n, - value: sat, - }); - } + if (relatedAddrs) relatedAddrs[addr] = 1; + var k = OUTS_PREFIX + txid + '-' + o.n; + var tsr = END_OF_WORLD_TS - ts; + dbScript.push({ + type: 'put', + key: k, + value: addr + ':' + sat, + }, { + type: 'put', + key: ADDR_PREFIX + addr + '-' + tsr + '-' + txid + '-' + o.n, + value: sat, + }); + } } return dbScript; }; @@ -626,12 +636,14 @@ TransactionDb.prototype._addScript = function(tx, relatedAddrs) { TransactionDb.prototype.add = function(tx, cb) { var relatedAddrs = {}; var dbScript = this._addScript(tx, relatedAddrs); - db.batch(dbScript, function(err) { return cb(err,relatedAddrs);}); + db.batch(dbScript, function(err) { + return cb(err, relatedAddrs); + }); }; TransactionDb.prototype._addManyFromObjs = function(txs, next) { var dbScript = []; - for(var ii in txs){ + for (var ii in txs) { var s = this._addScript(txs[ii]); dbScript = dbScript.concat(s); } @@ -639,17 +651,17 @@ TransactionDb.prototype._addManyFromObjs = function(txs, next) { }; TransactionDb.prototype._addManyFromHashes = function(txs, next) { - var self=this; + var self = this; var dbScript = []; async.eachLimit(txs, CONCURRENCY, function(tx, each_cb) { - if (tx === genesisTXID) - return each_cb(); + if (tx === genesisTXID) + return each_cb(); - Rpc.getTxInfo(tx, function(err, inInfo) { - if (!inInfo) return each_cb(err); - dbScript = dbScript.concat(self._addScript(inInfo)); - return each_cb(); - }); + Rpc.getTxInfo(tx, function(err, inInfo) { + if (!inInfo) return each_cb(err); + dbScript = dbScript.concat(self._addScript(inInfo)); + return each_cb(); + }); }, function(err) { if (err) return next(err); @@ -661,10 +673,10 @@ TransactionDb.prototype._addManyFromHashes = function(txs, next) { TransactionDb.prototype.addMany = function(txs, next) { if (!txs) return next(); - var fn = (typeof txs[0] ==='string') ? + var fn = (typeof txs[0] === 'string') ? this._addManyFromHashes : this._addManyFromObjs; - return fn.apply(this,[txs, next]); + return fn.apply(this, [txs, next]); }; @@ -677,7 +689,7 @@ TransactionDb.prototype.getPoolInfo = function(txid, cb) { if (txInfo && txInfo.isCoinBase) ret = self.poolMatch.match(new Buffer(txInfo.vin[0].coinbase, 'hex')); - + return cb(ret); }); }; @@ -685,16 +697,16 @@ TransactionDb.prototype.getPoolInfo = function(txid, cb) { TransactionDb.prototype.checkVersion02 = function(cb) { var k = 'txa-'; - var isV2=1; + var isV2 = 1; db.createReadStream({ start: k, end: k + '~', limit: 1, }) .on('data', function(data) { - isV2=0; + isV2 = 0; }) - .on('end', function (){ + .on('end', function() { return cb(isV2); }); }; @@ -702,9 +714,9 @@ TransactionDb.prototype.checkVersion02 = function(cb) { TransactionDb.prototype.migrateV02 = function(cb) { var k = 'txa-'; var dbScript = []; - var c=0; - var c2=0; - var N=50000; + var c = 0; + var c2 = 0; + var N = 50000; db.createReadStream({ start: k, end: k + '~' @@ -714,22 +726,21 @@ TransactionDb.prototype.migrateV02 = function(cb) { var v = data.value.split(':'); dbScript.push({ type: 'put', - key: ADDR_PREFIX + k[1] + '-' + (END_OF_WORLD_TS - parseInt(v[1])) - + '-' + k[2] + '-' + k[3], + key: ADDR_PREFIX + k[1] + '-' + (END_OF_WORLD_TS - parseInt(v[1])) + '-' + k[2] + '-' + k[3], value: v[0], }); - if (c++>N) { - console.log('\t%dM txs outs processed', ((c2+=N)/1e6).toFixed(3)); //TODO - db.batch(dbScript,function () { - c=0; - dbScript=[]; + if (c++ > N) { + console.log('\t%dM txs outs processed', ((c2 += N) / 1e6).toFixed(3)); //TODO + db.batch(dbScript, function() { + c = 0; + dbScript = []; }); } }) .on('error', function(err) { return cb(err); }) - .on('end', function (){ + .on('end', function() { return cb(); }); }; diff --git a/package.json b/package.json index f4ddecc5..25993fa1 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "grunt-nodemon": "~0.2.0", "grunt-mocha-test": "~0.8.1", "should": "2.1.1", - "chai": "=1.9.1", + "chai": "*", "grunt-markdown": "~0.5.0" } } diff --git a/test/lib/PeerSync.js b/test/lib/PeerSync.js index 092c9bae..9c29b11e 100644 --- a/test/lib/PeerSync.js +++ b/test/lib/PeerSync.js @@ -28,8 +28,7 @@ describe('PeerSync', function() { it('should return with no errors', function() { expect(function() { ps.handleInv(inv_info); - }).not.to. - throw (Error); + }).not.to.throw(Error); }); it('should call sendGetData', function() { ps.handleInv(inv_info); diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js new file mode 100644 index 00000000..d4a11ee8 --- /dev/null +++ b/test/test.MessageDb.js @@ -0,0 +1,19 @@ +'use strict'; + +var chai = require('chai'); +var should = chai.should; + +var MessageDb = require('../lib/MessageDb'); + +describe('MessageDb', function() { + it('should be able to create instance', function() { + var mdb = new MessageDb(); + }); + it('should receive events', function(done) { + var mdb = new MessageDb(); + var message = {}; + mdb.addMessage(message, 'from', 'to', function(err) { + done(); + }); + }); +}); From ac1c98f8d4ae0c9745b3aea368d2724332473424 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 30 Jul 2014 16:23:04 -0300 Subject: [PATCH 02/16] fix title print --- config/config.js | 1 + insight.js | 46 +++++++++++++++++++++--------------------- lib/MessageDb.js | 2 +- test/test.MessageDb.js | 7 ++++++- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/config/config.js b/config/config.js index 0b811fe0..379e9830 100644 --- a/config/config.js +++ b/config/config.js @@ -89,6 +89,7 @@ if (!fs.existsSync(db)) { } module.exports = { + version: version, root: rootPath, publicPath: process.env.INSIGHT_PUBLIC_PATH || false, appName: 'Insight ' + env, diff --git a/insight.js b/insight.js index 338f3a1e..6c41b9b7 100755 --- a/insight.js +++ b/insight.js @@ -26,32 +26,32 @@ console.log( /___/_/ /_/____/_/\\__, /_/ /_/\\__/ /_/ |_/ .___/_/ \n\ /____/ /_/ \n\ \n\t\t\t\t\t\tv%s\n\ - # Configuration:\n\ -\t\tNetwork: %s\tINSIGHT_NETWORK\n\ -\t\tDatabase Path: %s\tINSIGHT_DB\n\ -\t\tSafe Confirmations: %s\tINSIGHT_SAFE_CONFIRMATIONS\n\ -\t\tIgnore Cache: %s\tINSIGHT_IGNORE_CACHE\n\ +# Configuration:\n\ +\tINSIGHT_NETWORK (Network): %s\n\ +\tINSIGHT_DB (Database Path): %s\n\ +\tINSIGHT_SAFE_CONFIRMATIONS (Safe Confirmations): %s\n\ +\tINSIGHT_IGNORE_CACHE (Ignore Cache): %s\n\ # Bicoind Connection configuration:\n\ -\t\tRPC Username: %s\tBITCOIND_USER\n\ -\t\tRPC Password: %s\tBITCOIND_PASS\n\ -\t\tRPC Protocol: %s\tBITCOIND_PROTO\n\ -\t\tRPC Host: %s\tBITCOIND_HOST\n\ -\t\tRPC Port: %s\tBITCOIND_PORT\n\ -\t\tP2P Port: %s\tBITCOIND_P2P_PORT\n\ -\t\tData Dir: %s\tBITCOIND_DATADIR\n\ -\t\t%s\n\ -\nChange setting by assigning the enviroment variables in the last column. Example:\n\ +\tRPC Username: %s\t\tBITCOIND_USER\n\ +\tRPC Password: %s\tBITCOIND_PASS\n\ +\tRPC Protocol: %s\t\tBITCOIND_PROTO\n\ +\tRPC Host: %s\t\tBITCOIND_HOST\n\ +\tRPC Port: %s\t\t\tBITCOIND_PORT\n\ +\tP2P Port: %s\t\t\tBITCOIND_P2P_PORT\n\ +\tBITCOIND_DATADIR: %s\n\ +\t%s\n\ +\nChange setting by assigning the enviroment variables above. Example:\n\ $ INSIGHT_NETWORK="testnet" BITCOIND_HOST="123.123.123.123" ./insight.js\ \n\n', - version, - network, home, safeConfirmations, ignoreCache ? 'yes' : 'no', - bitcoindConf.user, - bitcoindConf.pass ? 'Yes(hidden)' : 'No', - bitcoindConf.protocol, - bitcoindConf.host, - bitcoindConf.port, - bitcoindConf.p2pPort, - dataDir + (network === 'testnet' ? '*' : ''), (network === 'testnet' ? '* (/testnet3 is added automatically)' : '') + config.version, + config.network, config.leveldb, config.safeConfirmations, config.ignoreCache ? 'yes' : 'no', + config.bitcoind.user, + config.bitcoind.pass ? 'Yes(hidden)' : 'No', + config.bitcoind.protocol, + config.bitcoind.host, + config.bitcoind.port, + config.bitcoind.p2pPort, + config.bitcoind.dataDir + (config.network === 'testnet' ? '*' : ''), (config.network === 'testnet' ? '* (/testnet3 is added automatically)' : '') ); /** diff --git a/lib/MessageDb.js b/lib/MessageDb.js index 0dc502e8..c8d1766f 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -34,7 +34,7 @@ MessageDb.prototype.close = function(cb) { var messageKey = function(from, to, ts) { - if (!ts) ts = Math.round(new Date().getTime() / 1000); + if (!ts) ts = Math.round(new Date().getTime()); return MESSAGE_PREFIX + from.toString() + '-' + to.toString() + '-' + ts; }; diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js index d4a11ee8..b5012a89 100644 --- a/test/test.MessageDb.js +++ b/test/test.MessageDb.js @@ -4,6 +4,8 @@ var chai = require('chai'); var should = chai.should; var MessageDb = require('../lib/MessageDb'); +var bitcore = require('bitcore'); +var SIN = bitcore.SIN; describe('MessageDb', function() { it('should be able to create instance', function() { @@ -12,7 +14,10 @@ describe('MessageDb', function() { it('should receive events', function(done) { var mdb = new MessageDb(); var message = {}; - mdb.addMessage(message, 'from', 'to', function(err) { + var from = new SIN(new Buffer('dadbad00', 'hex')); + var to = new SIN(new Buffer('bacacafe', 'hex')); + console.log(to.toString()); + mdb.addMessage(message, from, to, function(err) { done(); }); }); From 7273776e55166282a8c85475fdf4f30220fc6d6d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 30 Jul 2014 17:29:28 -0300 Subject: [PATCH 03/16] linking socket with leveldb --- app/controllers/socket.js | 19 ++++++++++++------- insight.js | 2 +- lib/MessageDb.js | 39 +++++++++++++++++++++++++++++---------- test/test.MessageDb.js | 22 ++++++++++++++++------ 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/app/controllers/socket.js b/app/controllers/socket.js index d6757292..81ce0985 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -1,11 +1,10 @@ 'use strict'; // server-side socket behaviour -// io is a variable already taken in express -var ios = null; +var ios = null; // io is already taken in express var util = require('bitcore').util; -module.exports.init = function(app, io_ext) { +module.exports.init = function(io_ext) { ios = io_ext; ios.sockets.on('connection', function(socket) { socket.on('subscribe', function(topic) { @@ -21,9 +20,7 @@ module.exports.broadcastTx = function(tx) { t = { txid: tx }; - } - - else { + } else { t = { txid: tx.txid, size: tx.size, @@ -34,7 +31,7 @@ module.exports.broadcastTx = function(tx) { valueOut += o.valueSat; }); - t.valueOut = (valueOut.toFixed(8)/util.COIN); + t.valueOut = (valueOut.toFixed(8) / util.COIN); } ios.sockets.in('inv').emit('tx', t); } @@ -55,3 +52,11 @@ module.exports.broadcastSyncInfo = function(historicSync) { if (ios) ios.sockets.in('sync').emit('status', historicSync); }; + +module.exports.broadcastMessage = function(from, to, ts, message) { + console.log('sending socket: %s, %s, %s, %s', from, to, ts, message); + if (ios) { + ios.sockets.in(to).emit(from + '-' + ts, message); + } + +} diff --git a/insight.js b/insight.js index 6c41b9b7..0923081c 100755 --- a/insight.js +++ b/insight.js @@ -120,7 +120,7 @@ require('./config/routes')(expressApp); // socket.io var server = require('http').createServer(expressApp); var ios = require('socket.io')(server); -require('./app/controllers/socket.js').init(expressApp, ios); +require('./app/controllers/socket.js').init(ios); //Start the app by listening on server.listen(config.port, function() { diff --git a/lib/MessageDb.js b/lib/MessageDb.js index c8d1766f..61bd3340 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -5,31 +5,50 @@ var config = require('../config/config'); var Rpc = imports.rpc || require('./Rpc'); var async = require('async'); var logger = require('./logger').logger; +var util = require('util'); +var EventEmitter = require('events').EventEmitter; +var sockets = require('../app/controllers/socket.js'); var MESSAGE_PREFIX = 'msg-'; // msg-- => var MAX_OPEN_FILES = 500; var CONCURRENCY = 5; -var db = imports.db || levelup(config.leveldb + '/messages', { - maxOpenFiles: MAX_OPEN_FILES -}); var d = logger.log; var info = logger.info; +var db; +var MessageDb = function(opts) { + opts = opts || {}; + this.path = config.leveldb + '/messages' + (opts.name ? ('-' + opts.name) : '') + if (!db) { + db = levelup(this.path, { + maxOpenFiles: MAX_OPEN_FILES + }); + } + this.db = db; + this.initEvents(); +}; +util.inherits(MessageDb, EventEmitter); -var MessageDb = function() { - db.on('put', function(key, value) { - console.log(key + '=>' + value); +MessageDb.prototype.initEvents = function() { + this.db.on('put', function(key, value) { + console.log('putting ' + key + '=>' + value); + var spl = key.split('-'); + var from = spl[0]; + var to = spl[1]; + var ts = spl[2]; + var message = value; + sockets.broadcastMessage(from, to, ts, message); }); - db.on('ready', function() { + this.db.on('ready', function() { console.log('Database ready!'); }); }; MessageDb.prototype.close = function(cb) { - db.close(cb); + this.db.close(cb); }; @@ -41,12 +60,12 @@ var messageKey = function(from, to, ts) { MessageDb.prototype.addMessage = function(m, from, to, cb) { var key = messageKey(from, to); var value = m; - db.put(key, value, cb); + this.db.put(key, value, cb); }; MessageDb.prototype.getMessages = function(from, to, from_ts, to_ts, cb) { // TODO - db.get(messageKey(from, to), function(err, val) { + this.db.get(messageKey(from, to), function(err, val) { if (err && err.notFound) return cb(); if (err) return cb(err); diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js index b5012a89..4a89d3aa 100644 --- a/test/test.MessageDb.js +++ b/test/test.MessageDb.js @@ -9,13 +9,23 @@ var SIN = bitcore.SIN; describe('MessageDb', function() { it('should be able to create instance', function() { - var mdb = new MessageDb(); + var mdb = new MessageDb(opts); }); - it('should receive events', function(done) { - var mdb = new MessageDb(); - var message = {}; - var from = new SIN(new Buffer('dadbad00', 'hex')); - var to = new SIN(new Buffer('bacacafe', 'hex')); + it('should be able to close instance', function() { + var mdb = new MessageDb(opts); + mdb.close(); + }); + var opts = { + name: 'test-MessageDb' + }; + var from = new SIN(new Buffer('dadbad00', 'hex')); + var to = new SIN(new Buffer('bacacafe', 'hex')); + var message = { + a: 1, + b: 2 + }; + it('should be able to add messages', function(done) { + var mdb = new MessageDb(opts); console.log(to.toString()); mdb.addMessage(message, from, to, function(err) { done(); From b825f51ce4fb9f0e8d7a0055ba8a8c544b35c190 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 31 Jul 2014 14:06:47 -0300 Subject: [PATCH 04/16] getMessages working --- lib/MessageDb.js | 59 +++++++++++++++++++++++++++--------------- package.json | 13 +++++----- test/test.MessageDb.js | 42 +++++++++++++++++++++++------- 3 files changed, 78 insertions(+), 36 deletions(-) diff --git a/lib/MessageDb.js b/lib/MessageDb.js index 61bd3340..8dc62c83 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -1,5 +1,6 @@ 'use strict'; -var imports = require('soop').imports(); +var soop = require('soop'); +var imports = soop.imports(); var levelup = require('levelup'); var config = require('../config/config'); var Rpc = imports.rpc || require('./Rpc'); @@ -21,29 +22,27 @@ var db; var MessageDb = function(opts) { opts = opts || {}; - this.path = config.leveldb + '/messages' + (opts.name ? ('-' + opts.name) : '') - if (!db) { - db = levelup(this.path, { - maxOpenFiles: MAX_OPEN_FILES - }); - } - this.db = db; + this.path = config.leveldb + '/messages' + (opts.name ? ('-' + opts.name) : ''); + this.db = opts.db || db || levelup(this.path, { + maxOpenFiles: MAX_OPEN_FILES, + valueEncoding : 'json' + }); + db = this.db; this.initEvents(); }; util.inherits(MessageDb, EventEmitter); MessageDb.prototype.initEvents = function() { this.db.on('put', function(key, value) { - console.log('putting ' + key + '=>' + value); var spl = key.split('-'); - var from = spl[0]; - var to = spl[1]; - var ts = spl[2]; + var from = spl[1]; + var to = spl[2]; + var ts = spl[3]; var message = value; sockets.broadcastMessage(from, to, ts, message); }); this.db.on('ready', function() { - console.log('Database ready!'); + //console.log('Database ready!'); }); }; @@ -63,14 +62,32 @@ MessageDb.prototype.addMessage = function(m, from, to, cb) { this.db.put(key, value, cb); }; -MessageDb.prototype.getMessages = function(from, to, from_ts, to_ts, cb) { - // TODO - this.db.get(messageKey(from, to), function(err, val) { - if (err && err.notFound) return cb(); - if (err) return cb(err); +MessageDb.prototype.getMessages = function(from, to, lower_ts, upper_ts, cb) { + var list = []; + var opts = { + start: messageKey(from, to, upper_ts.getTime()), + end: messageKey(from, to, lower_ts.getTime()), + //limit: limit, TODO + reverse: 1, + }; - return cb(null, val); - }); + db.createReadStream(opts) + .on('data', function(data) { + var spl = data.key.split('-'); + var from = spl[1]; + var to = spl[2]; + var ts = spl[3]; + list.push({ + ts: ts, + message: data.value, + }); + }) + .on('error', function(err) { + return cb(err); + }) + .on('end', function() { + return cb(null, list.reverse()); + }); }; -module.exports = require('soop')(MessageDb); +module.exports = soop(MessageDb); diff --git a/package.json b/package.json index 25993fa1..9e04263f 100644 --- a/package.json +++ b/package.json @@ -71,16 +71,17 @@ "bufferput": "git://github.com/bitpay/node-bufferput.git" }, "devDependencies": { + "chai": "*", "grunt": "~0.4.2", "grunt-cli": "~0.1.11", - "grunt-env": "~0.4.1", + "grunt-concurrent": "~0.4.2", "grunt-contrib-jshint": "~0.8.0", "grunt-contrib-watch": "~0.5.3", - "grunt-concurrent": "~0.4.2", - "grunt-nodemon": "~0.2.0", + "grunt-env": "~0.4.1", + "grunt-markdown": "~0.5.0", "grunt-mocha-test": "~0.8.1", - "should": "2.1.1", - "chai": "*", - "grunt-markdown": "~0.5.0" + "grunt-nodemon": "~0.2.0", + "memdown": "^0.10.2", + "should": "2.1.1" } } diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js index 4a89d3aa..44b91d1e 100644 --- a/test/test.MessageDb.js +++ b/test/test.MessageDb.js @@ -2,33 +2,57 @@ var chai = require('chai'); var should = chai.should; +var expect = chai.expect; var MessageDb = require('../lib/MessageDb'); var bitcore = require('bitcore'); var SIN = bitcore.SIN; +var levelup = require('levelup'); +var memdown = require('memdown'); describe('MessageDb', function() { + var opts = { + name: 'test-MessageDb', + db: levelup({ + db: memdown, + sync: true, + valueEncoding : 'json' + }) + }; it('should be able to create instance', function() { var mdb = new MessageDb(opts); + expect(mdb).to.exist; }); - it('should be able to close instance', function() { - var mdb = new MessageDb(opts); - mdb.close(); + it('should be able to create default instance', function() { + var mdb = MessageDb.default(); + expect(mdb).to.exist; }); - var opts = { - name: 'test-MessageDb' - }; var from = new SIN(new Buffer('dadbad00', 'hex')); var to = new SIN(new Buffer('bacacafe', 'hex')); var message = { a: 1, b: 2 }; - it('should be able to add messages', function(done) { + it('should be able to add and read messages', function(done) { var mdb = new MessageDb(opts); - console.log(to.toString()); mdb.addMessage(message, from, to, function(err) { - done(); + expect(err).to.not.exist; + var lower_ts = new Date('01/01/2014'); + var upper_ts = new Date(); + mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { + expect(err).to.not.exist; + messages.length.should.equal(1); + var m = messages[0].message; + m.a.should.equal(1); + m.b.should.equal(2); + done(); + + }); }); }); + it('should be able to close instance', function() { + var mdb = new MessageDb(opts); + mdb.close(); + expect(mdb).to.exist; + }); }); From 2174f3e4befcb90ee4c0a36eb6cbca4c5bdf73ea Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 31 Jul 2014 15:16:05 -0300 Subject: [PATCH 05/16] fix multiple handlers --- app/controllers/socket.js | 2 +- lib/MessageDb.js | 18 +++++++++-------- package.json | 1 + test/test.MessageDb.js | 41 ++++++++++++++++++++++++++++++++++----- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/app/controllers/socket.js b/app/controllers/socket.js index 81ce0985..04521a93 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -54,7 +54,7 @@ module.exports.broadcastSyncInfo = function(historicSync) { }; module.exports.broadcastMessage = function(from, to, ts, message) { - console.log('sending socket: %s, %s, %s, %s', from, to, ts, message); + console.log('sending socket: %s, %s, %s, %s', from, to, ts, JSON.stringify(message)); if (ios) { ios.sockets.in(to).emit(from + '-' + ts, message); } diff --git a/lib/MessageDb.js b/lib/MessageDb.js index 8dc62c83..f1b701ea 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -9,6 +9,7 @@ var logger = require('./logger').logger; var util = require('util'); var EventEmitter = require('events').EventEmitter; var sockets = require('../app/controllers/socket.js'); +var microtime = require('microtime'); var MESSAGE_PREFIX = 'msg-'; // msg-- => @@ -25,14 +26,15 @@ var MessageDb = function(opts) { this.path = config.leveldb + '/messages' + (opts.name ? ('-' + opts.name) : ''); this.db = opts.db || db || levelup(this.path, { maxOpenFiles: MAX_OPEN_FILES, - valueEncoding : 'json' + valueEncoding: 'json' }); - db = this.db; this.initEvents(); + db = this.db; }; util.inherits(MessageDb, EventEmitter); MessageDb.prototype.initEvents = function() { + if (db) return; this.db.on('put', function(key, value) { var spl = key.split('-'); var from = spl[1]; @@ -52,7 +54,7 @@ MessageDb.prototype.close = function(cb) { var messageKey = function(from, to, ts) { - if (!ts) ts = Math.round(new Date().getTime()); + if (!ts) ts = Math.round(microtime.now()); return MESSAGE_PREFIX + from.toString() + '-' + to.toString() + '-' + ts; }; @@ -65,10 +67,10 @@ MessageDb.prototype.addMessage = function(m, from, to, cb) { MessageDb.prototype.getMessages = function(from, to, lower_ts, upper_ts, cb) { var list = []; var opts = { - start: messageKey(from, to, upper_ts.getTime()), - end: messageKey(from, to, lower_ts.getTime()), - //limit: limit, TODO - reverse: 1, + end: messageKey(from, to, lower_ts), + start: messageKey(from, to, upper_ts), + // limit: limit, TODO + reverse: true, }; db.createReadStream(opts) @@ -76,7 +78,7 @@ MessageDb.prototype.getMessages = function(from, to, lower_ts, upper_ts, cb) { var spl = data.key.split('-'); var from = spl[1]; var to = spl[2]; - var ts = spl[3]; + var ts = +spl[3]; list.push({ ts: ts, message: data.value, diff --git a/package.json b/package.json index 9e04263f..31dd267a 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "grunt-mocha-test": "~0.8.1", "grunt-nodemon": "~0.2.0", "memdown": "^0.10.2", + "microtime": "^0.6.0", "should": "2.1.1" } } diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js index 44b91d1e..c6aabaa0 100644 --- a/test/test.MessageDb.js +++ b/test/test.MessageDb.js @@ -9,6 +9,7 @@ var bitcore = require('bitcore'); var SIN = bitcore.SIN; var levelup = require('levelup'); var memdown = require('memdown'); +var microtime = require('microtime'); describe('MessageDb', function() { var opts = { @@ -16,7 +17,7 @@ describe('MessageDb', function() { db: levelup({ db: memdown, sync: true, - valueEncoding : 'json' + valueEncoding: 'json' }) }; it('should be able to create instance', function() { @@ -33,20 +34,50 @@ describe('MessageDb', function() { a: 1, b: 2 }; - it('should be able to add and read messages', function(done) { + var message2 = {}; + var message3 = ['a', 'b']; + it('should be able to add and read a message', function(done) { var mdb = new MessageDb(opts); + var lower_ts = microtime.now(); mdb.addMessage(message, from, to, function(err) { expect(err).to.not.exist; - var lower_ts = new Date('01/01/2014'); - var upper_ts = new Date(); + var upper_ts = microtime.now(); mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { expect(err).to.not.exist; messages.length.should.equal(1); + messages[0].ts.should.be.below(upper_ts); + messages[0].ts.should.be.above(lower_ts); var m = messages[0].message; m.a.should.equal(1); m.b.should.equal(2); done(); - + }); + }); + }); + it('should be able to add many messages and read them', function(done) { + var mdb = new MessageDb(opts); + var lower_ts = microtime.now(); + mdb.addMessage(message, from, to, function(err) { + expect(err).to.not.exist; + mdb.addMessage(message2, from, to, function(err) { + expect(err).to.not.exist; + var upper_ts = microtime.now(); + setTimeout(function() { + mdb.addMessage(message3, from, to, function(err) { + expect(err).to.not.exist; + mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { + expect(err).to.not.exist; + messages.length.should.equal(2); + messages[0].ts.should.be.below(upper_ts); + messages[0].ts.should.be.above(lower_ts); + JSON.stringify(messages[0].message).should.equal('{"a":1,"b":2}'); + messages[1].ts.should.be.below(upper_ts); + messages[1].ts.should.be.above(lower_ts); + JSON.stringify(messages[1].message).should.equal('{}'); + done(); + }); + }); + }, 10); }); }); }); From fe2f6ec6c48b74dd72709f52299eb86e06208e75 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 31 Jul 2014 16:07:14 -0300 Subject: [PATCH 06/16] add example of websocket API use --- app/controllers/socket.js | 14 ++++++- examples/messages.html | 78 +++++++++++++++++++++++++++++++++++++++ lib/MessageDb.js | 1 + 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 examples/messages.html diff --git a/app/controllers/socket.js b/app/controllers/socket.js index 04521a93..71e7be0c 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -3,13 +3,20 @@ // server-side socket behaviour var ios = null; // io is already taken in express var util = require('bitcore').util; +var mdb = require('../../lib/MessageDb').default(); module.exports.init = function(io_ext) { ios = io_ext; ios.sockets.on('connection', function(socket) { socket.on('subscribe', function(topic) { + console.log('subscribe ' + topic); socket.join(topic); }); + socket.on('message', function(m) { + mdb.addMessage(m.payload, m.from, m.to, function(err) { + if (err) throw err; // TODO: handle + }); + }); }); }; @@ -54,9 +61,12 @@ module.exports.broadcastSyncInfo = function(historicSync) { }; module.exports.broadcastMessage = function(from, to, ts, message) { - console.log('sending socket: %s, %s, %s, %s', from, to, ts, JSON.stringify(message)); if (ios) { - ios.sockets.in(to).emit(from + '-' + ts, message); + console.log('sending message '+to); + ios.sockets.in(to).emit(from, { + payload: message, + ts: ts + }); } } diff --git a/examples/messages.html b/examples/messages.html new file mode 100644 index 00000000..2130fd2a --- /dev/null +++ b/examples/messages.html @@ -0,0 +1,78 @@ + + + + + Socket.IO chat + + + + +
    +
    + + +
    + + + + + + diff --git a/lib/MessageDb.js b/lib/MessageDb.js index f1b701ea..b4a4f401 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -59,6 +59,7 @@ var messageKey = function(from, to, ts) { }; MessageDb.prototype.addMessage = function(m, from, to, cb) { + console.log('adding message'); var key = messageKey(from, to); var value = m; this.db.put(key, value, cb); From fc5daaa988c8b6de6464518bd7a239abaa6e7d4c Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 1 Aug 2014 13:26:17 -0300 Subject: [PATCH 07/16] chat example working with SINs --- app/controllers/socket.js | 3 +- examples/bitcore-0.1.34.js | 392 +++++++++++++++++++++++++++++++++++++ examples/messages.html | 67 +++++-- 3 files changed, 445 insertions(+), 17 deletions(-) create mode 100644 examples/bitcore-0.1.34.js diff --git a/app/controllers/socket.js b/app/controllers/socket.js index 71e7be0c..41b7d363 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -63,7 +63,8 @@ module.exports.broadcastSyncInfo = function(historicSync) { module.exports.broadcastMessage = function(from, to, ts, message) { if (ios) { console.log('sending message '+to); - ios.sockets.in(to).emit(from, { + ios.sockets.in(to).emit('message', { + from: from, payload: message, ts: ts }); diff --git a/examples/bitcore-0.1.34.js b/examples/bitcore-0.1.34.js new file mode 100644 index 00000000..cdd8e2cb --- /dev/null +++ b/examples/bitcore-0.1.34.js @@ -0,0 +1,392 @@ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oi;i++)n[i]^=r[i];var o=t.fromUncompressedPubKey(e);o=t.multiply(o,n);var u=o.toUncompressedPubKey();return u},r.prototype.next=function(){var e=this.generatePubKey();return new r(this.chaincode,e)},r.fromMasterPublicKey=function(e){var n=e.substr(0,130),t=e.substr(130,e.length);return new r(t,n)},r.decodeSeed=function(t){for(var i=t.trim().split("\n"),o=[],c=0;c0){var i=new e(t);return i.fill(0),t==r.length?i:(n=n.toBuffer(),e.concat([i,n],t+n.length))}return n.toBuffer()}},s={encode:function(r){var t=new e(r.length+4),o=n(r);return r.copy(t),o.copy(t,r.length),l.encode(t)},decode:function(e){var r=l.decode(e);if(r.length<4)throw new Error("invalid input: too short");var t=r.slice(0,-4),o=r.slice(-4),i=n(t),c=i.slice(0,4);if(o.toString("hex")!==c.toString("hex"))throw new Error("checksum mismatch");return t}};exports.setBuffer=function(e){i=e},exports.base58=l,exports.base58Check=s,exports.encode=l.encode,exports.decode=l.decode}).call(this,require("buffer").Buffer); +},{"bignum":47,"buffer":76,"crypto":80}],"./lib/Block":[function(require,module,exports){ +module.exports=require('pJEQEB'); +},{}],"pJEQEB":[function(require,module,exports){ +(function(t){function e(t){"object"!=typeof t&&(t={}),this.hash=t.hash||null,this.prev_hash=t.prev_hash||r.NULL_HASH,this.merkle_root=t.merkle_root||r.NULL_HASH,this.timestamp=t.timestamp||0,this.bits=t.bits||0,this.nonce=t.nonce||0,this.version=t.version||0,this.height=t.height||0,this.size=t.size||0,this.active=t.active||!1,this.chainWork=t.chainWork||r.EMPTY_BUFFER,this.txs=t.txs||[]}var r=require("../util"),i=require("./Script"),o=require("bignum"),s=(require("binary"),require("step"),require("buffertools")),h=require("./Transaction"),n=h.In,a=h.Out,c=h.COINBASE_OP,u=require("../util/error").VerificationError,l={maxTimeOffset:7200,largestHash:new o("10000000000000000000000000000000000000000000000000000000000000000",16)};e.prototype.getHeader=function(){var e=new t(80),r=0;return e.writeUInt32LE(this.version,r),r+=4,this.prev_hash.copy(e,r),r+=32,this.merkle_root.copy(e,r),r+=32,e.writeUInt32LE(this.timestamp,r),r+=4,e.writeUInt32LE(this.bits,r),r+=4,e.writeUInt32LE(this.nonce,r),r+=4,e},e.prototype.parse=function(t,e){if(this.version=t.word32le(),this.prev_hash=t.buffer(32),this.merkle_root=t.buffer(32),this.timestamp=t.word32le(),this.bits=t.word32le(),this.nonce=t.word32le(),this.txs=[],this.size=0,!e)for(var r=t.varInt(),i=0;r>i;i++){var o=new h;o.parse(t),this.txs.push(o)}},e.prototype.calcHash=function(){var t=this.getHeader();return r.twoSha256(t)},e.prototype.checkHash=function(){return this.hash&&this.hash.length?0==s.compare(this.calcHash(),this.hash):!1},e.prototype.getHash=function(){return this.hash&&this.hash.length||(this.hash=this.calcHash()),this.hash},e.prototype.checkProofOfWork=function(){var t=r.decodeDiffBits(this.bits),e=s.reverse(this.hash);if(s.compare(e,t)>0)throw new u("Difficulty target not met");return!0},e.prototype.getWork=function(){var t=r.decodeDiffBits(this.bits,!0);return l.largestHash.div(t.add(1))},e.prototype.checkTimestamp=function(){var t=(new Date).getTime()/1e3;if(this.timestamp>t+l.maxTimeOffset)throw new u("Timestamp too far into the future");return!0},e.prototype.checkTransactions=function(t){if(!Array.isArray(t)||t.length<=0)throw new u("No transactions");if(!t[0].isCoinBase())throw new u("First tx must be coinbase");for(var e=1;e1;s=Math.floor((s+1)/2)){for(var n=0;s>n;n+=2){var a=Math.min(n+1,s-1),c=i[o+n],u=i[o+a];i.push(r.twoSha256(t.concat([c,u])))}o+=s}return i},e.prototype.calcMerkleRoot=function(t){var e=this.getMerkleTree(t);return e[e.length-1]},e.prototype.checkMerkleRoot=function(e){if(!this.merkle_root||!this.merkle_root.length)throw new u("No merkle root");if(0!==s.compare(this.calcMerkleRoot(e),new t(this.merkle_root)))throw new u("Merkle root incorrect");return!0},e.prototype.checkBlock=function(t){if(!this.checkHash())throw new u("Block hash invalid");if(this.checkProofOfWork(),this.checkTimestamp(),t&&(this.checkTransactions(t),!this.checkMerkleRoot(t)))throw new u("Merkle hash invalid");return!0},e.getBlockValue=function(t){var e=50*r.COIN;return e/=Math.pow(2,Math.floor(t/21e4)),e=Math.floor(e),e=new o(e)},e.prototype.getBlockValue=function(){return e.getBlockValue(this.height)},e.prototype.toString=function(){return""},e.prototype.createCoinbaseTx=function(t){var e=new h;return e.ins.push(new n({s:r.EMPTY_BUFFER,q:4294967295,o:c})),e.outs.push(new a({v:r.bigIntToValue(this.getBlockValue()),s:i.createPubKeyOut(t).getBuffer()})),e},e.prototype.solve=function(t,e){var i=this.getHeader(),o=r.decodeDiffBits(this.bits);t.solve(i,o,e)},e.prototype.getStandardizedObject=function(t){var e={hash:r.formatHashFull(this.getHash()),version:this.version,prev_block:r.formatHashFull(this.prev_hash),mrkl_root:r.formatHashFull(this.merkle_root),time:this.timestamp,bits:this.bits,nonce:this.nonce,height:this.height};if(t){var i=this.getMerkleTree(t).map(function(t){return r.formatHashFull(t)});e.mrkl_root=i[i.length-1],e.n_tx=t.length;var o=80;o+=r.getVarIntSize(t.length),t=t.map(function(t){return t=t.getStandardizedObject(),o+=t.size,t}),e.size=o,e.tx=t,e.mrkl_tree=i}else e.size=this.size;return e},module.exports=e}).call(this,require("buffer").Buffer); +},{"../util":161,"../util/error":160,"./Script":"hQ0t76","./Transaction":"LJhYtm","bignum":47,"binary":64,"buffer":76,"buffertools":"fugeBw","step":148}],"./lib/Bloom":[function(require,module,exports){ +module.exports=require('KifRG4'); +},{}],"KifRG4":[function(require,module,exports){ +function Bloom(){this.data="",this.hashFuncs=0}function ROTL32(t,n){return t<>32-n}function getBlockU32(t,n){var o=4*t,s=n[o+0]<<0|n[o+1]<<8|n[o+2]<<16|n[o+3]<<24;return s}function toInt(t){return~~t}function min(t,n){return n>t?t:n}var MAX_BLOOM_FILTER_SIZE=36e3,MAX_HASH_FUNCS=50,LN2SQUARED=.48045301391820144,LN2=.6931471805599453,bit_mask=[1,2,4,8,16,32,64,128];Bloom.prototype.hash=function(t,n){for(var o=t*(4294967295/(this.hashFuncs-1)),s=3432918353,a=461845907,h=n.length/4,i=-h;i;i++){var r=getBlockU32(i);r*=s,r=ROTLF32(r,15),r*=a,o^=r,o=ROTFL(o,13),o=5*o+3864292196}var e=n.slice(4*h),r=0;switch(3&n.length){case 3:r^=e[2]<<16;case 2:r^=e[1]<<8;case 1:r^=e[0],r*=s,r=ROTL32(r,15),r*=a,o^=r}return o^=n.length,o^=o>>16,o*=2246822507,o^=o>>13,o*=3266489909,o^=o>>16,o%(8*this.data.length)},Bloom.prototype.insert=function(t){for(var n=0;n>3]|=bit_mask[7&o]}},Bloom.prototype.contains=function(t){for(var n=0;n>3]&bit_mask[7&o]))return!1}return!0},Bloom.prototype.sizeOk=function(){return this.data.length<=MAX_BLOOM_FILTER_SIZE&&this.hashFuncs<=MAX_HASH_FUNCS},Bloom.prototype.init=function(t,n){var o=min(toInt(-1/LN2SQUARED*t*Math.log(n)),8*MAX_BLOOM_FILTER_SIZE)/8;this.data[o]=0,this.hashFuncs=min(toInt(8*this.data.length/t*LN2),MAX_HASH_FUNCS)},module.exports=Bloom; +},{}],"ez/meX":[function(require,module,exports){ +exports.intFromCompact=function(r){var t=(r>>>24&255)>>>0,n=(16777215&r)<<8*(t-3)>>>0;return n}; +},{}],"./lib/Deserialize":[function(require,module,exports){ +module.exports=require('ez/meX'); +},{}],"./lib/Electrum":[function(require,module,exports){ +module.exports=require('hdzBvq'); +},{}],"hdzBvq":[function(require,module,exports){ +(function(e){function r(r){this.mpk=new e(r,"hex")}var t=require("./Key"),u=require("./Point"),n=require("../util").twoSha256,i=(require("buffertools"),require("bignum"));r.prototype.getSequence=function(r,t){var u=r?1:0,o=e.concat([new e(t+":"+u+":","utf8"),this.mpk]);return i.fromBuffer(n(o))},r.prototype.generatePubKey=function(r,n){var o=i.fromBuffer(this.mpk.slice(0,32),{size:32}),f=i.fromBuffer(this.mpk.slice(32,64),{size:32}),c=new u(o,f),p=this.getSequence(n,r),s=new t;s.private=p.toBuffer(),s.regenerateSync(),s.compressed=!1;var a=u.fromUncompressedPubKey(s.public);pt=u.add(c,a);var m=pt.x.toBuffer({size:32}),b=pt.y.toBuffer({size:32}),h=new e([4]),l=new t;return l.compressed=!1,l.public=e.concat([h,m,b]),l.public},r.prototype.generateChangePubKey=function(e){return this.generatePubKey(e,!0)},module.exports=r}).call(this,require("buffer").Buffer); +},{"../util":161,"./Key":"ALJ4PS","./Point":"6tXgqr","bignum":47,"buffer":76,"buffertools":"fugeBw"}],"x1O6JW":[function(require,module,exports){ +(function(e){function i(e,i){if(e.lengthn;n++)t*=256,t+=e[n];return t}function t(e){return i(e,1)}function n(e){return i(e,4)}var r=require("./Base58").base58,s=require("../util"),h=require("./Key"),a=require("./Point"),c=require("./SecureRandom"),o=require("bignum"),d=require("../networks"),l=new o("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",16),u=(new o("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",16),function(i){if("undefined"==typeof i||"mainnet"==i||"livenet"==i?(i="livenet",this.version=d.livenet.hkeyPrivateVersion):"testnet"==i&&(this.version=d.testnet.hkeyPrivateVersion),"livenet"==i||"testnet"==i)return this.depth=0,this.parentFingerprint=new e([0,0,0,0]),this.childIndex=new e([0,0,0,0]),this.chainCode=c.getRandomBuffer(32),this.eckey=h.generateSync(),this.hasPrivateKey=!0,this.pubKeyHash=s.sha256ripe160(this.eckey.public),this.buildExtendedPublicKey(),void this.buildExtendedPrivateKey();if("string"==typeof i){var t=r.decode(i);if(82!=t.length)throw new Error("Not enough data, expected 82 and received "+t.length);var n=t.slice(78,82);i=t.slice(0,78);var a=s.sha256(s.sha256(i));if(a[0]!=n[0]||a[1]!=n[1]||a[2]!=n[2]||a[3]!=n[3])throw new Error("Invalid checksum")}void 0!==i&&null!==i&&this.initFromBytes(i)});u.seed=function(i,t){if(t||(t="livenet"),e.isBuffer(i)||(i=new e(i,"hex")),i.length<16)return!1;if(i.length>64)return!1;var n=s.sha512hmac(i,new e("Bitcoin seed")),r=new u(null);return r.depth=0,r.parentFingerprint=new e([0,0,0,0]),r.childIndex=new e([0,0,0,0]),r.chainCode=n.slice(32,64),r.version=d[t].hkeyPrivateVersion,r.eckey=new h,r.eckey.private=n.slice(0,32),r.eckey.regenerateSync(),r.hasPrivateKey=!0,r.pubKeyHash=s.sha256ripe160(r.eckey.public),r.buildExtendedPublicKey(),r.buildExtendedPrivateKey(),r},u.prototype.initFromBytes=function(e){if(78!=e.length)throw new Error("not enough data");this.version=n(e.slice(0,4)),this.depth=t(e.slice(4,5)),this.parentFingerprint=e.slice(5,9),this.childIndex=n(e.slice(9,13)),this.chainCode=e.slice(13,45);var i=e.slice(45,78),r=this.version==d.livenet.hkeyPrivateVersion||this.version==d.testnet.hkeyPrivateVersion,a=this.version==d.livenet.hkeyPublicVersion||this.version==d.testnet.hkeyPublicVersion;if(r&&0==i[0])this.eckey=new h,this.eckey.private=i.slice(1,33),this.eckey.compressed=!0,this.eckey.regenerateSync(),this.pubKeyHash=s.sha256ripe160(this.eckey.public),this.hasPrivateKey=!0;else{if(!a||2!=i[0]&&3!=i[0])throw new Error("Invalid key");this.eckey=new h,this.eckey.public=i,this.pubKeyHash=s.sha256ripe160(this.eckey.public),this.hasPrivateKey=!1}this.buildExtendedPublicKey(),this.buildExtendedPrivateKey()},u.prototype.buildExtendedPublicKey=function(){this.extendedPublicKey=new e([]);var i=null;switch(this.version){case d.livenet.hkeyPublicVersion:case d.livenet.hkeyPrivateVersion:i=d.livenet.hkeyPublicVersion;break;case d.testnet.hkeyPublicVersion:case d.testnet.hkeyPrivateVersion:i=d.testnet.hkeyPublicVersion;break;default:throw new Error("Unknown version")}this.extendedPublicKey=e.concat([new e([i>>24]),new e([i>>16&255]),new e([i>>8&255]),new e([255&i]),new e([this.depth]),this.parentFingerprint,new e([this.childIndex>>>24]),new e([this.childIndex>>>16&255]),new e([this.childIndex>>>8&255]),new e([255&this.childIndex]),this.chainCode,this.eckey.public])},u.prototype.extendedPublicKeyString=function(i){if(void 0===i||"base58"===i){var t=s.sha256(s.sha256(this.extendedPublicKey)),n=t.slice(0,4),h=e.concat([this.extendedPublicKey,n]);return r.encode(h)}if("hex"===i)return this.extendedPublicKey.toString("hex");throw new Error("bad format")},u.prototype.buildExtendedPrivateKey=function(){if(this.hasPrivateKey){this.extendedPrivateKey=new e([]);var i=this.version;this.extendedPrivateKey=e.concat([new e([i>>24]),new e([i>>16&255]),new e([i>>8&255]),new e([255&i]),new e([this.depth]),this.parentFingerprint,new e([this.childIndex>>>24]),new e([this.childIndex>>>16&255]),new e([this.childIndex>>>8&255]),new e([255&this.childIndex]),this.chainCode,new e([0]),this.eckey.private])}},u.prototype.extendedPrivateKeyString=function(i){if(void 0===i||"base58"===i){var t=s.sha256(s.sha256(this.extendedPrivateKey)),n=t.slice(0,4),h=e.concat([this.extendedPrivateKey,n]);return r.encode(h)}if("hex"===i)return this.extendedPrivateKey.toString("hex");throw new Error("bad format")},u.prototype.derive=function(e){var i=e.split("/");if("m"==e||"M"==e||"m'"==e||"M'"==e)return this;var t=this;for(var n in i){var r=i[n];if(0!=n){var s=r.length>1&&"'"==r[r.length-1],h=2147483647&parseInt(s?r.slice(0,r.length-1):r);s&&(h+=2147483648),t=t.deriveChild(h)}else if("m"!=r)throw new Error("invalid path")}return t},u.prototype.deriveChild=function(i){var t=[];t.push(i>>24&255),t.push(i>>16&255),t.push(i>>8&255),t.push(255&i),t=new e(t);var n=0!=(2147483648&i),r=this.version==d.livenet.hkeyPrivateVersion||this.version==d.testnet.hkeyPrivateVersion;if(n&&(!this.hasPrivateKey||!r))throw new Error("Cannot do private key derivation without private key");var c=null;if(this.hasPrivateKey){var y=null;y=e.concat(n?[new e([0]),this.eckey.private,t]:[this.eckey.public,t]);var v=s.sha512hmac(y,this.chainCode),p=o.fromBuffer(v.slice(0,32),{size:32}),w=v.slice(32,64),b=o.fromBuffer(this.eckey.private,{size:32}),f=p.add(b).mod(l);c=new u(null),c.chainCode=w,c.eckey=new h,c.eckey.private=f.toBuffer({size:32}),c.eckey.regenerateSync(),c.hasPrivateKey=!0}else{var y=e.concat([this.eckey.public,t]),v=s.sha512hmac(y,this.chainCode),p=v.slice(0,32),w=v.slice(32,64),k=new h;k.private=p,k.regenerateSync(),k.compressed=!1;var P=a.fromUncompressedPubKey(k.public),F=new h;F.public=this.eckey.public,F.compressed=!1;var x=a.fromUncompressedPubKey(F.public),K=a.add(P,x).toUncompressedPubKey();c=new u(null),c.chainCode=new e(w);var g=new h;g.public=K,g.compressed=!0,c.eckey=g,c.hasPrivateKey=!1}return c.childIndex=i,c.parentFingerprint=this.pubKeyHash.slice(0,4),c.version=this.version,c.depth=this.depth+1,c.eckey.compressed=!0,c.pubKeyHash=s.sha256ripe160(c.eckey.public),c.buildExtendedPublicKey(),c.buildExtendedPrivateKey(),c},module.exports=u}).call(this,require("buffer").Buffer); +},{"../networks":"ULNIu2","../util":161,"./Base58":"6VqyzY","./Key":"ALJ4PS","./Point":"6tXgqr","./SecureRandom":"p4SiC2","bignum":47,"buffer":76}],"./lib/HierarchicalKey":[function(require,module,exports){ +module.exports=require('x1O6JW'); +},{}],"CBDCgz":[function(require,module,exports){ +(function(e){"use strict";var n=require("../util"),i=require("./Key"),r=function(){};r.sign=function(e,n){var i=r.magicHash(e),t=n.signSync(i);return t},r.verifyWithPubKey=function(e,n,t){var u=r.magicHash(n),a=new i;return 65==e.length&&(a.compressed=!1),a.public=e,a.verifySignatureSync(u,t)},r.magicBytes=new e("Bitcoin Signed Message:\n"),r.magicHash=function(i){var t=r.magicBytes,u=n.varIntBuf(t.length),a=new e(i),c=n.varIntBuf(a.length),s=e.concat([u,t,c,a]),f=n.twoSha256(s);return f},module.exports=r}).call(this,require("buffer").Buffer); +},{"../util":161,"./Key":"ALJ4PS","buffer":76}],"./lib/Message":[function(require,module,exports){ +module.exports=require('CBDCgz'); +},{}],"Zm7/h9":[function(require,module,exports){ +function Opcode(O){this.code=O}Opcode.prototype.toString=function(){return Opcode.reverseMap[this.code]},Opcode.map={OP_FALSE:0,OP_0:0,OP_PUSHDATA1:76,OP_PUSHDATA2:77,OP_PUSHDATA4:78,OP_1NEGATE:79,OP_RESERVED:80,OP_TRUE:81,OP_1:81,OP_2:82,OP_3:83,OP_4:84,OP_5:85,OP_6:86,OP_7:87,OP_8:88,OP_9:89,OP_10:90,OP_11:91,OP_12:92,OP_13:93,OP_14:94,OP_15:95,OP_16:96,OP_NOP:97,OP_VER:98,OP_IF:99,OP_NOTIF:100,OP_VERIF:101,OP_VERNOTIF:102,OP_ELSE:103,OP_ENDIF:104,OP_VERIFY:105,OP_RETURN:106,OP_TOALTSTACK:107,OP_FROMALTSTACK:108,OP_2DROP:109,OP_2DUP:110,OP_3DUP:111,OP_2OVER:112,OP_2ROT:113,OP_2SWAP:114,OP_IFDUP:115,OP_DEPTH:116,OP_DROP:117,OP_DUP:118,OP_NIP:119,OP_OVER:120,OP_PICK:121,OP_ROLL:122,OP_ROT:123,OP_SWAP:124,OP_TUCK:125,OP_CAT:126,OP_SUBSTR:127,OP_LEFT:128,OP_RIGHT:129,OP_SIZE:130,OP_INVERT:131,OP_AND:132,OP_OR:133,OP_XOR:134,OP_EQUAL:135,OP_EQUALVERIFY:136,OP_RESERVED1:137,OP_RESERVED2:138,OP_1ADD:139,OP_1SUB:140,OP_2MUL:141,OP_2DIV:142,OP_NEGATE:143,OP_ABS:144,OP_NOT:145,OP_0NOTEQUAL:146,OP_ADD:147,OP_SUB:148,OP_MUL:149,OP_DIV:150,OP_MOD:151,OP_LSHIFT:152,OP_RSHIFT:153,OP_BOOLAND:154,OP_BOOLOR:155,OP_NUMEQUAL:156,OP_NUMEQUALVERIFY:157,OP_NUMNOTEQUAL:158,OP_LESSTHAN:159,OP_GREATERTHAN:160,OP_LESSTHANOREQUAL:161,OP_GREATERTHANOREQUAL:162,OP_MIN:163,OP_MAX:164,OP_WITHIN:165,OP_RIPEMD160:166,OP_SHA1:167,OP_SHA256:168,OP_HASH160:169,OP_HASH256:170,OP_CODESEPARATOR:171,OP_CHECKSIG:172,OP_CHECKSIGVERIFY:173,OP_CHECKMULTISIG:174,OP_CHECKMULTISIGVERIFY:175,OP_NOP1:176,OP_NOP2:177,OP_NOP3:178,OP_NOP4:179,OP_NOP5:180,OP_NOP6:181,OP_NOP7:182,OP_NOP8:183,OP_NOP9:184,OP_NOP10:185,OP_PUBKEYHASH:253,OP_PUBKEY:254,OP_INVALIDOPCODE:255},Opcode.reverseMap=[];for(var k in Opcode.map)Opcode.map.hasOwnProperty(k)&&(Opcode.reverseMap[Opcode.map[k]]=k.substr(3));Opcode.asList=function(){var O=[];for(var P in Opcode.map)Opcode.map.hasOwnProperty(P)&&O.push(P);return O},module.exports=Opcode; +},{}],"./lib/Opcode":[function(require,module,exports){ +module.exports=require('Zm7/h9'); +},{}],"izTl9z":[function(require,module,exports){ +(function(t){function i(t,e,r){i.super_.call(this,t,e),void 0!==r&&this.compressed(r)}var e=require("../util/VersionedData"),r=require("../util/EncodedData"),n=require("../networks"),a=require("util");a.inherits(i,e),r.applyEncodingsTo(i),i.prototype.validate=function(){if(this.doAsBinary(function(){if(i.super_.prototype.validate.call(this),this.data.length<32||this.data.length>33&&!this.compressed()||34==this.data.length&&1!=this.data[33]||this.data.length>34)throw new Error("invalid data length")}),"undefined"==typeof this.network())throw new Error("invalid network")},i.prototype.payload=function(t){if(t)return this.doAsBinary(function(){t.copy(this.data,1)}),t;var i=this.as("binary");return 34==i.length?i.slice(1,33):33==i.length?i.slice(1):void 0},i.prototype.compressed=function(i){if(void 0===i){var e=34,r=this.as("binary");if(r.length==e&&1==r[e-1])return!0;if(r.length==e-1)return!1;throw new Error("invalid private key")}this.doAsBinary(function(){var e=34;if(i){var r=new t(e);this.data.copy(r),this.data=r,this.data[e-1]=1}else this.data=this.data.slice(0,e-1)})},i.prototype.network=function(){var t,i=this.version(),e=n.livenet,r=n.testnet;return i===e.privKeyVersion?t=e:i===r.privKeyVersion&&(t=r),t},module.exports=i}).call(this,require("buffer").Buffer); +},{"../networks":"ULNIu2","../util/EncodedData":"eLfUFE","../util/VersionedData":"QLzNQg","buffer":76,"util":109}],"./lib/PrivateKey":[function(require,module,exports){ +module.exports=require('izTl9z'); +},{}],"./lib/RpcClient":[function(require,module,exports){ +module.exports=require('7siE1N'); +},{}],"7siE1N":[function(require,module,exports){ +(function(t){function e(t){t=t||{},this.host=t.host||"127.0.0.1",this.port=t.port||8332,this.user=t.user||"user",this.pass=t.pass||"pass",this.protocol="http"==t.protocol?n:o,this.batchedCalls=null,this.disableAgent=t.disableAgent||!1}function r(t,e,r){function s(t,e){return function(){var s=arguments.length-1;if(this.batchedCalls)var s=arguments.length;for(var n=0;s>n;n++)e[n]&&(arguments[n]=e[n](arguments[n]));this.batchedCalls?this.batchedCalls.push({jsonrpc:"2.0",method:t,params:l(arguments)}):r.call(this,{method:t,params:l(arguments,0,arguments.length-1)},arguments[arguments.length-1])}}var n={str:function(t){return t.toString()},"int":function(t){return parseFloat(t)},"float":function(t){return parseFloat(t)},bool:function(t){return t===!0||"1"==t||"true"==t||"true"==t.toString().toLowerCase()}};for(var o in e)if(e.hasOwnProperty(o)){for(var i=e[o].split(" "),a=0;a=h.map.OP_1&&t<=h.map.OP_16}function n(t){return t=t?2:65535>=t?3:5}function s(e){var r=void 0;return e=e?(r=new t(2),r.writeUInt8(h.map.OP_PUSHDATA1,0),r.writeUInt8(e,1)):65535>=e?(r=new t(3),r.writeUInt8(h.map.OP_PUSHDATA2,0),r.writeUInt16LE(e,1)):(r=new t(5),r.writeUInt8(h.map.OP_PUSHDATA4,0),r.writeUInt32LE(e,1)),r}var u=(require("../config"),require("../util/log")),h=require("./Opcode"),o=require("buffertools"),f=require("../util/util"),c=require("../util/BinaryParser"),p=require("bufferput"),a=0,l=1,g=2,k=3,y=4,w=["unknown","pubkey","pubkeyhash","multisig","scripthash"];e.TX_UNKNOWN=a,e.TX_PUBKEY=l,e.TX_PUBKEYHASH=g,e.TX_MULTISIG=k,e.TX_SCRIPTHASH=y,e.prototype.parse=function(){this.chunks=[];for(var t=new c(this.buffer);!t.eof();){var e,r,n=t.word8();n>0&&nh.map.OP_16)return!1}return!0},e.prototype.isP2SH=function(){return 3==this.chunks.length&&this.chunks[0]==h.map.OP_HASH160&&t.isBuffer(this.chunks[1])&&20==this.chunks[1].length&&this.chunks[2]==h.map.OP_EQUAL},e.prototype.isPubkey=function(){return 2==this.chunks.length&&t.isBuffer(this.chunks[0])&&this.chunks[1]==h.map.OP_CHECKSIG},e.prototype.isPubkeyHash=function(){return 5==this.chunks.length&&this.chunks[0]==h.map.OP_DUP&&this.chunks[1]==h.map.OP_HASH160&&t.isBuffer(this.chunks[2])&&20==this.chunks[2].length&&this.chunks[3]==h.map.OP_EQUALVERIFY&&this.chunks[4]==h.map.OP_CHECKSIG},e.prototype.isMultiSig=function(){return this.chunks.length>3&&r(this.chunks[0])&&this.chunks.slice(1,this.chunks.length-2).every(function(e){return t.isBuffer(e)})&&r(this.chunks[this.chunks.length-2])&&this.chunks[this.chunks.length-1]==h.map.OP_CHECKMULTISIG},e.prototype.isPubkeyHashScript=function(){return 2==this.chunks.length&&t.isBuffer(this.chunks[0])&&t.isBuffer(this.chunks[1])},e.prototype.isP2shScriptSig=function(){if(!r(this.chunks[0])||0!==this.chunks[0])return!1;var t=new e(this.chunks[this.chunks.length-1]),n=t.classify();return n!==a},e.prototype.isMultiSigScriptSig=function(){return r(this.chunks[0])&&0===this.chunks[0]?!this.isP2shScriptSig():!1},e.prototype.countSignatures=function(){var t=0,e=this.chunks.length;return t=this.isMultiSigScriptSig()?e-1:this.isP2shScriptSig()?e-2:this.isPubkeyHashScript()?1:0},e.prototype.getSignatures=function(){ret=[];var t=this.chunks.length;if(this.isMultiSigScriptSig())for(var e=1;t>e;e++)ret.push(this.chunks[e]);else if(this.isP2shScriptSig())for(var e=1;t-1>e;e++)ret.push(this.chunks[e]);else this.isPubkeyHashScript()&&ret.push(this.chunks[0]);return ret},e.prototype.getHashType=function(){for(var t=this.getSignatures(),e=null,r=0;rs;s++){var u=this.chunks[s];if(s>0&&(n+=" "),n+=t.isBuffer(u)?"0x"+f.formatBuffer(u,e?null:0):h.reverseMap[u],r&&s>r){n+=" ...";break}}return n},e.prototype.toString=function(t,e){var r=" + From 93a227316e57fadce16581238c46e6bda54665e2 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 1 Aug 2014 19:00:52 -0300 Subject: [PATCH 08/16] working towards verifying message sigs --- app/controllers/socket.js | 2 +- examples/bitcore-0.1.34.js | 392 ------------------------------------- examples/bitcore.js | 1 + examples/messages.html | 29 ++- lib/MessageDb.js | 16 +- 5 files changed, 30 insertions(+), 410 deletions(-) delete mode 100644 examples/bitcore-0.1.34.js create mode 120000 examples/bitcore.js diff --git a/app/controllers/socket.js b/app/controllers/socket.js index 41b7d363..a98f3503 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -13,7 +13,7 @@ module.exports.init = function(io_ext) { socket.join(topic); }); socket.on('message', function(m) { - mdb.addMessage(m.payload, m.from, m.to, function(err) { + mdb.addMessage(m, m.from, m.to, function(err) { if (err) throw err; // TODO: handle }); }); diff --git a/examples/bitcore-0.1.34.js b/examples/bitcore-0.1.34.js deleted file mode 100644 index cdd8e2cb..00000000 --- a/examples/bitcore-0.1.34.js +++ /dev/null @@ -1,392 +0,0 @@ -require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oi;i++)n[i]^=r[i];var o=t.fromUncompressedPubKey(e);o=t.multiply(o,n);var u=o.toUncompressedPubKey();return u},r.prototype.next=function(){var e=this.generatePubKey();return new r(this.chaincode,e)},r.fromMasterPublicKey=function(e){var n=e.substr(0,130),t=e.substr(130,e.length);return new r(t,n)},r.decodeSeed=function(t){for(var i=t.trim().split("\n"),o=[],c=0;c0){var i=new e(t);return i.fill(0),t==r.length?i:(n=n.toBuffer(),e.concat([i,n],t+n.length))}return n.toBuffer()}},s={encode:function(r){var t=new e(r.length+4),o=n(r);return r.copy(t),o.copy(t,r.length),l.encode(t)},decode:function(e){var r=l.decode(e);if(r.length<4)throw new Error("invalid input: too short");var t=r.slice(0,-4),o=r.slice(-4),i=n(t),c=i.slice(0,4);if(o.toString("hex")!==c.toString("hex"))throw new Error("checksum mismatch");return t}};exports.setBuffer=function(e){i=e},exports.base58=l,exports.base58Check=s,exports.encode=l.encode,exports.decode=l.decode}).call(this,require("buffer").Buffer); -},{"bignum":47,"buffer":76,"crypto":80}],"./lib/Block":[function(require,module,exports){ -module.exports=require('pJEQEB'); -},{}],"pJEQEB":[function(require,module,exports){ -(function(t){function e(t){"object"!=typeof t&&(t={}),this.hash=t.hash||null,this.prev_hash=t.prev_hash||r.NULL_HASH,this.merkle_root=t.merkle_root||r.NULL_HASH,this.timestamp=t.timestamp||0,this.bits=t.bits||0,this.nonce=t.nonce||0,this.version=t.version||0,this.height=t.height||0,this.size=t.size||0,this.active=t.active||!1,this.chainWork=t.chainWork||r.EMPTY_BUFFER,this.txs=t.txs||[]}var r=require("../util"),i=require("./Script"),o=require("bignum"),s=(require("binary"),require("step"),require("buffertools")),h=require("./Transaction"),n=h.In,a=h.Out,c=h.COINBASE_OP,u=require("../util/error").VerificationError,l={maxTimeOffset:7200,largestHash:new o("10000000000000000000000000000000000000000000000000000000000000000",16)};e.prototype.getHeader=function(){var e=new t(80),r=0;return e.writeUInt32LE(this.version,r),r+=4,this.prev_hash.copy(e,r),r+=32,this.merkle_root.copy(e,r),r+=32,e.writeUInt32LE(this.timestamp,r),r+=4,e.writeUInt32LE(this.bits,r),r+=4,e.writeUInt32LE(this.nonce,r),r+=4,e},e.prototype.parse=function(t,e){if(this.version=t.word32le(),this.prev_hash=t.buffer(32),this.merkle_root=t.buffer(32),this.timestamp=t.word32le(),this.bits=t.word32le(),this.nonce=t.word32le(),this.txs=[],this.size=0,!e)for(var r=t.varInt(),i=0;r>i;i++){var o=new h;o.parse(t),this.txs.push(o)}},e.prototype.calcHash=function(){var t=this.getHeader();return r.twoSha256(t)},e.prototype.checkHash=function(){return this.hash&&this.hash.length?0==s.compare(this.calcHash(),this.hash):!1},e.prototype.getHash=function(){return this.hash&&this.hash.length||(this.hash=this.calcHash()),this.hash},e.prototype.checkProofOfWork=function(){var t=r.decodeDiffBits(this.bits),e=s.reverse(this.hash);if(s.compare(e,t)>0)throw new u("Difficulty target not met");return!0},e.prototype.getWork=function(){var t=r.decodeDiffBits(this.bits,!0);return l.largestHash.div(t.add(1))},e.prototype.checkTimestamp=function(){var t=(new Date).getTime()/1e3;if(this.timestamp>t+l.maxTimeOffset)throw new u("Timestamp too far into the future");return!0},e.prototype.checkTransactions=function(t){if(!Array.isArray(t)||t.length<=0)throw new u("No transactions");if(!t[0].isCoinBase())throw new u("First tx must be coinbase");for(var e=1;e1;s=Math.floor((s+1)/2)){for(var n=0;s>n;n+=2){var a=Math.min(n+1,s-1),c=i[o+n],u=i[o+a];i.push(r.twoSha256(t.concat([c,u])))}o+=s}return i},e.prototype.calcMerkleRoot=function(t){var e=this.getMerkleTree(t);return e[e.length-1]},e.prototype.checkMerkleRoot=function(e){if(!this.merkle_root||!this.merkle_root.length)throw new u("No merkle root");if(0!==s.compare(this.calcMerkleRoot(e),new t(this.merkle_root)))throw new u("Merkle root incorrect");return!0},e.prototype.checkBlock=function(t){if(!this.checkHash())throw new u("Block hash invalid");if(this.checkProofOfWork(),this.checkTimestamp(),t&&(this.checkTransactions(t),!this.checkMerkleRoot(t)))throw new u("Merkle hash invalid");return!0},e.getBlockValue=function(t){var e=50*r.COIN;return e/=Math.pow(2,Math.floor(t/21e4)),e=Math.floor(e),e=new o(e)},e.prototype.getBlockValue=function(){return e.getBlockValue(this.height)},e.prototype.toString=function(){return""},e.prototype.createCoinbaseTx=function(t){var e=new h;return e.ins.push(new n({s:r.EMPTY_BUFFER,q:4294967295,o:c})),e.outs.push(new a({v:r.bigIntToValue(this.getBlockValue()),s:i.createPubKeyOut(t).getBuffer()})),e},e.prototype.solve=function(t,e){var i=this.getHeader(),o=r.decodeDiffBits(this.bits);t.solve(i,o,e)},e.prototype.getStandardizedObject=function(t){var e={hash:r.formatHashFull(this.getHash()),version:this.version,prev_block:r.formatHashFull(this.prev_hash),mrkl_root:r.formatHashFull(this.merkle_root),time:this.timestamp,bits:this.bits,nonce:this.nonce,height:this.height};if(t){var i=this.getMerkleTree(t).map(function(t){return r.formatHashFull(t)});e.mrkl_root=i[i.length-1],e.n_tx=t.length;var o=80;o+=r.getVarIntSize(t.length),t=t.map(function(t){return t=t.getStandardizedObject(),o+=t.size,t}),e.size=o,e.tx=t,e.mrkl_tree=i}else e.size=this.size;return e},module.exports=e}).call(this,require("buffer").Buffer); -},{"../util":161,"../util/error":160,"./Script":"hQ0t76","./Transaction":"LJhYtm","bignum":47,"binary":64,"buffer":76,"buffertools":"fugeBw","step":148}],"./lib/Bloom":[function(require,module,exports){ -module.exports=require('KifRG4'); -},{}],"KifRG4":[function(require,module,exports){ -function Bloom(){this.data="",this.hashFuncs=0}function ROTL32(t,n){return t<>32-n}function getBlockU32(t,n){var o=4*t,s=n[o+0]<<0|n[o+1]<<8|n[o+2]<<16|n[o+3]<<24;return s}function toInt(t){return~~t}function min(t,n){return n>t?t:n}var MAX_BLOOM_FILTER_SIZE=36e3,MAX_HASH_FUNCS=50,LN2SQUARED=.48045301391820144,LN2=.6931471805599453,bit_mask=[1,2,4,8,16,32,64,128];Bloom.prototype.hash=function(t,n){for(var o=t*(4294967295/(this.hashFuncs-1)),s=3432918353,a=461845907,h=n.length/4,i=-h;i;i++){var r=getBlockU32(i);r*=s,r=ROTLF32(r,15),r*=a,o^=r,o=ROTFL(o,13),o=5*o+3864292196}var e=n.slice(4*h),r=0;switch(3&n.length){case 3:r^=e[2]<<16;case 2:r^=e[1]<<8;case 1:r^=e[0],r*=s,r=ROTL32(r,15),r*=a,o^=r}return o^=n.length,o^=o>>16,o*=2246822507,o^=o>>13,o*=3266489909,o^=o>>16,o%(8*this.data.length)},Bloom.prototype.insert=function(t){for(var n=0;n>3]|=bit_mask[7&o]}},Bloom.prototype.contains=function(t){for(var n=0;n>3]&bit_mask[7&o]))return!1}return!0},Bloom.prototype.sizeOk=function(){return this.data.length<=MAX_BLOOM_FILTER_SIZE&&this.hashFuncs<=MAX_HASH_FUNCS},Bloom.prototype.init=function(t,n){var o=min(toInt(-1/LN2SQUARED*t*Math.log(n)),8*MAX_BLOOM_FILTER_SIZE)/8;this.data[o]=0,this.hashFuncs=min(toInt(8*this.data.length/t*LN2),MAX_HASH_FUNCS)},module.exports=Bloom; -},{}],"ez/meX":[function(require,module,exports){ -exports.intFromCompact=function(r){var t=(r>>>24&255)>>>0,n=(16777215&r)<<8*(t-3)>>>0;return n}; -},{}],"./lib/Deserialize":[function(require,module,exports){ -module.exports=require('ez/meX'); -},{}],"./lib/Electrum":[function(require,module,exports){ -module.exports=require('hdzBvq'); -},{}],"hdzBvq":[function(require,module,exports){ -(function(e){function r(r){this.mpk=new e(r,"hex")}var t=require("./Key"),u=require("./Point"),n=require("../util").twoSha256,i=(require("buffertools"),require("bignum"));r.prototype.getSequence=function(r,t){var u=r?1:0,o=e.concat([new e(t+":"+u+":","utf8"),this.mpk]);return i.fromBuffer(n(o))},r.prototype.generatePubKey=function(r,n){var o=i.fromBuffer(this.mpk.slice(0,32),{size:32}),f=i.fromBuffer(this.mpk.slice(32,64),{size:32}),c=new u(o,f),p=this.getSequence(n,r),s=new t;s.private=p.toBuffer(),s.regenerateSync(),s.compressed=!1;var a=u.fromUncompressedPubKey(s.public);pt=u.add(c,a);var m=pt.x.toBuffer({size:32}),b=pt.y.toBuffer({size:32}),h=new e([4]),l=new t;return l.compressed=!1,l.public=e.concat([h,m,b]),l.public},r.prototype.generateChangePubKey=function(e){return this.generatePubKey(e,!0)},module.exports=r}).call(this,require("buffer").Buffer); -},{"../util":161,"./Key":"ALJ4PS","./Point":"6tXgqr","bignum":47,"buffer":76,"buffertools":"fugeBw"}],"x1O6JW":[function(require,module,exports){ -(function(e){function i(e,i){if(e.lengthn;n++)t*=256,t+=e[n];return t}function t(e){return i(e,1)}function n(e){return i(e,4)}var r=require("./Base58").base58,s=require("../util"),h=require("./Key"),a=require("./Point"),c=require("./SecureRandom"),o=require("bignum"),d=require("../networks"),l=new o("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",16),u=(new o("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",16),function(i){if("undefined"==typeof i||"mainnet"==i||"livenet"==i?(i="livenet",this.version=d.livenet.hkeyPrivateVersion):"testnet"==i&&(this.version=d.testnet.hkeyPrivateVersion),"livenet"==i||"testnet"==i)return this.depth=0,this.parentFingerprint=new e([0,0,0,0]),this.childIndex=new e([0,0,0,0]),this.chainCode=c.getRandomBuffer(32),this.eckey=h.generateSync(),this.hasPrivateKey=!0,this.pubKeyHash=s.sha256ripe160(this.eckey.public),this.buildExtendedPublicKey(),void this.buildExtendedPrivateKey();if("string"==typeof i){var t=r.decode(i);if(82!=t.length)throw new Error("Not enough data, expected 82 and received "+t.length);var n=t.slice(78,82);i=t.slice(0,78);var a=s.sha256(s.sha256(i));if(a[0]!=n[0]||a[1]!=n[1]||a[2]!=n[2]||a[3]!=n[3])throw new Error("Invalid checksum")}void 0!==i&&null!==i&&this.initFromBytes(i)});u.seed=function(i,t){if(t||(t="livenet"),e.isBuffer(i)||(i=new e(i,"hex")),i.length<16)return!1;if(i.length>64)return!1;var n=s.sha512hmac(i,new e("Bitcoin seed")),r=new u(null);return r.depth=0,r.parentFingerprint=new e([0,0,0,0]),r.childIndex=new e([0,0,0,0]),r.chainCode=n.slice(32,64),r.version=d[t].hkeyPrivateVersion,r.eckey=new h,r.eckey.private=n.slice(0,32),r.eckey.regenerateSync(),r.hasPrivateKey=!0,r.pubKeyHash=s.sha256ripe160(r.eckey.public),r.buildExtendedPublicKey(),r.buildExtendedPrivateKey(),r},u.prototype.initFromBytes=function(e){if(78!=e.length)throw new Error("not enough data");this.version=n(e.slice(0,4)),this.depth=t(e.slice(4,5)),this.parentFingerprint=e.slice(5,9),this.childIndex=n(e.slice(9,13)),this.chainCode=e.slice(13,45);var i=e.slice(45,78),r=this.version==d.livenet.hkeyPrivateVersion||this.version==d.testnet.hkeyPrivateVersion,a=this.version==d.livenet.hkeyPublicVersion||this.version==d.testnet.hkeyPublicVersion;if(r&&0==i[0])this.eckey=new h,this.eckey.private=i.slice(1,33),this.eckey.compressed=!0,this.eckey.regenerateSync(),this.pubKeyHash=s.sha256ripe160(this.eckey.public),this.hasPrivateKey=!0;else{if(!a||2!=i[0]&&3!=i[0])throw new Error("Invalid key");this.eckey=new h,this.eckey.public=i,this.pubKeyHash=s.sha256ripe160(this.eckey.public),this.hasPrivateKey=!1}this.buildExtendedPublicKey(),this.buildExtendedPrivateKey()},u.prototype.buildExtendedPublicKey=function(){this.extendedPublicKey=new e([]);var i=null;switch(this.version){case d.livenet.hkeyPublicVersion:case d.livenet.hkeyPrivateVersion:i=d.livenet.hkeyPublicVersion;break;case d.testnet.hkeyPublicVersion:case d.testnet.hkeyPrivateVersion:i=d.testnet.hkeyPublicVersion;break;default:throw new Error("Unknown version")}this.extendedPublicKey=e.concat([new e([i>>24]),new e([i>>16&255]),new e([i>>8&255]),new e([255&i]),new e([this.depth]),this.parentFingerprint,new e([this.childIndex>>>24]),new e([this.childIndex>>>16&255]),new e([this.childIndex>>>8&255]),new e([255&this.childIndex]),this.chainCode,this.eckey.public])},u.prototype.extendedPublicKeyString=function(i){if(void 0===i||"base58"===i){var t=s.sha256(s.sha256(this.extendedPublicKey)),n=t.slice(0,4),h=e.concat([this.extendedPublicKey,n]);return r.encode(h)}if("hex"===i)return this.extendedPublicKey.toString("hex");throw new Error("bad format")},u.prototype.buildExtendedPrivateKey=function(){if(this.hasPrivateKey){this.extendedPrivateKey=new e([]);var i=this.version;this.extendedPrivateKey=e.concat([new e([i>>24]),new e([i>>16&255]),new e([i>>8&255]),new e([255&i]),new e([this.depth]),this.parentFingerprint,new e([this.childIndex>>>24]),new e([this.childIndex>>>16&255]),new e([this.childIndex>>>8&255]),new e([255&this.childIndex]),this.chainCode,new e([0]),this.eckey.private])}},u.prototype.extendedPrivateKeyString=function(i){if(void 0===i||"base58"===i){var t=s.sha256(s.sha256(this.extendedPrivateKey)),n=t.slice(0,4),h=e.concat([this.extendedPrivateKey,n]);return r.encode(h)}if("hex"===i)return this.extendedPrivateKey.toString("hex");throw new Error("bad format")},u.prototype.derive=function(e){var i=e.split("/");if("m"==e||"M"==e||"m'"==e||"M'"==e)return this;var t=this;for(var n in i){var r=i[n];if(0!=n){var s=r.length>1&&"'"==r[r.length-1],h=2147483647&parseInt(s?r.slice(0,r.length-1):r);s&&(h+=2147483648),t=t.deriveChild(h)}else if("m"!=r)throw new Error("invalid path")}return t},u.prototype.deriveChild=function(i){var t=[];t.push(i>>24&255),t.push(i>>16&255),t.push(i>>8&255),t.push(255&i),t=new e(t);var n=0!=(2147483648&i),r=this.version==d.livenet.hkeyPrivateVersion||this.version==d.testnet.hkeyPrivateVersion;if(n&&(!this.hasPrivateKey||!r))throw new Error("Cannot do private key derivation without private key");var c=null;if(this.hasPrivateKey){var y=null;y=e.concat(n?[new e([0]),this.eckey.private,t]:[this.eckey.public,t]);var v=s.sha512hmac(y,this.chainCode),p=o.fromBuffer(v.slice(0,32),{size:32}),w=v.slice(32,64),b=o.fromBuffer(this.eckey.private,{size:32}),f=p.add(b).mod(l);c=new u(null),c.chainCode=w,c.eckey=new h,c.eckey.private=f.toBuffer({size:32}),c.eckey.regenerateSync(),c.hasPrivateKey=!0}else{var y=e.concat([this.eckey.public,t]),v=s.sha512hmac(y,this.chainCode),p=v.slice(0,32),w=v.slice(32,64),k=new h;k.private=p,k.regenerateSync(),k.compressed=!1;var P=a.fromUncompressedPubKey(k.public),F=new h;F.public=this.eckey.public,F.compressed=!1;var x=a.fromUncompressedPubKey(F.public),K=a.add(P,x).toUncompressedPubKey();c=new u(null),c.chainCode=new e(w);var g=new h;g.public=K,g.compressed=!0,c.eckey=g,c.hasPrivateKey=!1}return c.childIndex=i,c.parentFingerprint=this.pubKeyHash.slice(0,4),c.version=this.version,c.depth=this.depth+1,c.eckey.compressed=!0,c.pubKeyHash=s.sha256ripe160(c.eckey.public),c.buildExtendedPublicKey(),c.buildExtendedPrivateKey(),c},module.exports=u}).call(this,require("buffer").Buffer); -},{"../networks":"ULNIu2","../util":161,"./Base58":"6VqyzY","./Key":"ALJ4PS","./Point":"6tXgqr","./SecureRandom":"p4SiC2","bignum":47,"buffer":76}],"./lib/HierarchicalKey":[function(require,module,exports){ -module.exports=require('x1O6JW'); -},{}],"CBDCgz":[function(require,module,exports){ -(function(e){"use strict";var n=require("../util"),i=require("./Key"),r=function(){};r.sign=function(e,n){var i=r.magicHash(e),t=n.signSync(i);return t},r.verifyWithPubKey=function(e,n,t){var u=r.magicHash(n),a=new i;return 65==e.length&&(a.compressed=!1),a.public=e,a.verifySignatureSync(u,t)},r.magicBytes=new e("Bitcoin Signed Message:\n"),r.magicHash=function(i){var t=r.magicBytes,u=n.varIntBuf(t.length),a=new e(i),c=n.varIntBuf(a.length),s=e.concat([u,t,c,a]),f=n.twoSha256(s);return f},module.exports=r}).call(this,require("buffer").Buffer); -},{"../util":161,"./Key":"ALJ4PS","buffer":76}],"./lib/Message":[function(require,module,exports){ -module.exports=require('CBDCgz'); -},{}],"Zm7/h9":[function(require,module,exports){ -function Opcode(O){this.code=O}Opcode.prototype.toString=function(){return Opcode.reverseMap[this.code]},Opcode.map={OP_FALSE:0,OP_0:0,OP_PUSHDATA1:76,OP_PUSHDATA2:77,OP_PUSHDATA4:78,OP_1NEGATE:79,OP_RESERVED:80,OP_TRUE:81,OP_1:81,OP_2:82,OP_3:83,OP_4:84,OP_5:85,OP_6:86,OP_7:87,OP_8:88,OP_9:89,OP_10:90,OP_11:91,OP_12:92,OP_13:93,OP_14:94,OP_15:95,OP_16:96,OP_NOP:97,OP_VER:98,OP_IF:99,OP_NOTIF:100,OP_VERIF:101,OP_VERNOTIF:102,OP_ELSE:103,OP_ENDIF:104,OP_VERIFY:105,OP_RETURN:106,OP_TOALTSTACK:107,OP_FROMALTSTACK:108,OP_2DROP:109,OP_2DUP:110,OP_3DUP:111,OP_2OVER:112,OP_2ROT:113,OP_2SWAP:114,OP_IFDUP:115,OP_DEPTH:116,OP_DROP:117,OP_DUP:118,OP_NIP:119,OP_OVER:120,OP_PICK:121,OP_ROLL:122,OP_ROT:123,OP_SWAP:124,OP_TUCK:125,OP_CAT:126,OP_SUBSTR:127,OP_LEFT:128,OP_RIGHT:129,OP_SIZE:130,OP_INVERT:131,OP_AND:132,OP_OR:133,OP_XOR:134,OP_EQUAL:135,OP_EQUALVERIFY:136,OP_RESERVED1:137,OP_RESERVED2:138,OP_1ADD:139,OP_1SUB:140,OP_2MUL:141,OP_2DIV:142,OP_NEGATE:143,OP_ABS:144,OP_NOT:145,OP_0NOTEQUAL:146,OP_ADD:147,OP_SUB:148,OP_MUL:149,OP_DIV:150,OP_MOD:151,OP_LSHIFT:152,OP_RSHIFT:153,OP_BOOLAND:154,OP_BOOLOR:155,OP_NUMEQUAL:156,OP_NUMEQUALVERIFY:157,OP_NUMNOTEQUAL:158,OP_LESSTHAN:159,OP_GREATERTHAN:160,OP_LESSTHANOREQUAL:161,OP_GREATERTHANOREQUAL:162,OP_MIN:163,OP_MAX:164,OP_WITHIN:165,OP_RIPEMD160:166,OP_SHA1:167,OP_SHA256:168,OP_HASH160:169,OP_HASH256:170,OP_CODESEPARATOR:171,OP_CHECKSIG:172,OP_CHECKSIGVERIFY:173,OP_CHECKMULTISIG:174,OP_CHECKMULTISIGVERIFY:175,OP_NOP1:176,OP_NOP2:177,OP_NOP3:178,OP_NOP4:179,OP_NOP5:180,OP_NOP6:181,OP_NOP7:182,OP_NOP8:183,OP_NOP9:184,OP_NOP10:185,OP_PUBKEYHASH:253,OP_PUBKEY:254,OP_INVALIDOPCODE:255},Opcode.reverseMap=[];for(var k in Opcode.map)Opcode.map.hasOwnProperty(k)&&(Opcode.reverseMap[Opcode.map[k]]=k.substr(3));Opcode.asList=function(){var O=[];for(var P in Opcode.map)Opcode.map.hasOwnProperty(P)&&O.push(P);return O},module.exports=Opcode; -},{}],"./lib/Opcode":[function(require,module,exports){ -module.exports=require('Zm7/h9'); -},{}],"izTl9z":[function(require,module,exports){ -(function(t){function i(t,e,r){i.super_.call(this,t,e),void 0!==r&&this.compressed(r)}var e=require("../util/VersionedData"),r=require("../util/EncodedData"),n=require("../networks"),a=require("util");a.inherits(i,e),r.applyEncodingsTo(i),i.prototype.validate=function(){if(this.doAsBinary(function(){if(i.super_.prototype.validate.call(this),this.data.length<32||this.data.length>33&&!this.compressed()||34==this.data.length&&1!=this.data[33]||this.data.length>34)throw new Error("invalid data length")}),"undefined"==typeof this.network())throw new Error("invalid network")},i.prototype.payload=function(t){if(t)return this.doAsBinary(function(){t.copy(this.data,1)}),t;var i=this.as("binary");return 34==i.length?i.slice(1,33):33==i.length?i.slice(1):void 0},i.prototype.compressed=function(i){if(void 0===i){var e=34,r=this.as("binary");if(r.length==e&&1==r[e-1])return!0;if(r.length==e-1)return!1;throw new Error("invalid private key")}this.doAsBinary(function(){var e=34;if(i){var r=new t(e);this.data.copy(r),this.data=r,this.data[e-1]=1}else this.data=this.data.slice(0,e-1)})},i.prototype.network=function(){var t,i=this.version(),e=n.livenet,r=n.testnet;return i===e.privKeyVersion?t=e:i===r.privKeyVersion&&(t=r),t},module.exports=i}).call(this,require("buffer").Buffer); -},{"../networks":"ULNIu2","../util/EncodedData":"eLfUFE","../util/VersionedData":"QLzNQg","buffer":76,"util":109}],"./lib/PrivateKey":[function(require,module,exports){ -module.exports=require('izTl9z'); -},{}],"./lib/RpcClient":[function(require,module,exports){ -module.exports=require('7siE1N'); -},{}],"7siE1N":[function(require,module,exports){ -(function(t){function e(t){t=t||{},this.host=t.host||"127.0.0.1",this.port=t.port||8332,this.user=t.user||"user",this.pass=t.pass||"pass",this.protocol="http"==t.protocol?n:o,this.batchedCalls=null,this.disableAgent=t.disableAgent||!1}function r(t,e,r){function s(t,e){return function(){var s=arguments.length-1;if(this.batchedCalls)var s=arguments.length;for(var n=0;s>n;n++)e[n]&&(arguments[n]=e[n](arguments[n]));this.batchedCalls?this.batchedCalls.push({jsonrpc:"2.0",method:t,params:l(arguments)}):r.call(this,{method:t,params:l(arguments,0,arguments.length-1)},arguments[arguments.length-1])}}var n={str:function(t){return t.toString()},"int":function(t){return parseFloat(t)},"float":function(t){return parseFloat(t)},bool:function(t){return t===!0||"1"==t||"true"==t||"true"==t.toString().toLowerCase()}};for(var o in e)if(e.hasOwnProperty(o)){for(var i=e[o].split(" "),a=0;a=h.map.OP_1&&t<=h.map.OP_16}function n(t){return t=t?2:65535>=t?3:5}function s(e){var r=void 0;return e=e?(r=new t(2),r.writeUInt8(h.map.OP_PUSHDATA1,0),r.writeUInt8(e,1)):65535>=e?(r=new t(3),r.writeUInt8(h.map.OP_PUSHDATA2,0),r.writeUInt16LE(e,1)):(r=new t(5),r.writeUInt8(h.map.OP_PUSHDATA4,0),r.writeUInt32LE(e,1)),r}var u=(require("../config"),require("../util/log")),h=require("./Opcode"),o=require("buffertools"),f=require("../util/util"),c=require("../util/BinaryParser"),p=require("bufferput"),a=0,l=1,g=2,k=3,y=4,w=["unknown","pubkey","pubkeyhash","multisig","scripthash"];e.TX_UNKNOWN=a,e.TX_PUBKEY=l,e.TX_PUBKEYHASH=g,e.TX_MULTISIG=k,e.TX_SCRIPTHASH=y,e.prototype.parse=function(){this.chunks=[];for(var t=new c(this.buffer);!t.eof();){var e,r,n=t.word8();n>0&&nh.map.OP_16)return!1}return!0},e.prototype.isP2SH=function(){return 3==this.chunks.length&&this.chunks[0]==h.map.OP_HASH160&&t.isBuffer(this.chunks[1])&&20==this.chunks[1].length&&this.chunks[2]==h.map.OP_EQUAL},e.prototype.isPubkey=function(){return 2==this.chunks.length&&t.isBuffer(this.chunks[0])&&this.chunks[1]==h.map.OP_CHECKSIG},e.prototype.isPubkeyHash=function(){return 5==this.chunks.length&&this.chunks[0]==h.map.OP_DUP&&this.chunks[1]==h.map.OP_HASH160&&t.isBuffer(this.chunks[2])&&20==this.chunks[2].length&&this.chunks[3]==h.map.OP_EQUALVERIFY&&this.chunks[4]==h.map.OP_CHECKSIG},e.prototype.isMultiSig=function(){return this.chunks.length>3&&r(this.chunks[0])&&this.chunks.slice(1,this.chunks.length-2).every(function(e){return t.isBuffer(e)})&&r(this.chunks[this.chunks.length-2])&&this.chunks[this.chunks.length-1]==h.map.OP_CHECKMULTISIG},e.prototype.isPubkeyHashScript=function(){return 2==this.chunks.length&&t.isBuffer(this.chunks[0])&&t.isBuffer(this.chunks[1])},e.prototype.isP2shScriptSig=function(){if(!r(this.chunks[0])||0!==this.chunks[0])return!1;var t=new e(this.chunks[this.chunks.length-1]),n=t.classify();return n!==a},e.prototype.isMultiSigScriptSig=function(){return r(this.chunks[0])&&0===this.chunks[0]?!this.isP2shScriptSig():!1},e.prototype.countSignatures=function(){var t=0,e=this.chunks.length;return t=this.isMultiSigScriptSig()?e-1:this.isP2shScriptSig()?e-2:this.isPubkeyHashScript()?1:0},e.prototype.getSignatures=function(){ret=[];var t=this.chunks.length;if(this.isMultiSigScriptSig())for(var e=1;t>e;e++)ret.push(this.chunks[e]);else if(this.isP2shScriptSig())for(var e=1;t-1>e;e++)ret.push(this.chunks[e]);else this.isPubkeyHashScript()&&ret.push(this.chunks[0]);return ret},e.prototype.getHashType=function(){for(var t=this.getSignatures(),e=null,r=0;rs;s++){var u=this.chunks[s];if(s>0&&(n+=" "),n+=t.isBuffer(u)?"0x"+f.formatBuffer(u,e?null:0):h.reverseMap[u],r&&s>r){n+=" ...";break}}return n},e.prototype.toString=function(t,e){var r=" - + diff --git a/lib/MessageDb.js b/lib/MessageDb.js index 164abfcd..36b195cb 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -8,10 +8,10 @@ var async = require('async'); var logger = require('./logger').logger; var util = require('util'); var EventEmitter = require('events').EventEmitter; -var sockets = require('../app/controllers/socket.js'); var microtime = require('microtime'); var bitcore = require('bitcore'); var AuthMessage = bitcore.AuthMessage; +var preconditions = require('preconditions').singleton(); var MESSAGE_PREFIX = 'msg-'; // msg-- => @@ -37,13 +37,13 @@ util.inherits(MessageDb, EventEmitter); MessageDb.prototype.initEvents = function() { if (db) return; + var self = this; this.db.on('put', function(key, value) { - var spl = key.split('-'); - var from = spl[1]; - var to = spl[2]; - var ts = spl[3]; - var message = value; - sockets.broadcastMessage(from, to, ts, message); + var data = {}; + data.key = key; + data.value = value; + var message = MessageDb.fromStorage(data); + self.emit('message', message); }); this.db.on('ready', function() { //console.log('Database ready!'); @@ -55,49 +55,58 @@ MessageDb.prototype.close = function(cb) { }; -var messageKey = function(from, to, ts) { +var messageKey = function(pubkey, to, ts) { if (!ts) ts = Math.round(microtime.now()); - return MESSAGE_PREFIX + from.toString() + '-' + to.toString() + '-' + ts; + return MESSAGE_PREFIX + pubkey.toString() + '-' + to.toString() + '-' + ts; }; -MessageDb.prototype.addMessage = function(m, from, to, cb) { - +MessageDb.prototype.addMessage = function(m, cb) { + if (!this.authenticate(m)) { cb(new Error('Authentication failed')); return; } - var key = messageKey(from, to); + var key = messageKey(m.pubkey, m.to); var value = m; this.db.put(key, value, cb); }; MessageDb.prototype.authenticate = function(m) { + preconditions.checkArgument(m.pubkey); + preconditions.checkArgument(m.sig); + preconditions.checkArgument(m.encrypted); + var frompubkey = new Buffer(m.pubkey, 'hex'); var sig = new Buffer(m.sig, 'hex'); var encrypted = new Buffer(m.encrypted, 'hex'); return AuthMessage._verify(frompubkey, sig, encrypted); }; -MessageDb.prototype.getMessages = function(from, to, lower_ts, upper_ts, cb) { +MessageDb.fromStorage = function(data) { + var spl = data.key.split('-'); + var pubkey = spl[1]; + var to = spl[2]; + var ts = +spl[3]; + var message = data.value; + message.ts = ts; + message.to = to; + return message; +}; + +MessageDb.prototype.getMessages = function(pubkey, to, lower_ts, upper_ts, cb) { var list = []; var opts = { - end: messageKey(from, to, lower_ts), - start: messageKey(from, to, upper_ts), + end: messageKey(pubkey, to, lower_ts), + start: messageKey(pubkey, to, upper_ts), // limit: limit, TODO reverse: true, }; db.createReadStream(opts) .on('data', function(data) { - var spl = data.key.split('-'); - var from = spl[1]; - var to = spl[2]; - var ts = +spl[3]; - list.push({ - ts: ts, - message: data.value, - }); + var message = MessageDb.fromStorage(data); + list.push(message); }) .on('error', function(err) { return cb(err); diff --git a/package.json b/package.json index 31dd267a..be8c9cd5 100644 --- a/package.json +++ b/package.json @@ -51,24 +51,25 @@ "start": "node node_modules/grunt-cli/bin/grunt" }, "dependencies": { - "bitcore": "git://github.com/bitpay/bitcore.git#4d8af75ae9916984c52ee2eda1870d5980656341", - "base58-native": "0.1.2", "async": "*", + "base58-native": "0.1.2", + "bignum": "*", + "bitcore": "git://github.com/bitpay/bitcore.git#4d8af75ae9916984c52ee2eda1870d5980656341", + "bufferput": "git://github.com/bitpay/node-bufferput.git", + "buffertools": "*", + "commander": "*", + "express": "~3.4.7", + "glob": "*", "leveldown": "*", "levelup": "*", - "glob": "*", - "soop": "=0.1.5", - "commander": "*", - "bignum": "*", - "winston": "*", - "express": "~3.4.7", - "buffertools": "*", - "should": "~2.1.1", - "socket.io": "~1.0.4", "moment": "~2.5.0", + "preconditions": "^1.0.7", + "should": "~2.1.1", "sinon": "~1.7.3", - "xmlhttprequest": "~1.6.0", - "bufferput": "git://github.com/bitpay/node-bufferput.git" + "socket.io": "~1.0.4", + "soop": "=0.1.5", + "winston": "*", + "xmlhttprequest": "~1.6.0" }, "devDependencies": { "chai": "*", diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js index c6aabaa0..151b6614 100644 --- a/test/test.MessageDb.js +++ b/test/test.MessageDb.js @@ -4,12 +4,14 @@ var chai = require('chai'); var should = chai.should; var expect = chai.expect; -var MessageDb = require('../lib/MessageDb'); -var bitcore = require('bitcore'); -var SIN = bitcore.SIN; var levelup = require('levelup'); var memdown = require('memdown'); var microtime = require('microtime'); +var MessageDb = require('../lib/MessageDb'); +var bitcore = require('bitcore'); +var SIN = bitcore.SIN; +var Key = bitcore.Key; +var AuthMessage = bitcore.AuthMessage; describe('MessageDb', function() { var opts = { @@ -28,18 +30,23 @@ describe('MessageDb', function() { var mdb = MessageDb.default(); expect(mdb).to.exist; }); - var from = new SIN(new Buffer('dadbad00', 'hex')); - var to = new SIN(new Buffer('bacacafe', 'hex')); - var message = { + var fpk = Key.generateSync(); + var tpk = Key.generateSync(); + var from = fpk.public.toString('hex'); + var to = tpk.public.toString('hex'); + var messageData = { a: 1, b: 2 }; - var message2 = {}; - var message3 = ['a', 'b']; + var messageData2 = {}; + var messageData3 = ['a', 'b']; + var message = AuthMessage.encode(to, fpk, messageData); + var message2 = AuthMessage.encode(to, fpk, messageData2); + var message3 = AuthMessage.encode(to, fpk, messageData3); it('should be able to add and read a message', function(done) { var mdb = new MessageDb(opts); var lower_ts = microtime.now(); - mdb.addMessage(message, from, to, function(err) { + mdb.addMessage(message, function(err) { expect(err).to.not.exist; var upper_ts = microtime.now(); mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { @@ -47,7 +54,7 @@ describe('MessageDb', function() { messages.length.should.equal(1); messages[0].ts.should.be.below(upper_ts); messages[0].ts.should.be.above(lower_ts); - var m = messages[0].message; + var m = AuthMessage.decode(tpk, messages[0]).payload; m.a.should.equal(1); m.b.should.equal(2); done(); @@ -57,23 +64,25 @@ describe('MessageDb', function() { it('should be able to add many messages and read them', function(done) { var mdb = new MessageDb(opts); var lower_ts = microtime.now(); - mdb.addMessage(message, from, to, function(err) { + mdb.addMessage(message, function(err) { expect(err).to.not.exist; - mdb.addMessage(message2, from, to, function(err) { + mdb.addMessage(message2, function(err) { expect(err).to.not.exist; var upper_ts = microtime.now(); setTimeout(function() { - mdb.addMessage(message3, from, to, function(err) { + mdb.addMessage(message3, function(err) { expect(err).to.not.exist; mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { expect(err).to.not.exist; messages.length.should.equal(2); messages[0].ts.should.be.below(upper_ts); messages[0].ts.should.be.above(lower_ts); - JSON.stringify(messages[0].message).should.equal('{"a":1,"b":2}'); + var m0 = AuthMessage.decode(tpk, messages[0]).payload; + JSON.stringify(m0).should.equal('{"a":1,"b":2}'); messages[1].ts.should.be.below(upper_ts); messages[1].ts.should.be.above(lower_ts); - JSON.stringify(messages[1].message).should.equal('{}'); + var m1 = AuthMessage.decode(tpk, messages[1]).payload; + JSON.stringify(m1).should.equal('{}'); done(); }); }); From 9087701d99ede71a222ada741d6aff172991b40e Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 4 Aug 2014 17:45:10 -0300 Subject: [PATCH 10/16] update bitcore version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index be8c9cd5..2bec243f 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "async": "*", "base58-native": "0.1.2", "bignum": "*", - "bitcore": "git://github.com/bitpay/bitcore.git#4d8af75ae9916984c52ee2eda1870d5980656341", + "bitcore": "git://github.com/maraoz/bitcore.git#895046cc3248c0c03fc9614ecc7388d3ab680849", "bufferput": "git://github.com/bitpay/node-bufferput.git", "buffertools": "*", "commander": "*", From 1d5af5bdad29d87cdc6825bcc7e1f82208b638f4 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 5 Aug 2014 13:04:38 -0300 Subject: [PATCH 11/16] add socket server test --- app/controllers/socket.js | 75 +++++++++++++++++++++++++------------- examples/messages.html | 8 ++++ lib/MessageDb.js | 22 ++++++----- test/test.MessageDb.js | 4 +- test/test.socket-server.js | 30 +++++++++++++++ 5 files changed, 101 insertions(+), 38 deletions(-) create mode 100644 test/test.socket-server.js diff --git a/app/controllers/socket.js b/app/controllers/socket.js index be6e614c..173ddb34 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -7,40 +7,63 @@ var mdb = require('../../lib/MessageDb').default(); module.exports.init = function(io_ext) { ios = io_ext; - ios.sockets.on('connection', function(socket) { - socket.on('subscribe', function(topic) { - socket.join(topic); - }); - socket.on('message', function(m) { - mdb.addMessage(m, function(err) { - if (err) throw err; // TODO: handle + if (ios) { + // when a new socket connects + ios.sockets.on('connection', function(socket) { + // when it subscribes, make it join the according room + socket.on('subscribe', function(topic) { + socket.join(topic); + }); + + // when it requests sync, send him all pending messages + socket.on('sync', function(ts) { + mdb.getMessages(to, lower_ts, upper_ts, function(err, messages) { + if (err) { + throw new Error('Couldn\'t get messages on sync request: ' + err); + } + for (var i = 0; i < message.length; i++) { + broadcastMessage(messages[i]); + } + }); + }); + + // when it sends a message, add it to db + socket.on('message', function(m) { + mdb.addMessage(m, function(err) { + if (err) { + throw new Error('Couldn\'t add message to database: ' + err); + } + }); }); }); + mdb.on('message', broadcastMessage); + } +}; + +var simpleTx = function(tx) { + return { + txid: tx + }; +}; + +var fullTx = function(tx) { + var t = { + txid: tx.txid, + size: tx.size, + }; + // Outputs + var valueOut = 0; + tx.vout.forEach(function(o) { + valueOut += o.valueSat; }); - mdb.on('message', broadcastMessage); + t.valueOut = (valueOut.toFixed(8) / util.COIN); + return t; }; module.exports.broadcastTx = function(tx) { if (ios) { - var t; - if (typeof tx === 'string') { - t = { - txid: tx - }; - } else { - t = { - txid: tx.txid, - size: tx.size, - }; - // Outputs - var valueOut = 0; - tx.vout.forEach(function(o) { - valueOut += o.valueSat; - }); - - t.valueOut = (valueOut.toFixed(8) / util.COIN); - } + var t = (typeof tx === 'string') ? simpleTx(tx) : fullTx(tx); ios.sockets.in('inv').emit('tx', t); } }; diff --git a/examples/messages.html b/examples/messages.html index dfbd83ee..088befbe 100644 --- a/examples/messages.html +++ b/examples/messages.html @@ -57,6 +57,8 @@