better remove in txDB
This commit is contained in:
parent
c516c113cb
commit
71b27aede0
|
@ -1,91 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
require('classtool');
|
||||
|
||||
|
||||
function spec() {
|
||||
|
||||
var util = require('bitcore/util/util'),
|
||||
TransactionRpc = require('../../lib/TransactionRpc').class(),
|
||||
TransactionDb = require('../../lib/TransactionDb').class(),
|
||||
async = require('async');
|
||||
|
||||
var CONCURRENCY = 20;
|
||||
|
||||
function Transaction(tdb) {
|
||||
this.txid = null;
|
||||
this.tdb = tdb || new TransactionDb();
|
||||
}
|
||||
|
||||
Transaction.fromIdWithInfo = function (txid, tdb, cb) {
|
||||
if (typeof tdb === 'function') {
|
||||
cb = tdb;
|
||||
tdb = null;
|
||||
}
|
||||
var tx = new Transaction(tdb);
|
||||
|
||||
|
||||
console.log('[Transaction.js.27]',tx.tdb); //TODO
|
||||
tx.txid = txid;
|
||||
|
||||
tx._fillInfo(function(err) {
|
||||
if (err) return cb(err);
|
||||
if (! tx.info ) return cb();
|
||||
|
||||
return cb(err,tx);
|
||||
});
|
||||
};
|
||||
|
||||
Transaction.prototype._fillInfo = function(next) {
|
||||
var self = this;
|
||||
|
||||
TransactionRpc.getRpcInfo(self.txid, function(err, info) {
|
||||
if (err) return next(err);
|
||||
self._fillOutpoints(info, function() {
|
||||
self.info = info;
|
||||
return next();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Transaction.prototype._fillOutpoints = function(info, cb) {
|
||||
var self = this;
|
||||
|
||||
if (!info || info.isCoinBase) return cb();
|
||||
|
||||
var valueIn = 0;
|
||||
var incompleteInputs = 0;
|
||||
async.eachLimit(info.vin, CONCURRENCY, function(i, c_in) {
|
||||
self.tdb.fromTxIdN(i.txid, i.vout, function(err, addr, valueSat) {
|
||||
|
||||
|
||||
if (err || !addr || !valueSat ) {
|
||||
console.log('Could not get TXouts in %s,%d from %s ', i.txid, i.vout, info.txid);
|
||||
incompleteInputs = 1;
|
||||
return c_in(); // error not scaled
|
||||
}
|
||||
i.addr = addr;
|
||||
i.valueSat = valueSat;
|
||||
i.value = valueSat / util.COIN;
|
||||
|
||||
valueIn += i.valueSat;
|
||||
return c_in();
|
||||
});
|
||||
},
|
||||
function () {
|
||||
if (! incompleteInputs ) {
|
||||
info.valueIn = valueIn / util.COIN;
|
||||
info.fees = (valueIn - parseInt(info.valueOut * util.COIN)) / util.COIN ;
|
||||
}
|
||||
else {
|
||||
info.incompleteInputs = 1;
|
||||
}
|
||||
return cb();
|
||||
});
|
||||
};
|
||||
|
||||
return Transaction;
|
||||
}
|
||||
module.defineClass(spec);
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ function spec() {
|
|||
async.series([
|
||||
// Already got it?
|
||||
function(c) {
|
||||
self.sync.hasBlock(blockHash, function(err, ret) {
|
||||
self.sync.blockDb.has(blockHash, function(err, ret) {
|
||||
if (err) {
|
||||
p(err);
|
||||
return c(err);
|
||||
|
@ -163,11 +163,7 @@ function spec() {
|
|||
if (existed) return c();
|
||||
|
||||
self.sync.storeBlock(blockInfo, function(err) {
|
||||
|
||||
existed = err && err.toString().match(/E11000/);
|
||||
|
||||
if (err && ! existed) return c(err);
|
||||
return c();
|
||||
return c(err);
|
||||
});
|
||||
},
|
||||
/* TODO: Should Start to sync backwards? (this is for partial syncs)
|
||||
|
@ -349,6 +345,20 @@ function spec() {
|
|||
};
|
||||
|
||||
|
||||
HistoricSync.prototype.countNotOrphan = function(cb) {
|
||||
var self = this;
|
||||
|
||||
if (self.notOrphanCount) return cb(null, self.notOrphanCount);
|
||||
|
||||
|
||||
self.sync.blockDb.countNotOrphan(function(err, count) {
|
||||
if (err) return cb(err);
|
||||
self.notOrphanCount = count;
|
||||
return cb(null, self.notOrphanCount);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
HistoricSync.prototype.getBlockCount = function(cb) {
|
||||
var self = this;
|
||||
|
||||
|
@ -389,7 +399,7 @@ function spec() {
|
|||
function(cb) {
|
||||
if (scanOpts.upToExisting) {
|
||||
// should be isOrphan = true or null to be more accurate.
|
||||
self.sync.countNotOrphan(function(err, count) {
|
||||
self.countNotOrphan(function(err, count) {
|
||||
if (err) return cb(err);
|
||||
|
||||
self.syncedBlocks = count || 0;
|
||||
|
@ -464,19 +474,19 @@ function spec() {
|
|||
HistoricSync.prototype.smartImport = function(scanOpts, next) {
|
||||
var self = this;
|
||||
|
||||
self.sync.hasBlock(self.genesis, function(err, b) {
|
||||
self.sync.blockDb.has(self.genesis, function(err, b) {
|
||||
if (err) return next(err);
|
||||
self.sync.countNotOrphan(function(err, count) {
|
||||
self.countNotOrphan(function(err, count) {
|
||||
if (err) return next(err);
|
||||
self.getBlockCount(function(err) {
|
||||
if (err) return next(err);
|
||||
|
||||
if (!b || scanOpts.destroy || self.blockChainHeight > count * 0.7 ) {
|
||||
if (!b || scanOpts.destroy || count < self.blockChainHeight * 0.8 ) {
|
||||
|
||||
if (!b)
|
||||
p('Could not find Genesis block. Running FULL SYNC');
|
||||
else
|
||||
p('Less that 70% of current blockchain is stored. Running FULL SYNC',
|
||||
p('Less that 80% of current blockchain is stored. Running FULL SYNC',
|
||||
parseInt(count/self.blockChainHeight*100));
|
||||
|
||||
if (config.bitcoind.dataDir) {
|
||||
|
|
16
lib/Sync.js
16
lib/Sync.js
|
@ -62,24 +62,12 @@ function spec() {
|
|||
Sync.prototype.destroy = function(next) {
|
||||
var self = this;
|
||||
async.series([
|
||||
function(b) { try {self.blockDb.drop(b);} catch (e) { return b(); } },
|
||||
function(b) { try {self.TransactionDb.drop(b);} catch (e) { return b(); } },
|
||||
function(b) { self.blockDb.drop(b); },
|
||||
function(b) { self.txDb.drop(b); },
|
||||
], next);
|
||||
};
|
||||
|
||||
|
||||
Sync.prototype.hasBlock = function(hash, cb) {
|
||||
var self = this;
|
||||
|
||||
return self.blockDb.has(hash, cb);
|
||||
};
|
||||
|
||||
Sync.prototype.countNotOrphan = function(hash, cb) {
|
||||
var self = this;
|
||||
return self.blockDb.countNotOrphan(hash, cb);
|
||||
};
|
||||
|
||||
|
||||
Sync.prototype.storeBlock = function(block, cb) {
|
||||
var self = this;
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ function spec() {
|
|||
util = require('bitcore/util/util'),
|
||||
levelup = require('levelup'),
|
||||
async = require('async'),
|
||||
config = require('../config/config');
|
||||
config = require('../config/config'),
|
||||
assert = require('assert');
|
||||
|
||||
var TransactionDb = function() {
|
||||
this.db = levelup(config.leveldb + '/txs');
|
||||
|
@ -91,12 +92,16 @@ function spec() {
|
|||
.on('data', function (data) {
|
||||
var k = data.key.split('-');
|
||||
var v = data.value.split(':');
|
||||
var set=0;
|
||||
for(var i=0; i<l; i++) {
|
||||
if (ret[i].index === k[3]) {
|
||||
ret[i].spendTxId= v[0];
|
||||
ret[i].spendIndex=v[1];
|
||||
set=1;
|
||||
}
|
||||
}
|
||||
assert(set,'Spent could not be stored: tx ' + txid +
|
||||
'spend in TX:' + k[2] + ',' + k[3]);
|
||||
})
|
||||
.on('error', function (err) {
|
||||
return cb(err);
|
||||
|
@ -225,8 +230,7 @@ console.log('[TransactionDb.js.165]', ret); //TODO
|
|||
|
||||
|
||||
|
||||
// Only for testing. Very slow (toRm outs to rm, only to speedup)
|
||||
TransactionDb.prototype.removeFromTxId = function(txid, toRm, cb) {
|
||||
TransactionDb.prototype.removeFromTxId = function(txid, cb) {
|
||||
var self = this;
|
||||
|
||||
async.series([
|
||||
|
@ -238,27 +242,14 @@ console.log('[TransactionDb.js.165]', ret); //TODO
|
|||
self.db.createWriteStream({type:'del'})
|
||||
).on('close', c);
|
||||
},
|
||||
function(s_c) {
|
||||
if (toRm && toRm.length) return s_c();
|
||||
|
||||
toRm = [];
|
||||
function(c) {
|
||||
self.db.createReadStream({
|
||||
start: SPEND_ROOT
|
||||
start: SPEND_ROOT + txid,
|
||||
end: SPEND_ROOT + txid + '~'
|
||||
})
|
||||
.on('data', function(data) {
|
||||
if (data.value.indexOf(txid) >= 0) {
|
||||
toRm.push(data.key);
|
||||
console.log('To Remove Found', data.key); //TODO
|
||||
}
|
||||
})
|
||||
.on('end', function() {
|
||||
return s_c();
|
||||
});
|
||||
},
|
||||
function(s_c) {
|
||||
async.each(toRm, function(k,e_c) {
|
||||
self.db.del(k,e_c);
|
||||
}, s_c);
|
||||
.pipe(
|
||||
self.db.createWriteStream({type:'del'})
|
||||
).on('close', c);
|
||||
}],
|
||||
function(err) {
|
||||
cb(err);
|
||||
|
|
|
@ -11,18 +11,18 @@ var assert = require('assert'),
|
|||
TransactionDb = require('../../lib/TransactionDb').class();
|
||||
|
||||
var txItemsValid = JSON.parse(fs.readFileSync('test/integration/txitems.json'));
|
||||
var tdb;
|
||||
var txDb;
|
||||
|
||||
describe('TransactionDb fromIdWithInfo', function(){
|
||||
|
||||
before(function(c) {
|
||||
tdb = new TransactionDb();
|
||||
txDb = new TransactionDb();
|
||||
return c();
|
||||
});
|
||||
|
||||
var txid = '7e621eeb02874ab039a8566fd36f4591e65eca65313875221842c53de6907d6c';
|
||||
it('tx info ' + txid, function(done) {
|
||||
tdb.fromIdWithInfo(txid, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid, function(err, tx) {
|
||||
|
||||
if (err) done(err);
|
||||
assert.equal(tx.txid, txid);
|
||||
|
@ -38,7 +38,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
|
||||
it('tx info', function(done) {
|
||||
var txid = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237';
|
||||
tdb.fromIdWithInfo(txid, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid, function(err, tx) {
|
||||
if (err) done(err);
|
||||
assert.equal(tx.txid, txid);
|
||||
assert(!tx.info.isCoinBase);
|
||||
|
@ -48,7 +48,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
|
||||
it('should pool tx\'s info from bitcoind', function(done) {
|
||||
var txid = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237';
|
||||
tdb.fromIdWithInfo(txid, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid, function(err, tx) {
|
||||
if (err) done(err);
|
||||
assert.equal(tx.info.txid, txid);
|
||||
assert.equal(tx.info.blockhash, '000000000185678d3d7ecc9962c96418174431f93fe20bf216d5565272423f74');
|
||||
|
@ -62,7 +62,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
|
||||
var txid1 = '2a104bab1782e9b6445583296d4a0ecc8af304e4769ceb64b890e8219c562399';
|
||||
it('test a coinbase TX ' + txid1, function(done) {
|
||||
tdb.fromIdWithInfo(txid1, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid1, function(err, tx) {
|
||||
if (err) done(err);
|
||||
assert(tx.info.isCoinBase);
|
||||
assert.equal(tx.info.txid, txid1);
|
||||
|
@ -72,7 +72,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
});
|
||||
var txid22 = '666';
|
||||
it('test invalid TX ' + txid22, function(done) {
|
||||
tdb.fromIdWithInfo(txid22, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid22, function(err, tx) {
|
||||
if (err && err.message.match(/must.be.hexadecimal/)) {
|
||||
return done();
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
var txid23 = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca227';
|
||||
it('test unexisting TX ' + txid23, function(done) {
|
||||
|
||||
tdb.fromIdWithInfo(txid23, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid23, function(err, tx) {
|
||||
assert(!err);
|
||||
assert(!tx);
|
||||
return done();
|
||||
|
@ -96,7 +96,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
|
||||
var txid2 = '64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608';
|
||||
it('create TX on the fly ' + txid2, function(done) {
|
||||
tdb.fromIdWithInfo(txid2, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid2, function(err, tx) {
|
||||
if (err) return done(err);
|
||||
assert.equal(tx.info.txid, txid2);
|
||||
done();
|
||||
|
@ -105,7 +105,7 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
|
||||
txid2 = '64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608';
|
||||
it('test a broken TX ' + txid2, function(done) {
|
||||
tdb.fromIdWithInfo(txid2, function(err, tx) {
|
||||
txDb.fromIdWithInfo(txid2, function(err, tx) {
|
||||
if (err) return done(err);
|
||||
assert.equal(tx.info.txid, txid2);
|
||||
assert.equal(tx.info.vin[0].addr, 'n1JagbRWBDi6VMvG7HfZmXX74dB9eiHJzU');
|
||||
|
@ -113,28 +113,25 @@ describe('TransactionDb fromIdWithInfo', function(){
|
|||
});
|
||||
});
|
||||
});
|
||||
/*
|
||||
|
||||
describe('TransactionDb Outs', function(){
|
||||
|
||||
var tdb = new TransactionDb();
|
||||
|
||||
txItemsValid.forEach( function(v) {
|
||||
if (v.disabled) return;
|
||||
it('test a processing tx ' + v.txid, function(done) {
|
||||
this.timeout(60000);
|
||||
|
||||
// Remove first
|
||||
tdb.removeFromTxId(v.txid, v.toRm, function() {
|
||||
txDb.removeFromTxId(v.txid, function() {
|
||||
|
||||
tdb.fromTxId( v.txid, function(err, readItems) {
|
||||
txDb.fromTxId( v.txid, function(err, readItems) {
|
||||
assert.equal(readItems.length,0);
|
||||
|
||||
var unmatch=[];
|
||||
tdb.createFromArray([v.txid], null, function(err) {
|
||||
txDb.createFromArray([v.txid], null, function(err) {
|
||||
if (err) return done(err);
|
||||
|
||||
tdb.fromTxId( v.txid, function(err, readItems) {
|
||||
txDb.fromTxId( v.txid, function(err, readItems) {
|
||||
|
||||
v.items.forEach(function(validItem){
|
||||
unmatch[validItem.addr] =1;
|
||||
|
@ -164,5 +161,4 @@ describe('TransactionDb Outs', function(){
|
|||
});
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||
|
||||
|
||||
|
||||
var mongoose = require('mongoose'),
|
||||
assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
util = require('util'),
|
||||
async = require('async'),
|
||||
config = require('../../config/config'),
|
||||
TransactionOut = require('../../app/models/TransactionOut');
|
||||
|
||||
var spentValid = JSON.parse(fs.readFileSync('test/model/spent.json'));
|
||||
|
||||
mongoose.connection.on('error', function(err) { console.log(err); });
|
||||
|
||||
|
||||
|
||||
describe('TransactionOut Expenses', function(){
|
||||
|
||||
before(function(done) {
|
||||
mongoose.connect(config.db);
|
||||
|
||||
// lets spend!
|
||||
async.each(Object.keys(spentValid),
|
||||
function(txid,c_out) {
|
||||
async.each(spentValid[txid],
|
||||
function(i,c_in) {
|
||||
TransactionOut._explodeTransactionOuts(i.txid, function(err) {
|
||||
return c_in();
|
||||
});
|
||||
},
|
||||
function(err) {
|
||||
return c_out();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(err) {
|
||||
console.log('[transactionouts.js.88]'); //TODO
|
||||
return done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
mongoose.connection.close();
|
||||
done();
|
||||
});
|
||||
|
||||
Object.keys(spentValid).forEach( function(txid) {
|
||||
it('test result of spending tx ' + txid, function(done) {
|
||||
var s = spentValid[txid];
|
||||
var c=0;
|
||||
TransactionOut.fromTxId( txid, function(err, readItems) {
|
||||
s.forEach( function(v) {
|
||||
assert.equal(readItems[c].spendTxIdBuf.toString('hex'),v.txid);
|
||||
assert.equal(readItems[c].spendIndex,v.n);
|
||||
c++;
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -6,7 +6,8 @@
|
|||
{
|
||||
"txid": "21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237",
|
||||
"toRm": [
|
||||
"txouts-spend-86a03cac7d87f596008c6d5a8d3fd8b88842932ea6f0337673eda16f6b472f7f-0"
|
||||
"txouts-spend-86a03cac7d87f596008c6d5a8d3fd8b88842932ea6f0337673eda16f6b472f7f-0",
|
||||
"txouts-spend-bcd8da8ee847da377f8aaca92502c05e5f914c6a2452753146013b0e642a25a0-0"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue