add MessageDb

This commit is contained in:
Manuel Araoz 2014-07-29 17:28:15 -03:00
parent 1c6010ba99
commit c39749c58e
7 changed files with 264 additions and 178 deletions

View File

@ -76,45 +76,6 @@ var bitcoindConf = {
disableAgent: true 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)) { if (!fs.existsSync(db)) {

View File

@ -15,6 +15,45 @@ var express = require('express'),
//Initializing system variables //Initializing system variables
var config = require('./config/config'); 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 * express app
*/ */
@ -32,8 +71,7 @@ var walk = function(path) {
if (/(.*)\.(js$)/.test(file)) { if (/(.*)\.(js$)/.test(file)) {
require(newPath); require(newPath);
} }
} } else if (stat.isDirectory()) {
else if (stat.isDirectory()) {
walk(newPath); walk(newPath);
} }
}); });
@ -45,7 +83,9 @@ walk(models_path);
* p2pSync process * p2pSync process
*/ */
var peerSync = new PeerSync({shouldBroadcast: true}); var peerSync = new PeerSync({
shouldBroadcast: true
});
if (!config.disableP2pSync) { if (!config.disableP2pSync) {
peerSync.run(); peerSync.run();
@ -60,16 +100,15 @@ var historicSync = new HistoricSync({
peerSync.historicSync = historicSync; peerSync.historicSync = historicSync;
if (!config.disableHistoricSync) { if (!config.disableHistoricSync) {
historicSync.start({}, function(err){ historicSync.start({}, function(err) {
if (err) { if (err) {
var txt = 'ABORTED with error: ' + err.message; var txt = 'ABORTED with error: ' + err.message;
console.log('[historic_sync] ' + txt); console.log('[historic_sync] ' + txt);
} }
if (peerSync) peerSync.allowReorgs = true; if (peerSync) peerSync.allowReorgs = true;
}); });
} } else
else if (peerSync) peerSync.allowReorgs = true;
if (peerSync) peerSync.allowReorgs = true;
//express settings //express settings
@ -84,8 +123,8 @@ var ios = require('socket.io')(server);
require('./app/controllers/socket.js').init(expressApp, ios); require('./app/controllers/socket.js').init(expressApp, ios);
//Start the app by listening on <port> //Start the app by listening on <port>
server.listen(config.port, function(){ server.listen(config.port, function() {
console.log('insight server listening on port %d in %s mode', server.address().port, process.env.NODE_ENV); console.log('insight server listening on port %d in %s mode', server.address().port, process.env.NODE_ENV);
}); });
//expose app //expose app

57
lib/MessageDb.js Normal file
View File

@ -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-<sin1>-<sin2> => <message>
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);

View File

@ -1,6 +1,6 @@
'use strict'; 'use strict';
var imports = require('soop').imports(); var imports = require('soop').imports();
@ -20,40 +20,42 @@ var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda
var CONCURRENCY = 10; var CONCURRENCY = 10;
var DEFAULT_SAFE_CONFIRMATIONS = 6; var DEFAULT_SAFE_CONFIRMATIONS = 6;
var MAX_OPEN_FILES = 500; var MAX_OPEN_FILES = 500;
var END_OF_WORLD_TS = 1e13; var END_OF_WORLD_TS = 1e13;
// var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend // var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend
/** /**
* Module dependencies. * Module dependencies.
*/ */
var bitcore = require('bitcore'), var bitcore = require('bitcore'),
Rpc = imports.rpc || require('./Rpc'), Rpc = imports.rpc || require('./Rpc'),
util = bitcore.util, util = bitcore.util,
networks = bitcore.networks, networks = bitcore.networks,
levelup = require('levelup'), levelup = require('levelup'),
async = require('async'), async = require('async'),
config = require('../config/config'), config = require('../config/config'),
assert = require('assert'), assert = require('assert'),
Script = bitcore.Script, Script = bitcore.Script,
bitcoreUtil = bitcore.util, bitcoreUtil = bitcore.util,
buffertools = require('buffertools'); buffertools = require('buffertools');
var logger = require('./logger').logger; 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 db = imports.db || levelup(config.leveldb + '/txs', {
var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch',config); maxOpenFiles: MAX_OPEN_FILES
});
var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch', config);
// This is 0.1.2 = > c++ version of base58-native // This is 0.1.2 = > c++ version of base58-native
var base58 = require('base58-native').base58Check; var base58 = require('base58-native').base58Check;
var encodedData = require('soop').load('bitcore/util/EncodedData',{ var encodedData = require('soop').load('bitcore/util/EncodedData', {
base58: base58 base58: base58
}); });
var versionedData= require('soop').load('bitcore/util/VersionedData',{ var versionedData = require('soop').load('bitcore/util/VersionedData', {
parent: encodedData parent: encodedData
}); });
var Address = require('soop').load('bitcore/lib/Address',{ var Address = require('soop').load('bitcore/lib/Address', {
parent: versionedData parent: versionedData
}); });
@ -76,7 +78,9 @@ TransactionDb.prototype.drop = function(cb) {
var path = config.leveldb + '/txs'; var path = config.leveldb + '/txs';
db.close(function() { db.close(function() {
require('leveldown').destroy(path, function() { require('leveldown').destroy(path, function() {
db = levelup(path, {maxOpenFiles: 500}); db = levelup(path, {
maxOpenFiles: 500
});
return cb(); return cb();
}); });
}); });
@ -278,13 +282,14 @@ TransactionDb.prototype.fromTxIdN = function(txid, n, cb) {
var k = OUTS_PREFIX + txid + '-' + n; var k = OUTS_PREFIX + txid + '-' + n;
db.get(k, function(err, val) { db.get(k, function(err, val) {
var ret; var ret;
if (!val || (err && err.notFound)) { if (!val || (err && err.notFound)) {
err=null; err = null;
ret= { unconfirmedInput: 1 }; ret = {
} unconfirmedInput: 1
else { };
} else {
var a = val.split(':'); var a = val.split(':');
ret = { ret = {
addr: a[0], 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 k = ADDR_PREFIX + addr + '-';
var dbScript = []; var dbScript = [];
db.createReadStream({ db.createReadStream({
@ -330,17 +335,17 @@ TransactionDb.prototype.deleteCacheForAddress = function(addr,cb) {
.on('error', function(err) { .on('error', function(err) {
return cb(err); return cb(err);
}) })
.on('end', function (){ .on('end', function() {
db.batch(dbScript,cb); db.batch(dbScript, cb);
}); });
}; };
TransactionDb.prototype.cacheConfirmations = function(txouts,cb) { TransactionDb.prototype.cacheConfirmations = function(txouts, cb) {
var self = this; var self = this;
var dbScript=[]; var dbScript = [];
for(var ii in txouts){ for (var ii in txouts) {
var txout=txouts[ii]; var txout = txouts[ii];
//everything already cached? //everything already cached?
if (txout.spentIsConfirmedCached) { if (txout.spentIsConfirmedCached) {
@ -354,15 +359,14 @@ TransactionDb.prototype.cacheConfirmations = function(txouts,cb) {
// if spent, we overwrite scriptPubKey cache (not needed anymore) // if spent, we overwrite scriptPubKey cache (not needed anymore)
// First 1 = txout.isConfirmedCached (must be equal to 1 at this point) // First 1 = txout.isConfirmedCached (must be equal to 1 at this point)
infoToCache = [1, 1, txout.spentTxId, txout.spentIndex, txout.spentTs]; infoToCache = [1, 1, txout.spentTxId, txout.spentIndex, txout.spentTs];
} } else {
else { if (!txout.isConfirmedCached) {
if (!txout.isConfirmedCached) {
infoToCache.push(1); infoToCache.push(1);
txout.confirmedWillBeCached=1; txout.confirmedWillBeCached = 1;
} }
} }
//console.log('[TransactionDb.js.352:infoToCache:]',infoToCache); //TODO //console.log('[TransactionDb.js.352:infoToCache:]',infoToCache); //TODO
if (infoToCache.length){ if (infoToCache.length) {
infoToCache.unshift(txout.value_sat); infoToCache.unshift(txout.value_sat);
dbScript.push({ dbScript.push({
@ -374,25 +378,24 @@ TransactionDb.prototype.cacheConfirmations = function(txouts,cb) {
} }
} }
//console.log('[TransactionDb.js.339:dbScript:]',dbScript); //TODO //console.log('[TransactionDb.js.339:dbScript:]',dbScript); //TODO
db.batch(dbScript,cb); db.batch(dbScript, cb);
}; };
TransactionDb.prototype.cacheScriptPubKey = function(txouts,cb) { TransactionDb.prototype.cacheScriptPubKey = function(txouts, cb) {
// console.log('[TransactionDb.js.381:cacheScriptPubKey:]'); //TODO // console.log('[TransactionDb.js.381:cacheScriptPubKey:]'); //TODO
var self = this; var self = this;
var dbScript=[]; var dbScript = [];
for(var ii in txouts){ for (var ii in txouts) {
var txout=txouts[ii]; var txout = txouts[ii];
//everything already cached? //everything already cached?
if (txout.scriptPubKeyCached || txout.spentTxId) { if (txout.scriptPubKeyCached || txout.spentTxId) {
continue; continue;
} }
if (txout.scriptPubKey) { if (txout.scriptPubKey) {
var infoToCache = [txout.value_sat, var infoToCache = [txout.value_sat, (txout.isConfirmedCached || txout.confirmedWillBeCached) ? 1 : 0, txout.scriptPubKey];
(txout.isConfirmedCached || txout.confirmedWillBeCached)?1:0, txout.scriptPubKey];
dbScript.push({ dbScript.push({
type: 'put', type: 'put',
key: txout.key, 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[1]== isConfirmedCached
// v[2]=== '1' -> is SpendCached -> [4]=spendTxId [5]=spentIndex [6]=spendTs // v[2]=== '1' -> is SpendCached -> [4]=spendTxId [5]=spentIndex [6]=spendTs
// v[2]!== '1' -> is ScriptPubkey -> [[2] = scriptPubkey // v[2]!== '1' -> is ScriptPubkey -> [[2] = scriptPubkey
if (v[1]==='1'){ if (v[1] === '1') {
item.isConfirmed = 1; item.isConfirmed = 1;
item.isConfirmedCached = 1; item.isConfirmedCached = 1;
// console.log('[TransactionDb.js.356] CACHE HIT CONF:', item.key); // console.log('[TransactionDb.js.356] CACHE HIT CONF:', item.key);
// Sent, confirmed // Sent, confirmed
if (v[2] === '1'){ if (v[2] === '1') {
// console.log('[TransactionDb.js.356] CACHE HIT SPENT:', item.key); // console.log('[TransactionDb.js.356] CACHE HIT SPENT:', item.key);
item.spentIsConfirmed = 1; item.spentIsConfirmed = 1;
item.spentIsConfirmedCached = 1; item.spentIsConfirmedCached = 1;
@ -441,7 +444,7 @@ TransactionDb.prototype._parseAddrData = function(k, data, ignoreCache) {
else if (v[2]) { else if (v[2]) {
item.scriptPubKey = v[2]; item.scriptPubKey = v[2];
item.scriptPubKeyCached = 1; 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; return item;
@ -452,24 +455,26 @@ TransactionDb.prototype.fromAddr = function(addr, opts, cb) {
var self = this; var self = this;
var k = ADDR_PREFIX + addr + '-'; var k = ADDR_PREFIX + addr + '-';
var ret = []; var ret = [];
var unique={}; var unique = {};
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: 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) { .on('data', function(data) {
var k = data.key.split('-'); var k = data.key.split('-');
var index = k[3]+k[4]; var index = k[3] + k[4];
if (!unique[index]) { if (!unique[index]) {
unique[index]=1; unique[index] = 1;
ret.push(self._parseAddrData(k, data, opts.ignoreCache)); ret.push(self._parseAddrData(k, data, opts.ignoreCache));
} }
}) })
.on('error', cb) .on('error', cb)
.on('end', function() { .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 + '-'; var k = SPENT_PREFIX + o.txid + '-' + o.index + '-';
db.createReadStream({ db.createReadStream({
start: k, start: k,
@ -488,18 +493,20 @@ TransactionDb.prototype.fromAddr = function(addr, opts, cb) {
}); });
}; };
TransactionDb.prototype._fromBuffer = function (buf) { TransactionDb.prototype._fromBuffer = function(buf) {
var buf2 = buffertools.reverse(buf); var buf2 = buffertools.reverse(buf);
return parseInt(buf2.toString('hex'), 16); return parseInt(buf2.toString('hex'), 16);
}; };
TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) { TransactionDb.prototype.getStandardizedTx = function(tx, time, isCoinBase) {
var self = this; var self = this;
tx.txid = bitcoreUtil.formatHashFull(tx.getHash()); tx.txid = bitcoreUtil.formatHashFull(tx.getHash());
var ti=0; var ti = 0;
tx.vin = tx.ins.map(function(txin) { tx.vin = tx.ins.map(function(txin) {
var ret = {n: ti++}; var ret = {
n: ti++
};
if (isCoinBase) { if (isCoinBase) {
ret.isCoinBase = true; ret.isCoinBase = true;
} else { } else {
@ -517,7 +524,9 @@ TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) {
var addrs = new Address.fromScriptPubKey(s, config.network); var addrs = new Address.fromScriptPubKey(s, config.network);
// support only for p2pubkey p2pubkeyhash and p2sh // support only for p2pubkey p2pubkeyhash and p2sh
if (addrs && addrs.length === 1) { if (addrs && addrs.length === 1) {
val = {addresses: [addrs[0].toString() ] }; val = {
addresses: [addrs[0].toString()]
};
} }
} }
return { return {
@ -532,22 +541,23 @@ TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) {
TransactionDb.prototype.fillScriptPubKey = function(txouts, cb) { TransactionDb.prototype.fillScriptPubKey = function(txouts, cb) {
var self=this; var self = this;
// Complete utxo info // 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) { self.fromIdInfoSimple(txout.txid, function(err, info) {
if (!info || !info.vout) return a_c(err); if (!info || !info.vout) return a_c(err);
txout.scriptPubKey = info.vout[txout.index].scriptPubKey.hex; txout.scriptPubKey = info.vout[txout.index].scriptPubKey.hex;
return a_c(); return a_c();
}); });
}, function(){ }, function() {
self.cacheScriptPubKey(txouts, cb); self.cacheScriptPubKey(txouts, cb);
}); });
}; };
TransactionDb.prototype.removeFromTxId = function(txid, cb) { TransactionDb.prototype.removeFromTxId = function(txid, cb) {
async.series([ async.series([
function(c) { function(c) {
db.createReadStream({ db.createReadStream({
start: OUTS_PREFIX + txid + '-', 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 // relatedAddrs is an optional hash, to collect related addresses in the transaction
TransactionDb.prototype._addScript = function(tx, relatedAddrs) { TransactionDb.prototype._addScript = function(tx, relatedAddrs) {
var dbScript = []; var dbScript = [];
var ts = tx.time; var ts = tx.time;
var txid = tx.txid || tx.hash; var txid = tx.txid || tx.hash;
// var u=require('util'); // var u=require('util');
// console.log('[TransactionDb.js.518]', u.inspect(tx,{depth:10})); //TODO // console.log('[TransactionDb.js.518]', u.inspect(tx,{depth:10})); //TODO
// Input Outpoints (mark them as spent) // Input Outpoints (mark them as spent)
for(var ii in tx.vin) { for (var ii in tx.vin) {
var i = tx.vin[ii]; var i = tx.vin[ii];
if (i.txid){ if (i.txid) {
var k = SPENT_PREFIX + i.txid + '-' + i.vout + '-' + txid + '-' + i.n; var k = SPENT_PREFIX + i.txid + '-' + i.vout + '-' + txid + '-' + i.n;
dbScript.push({ dbScript.push({
type: 'put', 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]; var o = tx.vout[ii];
if ( o.scriptPubKey && o.scriptPubKey.addresses && if (o.scriptPubKey && o.scriptPubKey.addresses &&
o.scriptPubKey.addresses[0] && !o.scriptPubKey.addresses[1] // TODO : not supported=> standard multisig o.scriptPubKey.addresses[0] && !o.scriptPubKey.addresses[1] // TODO : not supported=> standard multisig
) { ) {
var addr = o.scriptPubKey.addresses[0]; var addr = o.scriptPubKey.addresses[0];
var sat = o.valueSat || ((o.value||0) * util.COIN).toFixed(0); var sat = o.valueSat || ((o.value || 0) * util.COIN).toFixed(0);
if (relatedAddrs) relatedAddrs[addr]=1; if (relatedAddrs) relatedAddrs[addr] = 1;
var k = OUTS_PREFIX + txid + '-' + o.n; var k = OUTS_PREFIX + txid + '-' + o.n;
var tsr = END_OF_WORLD_TS - ts; var tsr = END_OF_WORLD_TS - ts;
dbScript.push({ dbScript.push({
type: 'put', type: 'put',
key: k, key: k,
value: addr + ':' + sat, value: addr + ':' + sat,
},{ }, {
type: 'put', type: 'put',
key: ADDR_PREFIX + addr + '-' + tsr + '-'+ txid + '-' + o.n, key: ADDR_PREFIX + addr + '-' + tsr + '-' + txid + '-' + o.n,
value: sat, value: sat,
}); });
} }
} }
return dbScript; return dbScript;
}; };
@ -626,12 +636,14 @@ TransactionDb.prototype._addScript = function(tx, relatedAddrs) {
TransactionDb.prototype.add = function(tx, cb) { TransactionDb.prototype.add = function(tx, cb) {
var relatedAddrs = {}; var relatedAddrs = {};
var dbScript = this._addScript(tx, 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) { TransactionDb.prototype._addManyFromObjs = function(txs, next) {
var dbScript = []; var dbScript = [];
for(var ii in txs){ for (var ii in txs) {
var s = this._addScript(txs[ii]); var s = this._addScript(txs[ii]);
dbScript = dbScript.concat(s); dbScript = dbScript.concat(s);
} }
@ -639,17 +651,17 @@ TransactionDb.prototype._addManyFromObjs = function(txs, next) {
}; };
TransactionDb.prototype._addManyFromHashes = function(txs, next) { TransactionDb.prototype._addManyFromHashes = function(txs, next) {
var self=this; var self = this;
var dbScript = []; var dbScript = [];
async.eachLimit(txs, CONCURRENCY, function(tx, each_cb) { async.eachLimit(txs, CONCURRENCY, function(tx, each_cb) {
if (tx === genesisTXID) if (tx === genesisTXID)
return each_cb(); return each_cb();
Rpc.getTxInfo(tx, function(err, inInfo) { Rpc.getTxInfo(tx, function(err, inInfo) {
if (!inInfo) return each_cb(err); if (!inInfo) return each_cb(err);
dbScript = dbScript.concat(self._addScript(inInfo)); dbScript = dbScript.concat(self._addScript(inInfo));
return each_cb(); return each_cb();
}); });
}, },
function(err) { function(err) {
if (err) return next(err); if (err) return next(err);
@ -661,10 +673,10 @@ TransactionDb.prototype._addManyFromHashes = function(txs, next) {
TransactionDb.prototype.addMany = function(txs, next) { TransactionDb.prototype.addMany = function(txs, next) {
if (!txs) return next(); if (!txs) return next();
var fn = (typeof txs[0] ==='string') ? var fn = (typeof txs[0] === 'string') ?
this._addManyFromHashes : this._addManyFromObjs; 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) if (txInfo && txInfo.isCoinBase)
ret = self.poolMatch.match(new Buffer(txInfo.vin[0].coinbase, 'hex')); ret = self.poolMatch.match(new Buffer(txInfo.vin[0].coinbase, 'hex'));
return cb(ret); return cb(ret);
}); });
}; };
@ -685,16 +697,16 @@ TransactionDb.prototype.getPoolInfo = function(txid, cb) {
TransactionDb.prototype.checkVersion02 = function(cb) { TransactionDb.prototype.checkVersion02 = function(cb) {
var k = 'txa-'; var k = 'txa-';
var isV2=1; var isV2 = 1;
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: k + '~', end: k + '~',
limit: 1, limit: 1,
}) })
.on('data', function(data) { .on('data', function(data) {
isV2=0; isV2 = 0;
}) })
.on('end', function (){ .on('end', function() {
return cb(isV2); return cb(isV2);
}); });
}; };
@ -702,9 +714,9 @@ TransactionDb.prototype.checkVersion02 = function(cb) {
TransactionDb.prototype.migrateV02 = function(cb) { TransactionDb.prototype.migrateV02 = function(cb) {
var k = 'txa-'; var k = 'txa-';
var dbScript = []; var dbScript = [];
var c=0; var c = 0;
var c2=0; var c2 = 0;
var N=50000; var N = 50000;
db.createReadStream({ db.createReadStream({
start: k, start: k,
end: k + '~' end: k + '~'
@ -714,22 +726,21 @@ TransactionDb.prototype.migrateV02 = function(cb) {
var v = data.value.split(':'); var v = data.value.split(':');
dbScript.push({ dbScript.push({
type: 'put', type: 'put',
key: ADDR_PREFIX + k[1] + '-' + (END_OF_WORLD_TS - parseInt(v[1])) key: ADDR_PREFIX + k[1] + '-' + (END_OF_WORLD_TS - parseInt(v[1])) + '-' + k[2] + '-' + k[3],
+ '-' + k[2] + '-' + k[3],
value: v[0], value: v[0],
}); });
if (c++>N) { if (c++ > N) {
console.log('\t%dM txs outs processed', ((c2+=N)/1e6).toFixed(3)); //TODO console.log('\t%dM txs outs processed', ((c2 += N) / 1e6).toFixed(3)); //TODO
db.batch(dbScript,function () { db.batch(dbScript, function() {
c=0; c = 0;
dbScript=[]; dbScript = [];
}); });
} }
}) })
.on('error', function(err) { .on('error', function(err) {
return cb(err); return cb(err);
}) })
.on('end', function (){ .on('end', function() {
return cb(); return cb();
}); });
}; };

View File

@ -80,7 +80,7 @@
"grunt-nodemon": "~0.2.0", "grunt-nodemon": "~0.2.0",
"grunt-mocha-test": "~0.8.1", "grunt-mocha-test": "~0.8.1",
"should": "2.1.1", "should": "2.1.1",
"chai": "=1.9.1", "chai": "*",
"grunt-markdown": "~0.5.0" "grunt-markdown": "~0.5.0"
} }
} }

View File

@ -28,8 +28,7 @@ describe('PeerSync', function() {
it('should return with no errors', function() { it('should return with no errors', function() {
expect(function() { expect(function() {
ps.handleInv(inv_info); ps.handleInv(inv_info);
}).not.to. }).not.to.throw(Error);
throw (Error);
}); });
it('should call sendGetData', function() { it('should call sendGetData', function() {
ps.handleInv(inv_info); ps.handleInv(inv_info);

19
test/test.MessageDb.js Normal file
View File

@ -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();
});
});
});