fix conflics.

This commit is contained in:
Matias Alejo Garcia 2014-02-13 00:28:30 -03:00
commit e5f92ed030
23 changed files with 173 additions and 91 deletions

4
.gitignore vendored
View File

@ -29,9 +29,13 @@ npm-debug.log
.DS_Store
public/lib/*
db/txs/*
db/txs
db/testnet/txs/*
db/testnet/txs
db/blocks/*
db/blocks
db/testnet/blocks/*
db/testnet/blocks
public/js/*
public/css/*

View File

@ -3,9 +3,9 @@
/**
* Module dependencies.
*/
var common = require('./common'),
async = require('async'),
BlockDb = require('../../lib/BlockDb').class();
var common = require('./common'),
async = require('async'),
BlockDb = require('../../lib/BlockDb').class();
var bdb = new BlockDb();
@ -14,7 +14,7 @@ var bdb = new BlockDb();
*/
exports.block = function(req, res, next, hash) {
bdb.fromHashWithInfo(hash, function(err, block) {
if (err || ! block)
if (err || !block)
return common.handleErrors(err, res, next);
else {
req.block = block.info;
@ -41,8 +41,7 @@ exports.blockindex = function(req, res, next, height) {
if (err) {
console.log(err);
res.status(400).send('Bad Request'); // TODO
}
else {
} else {
res.jsonp(hashStr);
}
});
@ -57,7 +56,7 @@ var getBlock = function(blockhash, cb) {
// TODO
if (!block.info) {
console.log('[blocks.js.60]: could not get %s from RPC. Orphan? Error?', blockhash); //TODO
console.log('[blocks.js.60]: could not get %s from RPC. Orphan? Error?', blockhash); //TODO
// Probably orphan
block.info = {
hash: blockhash,
@ -75,10 +74,10 @@ exports.list = function(req, res) {
var isToday = false;
//helper to convert timestamps to yyyy-mm-dd format
var formatTimestamp = function (date) {
var formatTimestamp = function(date) {
var yyyy = date.getUTCFullYear().toString();
var mm = (date.getUTCMonth() + 1).toString(); // getMonth() is zero-based
var dd = date.getUTCDate().toString();
var dd = date.getUTCDate().toString();
return yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]); //padding
};
@ -107,10 +106,10 @@ exports.list = function(req, res) {
res.status(500).send(err);
}
else {
var limit = parseInt(req.query.limit || blocks.length);
if (blocks.length < limit) {
limit = blocks.length;
}
var l = blocks.length;
var limit = parseInt(req.query.limit || l);
if (l < limit) limit = l;
async.mapSeries(blocks,
function(b, cb) {
getBlock(b.hash, function(err, info) {
@ -123,18 +122,18 @@ exports.list = function(req, res) {
});
});
}, function(err, allblocks) {
res.jsonp({
blocks: allblocks,
length: allblocks.length,
pagination: {
next: next,
prev: prev,
currentTs: lte-1,
current: dateStr,
isToday: isToday
}
res.jsonp({
blocks: allblocks,
length: allblocks.length,
pagination: {
next: next,
prev: prev,
currentTs: lte - 1,
current: dateStr,
isToday: isToday
}
});
});
});
}
});
};

View File

@ -3,6 +3,7 @@
// server-side socket behaviour
// io is a variable already taken in express
var ios = null;
var util = require('bitcore/util/util');
module.exports.init = function(app, io_ext) {
ios = io_ext;
@ -25,10 +26,10 @@ module.exports.broadcastTx = function(tx) {
// Outputs
var valueOut = 0;
t.vout.forEach( function(o) {
valueOut += o.value * 100000000;
valueOut += o.value * util.COIN;
});
t.valueOut = valueOut / 100000000;
t.valueOut = parseInt(valueOut) / util.COIN;
}
ios.sockets.in('inv').emit('tx', t);
}

View File

@ -50,3 +50,8 @@ exports.sync = function(req, res) {
if (req.historicSync)
res.jsonp(req.historicSync.info());
};
exports.peer = function(req, res) {
if (req.peerSync)
res.jsonp(req.peerSync.info());
};

View File

@ -7,13 +7,17 @@ var express = require('express'),
helpers = require('view-helpers'),
config = require('./config');
module.exports = function(app, historicSync) {
module.exports = function(app, historicSync, peerSync) {
//custom middleware
function setHistoric(req, res, next) {
req.historicSync = historicSync;
next();
}
function setPeer(req, res, next) {
req.peerSync = peerSync;
next();
}
app.set('showStackError', true);
@ -28,6 +32,7 @@ module.exports = function(app, historicSync) {
app.enable('jsonp callback');
app.use('/api/sync', setHistoric);
app.use('/api/peer', setPeer);
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());

View File

@ -29,6 +29,7 @@ module.exports = function(app) {
app.get('/api/status', st.show);
app.get('/api/sync', st.sync);
app.get('/api/peer', st.peer);
// Currency
var currency = require('../app/controllers/currency');

View File

@ -17,7 +17,7 @@ hash = 'e2253359458db3e732c82a43fc62f56979ff59928f25a2df34dfa443e9a41160';
var rpc = new RpcClient(config.bitcoind);
rpc.getRawTransaction( hash, 1, function(err, ret) {
rpc.getBlockCount( function(err, ret) {
console.log('Err:');
console.log(err);

View File

@ -43,8 +43,11 @@ walk(models_path);
/**
* p2pSync process
*/
var peerSync = new PeerSync();
if (!config.disableP2pSync) {
var ps = new PeerSync();
var ps = peerSync;
ps.init({
shouldBroadcast: true,
}, function() {
@ -83,7 +86,7 @@ if (!config.disableHistoricSync) {
//express settings
require('./config/express')(expressApp, historicSync);
require('./config/express')(expressApp, historicSync, peerSync);
//Bootstrap routes
require('./config/routes')(expressApp);

View File

@ -33,7 +33,6 @@ function spec() {
this.syncPercentage = 0;
this.syncedBlocks = 0;
this.skippedBlocks = 0;
this.orphanBlocks = 0;
this.type ='';
}
@ -88,11 +87,11 @@ function spec() {
HistoricSync.prototype.info = function() {
this.updatePercentage();
return {
status: this.status,
blockChainHeight: this.blockChainHeight,
syncPercentage: this.syncPercentage,
skippedBlocks: this.skippedBlocks,
syncedBlocks: this.syncedBlocks,
orphanBlocks: this.orphanBlocks,
syncTipHash: this.sync.tip,
@ -101,20 +100,24 @@ function spec() {
};
};
HistoricSync.prototype.updatePercentage = function() {
var r = this.syncedBlocks / this.blockChainHeight;
this.syncPercentage = parseFloat(100 * r).toFixed(3);
if (this.syncPercentage > 100) this.syncPercentage = 100;
};
HistoricSync.prototype.showProgress = function() {
var self = this;
if ( self.status ==='syncing' &&
( self.syncedBlocks + self.skippedBlocks) % self.step !== 1) return;
( self.syncedBlocks ) % self.step !== 1) return;
if (self.error) {
p('ERROR: ' + self.error);
}
else {
self.syncPercentage = parseFloat(100 * self.syncedBlocks / self.blockChainHeight).toFixed(3);
if (self.syncPercentage > 100) self.syncPercentage = 100;
p(util.format('status: [%d%%] skipped: %d ', self.syncPercentage, self.skippedBlocks));
self.updatePercentage();
p(util.format('status: [%d%%]', self.syncPercentage));
}
if (self.opts.shouldBroadcastSync) {
sockets.broadcastSyncInfo(self.info());
@ -189,21 +192,21 @@ function spec() {
self.status = 'syncing';
}
if ( (scanOpts.upToExisting && existed &&
self.syncedBlocks >= self.blockChainHeight) ||
(blockEnd && blockEnd === blockHash)) {
if ( blockEnd && blockEnd === blockHash) {
p('blockEnd found!:' + blockEnd);
self.found=1;
}
if ( self.found && self.syncedBlocks >= self.blockChainHeight ) {
self.status = 'finished';
p('DONE. Found block: ', blockHash);
p('DONE. Height: ' , self.syncedBlocks);
return cb(err);
}
// Continue
if (blockInfo) {
if (existed)
self.skippedBlocks++;
else
self.syncedBlocks++;
self.syncedBlocks++;
// recursion
if (scanOpts.prev && blockInfo.previousblockhash)
@ -337,7 +340,6 @@ function spec() {
self.rpc.getBlockHash(self.blockChainHeight, function(err, res) {
if (err) return cb(err);
lastBlock = res.result;
return cb();
});
},
@ -353,8 +355,7 @@ function spec() {
},
function(cb) {
if (scanOpts.upToExisting) {
// should be isOrphan = true or null to be more accurate.
if (scanOpts.reverse) {
self.countNotOrphan(function(err, count) {
if (err) return cb(err);
@ -389,7 +390,7 @@ function spec() {
if (scanOpts.reverse) {
start = lastBlock;
end = tip || self.genesis;
end = tip || self.genesis;
scanOpts.prev = true;
}
else {
@ -460,10 +461,9 @@ function spec() {
}
}
else {
p('Genesis block found. Syncing upto known blocks.');
p('Genesis block found. Syncing upto old TIP.');
p('Got ' + count + ' out of ' + self.blockChainHeight + ' blocks');
scanOpts.reverse = true;
scanOpts.upToExisting = true;
}
return self.importHistory(scanOpts, next);
});

View File

@ -12,12 +12,12 @@ function spec() {
var networks = require('bitcore/networks');
var peerdb_fn = 'peerdb.json';
function PeerSync() {}
PeerSync.prototype.init = function(opts, cb) {
if (!opts) opts = {};
this.connected = false;
this.peerdb = undefined;
this.allowReorgs = false;
@ -42,6 +42,12 @@ function spec() {
fs.writeFileSync(peerdb_fn, JSON.stringify(this.peerdb));
};
PeerSync.prototype.info = function() {
return {
connected: this.connected
};
};
PeerSync.prototype.handleInv = function(info) {
var invs = info.message.invs;
invs.forEach(function(inv) {
@ -114,12 +120,17 @@ function spec() {
});
this.peerman.on('connection', function(conn) {
self.connected = true;
conn.on('inv', self.handleInv.bind(self));
conn.on('block', self.handleBlock.bind(self));
conn.on('tx', self.handleTx.bind(self));
});
this.peerman.on('connect', self.handle_connected.bind(self));
this.peerman.on('netDisconnected', function() {
self.connected = false;
});
this.peerman.start();
};

View File

@ -1,7 +1,6 @@
{
"name": "insight",
"name": "insight-bitcore",
"version": "0.0.1",
"private": true,
"author": {
"name": "Ryan X Charles",
"email": "ryan@bitpay.com"

BIN
public/img/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -138,6 +138,13 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
font-family: 'Ubuntu', sans-serif;
}
#search.loading {
background-image: url('/img/loading.gif');
background-position: 5px center;
background-repeat: no-repeat;
padding-left: 25px;
}
#search::-webkit-input-placeholder {
color: #BCDF7E;
font-family: 'Ubuntu', sans-serif;
@ -186,6 +193,7 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
position: fixed;
width: 250px;
border: 1px solid #eee;
z-index: 1;
}
@media (max-width: 768px) {
@ -302,27 +310,40 @@ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
border: 2px solid #6C0000;
}
.label {
.txvalues {
display: inline-block;
padding: .7em 2em;
font-size: 13px;
text-transform: uppercase;
font-weight:100;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
}
.label-primary {
@media (max-width: 768px) {
.txvalues {
display: block;
margin: 5px;
}
}
.txvalues-primary {
background-color: #8DC429;
}
.label-default {
.txvalues-default {
background-color: #ffffff;
color: #333;
}
.label-success {
.txvalues-success {
background-color: #2FA4D7;
}
.label-danger {
.txvalues-danger {
background-color: #AC0015;
}

View File

@ -16,6 +16,27 @@ angular.module('insight.blocks').controller('BlocksController',
});
}
//Datepicker
var _formatTimestamp = function (date) {
var yyyy = date.getUTCFullYear().toString();
var mm = (date.getUTCMonth() + 1).toString(); // getMonth() is zero-based
var dd = date.getUTCDate().toString();
return yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]); //padding
};
$scope.$watch('dt', function(newValue, oldValue) {
if (newValue !== oldValue) {
$location.path('/blocks-date/' + _formatTimestamp(newValue));
}
});
$scope.openCalendar = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.humanSince = function(time) {
var m = moment.unix(time).startOf('day');

View File

@ -1,7 +1,7 @@
'use strict';
angular.module('insight.connection').controller('ConnectionController',
function($scope, $window, Status, Sync, getSocket) {
function($scope, $window, Status, getSocket, PeerSync) {
// Set initial values
$scope.apiOnline = true;
@ -21,9 +21,9 @@ function($scope, $window, Status, Sync, getSocket) {
// Check for the api connection
$scope.getConnStatus = function() {
Sync.get({},
function(sync) {
$scope.apiOnline = (sync.status !== 'aborted' && sync.status !== 'error');
PeerSync.get({},
function(peer) {
$scope.apiOnline = peer.connected;
},
function() {
$scope.apiOnline = false;

View File

@ -23,7 +23,6 @@ angular.module('insight.system').controller('IndexController',
$scope.flashMessage = $rootScope.flashMessage || null;
socket.on('tx', function(tx) {
console.log('Transaction received! ' + tx.txid);
$scope.txs.unshift(tx);
if (parseInt($scope.txs.length, 10) >= parseInt(TRANSACTION_DISPLAYED, 10)) {
$scope.txs = $scope.txs.splice(0, TRANSACTION_DISPLAYED);
@ -32,7 +31,6 @@ angular.module('insight.system').controller('IndexController',
socket.on('block', function(block) {
var blockHash = block.toString();
console.log('Block received! ' + JSON.stringify(blockHash));
_getBlocks();
});

View File

@ -3,6 +3,7 @@
angular.module('insight.search').controller('SearchController',
function($scope, $routeParams, $location, $timeout, Global, Block, Transaction, Address, BlockByHeight) {
$scope.global = Global;
$scope.loading = false;
var _badQuery = function() {
$scope.badQuery = true;
@ -12,39 +13,46 @@ angular.module('insight.search').controller('SearchController',
}, 2000);
};
var _resetSearch = function() {
$scope.q = '';
$scope.loading = false;
};
$scope.search = function() {
var q = $scope.q;
$scope.badQuery = false;
$scope.loading = true;
Block.get({
blockHash: q
}, function() {
$scope.q = '';
_resetSearch();
$location.path('block/' + q);
}, function () { //block not found, search on TX
}, function() { //block not found, search on TX
Transaction.get({
txId: q
}, function() {
$scope.q = '';
_resetSearch();
$location.path('tx/' + q);
}, function () { //tx not found, search on Address
}, function() { //tx not found, search on Address
Address.get({
addrStr: q
}, function() {
$scope.q = '';
_resetSearch();
$location.path('address/' + q);
}, function () { // block by height not found
}, function() { // block by height not found
if (isFinite(q)) { // ensure that q is a finite number. A logical height value.
BlockByHeight.get({
blockHeight: q
}, function(hash) {
$scope.q = '';
_resetSearch();
$location.path('/block/' + hash.blockHash);
}, function() { //not found, fail :(
_badQuery();
});
}
else {
$scope.loading = false;
_badQuery();
}
});

View File

@ -3,11 +3,15 @@
angular.module('insight.status')
.factory('Status',
function($resource) {
return $resource('/api/status', {
q: '@q'
});
})
return $resource('/api/status', {
q: '@q'
});
})
.factory('Sync',
function($resource) {
return $resource('/api/sync');
});
})
.factory('PeerSync',
function($resource) {
return $resource('api/peer');
});

View File

@ -8,7 +8,10 @@
<h3>Blocks <br> mined on:</h3>
</div>
</div>
<p class="lead text-center m20v">{{pagination.current}} UTC</p>
<p class="lead text-center m20v">
{{pagination.current}} UTC
<a href="#" class="btn btn-primary btn-xs" datepicker-popup show-button-bar="false" data-ng-click="openCalendar($event)" data-ng-model="dt" is-open="opened" data-ng-required="true"><span class="glyphicon glyphicon-calendar"></span></a>
</p>
<p class="lead text-center m20v" data-ng-show="loading">&nbsp;</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)}}
@ -31,8 +34,8 @@
<tr>
<th>Height</th>
<th>Timestamp</th>
<th>Transactions</th>
<th>Size</th>
<th class="text-right">Transactions</th>
<th class="text-right">Size</th>
</tr>
</thead>
<tbody>
@ -42,8 +45,8 @@
<tr class="fader" data-ng-repeat='b in blocks'>
<td><a href="/block/{{b.hash}}">{{b.height}}</a></td>
<td>{{b.time * 1000 | date:'medium'}}</td>
<td>{{b.txlength}}</td>
<td>{{b.size}}</td>
<td class="text-right">{{b.txlength}}</td>
<td class="text-right">{{b.size}}</td>
</tr>
</tbody>
</table>

View File

@ -17,7 +17,7 @@
</ul>
<form data-ng-controller="SearchController" class="navbar-form navbar-left" role="search" data-ng-submit="search()">
<div class="form-group" data-ng-class="{'has-error': badQuery}">
<input id="search" type="text" class="form-control" data-ng-model="q" placeholder="Search for block, transaction or address">
<input id="search" type="text" class="form-control" data-ng-model="q" data-ng-class="{'loading': loading}" placeholder="Search for block, transaction or address">
</div>
<div class="no_matching text-danger" data-ng-show="badQuery">No matching records found!</div>
</form>

View File

@ -24,7 +24,7 @@
</td>
<td><span class="ellipsis">{{humanSince(b.time)}}</span></td>
<td class="text-right">{{b.txlength}}</td>
<td class="text-right">{{b.size}}</td>
<td class="text-right">{{b.size}} bytes</td>
</tr>
</tbody>
</table>

View File

@ -141,12 +141,12 @@
</div>
</div>
<div class="line-top row">
<div class="col-xs-4 col-md-6">
<span data-ng-show="!tx.isCoinBase && !isNaN(parseFloat(tx.fees))" class="label label-default">Fees: {{$root.currency.getConvertion(tx.fees)}} </span>
<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>
</div>
<div class="col-xs-8 col-md-6 text-right">
<span data-ng-show="tx.confirmations" class="label label-success">{{tx.confirmations}} Confirmations</span>
<span data-ng-show="!tx.confirmations" class="label label-danger">Unconfirmed Transaction!</span>
<span class="label label-primary">{{$root.currency.getConvertion(tx.valueOut)}}</span>
<div class="col-xs-12 col-sm-8 col-md-8 text-right">
<span data-ng-show="tx.confirmations" class="txvalues txvalues-success">{{tx.confirmations}} Confirmations</span>
<span data-ng-show="!tx.confirmations" class="txvalues txvalues-danger">Unconfirmed Transaction!</span>
<span class="txvalues txvalues-primary">{{$root.currency.getConvertion(tx.valueOut)}}</span>
</div>
</div>

View File

@ -43,7 +43,6 @@ async.series([
historicSync.importHistory({
destroy: program.destroy,
reverse: program.reverse,
upToExisting: program.uptoexisting,
fromFiles: program.fromfiles,
}, cb);
}