diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 2b2ab152..0f47bc40 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -5,9 +5,11 @@ */ var common = require('./common'), async = require('async'), - BlockDb = require('../../lib/BlockDb'); + BlockDb = require('../../lib/BlockDb'), + TransactionDb = require('../../lib/TransactionDb'); var bdb = new BlockDb(); +var tdb = new TransactionDb(); /** * Find block by hash ... @@ -17,7 +19,7 @@ exports.block = function(req, res, next, hash) { if (err || !block) return common.handleErrors(err, res, next); else { - bdb.getPoolInfo(block.info.tx[0], function(info) { + tdb.getPoolInfo(block.info.tx[0], function(info) { block.info.poolInfo = info; req.block = block.info; return next(); @@ -67,7 +69,7 @@ var getBlock = function(blockhash, cb) { }; } - bdb.getPoolInfo(block.info.tx[0], function(info) { + tdb.getPoolInfo(block.info.tx[0], function(info) { block.info.poolInfo = info; return cb(err, block.info); }); diff --git a/app/controllers/socket.js b/app/controllers/socket.js index 8974837e..9ecd56f1 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -32,10 +32,10 @@ module.exports.broadcastTx = function(tx) { // Outputs var valueOut = 0; tx.vout.forEach(function(o) { - valueOut += o.value * util.COIN; + valueOut += o.valueSat; }); - t.valueOut = parseInt(valueOut) / util.COIN; + t.valueOut = (valueOut/util.COIN).toFixed(0); } ios.sockets.in('inv').emit('tx', t); } diff --git a/app/models/Address.js b/app/models/Address.js index 722607f2..370a4b12 100644 --- a/app/models/Address.js +++ b/app/models/Address.js @@ -9,6 +9,8 @@ var BitcoreUtil = bitcore.util; var Parser = bitcore.BinaryParser; var Buffer = bitcore.Buffer; var TransactionDb = imports.TransactionDb || require('../../lib/TransactionDb').default(); +var BlockDb = imports.BlockDb || require('../../lib/BlockDb').default(); +var config = require('../../config/config'); var CONCURRENCY = 5; function Address(addrStr) { @@ -20,6 +22,7 @@ function Address(addrStr) { this.txApperances = 0; this.unconfirmedTxApperances= 0; + this.seen = {}; // TODO store only txids? +index? +all? this.transactions = []; @@ -71,125 +74,123 @@ function Address(addrStr) { } -Address.prototype._getScriptPubKey = function(hex,n) { - // ScriptPubKey is not provided by bitcoind RPC, so we parse it from tx hex. - - var parser = new Parser(new Buffer(hex,'hex')); - var tx = new BitcoreTransaction(); - tx.parse(parser); - return (tx.outs[n].s.toString('hex')); -}; - Address.prototype.getUtxo = function(next) { var self = this; - if (!self.addrStr) return next(); + var tDb = TransactionDb; + var bDb = BlockDb; + var ret; + if (!self.addrStr) return next(new Error('no error')); - var ret = []; - var db = TransactionDb; - - db.fromAddr(self.addrStr, function(err,txOut){ + tDb.fromAddr(self.addrStr, function(err,txOut){ if (err) return next(err); + var unspent = txOut.filter(function(x){ + return !x.spentTxId; + }); - // Complete utxo info - async.eachLimit(txOut,CONCURRENCY,function (txItem, a_c) { - db.fromIdInfoSimple(txItem.txid, function(err, info) { - if (!info || !info.hex) return a_c(err); - - var scriptPubKey = self._getScriptPubKey(info.hex, txItem.index); - - // we are filtering out even unconfirmed spents! - // add || !txItem.spentIsConfirmed - if (!txItem.spentTxId) { - ret.push({ + bDb.fillConfirmations(unspent, function() { + tDb.fillScriptPubKey(unspent, function() { + ret = unspent.map(function(x){ + return { address: self.addrStr, - txid: txItem.txid, - vout: txItem.index, - ts: txItem.ts, - scriptPubKey: scriptPubKey, - amount: txItem.value_sat / BitcoreUtil.COIN, - confirmations: txItem.isConfirmed ? info.confirmations : 0, - }); - } - return a_c(err); + txid: x.txid, + vout: x.index, + ts: x.ts, + scriptPubKey: x.scriptPubKey, + amount: x.value_sat / BitcoreUtil.COIN, + confirmations: x.isConfirmedCached ? (config.safeConfirmations+'+') : x.confirmations, + }; + }); + return next(null, ret); }); - }, function(err) { - return next(err,ret); }); }); }; + +Address.prototype._addTxItem = function(txItem, notxlist) { + var add=0, addSpend=0; + var v = txItem.value_sat; + var seen = this.seen; + var txs = []; + + if ( !seen[txItem.txid] ) { + if (!notxlist) { + txs.push({txid: txItem.txid, ts: txItem.ts}); + } + seen[txItem.txid]=1; + add=1; + } + + if (txItem.spentTxId && !seen[txItem.spentTxId] ) { + if (!notxlist) { + txs.push({txid: txItem.spentTxId, ts: txItem.spentTs}); + } + seen[txItem.spentTxId]=1; + addSpend=1; + } + if (txItem.isConfirmed) { + this.txApperances += add; + this.totalReceivedSat += v; + if (! txItem.spentTxId ) { + //unspent + this.balanceSat += v; + } + else if(!txItem.spentIsConfirmed) { + // unspent + this.balanceSat += v; + this.unconfirmedBalanceSat -= v; + this.unconfirmedTxApperances += addSpend; + } + else { + // spent + this.totalSentSat += v; + this.txApperances += addSpend; + } + } + else { + this.unconfirmedBalanceSat += v; + this.unconfirmedTxApperances += add; + } + return txs; +}; + +Address.prototype._setTxs = function(txs) { + + // sort input and outputs togheter + txs.sort( + function compare(a,b) { + if (a.ts < b.ts) return 1; + if (a.ts > b.ts) return -1; + return 0; + }); + + this.transactions = txs.map(function(i) { return i.txid; } ); +}; + Address.prototype.update = function(next, notxlist) { var self = this; if (!self.addrStr) return next(); var txs = []; - var db = TransactionDb; - async.series([ - function (cb) { - var seen={}; - db.fromAddr(self.addrStr, function(err,txOut){ - if (err) return cb(err); + var tDb = TransactionDb; + var bDb = BlockDb; + tDb.fromAddr(self.addrStr, function(err,txOut){ + if (err) return next(err); + + bDb.fillConfirmations(txOut, function(err) { + if (err) return next(err); + tDb.cacheConfirmations(txOut, function(err) { + if (err) return next(err); + txOut.forEach(function(txItem){ - var add=0, addSpend=0; - var v = txItem.value_sat; - - if ( !seen[txItem.txid] ) { - if (!notxlist) { - txs.push({txid: txItem.txid, ts: txItem.ts}); - } - seen[txItem.txid]=1; - add=1; - } - - if (txItem.spentTxId && !seen[txItem.spentTxId] ) { - if (!notxlist) { - txs.push({txid: txItem.spentTxId, ts: txItem.spentTs}); - } - seen[txItem.spentTxId]=1; - addSpend=1; - } - - if (txItem.isConfirmed) { - self.txApperances += add; - self.totalReceivedSat += v; - if (! txItem.spentTxId ) { - //unspent - self.balanceSat += v; - } - else if(!txItem.spentIsConfirmed) { - // unspent - self.balanceSat += v; - self.unconfirmedBalanceSat -= v; - self.unconfirmedTxApperances += addSpend; - } - else { - // spent - self.totalSentSat += v; - self.txApperances += addSpend; - } - } - else { - self.unconfirmedBalanceSat += v; - self.unconfirmedTxApperances += add; - } + txs=txs.concat(self._addTxItem(txItem, notxlist)); }); - return cb(); + + if (!notxlist) + self._setTxs(txs); + return next(); }); - }, - ], function (err) { - - if (!notxlist) { - // sort input and outputs togheter - txs.sort( - function compare(a,b) { - if (a.ts < b.ts) return 1; - if (a.ts > b.ts) return -1; - return 0; - }); - - self.transactions = txs.map(function(i) { return i.txid; } ); - } - return next(err); + }); }); }; diff --git a/config/config.js b/config/config.js index b5a76756..c89fc3a9 100644 --- a/config/config.js +++ b/config/config.js @@ -91,5 +91,6 @@ module.exports = { currencyRefresh: 10, keys: { segmentio: process.env.INSIGHT_SEGMENTIO_KEY - } + }, + safeConfirmations: 6, // PLEASE NOTE THAT *FULL RESYNC* IS NEEDED TO CHANGE safeConfirmations }; diff --git a/dev-util/node-tick-report b/dev-util/node-tick-report new file mode 100644 index 00000000..3f9461d8 --- /dev/null +++ b/dev-util/node-tick-report @@ -0,0 +1,1328 @@ +Code move event for unknown code: 0x278907110560 +Code move event for unknown code: 0x27890730a4e0 +Statistical profiling result from v8.log, (24141 ticks, 452 unaccounted, 0 excluded). + + [Unknown]: + ticks total nonlib name + 452 1.9% + + [Shared libraries]: + ticks total nonlib name + 9018 37.4% 0.0% /usr/local/bin/node + 8405 34.8% 0.0% /usr/lib/system/libsystem_kernel.dylib + 606 2.5% 0.0% /usr/lib/system/libsystem_c.dylib + 509 2.1% 0.0% /usr/lib/system/libsystem_malloc.dylib + 375 1.6% 0.0% /usr/lib/system/libsystem_platform.dylib + 187 0.8% 0.0% /usr/lib/system/libsystem_pthread.dylib + 75 0.3% 0.0% /usr/lib/system/libsystem_m.dylib + 73 0.3% 0.0% /usr/lib/libc++abi.dylib + 31 0.1% 0.0% /usr/lib/libstdc++.6.dylib + + [JavaScript]: + ticks total nonlib name + 133 0.6% 2.7% LazyCompile: formatValue util.js:204 + 122 0.5% 2.5% LazyCompile: *formatProperty util.js:353 + 113 0.5% 2.3% Stub: CEntryStub + 96 0.4% 2.0% Builtin: A builtin from the snapshot {3} + 95 0.4% 2.0% Builtin: A builtin from the snapshot {2} + 92 0.4% 1.9% LazyCompile: *Batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:13 + 87 0.4% 1.8% LazyCompile: *ConvertDescriptorArrayToDescriptor native v8natives.js:581 + 84 0.3% 1.7% LazyCompile: *map native array.js:1215 + 81 0.3% 1.7% Stub: StringAddStub + 72 0.3% 1.5% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 65 0.3% 1.3% LazyCompile: *inspect buffer.js:283 + 64 0.3% 1.3% LazyCompile: native messages.js:1157 + 60 0.2% 1.2% LazyCompile: ToObject native runtime.js:567 + 58 0.2% 1.2% Stub: FastNewClosureStub {1} + 58 0.2% 1.2% LazyCompile: *FromPropertyDescriptor native v8natives.js:373 + 51 0.2% 1.0% Builtin: A builtin from the snapshot {1} + 50 0.2% 1.0% LazyCompile: stringify native json.js:308 + 50 0.2% 1.0% LazyCompile: join native array.js:410 + 47 0.2% 1.0% KeyedLoadIC: A keyed load IC from the snapshot + 46 0.2% 0.9% LazyCompile: *BuildResultFromMatchInfo native regexp.js:130 + 45 0.2% 0.9% Stub: CallFunctionStub_Args0_Recording + 43 0.2% 0.9% Stub: CallConstructStub + 42 0.2% 0.9% LazyCompile: *ArraySlice native array.js:621 + 40 0.2% 0.8% Stub: JSEntryStub + 40 0.2% 0.8% LazyCompile: *PropertyDescriptor native v8natives.js:482 + 39 0.2% 0.8% Stub: KeyedStoreElementStub + 39 0.2% 0.8% Stub: CompareStub + 39 0.2% 0.8% Stub: CallConstructStub {1} + 39 0.2% 0.8% LazyCompile: Join native array.js:119 + 39 0.2% 0.8% LazyCompile: *forEach native array.js:1087 + 37 0.2% 0.8% Stub: CallFunctionStub {1} + 36 0.1% 0.7% RegExp: ^"([a-zA-Z_][a-zA-Z_0-9]*)"$ + 36 0.1% 0.7% LazyCompile: Batch.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:19 + 34 0.1% 0.7% LazyCompile: *BasicJSONSerialize native json.js:274 + 34 0.1% 0.7% Builtin: A builtin from the snapshot + 33 0.1% 0.7% Stub: RegExpExecStub + 32 0.1% 0.7% Stub: SubStringStub + 32 0.1% 0.7% LazyCompile: *substr native string.js:695 + 31 0.1% 0.6% Stub: InstanceofStub + 30 0.1% 0.6% Stub: ToBooleanStub {2} + 30 0.1% 0.6% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 30 0.1% 0.6% LazyCompile: *Buffer.slice buffer.js:539 + 28 0.1% 0.6% LazyCompile: toString native v8natives.js:223 + 28 0.1% 0.6% LazyCompile: IN native runtime.js:354 + 28 0.1% 0.6% LazyCompile: *LevelUP.get /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:163 + 28 0.1% 0.6% LazyCompile: *GetOwnProperty native v8natives.js:637 + 27 0.1% 0.6% Stub: CompareICStub {4} + 27 0.1% 0.6% LazyCompile: native string.js:36 + 27 0.1% 0.6% LazyCompile: *getOwnPropertyDescriptor native v8natives.js:946 + 25 0.1% 0.5% LazyCompile: *toString native v8natives.js:1378 + 25 0.1% 0.5% LazyCompile: *isCoinBase /Users/ematiu/devel/node/bitcore/lib/Transaction.js:49 + 25 0.1% 0.5% LazyCompile: *formatPrimitive util.js:304 + 24 0.1% 0.5% LazyCompile: ToString native runtime.js:550 + 23 0.1% 0.5% Stub: CompareICStub + 23 0.1% 0.5% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:58 + 23 0.1% 0.5% LazyCompile: *indexOf native array.js:1261 + 23 0.1% 0.5% LazyCompile: *LevelUP.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:210 + 23 0.1% 0.5% LazyCompile: *Buffer.copy buffer.js:509 + 22 0.1% 0.5% LazyCompile: captureStackTrace native messages.js:1113 + 22 0.1% 0.5% LazyCompile: *split native string.js:554 + 21 0.1% 0.4% Stub: KeyedLoadElementStub {1} + 21 0.1% 0.4% LazyCompile: *Buffer.write buffer.js:315 + 20 0.1% 0.4% Stub: StringAddStub {1} + 20 0.1% 0.4% LazyCompile: *reduce native array.js:1381 + 20 0.1% 0.4% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 19 0.1% 0.4% RegExp: ^"|"$ + 19 0.1% 0.4% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:229 + 19 0.1% 0.4% LazyCompile: *match native string.js:182 + 18 0.1% 0.4% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 18 0.1% 0.4% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:238 + 18 0.1% 0.4% LazyCompile: *Script /Users/ematiu/devel/node/bitcore/lib/Script.js:25 + 18 0.1% 0.4% Builtin: A builtin from the snapshot {5} + 17 0.1% 0.3% Stub: FastNewContextStub + 17 0.1% 0.3% Stub: FastCloneShallowObjectStub + 17 0.1% 0.3% LazyCompile: ~indexOf native array.js:1261 + 17 0.1% 0.3% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 17 0.1% 0.3% LazyCompile: APPLY_PREPARE native runtime.js:438 + 17 0.1% 0.3% LazyCompile: *parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 17 0.1% 0.3% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 16 0.1% 0.3% Stub: FastNewClosureStub + 16 0.1% 0.3% Stub: CallFunctionStub_Args1 + 16 0.1% 0.3% LazyCompile: ~Script.capture /Users/ematiu/devel/node/bitcore/lib/Script.js:235 + 16 0.1% 0.3% LazyCompile: hasOwnProperty native v8natives.js:249 + 16 0.1% 0.3% LazyCompile: *indexOf native string.js:118 + 16 0.1% 0.3% LazyCompile: *ceil native math.js:79 + 15 0.1% 0.3% Stub: FastCloneShallowArrayStub {1} + 15 0.1% 0.3% Stub: BinaryOpStub + 15 0.1% 0.3% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:66 + 15 0.1% 0.3% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 15 0.1% 0.3% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 15 0.1% 0.3% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 15 0.1% 0.3% LazyCompile: *exports.formatHashFull /Users/ematiu/devel/node/bitcore/util/util.js:70 + 15 0.1% 0.3% LazyCompile: *arrayToHash util.js:193 + 15 0.1% 0.3% LazyCompile: *UseSparseVariant native array.js:111 + 15 0.1% 0.3% LazyCompile: *IsDataDescriptor native v8natives.js:354 + 15 0.1% 0.3% LazyCompile: *DefineObjectProperty native v8natives.js:695 + 14 0.1% 0.3% Stub: ToBooleanStub {1} + 14 0.1% 0.3% LazyCompile: ~EventEmitter.emit events.js:53 + 14 0.1% 0.3% LazyCompile: *inspect util.js:118 + 14 0.1% 0.3% LazyCompile: *formatArray util.js:333 + 14 0.1% 0.3% LazyCompile: *encodeKey /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:146 + 14 0.1% 0.3% LazyCompile: *Hash crypto.js:185 + 14 0.1% 0.3% LazyCompile: * util.js:293 + 13 0.1% 0.3% Stub: RecordWriteStub {1} + 13 0.1% 0.3% Stub: CallFunctionStub + 13 0.1% 0.3% LazyCompile: VersionedData /Users/ematiu/devel/node/bitcore/util/VersionedData.js:6 + 13 0.1% 0.3% LazyCompile: SimpleSlice native array.js:324 + 13 0.1% 0.3% LazyCompile: *keys native v8natives.js:333 + 13 0.1% 0.3% LazyCompile: *ToPropertyDescriptor native v8natives.js:420 + 13 0.1% 0.3% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 13 0.1% 0.3% LazyCompile: *$Array.enumerable_ native v8natives.js:523 + 12 0.0% 0.2% Stub: FastNewContextStub {1} + 12 0.0% 0.2% LazyCompile: ~exports.setImmediate timers.js:337 + 12 0.0% 0.2% LazyCompile: *replace native string.js:221 + 12 0.0% 0.2% LazyCompile: *Buffer.toString buffer.js:392 + 12 0.0% 0.2% LazyCompile: *Buffer.concat buffer.js:476 + 12 0.0% 0.2% Builtin: A builtin from the snapshot {7} + 11 0.0% 0.2% Stub: RegExpConstructResultStub + 11 0.0% 0.2% Stub: KeyedLoadElementStub + 11 0.0% 0.2% LazyCompile: ~prr /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/prr/prr.js:44 + 11 0.0% 0.2% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:204 + 11 0.0% 0.2% LazyCompile: *ToUint32 native runtime.js:586 + 11 0.0% 0.2% LazyCompile: *BlockDb.has /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:175 + 11 0.0% 0.2% LazyCompile: * /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:97 + 10 0.0% 0.2% LazyCompile: ~exports.format util.js:23 + 10 0.0% 0.2% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 10 0.0% 0.2% LazyCompile: NonNumberToNumber native runtime.js:538 + 10 0.0% 0.2% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 10 0.0% 0.2% LazyCompile: *isDate util.js:448 + 10 0.0% 0.2% LazyCompile: *isArray native array.js:1488 + 10 0.0% 0.2% LazyCompile: *exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 10 0.0% 0.2% LazyCompile: *encodings.utf8.encodings.utf-8.encode /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:40 + 10 0.0% 0.2% LazyCompile: *HistoricSync._fromBuffer /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:143 + 10 0.0% 0.2% LazyCompile: *$Array.enumerable_ native v8natives.js:516 + 9 0.0% 0.2% Stub: ToBooleanStub_UndefinedSpecObject + 9 0.0% 0.2% Stub: FastNewContextStub {2} + 9 0.0% 0.2% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:345 + 9 0.0% 0.2% LazyCompile: *serialize /Users/ematiu/devel/node/bitcore/lib/Transaction.js:152 + 9 0.0% 0.2% LazyCompile: *reduceToSingleString util.js:412 + 9 0.0% 0.2% LazyCompile: *isFinite native v8natives.js:103 + 9 0.0% 0.2% LazyCompile: *isBuffer buffer.js:277 + 9 0.0% 0.2% LazyCompile: *isArray util.js:435 + 9 0.0% 0.2% LazyCompile: *buffer /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:12 + 9 0.0% 0.2% LazyCompile: *Hash.update crypto.js:205 + 9 0.0% 0.2% LazyCompile: * util.js:414 + 9 0.0% 0.2% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 9 0.0% 0.2% LazyCompile: *$Array.writable_ native v8natives.js:530 + 9 0.0% 0.2% Builtin: A builtin from the snapshot {10} + 8 0.0% 0.2% Stub: ToBooleanStub + 8 0.0% 0.2% Stub: NumberToStringStub + 8 0.0% 0.2% Stub: BinaryOpStub_ADD_OverwriteLeft_BothStrings + 8 0.0% 0.2% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:155 + 8 0.0% 0.2% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 8 0.0% 0.2% LazyCompile: STRING_ADD_LEFT native runtime.js:183 + 8 0.0% 0.2% LazyCompile: *varIntBuf /Users/ematiu/devel/node/bitcore/util/util.js:444 + 8 0.0% 0.2% LazyCompile: *parseInt native v8natives.js:110 + 8 0.0% 0.2% LazyCompile: *isError util.js:454 + 8 0.0% 0.2% LazyCompile: *RegExpExecNoTests native regexp.js:157 + 8 0.0% 0.2% LazyCompile: * util.js:196 + 7 0.0% 0.1% Stub: ToBooleanStub_String + 7 0.0% 0.1% Stub: ToBooleanStub_SmiSpecObjectStringHeapNumber + 7 0.0% 0.1% Stub: CallFunctionStub {2} + 7 0.0% 0.1% Stub: ArgumentsAccessStub + 7 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/bitcore/util/VersionedData.js:23 + 7 0.0% 0.1% LazyCompile: toString native messages.js:1248 + 7 0.0% 0.1% LazyCompile: TransactionDb._addScript /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:462 + 7 0.0% 0.1% LazyCompile: Address /Users/ematiu/devel/node/bitcore/lib/Address.js:39 + 7 0.0% 0.1% LazyCompile: *stylizeNoColor util.js:188 + 7 0.0% 0.1% LazyCompile: *isRegExp util.js:442 + 7 0.0% 0.1% LazyCompile: *hasKeys /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/has-keys.js:3 + 7 0.0% 0.1% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Block.js:85 + 7 0.0% 0.1% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 7 0.0% 0.1% LazyCompile: *decodeLEu /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:61 + 7 0.0% 0.1% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:152 + 7 0.0% 0.1% LazyCompile: *$Array.get_ native v8natives.js:546 + 7 0.0% 0.1% LazyCompile: *$Array.configurable_ native v8natives.js:536 + 7 0.0% 0.1% KeyedStoreIC: A keyed store IC from the snapshot + 7 0.0% 0.1% Builtin: A builtin from the snapshot {9} + 7 0.0% 0.1% Builtin: A builtin from the snapshot {6} + 6 0.0% 0.1% Stub: ToBooleanStub_UndefinedString + 6 0.0% 0.1% Stub: StringAddStub {2} + 6 0.0% 0.1% Stub: RecordWriteStub {9} + 6 0.0% 0.1% Stub: RecordWriteStub {4} + 6 0.0% 0.1% Stub: RecordWriteStub {2} + 6 0.0% 0.1% Stub: CompareICStub {1} + 6 0.0% 0.1% LazyCompile: ~GetPropertyWithoutInvokingMonkeyGetters native messages.js:1203 + 6 0.0% 0.1% LazyCompile: *toLowerCase native string.js:739 + 6 0.0% 0.1% LazyCompile: *serialize /Users/ematiu/devel/node/bitcore/lib/Transaction.js:56 + 6 0.0% 0.1% LazyCompile: *isValueAsBuffer /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:162 + 6 0.0% 0.1% LazyCompile: *_map /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:53 + 6 0.0% 0.1% LazyCompile: *LevelUP._isOpening /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:155 + 6 0.0% 0.1% LazyCompile: *Hash.digest crypto.js:214 + 6 0.0% 0.1% LazyCompile: *$Array.writable_ native v8natives.js:526 + 6 0.0% 0.1% LazyCompile: *$Array.configurable_ native v8natives.js:540 + 5 0.0% 0.1% Stub: RecordWriteStub {16} + 5 0.0% 0.1% Stub: RecordWriteStub {11} + 5 0.0% 0.1% Stub: RecordWriteStub + 5 0.0% 0.1% Stub: KeyedStoreElementStub {2} + 5 0.0% 0.1% Stub: FastNewContextStub {4} + 5 0.0% 0.1% Stub: CompareStub_GE + 5 0.0% 0.1% Stub: CallFunctionStub_Args5_Recording + 5 0.0% 0.1% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:92 + 5 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:157 + 5 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/bitcore/util/VersionedData.js:32 + 5 0.0% 0.1% LazyCompile: NonStringToString native runtime.js:558 + 5 0.0% 0.1% LazyCompile: INSTANCE_OF native runtime.js:367 + 5 0.0% 0.1% LazyCompile: ErrorToStringDetectCycle native messages.js:1227 + 5 0.0% 0.1% LazyCompile: DefaultString native runtime.js:645 + 5 0.0% 0.1% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 5 0.0% 0.1% LazyCompile: *global.setImmediate node.js:192 + 5 0.0% 0.1% LazyCompile: *encodeValue /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:150 + 5 0.0% 0.1% LazyCompile: *constructor.super /Users/ematiu/devel/node/bitcore/node_modules/soop/soop.js:22 + 5 0.0% 0.1% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 5 0.0% 0.1% LazyCompile: *Sync.storeTipBlock /Users/ematiu/devel/node/insight-api/lib/Sync.js:79 + 5 0.0% 0.1% LazyCompile: *Script.isPubkey /Users/ematiu/devel/node/bitcore/lib/Script.js:89 + 5 0.0% 0.1% LazyCompile: *LazyTransform crypto.js:153 + 5 0.0% 0.1% LazyCompile: *IsAccessorDescriptor native v8natives.js:347 + 5 0.0% 0.1% LazyCompile: *HistoricSync.getStandardizedBlock /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:184 + 5 0.0% 0.1% LazyCompile: *EncodedData.doAsBinary /Users/ematiu/devel/node/bitcore/util/EncodedData.js:75 + 5 0.0% 0.1% LazyCompile: *Buffer.writeUInt8 buffer.js:792 + 5 0.0% 0.1% LazyCompile: *Block /Users/ematiu/devel/node/bitcore/lib/Block.js:20 + 5 0.0% 0.1% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 5 0.0% 0.1% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:237 + 5 0.0% 0.1% KeyedLoadIC: args_count: 0 {5} + 5 0.0% 0.1% KeyedLoadIC: args_count: 0 {3} + 5 0.0% 0.1% KeyedLoadIC: A keyed load IC from the snapshot {1} + 4 0.0% 0.1% Stub: ToBooleanStub_UndefinedSmi + 4 0.0% 0.1% Stub: RecordWriteStub {8} + 4 0.0% 0.1% Stub: RecordWriteStub {7} + 4 0.0% 0.1% Stub: RecordWriteStub {3} + 4 0.0% 0.1% Stub: FastCloneShallowObjectStub {1} + 4 0.0% 0.1% Stub: CompareICStub {5} + 4 0.0% 0.1% Stub: CompareICStub {3} + 4 0.0% 0.1% RegExp: ^\\d+$ + 4 0.0% 0.1% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 4 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:102 + 4 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:177 + 4 0.0% 0.1% LazyCompile: FILTER_KEY native runtime.js:398 + 4 0.0% 0.1% LazyCompile: DefineOneShotAccessor native messages.js:767 + 4 0.0% 0.1% LazyCompile: ConfigureTemplateInstance native apinatives.js:105 + 4 0.0% 0.1% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 4 0.0% 0.1% LazyCompile: *init _linklist.js:22 + 4 0.0% 0.1% LazyCompile: *hasOwnProperty util.js:577 + 4 0.0% 0.1% LazyCompile: *VersionedData.payload /Users/ematiu/devel/node/bitcore/util/VersionedData.js:30 + 4 0.0% 0.1% LazyCompile: *Transaction /Users/ematiu/devel/node/bitcore/lib/Transaction.js:108 + 4 0.0% 0.1% LazyCompile: *BlockDb.setLastFileIndex /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:112 + 4 0.0% 0.1% LazyCompile: *BlockDb.getTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:66 + 4 0.0% 0.1% LazyCompile: *$Array.enumerable_ native v8natives.js:520 + 4 0.0% 0.1% KeyedStoreIC: args_count: 0 {2} + 3 0.0% 0.1% Stub: StringAddStub {3} + 3 0.0% 0.1% Stub: RecordWriteStub {12} + 3 0.0% 0.1% Stub: RecordWriteStub {10} + 3 0.0% 0.1% Stub: JSEntryStub {1} + 3 0.0% 0.1% Stub: FastCloneShallowArrayStub + 3 0.0% 0.1% Stub: CompareStub_LT + 3 0.0% 0.1% Stub: CompareICStub {8} + 3 0.0% 0.1% Stub: ArgumentsAccessStub_NewStrict + 3 0.0% 0.1% LazyCompile: ~Buffer buffer.js:156 + 3 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:678 + 3 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:94 + 3 0.0% 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:448 + 3 0.0% 0.1% LazyCompile: *test native regexp.js:217 + 3 0.0% 0.1% LazyCompile: *VersionedData.version /Users/ematiu/devel/node/bitcore/util/VersionedData.js:21 + 3 0.0% 0.1% LazyCompile: *HistoricSync.getStandardizedTx /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:148 + 3 0.0% 0.1% LazyCompile: *Buffer.writeUInt32LE buffer.js:839 + 3 0.0% 0.1% LazyCompile: *$Array.get_ native v8natives.js:553 + 3 0.0% 0.1% KeyedLoadIC: args_count: 0 {8} + 3 0.0% 0.1% KeyedLoadIC: A keyed load IC from the snapshot {2} + 2 0.0% 0.0% Stub: ToBooleanStub_UndefinedNull + 2 0.0% 0.0% Stub: ToBooleanStub_Smi + 2 0.0% 0.0% Stub: RecordWriteStub {6} + 2 0.0% 0.0% Stub: RecordWriteStub {15} + 2 0.0% 0.0% Stub: RecordWriteStub {14} + 2 0.0% 0.0% Stub: MathPowStub + 2 0.0% 0.0% Stub: FastNewContextStub {5} + 2 0.0% 0.0% Stub: FastNewContextStub {3} + 2 0.0% 0.0% Stub: FastCloneShallowArrayStub {2} + 2 0.0% 0.0% Stub: ConstructStub + 2 0.0% 0.0% Stub: CompareICStub {7} + 2 0.0% 0.0% Stub: CompareICStub {6} + 2 0.0% 0.0% Stub: CompareICStub {2} + 2 0.0% 0.0% Stub: BinaryOpStub_SHR_Alloc_SMI + 2 0.0% 0.0% Stub: BinaryOpStub_ADD_OverwriteLeft_Strings + 2 0.0% 0.0% Stub: BinaryOpStub {1} + 2 0.0% 0.0% RegExp: ^(\\/?|)([\\s\\S]*?)((?:\\.{1\,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$ + 2 0.0% 0.0% LazyCompile: ~parseInt native v8natives.js:110 + 2 0.0% 0.0% LazyCompile: ~parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 2 0.0% 0.0% LazyCompile: ~formatValue util.js:204 + 2 0.0% 0.0% LazyCompile: ~formatArray util.js:333 + 2 0.0% 0.0% LazyCompile: ~exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 2 0.0% 0.0% LazyCompile: ~charAt native string.js:66 + 2 0.0% 0.0% LazyCompile: ~async.series.self.processReorg.height /Users/ematiu/devel/node/insight-api/lib/Sync.js:122 + 2 0.0% 0.0% LazyCompile: ~async.series.self.bDb.getNext.oldNext /Users/ematiu/devel/node/insight-api/lib/Sync.js:108 + 2 0.0% 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:161 + 2 0.0% 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:150 + 2 0.0% 0.0% LazyCompile: ~SimpleSlice native array.js:324 + 2 0.0% 0.0% LazyCompile: ~LevelUP.get /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:163 + 2 0.0% 0.0% LazyCompile: ~ArraySlice native array.js:621 + 2 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:440 + 2 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:150 + 2 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:129 + 2 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:154 + 2 0.0% 0.0% LazyCompile: defineProperty native v8natives.js:1050 + 2 0.0% 0.0% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 2 0.0% 0.0% LazyCompile: ToPrimitive native runtime.js:506 + 2 0.0% 0.0% LazyCompile: RegExpConstructor native regexp.js:86 + 2 0.0% 0.0% LazyCompile: COMPARE native runtime.js:120 + 2 0.0% 0.0% LazyCompile: *str util.js:383 + 2 0.0% 0.0% LazyCompile: *makeOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/prr/prr.js:25 + 2 0.0% 0.0% LazyCompile: *getOutpointIndex /Users/ematiu/devel/node/bitcore/lib/Transaction.js:72 + 2 0.0% 0.0% LazyCompile: *getOutpointHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:65 + 2 0.0% 0.0% LazyCompile: *async.series /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:605 + 2 0.0% 0.0% LazyCompile: *append _linklist.js:63 + 2 0.0% 0.0% LazyCompile: *IsInconsistentDescriptor native v8natives.js:367 + 2 0.0% 0.0% LazyCompile: *EncodedData.encoding /Users/ematiu/devel/node/bitcore/util/EncodedData.js:20 + 2 0.0% 0.0% LazyCompile: *BlockExtractor.getNextBlock /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:90 + 2 0.0% 0.0% LazyCompile: *BlockDb.setTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:82 + 2 0.0% 0.0% KeyedStoreIC: hash + 2 0.0% 0.0% KeyedLoadMegamorphicIC: args_count: 0 {7} + 2 0.0% 0.0% KeyedLoadIC: name + 2 0.0% 0.0% KeyedLoadIC: args_count: 0 {4} + 2 0.0% 0.0% KeyedLoadIC: args_count: 0 + 2 0.0% 0.0% CallMegamorphic: args_count: 2 + 2 0.0% 0.0% Builtin: A builtin from the snapshot {4} + 2 0.0% 0.0% Builtin: A builtin from the snapshot {13} + 1 0.0% 0.0% Stub: ToBooleanStub_SmiHeapNumber + 1 0.0% 0.0% Stub: ToBooleanStub_Null + 1 0.0% 0.0% Stub: RecordWriteStub {5} + 1 0.0% 0.0% Stub: RecordWriteStub {20} + 1 0.0% 0.0% Stub: RecordWriteStub {19} + 1 0.0% 0.0% Stub: RecordWriteStub {18} + 1 0.0% 0.0% Stub: RecordWriteStub {17} + 1 0.0% 0.0% Stub: RecordWriteStub {13} + 1 0.0% 0.0% Stub: KeyedStoreElementStub {1} + 1 0.0% 0.0% Stub: FastNewContextStub {6} + 1 0.0% 0.0% Stub: FastCloneShallowObjectStub {2} + 1 0.0% 0.0% Stub: CompareICStub {9} + 1 0.0% 0.0% Stub: CallFunctionStub_Args3 + 1 0.0% 0.0% Stub: CallFunctionStub_Args2 + 1 0.0% 0.0% Stub: CallFunctionStub_Args0 + 1 0.0% 0.0% Stub: BinaryOpStub_MUL_Alloc_SMI + 1 0.0% 0.0% Stub: BinaryOpStub_BIT_OR_Alloc_Oddball + 1 0.0% 0.0% RegExp: notfound {1} + 1 0.0% 0.0% RegExp: notfound + 1 0.0% 0.0% LazyCompile: ~tryPackage module.js:122 + 1 0.0% 0.0% LazyCompile: ~reduce native array.js:1381 + 1 0.0% 0.0% LazyCompile: ~parse native json.js:55 + 1 0.0% 0.0% LazyCompile: ~onError /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:140 + 1 0.0% 0.0% LazyCompile: ~indexOf native string.js:118 + 1 0.0% 0.0% LazyCompile: ~exports.resolve path.js:304 + 1 0.0% 0.0% LazyCompile: ~async.series.self.cachedLastHash /Users/ematiu/devel/node/insight-api/lib/Sync.js:130 + 1 0.0% 0.0% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:99 + 1 0.0% 0.0% LazyCompile: ~ToPropertyDescriptor native v8natives.js:420 + 1 0.0% 0.0% LazyCompile: ~Script.parse /Users/ematiu/devel/node/bitcore/lib/Script.js:41 + 1 0.0% 0.0% LazyCompile: ~Script.isMultiSig /Users/ematiu/devel/node/bitcore/lib/Script.js:110 + 1 0.0% 0.0% LazyCompile: ~NativeModule.compile node.js:888 + 1 0.0% 0.0% LazyCompile: ~Module._resolveFilename module.js:323 + 1 0.0% 0.0% LazyCompile: ~HistoricSync.getStandardizedTx /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:148 + 1 0.0% 0.0% LazyCompile: ~HistoricSync._fromBuffer /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:143 + 1 0.0% 0.0% LazyCompile: ~FromPropertyDescriptor native v8natives.js:373 + 1 0.0% 0.0% LazyCompile: ~Buffer.toString buffer.js:392 + 1 0.0% 0.0% LazyCompile: ~BlockDb.getTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:66 + 1 0.0% 0.0% LazyCompile: ~Block /Users/ematiu/devel/node/bitcore/lib/Block.js:20 + 1 0.0% 0.0% LazyCompile: ~Batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:13 + 1 0.0% 0.0% LazyCompile: ~BasicJSONSerialize native json.js:274 + 1 0.0% 0.0% LazyCompile: ~ArrayConcat native array.js:471 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:253 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:168 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:151 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:110 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:446 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:96 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 1 0.0% 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:84 + 1 0.0% 0.0% LazyCompile: statPath module.js:88 + 1 0.0% 0.0% LazyCompile: fs.readFileSync fs.js:271 + 1 0.0% 0.0% LazyCompile: ToBoolean native runtime.js:517 + 1 0.0% 0.0% LazyCompile: *shift _linklist.js:38 + 1 0.0% 0.0% LazyCompile: *processImmediate timers.js:320 + 1 0.0% 0.0% LazyCompile: *init /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:3 + 1 0.0% 0.0% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:194 + 1 0.0% 0.0% LazyCompile: *getCallback /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:30 + 1 0.0% 0.0% LazyCompile: *exports.dirname path.js:415 + 1 0.0% 0.0% LazyCompile: *eof /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:56 + 1 0.0% 0.0% LazyCompile: *dispatchError /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:129 + 1 0.0% 0.0% LazyCompile: *calcHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:183 + 1 0.0% 0.0% LazyCompile: *async.whilst /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:676 + 1 0.0% 0.0% LazyCompile: *Parser.varInt /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:123 + 1 0.0% 0.0% LazyCompile: *LevelUP.isOpen /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:151 + 1 0.0% 0.0% LazyCompile: *DefineOwnProperty native v8natives.js:924 + 1 0.0% 0.0% LazyCompile: *BlockExtractor.readCurrentFileSync /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:59 + 1 0.0% 0.0% LazyCompile: *BlockDb.setNext /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:153 + 1 0.0% 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:316 + 1 0.0% 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:192 + 1 0.0% 0.0% LazyCompile: * /Users/ematiu/devel/node/bitcore/lib/Transaction.js:160 + 1 0.0% 0.0% KeyedStoreIC: createIfMissing {1} + 1 0.0% 0.0% KeyedStoreIC: args_count: 0 {11} + 1 0.0% 0.0% KeyedStoreIC: args_count: 0 {10} + 1 0.0% 0.0% KeyedLoadMegamorphicIC: args_count: 0 {9} + 1 0.0% 0.0% KeyedLoadIC: log + 1 0.0% 0.0% KeyedLoadIC: info + 1 0.0% 0.0% KeyedLoadIC: errorIfExists {1} + 1 0.0% 0.0% KeyedLoadIC: cause + 1 0.0% 0.0% KeyedLoadIC: args_count: 0 {6} + 1 0.0% 0.0% KeyedLoadIC: args_count: 0 {1} + 1 0.0% 0.0% Function: /Users/ematiu/devel/node/bitcore/node_modules/bignum/index.js:1 + 1 0.0% 0.0% CallMegamorphic: args_count: 1 + 1 0.0% 0.0% Builtin: A builtin from the snapshot {8} + 1 0.0% 0.0% Builtin: A builtin from the snapshot {14} + 1 0.0% 0.0% Builtin: A builtin from the snapshot {11} + + [C++]: + ticks total nonlib name + + [GC]: + ticks total nonlib name + 880 3.6% + + [Bottom up (heavy) profile]: + Note: percentage shows a share of a particular caller in the total + amount of its parent calls. + Callers occupying less than 2.0% are not shown. + + ticks parent name + 9018 37.4% /usr/local/bin/node + 452 5.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:58 + 452 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:66 + 333 3.7% LazyCompile: *keys native v8natives.js:333 + 196 58.9% LazyCompile: formatValue util.js:204 + 183 93.4% LazyCompile: *formatProperty util.js:353 + 146 79.8% LazyCompile: * util.js:293 + 146 100.0% LazyCompile: *map native array.js:1215 + 33 18.0% LazyCompile: *formatArray util.js:333 + 33 100.0% LazyCompile: formatValue util.js:204 + 4 2.2% LazyCompile: ~formatArray util.js:333 + 4 100.0% LazyCompile: formatValue util.js:204 + 13 6.6% LazyCompile: *inspect util.js:118 + 13 100.0% LazyCompile: ~exports.format util.js:23 + 13 100.0% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 133 39.9% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 133 100.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 47 35.3% LazyCompile: Batch.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:19 + 46 97.9% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 1 2.1% LazyCompile: ~BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 38 28.6% LazyCompile: *LevelUP.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:210 + 19 50.0% LazyCompile: *BlockDb.setTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:82 + 19 50.0% LazyCompile: *BlockDb.setNext /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:153 + 34 25.6% LazyCompile: *LevelUP.get /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:163 + 34 100.0% LazyCompile: *BlockDb.has /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:175 + 11 8.3% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 11 100.0% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 260 2.9% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 113 43.5% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:151 + 113 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:345 + 45 17.3% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:162 + 45 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:154 + 45 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:238 + 43 16.5% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:157 + 43 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:84 + 43 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:238 + 19 7.3% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:94 + 19 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:177 + 19 100.0% LazyCompile: *dispatchError /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:129 + 19 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 16 6.2% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:58 + 16 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:66 + 6 2.3% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 6 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 6 100.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 250 2.8% LazyCompile: *GetOwnProperty native v8natives.js:637 + 250 100.0% LazyCompile: *getOwnPropertyDescriptor native v8natives.js:946 + 250 100.0% LazyCompile: *formatProperty util.js:353 + 230 92.0% LazyCompile: * util.js:293 + 228 99.1% LazyCompile: *map native array.js:1215 + 19 7.6% LazyCompile: *formatArray util.js:333 + 19 100.0% LazyCompile: formatValue util.js:204 + 249 2.8% LazyCompile: * util.js:196 + 248 99.6% LazyCompile: *forEach native array.js:1087 + 248 100.0% LazyCompile: *arrayToHash util.js:193 + 247 99.6% LazyCompile: formatValue util.js:204 + 209 84.6% LazyCompile: *formatProperty util.js:353 + 38 15.4% LazyCompile: *inspect util.js:118 + 225 2.5% LazyCompile: captureStackTrace native messages.js:1113 + 213 94.7% LazyCompile: native messages.js:1157 + 107 50.2% LazyCompile: native messages.js:1157 + 18 16.8% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 18 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 106 49.8% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 106 100.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 104 98.1% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 11 4.9% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 11 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 224 2.5% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 224 100.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 129 57.6% LazyCompile: Batch.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:19 + 127 98.4% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 127 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 44 19.6% LazyCompile: *LevelUP.get /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:163 + 44 100.0% LazyCompile: *BlockDb.has /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:175 + 44 100.0% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:92 + 37 16.5% LazyCompile: *LevelUP.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:210 + 21 56.8% LazyCompile: *BlockDb.setTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:82 + 21 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:155 + 16 43.2% LazyCompile: *BlockDb.setNext /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:153 + 16 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:161 + 11 4.9% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 10 90.9% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 10 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 1 9.1% LazyCompile: ~TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 1 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 220 2.4% LazyCompile: native messages.js:1157 + 205 93.2% LazyCompile: native messages.js:1157 + 15 6.8% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 15 100.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 15 100.0% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 15 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 212 2.4% LazyCompile: Join native array.js:119 + 211 99.5% LazyCompile: join native array.js:410 + 94 44.5% LazyCompile: *reduceToSingleString util.js:412 + 92 97.9% LazyCompile: formatValue util.js:204 + 71 77.2% LazyCompile: *formatProperty util.js:353 + 21 22.8% LazyCompile: *inspect util.js:118 + 2 2.1% LazyCompile: ~formatValue util.js:204 + 2 100.0% LazyCompile: *formatProperty util.js:353 + 88 41.7% LazyCompile: *formatProperty util.js:353 + 51 58.0% LazyCompile: *formatArray util.js:333 + 51 100.0% LazyCompile: formatValue util.js:204 + 35 39.8% LazyCompile: * util.js:293 + 35 100.0% LazyCompile: *map native array.js:1215 + 2 2.3% LazyCompile: ~formatArray util.js:333 + 2 100.0% LazyCompile: formatValue util.js:204 + 25 11.8% LazyCompile: ~exports.format util.js:23 + 25 100.0% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 25 100.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 210 2.3% LazyCompile: DefineOneShotAccessor native messages.js:767 + 210 100.0% LazyCompile: captureStackTrace native messages.js:1113 + 180 85.7% LazyCompile: native messages.js:1157 + 97 53.9% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 96 99.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 83 46.1% LazyCompile: native messages.js:1157 + 30 36.1% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 4 4.8% LazyCompile: *fs.statSync fs.js:682 + 2 2.4% LazyCompile: ~fs.statSync fs.js:682 + 30 14.3% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 30 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 209 2.3% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 196 93.8% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 196 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 196 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:150 + 196 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 10 4.8% LazyCompile: ~TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 10 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 10 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:150 + 10 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 209 2.3% LazyCompile: *LevelUP.get /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:163 + 209 100.0% LazyCompile: *BlockDb.has /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:175 + 209 100.0% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:92 + 209 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 209 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 189 2.1% LazyCompile: *Hash crypto.js:185 + 187 98.9% LazyCompile: *Hash crypto.js:185 + 112 59.9% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 83 74.1% LazyCompile: *parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 83 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 20 17.9% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Block.js:85 + 20 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 7 6.3% LazyCompile: *calcHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:183 + 7 100.0% LazyCompile: ~Transaction.parse /Users/ematiu/devel/node/bitcore/lib/Transaction.js:532 + 41 21.9% LazyCompile: *exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 41 100.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 41 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 29 15.5% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 29 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 29 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + + 8405 34.8% /usr/lib/system/libsystem_kernel.dylib + + 606 2.5% /usr/lib/system/libsystem_c.dylib + 38 6.3% LazyCompile: DefaultString native runtime.js:645 + 38 100.0% LazyCompile: NonStringToString native runtime.js:558 + 38 100.0% LazyCompile: *test native regexp.js:217 + 38 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 25 4.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:177 + 25 100.0% LazyCompile: *dispatchError /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:129 + 25 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 20 3.3% LazyCompile: *Hash.digest crypto.js:214 + 12 60.0% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 10 83.3% LazyCompile: *parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 10 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 10 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 1 8.3% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Block.js:85 + 1 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 1 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 1 8.3% LazyCompile: *calcHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:183 + 1 100.0% LazyCompile: ~Transaction.parse /Users/ematiu/devel/node/bitcore/lib/Transaction.js:532 + 1 100.0% LazyCompile: ~parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 5 25.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 5 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 5 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 5 100.0% LazyCompile: *map native array.js:1215 + 3 15.0% LazyCompile: *exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 3 100.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 3 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 3 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 15 2.5% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 15 100.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 12 80.0% LazyCompile: Batch.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:19 + 12 100.0% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 12 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 2 13.3% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 2 100.0% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 2 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 1 6.7% LazyCompile: *LevelUP.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:210 + 1 100.0% LazyCompile: *BlockDb.setTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:82 + 1 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:155 + + 509 2.1% /usr/lib/system/libsystem_malloc.dylib + 98 19.3% LazyCompile: *toString native v8natives.js:1378 + 98 100.0% LazyCompile: *inspect buffer.js:283 + 98 100.0% LazyCompile: formatValue util.js:204 + 98 100.0% LazyCompile: *formatProperty util.js:353 + 98 100.0% LazyCompile: * util.js:293 + 73 14.3% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 45 61.6% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:151 + 45 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:345 + 14 19.2% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:162 + 14 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:154 + 14 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:238 + 6 8.2% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:58 + 6 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:66 + 5 6.8% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:157 + 5 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:84 + 5 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:238 + 3 4.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:94 + 3 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:177 + 3 100.0% LazyCompile: *dispatchError /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:129 + 3 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 43 8.4% LazyCompile: Batch.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:19 + 41 95.3% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 41 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 41 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 41 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 2 4.7% LazyCompile: ~BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 2 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 2 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 2 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 35 6.9% LazyCompile: captureStackTrace native messages.js:1113 + 35 100.0% LazyCompile: native messages.js:1157 + 25 71.4% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 25 100.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 25 100.0% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 10 28.6% LazyCompile: native messages.js:1157 + 9 90.0% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 9 100.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 1 10.0% LazyCompile: *fs.statSync fs.js:682 + 1 100.0% LazyCompile: statPath module.js:88 + 34 6.7% LazyCompile: *Hash.digest crypto.js:214 + 19 55.9% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 10 52.6% LazyCompile: *parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 10 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 10 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 7 36.8% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Block.js:85 + 7 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 7 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 1 5.3% LazyCompile: ~parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 1 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 1 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 1 5.3% LazyCompile: *calcHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:183 + 1 100.0% LazyCompile: ~Transaction.parse /Users/ematiu/devel/node/bitcore/lib/Transaction.js:532 + 1 100.0% LazyCompile: ~parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 7 20.6% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 7 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 7 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 7 100.0% LazyCompile: *map native array.js:1215 + 7 20.6% LazyCompile: *exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 7 100.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 7 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 7 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 1 2.9% LazyCompile: ~exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 1 100.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 1 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 1 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 33 6.5% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 30 90.9% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 30 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 30 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:150 + 30 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 3 9.1% LazyCompile: ~TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 3 100.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 3 100.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:150 + 3 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 23 4.5% LazyCompile: *Buffer.toString buffer.js:392 + 19 82.6% LazyCompile: *HistoricSync._fromBuffer /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:143 + 19 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 19 100.0% LazyCompile: *map native array.js:1215 + 19 100.0% LazyCompile: *HistoricSync.getStandardizedTx /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:148 + 4 17.4% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:152 + 4 100.0% LazyCompile: *map native array.js:1215 + 4 100.0% LazyCompile: *HistoricSync.getStandardizedTx /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:148 + 4 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:192 + 22 4.3% LazyCompile: *Buffer.write buffer.js:315 + 12 54.5% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 8 66.7% LazyCompile: *parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 8 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 8 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 3 25.0% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Block.js:85 + 3 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 3 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 1 8.3% LazyCompile: ~parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 1 100.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 1 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6 27.3% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 6 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 6 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 6 100.0% LazyCompile: *map native array.js:1215 + 4 18.2% LazyCompile: *exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 4 100.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 4 100.0% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 4 100.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + + + [Top down (heavy) profile]: + Note: callees occupying less than 0.1% are not shown. + + inclusive self name + ticks total ticks total + 7965 33.0% 7965 33.0% /usr/lib/system/libsystem_kernel.dylib + + 7124 29.5% 5 0.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:189 + 6450 26.7% 1 0.0% LazyCompile: *dispatchError /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:129 + 6445 26.7% 4 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:177 + 6306 26.1% 3 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:94 + 6301 26.1% 5 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 6262 25.9% 3 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 6258 25.9% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 6255 25.9% 1 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 6251 25.9% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 6250 25.9% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6248 25.9% 1 0.0% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:99 + 6243 25.9% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 6238 25.8% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 6236 25.8% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 6235 25.8% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 6234 25.8% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 6233 25.8% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6230 25.8% 2 0.0% LazyCompile: ~async.series.self.bDb.getNext.oldNext /Users/ematiu/devel/node/insight-api/lib/Sync.js:108 + 6223 25.8% 4 0.0% LazyCompile: *BlockDb.getTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:66 + 6159 25.5% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:110 + 6150 25.5% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 6145 25.5% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 6145 25.5% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 6143 25.4% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 6143 25.4% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 6141 25.4% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6135 25.4% 2 0.0% LazyCompile: ~async.series.self.processReorg.height /Users/ematiu/devel/node/insight-api/lib/Sync.js:122 + 6131 25.4% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 6128 25.4% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 6127 25.4% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 6127 25.4% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 6127 25.4% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 6120 25.4% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6119 25.3% 1 0.0% LazyCompile: ~async.series.self.cachedLastHash /Users/ematiu/devel/node/insight-api/lib/Sync.js:130 + 6115 25.3% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 6112 25.3% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 6089 25.2% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 6087 25.2% 1 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 6085 25.2% 3 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 6082 25.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 6079 25.2% 8 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 5986 24.8% 20 0.1% LazyCompile: *BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 5212 21.6% 4 0.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 5205 21.6% 18 0.1% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 4869 20.2% 9 0.0% LazyCompile: ~exports.format util.js:23 + 4809 19.9% 14 0.1% LazyCompile: *inspect util.js:118 + 4776 19.8% 23 0.1% LazyCompile: formatValue util.js:204 + 4479 18.6% 9 0.0% LazyCompile: *map native array.js:1215 + 4449 18.4% 2 0.0% LazyCompile: * util.js:293 + 4445 18.4% 27 0.1% LazyCompile: *formatProperty util.js:353 + 3938 16.3% 18 0.1% LazyCompile: formatValue util.js:204 + 3214 13.3% 12 0.0% LazyCompile: *formatArray util.js:333 + 3125 12.9% 12 0.0% LazyCompile: *formatProperty util.js:353 + 2828 11.7% 15 0.1% LazyCompile: formatValue util.js:204 + 2342 9.7% 24 0.1% LazyCompile: *map native array.js:1215 + 2248 9.3% 10 0.0% LazyCompile: * util.js:293 + 2232 9.2% 70 0.3% LazyCompile: *formatProperty util.js:353 + 1268 5.3% 70 0.3% LazyCompile: formatValue util.js:204 + 558 2.3% 63 0.3% LazyCompile: *inspect buffer.js:283 + 318 1.3% 23 0.1% LazyCompile: *toString native v8natives.js:1378 + 114 0.5% 114 0.5% /usr/local/bin/node + 86 0.4% 86 0.4% /usr/lib/system/libsystem_malloc.dylib + 35 0.1% 35 0.1% /usr/lib/system/libsystem_m.dylib + 33 0.1% 33 0.1% /usr/lib/system/libsystem_platform.dylib + 95 0.4% 95 0.4% /usr/local/bin/node + 29 0.1% 25 0.1% LazyCompile: join native array.js:410 + 27 0.1% 27 0.1% Stub: KeyedStoreElementStub + 149 0.6% 8 0.0% LazyCompile: *arrayToHash util.js:193 + 131 0.5% 11 0.0% LazyCompile: *forEach native array.js:1087 + 62 0.3% 3 0.0% LazyCompile: * util.js:196 + 56 0.2% 56 0.2% /usr/local/bin/node + 145 0.6% 5 0.0% LazyCompile: *formatPrimitive util.js:304 + 62 0.3% 4 0.0% LazyCompile: STRING_ADD_LEFT native runtime.js:183 + 33 0.1% 33 0.1% /usr/local/bin/node + 41 0.2% 2 0.0% LazyCompile: *replace native string.js:221 + 32 0.1% 32 0.1% /usr/local/bin/node + 119 0.5% 2 0.0% LazyCompile: *keys native v8natives.js:333 + 114 0.5% 114 0.5% /usr/local/bin/node + 56 0.2% 56 0.2% /usr/local/bin/node + 42 0.2% 5 0.0% LazyCompile: *isRegExp util.js:442 + 40 0.2% 7 0.0% LazyCompile: *isError util.js:454 + 445 1.8% 20 0.1% LazyCompile: *getOwnPropertyDescriptor native v8natives.js:946 + 348 1.4% 15 0.1% LazyCompile: *GetOwnProperty native v8natives.js:637 + 168 0.7% 168 0.7% /usr/local/bin/node + 129 0.5% 53 0.2% LazyCompile: *ConvertDescriptorArrayToDescriptor native v8natives.js:581 + 76 0.3% 41 0.2% LazyCompile: *FromPropertyDescriptor native v8natives.js:373 + 124 0.5% 27 0.1% LazyCompile: stringify native json.js:308 + 74 0.3% 14 0.1% LazyCompile: *BasicJSONSerialize native json.js:274 + 57 0.2% 57 0.2% /usr/local/bin/node + 103 0.4% 6 0.0% LazyCompile: *match native string.js:182 + 96 0.4% 4 0.0% LazyCompile: *RegExpExecNoTests native regexp.js:157 + 50 0.2% 21 0.1% LazyCompile: *BuildResultFromMatchInfo native regexp.js:130 + 64 0.3% 7 0.0% LazyCompile: *indexOf native string.js:118 + 50 0.2% 50 0.2% /usr/local/bin/node + 46 0.2% 9 0.0% LazyCompile: hasOwnProperty native v8natives.js:249 + 36 0.1% 36 0.1% /usr/local/bin/node + 30 0.1% 15 0.1% LazyCompile: *indexOf native array.js:1261 + 29 0.1% 29 0.1% /usr/local/bin/node + 25 0.1% 4 0.0% LazyCompile: IN native runtime.js:354 + 204 0.8% 3 0.0% LazyCompile: *reduceToSingleString util.js:412 + 96 0.4% 12 0.0% LazyCompile: *reduce native array.js:1381 + 48 0.2% 8 0.0% LazyCompile: * util.js:414 + 40 0.2% 1 0.0% LazyCompile: *indexOf native string.js:118 + 34 0.1% 34 0.1% /usr/local/bin/node + 95 0.4% 3 0.0% LazyCompile: join native array.js:410 + 92 0.4% 20 0.1% LazyCompile: Join native array.js:119 + 59 0.2% 59 0.2% /usr/local/bin/node + 159 0.7% 0 0.0% LazyCompile: *arrayToHash util.js:193 + 156 0.6% 5 0.0% LazyCompile: *forEach native array.js:1087 + 121 0.5% 1 0.0% LazyCompile: * util.js:196 + 116 0.5% 116 0.5% /usr/local/bin/node + 35 0.1% 0 0.0% LazyCompile: *keys native v8natives.js:333 + 33 0.1% 33 0.1% /usr/local/bin/node + 70 0.3% 2 0.0% LazyCompile: join native array.js:410 + 65 0.3% 6 0.0% LazyCompile: Join native array.js:119 + 51 0.2% 51 0.2% /usr/local/bin/node + 51 0.2% 6 0.0% LazyCompile: *split native string.js:554 + 45 0.2% 45 0.2% /usr/local/bin/node + 48 0.2% 1 0.0% LazyCompile: *getOwnPropertyDescriptor native v8natives.js:946 + 42 0.2% 6 0.0% LazyCompile: *GetOwnProperty native v8natives.js:637 + 46 0.2% 9 0.0% LazyCompile: *map native array.js:1215 + 332 1.4% 2 0.0% LazyCompile: ~formatArray util.js:333 + 321 1.3% 0 0.0% LazyCompile: *formatProperty util.js:353 + 287 1.2% 0 0.0% LazyCompile: formatValue util.js:204 + 239 1.0% 0 0.0% LazyCompile: *map native array.js:1215 + 230 1.0% 2 0.0% LazyCompile: * util.js:293 + 226 0.9% 7 0.0% LazyCompile: *formatProperty util.js:353 + 123 0.5% 4 0.0% LazyCompile: formatValue util.js:204 + 52 0.2% 2 0.0% LazyCompile: *inspect buffer.js:283 + 28 0.1% 1 0.0% LazyCompile: *toString native v8natives.js:1378 + 37 0.2% 0 0.0% LazyCompile: *getOwnPropertyDescriptor native v8natives.js:946 + 31 0.1% 3 0.0% LazyCompile: *GetOwnProperty native v8natives.js:637 + 200 0.8% 15 0.1% LazyCompile: *formatPrimitive util.js:304 + 95 0.4% 10 0.0% LazyCompile: *replace native string.js:221 + 69 0.3% 69 0.3% /usr/local/bin/node + 43 0.2% 9 0.0% LazyCompile: stringify native json.js:308 + 29 0.1% 6 0.0% LazyCompile: *BasicJSONSerialize native json.js:274 + 30 0.1% 3 0.0% LazyCompile: STRING_ADD_LEFT native runtime.js:183 + 44 0.2% 44 0.2% /usr/local/bin/node + 41 0.2% 4 0.0% LazyCompile: *reduceToSingleString util.js:412 + 31 0.1% 0 0.0% LazyCompile: *arrayToHash util.js:193 + 28 0.1% 0 0.0% LazyCompile: *forEach native array.js:1087 + 142 0.6% 6 0.0% LazyCompile: *getOwnPropertyDescriptor native v8natives.js:946 + 115 0.5% 4 0.0% LazyCompile: *GetOwnProperty native v8natives.js:637 + 54 0.2% 18 0.1% LazyCompile: *ConvertDescriptorArrayToDescriptor native v8natives.js:581 + 47 0.2% 47 0.2% /usr/local/bin/node + 60 0.2% 9 0.0% LazyCompile: *map native array.js:1215 + 25 0.1% 25 0.1% /usr/local/bin/node + 50 0.2% 4 0.0% LazyCompile: *split native string.js:554 + 45 0.2% 45 0.2% /usr/local/bin/node + 49 0.2% 7 0.0% LazyCompile: *match native string.js:182 + 42 0.2% 1 0.0% LazyCompile: *RegExpExecNoTests native regexp.js:157 + 46 0.2% 3 0.0% LazyCompile: join native array.js:410 + 42 0.2% 2 0.0% LazyCompile: Join native array.js:119 + 35 0.1% 35 0.1% /usr/local/bin/node + 45 0.2% 3 0.0% LazyCompile: *indexOf native string.js:118 + 33 0.1% 33 0.1% /usr/local/bin/node + 33 0.1% 6 0.0% LazyCompile: stringify native json.js:308 + 94 0.4% 0 0.0% LazyCompile: *reduceToSingleString util.js:412 + 55 0.2% 5 0.0% LazyCompile: *reduce native array.js:1381 + 37 0.2% 1 0.0% LazyCompile: * util.js:414 + 36 0.1% 0 0.0% LazyCompile: *indexOf native string.js:118 + 27 0.1% 27 0.1% /usr/local/bin/node + 36 0.1% 5 0.0% LazyCompile: join native array.js:410 + 31 0.1% 3 0.0% LazyCompile: Join native array.js:119 + 75 0.3% 2 0.0% LazyCompile: *arrayToHash util.js:193 + 68 0.3% 3 0.0% LazyCompile: *forEach native array.js:1087 + 52 0.2% 2 0.0% LazyCompile: * util.js:196 + 38 0.2% 38 0.2% /usr/local/bin/node + 41 0.2% 1 0.0% LazyCompile: join native array.js:410 + 39 0.2% 2 0.0% LazyCompile: Join native array.js:119 + 259 1.1% 2 0.0% LazyCompile: native messages.js:1157 + 239 1.0% 2 0.0% LazyCompile: captureStackTrace native messages.js:1113 + 104 0.4% 104 0.4% /usr/local/bin/node + 98 0.4% 1 0.0% LazyCompile: DefineOneShotAccessor native messages.js:767 + 94 0.4% 94 0.4% /usr/local/bin/node + 25 0.1% 25 0.1% /usr/lib/system/libsystem_malloc.dylib + 29 0.1% 29 0.1% /usr/local/bin/node + 439 1.8% 35 0.1% LazyCompile: Batch.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:19 + 242 1.0% 6 0.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 230 1.0% 5 0.0% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 127 0.5% 127 0.5% /usr/local/bin/node + 48 0.2% 2 0.0% LazyCompile: *keys native v8natives.js:333 + 46 0.2% 46 0.2% /usr/local/bin/node + 50 0.2% 50 0.2% /usr/local/bin/node + 41 0.2% 41 0.2% /usr/lib/system/libsystem_malloc.dylib + 176 0.7% 4 0.0% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 155 0.6% 92 0.4% LazyCompile: *Batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:13 + 55 0.2% 55 0.2% /usr/local/bin/node + 63 0.3% 63 0.3% /usr/local/bin/node + 56 0.2% 56 0.2% /usr/lib/system/libsystem_kernel.dylib + 83 0.3% 0 0.0% LazyCompile: ~BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 65 0.3% 0 0.0% LazyCompile: *winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 65 0.3% 0 0.0% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 60 0.2% 1 0.0% LazyCompile: ~exports.format util.js:23 + 51 0.2% 0 0.0% LazyCompile: ~inspect util.js:118 + 42 0.2% 0 0.0% LazyCompile: ~formatValue util.js:204 + 38 0.2% 0 0.0% LazyCompile: *map native array.js:1215 + 38 0.2% 0 0.0% LazyCompile: * util.js:293 + 38 0.2% 0 0.0% LazyCompile: *formatProperty util.js:353 + 28 0.1% 1 0.0% LazyCompile: ~formatValue util.js:204 + 43 0.2% 12 0.0% LazyCompile: *split native string.js:554 + 30 0.1% 30 0.1% /usr/local/bin/node + 48 0.2% 48 0.2% /usr/local/bin/node + 48 0.2% 48 0.2% /usr/lib/system/libsystem_kernel.dylib + 25 0.1% 25 0.1% /usr/lib/system/libsystem_c.dylib + 303 1.3% 3 0.0% LazyCompile: *test native regexp.js:217 + 290 1.2% 3 0.0% LazyCompile: NonStringToString native runtime.js:558 + 280 1.2% 5 0.0% LazyCompile: DefaultString native runtime.js:645 + 114 0.5% 114 0.5% /usr/lib/system/libsystem_kernel.dylib + 56 0.2% 56 0.2% /usr/local/bin/node + 55 0.2% 7 0.0% LazyCompile: toString native messages.js:1248 + 48 0.2% 5 0.0% LazyCompile: ErrorToStringDetectCycle native messages.js:1227 + 27 0.1% 6 0.0% LazyCompile: ~GetPropertyWithoutInvokingMonkeyGetters native messages.js:1203 + 38 0.2% 38 0.2% /usr/lib/system/libsystem_c.dylib + 273 1.1% 4 0.0% LazyCompile: ~err /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:25 + 144 0.6% 1 0.0% LazyCompile: *init /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/errno/custom.js:3 + 143 0.6% 11 0.0% LazyCompile: ~prr /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/prr/prr.js:44 + 109 0.5% 0 0.0% LazyCompile: *Object.defineProperty.function.obj.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/prr/prr.js:16 + 105 0.4% 2 0.0% LazyCompile: defineProperty native v8natives.js:1050 + 63 0.3% 13 0.1% LazyCompile: *ToPropertyDescriptor native v8natives.js:420 + 39 0.2% 1 0.0% LazyCompile: *DefineOwnProperty native v8natives.js:924 + 38 0.2% 13 0.1% LazyCompile: *DefineObjectProperty native v8natives.js:695 + 66 0.3% 0 0.0% LazyCompile: native messages.js:1157 + 66 0.3% 0 0.0% LazyCompile: native messages.js:1157 + 64 0.3% 0 0.0% LazyCompile: captureStackTrace native messages.js:1113 + 35 0.1% 2 0.0% LazyCompile: DefineOneShotAccessor native messages.js:767 + 30 0.1% 30 0.1% /usr/local/bin/node + 43 0.2% 0 0.0% LazyCompile: captureStackTrace native messages.js:1113 + 32 0.1% 0 0.0% LazyCompile: DefineOneShotAccessor native messages.js:767 + 30 0.1% 30 0.1% /usr/local/bin/node + 67 0.3% 0 0.0% LazyCompile: ~dispatchError /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:129 + 51 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:177 + 48 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:94 + 48 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 47 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 47 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 41 0.2% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 41 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 41 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 41 0.2% 0 0.0% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:99 + 41 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 41 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 41 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 41 0.2% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 41 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 41 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 41 0.2% 0 0.0% LazyCompile: ~async.series.self.bDb.getNext.oldNext /Users/ematiu/devel/node/insight-api/lib/Sync.js:108 + 41 0.2% 0 0.0% LazyCompile: ~BlockDb.getTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:66 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:110 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 40 0.2% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 40 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 40 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 40 0.2% 0 0.0% LazyCompile: ~async.series.self.processReorg.height /Users/ematiu/devel/node/insight-api/lib/Sync.js:122 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 40 0.2% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 40 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 40 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 40 0.2% 0 0.0% LazyCompile: ~async.series.self.cachedLastHash /Users/ematiu/devel/node/insight-api/lib/Sync.js:130 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 40 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 40 0.2% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 40 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 40 0.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 40 0.2% 0 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:146 + 40 0.2% 0 0.0% LazyCompile: ~BlockDb.add /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:48 + 34 0.1% 0 0.0% LazyCompile: ~winston.(anonymous function) /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston.js:84 + 34 0.1% 0 0.0% LazyCompile: ~Logger.log /Users/ematiu/devel/node/insight-api/node_modules/winston/lib/winston/logger.js:123 + 33 0.1% 0 0.0% LazyCompile: ~exports.format util.js:23 + 33 0.1% 0 0.0% LazyCompile: ~inspect util.js:118 + 29 0.1% 0 0.0% LazyCompile: ~formatValue util.js:204 + 27 0.1% 0 0.0% LazyCompile: ~map native array.js:1215 + 27 0.1% 0 0.0% LazyCompile: * util.js:293 + + 3215 13.3% 1 0.0% LazyCompile: *processImmediate timers.js:320 + 3213 13.3% 3 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:448 + 3210 13.3% 3 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:678 + 3207 13.3% 0 0.0% LazyCompile: *async.whilst /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:676 + 3202 13.3% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:439 + 3202 13.3% 0 0.0% LazyCompile: *HistoricSync.getBlockFromFile /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:198 + 3200 13.3% 2 0.0% LazyCompile: *BlockExtractor.getNextBlock /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:90 + 3198 13.2% 0 0.0% LazyCompile: *async.series /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:605 + 3196 13.2% 2 0.0% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:229 + 3161 13.1% 1 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 3160 13.1% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 3158 13.1% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 3157 13.1% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:96 + 3155 13.1% 1 0.0% LazyCompile: *async.whilst /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:676 + 3152 13.1% 4 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:102 + 3106 12.9% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:678 + 3106 12.9% 0 0.0% LazyCompile: *async.whilst /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:676 + 3104 12.9% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 3097 12.8% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 3097 12.8% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 3097 12.8% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 3097 12.8% 2 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 3095 12.8% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 3094 12.8% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:129 + 3080 12.8% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 3078 12.8% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 3075 12.7% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 3075 12.7% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 3075 12.7% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 3075 12.7% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 3074 12.7% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:142 + 2130 8.8% 3 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 2117 8.8% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 2114 8.8% 4 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 2109 8.7% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:253 + 2106 8.7% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:150 + 2102 8.7% 11 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:204 + 1388 5.7% 5 0.0% LazyCompile: *HistoricSync.getStandardizedBlock /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:184 + 1317 5.5% 6 0.0% LazyCompile: *map native array.js:1215 + 1272 5.3% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:192 + 1270 5.3% 3 0.0% LazyCompile: *HistoricSync.getStandardizedTx /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:148 + 1178 4.9% 10 0.0% LazyCompile: *map native array.js:1215 + 975 4.0% 13 0.1% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:164 + 711 2.9% 17 0.1% LazyCompile: ~Address.fromScriptPubKey /Users/ematiu/devel/node/bitcore/lib/Address.js:97 + 352 1.5% 7 0.0% LazyCompile: *exports.sha256ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:54 + 166 0.7% 6 0.0% LazyCompile: *exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 50 0.2% 0 0.0% LazyCompile: *Hash crypto.js:185 + 50 0.2% 2 0.0% LazyCompile: *Hash crypto.js:185 + 41 0.2% 41 0.2% /usr/local/bin/node + 45 0.2% 1 0.0% LazyCompile: *Hash.digest crypto.js:214 + 32 0.1% 32 0.1% /usr/local/bin/node + 37 0.2% 3 0.0% LazyCompile: *Buffer.write buffer.js:315 + 47 0.2% 7 0.0% LazyCompile: *Buffer.write buffer.js:315 + 41 0.2% 0 0.0% LazyCompile: *Hash crypto.js:185 + 36 0.1% 4 0.0% LazyCompile: *Hash crypto.js:185 + 29 0.1% 29 0.1% /usr/local/bin/node + 34 0.1% 0 0.0% LazyCompile: *Hash.digest crypto.js:214 + 26 0.1% 1 0.0% LazyCompile: ~exports.ripe160 /Users/ematiu/devel/node/bitcore/util/util.js:29 + 222 0.9% 6 0.0% LazyCompile: Address /Users/ematiu/devel/node/bitcore/lib/Address.js:39 + 211 0.9% 5 0.0% LazyCompile: *constructor.super /Users/ematiu/devel/node/bitcore/node_modules/soop/soop.js:22 + 171 0.7% 13 0.1% LazyCompile: VersionedData /Users/ematiu/devel/node/bitcore/util/VersionedData.js:6 + 68 0.3% 68 0.3% /usr/local/bin/node + 46 0.2% 4 0.0% LazyCompile: *VersionedData.payload /Users/ematiu/devel/node/bitcore/util/VersionedData.js:30 + 37 0.2% 2 0.0% LazyCompile: *EncodedData.doAsBinary /Users/ematiu/devel/node/bitcore/util/EncodedData.js:75 + 30 0.1% 5 0.0% LazyCompile: ~ /Users/ematiu/devel/node/bitcore/util/VersionedData.js:32 + 25 0.1% 6 0.0% LazyCompile: *Buffer.copy buffer.js:509 + 28 0.1% 2 0.0% LazyCompile: *VersionedData.version /Users/ematiu/devel/node/bitcore/util/VersionedData.js:21 + 49 0.2% 49 0.2% /usr/local/bin/node + 42 0.2% 16 0.1% LazyCompile: ~Script.capture /Users/ematiu/devel/node/bitcore/lib/Script.js:235 + 122 0.5% 10 0.0% LazyCompile: *HistoricSync._fromBuffer /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:143 + 64 0.3% 5 0.0% LazyCompile: *Buffer.toString buffer.js:392 + 117 0.5% 16 0.1% LazyCompile: *Script /Users/ematiu/devel/node/bitcore/lib/Script.js:25 + 66 0.3% 3 0.0% LazyCompile: * /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:97 + 60 0.2% 0 0.0% LazyCompile: *buffer /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:12 + 60 0.2% 8 0.0% LazyCompile: *Buffer.slice buffer.js:539 + 31 0.1% 31 0.1% /usr/local/bin/node + 126 0.5% 7 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:152 + 53 0.2% 23 0.1% LazyCompile: *isCoinBase /Users/ematiu/devel/node/bitcore/lib/Transaction.js:49 + 27 0.1% 2 0.0% LazyCompile: *Buffer.toString buffer.js:392 + 48 0.2% 48 0.2% /usr/local/bin/node + 62 0.3% 6 0.0% LazyCompile: *exports.formatHashFull /Users/ematiu/devel/node/bitcore/util/util.js:70 + 25 0.1% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:192 + 50 0.2% 7 0.0% LazyCompile: *exports.formatHashFull /Users/ematiu/devel/node/bitcore/util/util.js:70 + 694 2.9% 1 0.0% LazyCompile: *BlockDb.setLastFileIndex /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:112 + 690 2.9% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:207 + 690 2.9% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:440 + 666 2.8% 5 0.0% LazyCompile: *Sync.storeTipBlock /Users/ematiu/devel/node/insight-api/lib/Sync.js:79 + 626 2.6% 1 0.0% LazyCompile: *async.series /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:605 + 620 2.6% 17 0.1% LazyCompile: /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:229 + 510 2.1% 4 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 506 2.1% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 504 2.1% 2 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 499 2.1% 4 0.0% LazyCompile: ~async.series.self.bDb.getTip.oldTip /Users/ematiu/devel/node/insight-api/lib/Sync.js:92 + 492 2.0% 10 0.0% LazyCompile: *BlockDb.has /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:175 + 477 2.0% 28 0.1% LazyCompile: *LevelUP.get /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:163 + 209 0.9% 209 0.9% /usr/local/bin/node + 100 0.4% 3 0.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 95 0.4% 3 0.0% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 44 0.2% 44 0.2% /usr/local/bin/node + 35 0.1% 0 0.0% LazyCompile: *keys native v8natives.js:333 + 34 0.1% 34 0.1% /usr/local/bin/node + 78 0.3% 78 0.3% /usr/lib/system/libsystem_kernel.dylib + 55 0.2% 2 0.0% LazyCompile: *_map /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:53 + 52 0.2% 9 0.0% LazyCompile: *map native array.js:1215 + 27 0.1% 27 0.1% /usr/local/bin/node + 31 0.1% 31 0.1% /usr/local/bin/node + 715 3.0% 17 0.1% LazyCompile: *parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 372 1.5% 7 0.0% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 119 0.5% 0 0.0% LazyCompile: *Hash crypto.js:185 + 110 0.5% 7 0.0% LazyCompile: *Hash crypto.js:185 + 83 0.3% 83 0.3% /usr/local/bin/node + 84 0.3% 5 0.0% LazyCompile: *Buffer.write buffer.js:315 + 44 0.2% 44 0.2% /usr/local/bin/node + 67 0.3% 2 0.0% LazyCompile: *Hash.digest crypto.js:214 + 38 0.2% 38 0.2% /usr/local/bin/node + 51 0.2% 6 0.0% LazyCompile: *Hash.update crypto.js:205 + 42 0.2% 42 0.2% /usr/local/bin/node + 197 0.8% 8 0.0% LazyCompile: *serialize /Users/ematiu/devel/node/bitcore/lib/Transaction.js:152 + 126 0.5% 8 0.0% LazyCompile: *forEach native array.js:1087 + 63 0.3% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/bitcore/lib/Transaction.js:160 + 62 0.3% 5 0.0% LazyCompile: *serialize /Users/ematiu/devel/node/bitcore/lib/Transaction.js:56 + 38 0.2% 5 0.0% LazyCompile: *Buffer.concat buffer.js:476 + 43 0.2% 0 0.0% LazyCompile: *serialize /Users/ematiu/devel/node/bitcore/lib/Transaction.js:103 + 26 0.1% 5 0.0% LazyCompile: *Buffer.concat buffer.js:476 + 27 0.1% 2 0.0% LazyCompile: *Buffer.concat buffer.js:476 + 45 0.2% 2 0.0% LazyCompile: *buffer /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:12 + 43 0.2% 8 0.0% LazyCompile: *Buffer.slice buffer.js:539 + 36 0.1% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:97 + 28 0.1% 1 0.0% LazyCompile: *buffer /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:12 + 27 0.1% 4 0.0% LazyCompile: *Buffer.slice buffer.js:539 + 26 0.1% 1 0.0% LazyCompile: *Parser.varInt /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:123 + 25 0.1% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/bitcore/util/BinaryParser.js:97 + 137 0.6% 5 0.0% LazyCompile: *getHash /Users/ematiu/devel/node/bitcore/lib/Block.js:85 + 119 0.5% 5 0.0% LazyCompile: *exports.twoSha256 /Users/ematiu/devel/node/bitcore/util/util.js:50 + 29 0.1% 1 0.0% LazyCompile: *Hash.digest crypto.js:214 + 26 0.1% 5 0.0% LazyCompile: *Buffer.write buffer.js:315 + 78 0.3% 2 0.0% LazyCompile: ~parse /Users/ematiu/devel/node/bitcore/lib/Block.js:51 + 55 0.2% 0 0.0% LazyCompile: ~Transaction.parse /Users/ematiu/devel/node/bitcore/lib/Transaction.js:532 + 46 0.2% 1 0.0% LazyCompile: *calcHash /Users/ematiu/devel/node/bitcore/lib/Transaction.js:183 + 25 0.1% 0 0.0% LazyCompile: *serialize /Users/ematiu/devel/node/bitcore/lib/Transaction.js:152 + + 1930 8.0% 1930 8.0% /usr/local/bin/node + + 1282 5.3% 15 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/batch.js:66 + 1098 4.5% 23 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:58 + 596 2.5% 7 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 546 2.3% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 543 2.2% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 540 2.2% 0 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 539 2.2% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 538 2.2% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 537 2.2% 2 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:150 + 532 2.2% 5 0.0% LazyCompile: *TransactionDb.createFromBlock /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:582 + 491 2.0% 2 0.0% LazyCompile: TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 371 1.5% 25 0.1% LazyCompile: ~LevelUP.batch /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:285 + 196 0.8% 196 0.8% /usr/local/bin/node + 31 0.1% 1 0.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 30 0.1% 2 0.0% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 30 0.1% 30 0.1% /usr/lib/system/libsystem_malloc.dylib + 54 0.2% 6 0.0% LazyCompile: TransactionDb._addScript /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:462 + 44 0.2% 44 0.2% /usr/local/bin/node + 29 0.1% 0 0.0% LazyCompile: ~TransactionDb.createFromObjs /Users/ematiu/devel/node/insight-api/lib/TransactionDb.js:552 + 452 1.9% 452 1.9% /usr/local/bin/node + 64 0.3% 64 0.3% /usr/local/bin/node + 40 0.2% 8 0.0% LazyCompile: ~EventEmitter.emit events.js:53 + 26 0.1% 26 0.1% /usr/local/bin/node + + 514 2.1% 37 0.2% LazyCompile: native messages.js:1157 + 429 1.8% 25 0.1% LazyCompile: native messages.js:1157 + 204 0.8% 204 0.8% /usr/local/bin/node + 173 0.7% 19 0.1% LazyCompile: captureStackTrace native messages.js:1113 + 87 0.4% 87 0.4% /usr/local/bin/node + 48 0.2% 1 0.0% LazyCompile: DefineOneShotAccessor native messages.js:767 + 46 0.2% 46 0.2% /usr/local/bin/node + + 478 2.0% 9 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:345 + 444 1.8% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:151 + 440 1.8% 16 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 175 0.7% 6 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 168 0.7% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 165 0.7% 1 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 162 0.7% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 160 0.7% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 160 0.7% 8 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:155 + 146 0.6% 2 0.0% LazyCompile: *BlockDb.setTip /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:82 + 138 0.6% 17 0.1% LazyCompile: *LevelUP.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:210 + 56 0.2% 3 0.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 51 0.2% 2 0.0% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 32 0.1% 32 0.1% /usr/local/bin/node + 113 0.5% 113 0.5% /usr/local/bin/node + 45 0.2% 45 0.2% /usr/lib/system/libsystem_malloc.dylib + 31 0.1% 31 0.1% /usr/lib/libc++abi.dylib + + 475 2.0% 18 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:238 + 217 0.9% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:84 + 213 0.9% 5 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:157 + 203 0.8% 19 0.1% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 115 0.5% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 113 0.5% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 112 0.5% 1 0.0% LazyCompile: *iterate /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:148 + 111 0.5% 0 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:248 + 111 0.5% 1 0.0% LazyCompile: * /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:608 + 108 0.4% 2 0.0% LazyCompile: ~async.series.err /Users/ematiu/devel/node/insight-api/lib/Sync.js:161 + 101 0.4% 1 0.0% LazyCompile: *BlockDb.setNext /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:153 + 99 0.4% 6 0.0% LazyCompile: *LevelUP.put /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:210 + 46 0.2% 1 0.0% LazyCompile: *getOptions /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/util.js:87 + 44 0.2% 3 0.0% LazyCompile: *extend /Users/ematiu/devel/node/insight-api/node_modules/levelup/node_modules/xtend/index.js:6 + 25 0.1% 25 0.1% /usr/local/bin/node + 43 0.2% 43 0.2% /usr/local/bin/node + 162 0.7% 2 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:154 + 156 0.6% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:162 + 155 0.6% 12 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:610 + 66 0.3% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:249 + 65 0.3% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:149 + 63 0.3% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:253 + 60 0.2% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:168 + 57 0.2% 1 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:446 + 54 0.2% 5 0.0% LazyCompile: *global.setImmediate node.js:192 + 46 0.2% 11 0.0% LazyCompile: ~exports.setImmediate timers.js:337 + 45 0.2% 45 0.2% /usr/local/bin/node + 29 0.1% 29 0.1% /usr/local/bin/node + + 415 1.7% 415 1.7% /usr/lib/system/libsystem_c.dylib + + 244 1.0% 0 0.0% Function: ~ node.js:27 + 243 1.0% 0 0.0% LazyCompile: ~startup node.js:30 + 227 0.9% 0 0.0% LazyCompile: ~Module.runMain module.js:495 + 227 0.9% 0 0.0% LazyCompile: Module._load module.js:275 + 216 0.9% 0 0.0% LazyCompile: ~Module.load module.js:346 + 214 0.9% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 213 0.9% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 212 0.9% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/util/sync.js:1 + 146 0.6% 0 0.0% LazyCompile: ~require module.js:379 + 146 0.6% 0 0.0% LazyCompile: ~Module.require module.js:361 + 146 0.6% 0 0.0% LazyCompile: Module._load module.js:275 + 143 0.6% 0 0.0% LazyCompile: ~Module.load module.js:346 + 143 0.6% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 142 0.6% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 134 0.6% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:1 + 82 0.3% 0 0.0% LazyCompile: ~require module.js:379 + 82 0.3% 0 0.0% LazyCompile: ~Module.require module.js:361 + 82 0.3% 0 0.0% LazyCompile: Module._load module.js:275 + 75 0.3% 0 0.0% LazyCompile: ~Module.load module.js:346 + 75 0.3% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 74 0.3% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 31 0.1% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/lib/BlockExtractor.js:1 + 29 0.1% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/lib/Sync.js:1 + 29 0.1% 0 0.0% LazyCompile: ~require module.js:379 + 29 0.1% 0 0.0% LazyCompile: ~Module.require module.js:361 + 29 0.1% 0 0.0% LazyCompile: Module._load module.js:275 + 28 0.1% 0 0.0% LazyCompile: ~Module.load module.js:346 + 28 0.1% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 28 0.1% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 28 0.1% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/lib/logger.js:1 + 49 0.2% 0 0.0% LazyCompile: ~Object.defineProperty.get /Users/ematiu/devel/node/bitcore/bitcore.js:10 + 49 0.2% 0 0.0% LazyCompile: ~require module.js:379 + 49 0.2% 0 0.0% LazyCompile: ~Module.require module.js:361 + 49 0.2% 0 0.0% LazyCompile: Module._load module.js:275 + 47 0.2% 0 0.0% LazyCompile: ~Module.load module.js:346 + 47 0.2% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 47 0.2% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 29 0.1% 0 0.0% Function: ~ /Users/ematiu/devel/node/bitcore/lib/Script.js:1 + 29 0.1% 0 0.0% LazyCompile: ~require module.js:379 + 29 0.1% 0 0.0% LazyCompile: ~Module.require module.js:361 + 29 0.1% 0 0.0% LazyCompile: Module._load module.js:275 + 62 0.3% 0 0.0% LazyCompile: ~HistoricSync /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:42 + 62 0.3% 0 0.0% LazyCompile: ~Sync /Users/ematiu/devel/node/insight-api/lib/Sync.js:18 + 61 0.3% 0 0.0% LazyCompile: ~require module.js:379 + 61 0.3% 0 0.0% LazyCompile: ~Module.require module.js:361 + 61 0.3% 0 0.0% LazyCompile: Module._load module.js:275 + 59 0.2% 0 0.0% LazyCompile: ~Module.load module.js:346 + 59 0.2% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 59 0.2% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 56 0.2% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/lib/BlockDb.js:1 + 41 0.2% 0 0.0% LazyCompile: ~require module.js:379 + 41 0.2% 0 0.0% LazyCompile: ~Module.require module.js:361 + 41 0.2% 0 0.0% LazyCompile: Module._load module.js:275 + 39 0.2% 0 0.0% LazyCompile: ~Module.load module.js:346 + 39 0.2% 0 0.0% LazyCompile: ~Module._extensions..js module.js:472 + 39 0.2% 0 0.0% LazyCompile: ~Module._compile module.js:374 + 38 0.2% 0 0.0% Function: ~ /Users/ematiu/devel/node/insight-api/node_modules/levelup/lib/levelup.js:1 + + 66 0.3% 66 0.3% /usr/lib/system/libsystem_malloc.dylib + + 65 0.3% 65 0.3% /usr/lib/system/libsystem_platform.dylib + + 45 0.2% 41 0.2% LazyCompile: *ArraySlice native array.js:621 + + 42 0.2% 0 0.0% LazyCompile: ~processImmediate timers.js:320 + 42 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/lib/HistoricSync.js:448 + 42 0.2% 0 0.0% LazyCompile: ~ /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:678 + 25 0.1% 0 0.0% LazyCompile: *async.whilst /Users/ematiu/devel/node/insight-api/node_modules/async/lib/async.js:676 + + 33 0.1% 33 0.1% Builtin: A builtin from the snapshot + + 26 0.1% 26 0.1% Stub: JSEntryStub + diff --git a/dev-util/stats b/dev-util/stats index 142758ff..671622d3 100644 --- a/dev-util/stats +++ b/dev-util/stats @@ -58,3 +58,13 @@ first 10% Mon Mar 10 11:59:25 ART 2014 10% de blk 0 (testnet) => 37s + +Thu May 22 13:42:50 ART 2014 (base58check + toString opts + custom getStandardizedObject) +10% testnet + => 29s + + +100% testnet + => 17m6s (user time) + + diff --git a/lib/BlockDb.js b/lib/BlockDb.js index 0ce250e5..93cb4d4c 100644 --- a/lib/BlockDb.js +++ b/lib/BlockDb.js @@ -1,16 +1,20 @@ 'use strict'; var imports = require('soop').imports(); -var ThisParent = imports.parent || require('events').EventEmitter; -var TIMESTAMP_PREFIX = 'bts-'; // b-ts- => -var PREV_PREFIX = 'bpr-'; // b-prev- => -var NEXT_PREFIX = 'bne-'; // b-next- => -var MAIN_PREFIX = 'bma-'; // b-main- => 1/0 -var TIP = 'bti-'; // last block on the chain +var TIMESTAMP_PREFIX = 'bts-'; // bts- => +var PREV_PREFIX = 'bpr-'; // bpr- => +var NEXT_PREFIX = 'bne-'; // bne- => +var MAIN_PREFIX = 'bma-'; // bma- => (0 is unconnected) +var TIP = 'bti-'; // bti = : last block on the chain var LAST_FILE_INDEX = 'file-'; // last processed file index -var MAX_OPEN_FILES = 500; +// txid - blockhash mapping (only for confirmed txs, ONLY FOR BEST BRANCH CHAIN) +var IN_BLK_PREFIX = 'btx-'; //btx- = +var MAX_OPEN_FILES = 500; +var CONCURRENCY = 5; +var DFLT_REQUIRED_CONFIRMATIONS = 1; + /** * Module dependencies. */ @@ -18,15 +22,18 @@ var levelup = require('levelup'), config = require('../config/config'); var db = imports.db || levelup(config.leveldb + '/blocks',{maxOpenFiles: MAX_OPEN_FILES} ); var Rpc = imports.rpc || require('./Rpc'); -var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch',config); +var async = require('async'); -var tDb = require('./TransactionDb.js').default(); -var BlockDb = function() { +var logger = require('./logger').logger; +var d = logger.log; +var info = logger.info; + +var BlockDb = function(opts) { + this.txDb = require('./TransactionDb').default(); + this.safeConfirmations = config.safeConfirmations || DEFAULT_SAFE_CONFIRMATIONS; BlockDb.super(this, arguments); - this.poolMatch = new PoolMatch(); }; -BlockDb.parent = ThisParent; BlockDb.prototype.close = function(cb) { db.close(cb); @@ -42,38 +49,146 @@ BlockDb.prototype.drop = function(cb) { }); }; -// adds a block. Does not update Next pointer in -// the block prev to the new block, nor TIP pointer -// -BlockDb.prototype.add = function(b, cb) { - var self = this; + +BlockDb.prototype._addBlockScript = function(b, height) { var time_key = TIMESTAMP_PREFIX + ( b.time || Math.round(new Date().getTime() / 1000) ); - return db.batch() - .put(time_key, b.hash) - .put(MAIN_PREFIX + b.hash, 1) - .put(PREV_PREFIX + b.hash, b.previousblockhash) - .write(function(err){ - if (!err) { - self.emit('new_block', {blockid: b.hash}); - } - cb(err); - }); + return [ + { + type: 'put', + key: time_key, + value: b.hash, + }, + { + type: 'put', + key: MAIN_PREFIX + b.hash, + value: height, + }, + { + type: 'put', + key:PREV_PREFIX + b.hash, + value: b.previousblockhash, + }, + ]; }; -BlockDb.prototype.getTip = function(cb) { - db.get(TIP, function(err, val) { - return cb(err,val); +BlockDb.prototype._delTxsScript = function(txs) { + var dbScript =[]; + + for(var ii in txs){ + dbScript.push({ + type: 'del', + key: IN_BLK_PREFIX + txs[ii], + }); + } + return dbScript; +}; + +BlockDb.prototype._addTxsScript = function(txs, hash, height) { + var dbScript =[]; + + for(var ii in txs){ + dbScript.push({ + type: 'put', + key: IN_BLK_PREFIX + txs[ii], + value: hash+':'+height, + }); + } + return dbScript; +}; + +// Returns blockHash and height for a given txId (If the tx is on the MAIN chain). +BlockDb.prototype.getBlockForTx = function(txId, cb) { + db.get(IN_BLK_PREFIX + txId,function (err, val) { + if (err && err.notFound) return cb(); + if (err) return cb(err); + + var v = val.split(':'); + return cb(err,v[0],parseInt(v[1])); }); }; -BlockDb.prototype.setTip = function(hash, cb) { - db.put(TIP, hash, function(err) { +BlockDb.prototype._changeBlockHeight = function(hash, height, cb) { + var self = this; + var dbScript1 = this._setHeightScript(hash,height); + + d('Getting TXS FROM %s to set it Main', hash); + this.fromHashWithInfo(hash, function(err, bi) { + if (!bi || !bi.info || !bi.info.tx) + throw new Error('unable to get info for block:'+ hash); + + var dbScript2; + if (height>=0) { + dbScript2 = self._addTxsScript(bi.info.tx, hash, height); + info('\t%s %d Txs', 'Confirming', bi.info.tx.length); + } else { + dbScript2 = self._delTxsScript(bi.info.tx); + info('\t%s %d Txs', 'Unconfirming', bi.info.tx.length); + } + db.batch(dbScript2.concat(dbScript1),cb); + }); +}; + +BlockDb.prototype.setBlockMain = function(hash, height, cb) { + this._changeBlockHeight(hash,height,cb); +}; + +BlockDb.prototype.setBlockNotMain = function(hash, cb) { + this._changeBlockHeight(hash,-1,cb); +}; + +// adds a block (and its txs). Does not update Next pointer in +// the block prev to the new block, nor TIP pointer +// +BlockDb.prototype.add = function(b, height, cb) { + d('adding block %s #d', b,height); + var dbScript = this._addBlockScript(b,height); + dbScript = dbScript.concat(this._addTxsScript( + b.tx.map( + function(o){ + return o.txid; + }), + b.hash, + height + )); + this.txDb.addMany(b.tx, function(err) { + if (err) return cb(err); + db.batch(dbScript,cb); + }); +}; + +BlockDb.prototype.getTip = function(cb) { + + if (this.cachedTip){ + var v = this.cachedTip.split(':'); + return cb(null,v[0], parseInt(v[1])); + } + + var self = this; + db.get(TIP, function(err, val) { + if (!val) return cb(); + self.cachedTip = val; + var v = val.split(':'); + return cb(err,v[0], parseInt(v[1])); + }); +}; + +BlockDb.prototype.setTip = function(hash, height, cb) { + this.cachedTip = hash + ':' + height; + db.put(TIP, this.cachedTip, function(err) { return cb(err); }); }; +BlockDb.prototype.getDepth = function(hash, cb) { + var v = this.cachedTip.split(':'); + if (!v) throw new Error('getDepth called with not cachedTip'); + this.getHeight(hash, function(err,h){ + return cb(err,parseInt(v[1]) - h); + }); +}; + //mainly for testing BlockDb.prototype.setPrev = function(hash, prevHash, cb) { db.put(PREV_PREFIX + hash, prevHash, function(err) { @@ -113,19 +228,22 @@ BlockDb.prototype.getNext = function(hash, cb) { }); }; -BlockDb.prototype.isMain = function(hash, cb) { +BlockDb.prototype.getHeight = function(hash, cb) { db.get(MAIN_PREFIX + hash, function(err, val) { if (err && err.notFound) { err = null; val = 0;} return cb(err,parseInt(val)); }); }; -BlockDb.prototype.setMain = function(hash, isMain, cb) { - if (!isMain) console.log('\tNew orphan: %s',hash); - db.put(MAIN_PREFIX + hash, isMain?1:0, function(err) { - return cb(err); - }); +BlockDb.prototype._setHeightScript = function(hash, height) { + d('setHeight: %s #%d', hash,height); + return ([{ + type: 'put', + key: MAIN_PREFIX + hash, + value: height, + }]); }; + BlockDb.prototype.setNext = function(hash, nextHash, cb) { db.put(NEXT_PREFIX + hash, nextHash, function(err) { return cb(err); @@ -160,34 +278,17 @@ BlockDb.prototype.has = function(hash, cb) { }); }; -BlockDb.prototype.getPoolInfo = function(tx, cb) { - var self = this; - - tDb._getInfo(tx, function(e, a) { - if (e) return cb(false); - - if (a && a.isCoinBase) { - var coinbaseHexBuffer = new Buffer(a.vin[0].coinbase, 'hex'); - var aa = self.poolMatch.match(coinbaseHexBuffer); - - return cb(aa); - } - else { - return cb(); - } - }); -}; - BlockDb.prototype.fromHashWithInfo = function(hash, cb) { var self = this; Rpc.getBlock(hash, function(err, info) { if (err || !info) return cb(err); - self.isMain(hash, function(err, val) { + //TODO can we get this from RPC .height? + self.getHeight(hash, function(err, height) { if (err) return cb(err); - info.isMainChain = val ? true : false; + info.isMainChain = height ? true : false; return cb(null, { hash: hash, @@ -223,4 +324,64 @@ BlockDb.prototype.blockIndex = function(height, cb) { return Rpc.blockIndex(height,cb); }; +BlockDb.prototype._fillConfirmationsOneSpent = function(o, chainHeight, cb) { + var self = this; + if (!o.spentTxId) return cb(); + if (o.multipleSpentAttempts) { + async.eachLimit(o.multipleSpentAttempts, CONCURRENCY, + function(oi, e_c) { + self.getBlockForTx(oi.spentTxId, function(err, hash, height) { + if (err) return; + if (height>=0) { + o.spentTxId = oi.spentTxId; + o.index = oi.index; + o.spentIsConfirmed = chainHeight - height >= self.safeConfirmations ? 1 : 0; + o.spentConfirmations = chainHeight - height; + } + return e_c(); + }); + }, cb); + } else { + self.getBlockForTx(o.spentTxId, function(err, hash, height) { + if (err) return cb(err); + o.spentIsConfirmed = chainHeight - height >= self.safeConfirmations ? 1 : 0; + o.spentConfirmations = chainHeight - height; + return cb(); + }); + } +}; + +BlockDb.prototype._fillConfirmationsOne = function(o, chainHeight, cb) { + var self = this; + self.getBlockForTx(o.txid, function(err, hash, height) { + if (err) return cb(err); + o.isConfirmed = chainHeight - height >= self.safeConfirmations ? 1 : 0; + o.confirmations = chainHeight - height; + return self._fillConfirmationsOneSpent(o,chainHeight,cb); + }); +}; + +BlockDb.prototype.fillConfirmations = function(txouts, cb) { + var self = this; + this.getTip(function(err, hash, height){ + var txs = txouts.filter(function(x){ + return !x.spentIsConfirmedCached // not 100%cached + && !(x.isConfirmedCached && !x.spentTxId); // and not 50%cached but not spent + }); +//console.log('[BlockDb.js.360:txouts:]',txs.length); //TODO +var i=0; + async.eachLimit(txs, CONCURRENCY, function(txout, e_c) { + if(txout.isConfirmedCached) { +//console.log('[BlockDb.js.378]', i++); //TODO + self._fillConfirmationsOneSpent(txout,height, e_c); + } else { +//console.log('[BlockDb.js.3782]', i++); //TODO + self._fillConfirmationsOne(txout,height, e_c); + } + + }, cb); + }); +}; + + module.exports = require('soop')(BlockDb); diff --git a/lib/HistoricSync.js b/lib/HistoricSync.js index 07196566..4140a4f7 100644 --- a/lib/HistoricSync.js +++ b/lib/HistoricSync.js @@ -2,24 +2,21 @@ var imports = require('soop').imports(); var util = require('util'); -var assert = require('assert'); var async = require('async'); var bitcore = require('bitcore'); -var RpcClient = bitcore.RpcClient; -var Script = bitcore.Script; var networks = bitcore.networks; var config = imports.config || require('../config/config'); var Sync = require('./Sync'); var sockets = require('../app/controllers/socket.js'); var BlockExtractor = require('./BlockExtractor.js'); var buffertools = require('buffertools'); -var Address = bitcore.Address; +var bitcoreUtil = bitcore.util; +var logger = require('./logger').logger; +var info = logger.info; +var error = logger.error; -// var bitcoreUtil = require('bitcore/util/util'); // 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_DB = 'Bad genesis block. Network mismatch between Insight and levelDB? Insight is configured for:'; @@ -41,35 +38,26 @@ function HistoricSync(opts) { this.sync = new Sync(opts); } -function p() { - var args = []; - Array.prototype.push.apply(args, arguments); - - args.unshift('[historic_sync]'); - /*jshint validthis:true */ - console.log.apply(this, args); -} - HistoricSync.prototype.showProgress = function() { var self = this; if ( self.status ==='syncing' && ( self.syncedBlocks ) % self.step !== 1) return; - if (self.error) { - p('ERROR: ' + self.error); - } + if (self.error) + error(self.error); + else { self.updatePercentage(); - p(util.format('status: [%d%%]', self.syncPercentage)); + info(util.format('status: [%d%%]', self.syncPercentage)); } if (self.shouldBroadcast) { sockets.broadcastSyncInfo(self.info()); } - -// if (self.syncPercentage > 10) { -// process.exit(-1); -// } + // + // if (self.syncPercentage > 10) { + // process.exit(-1); + // } }; @@ -133,6 +121,23 @@ HistoricSync.prototype.getBlockFromRPC = function(cb) { }); }; +HistoricSync.prototype.getStandardizedBlock = function(b) { + var self = this; + + var block = { + hash: bitcoreUtil.formatHashFull(b.getHash()), + previousblockhash: bitcoreUtil.formatHashFull(b.prev_hash), + time: b.timestamp, + }; + var isCoinBase = 1; + block.tx = b.txs.map(function(tx){ + var ret = self.sync.txDb.getStandardizedTx(tx, b.timestamp, isCoinBase); + isCoinBase=0; + return ret; + }); + return block; +}; + HistoricSync.prototype.getBlockFromFile = function(cb) { var self = this; @@ -141,36 +146,7 @@ HistoricSync.prototype.getBlockFromFile = function(cb) { //get Info self.blockExtractor.getNextBlock(function(err, b) { if (err || ! b) return cb(err); - blockInfo = b.getStandardizedObject(b.txs, self.network); - blockInfo.previousblockhash = blockInfo.prev_block; - - var ti=0; - // Get TX Address - b.txs.forEach(function(t) { - - - var objTx = blockInfo.tx[ti++]; - - //add time from block - objTx.time = blockInfo.time; - - var to=0; - t.outs.forEach( function(o) { - - try { - var s = new Script(o.s); - var addrs = new Address.fromScriptPubKey(s, config.network); - - // support only for p2pubkey p2pubkeyhash and p2sh - if (addrs.length === 1) { - objTx.out[to].addrStr = addrs[0]; - } - } catch (e) { - console.log('WARN Could not processs: ' + objTx.txid ,e); - } - to++; - }); - }); + blockInfo = self.getStandardizedBlock(b); self.sync.bDb.setLastFileIndex(self.blockExtractor.currentFileIndex, function(err) { return cb(err,blockInfo); }); @@ -235,7 +211,7 @@ HistoricSync.prototype.updateStartBlock = function(next) { self.sync.bDb.fromHashWithInfo(tip, function(err, bi) { blockInfo = bi ? bi.info : {}; if (oldtip) - self.sync.setBlockMain(oldtip, false, cb); + self.sync.setBlockHeight(oldtip, -1, cb); else return cb(); }); @@ -249,16 +225,18 @@ HistoricSync.prototype.updateStartBlock = function(next) { } else { oldtip = tip; + if (!tip) + throw new Error('Previous blockchain tip was not found on bitcoind. Please reset Insight DB. Tip was:'+tip) + tip = blockInfo.previousblockhash; - assert(tip); - p('Previous TIP is now orphan. Back to:' + tip); + info('Previous TIP is now orphan. Back to:' + tip); ret = true; } return ret; }, function(err) { self.startBlock = tip; - p('Resuming sync from block:'+tip); + info('Resuming sync from block:'+tip); return next(err); } ); @@ -275,7 +253,7 @@ HistoricSync.prototype.prepareFileSync = function(opts, next) { try { self.blockExtractor = new BlockExtractor(config.bitcoind.dataDir, config.network); } catch (e) { - p(e.message + '. Disabling file sync.'); + info(e.message + '. Disabling file sync.'); return next(); } @@ -288,7 +266,7 @@ HistoricSync.prototype.prepareFileSync = function(opts, next) { var h = self.genesis; - p('Seeking file to:' + self.startBlock); + info('Seeking file to:' + self.startBlock); //forward till startBlock async.whilst( function() { @@ -312,26 +290,26 @@ HistoricSync.prototype.prepareRpcSync = function(opts, next) { if (self.blockExtractor) return next(); self.getFn = self.getBlockFromRPC; + self.allowReorgs = true; self.currentRpcHash = self.startBlock; - self.allowReorgs = false; return next(); }; HistoricSync.prototype.showSyncStartMessage = function() { var self = this; - p('Got ' + self.connectedCountDB + + info('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); + info('bitcoind dataDir configured...importing blocks from .dat files'); + info('First file index: ' + self.blockExtractor.currentFileIndex); } else { - p('syncing from RPC (slow)'); + info('syncing from RPC (slow)'); } - p('Starting from: ', self.startBlock); + info('Starting from: ', self.startBlock); self.showProgress(); }; @@ -389,7 +367,7 @@ 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); + error('## Wont start to sync while status is %s', self.status); return next(); } @@ -404,17 +382,14 @@ HistoricSync.prototype.start = function(opts, next) { function (w_cb) { self.getFn(function(err,blockInfo) { if (err) return w_cb(self.setError(err)); - if (blockInfo && blockInfo.hash) { + if (blockInfo && blockInfo.hash + && (!opts.stopAt || opts.stopAt !== 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); - }); + setImmediate(function(){ + return w_cb(err); }); }); } diff --git a/lib/PeerSync.js b/lib/PeerSync.js index 41289b9b..348a4b36 100644 --- a/lib/PeerSync.js +++ b/lib/PeerSync.js @@ -49,10 +49,8 @@ PeerSync.prototype.handleInv = function(info) { PeerSync.prototype.handleTx = function(info) { var self =this; - var tx = info.message.tx.getStandardizedObject(); - tx.outs = info.message.tx.outs; - tx.ins = info.message.tx.ins; - console.log('[p2p_sync] Handle tx: ' + tx.hash); + var tx = this.sync.txDb.getStandardizedTx(info.message.tx); + console.log('[p2p_sync] Handle tx: ' + tx.txid); tx.time = tx.time || Math.round(new Date().getTime() / 1000); this.sync.storeTxs([tx], function(err) { @@ -62,10 +60,10 @@ PeerSync.prototype.handleTx = function(info) { else { if (self.shouldBroadcast) { sockets.broadcastTx(tx); - if (tx.addrsToEmit) { - tx.addrsToEmit.forEach(function(a) { - sockets.broadcastAddressTx(a, tx.txid); - }); + if (tx.relatedAddrs) { + for(var ii in tx.relatedAddrs){ + sockets.broadcastAddressTx(tx.relatedAddrs[ii], tx.txid); + } } } } @@ -77,7 +75,6 @@ PeerSync.prototype.handleBlock = function(info) { var self = this; var block = info.message.block; var blockHash = bitcoreUtil.formatHashFull(block.calcHash()); - console.log('[p2p_sync] Handle block: %s (allowReorgs: %s)', blockHash, self.allowReorgs); var tx_hashes = block.txs.map(function(tx) { diff --git a/lib/Sync.js b/lib/Sync.js index c3b1ccd7..bc39f659 100644 --- a/lib/Sync.js +++ b/lib/Sync.js @@ -7,6 +7,12 @@ var bitcore = require('bitcore'); var networks = bitcore.networks; var async = require('async'); +var logger = require('./logger').logger; +var d = logger.log; +var info = logger.info; + + + var syncId = 0; function Sync(opts) { @@ -15,6 +21,7 @@ function Sync(opts) { this.bDb = require('./BlockDb').default(); this.txDb = require('./TransactionDb').default(); this.network = config.network === 'testnet' ? networks.testnet : networks.livenet; + this.cachedLastHash = null; } Sync.prototype.close = function(cb) { @@ -56,7 +63,8 @@ Sync.prototype.destroy = function(next) { * \ * F-G-NEW * 1) Set F-G as connected (mark TXs as valid) - * 2) Declare D-E orphans (and possible invalidate TXs on them) + * 2) Set new heights in F-G-NEW + * 3) Declare D-E orphans (and possible invalidate TXs on them) * * * Case 3) @@ -77,39 +85,40 @@ Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) { if (!b) return cb(); var self = this; - var oldTip, oldNext, needReorg = false; + var oldTip, oldNext, oldHeight, needReorg = false, height = -1; var newPrev = b.previousblockhash; async.series([ - function(c) { + // TODO? remove this check? self.bDb.has(b.hash, function(err, val) { return c(err || (val ? new Error('WARN: Ignoring already existing block:' + b.hash) : null)); }); }, function(c) { - if (!allowReorgs) return c(); + if (!allowReorgs || newPrev === self.cachedLastHash) return c(); self.bDb.has(newPrev, function(err, val) { + // Genesis? no problem if (!val && newPrev.match(/^0+$/)) return c(); - return c(err || (!val ? new Error('NEED_SYNC Ignoring block with non existing prev:' + b.hash) : null)); }); }, - function(c) { - self.txDb.createFromBlock(b, function(err) { - return c(err); - }); - }, function(c) { if (!allowReorgs) return c(); - self.bDb.getTip(function(err, val) { - oldTip = val; - if (oldTip && newPrev !== oldTip) needReorg = true; + self.bDb.getTip(function(err, hash, h) { + oldTip = hash; + oldHeight = hash ? (h || 0) : -1 + + if (oldTip && newPrev !== oldTip) { + needReorg = true; + console.log('## REORG Triggered, tip mismatch'); + } return c(); }); }, + function(c) { if (!needReorg) return c(); self.bDb.getNext(newPrev, function(err, val) { @@ -118,17 +127,29 @@ Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) { return c(); }); }, - function(c) { - self.bDb.add(b, c); + function(c) { + if (!allowReorgs) return c(); + if (needReorg) { + info('NEW TIP: %s NEED REORG (old tip: %s #%d)', b.hash, oldTip, oldHeight); + self.processReorg(oldTip, oldNext, newPrev, oldHeight, function(err, h) { + if (err) throw err; + + height = h; + return c(); + }); + } + else { + height = oldHeight + 1; + return c(); + } }, function(c) { - if (!needReorg) return c(); - console.log('NEW TIP: %s NEED REORG (old tip: %s)', b.hash, oldTip); - self.processReorg(oldTip, oldNext, newPrev, c); + self.cachedLastHash = b.hash; // just for speed up. + self.bDb.add(b, height, c); }, function(c) { if (!allowReorgs) return c(); - self.bDb.setTip(b.hash, function(err) { + self.bDb.setTip(b.hash, height, function(err) { return c(err); }); }, @@ -147,21 +168,20 @@ Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) { }); }; - - -Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, cb) { +Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, oldHeight, cb) { var self = this; - var orphanizeFrom; + var orphanizeFrom, newHeight; async.series([ function(c) { - self.bDb.isMain(newPrev, function(err, val) { - if (!val) return c(); + self.bDb.getHeight(newPrev, function(err, height) { + if (!height) return c(new Error('Could not found block:' + newPrev)); + if (height<0) return c(); - console.log('# Reorg Case 1)'); - // case 1 + newHeight = height + 1; + info('# Reorg Case 1) OldNext: %s NewHeight: %d', oldNext, newHeight); orphanizeFrom = oldNext; return c(err); }); @@ -169,10 +189,12 @@ Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, cb) { function(c) { if (orphanizeFrom) return c(); - console.log('# Reorg Case 2)'); - self.setBranchConnectedBackwards(newPrev, function(err, yHash, newYHashNext) { + info('# Reorg Case 2)'); + self.setBranchConnectedBackwards(newPrev, function(err, yHash, newYHashNext, height) { if (err) return c(err); + newHeight = height; self.bDb.getNext(yHash, function(err, yHashNext) { + // Connect the new branch, and orphanize the old one. orphanizeFrom = yHashNext; self.bDb.setNext(yHash, newYHashNext, function(err) { return c(err); @@ -182,25 +204,17 @@ Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, cb) { }, function(c) { if (!orphanizeFrom) return c(); - self.setBranchOrphan(orphanizeFrom, function(err) { + self._setBranchOrphan(orphanizeFrom, function(err) { return c(err); }); }, ], function(err) { - return cb(err); + return cb(err, newHeight); }); }; -Sync.prototype.setBlockMain = function(hash, isMain, cb) { - var self = this; - self.bDb.setMain(hash, isMain, function(err) { - if (err) return cb(err); - return self.txDb.handleBlockChange(hash, isMain, cb); - }); -}; - -Sync.prototype.setBranchOrphan = function(fromHash, cb) { +Sync.prototype._setBranchOrphan = function(fromHash, cb) { var self = this, hashInterator = fromHash; @@ -209,7 +223,7 @@ Sync.prototype.setBranchOrphan = function(fromHash, cb) { return hashInterator; }, function(c) { - self.setBlockMain(hashInterator, false, function(err) { + self.bDb.setBlockNotMain(hashInterator, function(err) { if (err) return cb(err); self.bDb.getNext(hashInterator, function(err, val) { hashInterator = val; @@ -220,43 +234,52 @@ Sync.prototype.setBranchOrphan = function(fromHash, cb) { }; Sync.prototype.setBranchConnectedBackwards = function(fromHash, cb) { + //console.log('[Sync.js.219:setBranchConnectedBackwards:]',fromHash); //TODO var self = this, hashInterator = fromHash, lastHash = fromHash, - isMain; + yHeight, + branch = []; async.doWhilst( function(c) { - self.setBlockMain(hashInterator, true, function(err) { + branch.unshift(hashInterator); + + self.bDb.getPrev(hashInterator, function(err, val) { if (err) return c(err); - self.bDb.getPrev(hashInterator, function(err, val) { - if (err) return c(err); - lastHash = hashInterator; - hashInterator = val; - self.bDb.isMain(hashInterator, function(err, val) { - isMain = val; - return c(); - }); + lastHash = hashInterator; + hashInterator = val; + self.bDb.getHeight(hashInterator, function(err, height) { + yHeight = height; + return c(); }); }); }, function() { - return hashInterator && !isMain; + return hashInterator && yHeight<=0; }, - function(err) { - console.log('\tFound yBlock:', hashInterator); - return cb(err, hashInterator, lastHash); - } - ); + function() { + info('\tFound yBlock: %s #%d', hashInterator, yHeight); + var heightIter = yHeight + 1; + var hashIter; + async.whilst( + function() { + hashIter = branch.shift(); + return hashIter; + }, + function(c) { + self.bDb.setBlockMain(hashIter, heightIter++, c); + }, + function(err) { + return cb(err, hashInterator, lastHash, heightIter); + }); + }); }; +//Store unconfirmed TXs Sync.prototype.storeTxs = function(txs, cb) { - var self = this; - self.txDb.createFromArray(txs, null, function(err) { - if (err) return cb(err); - return cb(err); - }); + this.txDb.addMany(txs, cb); }; diff --git a/lib/TransactionDb.js b/lib/TransactionDb.js index b063011e..8cc37682 100644 --- a/lib/TransactionDb.js +++ b/lib/TransactionDb.js @@ -2,11 +2,6 @@ var imports = require('soop').imports(); -// blockHash -> txid mapping -var IN_BLK_PREFIX = 'txb-'; //txb-- => 1/0 (connected or not) - -// Only for orphan blocks -var FROM_BLK_PREFIX = 'tx-'; //tx-- => 1 // to show tx outs var OUTS_PREFIX = 'txo-'; //txo-- => [addr, btc_sat] @@ -18,6 +13,7 @@ var ADDR_PREFIX = 'txa-'; //txa--- => + btc_sat:ts [:-]( // TODO: use bitcore networks module var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b'; var CONCURRENCY = 10; +var DEFAULT_SAFE_CONFIRMATIONS = 6; var MAX_OPEN_FILES = 500; // var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend @@ -32,25 +28,36 @@ var bitcore = require('bitcore'), levelup = require('levelup'), async = require('async'), config = require('../config/config'), - assert = require('assert'); + assert = require('assert'), + Script = bitcore.Script, + bitcoreUtil = bitcore.util, + buffertools = require('buffertools'); + +var logger = require('./logger').logger; +var info = logger.info; var db = imports.db || levelup(config.leveldb + '/txs',{maxOpenFiles: MAX_OPEN_FILES} ); -var Script = bitcore.Script; -// This is 0.1.2 = > c++ version of base57-native -var base58 = require('base58-native').base58Check; -var encodedData = require('soop').load('bitcore/util/EncodedData',{ - base58: base58 -}); -var versionedData= require('soop').load('bitcore/util/VersionedData',{ - parent: encodedData -}); +var PoolMatch = imports.poolMatch || require('soop').load('./PoolMatch',config); +// This is 0.1.2 = > c++ version of base58-native + var base58 = require('base58-native').base58Check; + var encodedData = require('soop').load('bitcore/util/EncodedData',{ + base58: base58 + }); + var versionedData= require('soop').load('bitcore/util/VersionedData',{ + parent: encodedData + }); + var Address = require('soop').load('bitcore/lib/Address',{ parent: versionedData }); + + var TransactionDb = function() { TransactionDb.super(this, arguments); this.network = config.network === 'testnet' ? networks.testnet : networks.livenet; + this.poolMatch = new PoolMatch(); + this.safeConfirmations = config.safeConfirmations || DEFAULT_SAFE_CONFIRMATIONS; }; TransactionDb.prototype.close = function(cb) { @@ -67,25 +74,6 @@ TransactionDb.prototype.drop = function(cb) { }); }; - -TransactionDb.prototype.has = function(txid, cb) { - - var k = OUTS_PREFIX + txid; - db.get(k, function(err, val) { - - var ret; - - if (err && err.notFound) { - err = null; - ret = false; - } - if (typeof val !== undefined) { - ret = true; - } - return cb(err, ret); - }); -}; - TransactionDb.prototype._addSpentInfo = function(r, txid, index, ts) { if (r.spentTxId) { if (!r.multipleSpentAttempts) { @@ -181,25 +169,24 @@ TransactionDb.prototype._fillSpent = function(info, cb) { }; -TransactionDb.prototype._fillOutpoints = function(info, cb) { +TransactionDb.prototype._fillOutpoints = function(txInfo, cb) { var self = this; - if (!info || info.isCoinBase) return cb(); + if (!txInfo || txInfo.isCoinBase) return cb(); var valueIn = 0; var incompleteInputs = 0; - async.eachLimit(info.vin, CONCURRENCY, function(i, c_in) { - self.fromTxIdN(i.txid, i.vout, info.confirmations, function(err, ret) { - //console.log('[TransactionDb.js.154:ret:]',ret); //TODO + async.eachLimit(txInfo.vin, CONCURRENCY, function(i, c_in) { + self.fromTxIdN(i.txid, i.vout, txInfo.confirmations, function(err, ret) { if (!ret || !ret.addr || !ret.valueSat) { - console.log('Could not get TXouts in %s,%d from %s ', i.txid, i.vout, info.txid); + info('Could not get TXouts in %s,%d from %s ', i.txid, i.vout, txInfo.txid); if (ret) i.unconfirmedInput = ret.unconfirmedInput; incompleteInputs = 1; return c_in(); // error not scalated } - info.firstSeenTs = ret.spentTs; + txInfo.firstSeenTs = ret.spentTs; i.unconfirmedInput = i.unconfirmedInput; i.addr = ret.addr; i.valueSat = ret.valueSat; @@ -210,18 +197,18 @@ TransactionDb.prototype._fillOutpoints = function(info, cb) { * If confirmed by bitcoind, we could not check for double spents * but we prefer to keep the flag of double spent attempt * - if (info.confirmations - && info.confirmations >= CONFIRMATION_NR_TO_NOT_CHECK) + if (txInfo.confirmations + && txInfo.confirmations >= CONFIRMATION_NR_TO_NOT_CHECK) return c_in(); isspent */ // Double spent? if (ret.multipleSpentAttempt || !ret.spentTxId || - (ret.spentTxId && ret.spentTxId !== info.txid) + (ret.spentTxId && ret.spentTxId !== txInfo.txid) ) { if (ret.multipleSpentAttempts) { ret.multipleSpentAttempts.forEach(function(mul) { - if (mul.spentTxId !== info.txid) { + if (mul.spentTxId !== txInfo.txid) { i.doubleSpentTxID = ret.spentTxId; i.doubleSpentIndex = ret.spentIndex; } @@ -240,10 +227,10 @@ isspent }, function() { if (!incompleteInputs) { - info.valueIn = valueIn / util.COIN; - info.fees = (valueIn - (info.valueOut * util.COIN)).toFixed(0) / util.COIN; + txInfo.valueIn = valueIn / util.COIN; + txInfo.fees = (valueIn - (txInfo.valueOut * util.COIN)).toFixed(0) / util.COIN; } else { - info.incompleteInputs = 1; + txInfo.incompleteInputs = 1; } return cb(); }); @@ -252,12 +239,11 @@ isspent TransactionDb.prototype._getInfo = function(txid, next) { var self = this; - Rpc.getTxInfo(txid, function(err, info) { + Rpc.getTxInfo(txid, function(err, txInfo) { if (err) return next(err); - - self._fillOutpoints(info, function() { - self._fillSpent(info, function() { - return next(null, info); + self._fillOutpoints(txInfo, function() { + self._fillSpent(txInfo, function() { + return next(null, txInfo); }); }); }); @@ -306,7 +292,7 @@ TransactionDb.prototype.fromTxIdN = function(txid, n, confirmations, cb) { /* * If this TxID comes from an RPC request * the .confirmations value from bitcoind is available - * so we could avoid checking if the input were double spented + * so we could avoid checking if the input was double spent * * This speed up address calculations by ~30% * @@ -334,42 +320,133 @@ TransactionDb.prototype.fromTxIdN = function(txid, n, confirmations, cb) { }); }; -TransactionDb.prototype.fillConfirmations = function(o, cb) { + +TransactionDb.prototype.deleteCacheForAddress = function(addr,cb) { + var k = ADDR_PREFIX + addr + '-'; + var dbScript = []; + db.createReadStream({ + start: k, + end: k + '~' + }) + .on('data', function(data) { + var v = data.value.split(':'); + dbScript.push({ + type: 'put', + key: data.key, + value: v.slice(0,2).join(':'), + }); + }) + .on('error', function(err) { + return cb(err); + }) + .on('end', function (){ + db.batch(dbScript,cb); + }); +}; + +TransactionDb.prototype.cacheConfirmations = function(txouts,cb) { var self = this; - self.isConfirmed(o.txid, function(err, is) { - if (err) return cb(err); + var dbScript=[]; + for(var ii in txouts){ + var txout=txouts[ii]; - o.isConfirmed = is; - if (!o.spentTxId) return cb(); + //everything already cached? + if (txout.spentIsConfirmedCached) { + continue; + } - if (o.multipleSpentAttempts) { + var infoToCache = []; + if (txout.confirmations > self.safeConfirmations) { + if (!txout.isConfirmedCached) infoToCache.push(1); - async.eachLimit(o.multipleSpentAttempts, CONCURRENCY, - function(oi, e_c) { - self.isConfirmed(oi.spentTxId, function(err, is) { - if (err) return; - if (is) { - o.spentTxId = oi.spentTxId; - o.index = oi.index; - o.spentIsConfirmed = 1; - } - return e_c(); - }); - }, cb); - } else { - self.isConfirmed(o.spentTxId, function(err, is) { - if (err) return cb(err); - o.spentIsConfirmed = is; - return cb(); + if (txout.spentConfirmations > self.safeConfirmations) { +// console.log('[TransactionDb.js.309]',txout); //TODO + infoToCache = infoToCache.concat([1, txout.spentTxId, txout.spentIndex, txout.spentTs]); + } + if (infoToCache.length){ + + // if spent, we overwrite scriptPubKey cache (not needed anymore) + // Last 1 = txout.isConfirmedCached (must be equal to 1 at this point) + infoToCache.unshift(txout.value_sat,txout.ts, 1); + dbScript.push({ + type: 'put', + key: txout.key, + value: infoToCache.join(':'), + }); + } + } + } + +//console.log('[TransactionDb.js.339:dbScript:]',dbScript); //TODO + db.batch(dbScript,cb); +}; + + +TransactionDb.prototype.cacheScriptPubKey = function(txouts,cb) { + var self = this; + + var dbScript=[]; + for(var ii in txouts){ + var txout=txouts[ii]; + + //everything already cached? + if (txout.scriptPubKeyCached || txout.spentTxId) { + continue; + } + + if (txout.scriptPubKey) { + var infoToCache = [txout.value_sat,txout.ts, txout.isConfirmedCached?1:0, txout.scriptPubKey]; + dbScript.push({ + type: 'put', + key: txout.key, + value: infoToCache.join(':'), }); } - }); + } + db.batch(dbScript,cb); +}; + + + + +TransactionDb.prototype._parseAddrData = function(data) { + var k = data.key.split('-'); + var v = data.value.split(':'); + var item = { + key: data.key, + txid: k[2], + index: parseInt(k[3]), + value_sat: parseInt(v[0]), + ts: parseInt(v[1]), + }; + + // Cache + if (v[2]){ + item.isConfirmed = 1; + item.isConfirmedCached = 1; + //console.log('[TransactionDb.js.356] CACHE HIT CONF:', item.key); //TODO + // Sent, confirmed + if (v[3] === 1){ + + //console.log('[TransactionDb.js.356] CACHE HIT SPENT:', item.key); //TODO + item.spentIsConfirmed = 1; + item.spentIsConfirmedCached = 1; + item.spentTxId = v[4]; + item.spentIndex = parseInt(v[5]); + item.spentTs = parseInt(v[6]); + } + // Scriptpubkey cached + else if (v[3]) { + item.scriptPubKey = v[3]; + item.scriptPubKeyCached = 1; + } + } + return item; }; TransactionDb.prototype.fromAddr = function(addr, cb) { var self = this; - var k = ADDR_PREFIX + addr + '-'; var ret = []; @@ -378,21 +455,11 @@ TransactionDb.prototype.fromAddr = function(addr, cb) { end: k + '~' }) .on('data', function(data) { - var k = data.key.split('-'); - var v = data.value.split(':'); - ret.push({ - txid: k[2], - index: parseInt(k[3]), - value_sat: parseInt(v[0]), - ts: parseInt(v[1]), - }); - }) - .on('error', function(err) { - return cb(err); + ret.push(self._parseAddrData(data)); }) + .on('error', cb) .on('end', function() { - - async.eachLimit(ret, CONCURRENCY, function(o, e_c) { + async.eachLimit(ret.filter(function(x){return !x.spentIsConfirmed;}), CONCURRENCY, function(o, e_c) { var k = SPENT_PREFIX + o.txid + '-' + o.index + '-'; db.createReadStream({ start: k, @@ -402,28 +469,75 @@ TransactionDb.prototype.fromAddr = function(addr, cb) { var k = data.key.split('-'); self._addSpentInfo(o, k[3], k[4], data.value); }) - .on('error', function(err) { - return e_c(err); - }) - .on('end', function(err) { - return e_c(err); - }); + .on('error', e_c) + .on('end', e_c); }, - function() { - async.eachLimit(ret, CONCURRENCY, function(o, e_c) { - self.fillConfirmations(o, e_c); - }, function(err) { - return cb(err, ret); - }); + function(err) { + return cb(err, ret); }); }); }; +TransactionDb.prototype._fromBuffer = function (buf) { + var buf2 = buffertools.reverse(buf); + return parseInt(buf2.toString('hex'), 16); +}; + +TransactionDb.prototype.getStandardizedTx = function (tx, time, isCoinBase) { + var self = this; + tx.txid = bitcoreUtil.formatHashFull(tx.getHash()); + var ti=0; + + tx.vin = tx.ins.map(function(txin) { + var ret = {n: ti++}; + if (isCoinBase) { + ret.isCoinBase = true; + } else { + ret.txid = buffertools.reverse(new Buffer(txin.getOutpointHash())).toString('hex'); + ret.vout = txin.getOutpointIndex(); + } + return ret; + }); + + var to = 0; + tx.vout = tx.outs.map(function(txout) { + var val; + if (txout.s) { + var s = new Script(txout.s); + var addrs = new Address.fromScriptPubKey(s, config.network); + // support only for p2pubkey p2pubkeyhash and p2sh + if (addrs && addrs.length === 1) { + val = {addresses: [addrs[0].toString() ] }; + } + } + return { + valueSat: self._fromBuffer(txout.v), + scriptPubKey: val, + n: to++, + }; + }); + tx.time = time; + return tx; +}; + + +TransactionDb.prototype.fillScriptPubKey = function(txouts, cb) { + var self=this; + // Complete utxo info + async.eachLimit(txouts, CONCURRENCY, function (txout, a_c) { + self.fromIdInfoSimple(txout.txid, function(err, info) { + if (!info || !info.vout) return a_c(err); + + txout.scriptPubKey = info.vout[txout.index].scriptPubKey.hex; + return a_c(); + }); + }, function(){ + self.cacheScriptPubKey(txouts, cb); + }); +}; TransactionDb.prototype.removeFromTxId = function(txid, cb) { - async.series([ - function(c) { db.createReadStream({ start: OUTS_PREFIX + txid + '-', @@ -452,229 +566,109 @@ TransactionDb.prototype.removeFromTxId = function(txid, cb) { }; -TransactionDb.prototype.adaptTxObject = function(txInfo) { - var self = this; - // adapt bitcore TX object to bitcoind JSON response - txInfo.txid = txInfo.hash; - - var to = 0; - var tx = txInfo; - if (tx.outs) { - tx.outs.forEach(function(o) { - var s = new Script(o.s); - var addrs = new Address.fromScriptPubKey(s, config.network); - - // support only for p2pubkey p2pubkeyhash and p2sh - if (addrs.length === 1) { - tx.out[to].addrStr = addrs[0].toString(); - tx.out[to].n = to; - } - to++; - }); +TransactionDb.prototype._addScript = function(tx) { + var relatedAddrs = []; + var dbScript = []; + var ts = tx.time; + var txid = tx.txid || tx.hash; +// var u=require('util'); +// console.log('[TransactionDb.js.518]', u.inspect(tx,{depth:10})); //TODO + // Input Outpoints (mark them as spent) + for(var ii in tx.vin) { + var i = tx.vin[ii]; + if (i.txid){ + var k = SPENT_PREFIX + i.txid + '-' + i.vout + '-' + txid + '-' + i.n; + dbScript.push({ + type: 'put', + key: k, + value: ts || 0, + }); + } } - var count = 0; - txInfo.vin = txInfo. in .map(function(txin) { - var i = {}; + for(var ii in tx.vout) { + var o = tx.vout[ii]; + if ( o.scriptPubKey && o.scriptPubKey.addresses && + o.scriptPubKey.addresses[0] && !o.scriptPubKey.addresses[1] // TODO : not supported=> standard multisig + ) { + var addr = o.scriptPubKey.addresses[0]; + var sat = o.valueSat || ((o.value||0) * util.COIN).toFixed(0); - if (txin.coinbase) { - txInfo.isCoinBase = true; - } else { - i.txid = txin.prev_out.hash; - i.vout = txin.prev_out.n; - } - i.n = count++; - return i; - }); - - - count = 0; - txInfo.vout = txInfo.out.map(function(txout) { - var o = {}; - - o.value = txout.value; - o.n = count++; - - if (txout.addrStr) { - o.scriptPubKey = {}; - o.scriptPubKey.addresses = [txout.addrStr]; - } - return o; - }); + relatedAddrs[addr]=1; + var k = OUTS_PREFIX + txid + '-' + o.n; + dbScript.push({ + type: 'put', + key: k, + value: addr + ':' + sat, + },{ + type: 'put', + key: ADDR_PREFIX + addr + '-' + txid + '-' + o.n, + value: sat + ':' + ts, + }); + } + } + tx.relatedAddrs=relatedAddrs; + return dbScript; }; - TransactionDb.prototype.add = function(tx, blockhash, cb) { + var dbScript = this._addScript(tx, blockhash); + db.batch(dbScript, cb); +}; + +TransactionDb.prototype._addManyFromObjs = function(txs, next) { + var dbScript = []; + for(var ii in txs){ + var s = this._addScript(txs[ii]); + dbScript = dbScript.concat(s); + } + db.batch(dbScript, next); +}; + +TransactionDb.prototype._addManyFromHashes = function(txs, next) { + var self=this; + var dbScript = []; + async.eachLimit(txs, CONCURRENCY, function(tx, each_cb) { + if (tx === genesisTXID) + return each_cb(); + + Rpc.getTxInfo(tx, function(err, inInfo) { + if (!inInfo) return each_cb(err); + dbScript = dbScript.concat(self._addScript(inInfo)); + return each_cb(); + }); + }, + function(err) { + if (err) return next(err); + db.batch(dbScript,next); + }); +}; + + +TransactionDb.prototype.addMany = function(txs, next) { + if (!txs) return next(); + + var fn = (typeof txs[0] ==='string') ? + this._addManyFromHashes : this._addManyFromObjs; + + return fn.apply(this,[txs, next]); +}; + + +TransactionDb.prototype.getPoolInfo = function(txid, cb) { var self = this; - var addrs = []; - if (tx.hash) self.adaptTxObject(tx); + Rpc.getTxInfo(txid, function(err, txInfo) { + if (err) return cb(false); + var ret; - var ts = tx.time; - - async.series([ - // Input Outpoints (mark them as spent) - function(p_c) { - if (tx.isCoinBase) return p_c(); - async.forEachLimit(tx.vin, CONCURRENCY, - function(i, next_out) { - db.batch() - .put(SPENT_PREFIX + i.txid + '-' + i.vout + '-' + tx.txid + '-' + i.n, - ts || 0) - .write(next_out); - }, - function(err) { - return p_c(err); - }); - }, - // Parse Outputs - function(p_c) { - async.forEachLimit(tx.vout, CONCURRENCY, - function(o, next_out) { - if (o.value && o.scriptPubKey && - o.scriptPubKey.addresses && - o.scriptPubKey.addresses[0] && !o.scriptPubKey.addresses[1] // TODO : not supported - ) { - var addr = o.scriptPubKey.addresses[0]; - var sat = Math.round(o.value * util.COIN); - - if (addrs.indexOf(addr) === -1) { - addrs.push(addr); - } - - // existed? - var k = OUTS_PREFIX + tx.txid + '-' + o.n; - db.get(k, function(err, val) { - if (!val || (err && err.notFound)) { - db.batch() - .put(k, addr + ':' + sat) - .put(ADDR_PREFIX + addr + '-' + tx.txid + '-' + o.n, sat + ':' + ts) - .write(next_out); - } else { - return next_out(); - } - }); - } else { - return next_out(); - } - }, - function(err) { - if (err) { - console.log('ERR at TX %s: %s', tx.txid, err); - return cb(err); - } - return p_c(); - }); - }, - function(p_c) { - if (!blockhash) { - return p_c(); - } - return self.setConfirmation(tx.txid, blockhash, true, p_c); - }, - ], function(err) { - if (addrs.length > 0 && !blockhash) { - // only emit if we are processing a single tx (not from a block) - tx.addrsToEmit=addrs; - } - return cb(err); + if (txInfo && txInfo.isCoinBase) + ret = self.poolMatch.match(new Buffer(txInfo.vin[0].coinbase, 'hex')); + + return cb(ret); }); }; - - -TransactionDb.prototype.setConfirmation = function(txId, blockHash, confirmed, c) { - if (!blockHash) return c(); - - confirmed = confirmed ? 1 : 0; - - db.batch() - .put(IN_BLK_PREFIX + txId + '-' + blockHash, confirmed) - .put(FROM_BLK_PREFIX + blockHash + '-' + txId, 1) - .write(c); -}; - - -// This slowdown addr balance calculation by 100% -TransactionDb.prototype.isConfirmed = function(txId, c) { - var k = IN_BLK_PREFIX + txId; - var ret = false; - - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - if (data.value === '1') ret = true; - }) - .on('error', function(err) { - return c(err); - }) - .on('end', function(err) { - return c(err, ret); - }); -}; - -TransactionDb.prototype.handleBlockChange = function(hash, isMain, cb) { - var toChange = []; - console.log('\tSearching Txs from block:' + hash); - - var k = FROM_BLK_PREFIX + hash; - var k2 = IN_BLK_PREFIX; - // This is slow, but prevent us to create a new block->tx index. - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var ks = data.key.split('-'); - toChange.push({ - key: k2 + ks[2] + '-' + ks[1], - type: 'put', - value: isMain ? 1 : 0, - }); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function(err) { - if (err) return cb(err); - console.log('\t%s %d Txs', isMain ? 'Confirming' : 'Invalidating', toChange.length); - db.batch(toChange, cb); - }); -}; - -// txs can be a [hashes] or [txObjects] -TransactionDb.prototype.createFromArray = function(txs, blockHash, next) { - var self = this; - if (!txs) return next(); - - async.forEachLimit(txs, CONCURRENCY, function(t, each_cb) { - if (typeof t === 'string') { - // TODO: parse it from networks.genesisTX? - if (t === genesisTXID) return each_cb(); - - Rpc.getTxInfo(t, function(err, inInfo) { - if (!inInfo) return each_cb(err); - return self.add(inInfo, blockHash, each_cb); - }); - } else { - return self.add(t, blockHash, each_cb); - } - }, - function(err) { - return next(err); - }); -}; - - -TransactionDb.prototype.createFromBlock = function(b, next) { - var self = this; - if (!b || !b.tx) return next(); - - return self.createFromArray(b.tx, b.hash, next); -}; - module.exports = require('soop')(TransactionDb); diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 00000000..779b46de --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,5 @@ +var winston = require('winston'); + +winston.info('starting...') + +module.exports.logger=winston; diff --git a/package.json b/package.json index 39889d84..a7a7b6ed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "insight-bitcore-api", "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.12", + "version": "0.2.1", "author": { "name": "Ryan X Charles", "email": "ryan@bitpay.com" @@ -60,13 +60,13 @@ "soop": "=0.1.5", "commander": "*", "bignum": "*", + "winston": "*", "express": "~3.4.7", "buffertools": "*", "should": "~2.1.1", "socket.io": "~0.9.16", "moment": "~2.5.0", "sinon": "~1.7.3", - "chai": "~1.8.1", "xmlhttprequest": "~1.6.0", "bufferput": "git://github.com/bitpay/node-bufferput.git" }, @@ -80,6 +80,7 @@ "grunt-nodemon": "~0.2.0", "grunt-mocha-test": "~0.8.1", "should": "2.1.1", + "chai": "=1.9.1", "grunt-markdown": "~0.5.0" } } diff --git a/test/integration/01-transactionouts.js b/test/integration/01-transactionouts.js index bb41fd25..732c3c87 100644 --- a/test/integration/01-transactionouts.js +++ b/test/integration/01-transactionouts.js @@ -5,6 +5,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; +var should = require('chai'); var assert = require('assert'), fs = require('fs'), util = require('util'), @@ -29,10 +30,13 @@ describe('TransactionDb fromIdWithInfo', function(){ assert.equal(tx.txid, txid); assert(!tx.info.isCoinBase); - for(var i=0; i<20; i++) + for(var i=0; i<20; i++) { assert(parseFloat(tx.info.vin[i].value) === parseFloat(50), 'input '+i); - assert(tx.info.vin[0].addr === 'msGKGCy2i8wbKS5Fo1LbWUTJnf1GoFFG59', 'addr 0'); - assert(tx.info.vin[1].addr === 'mfye7oHsdrHbydtj4coPXCasKad2eYSv5P', 'addr 1'); + } + + + tx.info.vin[0].addr.should.equal('msGKGCy2i8wbKS5Fo1LbWUTJnf1GoFFG59'); + tx.info.vin[1].addr.should.equal('mfye7oHsdrHbydtj4coPXCasKad2eYSv5P'); done(); }); }); @@ -134,7 +138,7 @@ describe('TransactionDb Outs', function(){ assert.equal(readItems.length,0); var unmatch=[]; - txDb.createFromArray([v.txid], null, function(err) { + txDb.addMany([v.txid], function(err) { if (err) return done(err); txDb.fromTxId( v.txid, function(err, readItems) { diff --git a/test/integration/02-transactionouts.js b/test/integration/02-transactionouts.js index 6dc1f851..78a363f3 100644 --- a/test/integration/02-transactionouts.js +++ b/test/integration/02-transactionouts.js @@ -27,7 +27,7 @@ describe('TransactionDb Expenses', function(){ function(txid,c_out) { async.each(spentValid[txid], function(i,c_in) { - txDb.createFromArray([i.txid], null, function(err) { + txDb.addMany([i.txid], function(err) { return c_in(); }); }, diff --git a/test/integration/99-sync.js.descructive-test b/test/integration/99-sync.js.descructive-test index 23ae44d8..61d36695 100644 --- a/test/integration/99-sync.js.descructive-test +++ b/test/integration/99-sync.js.descructive-test @@ -2,12 +2,12 @@ 'use strict'; process.env.NODE_ENV = process.env.NODE_ENV || 'development'; +var should = require('chai'); var assert = require('assert'), async = require('async'), - HistoricSync = require('../../lib/HistoricSync').class(); - + HistoricSync = require('../../lib/HistoricSync'); var s; var b = [ @@ -16,6 +16,7 @@ var b = [ '000000008d55c3e978639f70af1d2bf1fe6f09cb3143e104405a599215c89a48', //2 '000000009b3bca4909f38313f2746120129cce4a699a1f552390955da470c5a9', //3 '00000000ede57f31cc598dc241d129ccb4d8168ef112afbdc870dc60a85f5dd3', //4 B#20 + '000000001a29aff8154de6230a4909a3a971c52ae590006e00fddff33f9e3773', //5 B#21 ]; var t = [ 'd08582d3711f75d085c618874fb0d049ae09d5ec95ec6f5abd289f4b54712c54', // TX from B#16 @@ -25,37 +26,55 @@ var t = [ 'd45f9da73619799e9d7bd03cc290e70875ea4cbad56b8bffa15135fbbb3df9ea', //4 Tx from B20 ]; -var test = function(cb) { +var initialTest = function(cb) { async.each([2,3,4], function(i,c) { - s.sync.bDb.getPrev(b[i], function(err, p) { - assert.equal(p,b[i-1]); - return c(); - }); + s.sync.bDb.getPrev(b[i], function(err, p) { + assert.equal(p,b[i-1]); + return c(); + }); }, function() { async.each([0,1,2,3,4], function(i,c) { - s.sync.bDb.has(b[i], function(err, p) { - assert(p); - return c(); - }); + s.sync.bDb.has(b[i], function(err, p) { + assert(p); + return c(); + }); }, function() { + async.each([0,1,2,3], function(i,c) { + s.sync.bDb.getNext(b[i], function(err, p) { + assert.equal(p,b[i+1]); + return c(); + }); + }, function() { async.each([0,1,2,3], function(i,c) { - s.sync.bDb.getNext(b[i], function(err, p) { - assert.equal(p,b[i+1]); - return c(); + s.sync.bDb.getHeight(b[i], function(err, h) { + assert.equal(h,16+i); + return c(); + }); + }, function() { + async.each([0,1,2,3], function(i,c) { + s.sync.bDb.getDepth(b[i], function(err, d) { + assert.equal(d,4-i); + return c(); }); - }, cb); + }, cb); + }); + }); }); - }); + }); }; + + /* * TEST CASES * + * b0 height = 16; + * * Blocks: 0-1-2-3-4 * case 1) * 0-1-2-3-4 * \ - * C1* + * C1* (height should be 19) * * case 2) * 0-1-2---3-4 @@ -75,474 +94,473 @@ var test = function(cb) { * */ +var checkTxs = function(txs,heights){ + var i=0; + txs.forEach(function(tx){ + var v=heights[i++]; + it('tx height:'+tx+' #'+v,function(done){ + s.sync.bDb.getBlockForTx(tx, function(err,hash,height) { + assert(!err,err); + if (v>=0) { + assert(hash); + height.should.equal(v); + } else { + assert(!hash); + assert(!height); + } + + return done(); + }); + }); + }); +}; + +//heights is optional +var checkBlocks = function(hashes,heights){ + var i=0; + hashes.forEach(function(hash){ + var v = heights[i++]; + it('block height:'+hash+' #'+v,function(done){ + s.sync.bDb.getHeight(hash, function(err,height) { + assert(!err,err); + height.should.equal(v); + return done(); + }); + }); + }); +}; + + describe('Sync Reorgs', function(){ + var opts = { + forceRPC: true, + stopAt: b[5], + }; before(function(done) { s = new HistoricSync(); - s.init({}, function(err) { - if (err) return done(err); - s.sync.destroy(done); - }); + s.sync.destroy(done); }); it('simple RPC forward syncing', function(done) { - s.getPrevNextBlock(s.genesis,b[4], { - next: true, - }, function(err) { - if (err) return done(err); - test(done); - }); + s.start(opts, function(err) { + if (err) return done(err); + initialTest(done); + }); }); var case1 = { - hash: '0000000000000000000000000000000000000000000000000000000000000001', - tx: [ 'f0596531810160d090813673b4a397f4617aab44eb26c7f06c8a766eac984b91' ], + hash: '0000000042d3db6c529dd8f1b085367cb6d907b534f5b1a5dfdd3a34a3459886', + tx: [ '2dc27c8d4b98f5e2ed009cfc164ac4990f18e03c4d5b71e780f9c8b7b2c5f151' ], time: 1296690099, previousblockhash: b[2], }; - it('reorg, case 1', function(done) { - async.series([ - function (c) { - s.sync.txDb.isConfirmed(t[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[3], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[4], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.storeTipBlock(case1, function(err) { - assert(!err, 'shouldnt return error' + err); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(b[2], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(b[3], function(err,is) { - assert(!err); - assert(!is, b[3] + 'should not be on main chain'); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(b[4], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[3], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[4], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case1.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - ], done ); - }); - - it('reorg, case 1 (repeat)', function(done) { - s.sync.storeTipBlock(case1, function(err) { - assert(!err, 'shouldnt return error' + err); - return done(); + describe('reorg, case 1', function(done) { + checkTxs([t[0], t[1], t[2], t[3], t[4]],[16,17,18,19,20]); + checkBlocks([b[0], b[1], b[2], b[3], b[4]],[16,17,18,19,20]); + it('trigger reorg case 1', function(done1){ + s.sync.storeTipBlock(case1, function(err) { + assert(!err, 'shouldnt return error' + err); + done1(); + }); }); + checkTxs([t[0], t[1], t[2], t[3], t[4],case1.tx],[16,17,18,-1,-1,19]); + checkBlocks([b[0], b[1], b[2],b[3],b[4],case1.hash],[16,17,18,-1,-1,19]); }); - - var case2 = { - hash: '0000000000000000000000000000000000000000000000000000000000000002', - tx: [ '99bb359a4b12a588fcb9e59e5e8d92d593ce7a56d2ba42085fe86d9a0b4fde15' ], - time: 1296690099, - previousblockhash: b[3], - }; - - - it('reorg, case 2', function(done) { - async.series([ - function (c) { - s.sync.txDb.isConfirmed(t[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case1.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[4], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.storeTipBlock(case2, function(err) { - assert(!err, 'shouldnt return error' + err); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(b[3], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(b[4], function(err,is) { - assert(!err); - assert(!is, b[3] + 'should not be on main chain'); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(case1.hash, function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(case2.hash, function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[3], function(err,is) { - assert(!err); - assert(is, 'transaction t[3] should be valid:' + t[3]); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case1.tx[0], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[4], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.bDb.getNext(b[2], function(err, val) { - assert(!err); - assert.equal(val,b[3]); - return c(); - }); - }, - - - - ], done ); - }); - - - var case2b = { - hash: '0000000000000000000000000000000000000000000000000000000000000003', - tx: case1.tx, - time: 1296690099, - previousblockhash: case2.hash, - }; - - it('reorg, case 2b', function(done) { - async.series([ - function (c) { - s.sync.txDb.isConfirmed(case2b.tx[0], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.storeTipBlock(case2b, function(err) { - assert(!err, 'shouldnt return error' + err); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[3], function(err,is) { - assert(!err); - assert(is, 'transaction t[3] should be valid:' + t[3]); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2b.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - ], done ); - }); - - - - var case2c = { - hash: '0000000000000000000000000000000000000000000000000000000000000004', - tx: case2.tx, - time: 1296690099, - previousblockhash: case1.hash, - }; - - it('reorg, case 2c', function(done) { - async.series([ - function (c) { - s.sync.txDb.isConfirmed(case1.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.isMain(case1.hash, function(err,is) { - assert(!err); - assert(!is, 'case1 block shouldnt be main:' + case1.hash); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2c.tx[0], function(err,is) { - assert(!err); - assert(is); //It was there before (from case2) - return c(); - }); - }, - function (c) { - s.sync.storeTipBlock(case2c, function(err) { - assert(!err, 'shouldnt return error' + err); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case1.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.has(case1.hash, function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.has(case2c.hash, function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2c.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[3], function(err,is) { - assert(!err); - assert(!is, 'TX t[3]: shouldnt be confirmed:' + t[3] +':'+ is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[4], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - - ], done ); - }); - - var case3 = { - hash: '0000000000000000000000000000000000000000000000000000000000000005', - tx: case2.tx, - time: 1296690099, - previousblockhash: '666', - }; - - it('reorg, case 3)', function(done) { - async.series([ - function (c) { - s.sync.storeTipBlock(case3, function(err) { - assert(!err, 'shouldnt return error' + err); - return c(); - }); - }, - - //shoudnt change anything - function (c) { - s.sync.txDb.isConfirmed(case1.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.has(case1.hash, function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.has(case2c.hash, function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2c.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[3], function(err,is) { - assert(!err); - assert(!is, 'TX t[3]: shouldnt be confirmed:' + t[3] +':'+ is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(t[4], function(err,is) { - assert(!err); - assert(!is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(case2.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - - ], done ); - }); - - var p2p = { - hash: '0000000000000000000000000000000000000000000000000000000000000006', - tx: ['f6c2901f39fd07f2f2e503183d76f73ecc1aee9ac9216fde58e867bc29ce674e'], - time: 1296690099, - previousblockhash: '111', - }; - - it('p2p, no reorg allowed', function(done) { - async.series([ - function (c) { - s.sync.storeTipBlock(p2p, false, function(err) { - assert(!err, 'shouldnt return error' + err); - return c(); - }); - }, - function (c) { - s.sync.bDb.has(p2p.hash, function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.txDb.isConfirmed(p2p.tx[0], function(err,is) { - assert(!err); - assert(is); - return c(); - }); - }, - function (c) { - s.sync.bDb.getNext(p2p.hash, function(err,v) { - assert(!err); - assert.equal(v,p2p.nextblockhash); - return c(); - }); - }, - function (c) { - s.sync.bDb.getNext(p2p.previousblockhash, function(err,v) { - assert(!err); - assert.equal(v,p2p.hash); - return c(); - }); - }, - - ], done ); - }); +// +// it('reorg, case 1 (repeat)', function(done) { +// s.sync.storeTipBlock(case1, function(err) { +// assert(!err, 'shouldnt return error' + err); +// return done(); +// }); +// }); +// +// var case2 = { +// hash: '00000000c262f9428bb84407780bb0bd008b74941d651111ab2500cf649fa45d', +// tx: [ '3fa6fce216e91c9dc9a6267168e9d8bfb4ae57aec0d26590442cfec6e8233682' ], +// time: 1296690099, +// previousblockhash: b[3], +// }; +// +// +// it('reorg, case 2', function(done) { +// async.series([ +// function (c) { +// s.sync.txDb.getBlock(t[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case1.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[4], function(err,is) { +// assert(!err); +// assert(!is); +// return c(); +// }); +// }, +// // BEFORE +// function (c) { +// s.sync.bDb.getHeight(b[3], function(err,is) { +// assert(!err); +// assert.equal(is,-1); +// return c(); +// }); +// }, +// function (c) { +// s.sync.storeTipBlock(case2, function(err) { +// assert(!err, 'shouldnt return error' + err); +// return c(); +// }); +// }, +// // AFTER +// function (c) { +// s.sync.bDb.getHeight(b[3], function(err,is) { +// assert(!err); +// assert.equal(is,19); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(b[4], function(err,is) { +// assert(!err); +// assert.equal( is,-1, b[3] + 'should not be on main chain: #'+is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(case1.hash, function(err,is) { +// assert(!err); +// assert.equal(is,-1); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(case2.hash, function(err,is) { +// assert(!err); +// assert.equal(is, 20); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[3], function(err,is) { +// console.log('[99-sync.js.descructive-test.300:is:]',is); //TODO +// assert(!err); +// assert(is, 'transaction t[3] should be valid:' + t[3]); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case1.tx[0], function(err,is) { +// assert(!err); +// assert(!is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[4], function(err,is) { +// assert(!err); +// assert(!is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getNext(b[2], function(err, val) { +// assert(!err); +// assert.equal(val,b[3]); +// return c(); +// }); +// }, +// +// +// +// ], done ); +// }); +// +// +// var case2b = { +// hash: '0000000022bb34bc09f8d8d0ae26b86c87f8483e54b9c3addfe6f30b12bc656a', +// tx: case1.tx, +// time: 1296690099, +// previousblockhash: case2.hash, +// }; +// +// it('reorg, case 2b', function(done) { +// async.series([ +// function (c) { +// s.sync.txDb.getBlock(case2b.tx[0], function(err,is) { +// assert(!err); +// assert(!is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.storeTipBlock(case2b, function(err) { +// assert(!err, 'shouldnt return error' + err); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[3], function(err,is) { +// assert(!err); +// assert(is, 'transaction t[3] should be valid:' + t[3]); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2b.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// ], done ); +// }); +// +// +// +// var case2c = { +// hash: '0000000000000000000000000000000000000000000000000000000000000004', +// tx: case2.tx, +// time: 1296690099, +// previousblockhash: case1.hash, +// }; +// +// it('reorg, case 2c', function(done) { +// async.series([ +// function (c) { +// s.sync.txDb.getBlock(case1.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(case1.hash, function(err,is) { +// assert(!err); +// assert.equal(is, -1, 'case1 block shouldnt be main:' + case1.hash); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2c.tx[0], function(err,is) { +// assert(!err); +// assert(is); //It was there before (from case2) +// return c(); +// }); +// }, +// function (c) { +// s.sync.storeTipBlock(case2c, function(err) { +// assert(!err, 'shouldnt return error' + err); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case1.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.has(case1.hash, function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.has(case2c.hash, function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(case1.hash, function(err,h) { +// assert(!err); +// assert.equal(h,19); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(case2c.hash, function(err,h) { +// assert(!err); +// assert.equal(h,20); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2c.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[3], function(err,is) { +// assert(!err); +// assert(!is, 'TX t[3]: shouldnt be confirmed:' + t[3] +':'+ is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[4], function(err,is) { +// assert(!err); +// assert(!is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// +// ], done ); +// }); +// +// var case3 = { +// hash: '0000000000000000000000000000000000000000000000000000000000000005', +// tx: case2.tx, +// time: 1296690099, +// previousblockhash: '666', +// }; +// +// it('reorg, case 3)', function(done) { +// async.series([ +// function (c) { +// s.sync.storeTipBlock(case3, function(err) { +// assert(err, 'should return error' + err); +// return c(); +// }); +// }, +// +// //shoudnt change anything +// function (c) { +// s.sync.txDb.getBlock(case1.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.has(case1.hash, function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.has(case2c.hash, function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2c.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[3], function(err,is) { +// assert(!err); +// assert(!is, 'TX t[3]: shouldnt be confirmed:' + t[3] +':'+ is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(t[4], function(err,is) { +// assert(!err); +// assert(!is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(case2.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// +// ], done ); +// }); +// +// var p2p = { +// hash: '0000000000000000000000000000000000000000000000000000000000000006', +// tx: ['f6c2901f39fd07f2f2e503183d76f73ecc1aee9ac9216fde58e867bc29ce674e'], +// time: 1296690099, +// previousblockhash: '111', +// }; +// +// it('p2p, no reorg allowed', function(done) { +// async.series([ +// function (c) { +// s.sync.storeTipBlock(p2p, false, function(err) { +// assert(!err, 'shouldnt return error' + err); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.has(p2p.hash, function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.txDb.getBlock(p2p.tx[0], function(err,is) { +// assert(!err); +// assert(is); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getNext(p2p.hash, function(err,v) { +// assert(!err); +// assert.equal(v,p2p.nextblockhash); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getNext(p2p.previousblockhash, function(err,v) { +// assert(!err); +// assert.equal(v,p2p.hash); +// return c(); +// }); +// }, +// function (c) { +// s.sync.bDb.getHeight(p2p.hash, function(err,is) { +// assert(!err); +// assert.equal(is,-1); +// return c(); +// }); +// }, +// +// ], done ); +// }); }); diff --git a/test/integration/addr.js b/test/integration/addr.js index 12309645..0e726824 100644 --- a/test/integration/addr.js +++ b/test/integration/addr.js @@ -11,8 +11,11 @@ var assert = require('assert'), addrValid = JSON.parse(fs.readFileSync('test/integration/addr.json')), utxoValid = JSON.parse(fs.readFileSync('test/integration/utxo.json')); +var should = require('chai'); + var txDb; describe('Address balances', function() { + this.timeout(5000); before(function(c) { txDb = TransactionDb; @@ -24,18 +27,16 @@ describe('Address balances', function() { console.log(v.addr + ' => disabled in JSON'); } else { it('Address info for: ' + v.addr, function(done) { - this.timeout(5000); - var a = new Address(v.addr, txDb); - a.update(function(err) { if (err) done(err); - assert.equal(v.addr, a.addrStr); - assert.equal(a.unconfirmedTxApperances ,v.unconfirmedTxApperances || 0, 'unconfirmedTxApperances'); - assert.equal(a.unconfirmedBalanceSat ,v.unconfirmedBalanceSat || 0, 'unconfirmedBalanceSat: ' + a.unconfirmedBalanceSat + ' vs.: ' + v.unconfirmedBalanceSat ); + v.addr.should.equal(a.addrStr); + a.unconfirmedTxApperances.should.equal(v.unconfirmedTxApperances || 0, 'unconfirmedTxApperances'); + a.unconfirmedBalanceSat.should.equal(v.unconfirmedBalanceSat || 0, 'unconfirmedBalanceSat'); if (v.txApperances) - assert.equal(v.txApperances, a.txApperances, 'txApperances: ' + a.txApperances); - if (v.totalReceived) assert.equal(v.totalReceived, a.totalReceived, 'received: ' + a.totalReceived); + a.txApperances.should.equal(v.txApperances, 'txApperances'); + + if (v.totalReceived) a.totalReceived.should.equal(v.totalReceived,'totalReceived'); if (v.totalSent) assert.equal(v.totalSent, a.totalSent, 'send: ' + a.totalSent); if (v.balance) assert.equal(v.balance, a.balance, 'balance: ' + a.balance); @@ -49,30 +50,137 @@ describe('Address balances', function() { done(); }); }); + + it('Address info (cache) for: ' + v.addr, function(done) { + var a = new Address(v.addr, txDb); + a.update(function(err) { + if (err) done(err); + v.addr.should.equal(a.addrStr); + a.unconfirmedTxApperances.should.equal(v.unconfirmedTxApperances || 0, 'unconfirmedTxApperances'); + a.unconfirmedBalanceSat.should.equal(v.unconfirmedBalanceSat || 0, 'unconfirmedBalanceSat'); + if (v.txApperances) + a.txApperances.should.equal(v.txApperances, 'txApperances'); + + if (v.totalReceived) a.totalReceived.should.equal(v.totalReceived,'totalReceived'); + if (v.totalSent) assert.equal(v.totalSent, a.totalSent, 'send: ' + a.totalSent); + if (v.balance) assert.equal(v.balance, a.balance, 'balance: ' + a.balance); + done(); + },1); + }); } }); }); +describe('Address cache ', function() { + this.timeout(5000); + before(function(c) { + txDb = TransactionDb; + txDb.deleteCacheForAddress('muAt5RRqDarPFCe6qDXGZc54xJjXYUyepG',function(){ + txDb.deleteCacheForAddress('mt2AzeCorSf7yFckj19HFiXJgh9aNyc4h3',c); + }); + }); + + it('cache case 1 w/o cache', function(done) { + var a = new Address('muAt5RRqDarPFCe6qDXGZc54xJjXYUyepG', txDb); + a.update(function(err) { + if (err) done(err); + a.balance.should.equal(0, 'balance'); + a.totalReceived.should.equal(19175, 'totalReceived'); + a.txApperances.should.equal(2, 'txApperances'); + return done(); + }); + }); + it('cache case 1 w cache', function(done) { + var a = new Address('muAt5RRqDarPFCe6qDXGZc54xJjXYUyepG', txDb); + a.update(function(err) { + if (err) done(err); + a.balance.should.equal(0, 'balance'); + a.totalReceived.should.equal(19175, 'totalReceived'); + a.txApperances.should.equal(2, 'txApperances'); + return done(); + }); + }); + + it('cache case 2 w/o cache', function(done) { + var a = new Address('mt2AzeCorSf7yFckj19HFiXJgh9aNyc4h3', txDb); + a.update(function(err) { + if (err) done(err); + a.balance.should.equal(0, 'balance'); + a.totalReceived.should.equal(1376000, 'totalReceived'); + a.txApperances.should.equal(8003, 'txApperances'); + return done(); + }); + },1); + it('cache case 2 w cache', function(done) { + var a = new Address('mt2AzeCorSf7yFckj19HFiXJgh9aNyc4h3', txDb); + a.update(function(err) { + if (err) done(err); + a.balance.should.equal(0, 'balance'); + a.totalReceived.should.equal(1376000, 'totalReceived'); + a.txApperances.should.equal(8003, 'txApperances'); + return done(); + },1); + }); +}); + +//tested against https://api.biteasy.com/testnet/v1/addresses/2N1pLkosf6o8Ciqs573iwwgVpuFS6NbNKx5/unspent-outputs?per_page=40 describe('Address utxo', function() { + + before(function(c) { + txDb = TransactionDb; + var l = utxoValid.length; + var d=0; + + utxoValid.forEach(function(v) { + //console.log('Deleting cache for', v.addr); //TODO + txDb.deleteCacheForAddress(v.addr,function(){ + if (d++ == l-1) return c(); + }); + }); + }); + + utxoValid.forEach(function(v) { if (v.disabled) { console.log(v.addr + ' => disabled in JSON'); } else { it('Address utxo for: ' + v.addr, function(done) { - this.timeout(50000); - + this.timeout(2000); var a = new Address(v.addr, txDb); a.getUtxo(function(err, utxo) { if (err) done(err); assert.equal(v.addr, a.addrStr); - if (v.length) assert.equal(v.length, utxo.length, 'length: ' + utxo.length); - if (v.tx0id) assert.equal(v.tx0id, utxo[0].txid, 'have tx: ' + utxo[0].txid); - if (v.tx0scriptPubKey) - assert.equal(v.tx0scriptPubKey, utxo[0].scriptPubKey, 'have tx: ' + utxo[0].scriptPubKey); - if (v.tx0amount) - assert.equal(v.tx0amount, utxo[0].amount, 'amount: ' + utxo[0].amount); + if (v.length) utxo.length.should.equal(v.length, 'Unspent count'); + if (v.tx0id) { + var x=utxo.filter(function(x){ + return x.txid === v.tx0id; + }); + assert(x,'found output'); + x.length.should.equal(1,'found output'); + x[0].scriptPubKey.should.equal(v.tx0scriptPubKey,'scriptPubKey'); + x[0].amount.should.equal(v.tx0amount,'amount'); + } + done(); + }); + }); + it('Address utxo (cached) for: ' + v.addr, function(done) { + this.timeout(2000); + var a = new Address(v.addr, txDb); + a.getUtxo(function(err, utxo) { + if (err) done(err); + assert.equal(v.addr, a.addrStr); + if (v.length) utxo.length.should.equal(v.length, 'Unspent count'); + if (v.tx0id) { + var x=utxo.filter(function(x){ + return x.txid === v.tx0id; + }); + assert(x,'found output'); + x.length.should.equal(1,'found output'); + x[0].scriptPubKey.should.equal(v.tx0scriptPubKey,'scriptPubKey'); + x[0].amount.should.equal(v.tx0amount,'amount'); + } done(); }); }); diff --git a/test/integration/addr.json b/test/integration/addr.json index ffd9358d..df83e9ef 100644 --- a/test/integration/addr.json +++ b/test/integration/addr.json @@ -41,35 +41,36 @@ "totalReceived": 54.81284116 }, { + "disabled": 1, "addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29", - "balance": 1271.87752288, - "totalReceived": 1271.87752288, + "balance": 1363.14677867, + "totalReceived": 1363.14677867, "totalSent": 0, - "txApperances": 6197, - "unconfirmedTxApperances": 3, - "unconfirmedBalanceSat": 149174913 + "txApperances": 7947, + "unconfirmedTxApperances": 5, + "unconfirmedBalanceSat": 149174913 }, { "addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H", - "txApperances": 7164, - "balance": 46413.0, + "txApperances": 7166, + "balance": 6513, "totalReceived": 357130.17644359, - "totalSent": 310717.17644359 + "totalSent": 350617.17644359 }, { "addr": "mgKY35SXqxFpcKK3Dq9mW9919N7wYXvcFM", - "txApperances": 1, - "balance": 0.01979459, - "totalReceived": 0.01979459, + "txApperances": 2, + "balance": 0, + "totalReceived": 0.01979459, "totalSent": 0, "transactions": [ "91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5" ] }, { "addr": "mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5", - "balance": 10580.50027254, + "balance": 5524.61806422, "totalReceived": 12157.65075053, - "totalSent": 1577.15047799, - "txApperances": 441, + "totalSent": 6633.03268631, + "txApperances": 443, "transactions": [ "91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5", "f6e80d4fd1a2377406856c67d0cee5ac7e5120993ff97e617ca9aac33b4c6b1e", diff --git a/test/integration/utxo.json b/test/integration/utxo.json index b38e4f00..f45dfb69 100644 --- a/test/integration/utxo.json +++ b/test/integration/utxo.json @@ -7,10 +7,10 @@ "tx0amount": 0.38571339 }, { - "addr": "mgKY35SXqxFpcKK3Dq9mW9919N7wYXvcFM", - "length": 1, - "tx0id": "91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5", - "tx0scriptPubKey": "76a91408cf4ceb2b7278043fcc7f545e6e6e73ef9a644f88ac", - "tx0amount": 0.01979459 - } + "addr": "2N1pLkosf6o8Ciqs573iwwgVpuFS6NbNKx5", + "length": 13, + "tx0id": "b9cc61b55814a0f972788e9025db1013157f83716e08239026a156efe892a05c", + "tx0scriptPubKey": "a9145e0461e38796367580305e3615fc1b70e4c3307687", + "tx0amount": 0.001 + } ] diff --git a/util/sync.js b/util/sync.js index e3fe31d4..1cfccd7f 100755 --- a/util/sync.js +++ b/util/sync.js @@ -15,6 +15,7 @@ program .option('-D --destroy', 'Remove current DB (and start from there)', 0) .option('-S --startfile', 'Number of file from bitcoind to start(default=0)') .option('-R --rpc', 'Force sync with RPC') + .option('--stop [hash]', 'StopAt block',1) .option('-v --verbose', 'Verbose 0/1', 0) .parse(process.argv); @@ -30,10 +31,13 @@ async.series([ historicSync.sync.destroy(cb); }, function(cb) { - historicSync.start({ + var opts= { forceStartFile: program.startfile, forceRPC: program.rpc, - },cb); + stopAt: program.stop, + }; + console.log('[options]',opts); //TODO + historicSync.start(opts,cb); }, ], function(err) {