insight with soop. WIP

This commit is contained in:
Matias Alejo Garcia 2014-03-05 23:03:56 -03:00
parent 1af6bb7a02
commit e19cd9f2ba
15 changed files with 2080 additions and 2138 deletions

View File

@ -7,9 +7,9 @@ var Address = require('../models/Address');
var async = require('async'); var async = require('async');
var common = require('./common'); var common = require('./common');
var TransactionDb = require('../../lib/TransactionDb').class(); var Rpc = require('../../lib/Rpc');
var BlockDb = require('../../lib/BlockDb').class(); var TransactionDb = require('../../lib/TransactionDb').default();
var Rpc = require('../../lib/Rpc').class(); var BlockDb = require('../../lib/BlockDb').default();
var tDb = new TransactionDb(); var tDb = new TransactionDb();
var bdb = new BlockDb(); var bdb = new BlockDb();

View File

@ -1,19 +1,16 @@
'use strict'; 'use strict';
require('classtool'); //var imports = require('soop').imports();
var async = require('async');
var BitcoreAddress = require('bitcore/Address');
var BitcoreTransaction = require('bitcore/Transaction');
var BitcoreUtil = require('bitcore/util/util');
var Parser = require('bitcore/util/BinaryParser');
var Buffer = require('buffer').Buffer;
var TransactionDb = require('../../lib/TransactionDb').default();
var CONCURRENCY = 5;
function Address(addrStr) {
function spec() {
var async = require('async');
var BitcoreAddress = require('bitcore/Address').class();
var BitcoreUtil = require('bitcore/util/util');
var TransactionDb = require('../../lib/TransactionDb').class();
var BitcoreTransaction = require('bitcore/Transaction').class();
var Parser = require('bitcore/util/BinaryParser').class();
var Buffer = require('buffer').Buffer;
var CONCURRENCY = 5;
function Address(addrStr) {
this.balanceSat = 0; this.balanceSat = 0;
this.totalReceivedSat = 0; this.totalReceivedSat = 0;
this.totalSentSat = 0; this.totalSentSat = 0;
@ -71,18 +68,18 @@ function spec() {
enumerable: 1, enumerable: 1,
}); });
} }
Address.prototype._getScriptPubKey = function(hex,n) { Address.prototype._getScriptPubKey = function(hex,n) {
// ScriptPubKey is not provided by bitcoind RPC, so we parse it from tx hex. // ScriptPubKey is not provided by bitcoind RPC, so we parse it from tx hex.
var parser = new Parser(new Buffer(hex,'hex')); var parser = new Parser(new Buffer(hex,'hex'));
var tx = new BitcoreTransaction(); var tx = new BitcoreTransaction();
tx.parse(parser); tx.parse(parser);
return (tx.outs[n].s.toString('hex')); return (tx.outs[n].s.toString('hex'));
}; };
Address.prototype.getUtxo = function(next) { Address.prototype.getUtxo = function(next) {
var self = this; var self = this;
if (!self.addrStr) return next(); if (!self.addrStr) return next();
@ -117,9 +114,9 @@ function spec() {
return next(err,ret); return next(err,ret);
}); });
}); });
}; };
Address.prototype.update = function(next) { Address.prototype.update = function(next) {
var self = this; var self = this;
if (!self.addrStr) return next(); if (!self.addrStr) return next();
@ -186,9 +183,7 @@ function spec() {
self.transactions = txs.map(function(i) { return i.txid; } ); self.transactions = txs.map(function(i) { return i.txid; } );
return next(err); return next(err);
}); });
}; };
return Address; module.exports = require('soop')(Address);
}
module.defineClass(spec);

View File

@ -1,19 +1,17 @@
'use strict'; 'use strict';
//var imports = require('soop').imports();
require('classtool'); var async = require('async');
var RpcClient = require('bitcore/RpcClient');
var BlockDb = require('../../lib/BlockDb');
var config = require('../../config/config');
var rpc = new RpcClient(config.bitcoind);
function spec() { function Status() {
var async = require('async');
var RpcClient = require('bitcore/RpcClient').class();
var BlockDb = require('../../lib/BlockDb').class();
var config = require('../../config/config');
var rpc = new RpcClient(config.bitcoind);
function Status() {
this.bDb = new BlockDb(); this.bDb = new BlockDb();
} }
Status.prototype.getInfo = function(next) { Status.prototype.getInfo = function(next) {
var that = this; var that = this;
async.series([ async.series([
function (cb) { function (cb) {
@ -27,9 +25,9 @@ function spec() {
], function (err) { ], function (err) {
return next(err); return next(err);
}); });
}; };
Status.prototype.getDifficulty = function(next) { Status.prototype.getDifficulty = function(next) {
var that = this; var that = this;
async.series([ async.series([
function (cb) { function (cb) {
@ -43,9 +41,9 @@ function spec() {
], function (err) { ], function (err) {
return next(err); return next(err);
}); });
}; };
Status.prototype.getTxOutSetInfo = function(next) { Status.prototype.getTxOutSetInfo = function(next) {
var that = this; var that = this;
async.series([ async.series([
function (cb) { function (cb) {
@ -59,9 +57,9 @@ function spec() {
], function (err) { ], function (err) {
return next(err); return next(err);
}); });
}; };
Status.prototype.getBestBlockHash = function(next) { Status.prototype.getBestBlockHash = function(next) {
var that = this; var that = this;
async.series([ async.series([
function (cb) { function (cb) {
@ -76,9 +74,9 @@ function spec() {
], function (err) { ], function (err) {
return next(err); return next(err);
}); });
}; };
Status.prototype.getLastBlockHash = function(next) { Status.prototype.getLastBlockHash = function(next) {
var that = this; var that = this;
that.bDb.getTip(function(err,tip) { that.bDb.getTip(function(err,tip) {
that.syncTipHash = tip; that.syncTipHash = tip;
@ -103,10 +101,6 @@ function spec() {
} }
); );
}); });
}; };
return Status;
}
module.defineClass(spec);
module.exports = require('soop')(Status);

View File

@ -5,7 +5,7 @@ var util = require('util');
process.env.NODE_ENV = process.env.NODE_ENV || 'development'; process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var RpcClient = require('../node_modules/bitcore/RpcClient').class(); var RpcClient = require('../node_modules/bitcore/RpcClient');
var config = require('../config/config'); var config = require('../config/config');

View File

@ -2,7 +2,7 @@
'use strict'; 'use strict';
var util = require('util'); var util = require('util');
var T = require('../lib/TransactionDb').class(); var T = require('../lib/TransactionDb');
process.env.NODE_ENV = process.env.NODE_ENV || 'development'; process.env.NODE_ENV = process.env.NODE_ENV || 'development';

View File

@ -1,44 +1,39 @@
'use strict'; 'use strict';
var imports = require('soop').imports();
var parent = imports.parent || require('events').EventEmitter;
var TIMESTAMP_PREFIX = 'bts-'; // b-ts-<ts> => <hash>
var PREV_PREFIX = 'bpr-'; // b-prev-<hash> => <prev_hash>
var NEXT_PREFIX = 'bne-'; // b-next-<hash> => <next_hash>
var MAIN_PREFIX = 'bma-'; // b-main-<hash> => 1/0
var TIP = 'bti-'; // last block on the chain
var LAST_FILE_INDEX = 'file-'; // last processed file index
require('classtool'); var MAX_OPEN_FILES = 500;
function spec(b) { /**
* Module dependencies.
var superclass = b.superclass || require('events').EventEmitter; */
var TIMESTAMP_PREFIX = 'bts-'; // b-ts-<ts> => <hash> var levelup = require('levelup'),
var PREV_PREFIX = 'bpr-'; // b-prev-<hash> => <prev_hash>
var NEXT_PREFIX = 'bne-'; // b-next-<hash> => <next_hash>
var MAIN_PREFIX = 'bma-'; // b-main-<hash> => 1/0
var TIP = 'bti-'; // last block on the chain
var LAST_FILE_INDEX = 'file-'; // last processed file index
var MAX_OPEN_FILES = 500;
/**
* Module dependencies.
*/
var levelup = require('levelup'),
config = require('../config/config'); config = require('../config/config');
var db = b.db || levelup(config.leveldb + '/blocks',{maxOpenFiles: MAX_OPEN_FILES} ); var db = imports.db || levelup(config.leveldb + '/blocks',{maxOpenFiles: MAX_OPEN_FILES} );
var Rpc = b.rpc || require('./Rpc').class(); var Rpc = imports.rpc || require('./Rpc');
var PoolMatch = b.poolMatch || require('./PoolMatch').class(config); var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch',config);
var TransactionDb = require('./TransactionDb.js').class(); var TransactionDb = require('./TransactionDb.js').default();
var BlockDb = function() { var BlockDb = function() {
BlockDb.super(this, arguments); BlockDb.super(this, arguments);
this.poolMatch = new PoolMatch(); this.poolMatch = new PoolMatch();
}; };
BlockDb.superclass = superclass; BlockDb.parent = parent;
BlockDb.prototype.close = function(cb) { BlockDb.prototype.close = function(cb) {
db.close(cb); db.close(cb);
}; };
BlockDb.prototype.drop = function(cb) { BlockDb.prototype.drop = function(cb) {
var path = config.leveldb + '/blocks'; var path = config.leveldb + '/blocks';
db.close(function() { db.close(function() {
require('leveldown').destroy(path, function () { require('leveldown').destroy(path, function () {
@ -46,12 +41,12 @@ function spec(b) {
return cb(); return cb();
}); });
}); });
}; };
// adds a block. Does not update Next pointer in // adds a block. Does not update Next pointer in
// the block prev to the new block, nor TIP pointer // the block prev to the new block, nor TIP pointer
// //
BlockDb.prototype.add = function(b, cb) { BlockDb.prototype.add = function(b, cb) {
var self = this; var self = this;
var time_key = TIMESTAMP_PREFIX + var time_key = TIMESTAMP_PREFIX +
( b.time || Math.round(new Date().getTime() / 1000) ); ( b.time || Math.round(new Date().getTime() / 1000) );
@ -66,36 +61,36 @@ function spec(b) {
} }
cb(err); cb(err);
}); });
}; };
BlockDb.prototype.getTip = function(cb) { BlockDb.prototype.getTip = function(cb) {
db.get(TIP, function(err, val) { db.get(TIP, function(err, val) {
return cb(err,val); return cb(err,val);
}); });
}; };
BlockDb.prototype.setTip = function(hash, cb) { BlockDb.prototype.setTip = function(hash, cb) {
db.put(TIP, hash, function(err) { db.put(TIP, hash, function(err) {
return cb(err); return cb(err);
}); });
}; };
//mainly for testing //mainly for testing
BlockDb.prototype.setPrev = function(hash, prevHash, cb) { BlockDb.prototype.setPrev = function(hash, prevHash, cb) {
db.put(PREV_PREFIX + hash, prevHash, function(err) { db.put(PREV_PREFIX + hash, prevHash, function(err) {
return cb(err); return cb(err);
}); });
}; };
BlockDb.prototype.getPrev = function(hash, cb) { BlockDb.prototype.getPrev = function(hash, cb) {
db.get(PREV_PREFIX + hash, function(err,val) { db.get(PREV_PREFIX + hash, function(err,val) {
if (err && err.notFound) { err = null; val = null;} if (err && err.notFound) { err = null; val = null;}
return cb(err,val); return cb(err,val);
}); });
}; };
BlockDb.prototype.setLastFileIndex = function(idx, cb) { BlockDb.prototype.setLastFileIndex = function(idx, cb) {
var self = this; var self = this;
if (this.lastFileIndexSaved === idx) return cb(); if (this.lastFileIndexSaved === idx) return cb();
@ -103,42 +98,42 @@ function spec(b) {
self.lastFileIndexSaved = idx; self.lastFileIndexSaved = idx;
return cb(err); return cb(err);
}); });
}; };
BlockDb.prototype.getLastFileIndex = function(cb) { BlockDb.prototype.getLastFileIndex = function(cb) {
db.get(LAST_FILE_INDEX, function(err,val) { db.get(LAST_FILE_INDEX, function(err,val) {
if (err && err.notFound) { err = null; val = null;} if (err && err.notFound) { err = null; val = null;}
return cb(err,val); return cb(err,val);
}); });
}; };
BlockDb.prototype.getNext = function(hash, cb) { BlockDb.prototype.getNext = function(hash, cb) {
db.get(NEXT_PREFIX + hash, function(err,val) { db.get(NEXT_PREFIX + hash, function(err,val) {
if (err && err.notFound) { err = null; val = null;} if (err && err.notFound) { err = null; val = null;}
return cb(err,val); return cb(err,val);
}); });
}; };
BlockDb.prototype.isMain = function(hash, cb) { BlockDb.prototype.isMain = function(hash, cb) {
db.get(MAIN_PREFIX + hash, function(err, val) { db.get(MAIN_PREFIX + hash, function(err, val) {
if (err && err.notFound) { err = null; val = 0;} if (err && err.notFound) { err = null; val = 0;}
return cb(err,parseInt(val)); return cb(err,parseInt(val));
}); });
}; };
BlockDb.prototype.setMain = function(hash, isMain, cb) { BlockDb.prototype.setMain = function(hash, isMain, cb) {
if (!isMain) console.log('\tNew orphan: %s',hash); if (!isMain) console.log('\tNew orphan: %s',hash);
db.put(MAIN_PREFIX + hash, isMain?1:0, function(err) { db.put(MAIN_PREFIX + hash, isMain?1:0, function(err) {
return cb(err); return cb(err);
}); });
}; };
BlockDb.prototype.setNext = function(hash, nextHash, cb) { BlockDb.prototype.setNext = function(hash, nextHash, cb) {
db.put(NEXT_PREFIX + hash, nextHash, function(err) { db.put(NEXT_PREFIX + hash, nextHash, function(err) {
return cb(err); return cb(err);
}); });
}; };
BlockDb.prototype.countConnected = function(cb) { BlockDb.prototype.countConnected = function(cb) {
var c = 0; var c = 0;
console.log('Counting connected blocks. This could take some minutes'); console.log('Counting connected blocks. This could take some minutes');
db.createReadStream({start: MAIN_PREFIX, end: MAIN_PREFIX + '~' }) db.createReadStream({start: MAIN_PREFIX, end: MAIN_PREFIX + '~' })
@ -151,10 +146,10 @@ function spec(b) {
.on('end', function () { .on('end', function () {
return cb(null, c); return cb(null, c);
}); });
}; };
// .has() return true orphans also // .has() return true orphans also
BlockDb.prototype.has = function(hash, cb) { BlockDb.prototype.has = function(hash, cb) {
var k = PREV_PREFIX + hash; var k = PREV_PREFIX + hash;
db.get(k, function (err) { db.get(k, function (err) {
var ret = true; var ret = true;
@ -164,9 +159,9 @@ function spec(b) {
} }
return cb(err, ret); return cb(err, ret);
}); });
}; };
BlockDb.prototype.getPoolInfo = function(tx, cb) { BlockDb.prototype.getPoolInfo = function(tx, cb) {
var tr = new TransactionDb(); var tr = new TransactionDb();
var self = this; var self = this;
@ -180,9 +175,9 @@ function spec(b) {
return cb(aa); return cb(aa);
} }
}); });
}; };
BlockDb.prototype.fromHashWithInfo = function(hash, cb) { BlockDb.prototype.fromHashWithInfo = function(hash, cb) {
var self = this; var self = this;
Rpc.getBlock(hash, function(err, info) { Rpc.getBlock(hash, function(err, info) {
@ -199,9 +194,9 @@ function spec(b) {
}); });
}); });
}); });
}; };
BlockDb.prototype.getBlocksByDate = function(start_ts, end_ts, cb) { BlockDb.prototype.getBlocksByDate = function(start_ts, end_ts, cb) {
var list = []; var list = [];
db.createReadStream({ db.createReadStream({
start: TIMESTAMP_PREFIX + start_ts, start: TIMESTAMP_PREFIX + start_ts,
@ -221,14 +216,10 @@ function spec(b) {
.on('end', function () { .on('end', function () {
return cb(null, list.reverse()); return cb(null, list.reverse());
}); });
}; };
BlockDb.prototype.blockIndex = function(height, cb) { BlockDb.prototype.blockIndex = function(height, cb) {
return Rpc.blockIndex(height,cb); return Rpc.blockIndex(height,cb);
}; };
return BlockDb;
}
module.defineClass(spec);
module.exports = require('soop')(BlockDb);

View File

@ -1,18 +1,13 @@
'use strict'; 'use strict';
var Block = require('bitcore/Block'),
require('classtool');
function spec() {
var Block = require('bitcore/Block').class(),
networks = require('bitcore/networks'), networks = require('bitcore/networks'),
Parser = require('bitcore/util/BinaryParser').class(), Parser = require('bitcore/util/BinaryParser'),
fs = require('fs'), fs = require('fs'),
Buffer = require('buffer').Buffer, Buffer = require('buffer').Buffer,
glob = require('glob'), glob = require('glob'),
async = require('async'); async = require('async');
function BlockExtractor(dataDir, network) { function BlockExtractor(dataDir, network) {
var self = this; var self = this;
var path = dataDir + '/blocks/blk*.dat'; var path = dataDir + '/blocks/blk*.dat';
@ -30,16 +25,16 @@ function spec() {
self.currentParser = null; self.currentParser = null;
self.network = network === 'testnet' ? networks.testnet: networks.livenet; self.network = network === 'testnet' ? networks.testnet: networks.livenet;
self.magic = self.network.magic.toString('hex'); self.magic = self.network.magic.toString('hex');
} }
BlockExtractor.prototype.currentFile = function() { BlockExtractor.prototype.currentFile = function() {
var self = this; var self = this;
return self.files[self.currentFileIndex]; return self.files[self.currentFileIndex];
}; };
BlockExtractor.prototype.nextFile = function() { BlockExtractor.prototype.nextFile = function() {
var self = this; var self = this;
if (self.currentFileIndex < 0) return false; if (self.currentFileIndex < 0) return false;
@ -58,9 +53,9 @@ function spec() {
ret = false; ret = false;
} }
return ret; return ret;
}; };
BlockExtractor.prototype.readCurrentFileSync = function() { BlockExtractor.prototype.readCurrentFileSync = function() {
var self = this; var self = this;
if (self.currentFileIndex < 0 || self.isCurrentRead) return; if (self.currentFileIndex < 0 || self.isCurrentRead) return;
@ -87,11 +82,11 @@ function spec() {
self.currentBuffer = buffer; self.currentBuffer = buffer;
self.currentParser = new Parser(buffer); self.currentParser = new Parser(buffer);
}; };
BlockExtractor.prototype.getNextBlock = function(cb) { BlockExtractor.prototype.getNextBlock = function(cb) {
var self = this; var self = this;
var b; var b;
@ -154,9 +149,7 @@ function spec() {
], function(err) { ], function(err) {
return cb(err,b); return cb(err,b);
}); });
}; };
return BlockExtractor; module.exports = require('soop')(BlockExtractor);
}
module.defineClass(spec);

View File

@ -1,30 +1,27 @@
'use strict'; 'use strict';
require('classtool'); var imports = require('soop').imports();
var util = require('util');
var assert = require('assert');
var RpcClient = require('bitcore/RpcClient');
var Script = require('bitcore/Script');
var networks = require('bitcore/networks');
var async = require('async');
var config = require('../config/config');
var Sync = require('./Sync');
var sockets = require('../app/controllers/socket.js');
var BlockExtractor = require('./BlockExtractor.js');
var buffertools = require('buffertools');
// var bitcoreUtil = require('bitcore/util/util');
// var Deserialize = require('bitcore/Deserialize');
var BAD_GEN_ERROR = 'Bad genesis block. Network mismatch between Insight and bitcoind? Insight is configured for:';
function spec() { var BAD_GEN_ERROR_DB = 'Bad genesis block. Network mismatch between Insight and levelDB? Insight is configured for:';
var util = require('util'); function HistoricSync(opts) {
var assert = require('assert');
var RpcClient = require('bitcore/RpcClient').class();
var Script = require('bitcore/Script').class();
var networks = require('bitcore/networks');
var async = require('async');
var config = require('../config/config');
var Sync = require('./Sync').class();
var sockets = require('../app/controllers/socket.js');
var BlockExtractor = require('./BlockExtractor.js').class();
var buffertools = require('buffertools');
// var bitcoreUtil = require('bitcore/util/util');
// var Deserialize = require('bitcore/Deserialize');
var BAD_GEN_ERROR = 'Bad genesis block. Network mismatch between Insight and bitcoind? Insight is configured for:';
var BAD_GEN_ERROR_DB = 'Bad genesis block. Network mismatch between Insight and levelDB? Insight is configured for:';
function HistoricSync(opts) {
opts = opts || {}; opts = opts || {};
this.network = config.network === 'testnet' ? networks.testnet: networks.livenet; this.network = config.network === 'testnet' ? networks.testnet: networks.livenet;
@ -37,18 +34,18 @@ function spec() {
this.rpc = new RpcClient(config.bitcoind); this.rpc = new RpcClient(config.bitcoind);
this.shouldBroadcast = opts.shouldBroadcastSync; this.shouldBroadcast = opts.shouldBroadcastSync;
this.sync = new Sync(opts); this.sync = new Sync(opts);
} }
function p() { function p() {
var args = []; var args = [];
Array.prototype.push.apply(args, arguments); Array.prototype.push.apply(args, arguments);
args.unshift('[historic_sync]'); args.unshift('[historic_sync]');
/*jshint validthis:true */ /*jshint validthis:true */
console.log.apply(this, args); console.log.apply(this, args);
} }
HistoricSync.prototype.showProgress = function() { HistoricSync.prototype.showProgress = function() {
var self = this; var self = this;
if ( self.status ==='syncing' && if ( self.status ==='syncing' &&
@ -65,28 +62,28 @@ function spec() {
sockets.broadcastSyncInfo(self.info()); sockets.broadcastSyncInfo(self.info());
} }
// if (self.syncPercentage > 10) { // if (self.syncPercentage > 10) {
// process.exit(-1); // process.exit(-1);
// } // }
}; };
HistoricSync.prototype.setError = function(err) { HistoricSync.prototype.setError = function(err) {
var self = this; var self = this;
self.error = err.message?err.message:err.toString(); self.error = err.message?err.message:err.toString();
self.status='error'; self.status='error';
self.showProgress(); self.showProgress();
return err; return err;
}; };
HistoricSync.prototype.close = function() { HistoricSync.prototype.close = function() {
this.sync.close(); this.sync.close();
}; };
HistoricSync.prototype.info = function() { HistoricSync.prototype.info = function() {
this.updatePercentage(); this.updatePercentage();
return { return {
status: this.status, status: this.status,
@ -99,15 +96,15 @@ function spec() {
startTs: this.startTs, startTs: this.startTs,
endTs: this.endTs, endTs: this.endTs,
}; };
}; };
HistoricSync.prototype.updatePercentage = function() { HistoricSync.prototype.updatePercentage = function() {
var r = this.syncedBlocks / this.blockChainHeight; var r = this.syncedBlocks / this.blockChainHeight;
this.syncPercentage = parseFloat(100 * r).toFixed(3); this.syncPercentage = parseFloat(100 * r).toFixed(3);
if (this.syncPercentage > 100) this.syncPercentage = 100; if (this.syncPercentage > 100) this.syncPercentage = 100;
}; };
HistoricSync.prototype.getBlockFromRPC = function(cb) { HistoricSync.prototype.getBlockFromRPC = function(cb) {
var self = this; var self = this;
if (!self.currentRpcHash) return cb(); if (!self.currentRpcHash) return cb();
@ -129,9 +126,9 @@ function spec() {
} }
return cb(null, blockInfo); return cb(null, blockInfo);
}); });
}; };
HistoricSync.prototype.getBlockFromFile = function(cb) { HistoricSync.prototype.getBlockFromFile = function(cb) {
var self = this; var self = this;
var blockInfo; var blockInfo;
@ -170,29 +167,29 @@ function spec() {
return cb(err,blockInfo); return cb(err,blockInfo);
}); });
}); });
}; };
HistoricSync.prototype.updateConnectedCountDB = function(cb) { HistoricSync.prototype.updateConnectedCountDB = function(cb) {
var self = this; var self = this;
self.sync.bDb.countConnected(function(err, count) { self.sync.bDb.countConnected(function(err, count) {
self.connectedCountDB = count || 0; self.connectedCountDB = count || 0;
self.syncedBlocks = count || 0; self.syncedBlocks = count || 0;
return cb(err); return cb(err);
}); });
}; };
HistoricSync.prototype.updateBlockChainHeight = function(cb) { HistoricSync.prototype.updateBlockChainHeight = function(cb) {
var self = this; var self = this;
self.rpc.getBlockCount(function(err, res) { self.rpc.getBlockCount(function(err, res) {
self.blockChainHeight = res.result; self.blockChainHeight = res.result;
return cb(err); return cb(err);
}); });
}; };
HistoricSync.prototype.checkNetworkSettings = function(next) { HistoricSync.prototype.checkNetworkSettings = function(next) {
var self = this; var self = this;
self.hasGenesis = false; self.hasGenesis = false;
@ -211,9 +208,9 @@ function spec() {
return next(err); return next(err);
}); });
}); });
}; };
HistoricSync.prototype.updateStartBlock = function(next) { HistoricSync.prototype.updateStartBlock = function(next) {
var self = this; var self = this;
self.startBlock = self.genesis; self.startBlock = self.genesis;
@ -258,9 +255,9 @@ function spec() {
} }
); );
}); });
}; };
HistoricSync.prototype.prepareFileSync = function(opts, next) { HistoricSync.prototype.prepareFileSync = function(opts, next) {
var self = this; var self = this;
if ( opts.forceRPC || !config.bitcoind.dataDir || if ( opts.forceRPC || !config.bitcoind.dataDir ||
@ -299,10 +296,10 @@ function spec() {
}); });
}, next); }, next);
}); });
}; };
//NOP //NOP
HistoricSync.prototype.prepareRpcSync = function(opts, next) { HistoricSync.prototype.prepareRpcSync = function(opts, next) {
var self = this; var self = this;
if (self.blockExtractor) return next(); if (self.blockExtractor) return next();
@ -310,9 +307,9 @@ function spec() {
self.currentRpcHash = self.startBlock; self.currentRpcHash = self.startBlock;
self.allowReorgs = false; self.allowReorgs = false;
return next(); return next();
}; };
HistoricSync.prototype.showSyncStartMessage = function() { HistoricSync.prototype.showSyncStartMessage = function() {
var self = this; var self = this;
p('Got ' + self.connectedCountDB + p('Got ' + self.connectedCountDB +
@ -328,10 +325,10 @@ function spec() {
p('Starting from: ', self.startBlock); p('Starting from: ', self.startBlock);
self.showProgress(); self.showProgress();
}; };
HistoricSync.prototype.setupSyncStatus = function() { HistoricSync.prototype.setupSyncStatus = function() {
var self = this; var self = this;
var step = parseInt( (self.blockChainHeight - self.syncedBlocks) / 1000); var step = parseInt( (self.blockChainHeight - self.syncedBlocks) / 1000);
@ -344,9 +341,9 @@ function spec() {
self.endTs = null; self.endTs = null;
this.error = null; this.error = null;
this.syncPercentage = 0; this.syncPercentage = 0;
}; };
HistoricSync.prototype.prepareToSync = function(opts, next) { HistoricSync.prototype.prepareToSync = function(opts, next) {
var self = this; var self = this;
self.status = 'starting'; self.status = 'starting';
@ -377,10 +374,10 @@ function spec() {
self.setupSyncStatus(); self.setupSyncStatus();
return next(); return next();
}); });
}; };
HistoricSync.prototype.start = function(opts, next) { HistoricSync.prototype.start = function(opts, next) {
var self = this; var self = this;
if (self.status==='starting' || self.status==='syncing') { if (self.status==='starting' || self.status==='syncing') {
@ -422,8 +419,6 @@ function spec() {
}); });
}, next); }, next);
}); });
}; };
return HistoricSync;
}
module.defineClass(spec);
module.exports = require('soop')(HistoricSync);

