leveldb connection using classtool

This commit is contained in:
Matias Alejo Garcia 2014-02-05 13:02:51 -03:00
parent a031941c62
commit 061e4e4b34
7 changed files with 40 additions and 78 deletions

View File

@ -3,7 +3,7 @@
require('classtool'); require('classtool');
function spec() { function spec(b) {
var TIMESTAMP_ROOT = 'b-ts-'; // b-ts-<ts> => <hash> var TIMESTAMP_ROOT = 'b-ts-'; // b-ts-<ts> => <hash>
var PREV_ROOT = 'b-prev-'; // b-prev-<hash> => <prev_hash> (0 if orphan) var PREV_ROOT = 'b-prev-'; // b-prev-<hash> => <prev_hash> (0 if orphan)
@ -17,36 +17,34 @@ function spec() {
levelup = require('levelup'), levelup = require('levelup'),
BitcoreBlock= require('bitcore/Block').class(), BitcoreBlock= require('bitcore/Block').class(),
config = require('../config/config'); config = require('../config/config');
var db = b.db || levelup(config.leveldb + '/blocks');
var BlockDb = function(db) {
this.db = db || levelup(config.leveldb + '/blocks'); var BlockDb = function() {
}; };
BlockDb.prototype.close = function(cb) { BlockDb.prototype.close = function(cb) {
this.db.close(cb); db.close(cb);
}; };
BlockDb.prototype.drop = function(cb) { BlockDb.prototype.drop = function(cb) {
var self = this;
var path = config.leveldb + '/blocks'; var path = config.leveldb + '/blocks';
self.db.close(function() { db.close(function() {
require('leveldown').destroy(path, function () { require('leveldown').destroy(path, function () {
self.db = levelup(path); db = levelup(path);
return cb(); return cb();
}); });
}); });
}; };
BlockDb.prototype.add = function(b, cb) { BlockDb.prototype.add = function(b, cb) {
var self = this;
if (!b.hash) return cb(new Error('no Hash at Block.save')); if (!b.hash) return cb(new Error('no Hash at Block.save'));
var time_key = TIMESTAMP_ROOT + var time_key = TIMESTAMP_ROOT +
( b.time || Math.round(new Date().getTime() / 1000) ); ( b.time || Math.round(new Date().getTime() / 1000) );
self.db.batch() db.batch()
.put(time_key, b.hash) .put(time_key, b.hash)
.put(PREV_ROOT + b.hash, b.previousblockhash) .put(PREV_ROOT + b.hash, b.previousblockhash)
.write(cb); .write(cb);
@ -55,13 +53,11 @@ function spec() {
BlockDb.prototype.setOrphan = function(hash, cb) { BlockDb.prototype.setOrphan = function(hash, cb) {
var self = this;
var k = PREV_ROOT + hash; var k = PREV_ROOT + hash;
self.db.get(k, function (err,oldPrevHash) { db.get(k, function (err,oldPrevHash) {
if (err || !oldPrevHash) return cb(err); if (err || !oldPrevHash) return cb(err);
self.db.put(PREV_ROOT + hash, 0, function() { db.put(PREV_ROOT + hash, 0, function() {
return cb(err, oldPrevHash); return cb(err, oldPrevHash);
}); });
}); });
@ -70,14 +66,14 @@ function spec() {
//mainly for testing //mainly for testing
BlockDb.prototype.setPrev = function(hash, prevHash, cb) { BlockDb.prototype.setPrev = function(hash, prevHash, cb) {
this.db.put(PREV_ROOT + hash, prevHash, function(err) { db.put(PREV_ROOT + hash, prevHash, function(err) {
return cb(err); return cb(err);
}); });
}; };
//mainly for testing //mainly for testing
BlockDb.prototype.getPrev = function(hash, cb) { BlockDb.prototype.getPrev = function(hash, cb) {
this.db.get(PREV_ROOT + hash, function(err,val) { db.get(PREV_ROOT + hash, function(err,val) {
return cb(err,val); return cb(err,val);
}); });
}; };
@ -87,7 +83,7 @@ function spec() {
BlockDb.prototype.countNotOrphan = function(cb) { BlockDb.prototype.countNotOrphan = 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');
this.db.createReadStream({start: PREV_ROOT, end: PREV_ROOT + '~' }) db.createReadStream({start: PREV_ROOT, end: PREV_ROOT + '~' })
.on('data', function (data) { .on('data', function (data) {
if (data.value !== 0) c++; if (data.value !== 0) c++;
}) })
@ -100,10 +96,8 @@ function spec() {
}; };
BlockDb.prototype.has = function(hash, cb) { BlockDb.prototype.has = function(hash, cb) {
var self = this;
var k = PREV_ROOT + hash; var k = PREV_ROOT + hash;
self.db.get(k, function (err,val) { db.get(k, function (err,val) {
var ret; var ret;
if (err && err.notFound) { if (err && err.notFound) {
err = null; err = null;
@ -135,17 +129,15 @@ function spec() {
}; };
BlockDb.prototype.getBlocksByDate = function(start_ts, end_ts, cb) { BlockDb.prototype.getBlocksByDate = function(start_ts, end_ts, cb) {
var self = this;
var list = []; var list = [];
self.db.createReadStream({ db.createReadStream({
start: TIMESTAMP_ROOT + start_ts, start: TIMESTAMP_ROOT + start_ts,
end: TIMESTAMP_ROOT + end_ts end: TIMESTAMP_ROOT + end_ts
}) })
.on('data', function (data) { .on('data', function (data) {
list.push({ list.push({
ts: data.key.replace(TIMESTAMP_ROOT, ''), ts: data.key.replace(TIMESTAMP_ROOT, ''),
hash: data.value, hash: data.value,
info: {}
}); });
}) })
.on('error', function (err) { .on('error', function (err) {

View File

@ -3,7 +3,7 @@
require('classtool'); require('classtool');
function spec() { function spec(b) {
// blockHash -> txid mapping (to reorgs) // blockHash -> txid mapping (to reorgs)
var ROOT = 'tx-b-'; //tx-b-<txid>-<block> => 1/0 (connected or not) var ROOT = 'tx-b-'; //tx-b-<txid>-<block> => 1/0 (connected or not)
@ -28,21 +28,21 @@ function spec() {
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');
var TransactionDb = function(db) { var TransactionDb = function() {
this.db = db || levelup(config.leveldb + '/txs');
}; };
TransactionDb.prototype.close = function(cb) { TransactionDb.prototype.close = function(cb) {
this.db.close(cb); db.close(cb);
}; };
TransactionDb.prototype.drop = function(cb) { TransactionDb.prototype.drop = function(cb) {
var self = this; var self = this;
var path = config.leveldb + '/txs'; var path = config.leveldb + '/txs';
self.db.close(function() { db.close(function() {
require('leveldown').destroy(path, function () { require('leveldown').destroy(path, function () {
self.db = levelup(path); db = levelup(path);
return cb(); return cb();
}); });
}); });
@ -54,7 +54,7 @@ function spec() {
var self = this; var self = this;
var k = OUTS_ROOT + txid; var k = OUTS_ROOT + txid;
self.db.get(k, function (err,val) { db.get(k, function (err,val) {
var ret; var ret;
@ -76,7 +76,7 @@ function spec() {
var ret=[]; var ret=[];
// outs. // outs.
self.db.createReadStream({start: k, end: k + '~'}) db.createReadStream({start: k, end: k + '~'})
.on('data', function (data) { .on('data', function (data) {
var k = data.key.split('-'); var k = data.key.split('-');
var v = data.value.split(':'); var v = data.value.split(':');
@ -92,7 +92,7 @@ function spec() {
.on('end', function () { .on('end', function () {
var k = SPEND_ROOT + txid; var k = SPEND_ROOT + txid;
var l = ret.length; var l = ret.length;
self.db.createReadStream({start: k, end: k + '~'}) db.createReadStream({start: k, end: k + '~'})
.on('data', function (data) { .on('data', function (data) {
var k = data.key.split('-'); var k = data.key.split('-');
var v = data.value.split(':'); var v = data.value.split(':');
@ -181,7 +181,7 @@ function spec() {
var k = OUTS_ROOT + txid + '-' + n; var k = OUTS_ROOT + txid + '-' + n;
self.db.get(k, function (err,val) { db.get(k, function (err,val) {
if (err && err.notFound) { if (err && err.notFound) {
err = null; err = null;
} }
@ -197,7 +197,7 @@ function spec() {
var ret=[]; var ret=[];
// //
self.db.createReadStream({start: k, end: k + '~'}) db.createReadStream({start: k, end: k + '~'})
.on('data', function (data) { .on('data', function (data) {
var k = data.key.split('-'); var k = data.key.split('-');
var v = data.value.split(':'); var v = data.value.split(':');
@ -214,7 +214,7 @@ function spec() {
.on('end', function () { .on('end', function () {
async.each(ret, function(o, e_c) { async.each(ret, function(o, e_c) {
var k = SPEND_ROOT + o.txid + '-' + o.index; var k = SPEND_ROOT + o.txid + '-' + o.index;
self.db.get(k, function(err, val) { db.get(k, function(err, val) {
if (err && err.notFound) err=null; if (err && err.notFound) err=null;
if (err || !val) return e_c(err); if (err || !val) return e_c(err);
@ -237,20 +237,20 @@ function spec() {
async.series([ async.series([
function(c) { function(c) {
self.db.createReadStream({ db.createReadStream({
start: OUTS_ROOT + txid, start: OUTS_ROOT + txid,
end: OUTS_ROOT + txid + '~', end: OUTS_ROOT + txid + '~',
}).pipe( }).pipe(
self.db.createWriteStream({type:'del'}) db.createWriteStream({type:'del'})
).on('close', c); ).on('close', c);
}, },
function(c) { function(c) {
self.db.createReadStream({ db.createReadStream({
start: SPEND_ROOT + txid, start: SPEND_ROOT + txid,
end: SPEND_ROOT + txid + '~' end: SPEND_ROOT + txid + '~'
}) })
.pipe( .pipe(
self.db.createWriteStream({type:'del'}) db.createWriteStream({type:'del'})
).on('close', c); ).on('close', c);
}], }],
function(err) { function(err) {
@ -313,7 +313,7 @@ function spec() {
if (tx.isCoinBase) return p_c(); if (tx.isCoinBase) return p_c();
async.forEachLimit(tx.vin, CONCURRENCY, async.forEachLimit(tx.vin, CONCURRENCY,
function(i, next_out) { function(i, next_out) {
self.db.batch() db.batch()
.put( SPEND_ROOT + i.txid + '-' + i.vout , .put( SPEND_ROOT + i.txid + '-' + i.vout ,
tx.txid + ':' + i.n + ':' + ts) tx.txid + ':' + i.n + ':' + ts)
.write(next_out); .write(next_out);
@ -344,7 +344,7 @@ function spec() {
var addr = o.scriptPubKey.addresses[0]; var addr = o.scriptPubKey.addresses[0];
var sat = Math.round(o.value * util.COIN); var sat = Math.round(o.value * util.COIN);
self.db.batch() db.batch()
.put( OUTS_ROOT + tx.txid + '-' + o.n, addr + ':' + sat) .put( OUTS_ROOT + tx.txid + '-' + o.n, addr + ':' + sat)
.put( ADDR_ROOT + addr + '-' + ts + '-' + tx.txid + .put( ADDR_ROOT + addr + '-' + ts + '-' + tx.txid +
'-' + o.n, sat) '-' + o.n, sat)
@ -395,7 +395,7 @@ function spec() {
self.add(inInfo, function(err) { self.add(inInfo, function(err) {
if (err || !blockHash) return each_cb(err); if (err || !blockHash) return each_cb(err);
self.db.put(ROOT + t + '-' + blockHash, 1, function(err) { db.put(ROOT + t + '-' + blockHash, 1, function(err) {
return each_cb(err); return each_cb(err);
}); });
}); });
@ -405,7 +405,7 @@ function spec() {
self.add(t, function(err) { self.add(t, function(err) {
if (err) return each_cb(err); if (err) return each_cb(err);
self.db.put(ROOT + t.txid + '-' + blockHash, 1, function(err) { db.put(ROOT + t.txid + '-' + blockHash, 1, function(err) {
return each_cb(err); return each_cb(err);
}); });
}); });

View File

@ -21,10 +21,6 @@ describe('TransactionDb fromIdWithInfo', function(){
}); });
after(function(c) {
txDb.close(c);
});
var txid = '7e621eeb02874ab039a8566fd36f4591e65eca65313875221842c53de6907d6c'; var txid = '7e621eeb02874ab039a8566fd36f4591e65eca65313875221842c53de6907d6c';
it('tx info ' + txid, function(done) { it('tx info ' + txid, function(done) {
txDb.fromIdWithInfo(txid, function(err, tx) { txDb.fromIdWithInfo(txid, function(err, tx) {
@ -126,11 +122,6 @@ describe('TransactionDb Outs', function(){
return c(); return c();
}); });
after(function(c) {
txDb.close(c);
});
txItemsValid.forEach( function(v) { txItemsValid.forEach( function(v) {
if (v.disabled) return; if (v.disabled) return;
it('test a processing tx ' + v.txid, function(done) { it('test a processing tx ' + v.txid, function(done) {

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').class();
var spentValid = JSON.parse(fs.readFileSync('test/integration/spent.json')); var spentValid = JSON.parse(fs.readFileSync('test/integration/spent.json'));
@ -42,11 +42,6 @@ describe('TransactionDb Expenses', function(){
); );
}); });
after(function(c) {
txDb.close(c);
});
Object.keys(spentValid).forEach( function(txid) { Object.keys(spentValid).forEach( function(txid) {
it('test result of spending tx ' + txid, function(done) { it('test result of spending tx ' + txid, function(done) {
var s = spentValid[txid]; var s = spentValid[txid];

View File

@ -17,12 +17,6 @@ describe('Address balances', function(){
return c(); return c();
}); });
after(function(c) {
txDb.close(c);
});
addrValid.forEach( function(v) { addrValid.forEach( function(v) {
if (v.disabled) { if (v.disabled) {
console.log(v.addr + " => disabled in JSON"); console.log(v.addr + " => disabled in JSON");

View File

@ -21,11 +21,6 @@ describe('BlockDb fromHashWithInfo', function(){
return c(); return c();
}); });
after(function(c) {
bDb.close(c);
});
it('should poll block\'s info from bitcoind', function(done) { it('should poll block\'s info from bitcoind', function(done) {
bDb.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { bDb.fromHashWithInfo(TESTING_BLOCK, function(err, b2) {
if (err) done(err); if (err) done(err);

View File

@ -5,8 +5,8 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var TESTING_BLOCK0 = '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943'; var TESTING_BLOCK0 = '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943';
var TESTING_BLOCK1 = '00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206'; var TESTING_BLOCK1 = '00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206';
var START_TS = 1293895128; // 1/1/2011 var START_TS = 1;
var END_TS = 1296688428; // 2/2/2011 23:23PM var END_TS = '1296688928~'; // 2/2/2011 23:23PM
var assert = require('assert'), var assert = require('assert'),
BlockDb = require('../../lib/BlockDb').class(); BlockDb = require('../../lib/BlockDb').class();
@ -21,11 +21,6 @@ describe('BlockDb getBlocksByDate', function(){
return c(); return c();
}); });
after(function(c) {
bDb.close(c);
});
it('Get Hash by Date', function(done) { it('Get Hash by Date', function(done) {
bDb.getBlocksByDate(START_TS, END_TS, function(err, list) { bDb.getBlocksByDate(START_TS, END_TS, function(err, list) {