@ -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 . sync edBlocks ) ;
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 . importH istory = 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 ) / 100 ) ;
if ( self . opts . progressStep ) {
step = self . opts . progressStep ;
}
if ( step < 100 ) step = 100 ;
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_i mport = function ( next ) {
HistoricSync . prototype . smartI mport = function ( next ) {
var self = this ;
Block . findOne ( {
@ -335,7 +339,7 @@ function spec() {
upToExisting : b ? true : false ,
} ;
return self . import_h istory ( opts , next ) ;
return self . importH istory ( opts , next ) ;
} ) ;
} ;