View File

@ -1,17 +1,14 @@
'use strict'; 'use strict';
require('classtool'); var fs = require('fs');
var bitcoreUtil = require('bitcore/util/util');
var Sync = require('./Sync');
var Peer = require('bitcore/Peer');
var config = require('../config/config');
var networks = require('bitcore/networks');
function spec() { var peerdb_fn = 'peerdb.json';
var fs = require('fs');
var bitcoreUtil = require('bitcore/util/util');
var Sync = require('./Sync').class();
var Peer = require('bitcore/Peer').class();
var config = require('../config/config');
var networks = require('bitcore/networks');
var peerdb_fn = 'peerdb.json'; function PeerSync(opts) {
function PeerSync(opts) {
this.connected = false; this.connected = false;
this.peerdb = undefined; this.peerdb = undefined;
this.allowReorgs = false; this.allowReorgs = false;
@ -21,31 +18,31 @@ function spec() {
this.peerman = new this.PeerManager(); this.peerman = new this.PeerManager();
this.load_peers(); this.load_peers();
this.sync = new Sync(opts); this.sync = new Sync(opts);
} }
PeerSync.prototype.load_peers = function() { PeerSync.prototype.load_peers = function() {
this.peerdb = [{ this.peerdb = [{
ipv4: config.bitcoind.host, ipv4: config.bitcoind.host,
port: config.bitcoind.p2pPort port: config.bitcoind.p2pPort
}]; }];
fs.writeFileSync(peerdb_fn, JSON.stringify(this.peerdb)); fs.writeFileSync(peerdb_fn, JSON.stringify(this.peerdb));
}; };
PeerSync.prototype.info = function() { PeerSync.prototype.info = function() {
return { return {
connected: this.connected, connected: this.connected,
host: this.peerdb[0].ipv4, host: this.peerdb[0].ipv4,
port: this.peerdb[0].port port: this.peerdb[0].port
}; };
}; };
PeerSync.prototype.handleInv = function(info) { PeerSync.prototype.handleInv = function(info) {
var invs = info.message.invs; var invs = info.message.invs;
info.conn.sendGetData(invs); info.conn.sendGetData(invs);
}; };
PeerSync.prototype.handleTx = function(info) { PeerSync.prototype.handleTx = function(info) {
var tx = info.message.tx.getStandardizedObject(); var tx = info.message.tx.getStandardizedObject();
tx.outs = info.message.tx.outs; tx.outs = info.message.tx.outs;
tx.ins = info.message.tx.ins; tx.ins = info.message.tx.ins;
@ -57,9 +54,9 @@ function spec() {
console.log('[p2p_sync] Error in handle TX: ' + JSON.stringify(err)); console.log('[p2p_sync] Error in handle TX: ' + JSON.stringify(err));
} }
}); });
}; };
PeerSync.prototype.handleBlock = function(info) { PeerSync.prototype.handleBlock = function(info) {
var self = this; var self = this;
var block = info.message.block; var block = info.message.block;
var blockHash = bitcoreUtil.formatHashFull(block.calcHash()); var blockHash = bitcoreUtil.formatHashFull(block.calcHash());
@ -85,15 +82,15 @@ function spec() {
console.log('[p2p_sync] Error in handle Block: ' + err); console.log('[p2p_sync] Error in handle Block: ' + err);
} }
}); });
}; };
PeerSync.prototype.handle_connected = function(data) { PeerSync.prototype.handle_connected = function(data) {
var peerman = data.pm; var peerman = data.pm;
var peers_n = peerman.peers.length; var peers_n = peerman.peers.length;
console.log('[p2p_sync] Connected to ' + peers_n + ' peer' + (peers_n !== 1 ? 's' : '')); console.log('[p2p_sync] Connected to ' + peers_n + ' peer' + (peers_n !== 1 ? 's' : ''));
}; };
PeerSync.prototype.run = function() { PeerSync.prototype.run = function() {
var self = this; var self = this;
this.peerdb.forEach(function(datum) { this.peerdb.forEach(function(datum) {
@ -114,14 +111,11 @@ function spec() {
}); });
this.peerman.start(); this.peerman.start();
}; };
PeerSync.prototype.close = function() { PeerSync.prototype.close = function() {
this.sync.close(); this.sync.close();
}; };
return PeerSync; module.exports = require('soop')(PeerSync);
}
module.defineClass(spec);

