fix conflicts
This commit is contained in:
commit
0f7ad7b948
|
@ -17,8 +17,11 @@ exports.block = function(req, res, next, hash) {
|
||||||
if (err || !block)
|
if (err || !block)
|
||||||
return common.handleErrors(err, res, next);
|
return common.handleErrors(err, res, next);
|
||||||
else {
|
else {
|
||||||
req.block = block.info;
|
bdb.getPoolInfo(block.info.tx[0], function(info) {
|
||||||
return next();
|
block.info.poolInfo = info;
|
||||||
|
req.block = block.info;
|
||||||
|
return next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -63,7 +66,12 @@ var getBlock = function(blockhash, cb) {
|
||||||
isOrphan: 1,
|
isOrphan: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return cb(err, block.info);
|
|
||||||
|
bdb.getPoolInfo(block.info.tx[0], function(info) {
|
||||||
|
block.info.poolInfo = info;
|
||||||
|
return cb(err, block.info);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,6 +135,7 @@ exports.list = function(req, res) {
|
||||||
hash: b.hash,
|
hash: b.hash,
|
||||||
time: b.ts || info.time,
|
time: b.ts || info.time,
|
||||||
txlength: info.tx.length,
|
txlength: info.tx.length,
|
||||||
|
poolInfo: info.poolInfo
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, function(err, allblocks) {
|
}, function(err, allblocks) {
|
||||||
|
|
|
@ -17,16 +17,21 @@ module.exports.init = function(app, io_ext) {
|
||||||
|
|
||||||
module.exports.broadcastTx = function(tx) {
|
module.exports.broadcastTx = function(tx) {
|
||||||
if (ios) {
|
if (ios) {
|
||||||
var t = {};
|
var t;
|
||||||
if (typeof tx === 'string') {
|
if (typeof tx === 'string') {
|
||||||
t = {
|
t = {
|
||||||
txid: tx
|
txid: tx
|
||||||
};
|
};
|
||||||
} else {
|
}
|
||||||
t = tx;
|
|
||||||
|
else {
|
||||||
|
t = {
|
||||||
|
txid: tx.txid,
|
||||||
|
size: tx.size,
|
||||||
|
};
|
||||||
// Outputs
|
// Outputs
|
||||||
var valueOut = 0;
|
var valueOut = 0;
|
||||||
t.vout.forEach(function(o) {
|
tx.vout.forEach(function(o) {
|
||||||
valueOut += o.value * util.COIN;
|
valueOut += o.value * util.COIN;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -77,20 +77,27 @@ function spec() {
|
||||||
var db = new TransactionDb();
|
var db = new TransactionDb();
|
||||||
async.series([
|
async.series([
|
||||||
function (cb) {
|
function (cb) {
|
||||||
|
var seen={};
|
||||||
db.fromAddr(self.addrStr, function(err,txOut){
|
db.fromAddr(self.addrStr, function(err,txOut){
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
txOut.forEach(function(txItem){
|
txOut.forEach(function(txItem){
|
||||||
|
var add=0, addSpend=0;
|
||||||
var v = txItem.value_sat;
|
var v = txItem.value_sat;
|
||||||
|
|
||||||
txs.push({txid: txItem.txid, ts: txItem.ts});
|
if ( !seen[txItem.txid] ) {
|
||||||
|
txs.push({txid: txItem.txid, ts: txItem.ts});
|
||||||
|
seen[txItem.txid]=1;
|
||||||
|
add=1;
|
||||||
|
}
|
||||||
|
|
||||||
if (txItem.spentTxId) {
|
if (txItem.spentTxId && !seen[txItem.spentTxId] ) {
|
||||||
txs.push({txid: txItem.spentTxId, ts: txItem.spentTs});
|
txs.push({txid: txItem.spentTxId, ts: txItem.spentTs});
|
||||||
|
seen[txItem.spentTxId]=1;
|
||||||
|
addSpend=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txItem.isConfirmed) {
|
if (txItem.isConfirmed) {
|
||||||
self.txApperances += 1;
|
self.txApperances += add;
|
||||||
self.totalReceivedSat += v;
|
self.totalReceivedSat += v;
|
||||||
if (! txItem.spentTxId ) {
|
if (! txItem.spentTxId ) {
|
||||||
//unspent
|
//unspent
|
||||||
|
@ -100,17 +107,17 @@ function spec() {
|
||||||
// unspent
|
// unspent
|
||||||
self.balanceSat += v;
|
self.balanceSat += v;
|
||||||
self.unconfirmedBalanceSat -= v;
|
self.unconfirmedBalanceSat -= v;
|
||||||
self.unconfirmedTxApperances += 1;
|
self.unconfirmedTxApperances += addSpend;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// spent
|
// spent
|
||||||
self.totalSentSat += v;
|
self.totalSentSat += v;
|
||||||
self.txApperances += 1;
|
self.txApperances += addSpend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.unconfirmedBalanceSat += v;
|
self.unconfirmedBalanceSat += v;
|
||||||
self.unconfirmedTxApperances += 1;
|
self.unconfirmedTxApperances += add;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return cb();
|
return cb();
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
|
||||||
|
first 5%
|
||||||
|
|
||||||
|
=> with data + mongo + w/RPC for blocks: 48.8s
|
||||||
|
=> with RPC + mongo: 2m26s
|
||||||
|
=> with files + mongo + wo/RPC for blocks: 36.7s
|
||||||
|
=> with files + mongo + wo/RPC for blocks + wo/mongoIndexes:
|
||||||
|
|
||||||
|
|
||||||
|
first 10%
|
||||||
|
|
||||||
|
=> sin RPC, sin Tx, sin store block => 0.7s
|
||||||
|
=> sin RPC, sin grabar, procesando TX => 8.5s
|
||||||
|
=> sin RPC, sin TX processing, sin grabar => 12s28
|
||||||
|
=> con RPC, TX processing, sin Grabar Tx, grabando bloques => 29s
|
||||||
|
=> con RPC, sin TX processing, sin Grabar Tx, grabando bloques => 35s
|
||||||
|
=> con RPC, TX processing, sin Grabar Tx, grabando bloques => 43s
|
||||||
|
|
||||||
|
=> TX processing, sin RPC, sin saves TX, y blocks => 11.6s
|
||||||
|
=> TX processing, CON RPC, sin saves TX, y blocks => 35s
|
||||||
|
=> con RPC, TX processing, sin saves TX => 45s
|
||||||
|
=> con RPC, TX processing, Grabarndo todo => 78s
|
||||||
|
=> con RPC, TX processing, Grabarndo todo => 78s
|
||||||
|
(18k blocks, 36k txouts)
|
||||||
|
|
||||||
|
//LEVEL DB
|
||||||
|
=> sin RPC, TX processing, todo en level => 14s
|
||||||
|
=> con RPC, TX processing, todo en level => 39.7s
|
||||||
|
=> con RPC, TX processing, tx mongo, blocks en level => 64s
|
||||||
|
|
||||||
|
|
||||||
|
=> sin RPC, TX processing, todo en level, handling REORGs, more data => 28s
|
||||||
|
=> sin RPC, TX processing, todo en level, handling REORGs, more data, tx ts => 34t s
|
||||||
|
|
||||||
|
|
||||||
|
//FROM blk00002.dat (more txs), 5%
|
||||||
|
|
||||||
|
=> now total : 1m13s
|
||||||
|
=> removing block writes => 1m8s
|
||||||
|
=> sacando los contenidos adentro de getblock from file de => 4.5s!!
|
||||||
|
|
||||||
|
=> con base58 cpp => 21s
|
||||||
|
=> toda la testnet => 17m
|
||||||
|
|
||||||
|
10% de blk2
|
||||||
|
=> 50s con base58cpp
|
||||||
|
=> 41s commentando todo addr
|
||||||
|
=> 5s commentando todo get HistoricSync.prototype.getBlockFromFile = function(cb) {
|
||||||
|
=> 15s commentando todo get HistoricSync.prototype.getBlockFromFile = function(cb) {
|
||||||
|
|
||||||
|
10% de blk 1
|
||||||
|
=> 59s
|
||||||
|
=> 15s comentando desde b.getStandardizedObject()
|
||||||
|
=> 39s comentando dps b.getStandardizedObject()
|
||||||
|
|
37
insight.js
37
insight.js
|
@ -44,48 +44,31 @@ walk(models_path);
|
||||||
* p2pSync process
|
* p2pSync process
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var peerSync = new PeerSync();
|
var peerSync = new PeerSync({shouldBroadcast: true});
|
||||||
|
|
||||||
if (!config.disableP2pSync) {
|
if (!config.disableP2pSync) {
|
||||||
var ps = peerSync;
|
peerSync.run();
|
||||||
ps.init({
|
|
||||||
shouldBroadcast: true,
|
|
||||||
}, function() {
|
|
||||||
ps.run();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* historic_sync process
|
* historic_sync process
|
||||||
*/
|
*/
|
||||||
var historicSync = {};
|
var historicSync = new HistoricSync({
|
||||||
|
shouldBroadcastSync: true
|
||||||
|
});
|
||||||
|
peerSync.historicSync = historicSync;
|
||||||
|
|
||||||
if (!config.disableHistoricSync) {
|
if (!config.disableHistoricSync) {
|
||||||
historicSync = new HistoricSync();
|
historicSync.start({}, function(err){
|
||||||
|
|
||||||
historicSync.init({
|
|
||||||
shouldBroadcastSync: true,
|
|
||||||
}, 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);
|
||||||
}
|
}
|
||||||
else {
|
if (peerSync) peerSync.allowReorgs = true;
|
||||||
historicSync.smartImport({}, function(err){
|
|
||||||
var txt = 'ended.';
|
|
||||||
if (err)
|
|
||||||
txt = 'ABORTED with error: ' + err.message;
|
|
||||||
else if (ps) {
|
|
||||||
ps.allowReorgs = true;
|
|
||||||
ps.historicSync = historicSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[historic_sync] ' + txt, historicSync.info());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if (peerSync) peerSync.allowReorgs = true;
|
||||||
|
|
||||||
|
|
||||||
//express settings
|
//express settings
|
||||||
|
|
|
@ -25,6 +25,9 @@ function spec(b) {
|
||||||
var Rpc = b.rpc || require('./Rpc').class();
|
var Rpc = b.rpc || require('./Rpc').class();
|
||||||
var PoolMatch = b.poolMatch || require('./PoolMatch').class(config);
|
var PoolMatch = b.poolMatch || require('./PoolMatch').class(config);
|
||||||
|
|
||||||
|
var buffertools = require('buffertools');
|
||||||
|
var TransactionDb = require('./TransactionDb.js').class();
|
||||||
|
|
||||||
var BlockDb = function() {
|
var BlockDb = function() {
|
||||||
BlockDb.super(this, arguments);
|
BlockDb.super(this, arguments);
|
||||||
this.poolMatch = new PoolMatch();
|
this.poolMatch = new PoolMatch();
|
||||||
|
@ -57,7 +60,7 @@ function spec(b) {
|
||||||
return db.batch()
|
return db.batch()
|
||||||
.put(time_key, b.hash)
|
.put(time_key, b.hash)
|
||||||
.put(MAIN_PREFIX + b.hash, 1)
|
.put(MAIN_PREFIX + b.hash, 1)
|
||||||
.put(PREV_PREFIX + b.hash, b.previousblockhash)
|
.put(PREV_PREFIX + b.hash, b.previousblockhash)
|
||||||
.write(function(err){
|
.write(function(err){
|
||||||
if (!err) {
|
if (!err) {
|
||||||
self.emit('new_block', {blockid: b.hash});
|
self.emit('new_block', {blockid: b.hash});
|
||||||
|
@ -136,7 +139,7 @@ function spec(b) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockDb.prototype.countNotOrphan = 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 + '~' })
|
||||||
|
@ -164,6 +167,21 @@ function spec(b) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BlockDb.prototype.getPoolInfo = function(tx, cb) {
|
||||||
|
var tr = new TransactionDb();
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
tr._getInfo(tx, function(e, a) {
|
||||||
|
if (e) return cb(false);
|
||||||
|
|
||||||
|
if (a.isCoinBase) {
|
||||||
|
var coinbaseHexBuffer = new Buffer(a.vin[0].coinbase, 'hex');
|
||||||
|
var a = self.poolMatch.match(coinbaseHexBuffer);
|
||||||
|
|
||||||
|
return cb(a);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
BlockDb.prototype.fromHashWithInfo = function(hash, cb) {
|
BlockDb.prototype.fromHashWithInfo = function(hash, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -175,7 +193,6 @@ function spec(b) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
info.isMainChain = val ? true : false;
|
info.isMainChain = val ? true : false;
|
||||||
// info.poolInfo = self.poolMatch.match(info.hex);
|
|
||||||
|
|
||||||
return cb(null, {
|
return cb(null, {
|
||||||
hash: hash,
|
hash: hash,
|
||||||
|
|
|
@ -6,6 +6,7 @@ require('classtool');
|
||||||
|
|
||||||
function spec() {
|
function spec() {
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
var assert = require('assert');
|
||||||
var RpcClient = require('bitcore/RpcClient').class();
|
var RpcClient = require('bitcore/RpcClient').class();
|
||||||
var Script = require('bitcore/Script').class();
|
var Script = require('bitcore/Script').class();
|
||||||
var networks = require('bitcore/networks');
|
var networks = require('bitcore/networks');
|
||||||
|
@ -14,20 +15,28 @@ function spec() {
|
||||||
var Sync = require('./Sync').class();
|
var Sync = require('./Sync').class();
|
||||||
var sockets = require('../app/controllers/socket.js');
|
var sockets = require('../app/controllers/socket.js');
|
||||||
var BlockExtractor = require('./BlockExtractor.js').class();
|
var BlockExtractor = require('./BlockExtractor.js').class();
|
||||||
|
var buffertools = require('buffertools');
|
||||||
|
|
||||||
// var bitcoreUtil = require('bitcore/util/util');
|
// var bitcoreUtil = require('bitcore/util/util');
|
||||||
// var Deserialize = require('bitcore/Deserialize');
|
// 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 = 'Bad genesis block. Network mismatch between Insight and bitcoind? Insight is configured for:';
|
||||||
|
|
||||||
function HistoricSync() {
|
var BAD_GEN_ERROR_DB = 'Bad genesis block. Network mismatch between Insight and levelDB? Insight is configured for:';
|
||||||
|
function HistoricSync(opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
|
||||||
this.network = config.network === 'testnet' ? networks.testnet: networks.livenet;
|
this.network = config.network === 'testnet' ? networks.testnet: networks.livenet;
|
||||||
|
|
||||||
var genesisHashReversed = new Buffer(32);
|
var genesisHashReversed = new Buffer(32);
|
||||||
this.network.genesisBlock.hash.copy(genesisHashReversed);
|
this.network.genesisBlock.hash.copy(genesisHashReversed);
|
||||||
this.genesis = genesisHashReversed.reverse().toString('hex');
|
buffertools.reverse(genesisHashReversed);
|
||||||
|
this.genesis = genesisHashReversed.toString('hex');
|
||||||
|
|
||||||
|
this.rpc = new RpcClient(config.bitcoind);
|
||||||
|
this.shouldBroadcast = opts.shouldBroadcastSync;
|
||||||
|
this.sync = new Sync(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function p() {
|
function p() {
|
||||||
|
@ -52,7 +61,7 @@ function spec() {
|
||||||
self.updatePercentage();
|
self.updatePercentage();
|
||||||
p(util.format('status: [%d%%]', self.syncPercentage));
|
p(util.format('status: [%d%%]', self.syncPercentage));
|
||||||
}
|
}
|
||||||
if (self.opts.shouldBroadcastSync) {
|
if (self.shouldBroadcast) {
|
||||||
sockets.broadcastSyncInfo(self.info());
|
sockets.broadcastSyncInfo(self.info());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,41 +73,13 @@ function spec() {
|
||||||
|
|
||||||
HistoricSync.prototype.setError = function(err) {
|
HistoricSync.prototype.setError = function(err) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.error = err.toString();
|
self.error = err.message?err.message:err.toString();
|
||||||
self.status='error';
|
self.status='error';
|
||||||
self.showProgress();
|
self.showProgress();
|
||||||
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
HistoricSync.prototype.init = function(opts, cb) {
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
self.opts = opts;
|
|
||||||
|
|
||||||
self.rpc = new RpcClient(config.bitcoind);
|
|
||||||
self.sync = new Sync(opts);
|
|
||||||
|
|
||||||
self.sync.init(opts, function(err) {
|
|
||||||
if (err) {
|
|
||||||
self.setError(err);
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
self.startTs = parseInt(Date.now());
|
|
||||||
|
|
||||||
// check testnet?
|
|
||||||
self.rpc.getBlockHash(0, function(err, res){
|
|
||||||
if (!err && ( res && res.result !== self.genesis)) {
|
|
||||||
err = new Error(BAD_GEN_ERROR + config.network);
|
|
||||||
self.setError(err);
|
|
||||||
}
|
|
||||||
if (err) self.setError(err);
|
|
||||||
return cb(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
HistoricSync.prototype.close = function() {
|
HistoricSync.prototype.close = function() {
|
||||||
this.sync.close();
|
this.sync.close();
|
||||||
|
@ -112,7 +93,6 @@ function spec() {
|
||||||
blockChainHeight: this.blockChainHeight,
|
blockChainHeight: this.blockChainHeight,
|
||||||
syncPercentage: this.syncPercentage,
|
syncPercentage: this.syncPercentage,
|
||||||
syncedBlocks: this.syncedBlocks,
|
syncedBlocks: this.syncedBlocks,
|
||||||
orphanBlocks: this.orphanBlocks,
|
|
||||||
syncTipHash: this.sync.tip,
|
syncTipHash: this.sync.tip,
|
||||||
error: this.error,
|
error: this.error,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
|
@ -127,100 +107,30 @@ function spec() {
|
||||||
if (this.syncPercentage > 100) this.syncPercentage = 100;
|
if (this.syncPercentage > 100) this.syncPercentage = 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
HistoricSync.prototype.getPrevNextBlock = function(blockHash, blockEnd, scanOpts, cb) {
|
HistoricSync.prototype.getBlockFromRPC = function(cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
// recursion end.
|
if (!self.currentRpcHash) return cb();
|
||||||
if (!blockHash) return cb();
|
|
||||||
|
|
||||||
var existed = false;
|
|
||||||
var blockInfo;
|
var blockInfo;
|
||||||
|
self.rpc.getBlock(self.currentRpcHash, function(err, ret) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
if (ret) {
|
||||||
|
blockInfo = ret.result;
|
||||||
|
// this is to match block retreived from file
|
||||||
|
if (blockInfo.hash === self.genesis)
|
||||||
|
blockInfo.previousblockhash =
|
||||||
|
self.network.genesisBlock.prev_hash.toString('hex');
|
||||||
|
|
||||||
async.series([
|
self.currentRpcHash = blockInfo.nextblockhash;
|
||||||
// Already got it?
|
|
||||||
function(c) {
|
|
||||||
self.sync.bDb.has(blockHash, function(err, ret) {
|
|
||||||
if (err) {
|
|
||||||
p(err);
|
|
||||||
return c(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) existed = true;
|
|
||||||
return c();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
//show some (inacurate) status
|
|
||||||
function(c) {
|
|
||||||
self.showProgress();
|
|
||||||
return c();
|
|
||||||
},
|
|
||||||
|
|
||||||
function(c) {
|
|
||||||
self.rpc.getBlock(blockHash, function(err, ret) {
|
|
||||||
if (err) return c(err);
|
|
||||||
if (ret) {
|
|
||||||
blockInfo = ret.result;
|
|
||||||
// this is to match block retreived from file
|
|
||||||
if (blockInfo.hash === self.genesis)
|
|
||||||
blockInfo.previousblockhash = self.network.genesisBlock.prev_hash.toString('hex');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
blockInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return c();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
//store it
|
|
||||||
function(c) {
|
|
||||||
if (existed) return c();
|
|
||||||
|
|
||||||
// When storing files from RPC recusively, reorgs are disabled
|
|
||||||
self.sync.storeTipBlock(blockInfo, false, function(err) {
|
|
||||||
return c(err);
|
|
||||||
});
|
|
||||||
}], function(err) {
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
self.setError(util.format('ERROR: @%s: %s [count: syncedBlocks: %d]',
|
|
||||||
blockHash, err, self.syncedBlocks));
|
|
||||||
return cb(err);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.status = 'syncing';
|
blockInfo = null;
|
||||||
}
|
}
|
||||||
|
return cb(null, blockInfo);
|
||||||
if ( blockEnd && blockEnd === blockHash) {
|
|
||||||
p('blockEnd found!:' + blockEnd);
|
|
||||||
self.found=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( self.found && self.syncedBlocks >= self.blockChainHeight ) {
|
|
||||||
|
|
||||||
self.endTs = parseInt(Date.now());
|
|
||||||
self.status = 'finished';
|
|
||||||
p('DONE. Height: ' , self.syncedBlocks);
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continue
|
|
||||||
if (blockInfo) {
|
|
||||||
|
|
||||||
self.syncedBlocks++;
|
|
||||||
|
|
||||||
// recursion
|
|
||||||
if (scanOpts.prev && blockInfo.previousblockhash)
|
|
||||||
return self.getPrevNextBlock(blockInfo.previousblockhash, blockEnd, scanOpts, cb);
|
|
||||||
|
|
||||||
if (scanOpts.next && blockInfo.nextblockhash)
|
|
||||||
return self.getPrevNextBlock(blockInfo.nextblockhash, blockEnd, scanOpts, cb);
|
|
||||||
}
|
|
||||||
return cb(err);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//var a=1;
|
|
||||||
HistoricSync.prototype.getBlockFromFile = function(cb) {
|
HistoricSync.prototype.getBlockFromFile = function(cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -228,12 +138,8 @@ function spec() {
|
||||||
|
|
||||||
//get Info
|
//get Info
|
||||||
self.blockExtractor.getNextBlock(function(err, b) {
|
self.blockExtractor.getNextBlock(function(err, b) {
|
||||||
// a++;
|
|
||||||
//return cb(null,{previousblockhash:a.toString(), hash:(a-1).toString() });
|
|
||||||
if (err || ! b) return cb(err);
|
if (err || ! b) return cb(err);
|
||||||
blockInfo = b.getStandardizedObject(b.txs, self.network);
|
blockInfo = b.getStandardizedObject(b.txs, self.network);
|
||||||
// blockInfo.curWork = Deserialize.intFromCompact(b.bits);
|
|
||||||
// We keep the RPC field names
|
|
||||||
blockInfo.previousblockhash = blockInfo.prev_block;
|
blockInfo.previousblockhash = blockInfo.prev_block;
|
||||||
|
|
||||||
var ti=0;
|
var ti=0;
|
||||||
|
@ -260,241 +166,263 @@ function spec() {
|
||||||
to++;
|
to++;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
self.sync.bDb.setLastFileIndex(self.blockExtractor.currentFileIndex, function(err) {
|
||||||
return cb(err,blockInfo);
|
return cb(err,blockInfo);
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
HistoricSync.prototype.nextBlockFromFile = function(scanOpts, cb) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.showProgress();
|
|
||||||
self.getBlockFromFile(function(err, blockInfo) {
|
|
||||||
if (err) {
|
|
||||||
self.setError(util.format('ERROR: @%s: %s [count: syncedBlocks: %d]',
|
|
||||||
blockInfo ? blockInfo.hash : '-', err, self.syncedBlocks));
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.sync.storeTipBlock(blockInfo, function(err) {
|
|
||||||
if (err) {
|
|
||||||
self.setError(util.format('ERROR: @%s: %s [count: syncedBlocks: %d]',
|
|
||||||
blockInfo ? blockInfo.hash : '-', err, self.syncedBlocks));
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.sync.bDb.setLastFileIndex(self.blockExtractor.currentFileIndex, function(err) {
|
|
||||||
if (err) return cb(err);
|
|
||||||
|
|
||||||
if (blockInfo && blockInfo.hash) {
|
|
||||||
self.syncedBlocks++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.endTs = parseInt(Date.now());
|
|
||||||
self.status = 'finished';
|
|
||||||
}
|
|
||||||
|
|
||||||
return cb(err);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HistoricSync.prototype.updateConnectedCountDB = function(cb) {
|
||||||
HistoricSync.prototype.countNotOrphan = function(cb) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
self.sync.bDb.countConnected(function(err, count) {
|
||||||
if (self.notOrphanCount) return cb(null, self.notOrphanCount);
|
self.connectedCountDB = count || 0;
|
||||||
|
self.syncedBlocks = count || 0;
|
||||||
|
return cb(err);
|
||||||
self.sync.bDb.countNotOrphan(function(err, count) {
|
|
||||||
if (err) return cb(err);
|
|
||||||
self.notOrphanCount = count;
|
|
||||||
return cb(null, self.notOrphanCount);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
HistoricSync.prototype.updateBlockCount = function(cb) {
|
HistoricSync.prototype.updateBlockChainHeight = function(cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (self.blockChainHeight) return cb();
|
|
||||||
|
|
||||||
self.rpc.getBlockCount(function(err, res) {
|
self.rpc.getBlockCount(function(err, res) {
|
||||||
if (err) return cb(err);
|
|
||||||
self.blockChainHeight = res.result;
|
self.blockChainHeight = res.result;
|
||||||
return cb();
|
return cb(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
HistoricSync.prototype.smartImport = function(scanOpts, next) {
|
|
||||||
|
HistoricSync.prototype.checkNetworkSettings = function(next) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var genesis, count;
|
self.hasGenesis = false;
|
||||||
var lastBlock;
|
|
||||||
var tip;
|
|
||||||
|
|
||||||
//available status: starting / syncing / finished / aborted
|
// check network config
|
||||||
this.status = 'starting';
|
self.rpc.getBlockHash(0, function(err, res){
|
||||||
this.error = null;
|
if (!err && ( res && res.result !== self.genesis)) {
|
||||||
|
err = new Error(BAD_GEN_ERROR + config.network);
|
||||||
this.syncPercentage = 0;
|
}
|
||||||
this.syncedBlocks = 0;
|
if (err) return next(err);
|
||||||
this.orphanBlocks = 0;
|
self.sync.bDb.has(self.genesis, function(err, b) {
|
||||||
this.type ='';
|
if (!err && ( res && res.result !== self.genesis)) {
|
||||||
|
err = new Error(BAD_GEN_ERROR_DB + config.network);
|
||||||
async.series([
|
|
||||||
function(s_c) {
|
|
||||||
if (!scanOpts.destroy) return s_c();
|
|
||||||
|
|
||||||
p('Deleting DB...');
|
|
||||||
return self.sync.destroy(s_c);
|
|
||||||
},
|
|
||||||
function(s_c) {
|
|
||||||
self.sync.bDb.has(self.genesis, function(err, b) {
|
|
||||||
genesis = b;
|
|
||||||
return s_c(err);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(s_c) {
|
|
||||||
self.countNotOrphan(function(err, c) {
|
|
||||||
count = c;
|
|
||||||
return s_c(err);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(s_c) {
|
|
||||||
if (!config.bitcoind.dataDir) return s_c();
|
|
||||||
if (scanOpts.startFile) {
|
|
||||||
self.blockExtractor = new BlockExtractor(config.bitcoind.dataDir, config.network);
|
|
||||||
self.blockExtractor.currentFileIndex = scanOpts.startFile;
|
|
||||||
return s_c();
|
|
||||||
}
|
}
|
||||||
self.sync.bDb.getLastFileIndex(function(err, idx) {
|
self.hasGenesis = b?true:false;
|
||||||
self.blockExtractor = new BlockExtractor(config.bitcoind.dataDir, config.network);
|
return next(err);
|
||||||
if (idx) self.blockExtractor.currentFileIndex = idx;
|
});
|
||||||
return s_c(err);
|
});
|
||||||
});
|
};
|
||||||
},
|
|
||||||
function(s_c) {
|
|
||||||
self.updateBlockCount(s_c);
|
|
||||||
},
|
|
||||||
|
|
||||||
// define sync strategy
|
HistoricSync.prototype.updateStartBlock = function(next) {
|
||||||
function(s_c) {
|
var self = this;
|
||||||
if (!genesis || scanOpts.destroy || count < self.blockChainHeight * 0.9 ) {
|
|
||||||
|
|
||||||
// Full sync.
|
self.startBlock = self.genesis;
|
||||||
if (!genesis)
|
|
||||||
p('Could not find Genesis block. Running FULL SYNC');
|
|
||||||
else
|
|
||||||
p('Less that 90% of current blockchain is stored. Running FULL SYNC',
|
|
||||||
parseInt(count/self.blockChainHeight*100));
|
|
||||||
|
|
||||||
if (config.bitcoind.dataDir) {
|
self.sync.bDb.getTip(function(err,tip) {
|
||||||
p('bitcoind dataDir configured...importing blocks from .dat files');
|
if (!tip) return next();
|
||||||
p('Starting from file: ' + self.blockExtractor.currentFileIndex);
|
|
||||||
scanOpts.fromFiles = true;
|
var blockInfo;
|
||||||
|
var oldtip;
|
||||||
|
|
||||||
|
//check that the tip is still on the mainchain
|
||||||
|
async.doWhilst(
|
||||||
|
function(cb) {
|
||||||
|
self.sync.bDb.fromHashWithInfo(tip, function(err, bi) {
|
||||||
|
blockInfo = bi ? bi.info : {};
|
||||||
|
if (oldtip)
|
||||||
|
self.sync.setBlockMain(oldtip, false, cb);
|
||||||
|
else
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
if (err) return next(err);
|
||||||
|
var ret = false;
|
||||||
|
if ( self.blockChainHeight === blockInfo.height ||
|
||||||
|
blockInfo.confirmations > 0) {
|
||||||
|
ret = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scanOpts.reverse = true;
|
oldtip = tip;
|
||||||
|
tip = blockInfo.previousblockhash;
|
||||||
|
assert(tip);
|
||||||
|
p('Previous TIP is now orphan. Back to:' + tip);
|
||||||
|
ret = true;
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
self.startBlock = tip;
|
||||||
|
p('Resuming sync from block:'+tip);
|
||||||
|
return next(err);
|
||||||
}
|
}
|
||||||
else {
|
);
|
||||||
p('Genesis block found. Syncing upto old TIP.');
|
});
|
||||||
p('Got ' + count + ' out of ' + self.blockChainHeight + ' blocks');
|
};
|
||||||
scanOpts.reverse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scanOpts.reverse) return s_c();
|
HistoricSync.prototype.prepareFileSync = function(opts, next) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
self.rpc.getBlockHash(self.blockChainHeight, function(err, res) {
|
if ( opts.forceRPC || !config.bitcoind.dataDir ||
|
||||||
if (err) return s_c(err);
|
self.connectedCountDB > self.blockChainHeight * 0.9) return next();
|
||||||
lastBlock = res.result;
|
|
||||||
return s_c();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(s_c) {
|
|
||||||
if (!scanOpts.reverse) return s_c();
|
|
||||||
self.sync.bDb.getTip(function(err, res) {
|
|
||||||
if (err) return s_c(err);
|
|
||||||
tip = res;
|
|
||||||
|
|
||||||
console.log('Old Tip:', tip);
|
|
||||||
return s_c();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(s_c) {
|
|
||||||
if (!scanOpts.reverse) return s_c();
|
|
||||||
self.countNotOrphan(function(err, count) {
|
|
||||||
if (err) return s_c(err);
|
|
||||||
|
|
||||||
self.syncedBlocks = count || 0;
|
|
||||||
return s_c();
|
|
||||||
});
|
|
||||||
}],
|
|
||||||
function(err) {
|
|
||||||
// SETUP Sync params
|
|
||||||
var start, end;
|
|
||||||
if (err) {
|
|
||||||
self.setError(err);
|
|
||||||
return next(err, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self.step) {
|
|
||||||
var step = parseInt( (self.blockChainHeight - self.syncedBlocks) / 1000);
|
|
||||||
|
|
||||||
if (self.opts.progressStep) {
|
|
||||||
step = self.opts.progressStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (step < 10) step = 10;
|
|
||||||
self.step = step;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scanOpts.reverse) {
|
|
||||||
start = lastBlock;
|
|
||||||
end = tip || self.genesis;
|
|
||||||
scanOpts.prev = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
start = self.genesis;
|
|
||||||
end = null;
|
|
||||||
scanOpts.next = true;
|
|
||||||
}
|
|
||||||
p('Starting from: ', start);
|
|
||||||
p(' to : ', end);
|
|
||||||
p(' scanOpts: ', JSON.stringify(scanOpts));
|
|
||||||
|
|
||||||
if (scanOpts.fromFiles) {
|
|
||||||
|
|
||||||
self.status = 'syncing';
|
|
||||||
self.type = 'from .dat Files';
|
|
||||||
|
|
||||||
|
|
||||||
async.whilst(function() {
|
try {
|
||||||
return self.status === 'syncing';
|
self.blockExtractor = new BlockExtractor(config.bitcoind.dataDir, config.network);
|
||||||
}, function (w_cb) {
|
} catch (e) {
|
||||||
self.nextBlockFromFile(scanOpts, function(err) {
|
p(e.message + '. Disabling file sync.');
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getFn = self.getBlockFromFile;
|
||||||
|
self.allowReorgs = true;
|
||||||
|
self.sync.bDb.getLastFileIndex(function(err, idx) {
|
||||||
|
if (opts.forceStartFile)
|
||||||
|
self.blockExtractor.currentFileIndex = opts.forceStartFile;
|
||||||
|
else if (idx) self.blockExtractor.currentFileIndex = idx;
|
||||||
|
|
||||||
|
var h = self.genesis;
|
||||||
|
|
||||||
|
p('Seeking file to:' + self.startBlock);
|
||||||
|
//forward till startBlock
|
||||||
|
async.whilst(
|
||||||
|
function() {
|
||||||
|
return h !== self.startBlock;
|
||||||
|
},
|
||||||
|
function (w_cb) {
|
||||||
|
self.getBlockFromFile(function(err,b) {
|
||||||
|
if (!b) return w_cb('Could not find block ' + self.startBlock);
|
||||||
|
h=b.hash;
|
||||||
setImmediate(function(){
|
setImmediate(function(){
|
||||||
return w_cb(err);
|
return w_cb(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, function(err) {
|
}, next);
|
||||||
self.showProgress();
|
|
||||||
return next(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.type = 'from RPC calls';
|
|
||||||
self.getPrevNextBlock(start, end, scanOpts, function(err) {
|
|
||||||
self.showProgress();
|
|
||||||
return next(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//NOP
|
||||||
|
HistoricSync.prototype.prepareRpcSync = function(opts, next) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (self.blockExtractor) return next();
|
||||||
|
self.getFn = self.getBlockFromRPC;
|
||||||
|
self.currentRpcHash = self.startBlock;
|
||||||
|
self.allowReorgs = false;
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
|
||||||
|
HistoricSync.prototype.showSyncStartMessage = function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
p('Got ' + self.connectedCountDB +
|
||||||
|
' blocks in current DB, out of ' + self.blockChainHeight + ' block at bitcoind');
|
||||||
|
|
||||||
|
if (self.blockExtractor) {
|
||||||
|
p('bitcoind dataDir configured...importing blocks from .dat files');
|
||||||
|
p('First file index: ' + self.blockExtractor.currentFileIndex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p('syncing from RPC (slow)');
|
||||||
|
}
|
||||||
|
|
||||||
|
p('Starting from: ', self.startBlock);
|
||||||
|
self.showProgress();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HistoricSync.prototype.setupSyncStatus = function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var step = parseInt( (self.blockChainHeight - self.syncedBlocks) / 1000);
|
||||||
|
if (step < 10) step = 10;
|
||||||
|
|
||||||
|
self.step = step;
|
||||||
|
self.type = self.blockExtractor?'from .dat Files':'from RPC calls';
|
||||||
|
self.status = 'syncing';
|
||||||
|
self.startTs = Date.now();
|
||||||
|
self.endTs = null;
|
||||||
|
this.error = null;
|
||||||
|
this.syncPercentage = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
HistoricSync.prototype.prepareToSync = function(opts, next) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.status = 'starting';
|
||||||
|
async.series([
|
||||||
|
function(s_c) {
|
||||||
|
self.checkNetworkSettings(s_c);
|
||||||
|
},
|
||||||
|
function(s_c) {
|
||||||
|
self.updateConnectedCountDB(s_c);
|
||||||
|
},
|
||||||
|
function(s_c) {
|
||||||
|
self.updateBlockChainHeight(s_c);
|
||||||
|
},
|
||||||
|
function(s_c) {
|
||||||
|
self.updateStartBlock(s_c);
|
||||||
|
},
|
||||||
|
function(s_c) {
|
||||||
|
self.prepareFileSync(opts, s_c);
|
||||||
|
},
|
||||||
|
function(s_c) {
|
||||||
|
self.prepareRpcSync(opts, s_c);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
function(err) {
|
||||||
|
if (err) return(self.setError(err));
|
||||||
|
|
||||||
|
self.showSyncStartMessage();
|
||||||
|
self.setupSyncStatus();
|
||||||
|
return next();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HistoricSync.prototype.start = function(opts, next) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (self.status==='starting' || self.status==='syncing') {
|
||||||
|
p('## Wont start to sync while status is %s', self.status);
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.prepareToSync(opts, function(err) {
|
||||||
|
if (err) return next(self.setError(err));
|
||||||
|
|
||||||
|
async.whilst(
|
||||||
|
function() {
|
||||||
|
self.showProgress();
|
||||||
|
return self.status === 'syncing';
|
||||||
|
},
|
||||||
|
function (w_cb) {
|
||||||
|
self.getFn(function(err,blockInfo) {
|
||||||
|
if (err) return w_cb(self.setError(err));
|
||||||
|
if (blockInfo && blockInfo.hash) {
|
||||||
|
self.syncedBlocks++;
|
||||||
|
self.sync.storeTipBlock(blockInfo, self.allowReorgs, function(err) {
|
||||||
|
if (err) return w_cb(self.setError(err));
|
||||||
|
|
||||||
|
self.sync.bDb.setTip(blockInfo.hash, function(err) {
|
||||||
|
if (err) return w_cb(self.setError(err));
|
||||||
|
|
||||||
|
setImmediate(function(){
|
||||||
|
return w_cb(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.endTs = Date.now();
|
||||||
|
self.status = 'finished';
|
||||||
|
console.log('Done Syncing', self.info());
|
||||||
|
return w_cb(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, next);
|
||||||
|
});
|
||||||
|
};
|
||||||
return HistoricSync;
|
return HistoricSync;
|
||||||
}
|
}
|
||||||
module.defineClass(spec);
|
module.defineClass(spec);
|
||||||
|
|
|
@ -3,8 +3,7 @@ require('classtool');
|
||||||
|
|
||||||
function spec() {
|
function spec() {
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var CoinConst = require('bitcore/const');
|
var bitcoreUtil = require('bitcore/util/util');
|
||||||
var coinUtil = require('bitcore/util/util');
|
|
||||||
var Sync = require('./Sync').class();
|
var Sync = require('./Sync').class();
|
||||||
var Peer = require('bitcore/Peer').class();
|
var Peer = require('bitcore/Peer').class();
|
||||||
var config = require('../config/config');
|
var config = require('../config/config');
|
||||||
|
@ -12,26 +11,17 @@ function spec() {
|
||||||
|
|
||||||
var peerdb_fn = 'peerdb.json';
|
var peerdb_fn = 'peerdb.json';
|
||||||
|
|
||||||
function PeerSync() {}
|
function PeerSync(opts) {
|
||||||
|
|
||||||
|
|
||||||
PeerSync.prototype.init = function(opts, cb) {
|
|
||||||
if (!opts) opts = {};
|
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
this.peerdb = undefined;
|
this.peerdb = undefined;
|
||||||
this.allowReorgs = false;
|
this.allowReorgs = false;
|
||||||
|
|
||||||
this.sync = new Sync();
|
|
||||||
this.PeerManager = require('bitcore/PeerManager').createClass({
|
this.PeerManager = require('bitcore/PeerManager').createClass({
|
||||||
network: (config.network === 'testnet' ? networks.testnet : networks.livenet)
|
network: (config.network === 'testnet' ? networks.testnet : networks.livenet)
|
||||||
});
|
});
|
||||||
this.peerman = new this.PeerManager();
|
this.peerman = new this.PeerManager();
|
||||||
this.load_peers();
|
this.load_peers();
|
||||||
this.sync.init(opts, function() {
|
this.sync = new Sync(opts);
|
||||||
if (!cb) return;
|
}
|
||||||
return cb();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
PeerSync.prototype.load_peers = function() {
|
PeerSync.prototype.load_peers = function() {
|
||||||
this.peerdb = [{
|
this.peerdb = [{
|
||||||
|
@ -72,20 +62,26 @@ function spec() {
|
||||||
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 = coinUtil.formatHashFull(block.calcHash());
|
var blockHash = bitcoreUtil.formatHashFull(block.calcHash());
|
||||||
|
|
||||||
console.log('[p2p_sync] Handle block: %s (allowReorgs: %s)', blockHash, self.allowReorgs);
|
console.log('[p2p_sync] Handle block: %s (allowReorgs: %s)', blockHash, self.allowReorgs);
|
||||||
|
|
||||||
var tx_hashes = block.txs.map(function(tx) {
|
var tx_hashes = block.txs.map(function(tx) {
|
||||||
return coinUtil.formatHashFull(tx.hash);
|
return bitcoreUtil.formatHashFull(tx.hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sync.storeTipBlock({
|
this.sync.storeTipBlock({
|
||||||
'hash': blockHash,
|
'hash': blockHash,
|
||||||
'tx': tx_hashes,
|
'tx': tx_hashes,
|
||||||
'previousblockhash': coinUtil.formatHashFull(block.prev_hash),
|
'previousblockhash': bitcoreUtil.formatHashFull(block.prev_hash),
|
||||||
}, self.allowReorgs, function(err) {
|
}, self.allowReorgs, function(err) {
|
||||||
if (err) {
|
if (err && err.message.match(/NEED_SYNC/) && self.historicSync) {
|
||||||
|
console.log('[p2p_sync] Orphan block received. Triggering sync');
|
||||||
|
self.historicSync.start({}, function(){
|
||||||
|
console.log('[p2p_sync] Done resync.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (err) {
|
||||||
console.log('[p2p_sync] Error in handle Block: ' + err);
|
console.log('[p2p_sync] Error in handle Block: ' + err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,36 +11,28 @@ function spec(b) {
|
||||||
var PoolMatch = function() {
|
var PoolMatch = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.strings={};
|
self.strings = {};
|
||||||
db.forEach(function(pool) {
|
db.forEach(function(pool) {
|
||||||
pool.searchStrings.forEach(function(s) {
|
pool.searchStrings.forEach(function(s) {
|
||||||
if (!self.strings[s]) self.strings[s] = [];
|
self.strings[s] = {
|
||||||
self.strings[s].push(pool);
|
poolName: pool.poolName,
|
||||||
|
url: pool.url
|
||||||
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Object.keys( self.strings, function(s) {
|
|
||||||
delete self.strings[s].searchStrings;
|
|
||||||
});
|
|
||||||
self.stringsK = Object.keys(self.strings);
|
|
||||||
self.stringsKl = self.stringsK.length;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PoolMatch.prototype.match = function(buffer) {
|
PoolMatch.prototype.match = function(buffer) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
for(var k in self.strings) {
|
||||||
var match;
|
if (buffertools.indexOf(buffer, k) >= 0) {
|
||||||
var i =0;
|
return self.strings[k];
|
||||||
while (!match && i < self.stringsKl) {
|
|
||||||
var k = self.stringsK[i++];
|
|
||||||
if ( buffertools.indexOf(buffer,self.strings[k]) >= 0 ) {
|
|
||||||
match = self.strings[k];
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
return match;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return PoolMatch;
|
return PoolMatch;
|
||||||
}
|
}
|
||||||
module.defineClass(spec);
|
module.defineClass(spec);
|
||||||
|
|
||||||
|
|
||||||
|
|
35
lib/Sync.js
35
lib/Sync.js
|
@ -13,20 +13,15 @@ function spec() {
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
|
||||||
|
|
||||||
function Sync() {}
|
function Sync(opts) {
|
||||||
|
this.opts = opts || {};
|
||||||
Sync.prototype.init = function(opts, cb) {
|
|
||||||
var self = this;
|
|
||||||
self.opts = opts;
|
|
||||||
this.bDb = new BlockDb(opts);
|
this.bDb = new BlockDb(opts);
|
||||||
this.txDb = new TransactionDb(opts);
|
this.txDb = new TransactionDb(opts);
|
||||||
this.txDb.on('tx_for_address', this.handleTxForAddress.bind(this));
|
this.txDb.on('tx_for_address', this.handleTxForAddress.bind(this));
|
||||||
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;
|
||||||
return cb();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
Sync.prototype.close = function(cb) {
|
Sync.prototype.close = function(cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -74,7 +69,8 @@ function spec() {
|
||||||
*
|
*
|
||||||
* A-B-C-D-E(TIP) ... NEW
|
* A-B-C-D-E(TIP) ... NEW
|
||||||
*
|
*
|
||||||
* NEW is ignored
|
* NEW is ignored (if allowReorgs is false)
|
||||||
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -100,15 +96,11 @@ function spec() {
|
||||||
},
|
},
|
||||||
function(c) {
|
function(c) {
|
||||||
if (!allowReorgs) return c();
|
if (!allowReorgs) return c();
|
||||||
|
|
||||||
self.bDb.has(newPrev, function(err, val) {
|
self.bDb.has(newPrev, function(err, val) {
|
||||||
if (!val && newPrev.match(/^0+$/)) return c();
|
if (!val && newPrev.match(/^0+$/)) return c();
|
||||||
/// AQUI! -> return is reor...
|
|
||||||
//
|
|
||||||
// needSync
|
|
||||||
// =>
|
|
||||||
return c(err ||
|
return c(err ||
|
||||||
(!val ? new Error('WARN: Ignoring block with non existing prev:' + b.hash) : null));
|
(!val ? new Error('NEED_SYNC Ignoring block with non existing prev:' + b.hash) : null));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(c) {
|
function(c) {
|
||||||
|
@ -126,7 +118,6 @@ function spec() {
|
||||||
},
|
},
|
||||||
function(c) {
|
function(c) {
|
||||||
if (!needReorg) return c();
|
if (!needReorg) return c();
|
||||||
|
|
||||||
self.bDb.getNext(newPrev, function(err, val) {
|
self.bDb.getNext(newPrev, function(err, val) {
|
||||||
if (err) return c(err);
|
if (err) return c(err);
|
||||||
oldNext = val;
|
oldNext = val;
|
||||||
|
@ -142,13 +133,17 @@ function spec() {
|
||||||
self.processReorg(oldTip, oldNext, newPrev, c);
|
self.processReorg(oldTip, oldNext, newPrev, c);
|
||||||
},
|
},
|
||||||
function(c) {
|
function(c) {
|
||||||
|
if (!allowReorgs) return c();
|
||||||
self.bDb.setTip(b.hash, function(err) {
|
self.bDb.setTip(b.hash, function(err) {
|
||||||
if (err) return c(err);
|
return c(err);
|
||||||
self.bDb.setNext(newPrev, b.hash, function(err) {
|
});
|
||||||
return c(err);
|
},
|
||||||
});
|
function(c) {
|
||||||
|
self.bDb.setNext(newPrev, b.hash, function(err) {
|
||||||
|
return c(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
function(err) {
|
function(err) {
|
||||||
if (err && err.toString().match(/WARN/)) {
|
if (err && err.toString().match(/WARN/)) {
|
||||||
|
|
|
@ -137,7 +137,7 @@ function spec(b) {
|
||||||
})
|
})
|
||||||
.on('end', function() {
|
.on('end', function() {
|
||||||
|
|
||||||
var k = SPENT_PREFIX + txid;
|
var k = SPENT_PREFIX + txid + '-';
|
||||||
db.createReadStream({
|
db.createReadStream({
|
||||||
start: k,
|
start: k,
|
||||||
end: k + '~'
|
end: k + '~'
|
||||||
|
@ -166,7 +166,7 @@ function spec(b) {
|
||||||
|
|
||||||
if (!info) return cb();
|
if (!info) return cb();
|
||||||
|
|
||||||
var k = SPENT_PREFIX + info.txid;
|
var k = SPENT_PREFIX + info.txid + '-';
|
||||||
db.createReadStream({
|
db.createReadStream({
|
||||||
start: k,
|
start: k,
|
||||||
end: k + '~'
|
end: k + '~'
|
||||||
|
@ -311,7 +311,7 @@ isspent
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// spent?
|
// spent?
|
||||||
var k = SPENT_PREFIX + txid + '-' + n;
|
var k = SPENT_PREFIX + txid + '-' + n + '-';
|
||||||
db.createReadStream({
|
db.createReadStream({
|
||||||
start: k,
|
start: k,
|
||||||
end: k + '~'
|
end: k + '~'
|
||||||
|
@ -365,7 +365,7 @@ 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 + '-';
|
||||||
var ret = [];
|
var ret = [];
|
||||||
|
|
||||||
db.createReadStream({
|
db.createReadStream({
|
||||||
|
@ -388,7 +388,7 @@ isspent
|
||||||
.on('end', function() {
|
.on('end', function() {
|
||||||
|
|
||||||
async.eachLimit(ret, CONCURRENCY, function(o, e_c) {
|
async.eachLimit(ret, 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,
|
||||||
end: k + '~'
|
end: k + '~'
|
||||||
|
@ -415,14 +415,13 @@ isspent
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 + '-',
|
||||||
end: OUTS_PREFIX + txid + '~',
|
end: OUTS_PREFIX + txid + '~',
|
||||||
}).pipe(
|
}).pipe(
|
||||||
db.createWriteStream({
|
db.createWriteStream({
|
||||||
|
@ -432,7 +431,7 @@ isspent
|
||||||
},
|
},
|
||||||
function(c) {
|
function(c) {
|
||||||
db.createReadStream({
|
db.createReadStream({
|
||||||
start: SPENT_PREFIX + txid,
|
start: SPENT_PREFIX + txid + '-',
|
||||||
end: SPENT_PREFIX + txid + '~'
|
end: SPENT_PREFIX + txid + '~'
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -578,7 +577,7 @@ isspent
|
||||||
addrs.push(addr);
|
addrs.push(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// existed?
|
// existed?
|
||||||
var k = OUTS_PREFIX + tx.txid + '-' + o.n;
|
var k = OUTS_PREFIX + tx.txid + '-' + o.n;
|
||||||
db.get(k, function(err) {
|
db.get(k, function(err) {
|
||||||
if (err && err.notFound) {
|
if (err && err.notFound) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "insight-bitcore",
|
"name": "insight-bitcore",
|
||||||
"version": "0.1.0",
|
"description": "An open-source bitcoin blockchain API. The Insight API provides you with a convenient, powerful and simple way to query and broadcast data on the bitcoin network and build your own services with it.",
|
||||||
|
"version": "0.1.2",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Ryan X Charles",
|
"name": "Ryan X Charles",
|
||||||
"email": "ryan@bitpay.com"
|
"email": "ryan@bitpay.com"
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
"email": "cmgustavo83@gmail.com"
|
"email": "cmgustavo83@gmail.com"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Juan Sosa",
|
"name": "Juan Ignacio Sosa Lopez",
|
||||||
"email": "bechilandia@gmail.com"
|
"email": "bechilandia@gmail.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -23,10 +23,10 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
|
|
||||||
/* Styling for the ngProgress itself */
|
/* Styling for the ngProgress itself */
|
||||||
#ngProgress {
|
#ngProgress {
|
||||||
background-color: #373D42 !important;
|
background-color: #6C9032 !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
color: #373D42 !important;
|
color: #373D42 !important;
|
||||||
height: 4px !important;
|
height: 3px !important;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -44,7 +44,7 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
top: 50px;
|
top: 63px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
|
@ -67,25 +67,36 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
.m10v { margin: 10px 0; }
|
.m10v { margin: 10px 0; }
|
||||||
.m50v { margin: 50px 0; }
|
.m50v { margin: 50px 0; }
|
||||||
.m10b { margin-bottom: 10px; }
|
.m10b { margin-bottom: 10px; }
|
||||||
|
.m10l { margin-left: 10px; }
|
||||||
|
|
||||||
.vm { vertical-align: middle; }
|
.vm { vertical-align: middle; }
|
||||||
|
|
||||||
|
.navbar-default .navbar-toggle {
|
||||||
|
border-color: #fff;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-default .navbar-toggle .icon-bar { background-color: #fff; }
|
||||||
|
.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus {background-color: #373D42;}
|
||||||
|
|
||||||
.navbar-default {
|
.navbar-default {
|
||||||
background-color: #8DC429;
|
background-color: #8DC429;
|
||||||
border-bottom: 4px solid #64920F;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-default .navbar-nav>li>a {
|
.navbar-default .navbar-nav>li>a {
|
||||||
color: #F4FBE8;
|
color: #F4FBE8;
|
||||||
font-family: 'Ubuntu', sans-serif;
|
font-family: 'Ubuntu', sans-serif;
|
||||||
|
padding-left: 25px;
|
||||||
|
padding-right: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, .navbar-default .navbar-nav>li>a:hover {
|
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus {
|
||||||
|
background-color: #6C9032;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-default .navbar-nav>li>a:hover, .navbar-default .navbar-nav>.active>a:hover {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
-webkit-box-shadow: 0px 4px 0px 0px rgba(55,61,56,1);
|
|
||||||
-moz-box-shadow: 0px 4px 0px 0px rgba(55,61,56,1);
|
|
||||||
box-shadow: 0px 4px 0px 0px rgba(55,61,56,1);
|
|
||||||
color: #373D42;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-form .form-group {
|
.navbar-form .form-group {
|
||||||
|
@ -93,7 +104,9 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-form {
|
.navbar-form {
|
||||||
|
margin-left: 20px;
|
||||||
width: 35%;
|
width: 35%;
|
||||||
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 991px) {
|
@media (max-width: 991px) {
|
||||||
|
@ -128,6 +141,8 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
|
|
||||||
.navbar-default .navbar-brand {
|
.navbar-default .navbar-brand {
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
|
margin-right: 20px;
|
||||||
|
padding: 22px 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-form .form-control {
|
.navbar-form .form-control {
|
||||||
|
@ -141,6 +156,11 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10);
|
box-shadow: 1px 1px 0px 0px rgba(255,255,255,0.41), inset 1px 1px 3px 0px rgba(0,0,0,0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar-nav>li>a {
|
||||||
|
padding-top: 22px;
|
||||||
|
padding-bottom: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
#search {
|
#search {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-family: 'Ubuntu', sans-serif;
|
font-family: 'Ubuntu', sans-serif;
|
||||||
|
@ -173,7 +193,7 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 3px;
|
||||||
background-color: #597338;
|
background-color: #597338;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin: 8px 0;
|
margin: 15px 0;
|
||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
|
@ -198,6 +218,7 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-gray-fixed {
|
.col-gray-fixed {
|
||||||
|
margin-top: 15px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
|
@ -247,11 +268,11 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
width: 165px;
|
width: 165px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 80px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-id span {
|
.block-id span {
|
||||||
margin-top: 10px;
|
font-size: 40px;
|
||||||
|
margin: 30px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-id h2 {
|
.block-id h2 {
|
||||||
|
@ -303,9 +324,12 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
color: #373D42;
|
color: #373D42;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-default {
|
.btn-default {
|
||||||
background-color: #E7E7E7;
|
background-color: #E7E7E7;
|
||||||
border: 2px solid #DCDCDC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-success {
|
.btn-success {
|
||||||
|
@ -360,18 +384,11 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
/* Set the fixed height of the footer here */
|
/* Set the fixed height of the footer here */
|
||||||
#footer {
|
#footer {
|
||||||
background-color: #373D42;
|
background-color: #373D42;
|
||||||
border-top: 4px solid #656E76;
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
height: 51px;
|
height: 51px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.currency a.active {
|
|
||||||
color: #000;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer a.insight {
|
#footer a.insight {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -399,7 +416,7 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
-------------------------------------------------- */
|
-------------------------------------------------- */
|
||||||
/* Not required for template or sticky footer method. */
|
/* Not required for template or sticky footer method. */
|
||||||
|
|
||||||
#wrap > .container { padding: 60px 15px 0; }
|
#wrap > .container { padding: 70px 15px 0; }
|
||||||
|
|
||||||
#footer > .container { padding: auto 15px; }
|
#footer > .container { padding: auto 15px; }
|
||||||
|
|
||||||
|
@ -499,6 +516,11 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-copy:hover, .btn-expand:hover {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-copy {
|
.btn-copy {
|
||||||
background: #fff url('/img/icons/copy.png') center center no-repeat;
|
background: #fff url('/img/icons/copy.png') center center no-repeat;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
@ -529,10 +551,14 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 165px;
|
width: 165px;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
font-size: 80px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tx-id span {
|
||||||
|
font-size: 40px;
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.transaction-vin-vout .ellipsis { margin-bottom: 10px; }
|
.transaction-vin-vout .ellipsis { margin-bottom: 10px; }
|
||||||
.transaction-vin-vout .btc-value { margin-left: 15px; }
|
.transaction-vin-vout .btc-value { margin-left: 15px; }
|
||||||
|
|
||||||
|
|
|
@ -59,16 +59,15 @@ function($scope, $rootScope, $routeParams, $location, Global, Transaction, Trans
|
||||||
tmp[addr].unconfirmedInput += items[i].unconfirmedInput;
|
tmp[addr].unconfirmedInput += items[i].unconfirmedInput;
|
||||||
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
|
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
|
||||||
tmp[addr].valueSat += items[i].value * COIN;
|
tmp[addr].valueSat += items[i].value * COIN;
|
||||||
tmp[addr].value = tmp[addr].valueSat / COIN;
|
|
||||||
tmp[addr].items.push(items[i]);
|
tmp[addr].items.push(items[i]);
|
||||||
tmp[addr].notAddr = notAddr;
|
tmp[addr].notAddr = notAddr;
|
||||||
tmp[addr].count++;
|
tmp[addr].count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
angular.forEach(tmp, function(v) {
|
angular.forEach(tmp, function(v) {
|
||||||
|
v.value = parseInt(v.valueSat) / COIN;
|
||||||
ret.push(v);
|
ret.push(v);
|
||||||
});
|
});
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -49,14 +49,15 @@ angular.module('insight')
|
||||||
};
|
};
|
||||||
|
|
||||||
client.on('mousedown', onMousedown);
|
client.on('mousedown', onMousedown);
|
||||||
client.on('noflash wrongflash', function() {
|
|
||||||
return elm.remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.$on('$destroy', function() {
|
scope.$on('$destroy', function() {
|
||||||
client.off('mousedown', onMousedown);
|
client.off('mousedown', onMousedown);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
clip.on('noFlash wrongflash', function() {
|
||||||
|
return elm.remove();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
<h1 class="text-center">Address</h1>
|
<h1 class="text-center">Address</h1>
|
||||||
<div class="m20v text-center text-muted" data-ng-if="!address.addrStr">
|
<div class="m20v text-center text-muted" data-ng-if="!address.addrStr">
|
||||||
<span>Loading Address Information...</span>
|
<span>Loading Address Information...</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ng-cloak" data-ng-cloak data-ng-if="address.addrStr">
|
<div class="ng-cloak" data-ng-cloak data-ng-if="address.addrStr">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<qrcode size="160" data="{{address.addrStr}}"></qrcode>
|
<qrcode size="160" data="{{address.addrStr}}"></qrcode>
|
||||||
|
<h4>{{$root.currency.getConvertion(address.balance)}}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="m10v">
|
<div class="m10v">
|
||||||
<button class="pull-right btn-copy" clip-copy="address.addrStr"></button>
|
<button class="pull-right btn-copy" clip-copy="address.addrStr"></button>
|
||||||
|
@ -66,3 +67,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- END OF ROW -->
|
</div> <!-- END OF ROW -->
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<h1 class="text-center">Block</h1>
|
<h1 class="text-center">Block</h1>
|
||||||
<div class="m20v text-center text-muted" data-ng-if="!block.hash">
|
<div class="m20v text-center text-muted" data-ng-if="!block.hash">
|
||||||
<span>Loading Block...</span>
|
<span>Loading Block...</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ng-cloak" data-ng-cloak data-ng-if="block.hash">
|
<div class="ng-cloak" data-ng-cloak data-ng-if="block.hash">
|
||||||
<div class="block-id">
|
<div class="block-id">
|
||||||
<span class="glyphicon glyphicon-list-alt"></span>
|
<span class="glyphicon glyphicon-list-alt"></span>
|
||||||
|
@ -54,6 +54,7 @@
|
||||||
<td class="text-right text-muted">{{block.height}}
|
<td class="text-right text-muted">{{block.height}}
|
||||||
<span data-ng-show="block.isMainChain" class="text-success">(Mainchain)</span>
|
<span data-ng-show="block.isMainChain" class="text-success">(Mainchain)</span>
|
||||||
<span data-ng-show="!block.isMainChain" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Orphaned)</span>
|
<span data-ng-show="!block.isMainChain" class="text-danger"> <span class="glyphicon glyphicon-warning-sign"></span> (Orphaned)</span>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Block Reward</strong></td>
|
<td><strong>Block Reward</strong></td>
|
||||||
|
@ -63,6 +64,12 @@
|
||||||
<td><strong>Timestamp</strong></td>
|
<td><strong>Timestamp</strong></td>
|
||||||
<td class="text-right text-muted">{{block.time * 1000 | date:'medium'}}</td>
|
<td class="text-right text-muted">{{block.time * 1000 | date:'medium'}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr data-ng-show="block.poolInfo">
|
||||||
|
<td><strong>Relayed by</strong></td>
|
||||||
|
<td class="text-right text-muted">
|
||||||
|
<a href="{{block.poolInfo.url}}" target="_blank" title="{{block.poolInfo.poolName}}">{{block.poolInfo.poolName}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>Merkle Root</strong></td>
|
<td><strong>Merkle Root</strong></td>
|
||||||
<td class="text-right text-muted">
|
<td class="text-right text-muted">
|
||||||
|
@ -109,3 +116,4 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
<p class="text-center m20v" data-ng-show="pagination.isToday && !loading">Today</p>
|
<p class="text-center m20v" data-ng-show="pagination.isToday && !loading">Today</p>
|
||||||
<p class="text-center m20v" data-ng-show="!pagination.isToday && !loading">{{humanSince(pagination.currentTs)}}
|
<p class="text-center m20v" data-ng-show="!pagination.isToday && !loading">{{humanSince(pagination.currentTs)}}
|
||||||
<p class="text-center m20v" data-ng-show="loading"> </p>
|
<p class="text-center m20v" data-ng-show="loading"> </p>
|
||||||
|
|
||||||
<div class="m50v text-center">
|
<div class="m50v text-center">
|
||||||
<a class="btn btn-primary" href="/blocks-date/{{pagination.prev}}"><small>← {{pagination.prev}}</small></a>
|
<a class="btn btn-primary" href="/blocks-date/{{pagination.prev}}"><small>← {{pagination.prev}}</small></a>
|
||||||
<a class="btn btn-primary" href="/blocks-date/{{pagination.next}}" data-ng-show="!pagination.isToday"><small>{{pagination.next}} →</small></a>
|
<a class="btn btn-primary" href="/blocks-date/{{pagination.next}}" data-ng-show="!pagination.isToday"><small>{{pagination.next}} →</small></a>
|
||||||
|
@ -40,6 +39,7 @@
|
||||||
<th>Height</th>
|
<th>Height</th>
|
||||||
<th>Timestamp</th>
|
<th>Timestamp</th>
|
||||||
<th class="text-right">Transactions</th>
|
<th class="text-right">Transactions</th>
|
||||||
|
<th class="text-right">Relayed by</th>
|
||||||
<th class="text-right">Size</th>
|
<th class="text-right">Size</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -51,6 +51,7 @@
|
||||||
<td><a href="/block/{{b.hash}}">{{b.height}}</a></td>
|
<td><a href="/block/{{b.hash}}">{{b.height}}</a></td>
|
||||||
<td>{{b.time * 1000 | date:'medium'}}</td>
|
<td>{{b.time * 1000 | date:'medium'}}</td>
|
||||||
<td class="text-right">{{b.txlength}}</td>
|
<td class="text-right">{{b.txlength}}</td>
|
||||||
|
<td class="text-right"><a href="{{b.poolInfo.url}}" title="{{b.poolInfo.poolName}}" target="_blank" data-ng-show="b.poolInfo">{{b.poolInfo.poolName}}</a></td>
|
||||||
<td class="text-right">{{b.size}}</td>
|
<td class="text-right">{{b.size}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -59,3 +60,4 @@
|
||||||
</div>
|
</div>
|
||||||
<h2 class="text-center text-muted" data-ng-show="!blocks.length && !loading">No blocks yet.</h2>
|
<h2 class="text-center text-muted" data-ng-show="!blocks.length && !loading">No blocks yet.</h2>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<div class="currency text-center m10t" data-ng-controller="CurrencyController">
|
<div class="text-center">
|
||||||
<small>
|
<small class="text-muted">Currency:</small>
|
||||||
Currency:
|
<div class="btn-group m10l" data-ng-controller="CurrencyController">
|
||||||
<a href="#" data-ng-click="setCurrency('USD')" data-ng-class="{active: currency.symbol == 'USD'}" tooltip="Change to USD: Bitstamp ${{currency.bitstamp}}">USD</a> ·
|
|
||||||
<a href="#" data-ng-click="setCurrency('BTC')" data-ng-class="{active: currency.symbol == 'BTC'}" tooltip="Change to BTC">BTC</a> ·
|
<a href="#" type="button" class="small btn btn-default btn-sm" data-ng-click="setCurrency('USD')" data-ng-class="{active: currency.symbol == 'USD'}" tooltip="Change to USD: Bitstamp ${{currency.bitstamp}}"> <small>USD </small></a>
|
||||||
<a href="#" data-ng-click="setCurrency('mBTC')" data-ng-class="{active: currency.symbol == 'mBTC'}" tooltip="Change to mBTC">mBTC</a>
|
<a href="#" type="button" class="btn btn-default btn-sm" data-ng-click="setCurrency('BTC')" data-ng-class="{active: currency.symbol == 'BTC'}" tooltip="Change to BTC"><small>BTC</small></a>
|
||||||
</small>
|
<a href="#" type="button" class="btn btn-default btn-sm" data-ng-click="setCurrency('mBTC')" data-ng-class="{active: currency.symbol == 'mBTC'}" tooltip="Change to mBTC"><small>mBTC</small></a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
|
@ -13,6 +13,7 @@
|
||||||
<th>Height</th>
|
<th>Height</th>
|
||||||
<th>Age</th>
|
<th>Age</th>
|
||||||
<th class="text-right"><span class="ellipsis">Transactions</span></th>
|
<th class="text-right"><span class="ellipsis">Transactions</span></th>
|
||||||
|
<th class="text-right"><span class="ellipsis">Relayed by</span></th>
|
||||||
<th class="text-right">Size</th>
|
<th class="text-right">Size</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td><span class="ellipsis">{{humanSince(b.time)}}</span></td>
|
<td><span class="ellipsis">{{humanSince(b.time)}}</span></td>
|
||||||
<td class="text-right">{{b.txlength}}</td>
|
<td class="text-right">{{b.txlength}}</td>
|
||||||
|
<td class="text-right"><a href="{{b.poolInfo.url}}" title="{{b.poolInfo.poolName}}" target="_blank" data-ng-show="b.poolInfo">{{b.poolInfo.poolName}}</a></td>
|
||||||
<td class="text-right">{{b.size}} bytes</td>
|
<td class="text-right">{{b.size}} bytes</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -10,23 +10,26 @@
|
||||||
<div class="col-xs-12 col-md-8">
|
<div class="col-xs-12 col-md-8">
|
||||||
<h2>Sync Status</h2>
|
<h2>Sync Status</h2>
|
||||||
<table class="table" data-ng-controller="StatusController" data-ng-init="getSync()">
|
<table class="table" data-ng-controller="StatusController" data-ng-init="getSync()">
|
||||||
<thead>
|
|
||||||
<span class="text-danger" data-ng-show="sync && sync.error">{{sync.error}}</span>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Sync Progress</td>
|
<td>Sync Progress</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: {{ sync.syncPercentage}}%">
|
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: {{ sync.syncPercentage}}%">
|
||||||
<span>{{sync.syncPercentage}}% Complete</span>
|
<span data-ng-show="sync.syncPercentage>0">{{sync.syncPercentage}}% Complete</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Current Sync Status</td>
|
<td>Current Sync Status</td>
|
||||||
<td class="text-right">{{sync.status}}</td>
|
<td class="text-right">
|
||||||
|
<span data-ng-show="!sync.error">{{sync.status}}</span>
|
||||||
|
<span class="text-danger" data-ng-show="sync.error">
|
||||||
|
<span class="glyphicon glyphicon-warning-sign"></span>
|
||||||
|
{{sync.error}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Start Date</td>
|
<td>Start Date</td>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
<div data-ng-include src="'/views/includes/connection.html'"></div>
|
||||||
<section data-ng-controller="transactionsController" data-ng-init="findThis()">
|
<section data-ng-controller="transactionsController" data-ng-init="findThis()">
|
||||||
|
|
||||||
<div class="row ng-cloak" data-ng-clock data-ng-if="tx.txid">
|
<div class="row ng-cloak" data-ng-cloak data-ng-if="tx.txid">
|
||||||
<div class="col-xs-12 col-gray col-gray-fixed">
|
<div class="col-xs-12 col-gray col-gray-fixed">
|
||||||
<h1 class="text-center">Transaction</h1>
|
<h1 class="text-center">Transaction</h1>
|
||||||
<div class="m20v text-center text-muted" data-ng-if="!tx.txid">
|
<div class="m20v text-center text-muted" data-ng-if="!tx.txid">
|
||||||
|
@ -75,3 +75,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="line-bot row ng-clock" data-ng-hide="!tx" data-ng-cloak>
|
<div class="line-bot row ng-cloak" data-ng-hide="!tx" data-ng-cloak>
|
||||||
<div class="col-xs-12 col-md-6">
|
<div class="col-xs-12 col-md-6">
|
||||||
<button class="btn-expand pull-left" data-ng-click="itemsExpanded = !itemsExpanded"><span class="glyphicon glyphicon-plus" data-ng-class="{'glyphicon-minus': itemsExpanded}" tooltip="Show/Hide items details" tooltip-placement="right"></span></button>
|
<button class="btn-expand pull-left" data-ng-click="itemsExpanded = !itemsExpanded"><span class="glyphicon glyphicon-plus" data-ng-class="{'glyphicon-minus': itemsExpanded}" tooltip="Show/Hide items details" tooltip-placement="right"></span></button>
|
||||||
<button class="btn-copy pull-right" clip-copy="tx.txid"></button>
|
<button class="btn-copy pull-right" clip-copy="tx.txid"></button>
|
||||||
|
@ -168,6 +168,7 @@
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="line-top row ng-cloak" data-ng-hide="!tx" data-ng-cloak>
|
<div class="line-top row ng-cloak" data-ng-hide="!tx" data-ng-cloak>
|
||||||
<div class="col-xs-12 col-sm-4 col-md-4">
|
<div class="col-xs-12 col-sm-4 col-md-4">
|
||||||
<span data-ng-show="!tx.isCoinBase && !isNaN(parseFloat(tx.fees))" class="txvalues txvalues-default">Fees: {{$root.currency.getConvertion(tx.fees)}} </span>
|
<span data-ng-show="!tx.isCoinBase && !isNaN(parseFloat(tx.fees))" class="txvalues txvalues-default">Fees: {{$root.currency.getConvertion(tx.fees)}} </span>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[
|
[
|
||||||
|
|
||||||
{
|
{
|
||||||
"addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS",
|
"addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS",
|
||||||
"balance": 0,
|
"balance": 0,
|
||||||
|
@ -37,7 +36,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"addr": "mgqvRGJMwR9JU5VhJ3x9uX9MTkzTsmmDgQ",
|
"addr": "mgqvRGJMwR9JU5VhJ3x9uX9MTkzTsmmDgQ",
|
||||||
"txApperances": 28,
|
"txApperances": 27,
|
||||||
"balance": 0,
|
"balance": 0,
|
||||||
"totalReceived": 54.81284116
|
"totalReceived": 54.81284116
|
||||||
},
|
},
|
||||||
|
@ -46,11 +45,11 @@
|
||||||
"balance": 1199.74393853,
|
"balance": 1199.74393853,
|
||||||
"totalReceived": 1199.74393853,
|
"totalReceived": 1199.74393853,
|
||||||
"totalSent": 0,
|
"totalSent": 0,
|
||||||
"txApperances": 6049
|
"txApperances": 6048
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H",
|
"addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H",
|
||||||
"txApperances": 13343,
|
"txApperances": 7164,
|
||||||
"balance": 46413.0,
|
"balance": 46413.0,
|
||||||
"totalReceived": 357130.17644359,
|
"totalReceived": 357130.17644359,
|
||||||
"totalSent": 310717.17644359
|
"totalSent": 310717.17644359
|
||||||
|
@ -68,7 +67,7 @@
|
||||||
"balance": 10580.50027254,
|
"balance": 10580.50027254,
|
||||||
"totalReceived": 12157.65075053,
|
"totalReceived": 12157.65075053,
|
||||||
"totalSent": 1577.15047799,
|
"totalSent": 1577.15047799,
|
||||||
"txApperances": 459,
|
"txApperances": 441,
|
||||||
"transactions": [
|
"transactions": [
|
||||||
"91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5",
|
"91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5",
|
||||||
"f6e80d4fd1a2377406856c67d0cee5ac7e5120993ff97e617ca9aac33b4c6b1e",
|
"f6e80d4fd1a2377406856c67d0cee5ac7e5120993ff97e617ca9aac33b4c6b1e",
|
||||||
|
@ -111,7 +110,20 @@
|
||||||
"a3789e113041db907a1217ddb5c3aaf0eff905cc3d913e68d977e1ab4d19acea",
|
"a3789e113041db907a1217ddb5c3aaf0eff905cc3d913e68d977e1ab4d19acea",
|
||||||
"80b460922faf0ad1e8b8a55533654c9a9f3039bfff0fff2bcf8536b8adf95939"
|
"80b460922faf0ad1e8b8a55533654c9a9f3039bfff0fff2bcf8536b8adf95939"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"addr": "mtA6woo1wjCeu1dLkWgpSD3tRnRfrHt3FL",
|
||||||
|
"balance": 349.845,
|
||||||
|
"totalReceived": 349.845,
|
||||||
|
"totalSent": 0,
|
||||||
|
"txApperances": 13,
|
||||||
|
"transactions": [
|
||||||
|
"794eafc0ad68a3576034eb137d7d20d3bdf1777ecf27e0e20e96e1adcfc66659",
|
||||||
|
"0130721f29f50b773858c3c9081678bdddebcd18078c5fa2436d979b54ed5cef",
|
||||||
|
"fb1024947b48d90255aedd3f0f1df3673a7e98d06346bb2ac89b116aa19c5db4"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,22 +9,12 @@ describe('PeerSync', function() {
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
ps = new PeerSync();
|
ps = new PeerSync();
|
||||||
ps.init({
|
done();
|
||||||
verbose: false
|
|
||||||
}, done);
|
|
||||||
});
|
});
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
ps.close();
|
ps.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#init()', function() {
|
|
||||||
it('should return with no errors', function() {
|
|
||||||
var other_ps = new PeerSync();
|
|
||||||
expect(other_ps.init.bind(other_ps)).not.to.
|
|
||||||
throw (Error);
|
|
||||||
other_ps.close();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#handleInv()', function() {
|
describe('#handleInv()', function() {
|
||||||
var inv_info = {
|
var inv_info = {
|
||||||
|
|
10
util/p2p.js
10
util/p2p.js
|
@ -10,17 +10,9 @@ var program = require('commander');
|
||||||
|
|
||||||
program
|
program
|
||||||
.version(PROGRAM_VERSION)
|
.version(PROGRAM_VERSION)
|
||||||
.option('-N --network [testnet]', 'Set bitcoin network [testnet]', 'testnet')
|
|
||||||
.option('-V --verbose', 'Verbose', 1)
|
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
|
|
||||||
var ps = new PeerSync();
|
var ps = new PeerSync();
|
||||||
ps.init(program, function(err){
|
ps.run();
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
ps.run();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
26
util/sync.js
26
util/sync.js
|
@ -14,34 +14,30 @@ program
|
||||||
.version(SYNC_VERSION)
|
.version(SYNC_VERSION)
|
||||||
.option('-D --destroy', 'Remove current DB (and start from there)', 0)
|
.option('-D --destroy', 'Remove current DB (and start from there)', 0)
|
||||||
.option('-S --startfile', 'Number of file from bitcoind to start(default=0)')
|
.option('-S --startfile', 'Number of file from bitcoind to start(default=0)')
|
||||||
|
.option('-R --rpc', 'Force sync with RPC')
|
||||||
.option('-v --verbose', 'Verbose 0/1', 0)
|
.option('-v --verbose', 'Verbose 0/1', 0)
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
|
|
||||||
var historicSync = new HistoricSync();
|
var historicSync = new HistoricSync({
|
||||||
|
shouldBroadcastSync: true,
|
||||||
|
});
|
||||||
|
|
||||||
/* TODO: Sure?
|
|
||||||
if (program.remove) {
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
async.series([
|
async.series([
|
||||||
function(cb) {
|
function(cb) {
|
||||||
historicSync.init(program, cb);
|
if (!program.destroy) return cb();
|
||||||
|
console.log('Deleting Sync DB...');
|
||||||
|
historicSync.sync.destroy(cb);
|
||||||
},
|
},
|
||||||
function(cb) {
|
function(cb) {
|
||||||
historicSync.smartImport({
|
historicSync.start({
|
||||||
destroy: program.destroy,
|
forceStartFile: program.startfile,
|
||||||
startFile: program.startfile,
|
forceRPC: program.rpc,
|
||||||
},cb);
|
},cb);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
function(err) {
|
function(err) {
|
||||||
historicSync.close();
|
historicSync.close();
|
||||||
if (err) {
|
if (err) console.log('CRITICAL ERROR: ', historicSync.info());
|
||||||
console.log('CRITICAL ERROR: ', historicSync.info());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('Finished.\n Status:\n', historicSync.info());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue