diff --git a/app/controllers/socket.js b/app/controllers/socket.js index ace6315..25a846e 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -26,6 +26,6 @@ module.exports.broadcast_address_tx = function(address, tx) { ios.sockets.in(address).emit('atx', tx); }; -module.exports.broadcastSyncInfo = function(syncInfo) { - ios.sockets.in('sync').emit('status', syncInfo); +module.exports.broadcastSyncInfo = function(historicSync) { + ios.sockets.in('sync').emit('status', historicSync); }; diff --git a/app/controllers/status.js b/app/controllers/status.js index 7fb6f72..c978722 100644 --- a/app/controllers/status.js +++ b/app/controllers/status.js @@ -50,6 +50,6 @@ exports.show = function(req, res) { }; exports.sync = function(req, res) { - if (req.syncInfo) - res.jsonp(req.syncInfo); + if (req.historicSync) + res.jsonp(req.historicSync.info()); }; diff --git a/config/express.js b/config/express.js index 0e5c58d..0b9c284 100644 --- a/config/express.js +++ b/config/express.js @@ -31,7 +31,7 @@ module.exports = function(app, historicSync) { //custom middleware function setHistoric(req, res, next) { - req.syncInfo = historicSync.syncInfo; + req.historicSync = historicSync; next(); } app.use('/api/sync', setHistoric); diff --git a/lib/HistoricSync.js b/lib/HistoricSync.js index 2593690..4f8c825 100644 --- a/lib/HistoricSync.js +++ b/lib/HistoricSync.js @@ -2,6 +2,8 @@ require('classtool'); + + function spec() { var util = require('util'); var RpcClient = require('bitcore/RpcClient').class(); @@ -12,6 +14,9 @@ function spec() { var Sync = require('./Sync').class(); var sockets = require('../app/controllers/socket.js'); + + var BAD_GEN_ERROR = 'Bad genesis block. Network mismatch between Insight and bitcoind? Insight is configured for:'; + function HistoricSync(opts) { this.network = config.network === 'testnet' ? networks.testnet: networks.livenet; @@ -22,7 +27,12 @@ function spec() { //available status: new / syncing / finished / aborted this.status = 'new'; - this.syncInfo = {}; + this.error = null; + + this.syncPercentage = 0; + this.syncedBlocks = 0; + this.skippedBlocks = 0; + } function p() { @@ -34,6 +44,13 @@ function spec() { console.log.apply(this, args); } + HistoricSync.prototype.setError = function(err) { + var self = this; + self.error = err.toString(); + self.status='error'; + self.showProgress(); + }; + HistoricSync.prototype.init = function(opts, cb) { var self = this; @@ -41,17 +58,15 @@ function spec() { self.opts = opts; self.sync.init(opts, function(err) { if (err) { - self.err = err.message; - self.syncInfo = util._extend(self.syncInfo, { error: err.message }); + self.setError(err); return cb(err); } else { // check testnet? self.rpc.getBlockHash(0, function(err, res){ if (!err && ( res && res.result !== self.genesis)) { - self.err = 'Bad genesis block. Network mismatch between Insight and bitcoind? Insight is configured for:' + config.network; - err = new Error(self.err); - self.syncInfo = util._extend(self.syncInfo, { error: err.message }); + err = new Error(BAD_GEN_ERROR + config.network); + self.setError(err); } return cb(err); }); @@ -64,14 +79,29 @@ function spec() { this.sync.close(); }; + + HistoricSync.prototype.info = function() { + return { + status: this.status, + blockChainHeight: this.blockChainHeight, + syncPercentage: this.syncPercentage, + skippedBlocks: this.skippedBlocks, + syncedBlocks: this.syncedBlocks, + }; + }; + HistoricSync.prototype.showProgress = function() { var self = this; - var i = self.syncInfo; - var per = parseInt(100 * i.syncedBlocks / i.blocksToSync); - p(util.format('status: %d/%d [%d%%]', i.syncedBlocks, i.blocksToSync, per)); + if (self.error) { + p('ERROR:' + self.error); + } + else { + self.syncPercentage = parseFloat(100 * self.syncedBlocks / self.blockChainHeight).toFixed(3); + p(util.format('status: [%d%%] skipped: %d', self.syncPercentage, self.skippedBlocks)); + } if (self.opts.shouldBroadcast) { - sockets.broadcastSyncInfo(self.syncInfo); + sockets.broadcastSyncInfo(self.info()); } }; @@ -105,17 +135,10 @@ function spec() { }, //show some (inacurate) status function(c) { - if (!self.step) { - var step = parseInt(self.syncInfo.blocksToSync / 100); - if (self.opts.progressStep) { - step = self.opts.progressStep; - } - if (step < 2) step = 2; - self.step = step; - } - if (self.syncInfo.syncedBlocks % self.step === 1) { + if ( ( self.syncedBlocks + self.skippedBlocks) % self.step === 1) { self.showProgress(); } + return c(); }, //get Info from RPC @@ -154,57 +177,49 @@ function spec() { ], function(err) { if (err) { - self.err = util.format('ERROR: @%s: %s [count: syncedBlocks: %d]', blockHash, err, self.syncInfo.syncedBlocks); + self.err = util.format('ERROR: @%s: %s [count: syncedBlocks: %d]', blockHash, err, self.syncedBlocks); self.status = 'aborted'; + self.showProgress(); p(self.err); } - else { self.err = null; self.status = 'syncing'; } - if (opts.upToExisting && existed) { - var diff = self.syncInfo.blocksToSync - self.syncInfo.syncedBlocks; - if (diff <= 0) { + if ( (opts.upToExisting && existed && self.syncedBlocks >= self.blockChainHeight) || + (blockEnd && blockEnd === blockHash)) { self.status = 'finished'; p('DONE. Found existing block: ', blockHash); + self.showProgress(); return cb(err); - } - else { - self.syncInfo.skipped_blocks = self.syncInfo.skipped_blocks || 1; - if ((self.syncInfo.skipped_blocks++ % 1000) === 1) { - p('WARN found target block\n\tbut blockChain Height is still higher that ours. Previous light sync must be interrupted.\n\tWill keep syncing.', self.syncInfo.syncedBlocks, self.syncInfo.blocksToSync, self.syncInfo.skipped_blocks); - } - } - } - - if (blockEnd && blockEnd === blockHash) { - self.status = 'finished'; - p('DONE. Found END block: ', blockHash); - return cb(err); } // Continue if (blockInfo && blockInfo.result) { - if (!existed) self.syncInfo.syncedBlocks++; - if (opts.prev && blockInfo.result.previousblockhash) { - return self.getPrevNextBlock(blockInfo.result.previousblockhash, blockEnd, opts, cb); - } - if (opts.next && blockInfo.result.nextblockhash) return self.getPrevNextBlock(blockInfo.result.nextblockhash, blockEnd, opts, cb); + if (existed) + self.skippedBlocks++; + else + self.syncedBlocks++; + + // recursion + if (opts.prev && blockInfo.result.previousblockhash) + return self.getPrevNextBlock(blockInfo.result.previousblockhash, blockEnd, opts, cb); + + if (opts.next && blockInfo.result.nextblockhash) + return self.getPrevNextBlock(blockInfo.result.nextblockhash, blockEnd, opts, cb); } return cb(err); }); }; - HistoricSync.prototype.import_history = function(opts, next) { + HistoricSync.prototype.importHistory = function(opts, next) { var self = this; var retry_secs = 2; var bestBlock; - var blockChainHeight; async.series([ function(cb) { @@ -220,14 +235,14 @@ function spec() { self.rpc.getBlockCount(function(err, res) { if (err) return cb(err); - blockChainHeight = res.result; + self.blockChainHeight = res.result; return cb(); }); }, function(cb) { if (!opts.reverse) return cb(); - self.rpc.getBlockHash(blockChainHeight, function(err, res) { + self.rpc.getBlockHash(self.blockChainHeight, function(err, res) { if (err) return cb(err); bestBlock = res.result; @@ -236,15 +251,8 @@ function spec() { }); }, function(cb) { - // This is only to inform progress. - if (!opts.upToExisting) { - self.rpc.getInfo(function(err, res) { - if (err) return cb(err); - self.syncInfo.blocksToSync = res.result.blocks; - return cb(); - }); - } - else { + if (opts.upToExisting) { + // should be isOrphan = true or null to be more accurate. Block.count({ isOrphan: null @@ -252,14 +260,12 @@ function spec() { function(err, count) { if (err) return cb(err); - self.syncInfo.blocksToSync = blockChainHeight - count; - if (self.syncInfo.blocksToSync < 1) self.syncInfo.blocksToSync = 1; + self.syncedBlocks = count || 0; return cb(); }); } }, ], function(err) { - var start, end; function sync() { if (opts.reverse) { @@ -272,18 +278,6 @@ function spec() { end = null; opts.next = true; } - - self.syncInfo = util._extend(self.syncInfo, { - start: start, - isStartGenesis: start === self.genesis, - end: end, - isEndGenesis: end === self.genesis, - scanningForward: opts.next, - scanningBackward: opts.prev, - upToExisting: opts.upToExisting, - syncedBlocks: 0, - }); - p('Starting from: ', start); p(' to : ', end); p(' opts: ', JSON.stringify(opts)); @@ -300,10 +294,20 @@ function spec() { }); } + + 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 (err) { - self.syncInfo = util._extend(self.syncInfo, { - error: err.message - }); + self.setError(err); return next(err, 0); } else { @@ -313,7 +317,7 @@ function spec() { }; // upto if we have genesis block? - HistoricSync.prototype.smart_import = function(next) { + HistoricSync.prototype.smartImport = function(next) { var self = this; Block.findOne({ @@ -335,7 +339,7 @@ function spec() { upToExisting: b ? true: false, }; - return self.import_history(opts, next); + return self.importHistory(opts, next); }); }; diff --git a/public/css/common.css b/public/css/common.css index 7e4da55..f65b19e 100644 --- a/public/css/common.css +++ b/public/css/common.css @@ -224,6 +224,10 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 45px; } +.progress-bar-info { + background-color: #8DC429; +} + /* Set the fixed height of the footer here */ #footer { height: 51px; @@ -368,4 +372,21 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { font-size: 80%; } +.status .t { + color: white; + display: inline-block; + padding:0px 5px; +} + +.status .text-danger { + background: red; +} + +.status .text-warning { + background: yellow; + color: black; +} + +.status .text-default { +} diff --git a/public/js/controllers/status.js b/public/js/controllers/status.js index a350002..56c823a 100644 --- a/public/js/controllers/status.js +++ b/public/js/controllers/status.js @@ -23,39 +23,23 @@ function($scope, $routeParams, $location, $rootScope, Global, Status, Sync, get_ }; var on_sync_update = function(sync) { - - if (sync.error) { - $rootScope.syncError = sync.error; - return; - } - - if (sync.blocksToSync > sync.syncedBlocks) { - var p = parseInt(100*(sync.syncedBlocks) / sync.blocksToSync); - var delta = sync.blocksToSync - sync.syncedBlocks; - sync.message = 'Sync ' + p + '% ['+delta+' blocks remaining]'; - sync.style = 'warn'; - } else { - sync.message = 'On sync'; - sync.style = 'success'; - } - sync.tooltip = 'Synced blocks: '+sync.syncedBlocks; $scope.sync = sync; }; $scope.getSync = function() { Sync.get({}, function(sync) { - $rootScope.syncError = null; on_sync_update(sync); }, function(e) { - $rootScope.syncError = 'Could not get sync information' + e; + $scope.sync = { error: 'Could not get sync information' + e }; }); }; var socket = get_socket($scope); socket.emit('subscribe', 'sync'); socket.on('status', function(sync) { +console.log('[status.js.55::] sync status update received!'); on_sync_update(sync); }); diff --git a/public/views/header.html b/public/views/header.html index 47917e1..726b838 100755 --- a/public/views/header.html +++ b/public/views/header.html @@ -25,8 +25,9 @@
- - {{sync.message}} +
ERROR
+
{{sync.status}} {{sync.syncPercentage}}%
+
On sync
diff --git a/public/views/status.html b/public/views/status.html index 8ca3f61..6ff6abf 100644 --- a/public/views/status.html +++ b/public/views/status.html @@ -4,76 +4,11 @@ Application Status
-
-
-

Bitcoin node information

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Loading... -
{{infoError}} -
Version{{info.version}}
Protocol version{{info.protocolversion}}
Wallet version{{info.walletversion}}
Balance (BTC){{info.balance}}
Blocks{{info.blocks}}
Time Offset{{info.timeoffset}}
Connections to other nodes{{info.connections}}
Proxy setting{{info.proxy}}
Mining Difficulty{{info.difficulty}}
Testnet{{info.testnet}}
Keypool Oldest Date{{info.keypoololdest*1000 | date:'medium' }}
Keypool Size{{info.keypoolsize}}
Default Transaction Fee (BTC){{info.paytxfee}}
Info Errors{{info.infoErrors}}
+
+
-

Sync Status

- +

Sync Status

+
- + - + - - -
{{ syncError }} @@ -91,29 +26,29 @@
Blocks to Sync{{sync.blocksToSync}}{{sync.blocksToSync}}
Synced Blocks{{sync.syncedBlocks}}{{sync.syncedBlocks}}
Start + {{sync.start}} (genesisBlock)
End + {{sync.end}} (genesisBlock)
Sync properties +
  • Stops at existing block
  • @@ -125,8 +60,8 @@
-

Transaction Output Set Information

- +

Transaction Output Set Information

+
@@ -136,54 +71,37 @@ - + - + - + - + - + - + - - - -
Loading...
Height{{txoutsetinfo.height}}{{txoutsetinfo.height}}
Best Block{{txoutsetinfo.bestblock}}{{txoutsetinfo.bestblock}}
Transactions{{txoutsetinfo.transactions}} {{txoutsetinfo.transactions}}
Transaction Outputs{{txoutsetinfo.txouts}}{{txoutsetinfo.txouts}}
Bytes Serialized{{txoutsetinfo.bytes_serialized}}{{txoutsetinfo.bytes_serialized}}
Hash Serialized{{txoutsetinfo.hash_serialized}}{{txoutsetinfo.hash_serialized}}
Total Amount{{txoutsetinfo.total_amount}}
- -

Difficulty

- - - - - - - - - - - - +
Loading...
{{infoError}}
Mining Difficulty{{difficulty}}{{txoutsetinfo.total_amount}}
-

Last Block

- +

Last Block

+
@@ -193,11 +111,98 @@ - +
Loading...
Last block hash{{lastblockhash}}{{lastblockhash}}
-
+
+ +
+
+

Bitcoin node information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Loading... +
{{infoError}} +
Version{{info.version}}
Protocol version{{info.protocolversion}}
Wallet version{{info.walletversion}}
Balance (BTC){{info.balance}}
Blocks{{info.blocks}}
Time Offset{{info.timeoffset}}
Connections to other nodes{{info.connections}}
Proxy setting{{info.proxy}}
Mining Difficulty{{info.difficulty}}
Testnet{{info.testnet}}
Keypool Oldest Date{{info.keypoololdest*1000 | date:'medium' }}
Keypool Size{{info.keypoolsize}}
Default Transaction Fee (BTC){{info.paytxfee}}
Info Errors{{info.infoErrors}}
+ +

Difficulty

+ + + + + + + + + + + + + + +
Loading...
{{infoError}}
Mining Difficulty{{difficulty}}
+
+
diff --git a/server.js b/server.js index a44d1ef..64027d0 100644 --- a/server.js +++ b/server.js @@ -55,8 +55,11 @@ walk(models_path); // historic_sync process var historicSync = {}; + + if (!config.disableHistoricSync) { historicSync = new HistoricSync(); + historicSync.init({ skipDbConnection: true, shouldBroadcast: true, @@ -68,11 +71,11 @@ if (!config.disableHistoricSync) { console.log('[historic_sync] ' + txt); } else { - historicSync.smart_import(function(err){ + historicSync.smartImport(function(err){ var txt= 'ended.'; if (err) txt = 'ABORTED with error: ' + err.message; - console.log('[historic_sync] ' + txt, historicSync.syncInfo); + console.log('[historic_sync] ' + txt, historicSync.info()); }); } }); diff --git a/util/sync.js b/util/sync.js index b7f6e03..2dd4f15 100755 --- a/util/sync.js +++ b/util/sync.js @@ -33,10 +33,10 @@ async.series([ }, function(cb) { if (program.smart) { - historicSync.smart_import(cb); + historicSync.smartImport(cb); } else { - historicSync.import_history({ + historicSync.importHistory({ destroy: program.destroy, reverse: program.reverse, upToExisting: program.uptoexisting, @@ -50,7 +50,7 @@ async.series([ console.log('CRITICAL ERROR: ', err); } else { - console.log('Finished.\n Status:\n', historicSync.syncInfo); + console.log('Finished.\n Status:\n', historicSync.info()); } });