View File

@ -1,14 +1,11 @@
'use strict'; 'use strict';
require('classtool'); var imports = require('soop').imports();
var fs = require('fs');
var buffertools = require('buffertools');
var db = imports.db || JSON.parse( fs.readFileSync(imports.poolMatchFile || './poolMatchFile.json'));
function spec(b) { var PoolMatch = function() {
var fs = require('fs');
var buffertools = require('buffertools');
var db = b.db || JSON.parse( fs.readFileSync(b.poolMatchFile || './poolMatchFile.json'));
var PoolMatch = function() {
var self = this; var self = this;
self.strings = {}; self.strings = {};
@ -20,19 +17,16 @@ function spec(b) {
}; };
}); });
}); });
}; };
PoolMatch.prototype.match = function(buffer) { PoolMatch.prototype.match = function(buffer) {
var self = this; var self = this;
for(var k in self.strings) { for(var k in self.strings) {
if (buffertools.indexOf(buffer, k) >= 0) { if (buffertools.indexOf(buffer, k) >= 0) {
return self.strings[k]; return self.strings[k];
} }
} }
}; };
return PoolMatch;
}
module.defineClass(spec);
module.exports = require('soop')(PoolMatch);

View File

@ -1,21 +1,19 @@
'use strict'; 'use strict';
require('classtool'); var imports = require('soop').imports();
var RpcClient = require('bitcore/RpcClient'),
function spec(b) { BitcoreBlock = require('bitcore/Block'),
var RpcClient = require('bitcore/RpcClient').class(),
BitcoreBlock = require('bitcore/Block').class(),
bitcoreUtil = require('bitcore/util/util'), bitcoreUtil = require('bitcore/util/util'),
util = require('util'), util = require('util'),
config = require('../config/config'); config = require('../config/config');
var bitcoreRpc = b.bitcoreRpc || new RpcClient(config.bitcoind); var bitcoreRpc = imports.bitcoreRpc || new RpcClient(config.bitcoind);
function Rpc() { function Rpc() {
} }
Rpc._parseTxResult = function(info) { Rpc._parseTxResult = function(info) {
var b = new Buffer(info.hex,'hex'); var b = new Buffer(info.hex,'hex');
// remove fields we dont need, to speed and adapt the information // remove fields we dont need, to speed and adapt the information
@ -39,10 +37,10 @@ function spec(b) {
info.size = b.length; info.size = b.length;
return info; return info;
}; };
Rpc.errMsg = function(err) { Rpc.errMsg = function(err) {
var e = err; var e = err;
e.message += util.format(' [Host: %s:%d User:%s Using password:%s]', e.message += util.format(' [Host: %s:%d User:%s Using password:%s]',
bitcoreRpc.host, bitcoreRpc.host,
@ -51,9 +49,9 @@ function spec(b) {
bitcoreRpc.pass?'yes':'no' bitcoreRpc.pass?'yes':'no'
); );
return e; return e;
}; };
Rpc.getTxInfo = function(txid, doNotParse, cb) { Rpc.getTxInfo = function(txid, doNotParse, cb) {
var self = this; var self = this;
if (typeof doNotParse === 'function') { if (typeof doNotParse === 'function') {
@ -69,19 +67,19 @@ function spec(b) {
var info = doNotParse ? txInfo.result : self._parseTxResult(txInfo.result); var info = doNotParse ? txInfo.result : self._parseTxResult(txInfo.result);
return cb(null,info); return cb(null,info);
}); });
}; };
Rpc.blockIndex = function(height, cb) { Rpc.blockIndex = function(height, cb) {
var self = this; var self = this;
bitcoreRpc.getBlockHash(height, function(err, bh){ bitcoreRpc.getBlockHash(height, function(err, bh){
if (err) return cb(self.errMsg(err)); if (err) return cb(self.errMsg(err));
cb(null, { blockHash: bh.result }); cb(null, { blockHash: bh.result });
}); });
}; };
Rpc.getBlock = function(hash, cb) { Rpc.getBlock = function(hash, cb) {
var self = this; var self = this;
bitcoreRpc.getBlock(hash, function(err,info) { bitcoreRpc.getBlock(hash, function(err,info) {
@ -95,9 +93,9 @@ function spec(b) {
return cb(err,info.result); return cb(err,info.result);
}); });
}; };
Rpc.sendRawTransaction = function(rawtx, cb) { Rpc.sendRawTransaction = function(rawtx, cb) {
var self = this; var self = this;
bitcoreRpc.sendRawTransaction(rawtx, function(err, txid) { bitcoreRpc.sendRawTransaction(rawtx, function(err, txid) {
if (err && err.code === -5) return cb(err); // transaction already in block chain if (err && err.code === -5) return cb(err); // transaction already in block chain
@ -105,10 +103,8 @@ function spec(b) {
return cb(err, txid.result); return cb(err, txid.result);
}); });
}; };
return Rpc; module.exports = require('soop')(Rpc);
}
module.defineClass(spec);

View File

@ -1,19 +1,16 @@
'use strict'; 'use strict';
require('classtool'); var imports = require('soop').imports();
var sockets = require('../app/controllers/socket.js');
var BlockDb = require('./BlockDb').default();
var TransactionDb = require('./TransactionDb').default();
var config = require('../config/config');
var networks = require('bitcore/networks');
var async = require('async');
function spec() { function Sync(opts) {
var sockets = require('../app/controllers/socket.js');
var BlockDb = require('./BlockDb').class();
var TransactionDb = require('./TransactionDb').class();
var config = require('../config/config');
var networks = require('bitcore/networks');
var async = require('async');
function Sync(opts) {
this.opts = opts || {}; this.opts = opts || {};
this.bDb = new BlockDb(opts); this.bDb = new BlockDb(opts);
this.txDb = new TransactionDb(opts); this.txDb = new TransactionDb(opts);
@ -21,17 +18,17 @@ function spec() {
this.txDb.on('new_tx', this.handleNewTx.bind(this)); this.txDb.on('new_tx', this.handleNewTx.bind(this));
this.bDb.on('new_block', this.handleNewBlock.bind(this)); this.bDb.on('new_block', this.handleNewBlock.bind(this));
this.network = config.network === 'testnet' ? networks.testnet : networks.livenet; this.network = config.network === 'testnet' ? networks.testnet : networks.livenet;
} }
Sync.prototype.close = function(cb) { Sync.prototype.close = function(cb) {
var self = this; var self = this;
self.txDb.close(function() { self.txDb.close(function() {
self.bDb.close(cb); self.bDb.close(cb);
}); });
}; };
Sync.prototype.destroy = function(next) { Sync.prototype.destroy = function(next) {
var self = this; var self = this;
async.series([ async.series([
@ -42,9 +39,9 @@ function spec() {
self.txDb.drop(b); self.txDb.drop(b);
}, },
], next); ], next);
}; };
/* /*
* Arrives a NEW block, which is the new TIP * Arrives a NEW block, which is the new TIP
* *
* Case 0) Simple case * Case 0) Simple case
@ -74,7 +71,7 @@ function spec() {
* *
*/ */
Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) { Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) {
if (typeof allowReorgs === 'function') { if (typeof allowReorgs === 'function') {
cb = allowReorgs; cb = allowReorgs;
@ -151,11 +148,11 @@ function spec() {
} }
return cb(err); return cb(err);
}); });
}; };
Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, cb) { Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, cb) {
var self = this; var self = this;
var orphanizeFrom; var orphanizeFrom;
@ -196,17 +193,17 @@ function spec() {
function(err) { function(err) {
return cb(err); return cb(err);
}); });
}; };
Sync.prototype.setBlockMain = function(hash, isMain, cb) { Sync.prototype.setBlockMain = function(hash, isMain, cb) {
var self = this; var self = this;
self.bDb.setMain(hash, isMain, function(err) { self.bDb.setMain(hash, isMain, function(err) {
if (err) return cb(err); if (err) return cb(err);
return self.txDb.handleBlockChange(hash, isMain, cb); return self.txDb.handleBlockChange(hash, isMain, cb);
}); });
}; };
Sync.prototype.setBranchOrphan = function(fromHash, cb) { Sync.prototype.setBranchOrphan = function(fromHash, cb) {
var self = this, var self = this,
hashInterator = fromHash; hashInterator = fromHash;
@ -223,9 +220,9 @@ function spec() {
}); });
}); });
}, cb); }, cb);
}; };
Sync.prototype.setBranchConnectedBackwards = function(fromHash, cb) { Sync.prototype.setBranchConnectedBackwards = function(fromHash, cb) {
var self = this, var self = this,
hashInterator = fromHash, hashInterator = fromHash,
lastHash = fromHash, lastHash = fromHash,
@ -254,36 +251,34 @@ function spec() {
return cb(err, hashInterator, lastHash); return cb(err, hashInterator, lastHash);
} }
); );
}; };
Sync.prototype.handleTxForAddress = function(data) { Sync.prototype.handleTxForAddress = function(data) {
if (this.opts.shouldBroadcast) { if (this.opts.shouldBroadcast) {
sockets.broadcastAddressTx(data.address, data.txid); sockets.broadcastAddressTx(data.address, data.txid);
} }
}; };
Sync.prototype.handleNewTx = function(data) { Sync.prototype.handleNewTx = function(data) {
if (this.opts.shouldBroadcast) { if (this.opts.shouldBroadcast) {
sockets.broadcastTx(data.tx); sockets.broadcastTx(data.tx);
} }
}; };
Sync.prototype.handleNewBlock = function(data) { Sync.prototype.handleNewBlock = function(data) {
if (this.opts.shouldBroadcast) { if (this.opts.shouldBroadcast) {
sockets.broadcastBlock(data.blockid); sockets.broadcastBlock(data.blockid);
} }
}; };
Sync.prototype.storeTxs = function(txs, cb) { Sync.prototype.storeTxs = function(txs, cb) {
var self = this; var self = this;
self.txDb.createFromArray(txs, null, function(err) { self.txDb.createFromArray(txs, null, function(err) {
if (err) return cb(err); if (err) return cb(err);
return cb(err); return cb(err);
}); });
}; };
return Sync; module.exports = require('soop')(Sync);
}
module.defineClass(spec);

