From 951eeea6d072475c2af931896b08a6eb9df97c80 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 20 Jan 2014 11:45:01 -0300 Subject: [PATCH 1/6] show sync status in /status page --- app/models/Status.js | 5 ---- public/js/controllers/status.js | 30 +++++++------------ public/js/services/status.js | 4 +++ public/views/status.html | 53 ++++++++++++++++++++++++++++++--- 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/app/models/Status.js b/app/models/Status.js index 321e227..517b51c 100644 --- a/app/models/Status.js +++ b/app/models/Status.js @@ -9,11 +9,6 @@ function spec() { var rpc = new RpcClient(config.bitcoind); function Status() { - this.info = {}; - this.difficulty = {}; - this.txoutsetinfo = {}; - this.bestblockhash = {}; - this.lastblockhash = {}; } Status.prototype.getInfo = function(next) { diff --git a/public/js/controllers/status.js b/public/js/controllers/status.js index 8b5b538..2bf2779 100644 --- a/public/js/controllers/status.js +++ b/public/js/controllers/status.js @@ -1,30 +1,22 @@ 'use strict'; -angular.module('insight.status').controller('StatusController', ['$scope', '$routeParams', '$location', 'Global', 'Status', function ($scope, $routeParams, $location, Global, Status) { +angular.module('insight.status').controller('StatusController', ['$scope', '$routeParams', '$location', 'Global', 'Status', 'Sync', function ($scope, $routeParams, $location, Global, Status, Sync) { $scope.global = Global; - $scope.getData = function(q) { + $scope.getStatus = function(q) { Status.get({ - q: q + q: 'get' + q }, function(d) { - if (q === 'getInfo') { - $scope.info = d.info; - } - if (q === 'getDifficulty') { - $scope.difficulty = d.difficulty; - } - if (q === 'getTxOutSetInfo') { - $scope.txoutsetinfo = d.txoutsetinfo; - } - if (q === 'getBestBlockHash') { - $scope.bestblockhash = d.bestblockhash; - } - if (q === 'getLastBlockHash') { - $scope.lastblockhash = d.lastblockhash; - } - + angular.extend($scope, d); }); }; + $scope.getSync = function() { + Sync.get({}, function(sync) { + $scope.sync = sync; + }, function() { + $rootScope.flashMessage = 'Could not get sync information'; + }); + }; }]); diff --git a/public/js/services/status.js b/public/js/services/status.js index f911c33..67d7004 100644 --- a/public/js/services/status.js +++ b/public/js/services/status.js @@ -6,3 +6,7 @@ angular.module('insight.status').factory('Status', ['$resource', function($resou }); }]); +angular.module('insight.status').factory('Sync', ['$resource', function($resource) { + return $resource('/api/sync'); +}]); + diff --git a/public/views/status.html b/public/views/status.html index 9009f92..d439d63 100644 --- a/public/views/status.html +++ b/public/views/status.html @@ -7,7 +7,7 @@

getInfo

- +
@@ -72,8 +72,53 @@
Loading...
+

sync status

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Sync Progress {{(100 * sync.syncedBlocks/sync.blocksToSync)| number:2}}% +
blocksToSync{{sync.blocksToSync}}
syncedBlocks{{sync.syncedBlocks}}
start{{sync.start}} + (genesisBlock) +
end{{sync.end}} + (genesisBlock) +
Sync Type +
    +
  • Stops at existing block +
  • + scanningBackward + scanningForward +
+
+

getTxOutSetInfo

- +
@@ -114,7 +159,7 @@

getDifficulty

-
Loading...
+
@@ -128,7 +173,7 @@

getLastBlockHash

-
Loading...
+
From 5468895e34db27140161d303dbe3c32d6de5e156 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 20 Jan 2014 12:10:49 -0300 Subject: [PATCH 2/6] fix socket io name error --- app/controllers/socket.js | 2 +- public/js/controllers/status.js | 2 +- public/views/status.html | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/controllers/socket.js b/app/controllers/socket.js index fa78f55..b98b0c2 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -23,5 +23,5 @@ module.exports.broadcast_block = function(block) { }; module.exports.broadcastSyncInfo = function(syncInfo) { - ios.sockets.emit('block', syncInfo); + ios.sockets.emit('sync', syncInfo); }; diff --git a/public/js/controllers/status.js b/public/js/controllers/status.js index 2bf2779..dcfd52e 100644 --- a/public/js/controllers/status.js +++ b/public/js/controllers/status.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('insight.status').controller('StatusController', ['$scope', '$routeParams', '$location', 'Global', 'Status', 'Sync', function ($scope, $routeParams, $location, Global, Status, Sync) { +angular.module('insight.status').controller('StatusController', ['$scope', '$routeParams', '$location', '$rootScope', 'Global', 'Status', 'Sync', function ($scope, $routeParams, $location, $rootScope, Global, Status, Sync) { $scope.global = Global; $scope.getStatus = function(q) { diff --git a/public/views/status.html b/public/views/status.html index d439d63..ce4c880 100644 --- a/public/views/status.html +++ b/public/views/status.html @@ -75,6 +75,11 @@

sync status

Loading...
+ + + +
{{ sync.err }} +
Sync Progress {{(100 * sync.syncedBlocks/sync.blocksToSync)| number:2}}% From b4936fd6b4cac61ab98fcd1d141c56a60c05ac9b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 20 Jan 2014 15:41:22 -0300 Subject: [PATCH 3/6] fix skipping during syc --- lib/HistoricSync.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/HistoricSync.js b/lib/HistoricSync.js index f9d3d0a..b33b4bd 100644 --- a/lib/HistoricSync.js +++ b/lib/HistoricSync.js @@ -142,13 +142,17 @@ function spec() { } if (opts.upToExisting && existed ) { - if (self.syncInfo.blocksToSync <= self.syncInfo.syncedBlocks) { + var diff = self.syncInfo.blocksToSync - self.syncInfo.syncedBlocks; + if (diff <= 0) { self.status = 'finished'; p('DONE. Found existing block: ', blockHash); return cb(err); } else { - 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.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); + } } } @@ -161,7 +165,7 @@ function spec() { // Continue if (blockInfo && blockInfo.result) { - self.syncInfo.syncedBlocks++; + if (! existed) self.syncInfo.syncedBlocks++; if (opts.prev && blockInfo.result.previousblockhash) { return self.getPrevNextBlock(blockInfo.result.previousblockhash, blockEnd, opts, cb); } From 4e1562ce7a62ca78d4a9910741d5f21e3d264c58 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 20 Jan 2014 15:51:23 -0300 Subject: [PATCH 4/6] fix HTTP reponse codes --- app/controllers/addresses.js | 28 ++++++++++++++-------------- app/controllers/blocks.js | 9 +++------ app/controllers/common.js | 18 ++++++++++++++++++ app/controllers/transactions.js | 12 +++++------- app/models/Address.js | 12 ++---------- app/models/Block.js | 29 +++++++++++++++++++++++++---- app/models/Transaction.js | 8 ++++++-- 7 files changed, 73 insertions(+), 43 deletions(-) create mode 100644 app/controllers/common.js diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js index e13000c..f12087e 100644 --- a/app/controllers/addresses.js +++ b/app/controllers/addresses.js @@ -4,30 +4,30 @@ * Module dependencies. */ -var Address = require('../models/Address'); +var Address = require('../models/Address'), + common = require('./common'); -/** - * Find block by hash ... - */ exports.address = function(req, res, next, addr) { - var a = Address.new(addr); + + + var a; + try { + a = Address.new(addr); + } catch (e) { + return common.handleErrors({message: 'Invalid address:' + e.message, code: 1}, res, next); + } a.update(function(err) { - if (err && !a.totalReceivedSat) { - console.log(err); - res.status(404).send('Invalid address'); - return next(); - } + if (err) return common.handleErrors(err, res, next); - req.address = a; - return next(); - }); + req.address = a; + return next(); + }); }; /** - * Show block */ exports.show = function(req, res) { if (req.address) { diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index a21d52e..9393359 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -4,7 +4,8 @@ * Module dependencies. */ var mongoose = require('mongoose'), - Block = mongoose.model('Block'); + Block = mongoose.model('Block'), + common = require('./common'); /** @@ -12,11 +13,7 @@ var mongoose = require('mongoose'), */ exports.block = function(req, res, next, hash) { Block.fromHashWithInfo(hash, function(err, block) { - if (err && !block) { - console.log(err); - res.status(404).send('Not found'); - return next(); - } + if (err || ! tx) return common.handleErrors(err, res, next); req.block = block.info; return next(); diff --git a/app/controllers/common.js b/app/controllers/common.js new file mode 100644 index 0000000..faae67c --- /dev/null +++ b/app/controllers/common.js @@ -0,0 +1,18 @@ +'use strict'; + + +exports.handleErrors = function (err, res, next) { + if (err) { + if (err.code) { + res.status(400).send(err.message + '. Code:' + err.code); + } + else { + res.status(503).send(err.message); + } + return next(); + } + else { + res.status(404).send('Not found'); + return next(); + } +}; diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js index 833fc66..c865f57 100644 --- a/app/controllers/transactions.js +++ b/app/controllers/transactions.js @@ -7,6 +7,7 @@ var Transaction = require('../models/Transaction'); var Block = require('../models/Block'); var Address = require('../models/Address'); var async = require('async'); +var common = require('./common'); /** @@ -14,15 +15,12 @@ var async = require('async'); */ exports.transaction = function(req, res, next, txid) { Transaction.fromIdWithInfo(txid, function(err, tx) { - if (err) { - console.log(err); - res.status(404).send('Not found'); - return next(); - } - if (!tx) return next(new Error('Failed to load TX ' + txid)); + if (err || ! tx) return common.handleErrors(err, res, next); + + req.transaction = tx.info; - next(); + return next(); }); }; diff --git a/app/models/Address.js b/app/models/Address.js index 05d1a78..e054ff1 100644 --- a/app/models/Address.js +++ b/app/models/Address.js @@ -19,11 +19,8 @@ function spec() { this.transactions = []; var a = new BitcoreAddress(addrStr); - try { - a.validate(); - this.addrStr = addrStr; - } catch(e){ - } + a.validate(); + this.addrStr = addrStr; Object.defineProperty(this, 'totalSent', { @@ -58,11 +55,6 @@ function spec() { } Address.prototype.update = function(next) { - - if (! this.addrStr) { - return next(new Error('Invalid or undefined address string')); - } - var that = this; async.series([ // TODO TXout! diff --git a/app/models/Block.js b/app/models/Block.js index e4d84d3..8669759 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -81,16 +81,34 @@ BlockSchema.statics.fromHash = function(hash, cb) { BlockSchema.statics.fromHashWithInfo = function(hash, cb) { + var That = this; + this.fromHash(hash, function(err, block) { if (err) return cb(err); - if (!block) { return cb(new Error('Block not found')); } - block.getInfo(function(err) { return cb(err,block); } ); + if (!block) { + // No in mongo...but maybe in bitcoind... lets query it + block = new That(); + + block.hash = hash; + block.getInfo(function(err, blockInfo) { +console.log('[Block.js.95:err:]',err); //TODO + if (err) return cb(err); + if (!blockInfo) return cb(); + + block.save(function(err) { + return cb(err,block); + }); + }); + } + else { + block.getInfo(function(err) { + return cb(err,block); + }); + } }); }; - - // TODO: Can we store the rpc instance in the Block object? BlockSchema.methods.getInfo = function (next) { @@ -98,6 +116,9 @@ BlockSchema.methods.getInfo = function (next) { var rpc = new RpcClient(config.bitcoind); rpc.getBlock(this.hash, function(err, blockInfo) { + // Not found? + if (err && err.code === -5) return next(); + if (err) return next(err); /* diff --git a/app/models/Transaction.js b/app/models/Transaction.js index fdad11e..291c8ba 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -73,8 +73,8 @@ TransactionSchema.statics.fromIdWithInfo = function(txid, cb) { tx.txid = txid; tx.fillInfo(function(err, txInfo) { - if (!txInfo) - return cb(new Error('TX not found')); + if (err) return cb(err); + if (!txInfo) return cb(); tx.save(function(err) { return cb(err,tx); @@ -239,6 +239,10 @@ TransactionSchema.statics.queryInfo = function(txid, cb) { var rpc = new RpcClient(config.bitcoind); rpc.getRawTransaction(txid, 1, function(err, txInfo) { + + // Not found? + if (err && err.code === -5) return cb(); + if (err) return cb(err); var info = txInfo.result; From f619192708be1464d67dca565e8d88ae8793b5b2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 20 Jan 2014 16:11:35 -0300 Subject: [PATCH 5/6] better error API handling --- app/controllers/blocks.js | 2 +- app/models/Block.js | 1 - public/js/controllers/address.js | 12 ++++++++++-- public/js/controllers/blocks.js | 12 ++++++++++-- public/js/controllers/transactions.js | 12 ++++++++++-- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 9393359..316f17f 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -13,7 +13,7 @@ var mongoose = require('mongoose'), */ exports.block = function(req, res, next, hash) { Block.fromHashWithInfo(hash, function(err, block) { - if (err || ! tx) return common.handleErrors(err, res, next); + if (err || ! block) return common.handleErrors(err, res, next); req.block = block.info; return next(); diff --git a/app/models/Block.js b/app/models/Block.js index 8669759..3f4bcbc 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -92,7 +92,6 @@ BlockSchema.statics.fromHashWithInfo = function(hash, cb) { block.hash = hash; block.getInfo(function(err, blockInfo) { -console.log('[Block.js.95:err:]',err); //TODO if (err) return cb(err); if (!blockInfo) return cb(); diff --git a/public/js/controllers/address.js b/public/js/controllers/address.js index 46a441d..b53ec85 100644 --- a/public/js/controllers/address.js +++ b/public/js/controllers/address.js @@ -8,8 +8,16 @@ angular.module('insight.address').controller('AddressController', ['$scope', '$r addrStr: $routeParams.addrStr }, function(address) { $scope.address = address; - }, function() { - $rootScope.flashMessage = 'Address Not Found'; + }, function(e) { + if (e.status === 400) { + $rootScope.flashMessage = 'Invalid Address: ' + $routeParams.addrStr; + } + else if (e.status === 503) { + $rootScope.flashMessage = 'Backend Error. ' + e.data; + } + else { + $rootScope.flashMessage = 'Address Not Found'; + } $location.path('/'); }); }; diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index b398ef3..e300299 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -17,8 +17,16 @@ angular.module('insight.blocks').controller('BlocksController', ['$scope', '$roo blockHash: $routeParams.blockHash }, function(block) { $scope.block = block; - }, function() { - $rootScope.flashMessage = 'Block Not Found'; + }, function(e) { + if (e.status === 400) { + $rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId; + } + else if (e.status === 503) { + $rootScope.flashMessage = 'Backend Error. ' + e.data; + } + else { + $rootScope.flashMessage = 'Block Not Found'; + } $location.path('/'); }); }; diff --git a/public/js/controllers/transactions.js b/public/js/controllers/transactions.js index e1272e8..6e47dc3 100644 --- a/public/js/controllers/transactions.js +++ b/public/js/controllers/transactions.js @@ -8,8 +8,16 @@ angular.module('insight.transactions').controller('transactionsController', ['$s txId: $routeParams.txId }, function(tx) { $scope.tx = tx; - }, function() { - $rootScope.flashMessage = 'Transaction Not Found'; + }, function(e) { + if (e.status === 400) { + $rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId; + } + else if (e.status === 503) { + $rootScope.flashMessage = 'Backend Error. ' + e.data; + } + else { + $rootScope.flashMessage = 'Transaction Not Found'; + } $location.path('/'); }); }; From 465e4698f62650e024a79ce401d6dc9f98f899b5 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 20 Jan 2014 16:40:20 -0300 Subject: [PATCH 6/6] more error handling --- app/controllers/addresses.js | 10 ++++++---- app/controllers/blocks.js | 10 ++++++---- app/controllers/common.js | 4 +--- app/controllers/status.js | 10 +++++++--- app/controllers/transactions.js | 12 ++++++------ public/js/controllers/status.js | 13 +++++++++++-- public/views/status.html | 34 ++++++++++++++++++++++----------- 7 files changed, 60 insertions(+), 33 deletions(-) diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js index f12087e..30671ee 100644 --- a/app/controllers/addresses.js +++ b/app/controllers/addresses.js @@ -19,10 +19,12 @@ exports.address = function(req, res, next, addr) { } a.update(function(err) { - if (err) return common.handleErrors(err, res, next); - - req.address = a; - return next(); + if (err) + return common.handleErrors(err, res); + else { + req.address = a; + return next(); + } }); }; diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 316f17f..37324a0 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -13,10 +13,12 @@ var mongoose = require('mongoose'), */ exports.block = function(req, res, next, hash) { Block.fromHashWithInfo(hash, function(err, block) { - if (err || ! block) return common.handleErrors(err, res, next); - - req.block = block.info; - return next(); + if (err || ! block) + return common.handleErrors(err, res, next); + else { + req.block = block.info; + return next(); + } }); }; diff --git a/app/controllers/common.js b/app/controllers/common.js index faae67c..b44756b 100644 --- a/app/controllers/common.js +++ b/app/controllers/common.js @@ -1,7 +1,7 @@ 'use strict'; -exports.handleErrors = function (err, res, next) { +exports.handleErrors = function (err, res) { if (err) { if (err.code) { res.status(400).send(err.message + '. Code:' + err.code); @@ -9,10 +9,8 @@ exports.handleErrors = function (err, res, next) { else { res.status(503).send(err.message); } - return next(); } else { res.status(404).send('Not found'); - return next(); } }; diff --git a/app/controllers/status.js b/app/controllers/status.js index 6652359..1874605 100644 --- a/app/controllers/status.js +++ b/app/controllers/status.js @@ -4,7 +4,8 @@ * Module dependencies. */ -var Status = require('../models/Status'); +var Status = require('../models/Status'), + common = require('./common'); /** * Status @@ -19,8 +20,11 @@ exports.show = function(req, res, next) { var statusObject = Status.new(); var returnJsonp = function (err) { - if(err) return next(err); - res.jsonp(statusObject); + if (err || ! statusObject) + return common.handleErrors(err, res); + else { + res.jsonp(statusObject); + } }; switch(option) { diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js index c865f57..991dd21 100644 --- a/app/controllers/transactions.js +++ b/app/controllers/transactions.js @@ -15,12 +15,12 @@ var common = require('./common'); */ exports.transaction = function(req, res, next, txid) { Transaction.fromIdWithInfo(txid, function(err, tx) { - - if (err || ! tx) return common.handleErrors(err, res, next); - - - req.transaction = tx.info; - return next(); + if (err || ! tx) + return common.handleErrors(err, res); + else { + req.transaction = tx.info; + return next(); + } }); }; diff --git a/public/js/controllers/status.js b/public/js/controllers/status.js index dcfd52e..8fa2f24 100644 --- a/public/js/controllers/status.js +++ b/public/js/controllers/status.js @@ -7,15 +7,24 @@ angular.module('insight.status').controller('StatusController', ['$scope', '$rou Status.get({ q: 'get' + q }, function(d) { + $rootScope.infoError = null; angular.extend($scope, d); + }, function(e) { + if (e.status === 503) { + $rootScope.infoError = 'Backend Error. ' + e.data; + } + else { + $rootScope.infoError = 'Unknown error:' + e.data; + } }); }; $scope.getSync = function() { Sync.get({}, function(sync) { + $rootScope.syncError = null; $scope.sync = sync; - }, function() { - $rootScope.flashMessage = 'Could not get sync information'; + }, function(e) { + $rootScope.syncError = 'Could not get sync information' + e; }); }; }]); diff --git a/public/views/status.html b/public/views/status.html index ce4c880..7195119 100644 --- a/public/views/status.html +++ b/public/views/status.html @@ -9,9 +9,10 @@

getInfo

- - - + + + @@ -65,8 +66,8 @@ - - + +
Loading...
Loading... +
{{infoError}}
Version {{info.version}}{{info.paytxfee}}
errors{{info.errors}}infoErrors{{info.infoErrors}}
@@ -75,8 +76,8 @@

sync status

- - + + @@ -125,9 +126,12 @@

getTxOutSetInfo

{{ syncError }}
{{ sync.err }}
- + + + + @@ -166,9 +170,13 @@

getDifficulty

Loading...
{{infoError}}
Height {{txoutsetinfo.height}}
- + + + + + @@ -180,10 +188,14 @@

getLastBlockHash

Loading...
{{infoError}}
Difficulty {{difficulty}}
- - + + + + + +
Loading...
Loading...
{{infoError}}
Last block hash {{lastblockhash}}