View File

@ -1,66 +1,63 @@
'use strict'; 'use strict';
require('classtool'); var imports = require('soop').imports();
var parent = imports.parent || require('events').EventEmitter;
// blockHash -> txid mapping
var IN_BLK_PREFIX = 'txb-'; //txb-<txid>-<block> => 1/0 (connected or not)
function spec(b) { // Only for orphan blocks
var FROM_BLK_PREFIX = 'tx-'; //tx-<block>-<txid> => 1
var superclass = b.superclass || require('events').EventEmitter; // to show tx outs
// blockHash -> txid mapping var OUTS_PREFIX = 'txo-'; //txo-<txid>-<n> => [addr, btc_sat]
var IN_BLK_PREFIX = 'txb-'; //txb-<txid>-<block> => 1/0 (connected or not) var SPENT_PREFIX = 'txs-'; //txs-<txid(out)>-<n(out)>-<txid(in)>-<n(in)> = ts
// Only for orphan blocks // to sum up addr balance (only outs, spents are gotten later)
var FROM_BLK_PREFIX = 'tx-'; //tx-<block>-<txid> => 1 var ADDR_PREFIX = 'txa-'; //txa-<addr>-<txid>-<n> => + btc_sat:ts
// to show tx outs // TODO: use bitcore networks module
var OUTS_PREFIX = 'txo-'; //txo-<txid>-<n> => [addr, btc_sat] var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b';
var SPENT_PREFIX = 'txs-'; //txs-<txid(out)>-<n(out)>-<txid(in)>-<n(in)> = ts var CONCURRENCY = 10;
// to sum up addr balance (only outs, spents are gotten later) var MAX_OPEN_FILES = 500;
var ADDR_PREFIX = 'txa-'; //txa-<addr>-<txid>-<n> => + btc_sat:ts
// TODO: use bitcore networks module
var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b';
var CONCURRENCY = 10;
var MAX_OPEN_FILES = 500;
// var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend // var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend
/** /**
* Module dependencies. * Module dependencies.
*/ */
var Rpc = b.rpc || require('./Rpc').class(), var Rpc = imports.rpc || require('./Rpc'),
util = require('bitcore/util/util'), util = require('bitcore/util/util'),
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');
var db = b.db || levelup(config.leveldb + '/txs',{maxOpenFiles: MAX_OPEN_FILES} ); var db = imports.db || levelup(config.leveldb + '/txs',{maxOpenFiles: MAX_OPEN_FILES} );
var Script = require('bitcore/Script').class(); var Script = require('bitcore/Script');
// This is 0.1.2 => c++ version of base57-native // This is 0.1.2 = > c++ version of base57-native
var base58 = require('base58-native').base58Check; var base58 = require('base58-native').base58Check;
var encodedData = require('bitcore/util/EncodedData').class({ var encodedData = require('soop').load('bitcore/util/EncodedData',{
base58: base58 base58: base58
}); });
var versionedData = require('bitcore/util/VersionedData').class({ var versionedData= require('soop').load('bitcore/util/VersionedData',{
superclass: encodedData patent: encodedData
}); });
var Address = require('bitcore/Address').class({ var Address = require('soop').load('bitcore/Address',{
superclass: versionedData parent: versionedData
}); });
var bitutil = require('bitcore/util/util'); var bitutil = require('bitcore/util/util');
var networks = require('bitcore/networks'); var networks = require('bitcore/networks');
var TransactionDb = function() { var TransactionDb = function() {
TransactionDb.super(this, arguments); TransactionDb.super(this, arguments);
this.network = config.network === 'testnet' ? networks.testnet : networks.livenet; this.network = config.network === 'testnet' ? networks.testnet : networks.livenet;
}; };
TransactionDb.superclass = superclass; TransactionDb.parent = parent;
TransactionDb.prototype.close = function(cb) { TransactionDb.prototype.close = function(cb) {
db.close(cb); db.close(cb);
}; };
TransactionDb.prototype.drop = function(cb) { 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() {
@ -68,10 +65,10 @@ function spec(b) {
return cb(); return cb();
}); });
}); });
}; };
TransactionDb.prototype.has = function(txid, cb) { TransactionDb.prototype.has = function(txid, cb) {
var k = OUTS_PREFIX + txid; var k = OUTS_PREFIX + txid;
db.get(k, function(err, val) { db.get(k, function(err, val) {
@ -87,9 +84,9 @@ function spec(b) {
} }
return cb(err, ret); return cb(err, ret);
}); });
}; };
TransactionDb.prototype._addSpentInfo = function(r, txid, index, ts) { TransactionDb.prototype._addSpentInfo = function(r, txid, index, ts) {
if (r.spentTxId) { if (r.spentTxId) {
if (!r.multipleSpentAttempts) { if (!r.multipleSpentAttempts) {
r.multipleSpentAttempts = [{ r.multipleSpentAttempts = [{
@ -106,11 +103,11 @@ function spec(b) {
r.spentIndex = parseInt(index); r.spentIndex = parseInt(index);
r.spentTs = parseInt(ts); r.spentTs = parseInt(ts);
} }
}; };
// This is not used now // This is not used now
TransactionDb.prototype.fromTxId = function(txid, cb) { TransactionDb.prototype.fromTxId = function(txid, cb) {
var self = this; var self = this;
var k = OUTS_PREFIX + txid; var k = OUTS_PREFIX + txid;
var ret = []; var ret = [];
@ -158,10 +155,10 @@ function spec(b) {
return cb(err, ret); return cb(err, ret);
}); });
}); });
}; };
TransactionDb.prototype._fillSpent = function(info, cb) { TransactionDb.prototype._fillSpent = function(info, cb) {
var self = this; var self = this;
if (!info) return cb(); if (!info) return cb();
@ -181,10 +178,10 @@ function spec(b) {
.on('end', function(err) { .on('end', function(err) {
return cb(err); return cb(err);
}); });
}; };
TransactionDb.prototype._fillOutpoints = function(info, cb) { TransactionDb.prototype._fillOutpoints = function(info, cb) {
var self = this; var self = this;
if (!info || info.isCoinBase) return cb(); if (!info || info.isCoinBase) return cb();
@ -210,9 +207,9 @@ function spec(b) {
valueIn += i.valueSat; valueIn += i.valueSat;
/* /*
* If confirmed by bitcoind, we could not check for double spents * If confirmed by bitcoind, we could not check for double spents
* but we prefer to keep the flag of double spent attempt * but we prefer to keep the flag of double spent attempt
* *
if (info.confirmations if (info.confirmations
&& info.confirmations >= CONFIRMATION_NR_TO_NOT_CHECK) && info.confirmations >= CONFIRMATION_NR_TO_NOT_CHECK)
return c_in(); return c_in();
@ -250,9 +247,9 @@ isspent
} }
return cb(); return cb();
}); });
}; };
TransactionDb.prototype._getInfo = function(txid, next) { TransactionDb.prototype._getInfo = function(txid, next) {
var self = this; var self = this;
Rpc.getTxInfo(txid, function(err, info) { Rpc.getTxInfo(txid, function(err, info) {
@ -264,19 +261,19 @@ isspent
}); });
}); });
}); });
}; };
// Simplified / faster Info version: No spent / outpoints info. // Simplified / faster Info version: No spent / outpoints info.
TransactionDb.prototype.fromIdInfoSimple = function(txid, cb) { TransactionDb.prototype.fromIdInfoSimple = function(txid, cb) {
Rpc.getTxInfo(txid, true, function(err, info) { Rpc.getTxInfo(txid, true, function(err, info) {
if (err) return cb(err); if (err) return cb(err);
if (!info) return cb(); if (!info) return cb();
return cb(err, info); return cb(err, info);
}); });
}; };
TransactionDb.prototype.fromIdWithInfo = function(txid, cb) { TransactionDb.prototype.fromIdWithInfo = function(txid, cb) {
var self = this; var self = this;
self._getInfo(txid, function(err, info) { self._getInfo(txid, function(err, info) {
@ -287,9 +284,9 @@ isspent
info: info info: info
}); });
}); });
}; };
TransactionDb.prototype.fromTxIdN = function(txid, n, confirmations, cb) { TransactionDb.prototype.fromTxIdN = function(txid, n, confirmations, cb) {
var self = this; var self = this;
var k = OUTS_PREFIX + txid + '-' + n; var k = OUTS_PREFIX + txid + '-' + n;
@ -335,9 +332,9 @@ isspent
return cb(null, ret); return cb(null, ret);
}); });
}); });
}; };
TransactionDb.prototype.fillConfirmations = function(o, cb) { TransactionDb.prototype.fillConfirmations = function(o, cb) {
var self = this; var self = this;
self.isConfirmed(o.txid, function(err, is) { self.isConfirmed(o.txid, function(err, is) {
@ -368,9 +365,9 @@ isspent
}); });
} }
}); });
}; };
TransactionDb.prototype.fromAddr = function(addr, cb) { TransactionDb.prototype.fromAddr = function(addr, cb) {
var self = this; var self = this;
var k = ADDR_PREFIX + addr + '-'; var k = ADDR_PREFIX + addr + '-';
@ -420,10 +417,10 @@ isspent
}); });
}); });
}); });
}; };
TransactionDb.prototype.removeFromTxId = function(txid, cb) { TransactionDb.prototype.removeFromTxId = function(txid, cb) {
async.series([ async.series([
@ -453,12 +450,12 @@ isspent
cb(err); cb(err);
}); });
}; };
// TODO. replace with // TODO. replace with
// Script.prototype.getAddrStrs if that one get merged in bitcore // Script.prototype.getAddrStrs if that one get merged in bitcore
TransactionDb.prototype.getAddrStr = function(s) { TransactionDb.prototype.getAddrStr = function(s) {
var self = this; var self = this;
var addrStrs = []; var addrStrs = [];
@ -491,9 +488,9 @@ isspent
} }
return addrStrs; return addrStrs;
}; };
TransactionDb.prototype.adaptTxObject = function(txInfo) { TransactionDb.prototype.adaptTxObject = function(txInfo) {
var self = this; var self = this;
// adapt bitcore TX object to bitcoind JSON response // adapt bitcore TX object to bitcoind JSON response
txInfo.txid = txInfo.hash; txInfo.txid = txInfo.hash;
@ -543,11 +540,11 @@ isspent
} }
return o; return o;
}); });
}; };
TransactionDb.prototype.add = function(tx, blockhash, cb) { TransactionDb.prototype.add = function(tx, blockhash, cb) {
var self = this; var self = this;
var addrs = []; var addrs = [];
@ -631,11 +628,11 @@ isspent
return cb(err); return cb(err);
}); });
}; };
TransactionDb.prototype.setConfirmation = function(txId, blockHash, confirmed, c) { TransactionDb.prototype.setConfirmation = function(txId, blockHash, confirmed, c) {
if (!blockHash) return c(); if (!blockHash) return c();
confirmed = confirmed ? 1 : 0; confirmed = confirmed ? 1 : 0;
@ -644,11 +641,11 @@ isspent
.put(IN_BLK_PREFIX + txId + '-' + blockHash, confirmed) .put(IN_BLK_PREFIX + txId + '-' + blockHash, confirmed)
.put(FROM_BLK_PREFIX + blockHash + '-' + txId, 1) .put(FROM_BLK_PREFIX + blockHash + '-' + txId, 1)
.write(c); .write(c);
}; };
// This slowdown addr balance calculation by 100% // This slowdown addr balance calculation by 100%
TransactionDb.prototype.isConfirmed = function(txId, c) { TransactionDb.prototype.isConfirmed = function(txId, c) {
var k = IN_BLK_PREFIX + txId; var k = IN_BLK_PREFIX + txId;
var ret = false; var ret = false;
@ -665,9 +662,9 @@ isspent
.on('end', function(err) { .on('end', function(err) {
return c(err, ret); return c(err, ret);
}); });
}; };
TransactionDb.prototype.handleBlockChange = function(hash, isMain, cb) { TransactionDb.prototype.handleBlockChange = function(hash, isMain, cb) {
var toChange = []; var toChange = [];
console.log('\tSearching Txs from block:' + hash); console.log('\tSearching Txs from block:' + hash);
@ -694,10 +691,10 @@ isspent
console.log('\t%s %d Txs', isMain ? 'Confirming' : 'Invalidating', toChange.length); console.log('\t%s %d Txs', isMain ? 'Confirming' : 'Invalidating', toChange.length);
db.batch(toChange, cb); db.batch(toChange, cb);
}); });
}; };
// txs can be a [hashes] or [txObjects] // txs can be a [hashes] or [txObjects]
TransactionDb.prototype.createFromArray = function(txs, blockHash, next) { TransactionDb.prototype.createFromArray = function(txs, blockHash, next) {
var self = this; var self = this;
if (!txs) return next(); if (!txs) return next();
@ -718,16 +715,14 @@ isspent
function(err) { function(err) {
return next(err); return next(err);
}); });
}; };
TransactionDb.prototype.createFromBlock = function(b, next) { TransactionDb.prototype.createFromBlock = function(b, next) {
var self = this; var self = this;
if (!b || !b.tx) return next(); if (!b || !b.tx) return next();
return self.createFromArray(b.tx, b.hash, next); return self.createFromArray(b.tx, b.hash, next);
}; };
return TransactionDb; module.exports = require('soop')(TransactionDb);
}
module.defineClass(spec);

View File

@ -57,7 +57,7 @@
"leveldown": "*", "leveldown": "*",
"levelup": "*", "levelup": "*",
"glob": "*", "glob": "*",
"classtool": "*", "soop": "git://github.com/gasteve/node-soop.git",
"commander": "*", "commander": "*",
"bignum": "*", "bignum": "*",
"express": "~3.4.7", "express": "~3.4.7",

View File

@ -11,7 +11,7 @@ var
util = require('util'), util = require('util'),
async = require('async'), async = require('async'),
config = require('../../config/config'), config = require('../../config/config'),
TransactionDb = require('../../lib/TransactionDb').class(); TransactionDb = require('../../lib/TransactionDb').default();
var spentValid = JSON.parse(fs.readFileSync('test/integration/spent.json')); var spentValid = JSON.parse(fs.readFileSync('test/integration/spent.json'));