diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 80c6464..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -module.exports = function(grunt) { - - //Load NPM tasks - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-mocha-test'); - grunt.loadNpmTasks('grunt-nodemon'); - grunt.loadNpmTasks('grunt-concurrent'); - grunt.loadNpmTasks('grunt-env'); - grunt.loadNpmTasks('grunt-markdown'); - - // Project Configuration - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - watch: { - readme: { - files: ['README.md'], - tasks: ['markdown'] - }, - js: { - files: ['Gruntfile.js', 'insight.js', 'app/**/*.js'], - options: { - livereload: true, - }, - }, - test: { - files: ['test/**/*.js', 'test/*.js','app/**/*.js'], - tasks: ['test'], - } - }, - jshint: { - all: { - src: ['Gruntfile.js', 'insight.js', 'app/**/*.js', 'lib/*.js', 'config/*.js'], - options: { - jshintrc: true - } - } - }, - mochaTest: { - options: { - reporter: 'spec', - }, - src: ['test/**/*.js'], - }, - nodemon: { - dev: { - script: 'insight.js', - options: { - args: [], - ignore: ['test/**/*', 'util/**/*', 'dev-util/**/*'], - // nodeArgs: ['--debug'], - delayTime: 1, - env: { - PORT: 3000 - }, - cwd: __dirname - } - } - }, - concurrent: { - tasks: ['nodemon', 'watch'], - options: { - logConcurrentOutput: true - } - }, - env: { - test: { - NODE_ENV: 'test' - } - }, - markdown: { - all: { - files: [ - { - expand: true, - src: 'README.md', - dest: '.', - ext: '.html' - } - ] - } - } - }); - - //Making grunt default to force in order not to break the project. - grunt.option('force', true); - - //Default task(s). - grunt.registerTask('default', ['concurrent']); - - //Test task. - grunt.registerTask('test', ['env:test', 'mochaTest']); -}; diff --git a/README.md b/README.md index 046f553..2f9db63 100644 --- a/README.md +++ b/README.md @@ -1,184 +1,23 @@ +# Insight API -# *insight API* +A Bitcoin blockchain REST and web socket API service for [Bitcore Node](https://github.com/bitpay/bitcore-node). -*insight API* is an open-source bitcoin blockchain REST -and websocket API. Insight API runs in NodeJS and uses LevelDB for storage. - -This is a backend-only service. If you're looking for the web frontend application, -take a look at https://github.com/bitpay/insight. - -*Insight API* allows to develop bitcoin-related applications (such as wallets) that -require certain information from the blockchain that bitcoind does not provide. - -A blockchain explorer front-end has been developed on top of *Insight API*. It can -be downloaded at [Github Insight Repository](https://github.com/bitpay/insight). - -## Warning - Insight file sync does not work with **bitcoind** v0.10 - In order to use Insigtht you must set the environment variable INSIGHT_FORCE_RPC_SYNC = 1 - We are working on `bitcore-node` to replace Insight-api. Check `bitcore-node` on [github](https://github.com/bitpay/bitcore-node). +This is a backend-only service. If you're looking for the web frontend application, take a look at https://github.com/bitpay/insight. ## Prerequisites -* **bitcoind** - Download and Install [Bitcoin](http://bitcoin.org/en/download) +- [Bitcore Node 0.2.x](https://github.com/bitpay/bitcore-node) -*insight API* needs a *trusted* bitcoind node to run. *insight API* will connect to the node -through the RPC API, bitcoin peer-to-peer protocol, and will even read its raw block .dat files for syncing. - -Configure bitcoind to listen to RPC calls and set `txindex` to true. -The easiest way to do this is by copying `./etc/bitcoind/bitcoin.conf` to your -bitcoin data directory (usually `~/.bitcoin` on Linux, `%appdata%\Bitcoin\` on Windows, -or `~/Library/Application Support/Bitcoin` on Mac OS X). - -bitcoind must be running and must have finished downloading the blockchain **before** running *insight API*. - - -* **Node.js v0.10.x** - Download and Install [Node.js](http://www.nodejs.org/download/). - -* **NPM** - Node.js package manager, should be automatically installed when you get node.js. - - -## Quick Install - Check the Prerequisites section above before installing. - - To install Insight API, clone the main repository: - - $ git clone https://github.com/bitpay/insight-api && cd insight-api - - Install dependencies: - - $ npm install - - Run the main application: - - $ node insight.js - - Then open a browser and go to: - - http://localhost:3001 - - Please note that the app will need to sync its internal database - with the blockchain state, which may take some time. You can check - sync progress at http://localhost:3001/api/sync. - - -## Configuration - -All configuration is specified in the [config](config/) folder, particularly the [config.js](config/config.js) file. There you can specify your application name and database name. Certain configuration values are pulled from environment variables if they are defined: - -``` -BITCOIND_HOST # RPC bitcoind host -BITCOIND_PORT # RPC bitcoind Port -BITCOIND_P2P_HOST # P2P bitcoind Host (will default to BITCOIND_HOST, if specified) -BITCOIND_P2P_PORT # P2P bitcoind Port -BITCOIND_USER # RPC username -BITCOIND_PASS # RPC password -BITCOIND_DATADIR # bitcoind datadir. 'testnet3' will be appended automatically if testnet is used. NEED to finish with '/'. e.g: `/vol/data/` -INSIGHT_NETWORK [= 'livenet' | 'testnet'] -INSIGHT_PORT # insight api port -INSIGHT_DB # Path where to store insight's internal DB. (defaults to $HOME/.insight) -INSIGHT_SAFE_CONFIRMATIONS=6 # Nr. of confirmation needed to start caching transaction information -INSIGHT_IGNORE_CACHE # True to ignore cache of spents in transaction, with more than INSIGHT_SAFE_CONFIRMATIONS confirmations. This is useful for tracking double spents for old transactions. -ENABLE_CURRENCYRATES # if "true" will enable a plugin to obtain historic conversion rates for various currencies -ENABLE_RATELIMITER # if "true" will enable the ratelimiter plugin -LOGGER_LEVEL # defaults to 'info', can be 'debug','verbose','error', etc. -ENABLE_HTTPS # if "true" it will server using SSL/HTTPS -ENABLE_EMAILSTORE # if "true" will enable a plugin to store data with a validated email address -INSIGHT_EMAIL_CONFIRM_HOST # Only meanfull if ENABLE_EMAILSTORE is enable. Hostname for the confirm URLs. E.g: 'https://insight.bitpay.com' - -``` - -Make sure that bitcoind is configured to [accept incoming connections using 'rpcallowip'](https://en.bitcoin.it/wiki/Running_Bitcoin). - -In case the network is changed (testnet to livenet or vice versa) levelDB database needs to be deleted. This can be performed running: -```util/sync.js -D``` and waiting for *insight* to synchronize again. Once the database is deleted, the sync.js process can be safely interrupted (CTRL+C) and continued from the synchronization process embedded in main app. - -## Synchronization - -The initial synchronization process scans the blockchain from the paired bitcoind server to update addresses and balances. *insight-api* needs exactly one trusted bitcoind node to run. This node must have finished downloading the blockchain before running *insight-api*. - -While *insight* is synchronizing the website can be accessed (the sync process is embedded in the webserver), but there may be missing data or incorrect balances for addresses. The 'sync' status is shown at the `/api/sync` endpoint. - -The blockchain can be read from bitcoind's raw `.dat` files or RPC interface. -Reading the information from the `.dat` files is much faster so it's the -recommended (and default) alternative. `.dat` files are scanned in the default -location for each platform (for example, `~/.bitcoin` on Linux). In case a -non-standard location is used, it needs to be defined (see the Configuration section). -As of June 2014, using `.dat` files the sync process takes 9 hrs. -for livenet and 30 mins. for testnet. - -While synchronizing the blockchain, *insight-api* listens for new blocks and -transactions relayed by the bitcoind node. Those are also stored on *insight-api*'s database. -In case *insight-api* is shutdown for a period of time, restarting it will trigger -a partial (historic) synchronization of the blockchain. Depending on the size of -that synchronization task, a reverse RPC or forward `.dat` syncing strategy will be used. - -If bitcoind is shutdown, *insight-api* needs to be stopped and restarted -once bitcoind is restarted. - -### Syncing old blockchain data manually - - Old blockchain data can be manually synced issuing: - - $ util/sync.js - - Check util/sync.js --help for options, particulary -D to erase the current DB. - - *NOTE*: there is no need to run this manually since the historic synchronization - is built in into the web application. Running *insight-api* normally will trigger - the historic sync automatically. - - -### DB storage requirement - -To store the blockchain and address related information, *insight-api* uses LevelDB. -Two DBs are created: txs and blocks. By default these are stored on - - ``~/.insight/`` - -Please note that some older versions of Insight-API store that on `/db`. - -This can be changed at config/config.js. As of June 2014, storing the livenet blockchain takes ~35GB of disk space (2GB for the testnet). - -## Development - -To run insight locally for development with grunt: - -```$ NODE_ENV=development grunt``` - -To run the tests - -```$ grunt test``` - - -Contributions and suggestions are welcome at [insight-api github repository](https://github.com/bitpay/insight-api). - -## Caching schema - -Since v0.2 a new cache schema has been introduced. Only information from transactions with -INSIGHT_SAFE_CONFIRMATIONS settings will be cached (by default SAFE_CONFIRMATIONS=6). There -are 3 different caches: - * Number of confirmations - * Transaction output spent/unspent status - * scriptPubKey for unspent transactions - -Cache data is only populated on request, i.e., only after accessing the required data for -the first time, the information is cached, there is not pre-caching procedure. To ignore -cache by default, use INSIGHT_IGNORE_CACHE. Also, address related calls support `?noCache=1` -to ignore the cache in a particular API request. - -## API - -By default, insight provides a REST API at `/api`, but this prefix is configurable from the var `apiPrefix` in the `config.js` file. - -The end-points are: +**Note:** You can use an existing Bitcoin data directory, however `txindex` needs to be set to true in `bitcoin.conf`. +## API HTTP Endpoints ### Block ``` /api/block/[:hash] /api/block/00000000a967199a2fad0877433c93df785a8d8ce062e5f9b451cd1397bdbf62 ``` + ### Block index Get block hash by height ``` @@ -198,11 +37,13 @@ which is the hash of the Genesis block (0 height) /api/raw/[:rawid] /api/raw/525de308971eabd941b139f46c7198b5af9479325c2395db7f2fb5ae8562556c ``` + ### Address ``` /api/addr/[:addr][?noTxList=1&noCache=1] /api/addr/mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5?noTxList=1 ``` + ### Address Properties ``` /api/addr/[:addr]/balance @@ -211,6 +52,7 @@ which is the hash of the Genesis block (0 height) /api/addr/[:addr]/unconfirmedBalance ``` The response contains the value in Satoshis. + ### Unspent Outputs ``` /api/addr/[:addr]/utxo[?noCache=1] @@ -320,7 +162,6 @@ Sample output: Note: if pagination params are not specified, the result is an array of transactions. - ### Transaction broadcasting POST method: ``` diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js deleted file mode 100644 index 425602b..0000000 --- a/app/controllers/addresses.js +++ /dev/null @@ -1,284 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ - -var _ = require('lodash'); -var Address = require('../models/Address'); -var common = require('./common'); -var async = require('async'); - -var MAX_BATCH_SIZE = 100; -var RPC_CONCURRENCY = 5; - -var tDb = require('../../lib/TransactionDb').default(); - -var checkSync = function(req, res) { - if (req.historicSync) { - var i = req.historicSync.info() - if (i.status !== 'finished') { - common.notReady(req, res, i.syncPercentage); - return false; - } - } - return true; -}; - - -var getAddr = function(req, res, next) { - var a; - try { - var addr = req.param('addr'); - a = new Address(addr); - } catch (e) { - common.handleErrors({ - message: 'Invalid address:' + e.message, - code: 1 - }, res, next); - return null; - } - return a; -}; - -var getAddrs = function(req, res, next) { - var as = []; - try { - var addrStrs = req.param('addrs'); - var s = addrStrs.split(','); - if (s.length === 0) return as; - for (var i = 0; i < s.length; i++) { - var a = new Address(s[i]); - as.push(a); - } - } catch (e) { - common.handleErrors({ - message: 'Invalid addrs param:' + e.message, - code: 1 - }, res, next); - return null; - } - return as; -}; - -exports.show = function(req, res, next) { - if (!checkSync(req, res)) return; - var a = getAddr(req, res, next); - - if (a) { - a.update(function(err) { - if (err) { - return common.handleErrors(err, res); - } else { - return res.jsonp(a.getObj()); - } - }, { - txLimit: req.query.noTxList ? 0 : -1, - ignoreCache: req.param('noCache') - }); - } -}; - - - -exports.utxo = function(req, res, next) { - if (!checkSync(req, res)) return; - - var a = getAddr(req, res, next); - if (a) { - a.update(function(err) { - if (err) - return common.handleErrors(err, res); - else { - return res.jsonp(a.unspent); - } - }, { - onlyUnspent: 1, - ignoreCache: req.param('noCache') - }); - } -}; - -exports.multiutxo = function(req, res, next) { - if (!checkSync(req, res)) return; - var as = getAddrs(req, res, next); - if (as) { - var utxos = []; - async.eachLimit(as, RPC_CONCURRENCY, function(a, callback) { - a.update(function(err) { - if (err) callback(err); - utxos = utxos.concat(a.unspent); - callback(); - }, { - onlyUnspent: 1, - ignoreCache: req.param('noCache') - }); - }, function(err) { // finished callback - if (err) return common.handleErrors(err, res); - res.jsonp(utxos); - }); - } -}; - -exports.multitxs = function(req, res, next) { - if (!checkSync(req, res)) return; - - function processTxs(txs, from, to, cb) { - txs = _.uniq(_.flatten(txs), 'txid'); - var nbTxs = txs.length; - - if (_.isUndefined(from) && _.isUndefined(to)) { - from = 0; - to = MAX_BATCH_SIZE; - } - if (!_.isUndefined(from) && _.isUndefined(to)) - to = from + MAX_BATCH_SIZE; - - if (!_.isUndefined(from) && !_.isUndefined(to) && to - from > MAX_BATCH_SIZE) - to = from + MAX_BATCH_SIZE; - - if (from < 0) from = 0; - if (to < 0) to = 0; - if (from > nbTxs) from = nbTxs; - if (to > nbTxs) to = nbTxs; - - txs.sort(function(a, b) { - var b = (b.firstSeenTs || b.ts)+ b.txid; - var a = (a.firstSeenTs || a.ts)+ a.txid; - if (a > b) return -1; - if (a < b) return 1; - return 0; - }); - txs = txs.slice(from, to); - - var txIndex = {}; - _.each(txs, function(tx) { - txIndex[tx.txid] = tx; - }); - - async.eachLimit(txs, RPC_CONCURRENCY, function(tx2, callback) { - tDb.fromIdWithInfo(tx2.txid, function(err, tx) { - if (err) { - console.log(err); - return common.handleErrors(err, res); - } - if (tx && tx.info) { - - if (tx2.firstSeenTs) - tx.info.firstSeenTs = tx2.firstSeenTs; - - txIndex[tx.txid].info = tx.info; - } else { - // TX no longer available - txIndex[tx2.txid].info = { - txid: tx2.txid, - possibleDoubleSpend: true, - firstSeenTs: tx2.firstSeenTs, - }; - } - - callback(); - }); - }, function(err) { - if (err) return cb(err); - - // It could be that a txid is stored at an address but it is - // no longer at bitcoind (for example a double spend) - - var transactions = _.compact(_.pluck(txs, 'info')); - transactions = { - totalItems: nbTxs, - from: +from, - to: +to, - items: transactions, - }; - return cb(null, transactions); - }); - }; - - var from = req.param('from'); - var to = req.param('to'); - - var as = getAddrs(req, res, next); - if (as) { - var txs = []; - async.eachLimit(as, RPC_CONCURRENCY, function(a, callback) { - a.update(function(err) { - if (err) callback(err); - - txs.push(a.transactions); - callback(); - }, { - ignoreCache: req.param('noCache'), - includeTxInfo: true, - }); - }, function(err) { // finished callback - if (err) return common.handleErrors(err, res); - - processTxs(txs, from, to, function(err, transactions) { - if (err) return common.handleErrors(err, res); - res.jsonp(transactions); - }); - }); - } -}; - -exports.balance = function(req, res, next) { - if (!checkSync(req, res)) return; - var a = getAddr(req, res, next); - if (a) - a.update(function(err) { - if (err) { - return common.handleErrors(err, res); - } else { - return res.jsonp(a.balanceSat); - } - }, { - ignoreCache: req.param('noCache') - }); -}; - -exports.totalReceived = function(req, res, next) { - if (!checkSync(req, res)) return; - var a = getAddr(req, res, next); - if (a) - a.update(function(err) { - if (err) { - return common.handleErrors(err, res); - } else { - return res.jsonp(a.totalReceivedSat); - } - }, { - ignoreCache: req.param('noCache') - }); -}; - -exports.totalSent = function(req, res, next) { - if (!checkSync(req, res)) return; - var a = getAddr(req, res, next); - if (a) - a.update(function(err) { - if (err) { - return common.handleErrors(err, res); - } else { - return res.jsonp(a.totalSentSat); - } - }, { - ignoreCache: req.param('noCache') - }); -}; - -exports.unconfirmedBalance = function(req, res, next) { - if (!checkSync(req, res)) return; - var a = getAddr(req, res, next); - if (a) - a.update(function(err) { - if (err) { - return common.handleErrors(err, res); - } else { - return res.jsonp(a.unconfirmedBalanceSat); - } - }, { - ignoreCache: req.param('noCache') - }); -}; diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js deleted file mode 100644 index 2478812..0000000 --- a/app/controllers/blocks.js +++ /dev/null @@ -1,173 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ -var common = require('./common'); -var async = require('async'); -var bdb = require('../../lib/BlockDb').default(); -var tdb = require('../../lib/TransactionDb').default(); - -/** - * Find block by hash ... - */ -exports.block = function(req, res, next, hash) { - bdb.fromHashWithInfo(hash, function(err, block) { - if (err || !block) - return common.handleErrors(err, res, next); - else { - tdb.getPoolInfo(block.info.tx[0], function(info) { - block.info.poolInfo = info; - req.block = block.info; - return next(); - }); - } - }); -}; - - -/** - * Show block - */ -exports.show = function(req, res) { - if (req.block) { - res.jsonp(req.block); - } -}; - -/** - * Show block by Height - */ -exports.blockindex = function(req, res, next, height) { - bdb.blockIndex(height, function(err, hashStr) { - if (err) { - console.log(err); - res.status(400).send('Bad Request'); // TODO - } else { - res.jsonp(hashStr); - } - }); -}; - -var getBlock = function(blockhash, cb) { - bdb.fromHashWithInfo(blockhash, function(err, block) { - if (err) { - console.log(err); - return cb(err); - } - - // TODO - if (!block.info) { - console.log('Could not get %s from RPC. Orphan? Error?', blockhash); //TODO - // Probably orphan - block.info = { - hash: blockhash, - isOrphan: 1, - }; - } - - tdb.getPoolInfo(block.info.tx[0], function(info) { - block.info.poolInfo = info; - return cb(err, block.info); - }); - - }); -}; - -/** - * List of blocks by date - */ - -var DFLT_LIMIT=200; - // in testnet, this number is much bigger, we dont support - // exploring blocks by date. - -exports.list = function(req, res) { - var isToday = false; - - //helper to convert timestamps to yyyy-mm-dd format - var formatTimestamp = function(date) { - var yyyy = date.getUTCFullYear().toString(); - var mm = (date.getUTCMonth() + 1).toString(); // getMonth() is zero-based - var dd = date.getUTCDate().toString(); - - return yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]); //padding - }; - - var dateStr; - var todayStr = formatTimestamp(new Date()); - - if (req.query.blockDate) { - // TODO: Validate format yyyy-mm-dd - dateStr = req.query.blockDate; - isToday = dateStr === todayStr; - } else { - dateStr = todayStr; - isToday = true; - } - var gte = Math.round((new Date(dateStr)).getTime() / 1000); - - //pagination - var lte = parseInt(req.query.startTimestamp) || gte + 86400; - var prev = formatTimestamp(new Date((gte - 86400) * 1000)); - var next = lte ? formatTimestamp(new Date(lte * 1000)) :null; - var limit = parseInt(req.query.limit || DFLT_LIMIT) + 1; - var more; - - bdb.getBlocksByDate(gte, lte, limit, function(err, blockList) { - - if (err) { - res.status(500).send(err); - } else { - var l = blockList.length; - - if (l===limit) { - more = true; - blockList.pop; - } - - var moreTs=lte; - async.mapSeries(blockList, - function(b, cb) { - getBlock(b.hash, function(err, info) { - if (err) { - console.log(err); - return cb(err); - } - if (b.ts < moreTs) moreTs = b.ts; - return cb(err, { - height: info.height, - size: info.size, - hash: b.hash, - time: b.ts || info.time, - txlength: info.tx.length, - poolInfo: info.poolInfo - }); - }); - }, function(err, allblocks) { - - // sort blocks by height - allblocks.sort( - function compare(a,b) { - if (a.height < b.height) return 1; - if (a.height > b.height) return -1; - return 0; - }); - - res.jsonp({ - blocks: allblocks, - length: allblocks.length, - pagination: { - next: next, - prev: prev, - currentTs: lte - 1, - current: dateStr, - isToday: isToday, - more: more, - moreTs: moreTs, - } - }); - }); - } - }); -}; diff --git a/app/controllers/currency.js b/app/controllers/currency.js deleted file mode 100644 index 244ef32..0000000 --- a/app/controllers/currency.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -var config = require('../../config/config'); - -// Set the initial vars -var timestamp = +new Date(), - delay = config.currencyRefresh * 60000, - bitstampRate = 0; - -exports.index = function(req, res) { - - var _xhr = function() { - if (typeof XMLHttpRequest !== 'undefined' && XMLHttpRequest !== null) { - return new XMLHttpRequest(); - } else if (typeof require !== 'undefined' && require !== null) { - var XMLhttprequest = require('xmlhttprequest').XMLHttpRequest; - return new XMLhttprequest(); - } - }; - - var _request = function(url, cb) { - var request; - request = _xhr(); - request.open('GET', url, true); - request.onreadystatechange = function() { - if (request.readyState === 4) { - if (request.status === 200) { - return cb(false, request.responseText); - } - - return cb(true, { - status: request.status, - message: 'Request error' - }); - } - }; - - return request.send(null); - }; - - // Init - var currentTime = +new Date(); - if (bitstampRate === 0 || currentTime >= (timestamp + delay)) { - timestamp = currentTime; - - _request('https://www.bitstamp.net/api/ticker/', function(err, data) { - if (!err) bitstampRate = parseFloat(JSON.parse(data).last); - - res.jsonp({ - status: 200, - data: { bitstamp: bitstampRate } - }); - }); - } else { - res.jsonp({ - status: 200, - data: { bitstamp: bitstampRate } - }); - } -}; diff --git a/app/controllers/index.js b/app/controllers/index.js deleted file mode 100644 index 1d2d435..0000000 --- a/app/controllers/index.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -var config = require('../../config/config'); - -var _getVersion = function() { - var pjson = require('../../package.json'); - return pjson.version; -}; - -exports.render = function(req, res) { - - if (config.publicPath) { - return res.sendfile(config.publicPath + '/index.html'); - } - else { - var version = _getVersion(); - res.send('insight API v' + version); - } -}; - -exports.version = function(req, res) { - var version = _getVersion(); - res.json({ - version: version - }); -}; diff --git a/app/controllers/messages.js b/app/controllers/messages.js deleted file mode 100644 index 5c2fbfc..0000000 --- a/app/controllers/messages.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -var common = require('./common'); -var Rpc = require('../../lib/Rpc'); - - -exports.verify = function(req, res) { - var address = req.param('address'), - signature = req.param('signature'), - message = req.param('message'); - - if(typeof(address) == 'undefined' - || typeof(signature) == 'undefined' - || typeof(message) == 'undefined') { - return common.handleErrors({ - message: 'Missing parameters (expected "address", "signature" and "message")', - code: 1 - }, res); - } - - Rpc.verifyMessage(address, signature, message, function(err, result) { - if (err) { - return common.handleErrors(err, res); - } - res.json({'result' : result}); - }); -}; diff --git a/app/controllers/socket.js b/app/controllers/socket.js deleted file mode 100644 index 140e6d6..0000000 --- a/app/controllers/socket.js +++ /dev/null @@ -1,80 +0,0 @@ -'use strict'; - -// server-side socket behaviour -var ios = null; // io is already taken in express -var util = require('bitcore').util; -var logger = require('../../lib/logger').logger; - -module.exports.init = function(io_ext) { - ios = io_ext; - if (ios) { - // when a new socket connects - ios.sockets.on('connection', function(socket) { - logger.verbose('New connection from ' + socket.id); - // when it subscribes, make it join the according room - socket.on('subscribe', function(topic) { - logger.debug('subscribe to ' + topic); - socket.join(topic); - socket.emit('subscribed'); - }); - - // disconnect handler - socket.on('disconnect', function() { - logger.verbose('disconnected ' + socket.id); - }); - - }); - } - return ios; -}; - -var simpleTx = function(tx) { - return { - txid: tx - }; -}; - -var fullTx = function(tx) { - var t = { - txid: tx.txid, - size: tx.size, - }; - // Outputs - var valueOut = 0; - tx.vout.forEach(function(o) { - valueOut += o.valueSat; - }); - - t.valueOut = (valueOut.toFixed(8) / util.COIN); - try { - t.vout = tx.vout.map(function(o) { - var r = {}; - r[o.scriptPubKey.addresses] = o.valueSat; - return r; - }); - } catch (e) {}; - return t; -}; - -module.exports.broadcastTx = function(tx) { - if (ios) { - var t = (typeof tx === 'string') ? simpleTx(tx) : fullTx(tx); - ios.sockets.in('inv').emit('tx', t); - } -}; - -module.exports.broadcastBlock = function(block) { - if (ios) - ios.sockets.in('inv').emit('block', block); -}; - -module.exports.broadcastAddressTx = function(txid, address) { - if (ios) { - ios.sockets.in(address).emit(address, txid); - } -}; - -module.exports.broadcastSyncInfo = function(historicSync) { - if (ios) - ios.sockets.in('sync').emit('status', historicSync); -}; diff --git a/app/controllers/status.js b/app/controllers/status.js deleted file mode 100644 index b6feb25..0000000 --- a/app/controllers/status.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ - -var Status = require('../models/Status'), - common = require('./common'); - -/** - * Status - */ -exports.show = function(req, res) { - - var option = req.query.q; - var statusObject = new Status(); - - var returnJsonp = function (err) { - if (err || ! statusObject) - return common.handleErrors(err, res); - else { - res.jsonp(statusObject); - } - }; - - switch(option) { - case 'getDifficulty': - statusObject.getDifficulty(returnJsonp); - break; - case 'getTxOutSetInfo': - statusObject.getTxOutSetInfo(returnJsonp); - break; - case 'getLastBlockHash': - statusObject.getLastBlockHash(returnJsonp); - break; - case 'getBestBlockHash': - statusObject.getBestBlockHash(returnJsonp); - break; - case 'getInfo': - default: - statusObject.getInfo(returnJsonp); - } -}; - -exports.sync = function(req, res) { - if (req.historicSync) - res.jsonp(req.historicSync.info()); -}; - -exports.peer = function(req, res) { - if (req.peerSync) { - var info = req.peerSync.info(); - res.jsonp(info); - } -}; diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js deleted file mode 100644 index bb16219..0000000 --- a/app/controllers/transactions.js +++ /dev/null @@ -1,197 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ -var Address = require('../models/Address'); -var async = require('async'); -var common = require('./common'); -var util = require('util'); - -var Rpc = require('../../lib/Rpc'); - -var imports = require('soop').imports(); -var bitcore = require('bitcore'); -var RpcClient = bitcore.RpcClient; -var config = require('../../config/config'); -var bitcoreRpc = imports.bitcoreRpc || new RpcClient(config.bitcoind); - -var tDb = require('../../lib/TransactionDb').default(); -var bdb = require('../../lib/BlockDb').default(); - -exports.send = function(req, res) { - Rpc.sendRawTransaction(req.body.rawtx, function(err, txid) { - if (err) { - var message; - if(err.code == -25) { - message = util.format( - 'Generic error %s (code %s)', - err.message, err.code); - } else if(err.code == -26) { - message = util.format( - 'Transaction rejected by network (code %s). Reason: %s', - err.code, err.message); - } else { - message = util.format('%s (code %s)', err.message, err.code); - } - return res.status(400).send(message); - } - res.json({'txid' : txid}); - }); -}; - -exports.rawTransaction = function (req, res, next, txid) { - bitcoreRpc.getRawTransaction(txid, function (err, transaction) { - if (err || !transaction) - return common.handleErrors(err, res); - else { - req.rawTransaction = { 'rawtx': transaction.result }; - return next(); - } - }); -}; - -/** - * Find transaction by hash ... - */ -exports.transaction = function(req, res, next, txid) { - - tDb.fromIdWithInfo(txid, function(err, tx) { - if (err || ! tx) - return common.handleErrors(err, res); - - bdb.fillVinConfirmations(tx.info, function(err) { - if (err) - return common.handleErrors(err, res); - - req.transaction = tx.info; - return next(); - }); - - }); -}; - - -/** - * Show transaction - */ -exports.show = function(req, res) { - - if (req.transaction) { - res.jsonp(req.transaction); - } -}; - -/** - * Show raw transaction - */ -exports.showRaw = function(req, res) { - - if (req.rawTransaction) { - res.jsonp(req.rawTransaction); - } -}; - - -var getTransaction = function(txid, cb) { - - tDb.fromIdWithInfo(txid, function(err, tx) { - if (err) console.log(err); - - if (!tx || !tx.info) { - console.log('[transactions.js.48]:: TXid %s not found in RPC. CHECK THIS.', txid); - return ({ txid: txid }); - } - - return cb(null, tx.info); - }); -}; - - -/** - * List of transaction - */ -exports.list = function(req, res, next) { - var bId = req.query.block; - var addrStr = req.query.address; - var page = req.query.pageNum; - var pageLength = 10; - var pagesTotal = 1; - var txLength; - var txs; - - if (bId) { - bdb.fromHashWithInfo(bId, function(err, block) { - if (err) { - console.log(err); - return res.status(500).send('Internal Server Error'); - } - - if (! block) { - return res.status(404).send('Not found'); - } - - txLength = block.info.tx.length; - - if (page) { - var spliceInit = page * pageLength; - txs = block.info.tx.splice(spliceInit, pageLength); - pagesTotal = Math.ceil(txLength / pageLength); - } - else { - txs = block.info.tx; - } - - async.mapSeries(txs, getTransaction, function(err, results) { - if (err) { - console.log(err); - res.status(404).send('TX not found'); - } - - res.jsonp({ - pagesTotal: pagesTotal, - txs: results - }); - }); - }); - } - else if (addrStr) { - var a = new Address(addrStr); - - a.update(function(err) { - if (err && !a.totalReceivedSat) { - console.log(err); - res.status(404).send('Invalid address'); - return next(); - } - - txLength = a.transactions.length; - - if (page) { - var spliceInit = page * pageLength; - txs = a.transactions.splice(spliceInit, pageLength); - pagesTotal = Math.ceil(txLength / pageLength); - } - else { - txs = a.transactions; - } - - async.mapSeries(txs, getTransaction, function(err, results) { - if (err) { - console.log(err); - res.status(404).send('TX not found'); - } - - res.jsonp({ - pagesTotal: pagesTotal, - txs: results - }); - }); - }); - } - else { - res.jsonp({ - txs: [] - }); - } -}; diff --git a/app/controllers/utils.js b/app/controllers/utils.js deleted file mode 100644 index 63ca715..0000000 --- a/app/controllers/utils.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ - -var _ = require('lodash'); - -var Utils = require('../models/Utils'); -var common = require('./common'); - -exports.estimateFee = function(req, res) { - var args = req.query.nbBlocks || '2'; - var nbBlocks = args.split(','); - - var utilsObject = new Utils(); - utilsObject.estimateFee(nbBlocks, function(err, fees) { - if (err) return common.handleErrors(err, res); - res.jsonp(fees); - }); -}; diff --git a/app/models/Address.js b/app/models/Address.js deleted file mode 100644 index 780daf7..0000000 --- a/app/models/Address.js +++ /dev/null @@ -1,216 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); -var _ = require('lodash'); -var async = require('async'); -var bitcore = require('bitcore'); -var BitcoreAddress = bitcore.Address; -var BitcoreTransaction = bitcore.Transaction; -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) { - this.balanceSat = 0; - this.totalReceivedSat = 0; - this.totalSentSat = 0; - - this.unconfirmedBalanceSat = 0; - - this.txApperances = 0; - this.unconfirmedTxApperances = 0; - this.seen = {}; - - // TODO store only txids? +index? +all? - this.transactions = []; - this.unspent = []; - - var a = new BitcoreAddress(addrStr); - a.validate(); - this.addrStr = addrStr; - - Object.defineProperty(this, 'totalSent', { - get: function() { - return parseFloat(this.totalSentSat) / parseFloat(BitcoreUtil.COIN); - }, - set: function(i) { - this.totalSentSat = i * BitcoreUtil.COIN; - }, - enumerable: 1, - }); - - Object.defineProperty(this, 'balance', { - get: function() { - return parseFloat(this.balanceSat) / parseFloat(BitcoreUtil.COIN); - }, - set: function(i) { - this.balance = i * BitcoreUtil.COIN; - }, - enumerable: 1, - }); - - Object.defineProperty(this, 'totalReceived', { - get: function() { - return parseFloat(this.totalReceivedSat) / parseFloat(BitcoreUtil.COIN); - }, - set: function(i) { - this.totalReceived = i * BitcoreUtil.COIN; - }, - enumerable: 1, - }); - - - Object.defineProperty(this, 'unconfirmedBalance', { - get: function() { - return parseFloat(this.unconfirmedBalanceSat) / parseFloat(BitcoreUtil.COIN); - }, - set: function(i) { - this.unconfirmedBalanceSat = i * BitcoreUtil.COIN; - }, - enumerable: 1, - }); - -} - -Address.prototype.getObj = function() { - // Normalize json address - return { - 'addrStr': this.addrStr, - 'balance': this.balance, - 'balanceSat': this.balanceSat, - 'totalReceived': this.totalReceived, - 'totalReceivedSat': this.totalReceivedSat, - 'totalSent': this.totalSent, - 'totalSentSat': this.totalSentSat, - 'unconfirmedBalance': this.unconfirmedBalance, - 'unconfirmedBalanceSat': this.unconfirmedBalanceSat, - 'unconfirmedTxApperances': this.unconfirmedTxApperances, - 'txApperances': this.txApperances, - 'transactions': this.transactions - }; -}; - -Address.prototype._addTxItem = function(txItem, txList, includeInfo) { - function addTx(data) { - if (!txList) return; - if (includeInfo) { - txList.push(data); - } else { - txList.push(data.txid); - } - }; - - var add = 0, - addSpend = 0; - var v = txItem.value_sat; - var seen = this.seen; - - // Founding tx - if (!seen[txItem.txid]) { - seen[txItem.txid] = 1; - add = 1; - - addTx({ - txid: txItem.txid, - ts: txItem.ts, - firstSeenTs: txItem.firstSeenTs, - }); - } - - // Spent tx - if (txItem.spentTxId && !seen[txItem.spentTxId]) { - addTx({ - 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; - } -}; - -// opts are -// .onlyUnspent -// .txLimit (=0 -> no txs, => -1 no limit) -// .includeTxInfo -// -Address.prototype.update = function(next, opts) { - var self = this; - if (!self.addrStr) return next(); - opts = opts || {}; - - if (!('ignoreCache' in opts)) - opts.ignoreCache = config.ignoreCache; - - // should collect txList from address? - var txList = opts.txLimit === 0 ? null : []; - - var tDb = TransactionDb; - var bDb = BlockDb; - tDb.fromAddr(self.addrStr, opts, function(err, txOut) { - if (err) return next(err); - - bDb.fillConfirmations(txOut, function(err) { - if (err) return next(err); - - tDb.cacheConfirmations(txOut, function(err) { - // console.log('[Address.js.161:txOut:]',txOut); //TODO - if (err) return next(err); - if (opts.onlyUnspent) { - txOut = txOut.filter(function(x) { - return !x.spentTxId; - }); - tDb.fillScriptPubKey(txOut, function() { - //_.filter will filterout unspend without scriptPubkey - //(probably from double spends) - self.unspent = _.filter(txOut.map(function(x) { - return { - address: self.addrStr, - 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, - confirmationsFromCache: !!x.isConfirmedCached, - }; - }), 'scriptPubKey');; - return next(); - }); - } else { - txOut.forEach(function(txItem) { - self._addTxItem(txItem, txList, opts.includeTxInfo); - }); - if (txList) - self.transactions = txList; - return next(); - } - }); - }); - }); -}; - -module.exports = require('soop')(Address); diff --git a/app/models/Status.js b/app/models/Status.js deleted file mode 100644 index ffb744a..0000000 --- a/app/models/Status.js +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; -//var imports = require('soop').imports(); - -var async = require('async'); -var bitcore = require('bitcore'); -var RpcClient = bitcore.RpcClient; -var config = require('../../config/config'); -var rpc = new RpcClient(config.bitcoind); -var bDb = require('../../lib/BlockDb').default(); - -function Status() {} - -Status.prototype.getInfo = function(next) { - var that = this; - async.series([ - function (cb) { - rpc.getInfo(function(err, info){ - if (err) return cb(err); - - that.info = info.result; - return cb(); - }); - }, - ], function (err) { - return next(err); - }); -}; - -Status.prototype.getDifficulty = function(next) { - var that = this; - async.series([ - function (cb) { - rpc.getDifficulty(function(err, df){ - if (err) return cb(err); - - that.difficulty = df.result; - return cb(); - }); - } - ], function (err) { - return next(err); - }); -}; - -Status.prototype.getTxOutSetInfo = function(next) { - var that = this; - async.series([ - function (cb) { - rpc.getTxOutSetInfo(function(err, txout){ - if (err) return cb(err); - - that.txoutsetinfo = txout.result; - return cb(); - }); - } - ], function (err) { - return next(err); - }); -}; - -Status.prototype.getBestBlockHash = function(next) { - var that = this; - async.series([ - function (cb) { - rpc.getBestBlockHash(function(err, bbh){ - if (err) return cb(err); - - that.bestblockhash = bbh.result; - return cb(); - }); - }, - - ], function (err) { - return next(err); - }); -}; - -Status.prototype.getLastBlockHash = function(next) { - var that = this; - bDb.getTip(function(err,tip) { - that.syncTipHash = tip; - async.waterfall( - [ - function(callback){ - rpc.getBlockCount(function(err, bc){ - if (err) return callback(err); - callback(null, bc.result); - }); - }, - function(bc, callback){ - rpc.getBlockHash(bc, function(err, bh){ - if (err) return callback(err); - callback(null, bh.result); - }); - } - ], - function (err, result) { - that.lastblockhash = result; - return next(); - } - ); - }); -}; - -module.exports = require('soop')(Status); diff --git a/app/models/Utils.js b/app/models/Utils.js deleted file mode 100644 index 9f9e884..0000000 --- a/app/models/Utils.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; -//var imports = require('soop').imports(); -var _ = require('lodash'); -var async = require('async'); - -var bitcore = require('bitcore'); -var RpcClient = bitcore.RpcClient; -var config = require('../../config/config'); -var rpc = new RpcClient(config.bitcoind); - -function Utils() {} - -Utils.prototype.estimateFee = function(nbBlocks, cb) { - var that = this; - - async.map([].concat(nbBlocks), function(n, next) { - rpc.estimateFee(+n, function(err, info) { - return next(err, [n, info.result]); - }); - }, function(err, result) { - if (err) return cb(err); - return cb(null, _.zipObject(result)); - }); -}; - -module.exports = require('soop')(Utils); diff --git a/bitcore-node/common.js b/bitcore-node/common.js deleted file mode 100644 index d7fb9af..0000000 --- a/bitcore-node/common.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -exports.notReady = function (err, res, p) { - res.status(503).send('Server not yet ready. Sync Percentage:' + p); -}; - -exports.handleErrors = function (err, res) { - if (err) { - if (err.code) { - res.status(400).send(err.message + '. Code:' + err.code); - } - else { - res.status(503).send(err.message); - } - } - else { - res.status(404).send('Not found'); - } -}; diff --git a/config/config.js b/config/config.js deleted file mode 100644 index 96402b4..0000000 --- a/config/config.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict'; - -var path = require('path'); -var fs = require('fs'); -var mkdirp = require('mkdirp'); - -var rootPath = path.normalize(__dirname + '/..'), - env, - db, - port, - b_port, - p2p_port; - -var packageStr = fs.readFileSync(rootPath + '/package.json'); -var version = JSON.parse(packageStr).version; - - -function getUserHome() { - return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']; -} - -var home = process.env.INSIGHT_DB || (getUserHome() + '/.insight'); - -if (process.env.INSIGHT_NETWORK === 'livenet') { - env = 'livenet'; - db = home; - port = '3000'; - b_port = '8332'; - p2p_port = '8333'; -} else { - env = 'testnet'; - db = home + '/testnet'; - port = '3001'; - b_port = '18332'; - p2p_port = '18333'; -} -port = parseInt(process.env.INSIGHT_PORT) || port; - - -switch (process.env.NODE_ENV) { - case 'production': - env += ''; - break; - case 'test': - env += ' - test environment'; - break; - default: - env += ' - development'; - break; -} - -var network = process.env.INSIGHT_NETWORK || 'testnet'; -var forceRPCsync = process.env.INSIGHT_FORCE_RPC_SYNC; - -var dataDir = process.env.BITCOIND_DATADIR; -var isWin = /^win/.test(process.platform); -var isMac = /^darwin/.test(process.platform); -var isLinux = /^linux/.test(process.platform); -if (!dataDir) { - if (isWin) dataDir = '%APPDATA%\\Bitcoin\\'; - if (isMac) dataDir = process.env.HOME + '/Library/Application Support/Bitcoin/'; - if (isLinux) dataDir = process.env.HOME + '/.bitcoin/'; -} -dataDir += network === 'testnet' ? 'testnet3' : ''; - -var safeConfirmations = process.env.INSIGHT_SAFE_CONFIRMATIONS || 6; -var ignoreCache = process.env.INSIGHT_IGNORE_CACHE || 0; - - -var bitcoindConf = { - protocol: process.env.BITCOIND_PROTO || 'http', - user: process.env.BITCOIND_USER || 'user', - pass: process.env.BITCOIND_PASS || 'pass', - host: process.env.BITCOIND_HOST || '127.0.0.1', - port: process.env.BITCOIND_PORT || b_port, - p2pPort: process.env.BITCOIND_P2P_PORT || p2p_port, - p2pHost: process.env.BITCOIND_P2P_HOST || process.env.BITCOIND_HOST || '127.0.0.1', - dataDir: dataDir, - // DO NOT CHANGE THIS! - disableAgent: true -}; - -var enableRatelimiter = process.env.ENABLE_RATELIMITER === 'true'; -var enableEmailstore = process.env.ENABLE_EMAILSTORE === 'true'; -var loggerLevel = process.env.LOGGER_LEVEL || 'info'; -var enableHTTPS = process.env.ENABLE_HTTPS === 'true'; -var enableCurrencyRates = process.env.ENABLE_CURRENCYRATES === 'true'; - -if (!fs.existsSync(db)) { - mkdirp.sync(db); -} - -module.exports = { - enableRatelimiter: enableRatelimiter, - ratelimiter: require('../plugins/config-ratelimiter.js'), - enableEmailstore: enableEmailstore, - enableCurrencyRates: enableCurrencyRates, - currencyrates: require('../plugins/config-currencyrates'), - loggerLevel: loggerLevel, - enableHTTPS: enableHTTPS, - version: version, - root: rootPath, - publicPath: process.env.INSIGHT_PUBLIC_PATH || false, - appName: 'Insight ' + env, - apiPrefix: '/api', - port: port, - leveldb: db, - bitcoind: bitcoindConf, - network: network, - disableP2pSync: false, - disableHistoricSync: false, - poolMatchFile: rootPath + '/etc/minersPoolStrings.json', - - // Time to refresh the currency rate. In minutes - currencyRefresh: 10, - keys: { - segmentio: process.env.INSIGHT_SEGMENTIO_KEY - }, - safeConfirmations: safeConfirmations, // PLEASE NOTE THAT *FULL RESYNC* IS NEEDED TO CHANGE safeConfirmations - ignoreCache: ignoreCache, - forceRPCsync: forceRPCsync, -}; diff --git a/config/express.js b/config/express.js deleted file mode 100644 index 4689b6c..0000000 --- a/config/express.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ -var express = require('express'); -var config = require('./config'); -var path = require('path'); -var logger = require('../lib/logger').logger; - -module.exports = function(app, historicSync, peerSync) { - - - //custom middleware - var setHistoric = function(req, res, next) { - req.historicSync = historicSync; - next(); - }; - - var setPeer = function(req, res, next) { - req.peerSync = peerSync; - next(); - }; - - app.set('showStackError', true); - app.set('json spaces', 0); - - app.enable('jsonp callback'); - app.use(config.apiPrefix, setHistoric); - app.use(config.apiPrefix, setPeer); - app.use(require('morgan')(':remote-addr :date[iso] ":method :url" :status :res[content-length] :response-time ":user-agent" ')); - - app.use(express.json()); - app.use(express.urlencoded()); - app.use(express.methodOverride()); - app.use(express.compress()); - - if (config.enableEmailstore) { - var allowCopayCrossDomain = function(req, res, next) { - if ('OPTIONS' == req.method) { - res.send(200); - res.end(); - return; - } - next(); - } - app.use(allowCopayCrossDomain); - } - - if (config.publicPath) { - var staticPath = path.normalize(config.rootPath + '/../' + config.publicPath); - //IMPORTANT: for html5mode, this line must to be before app.router - app.use(express.static(staticPath)); - } - - app.use(function(req, res, next) { - app.locals.config = config; - next(); - }); - - //routes should be at the last - app.use(app.router); - - //Assume 404 since no middleware responded - app.use(function(req, res) { - res.status(404).jsonp({ - status: 404, - url: req.originalUrl, - error: 'Not found' - }); - }); -}; diff --git a/config/headers.js b/config/headers.js deleted file mode 100644 index 8cd9e73..0000000 --- a/config/headers.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -var logger = require('../lib/logger').logger; - -module.exports = function(app) { - - app.use(function(req, res, next) { - res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE'); - res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type,Authorization'); - res.setHeader('Access-Control-Expose-Headers', 'X-Email-Needs-Validation,X-Quota-Per-Item,X-Quota-Items-Limit,X-RateLimit-Limit,X-RateLimit-Remaining'); - next(); - }); -}; diff --git a/config/routes.js b/config/routes.js deleted file mode 100644 index 0b77446..0000000 --- a/config/routes.js +++ /dev/null @@ -1,85 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ -var config = require('./config'); - -module.exports = function(app) { - - var apiPrefix = config.apiPrefix; - - //Block routes - var blocks = require('../app/controllers/blocks'); - app.get(apiPrefix + '/blocks', blocks.list); - - - app.get(apiPrefix + '/block/:blockHash', blocks.show); - app.param('blockHash', blocks.block); - - app.get(apiPrefix + '/block-index/:height', blocks.blockindex); - app.param('height', blocks.blockindex); - - // Transaction routes - var transactions = require('../app/controllers/transactions'); - app.get(apiPrefix + '/tx/:txid', transactions.show); - app.param('txid', transactions.transaction); - app.get(apiPrefix + '/txs', transactions.list); - app.post(apiPrefix + '/tx/send', transactions.send); - - // Raw Routes - app.get(apiPrefix + '/rawtx/:txid', transactions.showRaw); - app.param('txid', transactions.rawTransaction); - - // Address routes - var addresses = require('../app/controllers/addresses'); - app.get(apiPrefix + '/addr/:addr', addresses.show); - app.get(apiPrefix + '/addr/:addr/utxo', addresses.utxo); - app.get(apiPrefix + '/addrs/:addrs/utxo', addresses.multiutxo); - app.post(apiPrefix + '/addrs/utxo', addresses.multiutxo); - app.get(apiPrefix + '/addrs/:addrs/txs', addresses.multitxs); - app.post(apiPrefix + '/addrs/txs', addresses.multitxs); - - // Address property routes - app.get(apiPrefix + '/addr/:addr/balance', addresses.balance); - app.get(apiPrefix + '/addr/:addr/totalReceived', addresses.totalReceived); - app.get(apiPrefix + '/addr/:addr/totalSent', addresses.totalSent); - app.get(apiPrefix + '/addr/:addr/unconfirmedBalance', addresses.unconfirmedBalance); - - // Status route - var st = require('../app/controllers/status'); - app.get(apiPrefix + '/status', st.show); - - app.get(apiPrefix + '/sync', st.sync); - app.get(apiPrefix + '/peer', st.peer); - - // Utils route - var utils = require('../app/controllers/utils'); - app.get(apiPrefix + '/utils/estimatefee', utils.estimateFee); - - // Currency - var currency = require('../app/controllers/currency'); - app.get(apiPrefix + '/currency', currency.index); - - // Email store plugin - if (config.enableEmailstore) { - var emailPlugin = require('../plugins/emailstore'); - app.get(apiPrefix + '/email/retrieve', emailPlugin.retrieve); - } - - // Currency rates plugin - if (config.enableCurrencyRates) { - var currencyRatesPlugin = require('../plugins/currencyrates'); - app.get(apiPrefix + '/rates/:code', currencyRatesPlugin.getRate); - } - - // Address routes - var messages = require('../app/controllers/messages'); - app.get(apiPrefix + '/messages/verify', messages.verify); - app.post(apiPrefix + '/messages/verify', messages.verify); - - //Home route - var index = require('../app/controllers/index'); - app.get(apiPrefix + '/version', index.version); - app.get('*', index.render); -}; diff --git a/dev-util/block-level.js b/dev-util/block-level.js deleted file mode 100755 index 559717f..0000000 --- a/dev-util/block-level.js +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node - -var - config = require('../config/config'), - levelup = require('levelup'); - - -db = levelup(config.leveldb + '/blocks'); - -db.createReadStream({start: 'b-'}) - .on('data', function (data) { -console.log('[block-level.js.11:data:]',data); //TODO - if (data==false) c++; - }) - .on('error', function (err) { - return cb(err); - }) - .on('close', function () { - return cb(null); - }) - .on('end', function () { - return cb(null); - }); - - diff --git a/dev-util/dbdump.js b/dev-util/dbdump.js deleted file mode 100644 index 64635f4..0000000 --- a/dev-util/dbdump.js +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env node -'use strict'; - - var levelup = require('levelup'); - - - -var dbPath = process.argv[2]; -var s = process.argv[3]; -console.log('DB: ',dbPath); //TODO - - - -var db = levelup(dbPath ); - - -db.createReadStream({start: s, end: s+'~'}) - .on('data', function (data) { - console.log(data.key + ' => ' + data.value); //TODO - }) - .on('error', function () { - }) - .on('end', function () { - }); - - diff --git a/dev-util/deleteWholeProfile.js b/dev-util/deleteWholeProfile.js deleted file mode 100644 index 3689309..0000000 --- a/dev-util/deleteWholeProfile.js +++ /dev/null @@ -1,21 +0,0 @@ -#!usr/bin/env node - -var email = process.argv[2]; - -if (!email) { - console.log('\tdeleteWholeProfile.js '); - process.exit(-1); -} - -console.log('\t Deleting email:', email, process.env.INSIGHT_NETWORK); - -var p = require('../plugins/emailstore'); - -p.init({}); - -p.deleteWholeProfile(email, function(err) { - if (err) - console.log('[err:]', err); - else - console.log('done'); -}); diff --git a/dev-util/explode_tx.js b/dev-util/explode_tx.js deleted file mode 100755 index f9849c2..0000000 --- a/dev-util/explode_tx.js +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var util = require('util'); -var mongoose= require('mongoose'), - config = require('../config/config'); - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var T = require('../app/models/TransactionOut'); - - -// var hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; -var hash = process.argv[2] || '6749762ae220c10705556799dcec9bb6a54a7b881eb4b961323a3363b00db518'; - - - - -mongoose.connect(config.db); - -mongoose.connection.on('error', function(err) { console.log(err); }); - - -mongoose.connection.on('open', function() { - - var b = new Buffer(hash,'hex'); - - T.createFromTxs([hash], function(err, ret) { - - console.log('Err:'); - console.log(err); - - - console.log('Ret:'); - console.log(util.inspect(ret,{depth:null})); - mongoose.connection.close(); - }); -}); - - - diff --git a/dev-util/find_ref.sh b/dev-util/find_ref.sh deleted file mode 100755 index 2656eb2..0000000 --- a/dev-util/find_ref.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -FIND='find'; - -##if [[ "$OSTYPE" =~ "darwin" ]] -##then -## FIND='gfind' -##fi - - -if [ -z "$1" ] -then - echo "$0 : find functions references " - echo "Usage $0 function_name " - exit; -fi - -EXTRA='' - - -CMD="grep -rnH" - -if [ "$2" != '--nocolor' ] -then - CMD="$CMD --color=always" -fi - - -$FIND -L . -name \*.json -not -wholename \*node_modules\* -not -wholename \*public/lib\* -exec $CMD "$1" {} + \ - -o -name \*.html -not -wholename \*node_modules\* -not -wholename \*public/lib\* -exec $CMD "$1" {} + \ - -o -name \*.jade -not -wholename \*node_modules\* -not -wholename \*public/lib\* -exec $CMD "$1" {} + \ - -o -name \*.js -not -wholename \*node_modules\* -not -wholename \*public/lib\* -exec $CMD "$1" {} + - diff --git a/dev-util/getAddr.js b/dev-util/getAddr.js deleted file mode 100755 index e0f086c..0000000 --- a/dev-util/getAddr.js +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var util = require('util'), - config = require('../config/config'); - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var A = require('../app/models/Address'); - -// var hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; -var hash = process.argv[2] || 'mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS'; - -var a= new A(hash); -a.update(function(err) { - console.log('Err:'); - console.log(err); - - console.log('Ret:'); - console.log(util.inspect(a,{depth:null})); - -}) - - - diff --git a/dev-util/getTx.js b/dev-util/getTx.js deleted file mode 100755 index 2a0ac83..0000000 --- a/dev-util/getTx.js +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var util = require('util'), - config = require('../config/config'); - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var TransactionDb = require('../lib/TransactionDb.js').default(); -var hash = process.argv[2] || '4286d6fc82a314348af4e9d3ce649f78ce4569937e9ad6613563755f0d14e3d1'; - -var t= TransactionDb.fromIdWithInfo(hash,function(err,tx) { - console.log('Err:'); - console.log(err); - - console.log('Ret:'); - console.log(util.inspect(tx,{depth:null})); -}); - - - diff --git a/dev-util/get_block.js b/dev-util/get_block.js deleted file mode 100755 index 34da1b1..0000000 --- a/dev-util/get_block.js +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var util = require('util'); - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var RpcClient = require('../node_modules/bitcore/RpcClient'); - -var config = require('../config/config'); - - - var hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; -//var hash = process.argv[2] || 'f6c2901f39fd07f2f2e503183d76f73ecc1aee9ac9216fde58e867bc29ce674e'; - -//hash = 'e2253359458db3e732c82a43fc62f56979ff59928f25a2df34dfa443e9a41160'; - -var rpc = new RpcClient(config.bitcoind); - -rpc.getBlock( hash, function(err, ret) { - - console.log('Err:'); - console.log(err); - - - console.log('Ret:'); - console.log(util.inspect(ret, { depth: 10} )); -}); - - - diff --git a/dev-util/level-put.js b/dev-util/level-put.js deleted file mode 100755 index 45cdb31..0000000 --- a/dev-util/level-put.js +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var config = require('../config/config'), - levelup = require('levelup'); - - - -var k = process.argv[2]; -var v = process.argv[3]; -var isBlock = process.argv[4] === '1'; - - -var dbPath = config.leveldb + (isBlock ? '/blocks' : '/txs'); -console.log('DB: ',dbPath); //TODO - - - -var db = levelup(dbPath ); - - -if (v) { - db.put(k,v,function(err) { - console.log('[PUT done]',err); //TODO - }); -} -else { - db.del(k,function(err) { - console.log('[DEL done]',err); //TODO - }); -} - - - diff --git a/dev-util/level.js b/dev-util/level.js deleted file mode 100755 index f897c2a..0000000 --- a/dev-util/level.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var config = require('../config/config'), - levelup = require('levelup'); - - - -var s = process.argv[2]; -var isBlock = process.argv[3] === '1'; - - -var dbPath = config.leveldb + (isBlock ? '/blocks' : '/txs'); -console.log('DB: ',dbPath); //TODO - - - -var db = levelup(dbPath ); - - -db.createReadStream({start: s, end: s+'~'}) - .on('data', function (data) { - console.log(data.key + ' => ' + data.value); //TODO - }) - .on('error', function () { - }) - .on('end', function () { - }); - - diff --git a/dev-util/node-tick-report b/dev-util/node-tick-report deleted file mode 100644 index 3f9461d..0000000 --- a/dev-util/node-tick-report +++ /dev/null @@ -1,1328 +0,0 @@ -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/read_block.js b/dev-util/read_block.js deleted file mode 100755 index 99fd0d8..0000000 --- a/dev-util/read_block.js +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var assert = require('assert'), - config = require('../config/config'), - BlockExtractor = require('../lib/BlockExtractor').class(), - networks = require('bitcore/networks'), - util = require('bitcore/util/util'); - - var be = new BlockExtractor(config.bitcoind.dataDir, config.network); - var network = config.network === 'testnet' ? networks.testnet: networks.livenet; -// console.log('[read_block.js.13]', be.nextFile() ); - - var c=0; - while (c++ < 100) { - be.getNextBlock(function(err, b) { - console.log('[read_block.js.14]',err, c, b?util.formatHashAlt(b.hash):''); //TODO - }); - } - - - - diff --git a/dev-util/stats b/dev-util/stats deleted file mode 100644 index 73399ec..0000000 --- a/dev-util/stats +++ /dev/null @@ -1,70 +0,0 @@ - - -first 5% - - => with data + mongo + w/RPC for blocks: 48.8s - => with RPC + mongo: 2m26s - => with files + mongo + wo/RPC for blocks: 36.7s - => with files + mongo + wo/RPC for blocks + wo/mongoIndexes: - - -first 10% - - => sin RPC, sin Tx, sin store block => 0.7s - => sin RPC, sin grabar, procesando TX => 8.5s - => sin RPC, sin TX processing, sin grabar => 12s28 - => con RPC, TX processing, sin Grabar Tx, grabando bloques => 29s - => con RPC, sin TX processing, sin Grabar Tx, grabando bloques => 35s - => con RPC, TX processing, sin Grabar Tx, grabando bloques => 43s - - => TX processing, sin RPC, sin saves TX, y blocks => 11.6s - => TX processing, CON RPC, sin saves TX, y blocks => 35s - => con RPC, TX processing, sin saves TX => 45s - => con RPC, TX processing, Grabarndo todo => 78s - => con RPC, TX processing, Grabarndo todo => 78s - (18k blocks, 36k txouts) - -//LEVEL DB - => sin RPC, TX processing, todo en level => 14s - => con RPC, TX processing, todo en level => 39.7s - => con RPC, TX processing, tx mongo, blocks en level => 64s - - - => sin RPC, TX processing, todo en level, handling REORGs, more data => 28s - => sin RPC, TX processing, todo en level, handling REORGs, more data, tx ts => 34t s - - -//FROM blk00002.dat (more txs), 5% - - => now total : 1m13s - => removing block writes => 1m8s - => sacando los contenidos adentro de getblock from file de => 4.5s!! - - => con base58 cpp => 21s - => toda la testnet => 17m !! - -10% de blk2 - => 50s con base58cpp - => 41s commentando todo addr - => 5s commentando todo get HistoricSync.prototype.getBlockFromFile = function(cb) { - => 15s commentando todo get HistoricSync.prototype.getBlockFromFile = function(cb) { - -10% de blk 1 - => 59s - => 15s comentando desde b.getStandardizedObject() - => 39s comentando dps b.getStandardizedObject() - - -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 - => 17m10s - - diff --git a/dev-util/status_info.js b/dev-util/status_info.js deleted file mode 100755 index 1b4deb8..0000000 --- a/dev-util/status_info.js +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var RpcClient = require('../node_modules/bitcore/RpcClient').class(); - -var config = require('../config/config'); - -var rpc = new RpcClient(config.bitcoind); - -var block = rpc.getInfo(function(err, block) { - if (err) { - console.log("Err:"); - console.log(err); - } - - console.log("Block info:"); - console.log(block); -}); - - diff --git a/dev-util/sync-level.js b/dev-util/sync-level.js deleted file mode 100644 index 2f2f95b..0000000 --- a/dev-util/sync-level.js +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var Sync = require('../lib/Sync').class(); - - -var s = new Sync(); - - -s.setOrphan( - '0000000000c2b1e8dab92a72741289e5ef0d4f375fd1b26f729da2ba979c028a', - '000000000228f9d02654459e09998c7557afa9082784c11226853f5feb805df9', - function (err) { - console.log('[sync-level.js.15]',err); //TODO - }); - - diff --git a/etc/bitcoind/bitcoin-livenet.conf b/etc/bitcoind/bitcoin-livenet.conf deleted file mode 100644 index 52e6d08..0000000 --- a/etc/bitcoind/bitcoin-livenet.conf +++ /dev/null @@ -1,10 +0,0 @@ -rpcuser=user -rpcpassword=pass -server=1 -txindex=1 - -# Allow connections outsite localhost? -rpcallowip=192.168.1.* - -rpcport=8332 - diff --git a/etc/bitcoind/bitcoin-testnet.conf b/etc/bitcoind/bitcoin-testnet.conf deleted file mode 100644 index 99bc260..0000000 --- a/etc/bitcoind/bitcoin-testnet.conf +++ /dev/null @@ -1,10 +0,0 @@ -rpcuser=user -rpcpassword=pass -server=1 -txindex=1 - -# Allow connections outsite localhost? -rpcallowip=192.168.1.* - -rpcport=18332 -testnet=3 diff --git a/etc/minersPoolStrings.json b/etc/minersPoolStrings.json deleted file mode 100644 index 4cfa885..0000000 --- a/etc/minersPoolStrings.json +++ /dev/null @@ -1,235 +0,0 @@ -[ - { - "poolName":"50BTC", - "url":"https://50btc.com/", - "searchStrings":[ - "50BTC.com", - "50btc.com" - ] - }, - { - "poolName":"175btc", - "url":"http://www.175btc.com/", - "searchStrings":[ - "Mined By 175btc.com" - ] - }, - { - "poolName":"ASICminer", - "url":"https://bitcointalk.org/index.php?topic=99497.0", - "searchStrings":[ - "Mined By ASICMiner" - ] - }, - { - "poolName":"AntMiner", - "url":"https://bitmaintech.com/", - "searchStrings":[ - "AntPool" - ] - }, - { - "poolName":"agentD", - "url":"http://", - "searchStrings":[ - "agentD" - ] - }, - { - "poolName":"Bitfury", - "url":"http://bitfury.org/", - "searchStrings":[ - "2av0id51pct" - ] - }, - { - "poolName":"BitMinter", - "url":"https://bitminter.com/", - "searchStrings":[ - "BitMinter" - ] - }, - { - "poolName":"Bitparking", - "url":"http://bitparking.com/", - "searchStrings":[ - "bitparking" - ] - }, - { - "poolName":"BTC Guild", - "url":"https://www.btcguild.com/", - "searchStrings":[ - "Mined by BTC Guild", - "BTC Guild" - ] - }, - { - "poolName":"bcpool.io", - "url":"https://bcpool.io/", - "searchStrings":[ - "bcpool" - ] - }, - { - "poolName":"Discus Fish", - "url":"http://f2pool.com/", - "searchStrings":[ - "七彩神仙鱼", - "Made in China", - "Mined by user" - ] - }, - { - "poolName":"Discus Fish Solo", - "url":"http://f2pool.com/", - "searchStrings":[ - "For Pierce and Paul" - ] - }, - { - "poolName":"Cointerra", - "url":"http://cointerra.com/", - "searchStrings":[ - "cointerra" - ] - }, - { - "poolName":"Eligius", - "url":"http://eligius.st/", - "searchStrings":[ - "Eligius" - ] - }, - { - "poolName":"EclipseMC", - "url":"https://eclipsemc.com/", - "searchStrings":[ - "Josh Zerlan was here!", - "EclipseMC", - "Aluminum Falcon" - ] - }, - { - "poolName":"GIVE-ME-COINS", - "url":"https://give-me-coins.com/", - "searchStrings":[ - "Mined at GIVE-ME-COINS.com" - ] - }, - { - "poolName":"ghash.io", - "url":"https://ghash.io/", - "searchStrings":[ - "ghash.io", - "GHash.IO" - ] - }, - { - "poolName":"HHTT", - "url":"http://hhtt.1209k.com/", - "searchStrings":[ - "HHTT" - ] - }, - { - "poolName":"KNCminer", - "url":"https://www.kncminer.com/", - "searchStrings":[ - "KnCMiner" - ] - }, - { - "poolName":"Megabigpower", - "url":"http://megabigpower.com/", - "searchStrings":[ - "megabigpower.com" - ] - }, - { - "poolName":"MultiCoin", - "url":"https://multicoin.co/", - "searchStrings":[ - "MultiCoin.co" - ] - }, - { - "poolName":"Mt Red", - "url":"https://mtred.com/‎", - "searchStrings":[ - "/mtred/" - ] - }, - { - "poolName":"MaxBTC", - "url":"https://www.maxbtc.com", - "searchStrings":[ - "MaxBTC" - ] - }, - { - "poolName":"NMCbit", - "url":"http://nmcbit.com/", - "searchStrings":[ - "nmcbit.com" - ] - }, - { - "poolName":"ozcoin", - "url":"https://ozco.in/", - "searchStrings":[ - "ozco.in", - "ozcoin" - ] - }, - { - "poolName":"Polmine.pl", - "url":"https://polmine.pl/‎", - "searchStrings":[ - "by polmine.pl" - ] - }, - { - "poolName":"simplecoin", - "url":"http://simplecoin.us/", - "searchStrings":[ - "simplecoin.us ftw" - ] - }, - { - "poolName":"Slush", - "url":"https://mining.bitcoin.cz/", - "searchStrings":[ - "slush" - ] - }, - { - "poolName":"TripleMining", - "url":"https://www.triplemining.com/", - "searchStrings":[ - "Triplemining.com" - ] - }, - { - "poolName":"wizkid057", - "url":"http://wizkid057.com/btc", - "searchStrings":[ - "wizkid057" - ] - }, - { - "poolName":"Yourbtc.net", - "url":"http://yourbtc.net/", - "searchStrings":[ - "yourbtc.net" - ] - }, - { - "poolName":"BTCChina Pool", - "url":"https://pool.btcchina.com/", - "searchStrings":[ - "BTCChina Pool", - "btcchina.com" - ] - } -] diff --git a/etc/test-cert.pem b/etc/test-cert.pem deleted file mode 100644 index 4e95885..0000000 --- a/etc/test-cert.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICMjCCAZugAwIBAgIJAK9dKmjfxq+BMA0GCSqGSIb3DQEBCwUAMDIxCzAJBgNV -BAYTAkFSMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVDb3BheTAeFw0x -NDA4MjExNzQyMTBaFw0xNDA5MjAxNzQyMTBaMDIxCzAJBgNVBAYTAkFSMRMwEQYD -VQQIDApTb21lLVN0YXRlMQ4wDAYDVQQKDAVDb3BheTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEA1BbMI6V06LKoBrcf5bJ8LH7EjwqbEacIOpiY7B+8W3sAM1bB -6hA2IlPvKL3qTdhMMKFZGZMYypmlAQTI1N+VNSwJHNjyepFbtkdNytSC8qw8bhak -yt4TByYEw1NMYx7I0OOdjh/DKsS+EOIgQDT9zSB+NgErKb0mKrginwgk5XkCAwEA -AaNQME4wHQYDVR0OBBYEFM0G1agUfY4zRNfxJ+0sHV3EsoGKMB8GA1UdIwQYMBaA -FM0G1agUfY4zRNfxJ+0sHV3EsoGKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADgYEAOg7n1RCyB1BJ6TuF99i25H7kpGUSL57ajNyyCKDciTPmpxVJ5knAjPYa -hbXX+dlq2B8QEnfkE5FMDLkO3RS3xU8YfekIDHofDuXR9boD/4rRlsN8md2Jmkr6 -MyRtYPtsPWVeoz0WmG5f1yobHmh7mYf17oN+uRJKX68s8G6b/SQ= ------END CERTIFICATE----- diff --git a/etc/test-key.pem b/etc/test-key.pem deleted file mode 100644 index 7bb97c2..0000000 --- a/etc/test-key.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDUFswjpXTosqgGtx/lsnwsfsSPCpsRpwg6mJjsH7xbewAzVsHq -EDYiU+8ovepN2EwwoVkZkxjKmaUBBMjU35U1LAkc2PJ6kVu2R03K1ILyrDxuFqTK -3hMHJgTDU0xjHsjQ452OH8MqxL4Q4iBANP3NIH42ASspvSYquCKfCCTleQIDAQAB -AoGAMUzDUx3o2RZ+XGFA9uHQX39wLVfnx+itzwEduvV9kT48Q7LNDJ2MF9qu4yeS -SVoYC83Vqk45Gw8v/dag4GrAgdk1NHZZ56Z/G55m06Y45xS6ZarBdbe0N1jdZEab -RG3FgxyPSUiZ5aLIMxMMtgt/DRv9BPpIeLNDMgyQRjVWlMkCQQDzlLwkp4bo+CAY -UMcsSN+KGurEMsuF0qc/+TLqpKDoOaLtd1F+Ntn20tQqeH0YLWktFvzAgY7wYXrb -lhMuAxa7AkEA3ucGEXNqwu1qVP4fXfEN1E0Y5X/euXMsfgNG8IK82hF3h83hnqNM -3FcGFOyKnL7E5TfRlJfxhAGqUfCe+2zjWwJBAKA6CID8CkyZW1NjX4EL9q+8AQ5K -c4J2DTqRzCJ5ZLcdosUeJecmYb5w9MtzMqaCyJq2clCXaNVK6iwjzj4IHh0CQQCY -sgwvIjCtrfQcmyUjtoExwUrf1LPfuK1u+ZG8KuNyQ2rtxjTb9qQtgRPye4QNEoZR -O+a/c0MImhdyIHLYa+RnAkEAwfLD4q+FDx4eX0ANO7/PI/XiJGqi6x1cYUwyRg9o -2S6hN5RnUD/nf2HKHU0esp34UMY/UWMrodCRDZj/ijg4UA== ------END RSA PRIVATE KEY----- diff --git a/examples/bitcore.js b/examples/bitcore.js deleted file mode 100644 index 3f55d37..0000000 --- a/examples/bitcore.js +++ /dev/null @@ -1,41841 +0,0 @@ -require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o prevnonce; false otherwise -AuthMessage._noncegt = function(nonce, prevnonce) { - var noncep1 = nonce.slice(0, 4).readUInt32BE(0); - var prevnoncep1 = prevnonce.slice(0, 4).readUInt32BE(0); - - if (noncep1 > prevnoncep1) - return true; - - if (noncep1 < prevnoncep1) - return false; - - var noncep2 = nonce.slice(4, 8).readUInt32BE(0); - var prevnoncep2 = prevnonce.slice(4, 8).readUInt32BE(0); - - if (noncep2 > prevnoncep2) - return true; - - return false; -}; - -AuthMessage._encrypt = function(topubkey, payload, r, iv) { - var encrypted = ECIES.encrypt(topubkey, payload, r, iv); - return encrypted; -}; - -AuthMessage._decrypt = function(privkey, encrypted) { - var decrypted = ECIES.decrypt(privkey, encrypted); - return decrypted; -}; - -AuthMessage._sign = function(key, payload) { - var sig = Message.sign(payload, key); - return sig; -}; - -AuthMessage._verify = function(pubkey, signature, payload) { - var v = Message.verifyWithPubKey(pubkey, payload, signature); - return v; -}; - -module.exports = AuthMessage; - -}).call(this,require("buffer").Buffer) -},{"./ECIES":"0Qraa1","./Key":"ALJ4PS","./Message":"CBDCgz","buffer":95,"preconditions":163}],"./lib/AuthMessage":[function(require,module,exports){ -module.exports=require('cBnJMk'); -},{}],"./lib/BIP39":[function(require,module,exports){ -module.exports=require('82LilS'); -},{}],"82LilS":[function(require,module,exports){ -(function (Buffer){ -var coinUtil = require('../util'); -var sjcl = require('./sjcl'); -var SecureRandom = require('./SecureRandom'); - -var hmacSHA512 = function(key) { - var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha512); - this.encrypt = function() { - return hasher.encrypt.apply(hasher, arguments); - }; -}; - -var pbkdf2Sync_sha512 = function(password, salt, iterations, keylen) { - var derivedKey = sjcl.misc.pbkdf2(password, salt, iterations, 512, hmacSHA512); - return sjcl.codec.hex.fromBits(derivedKey) -}; - -var BIP39 = function() {}; - -BIP39.mnemonic = function(wordlist, bits) { - if (!bits) - bits = 128; - if (bits % 32 != 0) - throw new Error("bits must be multiple of 32"); - var buf = SecureRandom.getRandomBuffer(bits / 8); - return BIP39.entropy2mnemonic(wordlist, buf); -} - -BIP39.entropy2mnemonic = function(wordlist, buf) { - var hash = coinUtil.sha256(buf); - var bin = ""; - var bits = buf.length * 8; - for (var i = 0; i < buf.length; i++) { - bin = bin + ("00000000" + buf[i].toString(2)).slice(-8); - } - var hashbits = hash[0].toString(2); - hashbits = ("00000000" + hashbits).slice(-8).slice(0, bits / 32); - bin = bin + hashbits; - if (bin.length % 11 != 0) - throw new Error("internal error - entropy not an even multiple of 11 bits - " + bin.length); - var mnemonic = ""; - for (var i = 0; i < bin.length / 11; i++) { - if (mnemonic != "") - mnemonic = mnemonic + " "; - var wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2); - mnemonic = mnemonic + wordlist[wi]; - } - return mnemonic; -} - -BIP39.check = function(wordlist, mnemonic) { - var words = mnemonic.split(' '); - var bin = ""; - for (var i = 0; i < words.length; i++) { - var ind = wordlist.indexOf(words[i]); - if (ind < 0) - return false; - bin = bin + ("00000000000" + ind.toString(2)).slice(-11); - } - - if (bin.length % 11 != 0) { - throw new Error("internal error - entropy not an even multiple of 11 bits - " + bin.length); - } - var cs = bin.length / 33; - var hash_bits = bin.slice(-cs); - var nonhash_bits = bin.slice(0, bin.length - cs); - var buf = new Buffer(nonhash_bits.length / 8); - for (var i = 0; i < nonhash_bits.length / 8; i++) { - buf.writeUInt8(parseInt(bin.slice(i * 8, (i + 1) * 8), 2), i); - } - var hash = coinUtil.sha256(buf); - var expected_hash_bits = hash[0].toString(2); - expected_hash_bits = ("00000000" + expected_hash_bits).slice(-8).slice(0, cs); - return expected_hash_bits == hash_bits; -} - -BIP39.mnemonic2seed = function(mnemonic, passphrase) { - if (!passphrase) - passphrase = ""; - var hex = pbkdf2Sync_sha512(mnemonic, "mnemonic" + passphrase, 2048, 64); - var buf = new Buffer(hex, 'hex'); - return buf; -} - -module.exports = BIP39; - -}).call(this,require("buffer").Buffer) -},{"../util":191,"./SecureRandom":"p4SiC2","./sjcl":"oLMOpG","buffer":95}],"./lib/BIP39WordlistEn":[function(require,module,exports){ -module.exports=require('sp4vFZ'); -},{}],"sp4vFZ":[function(require,module,exports){ -var BIP39WordlistEn = ["abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid", "acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual", "adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance", "advice", "aerobic", "affair", "afford", "afraid", "again", "age", "agent", "agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album", "alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone", "alpha", "already", "also", "alter", "always", "amateur", "amazing", "among", "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry", "animal", "ankle", "announce", "annual", "another", "answer", "antenna", "antique", "anxiety", "any", "apart", "apology", "appear", "apple", "approve", "april", "arch", "arctic", "area", "arena", "argue", "arm", "armed", "armor", "army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact", "artist", "artwork", "ask", "aspect", "assault", "asset", "assist", "assume", "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract", "auction", "audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado", "avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis", "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball", "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base", "basic", "basket", "battle", "beach", "bean", "beauty", "because", "become", "beef", "before", "begin", "behave", "behind", "believe", "below", "belt", "bench", "benefit", "best", "betray", "better", "between", "beyond", "bicycle", "bid", "bike", "bind", "biology", "bird", "birth", "bitter", "black", "blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood", "blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body", "boil", "bomb", "bone", "bonus", "book", "boost", "border", "boring", "borrow", "boss", "bottom", "bounce", "box", "boy", "bracket", "brain", "brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief", "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother", "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb", "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus", "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable", "cactus", "cage", "cake", "call", "calm", "camera", "camp", "can", "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable", "capital", "captain", "car", "carbon", "card", "cargo", "carpet", "carry", "cart", "case", "cash", "casino", "castle", "casual", "cat", "catalog", "catch", "category", "cattle", "caught", "cause", "caution", "cave", "ceiling", "celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk", "champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap", "check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child", "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle", "citizen", "city", "civil", "claim", "clap", "clarify", "claw", "clay", "clean", "clerk", "clever", "click", "client", "cliff", "climb", "clinic", "clip", "clock", "clog", "close", "cloth", "cloud", "clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut", "code", "coffee", "coil", "coin", "collect", "color", "column", "combine", "come", "comfort", "comic", "common", "company", "concert", "conduct", "confirm", "congress", "connect", "consider", "control", "convince", "cook", "cool", "copper", "copy", "coral", "core", "corn", "correct", "cost", "cotton", "couch", "country", "couple", "course", "cousin", "cover", "coyote", "crack", "cradle", "craft", "cram", "crane", "crash", "crater", "crawl", "crazy", "cream", "credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop", "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch", "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard", "curious", "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad", "damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn", "day", "deal", "debate", "debris", "decade", "december", "decide", "decline", "decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay", "deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend", "deposit", "depth", "deputy", "derive", "describe", "desert", "design", "desk", "despair", "destroy", "detail", "detect", "develop", "device", "devote", "diagram", "dial", "diamond", "diary", "dice", "diesel", "diet", "differ", "digital", "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree", "discover", "disease", "dish", "dismiss", "disorder", "display", "distance", "divert", "divide", "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin", "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft", "dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill", "drink", "drip", "drive", "drop", "drum", "dry", "duck", "dumb", "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic", "eager", "eagle", "early", "earn", "earth", "easily", "east", "easy", "echo", "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight", "either", "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator", "elite", "else", "embark", "embody", "embrace", "emerge", "emotion", "employ", "empower", "empty", "enable", "enact", "end", "endless", "endorse", "enemy", "energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough", "enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode", "equal", "equip", "era", "erase", "erode", "erosion", "error", "erupt", "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil", "evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude", "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit", "exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend", "extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint", "faith", "fall", "false", "fame", "family", "famous", "fan", "fancy", "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue", "fault", "favorite", "feature", "february", "federal", "fee", "feed", "feel", "female", "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field", "figure", "file", "film", "filter", "final", "find", "fine", "finger", "finish", "fire", "firm", "first", "fiscal", "fish", "fit", "fitness", "fix", "flag", "flame", "flash", "flat", "flavor", "flee", "flight", "flip", "float", "flock", "floor", "flower", "fluid", "flush", "fly", "foam", "focus", "fog", "foil", "fold", "follow", "food", "foot", "force", "forest", "forget", "fork", "fortune", "forum", "forward", "fossil", "foster", "found", "fox", "fragile", "frame", "frequent", "fresh", "friend", "fringe", "frog", "front", "frost", "frown", "frozen", "fruit", "fuel", "fun", "funny", "furnace", "fury", "future", "gadget", "gain", "galaxy", "gallery", "game", "gap", "garage", "garbage", "garden", "garlic", "garment", "gas", "gasp", "gate", "gather", "gauge", "gaze", "general", "genius", "genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift", "giggle", "ginger", "giraffe", "girl", "give", "glad", "glance", "glare", "glass", "glide", "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue", "goat", "goddess", "gold", "good", "goose", "gorilla", "gospel", "gossip", "govern", "gown", "grab", "grace", "grain", "grant", "grape", "grass", "gravity", "great", "green", "grid", "grief", "grit", "grocery", "group", "grow", "grunt", "guard", "guess", "guide", "guilt", "guitar", "gun", "gym", "habit", "hair", "half", "hammer", "hamster", "hand", "happy", "harbor", "hard", "harsh", "harvest", "hat", "have", "hawk", "hazard", "head", "health", "heart", "heavy", "hedgehog", "height", "hello", "helmet", "help", "hen", "hero", "hidden", "high", "hill", "hint", "hip", "hire", "history", "hobby", "hockey", "hold", "hole", "holiday", "hollow", "home", "honey", "hood", "hope", "horn", "horror", "horse", "hospital", "host", "hotel", "hour", "hover", "hub", "huge", "human", "humble", "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt", "husband", "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore", "ill", "illegal", "illness", "image", "imitate", "immense", "immune", "impact", "impose", "improve", "impulse", "inch", "include", "income", "increase", "index", "indicate", "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit", "initial", "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane", "insect", "inside", "inspire", "install", "intact", "interest", "into", "invest", "invite", "involve", "iron", "island", "isolate", "issue", "item", "ivory", "jacket", "jaguar", "jar", "jazz", "jealous", "jeans", "jelly", "jewel", "job", "join", "joke", "journey", "joy", "judge", "juice", "jump", "jungle", "junior", "junk", "just", "kangaroo", "keen", "keep", "ketchup", "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit", "kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock", "know", "lab", "label", "labor", "ladder", "lady", "lake", "lamp", "language", "laptop", "large", "later", "latin", "laugh", "laundry", "lava", "law", "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn", "leave", "lecture", "left", "leg", "legal", "legend", "leisure", "lemon", "lend", "length", "lens", "leopard", "lesson", "letter", "level", "liar", "liberty", "library", "license", "life", "lift", "light", "like", "limb", "limit", "link", "lion", "liquid", "list", "little", "live", "lizard", "load", "loan", "lobster", "local", "lock", "logic", "lonely", "long", "loop", "lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage", "lumber", "lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet", "maid", "mail", "main", "major", "make", "mammal", "man", "manage", "mandate", "mango", "mansion", "manual", "maple", "marble", "march", "margin", "marine", "market", "marriage", "mask", "mass", "master", "match", "material", "math", "matrix", "matter", "maximum", "maze", "meadow", "mean", "measure", "meat", "mechanic", "medal", "media", "melody", "melt", "member", "memory", "mention", "menu", "mercy", "merge", "merit", "merry", "mesh", "message", "metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind", "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake", "mix", "mixed", "mixture", "mobile", "model", "modify", "mom", "moment", "monitor", "monkey", "monster", "month", "moon", "moral", "more", "morning", "mosquito", "mother", "motion", "motor", "mountain", "mouse", "move", "movie", "much", "muffin", "mule", "multiply", "muscle", "museum", "mushroom", "music", "must", "mutual", "myself", "mystery", "myth", "naive", "name", "napkin", "narrow", "nasty", "nation", "nature", "near", "neck", "need", "negative", "neglect", "neither", "nephew", "nerve", "nest", "net", "network", "neutral", "never", "news", "next", "nice", "night", "noble", "noise", "nominee", "noodle", "normal", "north", "nose", "notable", "note", "nothing", "notice", "novel", "now", "nuclear", "number", "nurse", "nut", "oak", "obey", "object", "oblige", "obscure", "observe", "obtain", "obvious", "occur", "ocean", "october", "odor", "off", "offer", "office", "often", "oil", "okay", "old", "olive", "olympic", "omit", "once", "one", "onion", "online", "only", "open", "opera", "opinion", "oppose", "option", "orange", "orbit", "orchard", "order", "ordinary", "organ", "orient", "original", "orphan", "ostrich", "other", "outdoor", "outer", "output", "outside", "oval", "oven", "over", "own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle", "page", "pair", "palace", "palm", "panda", "panel", "panic", "panther", "paper", "parade", "parent", "park", "parrot", "party", "pass", "patch", "path", "patient", "patrol", "pattern", "pause", "pave", "payment", "peace", "peanut", "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people", "pepper", "perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical", "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot", "pink", "pioneer", "pipe", "pistol", "pitch", "pizza", "place", "planet", "plastic", "plate", "play", "please", "pledge", "pluck", "plug", "plunge", "poem", "poet", "point", "polar", "pole", "police", "pond", "pony", "pool", "popular", "portion", "position", "possible", "post", "potato", "pottery", "poverty", "powder", "power", "practice", "praise", "predict", "prefer", "prepare", "present", "pretty", "prevent", "price", "pride", "primary", "print", "priority", "prison", "private", "prize", "problem", "process", "produce", "profit", "program", "project", "promote", "proof", "property", "prosper", "protect", "proud", "provide", "public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch", "pupil", "puppy", "purchase", "purity", "purpose", "purse", "push", "put", "puzzle", "pyramid", "quality", "quantum", "quarter", "question", "quick", "quit", "quiz", "quote", "rabbit", "raccoon", "race", "rack", "radar", "radio", "rail", "rain", "raise", "rally", "ramp", "ranch", "random", "range", "rapid", "rare", "rate", "rather", "raven", "raw", "razor", "ready", "real", "reason", "rebel", "rebuild", "recall", "receive", "recipe", "record", "recycle", "reduce", "reflect", "reform", "refuse", "region", "regret", "regular", "reject", "relax", "release", "relief", "rely", "remain", "remember", "remind", "remove", "render", "renew", "rent", "reopen", "repair", "repeat", "replace", "report", "require", "rescue", "resemble", "resist", "resource", "response", "result", "retire", "retreat", "return", "reunion", "reveal", "review", "reward", "rhythm", "rib", "ribbon", "rice", "rich", "ride", "ridge", "rifle", "right", "rigid", "ring", "riot", "ripple", "risk", "ritual", "rival", "river", "road", "roast", "robot", "robust", "rocket", "romance", "roof", "rookie", "room", "rose", "rotate", "rough", "round", "route", "royal", "rubber", "rude", "rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness", "safe", "sail", "salad", "salmon", "salon", "salt", "salute", "same", "sample", "sand", "satisfy", "satoshi", "sauce", "sausage", "save", "say", "scale", "scan", "scare", "scatter", "scene", "scheme", "school", "science", "scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub", "sea", "search", "season", "seat", "second", "secret", "section", "security", "seed", "seek", "segment", "select", "sell", "seminar", "senior", "sense", "sentence", "series", "service", "session", "settle", "setup", "seven", "shadow", "shaft", "shallow", "share", "shed", "shell", "sheriff", "shield", "shift", "shine", "ship", "shiver", "shock", "shoe", "shoot", "shop", "short", "shoulder", "shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick", "side", "siege", "sight", "sign", "silent", "silk", "silly", "silver", "similar", "simple", "since", "sing", "siren", "sister", "situate", "six", "size", "skate", "sketch", "ski", "skill", "skin", "skirt", "skull", "slab", "slam", "sleep", "slender", "slice", "slide", "slight", "slim", "slogan", "slot", "slow", "slush", "small", "smart", "smile", "smoke", "smooth", "snack", "snake", "snap", "sniff", "snow", "soap", "soccer", "social", "sock", "soda", "soft", "solar", "soldier", "solid", "solution", "solve", "someone", "song", "soon", "sorry", "sort", "soul", "sound", "soup", "source", "south", "space", "spare", "spatial", "spawn", "speak", "special", "speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin", "spirit", "split", "spoil", "sponsor", "spoon", "sport", "spot", "spray", "spread", "spring", "spy", "square", "squeeze", "squirrel", "stable", "stadium", "staff", "stage", "stairs", "stamp", "stand", "start", "state", "stay", "steak", "steel", "stem", "step", "stereo", "stick", "still", "sting", "stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street", "strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject", "submit", "subway", "success", "such", "sudden", "suffer", "sugar", "suggest", "suit", "summer", "sun", "sunny", "sunset", "super", "supply", "supreme", "sure", "surface", "surge", "surprise", "surround", "survey", "suspect", "sustain", "swallow", "swamp", "swap", "swarm", "swear", "sweet", "swift", "swim", "swing", "switch", "sword", "symbol", "symptom", "syrup", "system", "table", "tackle", "tag", "tail", "talent", "talk", "tank", "tape", "target", "task", "taste", "tattoo", "taxi", "teach", "team", "tell", "ten", "tenant", "tennis", "tent", "term", "test", "text", "thank", "that", "theme", "then", "theory", "there", "they", "thing", "this", "thought", "three", "thrive", "throw", "thumb", "thunder", "ticket", "tide", "tiger", "tilt", "timber", "time", "tiny", "tip", "tired", "tissue", "title", "toast", "tobacco", "today", "toddler", "toe", "together", "toilet", "token", "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth", "top", "topic", "topple", "torch", "tornado", "tortoise", "toss", "total", "tourist", "toward", "tower", "town", "toy", "track", "trade", "traffic", "tragic", "train", "transfer", "trap", "trash", "travel", "tray", "treat", "tree", "trend", "trial", "tribe", "trick", "trigger", "trim", "trip", "trophy", "trouble", "truck", "true", "truly", "trumpet", "trust", "truth", "try", "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn", "turtle", "twelve", "twenty", "twice", "twin", "twist", "two", "type", "typical", "ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under", "undo", "unfair", "unfold", "unhappy", "uniform", "unique", "unit", "universe", "unknown", "unlock", "until", "unusual", "unveil", "update", "upgrade", "uphold", "upon", "upper", "upset", "urban", "urge", "usage", "use", "used", "useful", "useless", "usual", "utility", "vacant", "vacuum", "vague", "valid", "valley", "valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle", "velvet", "vendor", "venture", "venue", "verb", "verify", "version", "very", "vessel", "veteran", "viable", "vibrant", "vicious", "victory", "video", "view", "village", "vintage", "violin", "virtual", "virus", "visa", "visit", "visual", "vital", "vivid", "vocal", "voice", "void", "volcano", "volume", "vote", "voyage", "wage", "wagon", "wait", "walk", "wall", "walnut", "want", "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave", "way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding", "weekend", "weird", "welcome", "west", "wet", "whale", "what", "wheat", "wheel", "when", "where", "whip", "whisper", "wide", "width", "wife", "wild", "will", "win", "window", "wine", "wing", "wink", "winner", "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman", "wonder", "wood", "wool", "word", "work", "world", "worry", "worth", "wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard", "year", "yellow", "you", "young", "youth", "zebra", "zero", "zone", "zoo"]; -module.exports = BIP39WordlistEn; - -},{}],"./lib/Base58":[function(require,module,exports){ -module.exports=require('6VqyzY'); -},{}],"6VqyzY":[function(require,module,exports){ -(function (Buffer){ -var crypto = require('crypto'); -var bignum = require('bignum'); - -var globalBuffer = new Buffer(1024); -var zerobuf = new Buffer(0); -var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; -var ALPHABET_ZERO = ALPHABET[0]; -var ALPHABET_BUF = new Buffer(ALPHABET, 'ascii'); -var ALPHABET_INV = {}; -for (var i = 0; i < ALPHABET.length; i++) { - ALPHABET_INV[ALPHABET[i]] = i; -}; - -// Vanilla Base58 Encoding -var base58 = { - encode: function(buf) { - var str; - var x = bignum.fromBuffer(buf); - var r; - - if (buf.length < 512) { - str = globalBuffer; - } else { - str = new Buffer(buf.length << 1); - } - var i = str.length - 1; - while (x.gt(0)) { - r = x.mod(58); - x = x.div(58); - str[i] = ALPHABET_BUF[r.toNumber()]; - i--; - } - - // deal with leading zeros - var j = 0; - while (buf[j] == 0) { - str[i] = ALPHABET_BUF[0]; - j++; - i--; - } - - return str.slice(i + 1, str.length).toString('ascii'); - }, - - decode: function(str) { - if (str.length == 0) return zerobuf; - var answer = bignum(0); - for (var i = 0; i < str.length; i++) { - answer = answer.mul(58); - answer = answer.add(ALPHABET_INV[str[i]]); - }; - var i = 0; - while (i < str.length && str[i] == ALPHABET_ZERO) { - i++; - } - if (i > 0) { - var zb = new Buffer(i); - zb.fill(0); - if (i == str.length) return zb; - answer = answer.toBuffer(); - return Buffer.concat([zb, answer], i + answer.length); - } else { - return answer.toBuffer(); - } - }, -}; - -// Base58Check Encoding -function sha256(data) { - return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary'); -}; - -function doubleSHA256(data) { - return sha256(sha256(data)); -}; - -var base58Check = { - encode: function(buf) { - var checkedBuf = new Buffer(buf.length + 4); - var hash = doubleSHA256(buf); - buf.copy(checkedBuf); - hash.copy(checkedBuf, buf.length); - return base58.encode(checkedBuf); - }, - - decode: function(s) { - var buf = base58.decode(s); - if (buf.length < 4) { - throw new Error("invalid input: too short"); - } - - var data = buf.slice(0, -4); - var csum = buf.slice(-4); - - var hash = doubleSHA256(data); - var hash4 = hash.slice(0, 4); - - if (csum.toString('hex') !== hash4.toString('hex')) { - throw new Error("checksum mismatch"); - } - - return data; - }, -}; - -// if you frequently do base58 encodings with data larger -// than 512 bytes, you can use this method to expand the -// size of the reusable buffer -exports.setBuffer = function(buf) { - globalBuffer = buf; -}; - -exports.base58 = base58; -exports.base58Check = base58Check; -exports.encode = base58.encode; -exports.decode = base58.decode; - -}).call(this,require("buffer").Buffer) -},{"bignum":61,"buffer":95,"crypto":99}],"./lib/Block":[function(require,module,exports){ -module.exports=require('pJEQEB'); -},{}],"pJEQEB":[function(require,module,exports){ -(function (Buffer){ -var util = require('../util'); -var Script = require('./Script'); -var Bignum = require('bignum'); -var Binary = require('binary'); -var Step = require('step'); -var buffertools = require('buffertools'); -var Transaction = require('./Transaction'); -var TransactionIn = Transaction.In; -var TransactionOut = Transaction.Out; -var COINBASE_OP = Transaction.COINBASE_OP; -var VerificationError = require('../util/error').VerificationError; -var BlockRules = { - maxTimeOffset: 2 * 60 * 60, // How far block timestamps can be into the future - //largestHash: (new Bignum(2)).pow(256) - //largestHash: new Bignum('115792089237316195423570985008687907853269984665640564039457584007913129639936') // = 2^256 - largestHash: new Bignum('10000000000000000000000000000000000000000000000000000000000000000', 16) -}; - -function Block(data) { - if ("object" !== typeof data) { - data = {}; - } - this.hash = data.hash || null; - this.prev_hash = data.prev_hash || util.NULL_HASH; - this.merkle_root = data.merkle_root || util.NULL_HASH; - this.timestamp = data.timestamp || 0; - this.bits = data.bits || 0; - this.nonce = data.nonce || 0; - this.version = data.version || 0; - this.height = data.height || 0; - this.size = data.size || 0; - this.active = data.active || false; - this.chainWork = data.chainWork || util.EMPTY_BUFFER; - this.txs = data.txs || []; -} - -Block.prototype.getHeader = function getHeader() { - var buf = new Buffer(80); - var ofs = 0; - buf.writeUInt32LE(this.version, ofs); - ofs += 4; - this.prev_hash.copy(buf, ofs); - ofs += 32; - this.merkle_root.copy(buf, ofs); - ofs += 32; - buf.writeUInt32LE(this.timestamp, ofs); - ofs += 4; - buf.writeUInt32LE(this.bits, ofs); - ofs += 4; - buf.writeUInt32LE(this.nonce, ofs); - ofs += 4; - return buf; -}; - -Block.prototype.parse = function parse(parser, headerOnly) { - this.version = parser.word32le(); - this.prev_hash = parser.buffer(32); - this.merkle_root = parser.buffer(32); - this.timestamp = parser.word32le(); - this.bits = parser.word32le(); - this.nonce = parser.word32le(); - - this.txs = []; - this.size = 0; - - if (headerOnly) - return; - - var txCount = parser.varInt(); - - for (var i = 0; i < txCount; i++) { - var tx = new Transaction(); - tx.parse(parser); - this.txs.push(tx); - } -}; - -Block.prototype.calcHash = function calcHash() { - var header = this.getHeader(); - - return util.twoSha256(header); -}; - -Block.prototype.checkHash = function checkHash() { - if (!this.hash || !this.hash.length) return false; - return buffertools.compare(this.calcHash(), this.hash) == 0; -}; - -Block.prototype.getHash = function getHash() { - if (!this.hash || !this.hash.length) this.hash = this.calcHash(); - - return this.hash; -}; - -Block.prototype.checkProofOfWork = function checkProofOfWork() { - var target = util.decodeDiffBits(this.bits); - - // TODO: Create a compare method in node-buffertools that uses the correct - // endian so we don't have to reverse both buffers before comparing. - var reverseHash = buffertools.reverse(this.hash); - if (buffertools.compare(reverseHash, target) > 0) { - throw new VerificationError('Difficulty target not met'); - } - - return true; -}; - -/** - * Returns the amount of work that went into this block. - * - * Work is defined as the average number of tries required to meet this - * block's difficulty target. For example a target that is greater than 5% - * of all possible hashes would mean that 20 "work" is required to meet it. - */ -Block.prototype.getWork = function getWork() { - var target = util.decodeDiffBits(this.bits, true); - return BlockRules.largestHash.div(target.add(1)); -}; - -Block.prototype.checkTimestamp = function checkTimestamp() { - var currentTime = new Date().getTime() / 1000; - if (this.timestamp > currentTime + BlockRules.maxTimeOffset) { - throw new VerificationError('Timestamp too far into the future'); - } - - return true; -}; - -Block.prototype.checkTransactions = function checkTransactions(txs) { - if (!Array.isArray(txs) || txs.length <= 0) { - throw new VerificationError('No transactions'); - } - if (!txs[0].isCoinBase()) { - throw new VerificationError('First tx must be coinbase'); - } - for (var i = 1; i < txs.length; i++) { - if (txs[i].isCoinBase()) { - throw new VerificationError('Tx index ' + i + ' must not be coinbase'); - } - } - - return true; -}; - -/** - * Build merkle tree. - * - * Ported from Java. Original code: BitcoinJ by Mike Hearn - * Copyright (c) 2011 Google Inc. - */ -Block.prototype.getMerkleTree = function getMerkleTree(txs) { - // The merkle hash is based on a tree of hashes calculated from the transactions: - // - // merkleHash - // /\ - // / \ - // A B - // / \ / \ - // tx1 tx2 tx3 tx4 - // - // Basically transactions are hashed, then the hashes of the transactions are hashed - // again and so on upwards into the tree. The point of this scheme is to allow for - // disk space savings later on. - // - // This function is a direct translation of CBlock::BuildMerkleTree(). - - if (txs.length == 0) { - return [util.NULL_HASH.slice(0)]; - } - - // Start by adding all the hashes of the transactions as leaves of the tree. - var tree = txs.map(function(tx) { - return tx instanceof Transaction ? tx.getHash() : tx; - }); - - var j = 0; - // Now step through each level ... - for (var size = txs.length; size > 1; size = Math.floor((size + 1) / 2)) { - // and for each leaf on that level .. - for (var i = 0; i < size; i += 2) { - var i2 = Math.min(i + 1, size - 1); - var a = tree[j + i]; - var b = tree[j + i2]; - tree.push(util.twoSha256(Buffer.concat([a, b]))); - } - j += size; - } - - return tree; -}; - -Block.prototype.calcMerkleRoot = function calcMerkleRoot(txs) { - var tree = this.getMerkleTree(txs); - return tree[tree.length - 1]; -}; - -Block.prototype.checkMerkleRoot = function checkMerkleRoot(txs) { - if (!this.merkle_root || !this.merkle_root.length) { - throw new VerificationError('No merkle root'); - } - - if (buffertools.compare(this.calcMerkleRoot(txs), new Buffer(this.merkle_root)) !== 0) { - throw new VerificationError('Merkle root incorrect'); - } - - return true; -}; - -Block.prototype.checkBlock = function checkBlock(txs) { - if (!this.checkHash()) { - throw new VerificationError("Block hash invalid"); - } - this.checkProofOfWork(); - this.checkTimestamp(); - - if (txs) { - this.checkTransactions(txs); - if (!this.checkMerkleRoot(txs)) { - throw new VerificationError("Merkle hash invalid"); - } - } - return true; -}; - -Block.getBlockValue = function getBlockValue(height) { - var subsidy = 50 * util.COIN; - subsidy = subsidy / (Math.pow(2, Math.floor(height / 210000))); - subsidy = Math.floor(subsidy); - subsidy = new Bignum(subsidy); - return subsidy; -}; - -Block.prototype.getBlockValue = function getBlockValue() { - return Block.getBlockValue(this.height); -}; - -Block.prototype.toString = function toString() { - return ""; -}; - - -Block.prototype.createCoinbaseTx = - function createCoinbaseTx(beneficiary) { - var tx = new Transaction(); - tx.ins.push(new TransactionIn({ - s: util.EMPTY_BUFFER, - q: 0xffffffff, - o: COINBASE_OP - })); - tx.outs.push(new TransactionOut({ - v: util.bigIntToValue(this.getBlockValue()), - s: Script.createPubKeyOut(beneficiary).getBuffer() - })); - return tx; -}; - -Block.prototype.solve = function solve(miner, callback) { - var header = this.getHeader(); - var target = util.decodeDiffBits(this.bits); - miner.solve(header, target, callback); -}; - -/** - * Returns an object with the same field names as jgarzik's getblock patch. - */ -Block.prototype.getStandardizedObject = - function getStandardizedObject(txs) { - var block = { - hash: util.formatHashFull(this.getHash()), - version: this.version, - prev_block: util.formatHashFull(this.prev_hash), - mrkl_root: util.formatHashFull(this.merkle_root), - time: this.timestamp, - bits: this.bits, - nonce: this.nonce, - height: this.height - }; - - - if (txs) { - var mrkl_tree = this.getMerkleTree(txs).map(function(buffer) { - return util.formatHashFull(buffer); - }); - block.mrkl_root = mrkl_tree[mrkl_tree.length - 1]; - - block.n_tx = txs.length; - var totalSize = 80; // Block header - totalSize += util.getVarIntSize(txs.length); // txn_count - txs = txs.map(function(tx) { - tx = tx.getStandardizedObject(); - totalSize += tx.size; - return tx; - }); - block.size = totalSize; - block.tx = txs; - - block.mrkl_tree = mrkl_tree; - } else { - block.size = this.size; - } - return block; -}; - -module.exports = Block; - -}).call(this,require("buffer").Buffer) -},{"../util":191,"../util/error":190,"./Script":"hQ0t76","./Transaction":"LJhYtm","bignum":61,"binary":83,"buffer":95,"buffertools":"fugeBw","step":178}],"KifRG4":[function(require,module,exports){ -var MAX_BLOOM_FILTER_SIZE = 36000; // bytes -var MAX_HASH_FUNCS = 50; -var LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455; -var LN2 = 0.6931471805599453094172321214581765680755001343602552; -var bit_mask = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]; - -function Bloom() { - this.data = ''; - this.hashFuncs = 0; -}; - -function ROTL32(x, r) { - return (x << r) | (x >> (32 - r)); -}; - -function getBlockU32(blockIdx, data) { - var idx = blockIdx * 4; - var v = (data[idx + 0] << (0 * 8)) | - (data[idx + 1] << (1 * 8)) | - (data[idx + 2] << (2 * 8)) | - (data[idx + 3] << (3 * 8)); - return v; -}; - -Bloom.prototype.hash = function(hashNum, data) { - var h1 = hashNum * (0xffffffff / (this.hashFuncs - 1)); - var c1 = 0xcc9e2d51; - var c2 = 0x1b873593; - var nBlocks = data.length / 4; - - // data body - for (var i = -nBlocks; i; i++) { - var k1 = getBlockU32(i); - - k1 *= c1; - k1 = ROTLF32(k1, 15); - k1 *= c2; - - h1 ^= k1; - h1 = ROTFL(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } - - // tail (trailing 1-3 bytes) - var tail = data.slice(nBlocks * 4); - - var k1 = 0; - - switch (data.length & 3) { - case 3: - k1 ^= tail[2] << 16; - case 2: - k1 ^= tail[1] << 8; - case 1: - k1 ^= tail[0]; - k1 *= c1; - k1 = ROTL32(k1, 15); - k1 *= c2; - h1 ^= k1; - } - - // finalize - h1 ^= data.length; - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - return h1 % (this.data.length * 8); -}; - -Bloom.prototype.insert = function(data) { - for (var i = 0; i < this.hashFuncs; i++) { - var index = this.hash(i, data); - this.data[index >> 3] |= bit_mask[7 & index]; - } -}; - -Bloom.prototype.contains = function(data) { - for (var i = 0; i < this.hashFuncs; i++) { - var index = this.hash(i, data); - if (!(this.data[index >> 3] & bit_mask[7 & index])) - return false; - } - - return true; -}; - -Bloom.prototype.sizeOk = function() { - return this.data.length <= MAX_BLOOM_FILTER_SIZE && - this.hashFuncs <= MAX_HASH_FUNCS; -}; - -function toInt(v) { - return~~ v; -} - -function min(a, b) { - if (a < b) - return a; - return b; -} - -Bloom.prototype.init = function(elements, FPRate) { - var filterSize = min(toInt(-1.0 / LN2SQUARED * elements * Math.log(FPRate)), - MAX_BLOOM_FILTER_SIZE * 8) / 8; - this.data[filterSize] = 0; - this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2), - MAX_HASH_FUNCS); -}; - - -module.exports = Bloom; - -},{}],"./lib/Bloom":[function(require,module,exports){ -module.exports=require('KifRG4'); -},{}],"./lib/Connection":[function(require,module,exports){ -module.exports=require('DB/p3X'); -},{}],"DB/p3X":[function(require,module,exports){ -(function (Buffer){ -var log = require('../util/log'); - -var MAX_RECEIVE_BUFFER = 10000000; -var PROTOCOL_VERSION = 70000; - -var Put = require('bufferput'); -var Buffers = require('buffers'); -require('../patches/Buffers.monkey').patch(Buffers); - -var bitcoreDefaults = require('../config'); -var networks = require('../networks'); -var Block = require('./Block'); -var Transaction = require('./Transaction'); -var util = require('../util'); -var Parser = require('../util/BinaryParser'); -var buffertools = require('buffertools'); -var doubleSha256 = util.twoSha256; -var SecureRandom = require('./SecureRandom'); -var nonce = SecureRandom.getPseudoRandomBuffer(8); -var nodeUtil = require('util'); -var EventEmitter = require('events').EventEmitter; - -var BIP0031_VERSION = 60000; - -function Connection(socket, peer, opts) { - this.config = opts || bitcoreDefaults; - - this.network = networks[this.config.network] || networks.livenet; - this.socket = socket; - this.peer = peer; - - // check for socks5 proxy options and construct a proxied socket - if (this.config.proxy) { - var Socks5Client = require('socks5-client'); - this.socket = new Socks5Client(this.config.proxy.host, this.config.proxy.port); - } - - // A connection is considered "active" once we have received verack - this.active = false; - // The version incoming packages are interpreted as - this.recvVer = 0; - // The version outgoing packages are sent as - this.sendVer = 0; - // The (claimed) height of the remote peer's block chain - this.bestHeight = 0; - // Is this an inbound connection? - this.inbound = !!this.socket.server; - // Have we sent a getaddr on this connection? - this.getaddr = false; - - // Receive buffer - this.buffers = new Buffers(); - - // Starting 20 Feb 2012, Version 0.2 is obsolete - // This is the same behavior as the official client - if (new Date().getTime() > 1329696000000) { - this.recvVer = 209; - this.sendVer = 209; - } - - this.setupHandlers(); -} -nodeUtil.inherits(Connection, EventEmitter); -Connection.prototype.open = function(callback) { - if (typeof callback === 'function') this.once('connect', callback); - this.socket.connect(this.peer.port, this.peer.host); - return this; -}; - -Connection.prototype.setupHandlers = function() { - this.socket.addListener('connect', this.handleConnect.bind(this)); - this.socket.addListener('error', this.handleError.bind(this)); - this.socket.addListener('end', this.handleDisconnect.bind(this)); - this.socket.addListener('data', (function(data) { - var dumpLen = 35; - log.debug('[' + this.peer + '] ' + - 'Recieved ' + data.length + ' bytes of data:'); - log.debug('... ' + buffertools.toHex(data.slice(0, dumpLen > data.length ? - data.length : dumpLen)) + - (data.length > dumpLen ? '...' : '')); - }).bind(this)); - this.socket.addListener('data', this.handleData.bind(this)); -}; - -Connection.prototype.handleConnect = function() { - if (!this.inbound) { - this.sendVersion(); - } - this.emit('connect', { - conn: this, - socket: this.socket, - peer: this.peer - }); -}; - -Connection.prototype.handleError = function(err) { - if (err.errno == 110 || err.errno == 'ETIMEDOUT') { - log.info('connection timed out for ' + this.peer); - } else if (err.errno == 111 || err.errno == 'ECONNREFUSED') { - log.info('connection refused for ' + this.peer); - } else { - log.warn('connection with ' + this.peer + ' ' + err.toString()); - } - this.emit('error', { - conn: this, - socket: this.socket, - peer: this.peer, - err: err - }); -}; - -Connection.prototype.handleDisconnect = function() { - this.emit('disconnect', { - conn: this, - socket: this.socket, - peer: this.peer - }); -}; - -Connection.prototype.handleMessage = function(message) { - if (!message) { - // Parser was unable to make sense of the message, drop it - return; - } - - try { - switch (message.command) { - case 'version': - // Did we connect to ourself? - if (buffertools.compare(nonce, message.nonce) === 0) { - this.socket.end(); - return; - } - - if (this.inbound) { - this.sendVersion(); - } - - if (message.version >= 209) { - this.sendMessage('verack', new Buffer([])); - } - this.sendVer = Math.min(message.version, PROTOCOL_VERSION); - if (message.version < 209) { - this.recvVer = Math.min(message.version, PROTOCOL_VERSION); - } else { - // We won't start expecting a checksum until after we've received - // the 'verack' message. - this.once('verack', (function() { - this.recvVer = message.version; - }).bind(this)); - } - this.bestHeight = message.start_height; - break; - - case 'verack': - this.recvVer = Math.min(message.version, PROTOCOL_VERSION); - this.active = true; - break; - - case 'ping': - if ('object' === typeof message.nonce) { - this.sendPong(message.nonce); - } - break; - } - } catch (e) { - log.err('Error while handling "' + message.command + '" message from ' + - this.peer + ':\n' + - (e.stack ? e.stack : e.toString())); - return; - } - this.emit(message.command, { - conn: this, - socket: this.socket, - peer: this.peer, - message: message - }); -}; - -Connection.prototype.sendPong = function(nonce) { - this.sendMessage('pong', nonce); -}; - -Connection.prototype.sendVersion = function() { - var subversion = '/BitcoinX:0.1/'; - - var put = new Put(); - put.word32le(PROTOCOL_VERSION); // version - put.word64le(1); // services - put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp - put.pad(26); // addr_me - put.pad(26); // addr_you - put.put(nonce); - put.varint(subversion.length); - put.put(new Buffer(subversion, 'ascii')); - put.word32le(0); - - this.sendMessage('version', put.buffer()); -}; - -Connection.prototype.sendGetBlocks = function(starts, stop, wantHeaders) { - // Default value for stop is 0 to get as many blocks as possible (500) - stop = stop || util.NULL_HASH; - - var put = new Put(); - - // https://en.bitcoin.it/wiki/Protocol_specification#getblocks - put.word32le(this.sendVer); - put.varint(starts.length); - - for (var i = 0; i < starts.length; i++) { - if (starts[i].length != 32) { - throw new Error('Invalid hash length'); - } - - put.put(starts[i]); - } - - var stopBuffer = new Buffer(stop, 'binary'); - if (stopBuffer.length != 32) { - throw new Error('Invalid hash length'); - } - - put.put(stopBuffer); - - var command = 'getblocks'; - if (wantHeaders) - command = 'getheaders'; - this.sendMessage(command, put.buffer()); -}; - -Connection.prototype.sendGetHeaders = function(starts, stop) { - this.sendGetBlocks(starts, stop, true); -}; - -Connection.prototype.sendGetData = function(invs) { - var put = new Put(); - put.varint(invs.length); - for (var i = 0; i < invs.length; i++) { - put.word32le(invs[i].type); - put.put(invs[i].hash); - } - this.sendMessage('getdata', put.buffer()); -}; - -Connection.prototype.sendGetAddr = function(invs) { - var put = new Put(); - this.sendMessage('getaddr', put.buffer()); -}; - -Connection.prototype.sendInv = function(data) { - if (!Array.isArray(data)) data = [data]; - var put = new Put(); - put.varint(data.length); - data.forEach(function(value) { - if (value instanceof Block) { - // Block - put.word32le(2); // MSG_BLOCK - } else { - // Transaction - put.word32le(1); // MSG_TX - } - put.put(value.getHash()); - }); - this.sendMessage('inv', put.buffer()); -}; - -Connection.prototype.sendHeaders = function(headers) { - var put = new Put(); - put.varint(headers.length); - headers.forEach(function(header) { - put.put(header); - - // Indicate 0 transactions - put.word8(0); - }); - this.sendMessage('headers', put.buffer()); -}; - -Connection.prototype.sendTx = function(tx) { - this.sendMessage('tx', tx.serialize()); -}; - -Connection.prototype.sendBlock = function(block, txs) { - var put = new Put(); - - // Block header - put.put(block.getHeader()); - - // List of transactions - put.varint(txs.length); - txs.forEach(function(tx) { - put.put(tx.serialize()); - }); - - this.sendMessage('block', put.buffer()); -}; - -Connection.prototype.sendMessage = function(command, payload) { - try { - var magic = this.network.magic; - var commandBuf = new Buffer(command, 'ascii'); - if (commandBuf.length > 12) throw 'Command name too long'; - - var checksum; - if (this.sendVer >= 209) { - checksum = doubleSha256(payload).slice(0, 4); - } else { - checksum = new Buffer([]); - } - - var message = new Put(); // -- HEADER -- - message.put(magic); // magic bytes - message.put(commandBuf); // command name - message.pad(12 - commandBuf.length); // zero-padded - message.word32le(payload.length); // payload length - message.put(checksum); // checksum - // -- BODY -- - message.put(payload); // payload data - - var buffer = message.buffer(); - - log.debug('[' + this.peer + '] ' + - 'Sending message ' + command + ' (' + payload.length + ' bytes)'); - - this.socket.write(buffer); - } catch (err) { - // TODO: We should catch this error one level higher in order to better - // determine how to react to it. For now though, ignoring it will do. - log.err('Error while sending message to peer ' + this.peer + ': ' + - (err.stack ? err.stack : err.toString())); - } -}; - -Connection.prototype.handleData = function(data) { - this.buffers.push(data); - - if (this.buffers.length > MAX_RECEIVE_BUFFER) { - log.err('Peer ' + this.peer + ' exceeded maxreceivebuffer, disconnecting.' + - (err.stack ? err.stack : err.toString())); - this.socket.destroy(); - return; - } - - this.processData(); -}; - -Connection.prototype.processData = function() { - // If there are less than 20 bytes there can't be a message yet. - if (this.buffers.length < 20) return; - - var magic = this.network.magic; - var i = 0; - for (;;) { - if (this.buffers.get(i) === magic[0] && - this.buffers.get(i + 1) === magic[1] && - this.buffers.get(i + 2) === magic[2] && - this.buffers.get(i + 3) === magic[3]) { - if (i !== 0) { - log.debug('[' + this.peer + '] ' + - 'Received ' + i + - ' bytes of inter-message garbage: '); - log.debug('... ' + this.buffers.slice(0, i)); - - this.buffers.skip(i); - } - break; - } - - if (i > (this.buffers.length - 4)) { - this.buffers.skip(i); - return; - } - i++; - } - - var payloadLen = (this.buffers.get(16)) + - (this.buffers.get(17) << 8) + - (this.buffers.get(18) << 16) + - (this.buffers.get(19) << 24); - - var startPos = (this.recvVer >= 209) ? 24 : 20; - var endPos = startPos + payloadLen; - - if (this.buffers.length < endPos) return; - - var command = this.buffers.slice(4, 16).toString('ascii').replace(/\0+$/, ''); - var payload = this.buffers.slice(startPos, endPos); - var checksum = (this.recvVer >= 209) ? this.buffers.slice(20, 24) : null; - - log.debug('[' + this.peer + '] ' + - 'Received message ' + command + - ' (' + payloadLen + ' bytes)'); - - if (checksum !== null) { - var checksumConfirm = doubleSha256(payload).slice(0, 4); - if (buffertools.compare(checksumConfirm, checksum) !== 0) { - log.err('[' + this.peer + '] ' + - 'Checksum failed', { - cmd: command, - expected: checksumConfirm.toString('hex'), - actual: checksum.toString('hex') - }); - return; - } - } - - var message; - try { - message = this.parseMessage(command, payload); - } catch (e) { - log.err('Error while parsing message ' + command + ' from ' + - this.peer + ':\n' + - (e.stack ? e.stack : e.toString())); - } - - if (message) { - this.handleMessage(message); - } - - this.buffers.skip(endPos); - this.processData(); -}; - -Connection.prototype.parseMessage = function(command, payload) { - var parser = new Parser(payload); - - var data = { - command: command - }; - - var i; - - switch (command) { - case 'version': // https://en.bitcoin.it/wiki/Protocol_specification#version - data.version = parser.word32le(); - data.services = parser.word64le(); - data.timestamp = parser.word64le(); - data.addr_me = parser.buffer(26); - data.addr_you = parser.buffer(26); - data.nonce = parser.buffer(8); - data.subversion = parser.varStr(); - data.start_height = parser.word32le(); - break; - - case 'inv': - case 'getdata': - data.count = parser.varInt(); - - data.invs = []; - for (i = 0; i < data.count; i++) { - data.invs.push({ - type: parser.word32le(), - hash: parser.buffer(32) - }); - } - break; - - case 'headers': - data.count = parser.varInt(); - - data.headers = []; - for (i = 0; i < data.count; i++) { - var header = new Block(); - header.parse(parser); - data.headers.push(header); - } - break; - - case 'block': - var block = new Block(); - block.parse(parser); - - data.block = block; - data.version = block.version; - data.prev_hash = block.prev_hash; - data.merkle_root = block.merkle_root; - data.timestamp = block.timestamp; - data.bits = block.bits; - data.nonce = block.nonce; - - data.txs = block.txs; - - data.size = payload.length; - break; - - case 'tx': - var tx = new Transaction(); - tx.parse(parser); - return { - command: command, - version: tx.version, - lock_time: tx.lock_time, - ins: tx.ins, - outs: tx.outs, - tx: tx, - }; - - case 'getblocks': - case 'getheaders': - // parse out the version - data.version = parser.word32le(); - - // TODO: Limit block locator size? - // reference implementation limits to 500 results - var startCount = parser.varInt(); - - data.starts = []; - for (i = 0; i < startCount; i++) { - data.starts.push(parser.buffer(32)); - } - data.stop = parser.buffer(32); - break; - - case 'addr': - var addrCount = parser.varInt(); - - // Enforce a maximum number of addresses per message - if (addrCount > 1000) { - addrCount = 1000; - } - - data.addrs = []; - for (i = 0; i < addrCount; i++) { - // TODO: Time actually depends on the version of the other peer (>=31402) - data.addrs.push({ - time: parser.word32le(), - services: parser.word64le(), - ip: parser.buffer(16), - port: parser.word16be() - }); - } - break; - - case 'alert': - data.payload = parser.varStr(); - data.signature = parser.varStr(); - break; - - case 'ping': - if (this.recvVer > BIP0031_VERSION) { - data.nonce = parser.buffer(8); - } - break; - - case 'getaddr': - case 'verack': - case 'reject': - // Empty message, nothing to parse - break; - - default: - log.err('Connection.parseMessage(): Command not implemented', { - cmd: command - }); - - // This tells the calling function not to issue an event - return null; - } - - return data; -}; - -module.exports = Connection; - -}).call(this,require("buffer").Buffer) -},{"../config":"4itQ50","../networks":"ULNIu2","../patches/Buffers.monkey":"kytKTK","../util":191,"../util/BinaryParser":"b3ZSD7","../util/log":"AdF7pF","./Block":"pJEQEB","./SecureRandom":"p4SiC2","./Transaction":"LJhYtm","buffer":95,"bufferput":"aXRuS6","buffers":"OBo3aV","buffertools":"fugeBw","events":"T9Wsc/","socks5-client":172,"util":128}],"ez/meX":[function(require,module,exports){ -exports.intFromCompact = function(c) { - var bytes = ((c >>> 24) & 0xff) >>> 0; - var v = ((c & 0xffffff) << (8 * (bytes - 3))) >>> 0; - return v; -} - -},{}],"./lib/Deserialize":[function(require,module,exports){ -module.exports=require('ez/meX'); -},{}],"./lib/Electrum":[function(require,module,exports){ -module.exports=require('hdzBvq'); -},{}],"hdzBvq":[function(require,module,exports){ -(function (Buffer){ -var Key = require('./Key'), - Point = require('./Point'), - twoSha256 = require('../util').twoSha256, - buffertools = require('buffertools'), - bignum = require('bignum'); - -/** - * Pre-BIP32 Electrum public key derivation (electrum <2.0) - * - * For now, this class can only understands master public keys. - * It doesn't support derivation from a private master key (TODO). - * - * @example examples/ElectrumMPK.js - */ -function Electrum(master_public_key) { - this.mpk = new Buffer(master_public_key, 'hex'); -} - -Electrum.prototype.getSequence = function(for_change, n) { - var mode = for_change ? 1 : 0; - var buf = Buffer.concat([new Buffer(n + ':' + mode + ':', 'utf8'), this.mpk]); - return bignum.fromBuffer(twoSha256(buf)); -}; - -Electrum.prototype.generatePubKey = function(n, for_change) { - var x = bignum.fromBuffer(this.mpk.slice(0, 32), { - size: 32 - }); - var y = bignum.fromBuffer(this.mpk.slice(32, 64), { - size: 32 - }); - var mpk_pt = new Point(x, y); - - var sequence = this.getSequence(for_change, n); - var sequence_key = new Key(); - sequence_key.private = sequence.toBuffer(); - sequence_key.regenerateSync(); - sequence_key.compressed = false; - - var sequence_pt = Point.fromUncompressedPubKey(sequence_key.public); - - pt = Point.add(mpk_pt, sequence_pt); - - var xbuf = pt.x.toBuffer({ - size: 32 - }); - var ybuf = pt.y.toBuffer({ - size: 32 - }); - var prefix = new Buffer([0x04]); - - var key = new Key(); - key.compressed = false; - key.public = Buffer.concat([prefix, xbuf, ybuf]); - - return key.public; -}; - -Electrum.prototype.generateChangePubKey = function(sequence) { - return this.generatePubKey(sequence, true); -}; - -module.exports = Electrum; - -}).call(this,require("buffer").Buffer) -},{"../util":191,"./Key":"ALJ4PS","./Point":"6tXgqr","bignum":61,"buffer":95,"buffertools":"fugeBw"}],"./lib/HierarchicalKey":[function(require,module,exports){ -module.exports=require('x1O6JW'); -},{}],"x1O6JW":[function(require,module,exports){ -(function (Buffer){ -var base58 = require('./Base58').base58; -var coinUtil = require('../util'); -var Key = require('./Key'); -var Point = require('./Point'); -var SecureRandom = require('./SecureRandom'); -var bignum = require('bignum'); -var networks = require('../networks'); - -var secp256k1_n = new bignum('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16); -var secp256k1_Gx = new bignum('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16); - -/* -random new HierarchicalKey: new HierarchicalKey(); -from extended public or private key: new HierarchicalKey(str); -new blank HierarchicalKey: new HierarchicalKey(null); -*/ -var HierarchicalKey = function(bytes) { - if (typeof bytes == 'undefined' || bytes == 'mainnet' || bytes == 'livenet') { - bytes = 'livenet'; - this.version = networks['livenet'].hkeyPrivateVersion; - } else if (bytes == 'testnet') { - this.version = networks['testnet'].hkeyPrivateVersion; - } - if (bytes == 'livenet' || bytes == 'testnet') { - this.depth = 0x00; - this.parentFingerprint = new Buffer([0, 0, 0, 0]); - this.childIndex = new Buffer([0, 0, 0, 0]); - this.chainCode = SecureRandom.getRandomBuffer(32); - this.eckey = Key.generateSync(); - this.hasPrivateKey = true; - this.pubKeyHash = coinUtil.sha256ripe160(this.eckey.public); - this.buildExtendedPublicKey(); - this.buildExtendedPrivateKey(); - return; - } - - // decode base58 - if (typeof bytes === 'string') { - var decoded = base58.decode(bytes); - if (decoded.length != 82) - throw new Error('Not enough data, expected 82 and received ' + decoded.length); - var checksum = decoded.slice(78, 82); - bytes = decoded.slice(0, 78); - - var hash = coinUtil.sha256(coinUtil.sha256(bytes)); - - if (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) { - throw new Error('Invalid checksum'); - } - } - - if (bytes !== undefined && bytes !== null) - this.initFromBytes(bytes); -} - -HierarchicalKey.seed = function(bytes, network) { - if (!network) - network = 'livenet'; - - if (!Buffer.isBuffer(bytes)) - bytes = new Buffer(bytes, 'hex'); //if not buffer, assume hex - if (bytes.length < 128 / 8) - return false; //need more entropy - if (bytes.length > 512 / 8) - return false; - var hash = coinUtil.sha512hmac(bytes, new Buffer('Bitcoin seed')); - - var hkey = new HierarchicalKey(null); - hkey.depth = 0x00; - hkey.parentFingerprint = new Buffer([0, 0, 0, 0]); - hkey.childIndex = new Buffer([0, 0, 0, 0]); - hkey.chainCode = hash.slice(32, 64); - hkey.version = networks[network].hkeyPrivateVersion; - hkey.eckey = new Key(); - hkey.eckey.private = hash.slice(0, 32); - hkey.eckey.regenerateSync(); - hkey.hasPrivateKey = true; - hkey.pubKeyHash = coinUtil.sha256ripe160(hkey.eckey.public); - - hkey.buildExtendedPublicKey(); - hkey.buildExtendedPrivateKey(); - - return hkey; -}; - -HierarchicalKey.prototype.initFromBytes = function(bytes) { - // Both pub and private extended keys are 78 bytes - if (bytes.length != 78) throw new Error('not enough data'); - - this.version = u32(bytes.slice(0, 4)); - this.depth = u8(bytes.slice(4, 5)); - this.parentFingerprint = bytes.slice(5, 9); - this.childIndex = u32(bytes.slice(9, 13)); - this.chainCode = bytes.slice(13, 45); - - var keyBytes = bytes.slice(45, 78); - - var isPrivate = - (this.version == networks['livenet'].hkeyPrivateVersion || - this.version == networks['testnet'].hkeyPrivateVersion); - - var isPublic = - (this.version == networks['livenet'].hkeyPublicVersion || - this.version == networks['testnet'].hkeyPublicVersion); - - if (isPrivate && keyBytes[0] == 0) { - this.eckey = new Key(); - this.eckey.private = keyBytes.slice(1, 33); - this.eckey.compressed = true; - this.eckey.regenerateSync(); - this.pubKeyHash = coinUtil.sha256ripe160(this.eckey.public); - this.hasPrivateKey = true; - } else if (isPublic && (keyBytes[0] == 0x02 || keyBytes[0] == 0x03)) { - this.eckey = new Key(); - this.eckey.public = keyBytes; - this.pubKeyHash = coinUtil.sha256ripe160(this.eckey.public); - this.hasPrivateKey = false; - } else { - throw new Error('Invalid key'); - } - - this.buildExtendedPublicKey(); - this.buildExtendedPrivateKey(); -} - -HierarchicalKey.prototype.buildExtendedPublicKey = function() { - this.extendedPublicKey = new Buffer([]); - - var v = null; - switch (this.version) { - case networks['livenet'].hkeyPublicVersion: - case networks['livenet'].hkeyPrivateVersion: - v = networks['livenet'].hkeyPublicVersion; - break; - case networks['testnet'].hkeyPublicVersion: - case networks['testnet'].hkeyPrivateVersion: - v = networks['testnet'].hkeyPublicVersion; - break; - default: - throw new Error('Unknown version'); - } - - // Version - this.extendedPublicKey = Buffer.concat([ - new Buffer([v >> 24]), - new Buffer([(v >> 16) & 0xff]), - new Buffer([(v >> 8) & 0xff]), - new Buffer([v & 0xff]), - new Buffer([this.depth]), - this.parentFingerprint, - new Buffer([this.childIndex >>> 24]), - new Buffer([(this.childIndex >>> 16) & 0xff]), - new Buffer([(this.childIndex >>> 8) & 0xff]), - new Buffer([this.childIndex & 0xff]), - this.chainCode, - this.eckey.public - ]); -} - -HierarchicalKey.prototype.extendedPublicKeyString = function(format) { - if (format === undefined || format === 'base58') { - var hash = coinUtil.sha256(coinUtil.sha256(this.extendedPublicKey)); - var checksum = hash.slice(0, 4); - var data = Buffer.concat([this.extendedPublicKey, checksum]); - return base58.encode(data); - } else if (format === 'hex') { - return this.extendedPublicKey.toString('hex');; - } else { - throw new Error('bad format'); - } -} - -HierarchicalKey.prototype.buildExtendedPrivateKey = function() { - if (!this.hasPrivateKey) return; - this.extendedPrivateKey = new Buffer([]); - - var v = this.version; - - this.extendedPrivateKey = Buffer.concat([ - new Buffer([v >> 24]), - new Buffer([(v >> 16) & 0xff]), - new Buffer([(v >> 8) & 0xff]), - new Buffer([v & 0xff]), - new Buffer([this.depth]), - this.parentFingerprint, - new Buffer([this.childIndex >>> 24]), - new Buffer([(this.childIndex >>> 16) & 0xff]), - new Buffer([(this.childIndex >>> 8) & 0xff]), - new Buffer([this.childIndex & 0xff]), - this.chainCode, - new Buffer([0]), - this.eckey.private - ]); -} - -HierarchicalKey.prototype.extendedPrivateKeyString = function(format) { - if (format === undefined || format === 'base58') { - var hash = coinUtil.sha256(coinUtil.sha256(this.extendedPrivateKey)); - var checksum = hash.slice(0, 4); - var data = Buffer.concat([this.extendedPrivateKey, checksum]); - return base58.encode(data); - } else if (format === 'hex') { - return this.extendedPrivateKey.toString('hex'); - } else { - throw new Error('bad format'); - } -} - - -HierarchicalKey.prototype.derive = function(path) { - var e = path.split('/'); - - // Special cases: - if (path == 'm' || path == 'M' || path == 'm\'' || path == 'M\'') - return this; - - var hkey = this; - for (var i in e) { - var c = e[i]; - - if (i == 0) { - if (c != 'm') throw new Error('invalid path'); - continue; - } - - var usePrivate = (c.length > 1) && (c[c.length - 1] == '\''); - var childIndex = parseInt(usePrivate ? c.slice(0, c.length - 1) : c) & 0x7fffffff; - - if (usePrivate) - childIndex += 0x80000000; - - hkey = hkey.deriveChild(childIndex); - } - - return hkey; -} - -HierarchicalKey.prototype.deriveChild = function(i) { - var ib = []; - ib.push((i >> 24) & 0xff); - ib.push((i >> 16) & 0xff); - ib.push((i >> 8) & 0xff); - ib.push(i & 0xff); - ib = new Buffer(ib); - - var usePrivate = (i & 0x80000000) != 0; - - var isPrivate = - (this.version == networks['livenet'].hkeyPrivateVersion || - this.version == networks['testnet'].hkeyPrivateVersion); - - if (usePrivate && (!this.hasPrivateKey || !isPrivate)) - throw new Error('Cannot do private key derivation without private key'); - - var ret = null; - if (this.hasPrivateKey) { - var data = null; - - if (usePrivate) { - data = Buffer.concat([new Buffer([0]), this.eckey.private, ib]); - } else { - data = Buffer.concat([this.eckey.public, ib]); - } - - var hash = coinUtil.sha512hmac(data, this.chainCode); - var il = bignum.fromBuffer(hash.slice(0, 32), { - size: 32 - }); - var ir = hash.slice(32, 64); - - // ki = IL + kpar (mod n). - var priv = bignum.fromBuffer(this.eckey.private, { - size: 32 - }); - var k = il.add(priv).mod(secp256k1_n); - - ret = new HierarchicalKey(null); - ret.chainCode = ir; - - ret.eckey = new Key(); - ret.eckey.private = k.toBuffer({ - size: 32 - }); - ret.eckey.regenerateSync(); - ret.hasPrivateKey = true; - - } else { - var data = Buffer.concat([this.eckey.public, ib]); - var hash = coinUtil.sha512hmac(data, this.chainCode); - var il = hash.slice(0, 32); - var ir = hash.slice(32, 64); - - // Ki = (IL + kpar)*G = IL*G + Kpar - var ilGkey = new Key(); - ilGkey.private = il; - ilGkey.regenerateSync(); - ilGkey.compressed = false; - var ilG = Point.fromUncompressedPubKey(ilGkey.public); - var oldkey = new Key(); - oldkey.public = this.eckey.public; - oldkey.compressed = false; - var Kpar = Point.fromUncompressedPubKey(oldkey.public); - var newpub = Point.add(ilG, Kpar).toUncompressedPubKey(); - - ret = new HierarchicalKey(null); - ret.chainCode = new Buffer(ir); - - var eckey = new Key(); - eckey.public = newpub; - eckey.compressed = true; - ret.eckey = eckey; - ret.hasPrivateKey = false; - } - - ret.childIndex = i; - ret.parentFingerprint = this.pubKeyHash.slice(0, 4); - ret.version = this.version; - ret.depth = this.depth + 1; - - ret.eckey.compressed = true; - ret.pubKeyHash = coinUtil.sha256ripe160(ret.eckey.public); - - ret.buildExtendedPublicKey(); - ret.buildExtendedPrivateKey(); - - return ret; -} - - -function uint(f, size) { - if (f.length < size) - throw new Error('not enough data'); - var n = 0; - for (var i = 0; i < size; i++) { - n *= 256; - n += f[i]; - } - return n; -} - -function u8(f) { - return uint(f, 1); -} - -function u16(f) { - return uint(f, 2); -} - -function u32(f) { - return uint(f, 4); -} - -function u64(f) { - return uint(f, 8); -} - -module.exports = HierarchicalKey; - -}).call(this,require("buffer").Buffer) -},{"../networks":"ULNIu2","../util":191,"./Base58":"6VqyzY","./Key":"ALJ4PS","./Point":"6tXgqr","./SecureRandom":"p4SiC2","bignum":61,"buffer":95}],"CBDCgz":[function(require,module,exports){ -(function (Buffer){ -'use strict'; -var coinUtil = require('../util'); -var Key = require('./Key'); - -var Message = function() {}; - -Message.sign = function(str, key) { - var hash = Message.magicHash(str); - var sig = key.signSync(hash); - return sig; -}; - -Message.verifyWithPubKey = function(pubkey, message, sig) { - var hash = Message.magicHash(message); - var key = new Key(); - if (pubkey.length == 65) - key.compressed = false; - key.public = pubkey; - - return key.verifySignatureSync(hash, sig); -}; - -//TODO: Message.verify ... with address, not pubkey - -Message.magicBytes = new Buffer('Bitcoin Signed Message:\n'); - -Message.magicHash = function(str) { - var magicBytes = Message.magicBytes; - var prefix1 = coinUtil.varIntBuf(magicBytes.length); - var message = new Buffer(str); - var prefix2 = coinUtil.varIntBuf(message.length); - - var buf = Buffer.concat([prefix1, magicBytes, prefix2, message]); - - var hash = coinUtil.twoSha256(buf); - - return hash; -}; - -module.exports = Message; - -}).call(this,require("buffer").Buffer) -},{"../util":191,"./Key":"ALJ4PS","buffer":95}],"./lib/Message":[function(require,module,exports){ -module.exports=require('CBDCgz'); -},{}],"./lib/NetworkMonitor":[function(require,module,exports){ -module.exports=require('qYkfjX'); -},{}],"qYkfjX":[function(require,module,exports){ -var log = require('../util/log'); -var networks = require('../networks'); -var Address = require('./Address'); -var Peer = require('./Peer'); -var PeerManager = require('./PeerManager'); -var util = require('util'); -var EventEmitter = require('events').EventEmitter; -var preconditions = require('preconditions').singleton(); - -var NetworkMonitor = function(peerman) { - preconditions.checkArgument(peerman); - this.peerman = peerman; - this.networkName = peerman.config.network; - this.init(); -} - -util.inherits(NetworkMonitor, EventEmitter); - -NetworkMonitor.create = function(config) { - this.config = config; - var peerman = new PeerManager({ - network: config.networkName - }); - - peerman.addPeer(new Peer(config.host, config.port)); - return new NetworkMonitor(peerman); -}; - -NetworkMonitor.prototype.init = function() { - var self = this; - var handleInv = function(info) { - var invs = info.message.invs; - info.conn.sendGetData(invs); - }; - - var handleBlock = function(info) { - self.emit('block', info.message); - }; - - var handleTx = function(info) { - var tx = info.message.tx; - self.emit('tx', tx); - - var from = tx.getSendingAddresses(self.networkName); - for (var i = 0; i < from.length; i++) { - var addr = from[i]; - self.emit('out:'+addr, tx); - } - var to = tx.getReceivingAddresses(self.networkName); - for (var i = 0; i < to.length; i++) { - var addr = to[i]; - self.emit('in:'+addr, tx); - } - }; - - this.peerman.on('connection', function(conn) { - if (self.connection) throw new Error('Cant handle more than one connection'); - self.connection = conn; - conn.on('inv', handleInv); - conn.on('block', handleBlock); - conn.on('tx', handleTx); - }); -}; - -NetworkMonitor.prototype.incoming = function(addrStr, callback) { - preconditions.checkArgument(Address.validate(addrStr)); - this.on('in:'+addrStr, callback); -}; - -NetworkMonitor.prototype.outgoing = function(addrStr, callback) { - preconditions.checkArgument(Address.validate(addrStr)); - this.on('out:'+addrStr, callback); -}; - -NetworkMonitor.prototype.start = function() { - this.peerman.start(); -}; - -NetworkMonitor.prototype.stop = function() { - this.peerman.stop(); -}; - -module.exports = NetworkMonitor; - -},{"../networks":"ULNIu2","../util/log":"AdF7pF","./Address":"G+CcXD","./Peer":"oolY81","./PeerManager":"nsqKeP","events":"T9Wsc/","preconditions":163,"util":128}],"Zm7/h9":[function(require,module,exports){ -function Opcode(num) { - this.code = num; -}; - -Opcode.prototype.toString = function() { - return Opcode.reverseMap[this.code]; -}; - -Opcode.map = { - // push value - OP_FALSE: 0, - OP_0: 0, - OP_PUSHDATA1: 76, - OP_PUSHDATA2: 77, - OP_PUSHDATA4: 78, - OP_1NEGATE: 79, - OP_RESERVED: 80, - OP_TRUE: 81, - OP_1: 81, - OP_2: 82, - OP_3: 83, - OP_4: 84, - OP_5: 85, - OP_6: 86, - OP_7: 87, - OP_8: 88, - OP_9: 89, - OP_10: 90, - OP_11: 91, - OP_12: 92, - OP_13: 93, - OP_14: 94, - OP_15: 95, - OP_16: 96, - - // control - OP_NOP: 97, - OP_VER: 98, - OP_IF: 99, - OP_NOTIF: 100, - OP_VERIF: 101, - OP_VERNOTIF: 102, - OP_ELSE: 103, - OP_ENDIF: 104, - OP_VERIFY: 105, - OP_RETURN: 106, - - // stack ops - OP_TOALTSTACK: 107, - OP_FROMALTSTACK: 108, - OP_2DROP: 109, - OP_2DUP: 110, - OP_3DUP: 111, - OP_2OVER: 112, - OP_2ROT: 113, - OP_2SWAP: 114, - OP_IFDUP: 115, - OP_DEPTH: 116, - OP_DROP: 117, - OP_DUP: 118, - OP_NIP: 119, - OP_OVER: 120, - OP_PICK: 121, - OP_ROLL: 122, - OP_ROT: 123, - OP_SWAP: 124, - OP_TUCK: 125, - - // splice ops - OP_CAT: 126, - OP_SUBSTR: 127, - OP_LEFT: 128, - OP_RIGHT: 129, - OP_SIZE: 130, - - // bit logic - OP_INVERT: 131, - OP_AND: 132, - OP_OR: 133, - OP_XOR: 134, - OP_EQUAL: 135, - OP_EQUALVERIFY: 136, - OP_RESERVED1: 137, - OP_RESERVED2: 138, - - // numeric - OP_1ADD: 139, - OP_1SUB: 140, - OP_2MUL: 141, - OP_2DIV: 142, - OP_NEGATE: 143, - OP_ABS: 144, - OP_NOT: 145, - OP_0NOTEQUAL: 146, - - OP_ADD: 147, - OP_SUB: 148, - OP_MUL: 149, - OP_DIV: 150, - OP_MOD: 151, - OP_LSHIFT: 152, - OP_RSHIFT: 153, - - OP_BOOLAND: 154, - OP_BOOLOR: 155, - OP_NUMEQUAL: 156, - OP_NUMEQUALVERIFY: 157, - OP_NUMNOTEQUAL: 158, - OP_LESSTHAN: 159, - OP_GREATERTHAN: 160, - OP_LESSTHANOREQUAL: 161, - OP_GREATERTHANOREQUAL: 162, - OP_MIN: 163, - OP_MAX: 164, - - OP_WITHIN: 165, - - // crypto - OP_RIPEMD160: 166, - OP_SHA1: 167, - OP_SHA256: 168, - OP_HASH160: 169, - OP_HASH256: 170, - OP_CODESEPARATOR: 171, - OP_CHECKSIG: 172, - OP_CHECKSIGVERIFY: 173, - OP_CHECKMULTISIG: 174, - OP_CHECKMULTISIGVERIFY: 175, - - // expansion - OP_NOP1: 176, - OP_NOP2: 177, - OP_NOP3: 178, - OP_NOP4: 179, - OP_NOP5: 180, - OP_NOP6: 181, - OP_NOP7: 182, - OP_NOP8: 183, - OP_NOP9: 184, - OP_NOP10: 185, - - // template matching params - OP_PUBKEYHASH: 253, - OP_PUBKEY: 254, - OP_INVALIDOPCODE: 255 -}; - -Opcode.reverseMap = []; - -for (var k in Opcode.map) { - if (Opcode.map.hasOwnProperty(k)) { - Opcode.reverseMap[Opcode.map[k]] = k.substr(3); - } -} - -Opcode.asList = function() { - var keys = []; - for (var prop in Opcode.map) { - if (Opcode.map.hasOwnProperty(prop)) { - keys.push(prop); - } - } - return keys; -}; - -module.exports = Opcode; - -},{}],"./lib/Opcode":[function(require,module,exports){ -module.exports=require('Zm7/h9'); -},{}],"./lib/Peer":[function(require,module,exports){ -module.exports=require('oolY81'); -},{}],"oolY81":[function(require,module,exports){ -(function (Buffer){ -var Net = require('net'); -var Binary = require('binary'); -var buffertools = require('buffertools'); - -function Peer(host, port, services) { - if ("string" === typeof host) { - if (host.indexOf(':') && !port) { - var parts = host.split(':'); - host = parts[0]; - port = parts[1]; - } - this.host = host; - this.port = +port || 8333; - } else if (host instanceof Peer) { - this.host = host.host; - this.port = host.port; - } else if (Buffer.isBuffer(host)) { - if (buffertools.compare(Peer.IPV6_IPV4_PADDING, host.slice(0, 12)) != 0) { - throw new Error('IPV6 not supported yet! Cannot instantiate host.'); - } - this.host = Array.prototype.slice.apply(host.slice(12)).join('.'); - this.port = +port || 8333; - } else { - throw new Error('Could not instantiate peer, invalid parameter type: ' + - typeof host); - } - - this.services = (services) ? services : null; - this.lastSeen = 0; -}; - -Peer.IPV6_IPV4_PADDING = new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255]); - -Peer.prototype.createConnection = function() { - this.connection = Net.createConnection(this.port, this.host); - return this.connection; -}; - -Peer.prototype.getHostAsBuffer = function() { - return new Buffer(this.host.split('.')); -}; - -Peer.prototype.toString = function() { - return this.host + ":" + this.port; -}; - -Peer.prototype.toBuffer = function() { - var put = Binary.put(); - put.word32le(this.lastSeen); - put.word64le(this.services); - put.put(this.getHostAsBuffer()); - put.word16be(this.port); - return put.buffer(); -}; - -module.exports = Peer; - -}).call(this,require("buffer").Buffer) -},{"binary":83,"buffer":95,"buffertools":"fugeBw","net":91}],"./lib/PeerManager":[function(require,module,exports){ -module.exports=require('nsqKeP'); -},{}],"nsqKeP":[function(require,module,exports){ -var log = require('../util/log'); -var bitcoreDefaults = require('../config'); -var Connection = require('./Connection'); -var Peer = require('./Peer'); -var async = require('async'); -var dns = require('dns'); -var networks = require('../networks'); -var util = require('util'); - -GetAdjustedTime = function() { - // TODO: Implement actual adjustment - return Math.floor(new Date().getTime() / 1000); -}; - -function PeerManager(config) { - // extend defaults with config - this.config = config || {}; - for (var i in bitcoreDefaults) - if (bitcoreDefaults.hasOwnProperty(i) && this.config[i] === undefined) - this.config[i] = bitcoreDefaults[i]; - - this.active = false; - this.timer = null; - - this.peers = []; - this.pool = []; - this.connections = []; - this.isConnected = false; - this.peerDiscovery = false; - - // Move these to the Node's settings object - this.interval = 5000; - this.minConnections = 8; - this.minKnownPeers = 10; - - // keep track of tried seeds and results - this.seeds = { - resolved: [], - failed: [] - }; -} - -var EventEmitter = require('events').EventEmitter; -util.inherits(PeerManager, EventEmitter); -PeerManager.Connection = Connection; - -PeerManager.prototype.start = function() { - this.active = true; - if (!this.timer) { - this.timer = setInterval(this.checkStatus.bind(this), this.interval); - } -}; - -PeerManager.prototype.stop = function() { - this.active = false; - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - for (var i = 0; i < this.connections.length; i++) { - this.connections[i].socket.end(); - }; -}; - -PeerManager.prototype.addPeer = function(peer, port) { - if (peer instanceof Peer) { - this.peers.push(peer); - } else if ("string" == typeof peer) { - this.addPeer(new Peer(peer, port)); - } else { - log.err('Node.addPeer(): Invalid value provided for peer', { - val: peer - }); - throw 'Node.addPeer(): Invalid value provided for peer.'; - } -}; - -PeerManager.prototype.removePeer = function(peer) { - var index = this.peers.indexOf(peer); - var exists = !!~index; - if (exists) this.peers.splice(index, 1); - return exists; -}; - -PeerManager.prototype.checkStatus = function checkStatus() { - // Make sure we are connected to all forcePeers - if (this.peers.length) { - var peerIndex = {}; - this.peers.forEach(function(peer) { - peerIndex[peer.toString()] = peer; - }); - - // Ignore the ones we're already connected to - this.connections.forEach(function(conn) { - var peerName = conn.peer.toString(); - if ("undefined" !== peerIndex[peerName]) { - delete peerIndex[peerName]; - } - }); - - // for debug purposes, print how many of our peers are actually connected - var connected = 0 - this.peers.forEach(function(p) { - if (p.connection && !p.connection._connecting) connected++ - }); - log.debug(connected + ' of ' + this.peers.length + ' peers connected'); - - Object.keys(peerIndex).forEach(function(i) { - this.connectTo(peerIndex[i]); - }.bind(this)); - } -}; - -PeerManager.prototype.connectTo = function(peer) { - log.info('connecting to ' + peer); - try { - return this.addConnection(peer.createConnection(), peer); - } catch (e) { - log.err('creating connection', e); - return null; - } -}; - -PeerManager.prototype.addConnection = function(socketConn, peer) { - var conn = new Connection(socketConn, peer, this.config); - this.connections.push(conn); - this.emit('connection', conn); - - conn.addListener('version', this.handleVersion.bind(this)); - conn.addListener('verack', this.handleReady.bind(this)); - conn.addListener('addr', this.handleAddr.bind(this)); - conn.addListener('getaddr', this.handleGetAddr.bind(this)); - conn.addListener('error', this.handleError.bind(this)); - conn.addListener('disconnect', this.handleDisconnect.bind(this)); - - return conn; -}; - -PeerManager.prototype.handleVersion = function(e) { - e.peer.version = e.message.version; - e.peer.start_height = e.message.start_height; - - if (!e.conn.inbound) { - // TODO: Advertise our address (if listening) - } - // Get recent addresses - if (this.peerDiscovery && - (e.message.version >= 31402 || this.peers.length < 1000)) { - e.conn.sendGetAddr(); - e.conn.getaddr = true; - } -}; - -PeerManager.prototype.handleReady = function(e) { - log.info('connected to ' + e.conn.peer.host + ':' + e.conn.peer.port); - this.emit('connect', { - pm: this, - conn: e.conn, - socket: e.socket, - peer: e.peer - }); - - if (this.isConnected == false) { - this.emit('netConnected', e); - this.isConnected = true; - } -}; - -PeerManager.prototype.handleAddr = function(e) { - if (!this.peerDiscovery) return; - - var now = GetAdjustedTime(); - e.message.addrs.forEach(function(addr) { - try { - // In case of an invalid time, assume "5 days ago" - if (addr.time <= 100000000 || addr.time > (now + 10 * 60)) { - addr.time = now - 5 * 24 * 60 * 60; - } - var peer = new Peer(addr.ip, addr.port, addr.services); - peer.lastSeen = addr.time; - - // TODO: Handle duplicate peers - this.peers.push(peer); - - // TODO: Handle addr relay - } catch (e) { - log.warn("Invalid addr received: " + e.message); - } - }.bind(this)); - if (e.message.addrs.length < 1000) { - e.conn.getaddr = false; - } -}; - -PeerManager.prototype.handleGetAddr = function(e) { - // TODO: Reply with addr message. -}; - -PeerManager.prototype.handleError = function(e) { - log.err('unkown error with peer ' + e.peer + ' (disconnecting): ' + e.err); - this.handleDisconnect.apply(this, [].slice.call(arguments)); -}; - -PeerManager.prototype.handleDisconnect = function(e) { - log.info('disconnected from peer ' + e.peer); - var i = this.connections.indexOf(e.conn); - if (i != -1) this.connections.splice(i, 1); - - this.removePeer(e.peer); - if (this.pool.length) { - log.info('replacing peer using the pool of ' + this.pool.length + ' seeds'); - this.addPeer(this.pool.pop()); - } - - if (!this.connections.length) { - this.emit('netDisconnected'); - this.isConnected = false; - } -}; - -PeerManager.prototype.getActiveConnection = function() { - var activeConnections = this.connections.filter(function(conn) { - return conn.active; - }); - - if (activeConnections.length) { - var randomIndex = Math.floor(Math.random() * activeConnections.length); - var candidate = activeConnections[randomIndex]; - if (candidate.socket.writable) { - return candidate; - } else { - // Socket is not writable, remove it from active connections - activeConnections.splice(randomIndex, 1); - - // Then try again - // TODO: This causes an infinite recursion when all connections are dead, - // although it shouldn't. - return this.getActiveConnection(); - } - } else { - return null; - } -}; - -PeerManager.prototype.getActiveConnections = function() { - return this.connections.slice(0); -}; - -PeerManager.prototype.discover = function(options, callback) { - var self = this; - var seeds = networks[self.config.network].dnsSeeds; - - self.limit = options.limit || 12; - - var dnsExecutor = seeds.map(function(seed) { - return function(done) { - // have we already resolved this seed? - if (~self.seeds.resolved.indexOf(seed)) { - // if so, just pass back cached peer list - return done(null, self.seeds.results[seed]); - } - - // has this seed failed to resolve? - if (~self.seeds.failed.indexOf(seed)) { - // if so, pass back empty results - return done(null, []); - } - - log.info('resolving dns seed ' + seed); - - dns.resolve(seed, function(err, peers) { - if (err) { - log.err('failed to resolve dns seed ' + seed, err); - self.seeds.failed.push(seed); - return done(null, []); - } - - log.info('found ' + peers.length + ' peers from ' + seed); - self.seeds.resolved.push(seed); - - // transform that list into a list of Peer instances - peers = peers.map(function(ip) { - return new Peer(ip, networks[self.config.network].defaultClientPort); - }); - - peers.forEach(function(p) { - if (self.peers.length < self.limit) self.addPeer(p); - else self.pool.push(p); - }); - - self.emit('peers', peers); - - return done(null, peers); - }); - - }; - }); - - // try resolving all seeds - async.parallel(dnsExecutor, function(err, results) { - var peers = []; - - // consolidate all resolved peers into one list - results.forEach(function(peerlist) { - peers = peers.concat(peerlist); - }); - - if (typeof callback === 'function') callback(null, peers); - }); - - return self; -}; - -module.exports = PeerManager; - -},{"../config":"4itQ50","../networks":"ULNIu2","../util/log":"AdF7pF","./Connection":"DB/p3X","./Peer":"oolY81","async":82,"dns":91,"events":"T9Wsc/","util":128}],"izTl9z":[function(require,module,exports){ -(function (Buffer){ - -var VersionedData = require('../util/VersionedData'); -var EncodedData = require('../util/EncodedData'); -var networks = require('../networks'); -var util = require('util'); - -//compressed is true if public key is compressed; false otherwise -function PrivateKey(version, buf, compressed) { - PrivateKey.super_.call(this, version, buf); - if (compressed !== undefined) - this.compressed(compressed); -}; -util.inherits(PrivateKey, VersionedData); -EncodedData.applyEncodingsTo(PrivateKey); - -PrivateKey.prototype.validate = function() { - this.doAsBinary(function() { - PrivateKey.super_.prototype.validate.call(this); - if (this.data.length < 32 || (this.data.length > 1 + 32 && !this.compressed()) || (this.data.length == 1 + 32 + 1 && this.data[1 + 32 + 1 - 1] != 1) || this.data.length > 1 + 32 + 1) - throw new Error('invalid data length'); - }); - if (typeof this.network() === 'undefined') throw new Error('invalid network'); -}; - -// get or set the payload data (as a Buffer object) -// overloaded from VersionedData -PrivateKey.prototype.payload = function(data) { - if (data) { - this.doAsBinary(function() { - data.copy(this.data, 1); - }); - return data; - } - var buf = this.as('binary'); - if (buf.length == 1 + 32 + 1) - return buf.slice(1, 1 + 32); - else if (buf.length == 1 + 32) - return buf.slice(1); -}; - -// get or set whether the corresponding public key is compressed -PrivateKey.prototype.compressed = function(compressed) { - if (compressed !== undefined) { - this.doAsBinary(function() { - var len = 1 + 32 + 1; - if (compressed) { - var data = new Buffer(len); - this.data.copy(data); - this.data = data; - this.data[len - 1] = 1; - } else { - this.data = this.data.slice(0, len - 1); - } - }); - } else { - var len = 1 + 32 + 1; - var data = this.as('binary'); - if (data.length == len && data[len - 1] == 1) - return true; - else if (data.length == len - 1) - return false; - else - throw new Error('invalid private key'); - } -}; - -PrivateKey.prototype.network = function() { - var version = this.version(); - - var livenet = networks.livenet; - var testnet = networks.testnet; - - var answer; - if (version === livenet.privKeyVersion) - answer = livenet; - else if (version === testnet.privKeyVersion) - answer = testnet; - - return answer; -}; - -module.exports = PrivateKey; - -}).call(this,require("buffer").Buffer) -},{"../networks":"ULNIu2","../util/EncodedData":"eLfUFE","../util/VersionedData":"QLzNQg","buffer":95,"util":128}],"./lib/PrivateKey":[function(require,module,exports){ -module.exports=require('izTl9z'); -},{}],"./lib/RpcClient":[function(require,module,exports){ -module.exports=require('7siE1N'); -},{}],"7siE1N":[function(require,module,exports){ -(function (Buffer){ -// RpcClient.js -// MIT/X11-like license. See LICENSE.txt. -// Copyright 2013 BitPay, Inc. -// -var http = require('http'); -var https = require('https'); -var log = require('../util/log'); - -function RpcClient(opts) { - opts = opts || {}; - this.host = opts.host || '127.0.0.1'; - this.port = opts.port || 8332; - this.user = opts.user || 'user'; - this.pass = opts.pass || 'pass'; - this.protocol = (opts.protocol == 'http') ? http : https; - this.batchedCalls = null; - this.disableAgent = opts.disableAgent || false; -} - -RpcClient.prototype.batch = function(batchCallback, resultCallback) { - this.batchedCalls = []; - batchCallback(); - rpc.call(this, this.batchedCalls, resultCallback); - this.batchedCalls = null; -} - -var callspec = { - addMultiSigAddress: '', - addNode: '', - backupWallet: '', - createMultiSig: '', - createRawTransaction: '', - decodeRawTransaction: '', - dumpPrivKey: '', - encryptWallet: '', - getAccount: '', - getAccountAddress: 'str', - getAddedNodeInfo: '', - getAddressesByAccount: '', - getBalance: 'str int', - getBestBlockHash: '', - getBlock: '', - getBlockCount: '', - getBlockHash: 'int', - getBlockNumber: '', - getBlockTemplate: '', - getConnectionCount: '', - getDifficulty: '', - getGenerate: '', - getHashesPerSec: '', - getInfo: '', - getMemoryPool: '', - getMiningInfo: '', - getNewAddress: '', - getPeerInfo: '', - getRawMemPool: '', - getRawTransaction: 'str int', - getReceivedByAccount: 'str int', - getReceivedByAddress: 'str int', - getTransaction: '', - getTxOut: 'str int bool', - getTxOutSetInfo: '', - getWork: '', - help: '', - importAddress: 'str str bool', - importPrivKey: 'str str bool', - keyPoolRefill: '', - listAccounts: 'int', - listAddressGroupings: '', - listReceivedByAccount: 'int bool', - listReceivedByAddress: 'int bool', - listSinceBlock: 'str int', - listTransactions: 'str int int', - listUnspent: 'int int', - listLockUnspent: 'bool', - lockUnspent: '', - move: 'str str float int str', - sendFrom: 'str str float int str str', - sendMany: 'str str int str', //not sure this is will work - sendRawTransaction: '', - sendToAddress: 'str float str str', - setAccount: '', - setGenerate: 'bool int', - setTxFee: 'float', - signMessage: '', - signRawTransaction: '', - stop: '', - submitBlock: '', - validateAddress: '', - verifyMessage: '', - walletLock: '', - walletPassPhrase: 'string int', - walletPassphraseChange: '', -}; - -var slice = function(arr, start, end) { - return Array.prototype.slice.call(arr, start, end); -}; - -function generateRPCMethods(constructor, apiCalls, rpc) { - function createRPCMethod(methodName, argMap) { - return function() { - var limit = arguments.length - 1; - if (this.batchedCalls) var limit = arguments.length; - for (var i = 0; i < limit; i++) { - if (argMap[i]) arguments[i] = argMap[i](arguments[i]); - }; - if (this.batchedCalls) { - this.batchedCalls.push({ - jsonrpc: '2.0', - method: methodName, - params: slice(arguments) - }); - } else { - rpc.call(this, { - method: methodName, - params: slice(arguments, 0, arguments.length - 1) - }, arguments[arguments.length - 1]); - } - }; - }; - - var types = { - str: function(arg) { - return arg.toString(); - }, - int: function(arg) { - return parseFloat(arg); - }, - float: function(arg) { - return parseFloat(arg); - }, - bool: function(arg) { - return (arg === true || arg == '1' || arg == 'true' || arg.toString().toLowerCase() == 'true'); - }, - }; - - for (var k in apiCalls) { - if (apiCalls.hasOwnProperty(k)) { - var spec = apiCalls[k].split(' '); - for (var i = 0; i < spec.length; i++) { - if (types[spec[i]]) { - spec[i] = types[spec[i]]; - } else { - spec[i] = types.string; - } - } - var methodName = k.toLowerCase(); - constructor.prototype[k] = createRPCMethod(methodName, spec); - constructor.prototype[methodName] = constructor.prototype[k]; - } - } -} - -function rpc(request, callback) { - var self = this; - var request; - request = JSON.stringify(request); - var auth = Buffer(self.user + ':' + self.pass).toString('base64'); - - var options = { - host: self.host, - path: '/', - method: 'POST', - port: self.port, - agent: self.disableAgent ? false : undefined, - }; - if (self.httpOptions) { - for (var k in self.httpOptions) { - options[k] = self.httpOptions[k]; - } - } - var err = null; - var req = this.protocol.request(options, function(res) { - - var buf = ''; - res.on('data', function(data) { - buf += data; - }); - res.on('end', function() { - if (res.statusCode == 401) { - callback(new Error('bitcoin JSON-RPC connection rejected: 401 unauthorized')); - return; - } - if (res.statusCode == 403) { - callback(new Error('bitcoin JSON-RPC connection rejected: 403 forbidden')); - return; - } - - if (err) { - callback(err); - return; - } - try { - var parsedBuf = JSON.parse(buf); - } catch (e) { - log.err(e.stack); - log.err(buf); - log.err('HTTP Status code:' + res.statusCode); - callback(e); - return; - } - callback(parsedBuf.error, parsedBuf); - }); - }); - req.on('error', function(e) { - var err = new Error('Could not connect to bitcoin via RPC: ' + e.message); - log.err(err); - callback(err); - }); - - req.setHeader('Content-Length', request.length); - req.setHeader('Content-Type', 'application/json'); - req.setHeader('Authorization', 'Basic ' + auth); - req.write(request); - req.end(); -}; - -generateRPCMethods(RpcClient, callspec, rpc); - -module.exports = RpcClient; - -}).call(this,require("buffer").Buffer) -},{"../util/log":"AdF7pF","buffer":95,"http":106,"https":110}],"./lib/SIN":[function(require,module,exports){ -module.exports=require('tBM27q'); -},{}],"tBM27q":[function(require,module,exports){ -(function (Buffer){ -'use strict'; -var VersionedData = require('../util/VersionedData'); -var EncodedData = require('../util/EncodedData'); -var util = require('util'); -var coinUtil = require('../util'); - -function SIN(type, payload) { - if (typeof type != 'number') { - SIN.super_.call(this, type, payload); - return; - } - if (!Buffer.isBuffer(payload) || payload.length != 20) - throw new Error('Payload must be 20 bytes'); - - this.data = new Buffer(1 + 1 + payload.length); - this.converters = this.encodings['binary'].converters; - this._encoding = this.encodings['binary']._encoding; - this.encoding('binary'); - this.prefix(0x0F); // SIN magic number, in numberspace - this.type(type); - this.payload(payload); -}; - -util.inherits(SIN, VersionedData); -EncodedData.applyEncodingsTo(SIN); - -SIN.SIN_PERSIST_MAINNET = 0x01; // associated with sacrifice TX -SIN.SIN_PERSIST_TESTNET = 0x11; // associated with sacrifice TX -SIN.SIN_EPHEM = 0x02; // generate off-net at any time - -// get or set the prefix data (the first byte of the address) -SIN.prototype.prefix = function(num) { - if (num || (num === 0)) { - this.doAsBinary(function() { - this.data.writeUInt8(num, 0); - }); - return num; - } - return this.as('binary').readUInt8(0); -}; - -// get or set the SIN-type data (the second byte of the address) -SIN.prototype.type = function(num) { - if (num || (num === 0)) { - this.doAsBinary(function() { - this.data.writeUInt8(num, 1); - }); - return num; - } - return this.as('binary').readUInt8(1); -}; - -// get or set the payload data (as a Buffer object) -SIN.prototype.payload = function(data) { - if (data) { - this.doAsBinary(function() { - data.copy(this.data, 2); - }); - return data; - } - return this.as('binary').slice(1); -}; - -SIN.prototype.validate = function() { - this.doAsBinary(function() { - SIN.super_.prototype.validate.call(this); - if (this.data.length != 22) throw new Error('invalid data length'); - }); -}; - - -// create a SIN from a public key -SIN.fromPubKey = function(pubKey, type) { - if (!type) - type = SIN.SIN_EPHEM; - - if (!Buffer.isBuffer(pubKey) || (pubKey.length !== 33 && pubKey.length != 65)) - throw new Error('Invalid public key'); - - var hash = coinUtil.sha256ripe160(pubKey); - return new SIN(hash, type); -}; - -module.exports = SIN; - -}).call(this,require("buffer").Buffer) -},{"../util":191,"../util/EncodedData":"eLfUFE","../util/VersionedData":"QLzNQg","buffer":95,"util":128}],"EyghZQ":[function(require,module,exports){ -var coinUtil = require('../util'); -var timeUtil = require('../util/time'); -var Key = require('./Key'); -var SIN = require('./SIN'); - -function SINKey(cfg) { - if (typeof cfg != 'object') - cfg = {}; - - this.created = cfg.created; - this.privKey = cfg.privKey; -}; - -SINKey.prototype.generate = function() { - this.privKey = Key.generateSync(); - this.created = timeUtil.curtime(); -}; - -SINKey.prototype.pubkeyHash = function() { - return coinUtil.sha256ripe160(this.privKey.public); -}; - -SINKey.prototype.storeObj = function() { - var pubKey = this.privKey.public.toString('hex'); - var pubKeyHash = this.pubkeyHash(); - var sin = new SIN(SIN.SIN_EPHEM, pubKeyHash); - var obj = { - created: this.created, - priv: this.privKey.private.toString('hex'), - pub: pubKey, - sin: sin.toString(), - }; - - return obj; -}; - -module.exports = SINKey; - -},{"../util":191,"../util/time":194,"./Key":"ALJ4PS","./SIN":"tBM27q"}],"./lib/SINKey":[function(require,module,exports){ -module.exports=require('EyghZQ'); -},{}],"./lib/Script":[function(require,module,exports){ -module.exports=require('hQ0t76'); -},{}],"hQ0t76":[function(require,module,exports){ -(function (Buffer){ -var config = require('../config'); -var log = require('../util/log'); -var Opcode = require('./Opcode'); -var buffertools = require('buffertools'); -var util = require('../util/util'); -var Parser = require('../util/BinaryParser'); -var Put = require('bufferput'); - -var TX_UNKNOWN = 0; -var TX_PUBKEY = 1; -var TX_PUBKEYHASH = 2; -var TX_MULTISIG = 3; -var TX_SCRIPTHASH = 4; - -var TX_TYPES = [ - 'unknown', - 'pubkey', - 'pubkeyhash', - 'multisig', - 'scripthash' -]; - -function Script(buffer) { - if (buffer) { - this.buffer = buffer; - } else { - this.buffer = util.EMPTY_BUFFER; - } - this.chunks = []; - this.parse(); -} - -Script.TX_UNKNOWN = TX_UNKNOWN; -Script.TX_PUBKEY = TX_PUBKEY; -Script.TX_PUBKEYHASH = TX_PUBKEYHASH; -Script.TX_MULTISIG = TX_MULTISIG; -Script.TX_SCRIPTHASH = TX_SCRIPTHASH; - -Script.prototype.parse = function() { - this.chunks = []; - - var parser = new Parser(this.buffer); - while (!parser.eof()) { - var opcode = parser.word8(); - - var len, chunk; - if (opcode > 0 && opcode < Opcode.map.OP_PUSHDATA1) { - // Read some bytes of data, opcode value is the length of data - this.chunks.push(parser.buffer(opcode)); - } else if (opcode === Opcode.map.OP_PUSHDATA1) { - len = parser.word8(); - chunk = parser.buffer(len); - this.chunks.push(chunk); - } else if (opcode === Opcode.map.OP_PUSHDATA2) { - len = parser.word16le(); - chunk = parser.buffer(len); - this.chunks.push(chunk); - } else if (opcode === Opcode.map.OP_PUSHDATA4) { - len = parser.word32le(); - chunk = parser.buffer(len); - this.chunks.push(chunk); - } else { - this.chunks.push(opcode); - } - } -}; - -Script.prototype.isPushOnly = function() { - for (var i = 0; i < this.chunks.length; i++) { - var op = this.chunks[i]; - if (!Buffer.isBuffer(op) && op > Opcode.map.OP_16) { - return false; - } - } - - return true; -}; - -Script.prototype.isP2SH = function() { - return (this.chunks.length == 3 && - this.chunks[0] == Opcode.map.OP_HASH160 && - Buffer.isBuffer(this.chunks[1]) && - this.chunks[1].length == 20 && - this.chunks[2] == Opcode.map.OP_EQUAL); -}; - -Script.prototype.isPubkey = function() { - return (this.chunks.length == 2 && - Buffer.isBuffer(this.chunks[0]) && - this.chunks[1] == Opcode.map.OP_CHECKSIG); -}; - -Script.prototype.isPubkeyHash = function() { - return (this.chunks.length == 5 && - this.chunks[0] == Opcode.map.OP_DUP && - this.chunks[1] == Opcode.map.OP_HASH160 && - Buffer.isBuffer(this.chunks[2]) && - this.chunks[2].length == 20 && - this.chunks[3] == Opcode.map.OP_EQUALVERIFY && - this.chunks[4] == Opcode.map.OP_CHECKSIG); -}; - -function isSmallIntOp(opcode) { - return ((opcode == Opcode.map.OP_0) || - ((opcode >= Opcode.map.OP_1) && (opcode <= Opcode.map.OP_16))); -}; - -Script.prototype.isMultiSig = function() { - return (this.chunks.length > 3 && - isSmallIntOp(this.chunks[0]) && - this.chunks.slice(1, this.chunks.length - 2).every(function(i) { - return Buffer.isBuffer(i); - }) && - isSmallIntOp(this.chunks[this.chunks.length - 2]) && - this.chunks[this.chunks.length - 1] == Opcode.map.OP_CHECKMULTISIG); -}; - -Script.prototype.isPubkeyHashScriptSig = function() { - return (this.chunks.length == 2 && - Buffer.isBuffer(this.chunks[0]) && - Buffer.isBuffer(this.chunks[1])); -}; - -Script.prototype.isP2shScriptSig = function() { - if (!isSmallIntOp(this.chunks[0]) || this.chunks[0] !== 0) - return false; - - var redeemScript = new Script(this.chunks[this.chunks.length - 1]); - var type = redeemScript.classify(); - return type !== TX_UNKNOWN; -}; - -Script.prototype.isMultiSigScriptSig = function() { - if (!isSmallIntOp(this.chunks[0]) || this.chunks[0] !== 0) - return false; - return !this.isP2shScriptSig(); -}; -Script.prototype.isPubkeyScriptSig = function() { - return (this.chunks.length == 1 && - Buffer.isBuffer(this.chunks[0])); -}; - -Script.prototype.countSignatures = function() { - var ret = 0; - var l = this.chunks.length; - // Multisig? - if (this.isMultiSigScriptSig()) { - ret = l - 1; - } - // p2sh - else if (this.isP2shScriptSig()) { - ret = l - 2; - } - // p2pubkeyhash - else if (this.isPubkeyHashScriptSig()) { - ret = 1; - } - // p2pubkey - else { - ret = 0; - } - return ret; -}; - - -Script.prototype.getSignatures = function() { - ret = []; - var l = this.chunks.length; - // Multisig? - if (this.isMultiSigScriptSig()) { - for(var i = 1; i marked 0 + redeemScript - } - } - // p2pubkey or p2pubkeyhash - else { - if (buffertools.compare(this.getBuffer(), util.EMPTY_BUFFER) === 0) { - ret = 1; - } - } - return ret; -}; - -Script.prototype.finishedMultiSig = function() { - var missing = this.countMissingSignatures(); - if (missing === null) return null; - - return missing === 0; -}; - -Script.prototype.getMultiSigInfo = function() { - if (!this.isMultiSig()) { - throw new Error("Script.getMultiSigInfo(): Not a multiSig script."); - } - - var nsigs = this.chunks[0] - 80; //see OP_2-OP_16; - var npubkeys = this.chunks[this.chunks.length - 2] - 80; //see OP_2-OP_16; - - var pubkeys = []; - for (var i = 1; i < this.chunks.length - 2; i++) { - pubkeys.push(this.chunks[i]); - } - - if (pubkeys.length != npubkeys) { - throw new Error("Script.getMultiSigInfo(): Amount of PKs does not match what the script specifies."); - } - - return { - nsigs: nsigs, - npubkeys: npubkeys, - pubkeys: pubkeys - } -}; - -Script.prototype.prependOp0 = function() { - var chunks = [0]; - for (i in this.chunks) { - if (this.chunks.hasOwnProperty(i)) { - chunks.push(this.chunks[i]); - } - } - this.chunks = chunks; - this.updateBuffer(); - return this; -}; - -// is this a script form we know? -Script.prototype.classify = function() { - if (this.isPubkeyHash()) - return TX_PUBKEYHASH; - if (this.isP2SH()) - return TX_SCRIPTHASH; - if (this.isMultiSig()) - return TX_MULTISIG; - if (this.isPubkey()) - return TX_PUBKEY; - return TX_UNKNOWN; -}; - -// extract useful data items from known scripts -Script.prototype.capture = function() { - var txType = this.classify(); - var res = []; - switch (txType) { - case TX_PUBKEY: - res.push(this.chunks[0]); - break; - case TX_PUBKEYHASH: - res.push(this.chunks[2]); - break; - case TX_MULTISIG: - for (var i = 1; i < (this.chunks.length - 2); i++) - res.push(this.chunks[i]); - break; - case TX_SCRIPTHASH: - res.push(this.chunks[1]); - break; - - case TX_UNKNOWN: - default: - // do nothing - break; - } - - return res; -}; - -// return first extracted data item from script -Script.prototype.captureOne = function() { - var arr = this.capture(); - return arr[0]; -}; - -Script.prototype.getOutType = function() { - var txType = this.classify(); - switch (txType) { - case TX_PUBKEY: - return 'Pubkey'; - case TX_PUBKEYHASH: - return 'Address'; - default: - return 'Strange'; - } -}; - -Script.prototype.getRawOutType = function() { - return TX_TYPES[this.classify()]; -}; - -Script.prototype.simpleOutHash = function() { - switch (this.getOutType()) { - case 'Address': - return this.chunks[2]; - case 'Pubkey': - return util.sha256ripe160(this.chunks[0]); - default: - log.debug("Encountered non-standard scriptPubKey"); - log.debug("Strange script was: " + this.toString()); - return null; - } -}; - -Script.prototype.getInType = function() { - if (this.chunks.length == 1) { - // Direct IP to IP transactions only have the public key in their scriptSig. - return 'Pubkey'; - } else if (this.chunks.length == 2 && - Buffer.isBuffer(this.chunks[0]) && - Buffer.isBuffer(this.chunks[1])) { - return 'Address'; - } else { - return 'Strange'; - } -}; - -Script.prototype.simpleInPubKey = function() { - switch (this.getInType()) { - case 'Address': - return this.chunks[1]; - case 'Pubkey': - return null; - default: - log.debug("Encountered non-standard scriptSig"); - log.debug("Strange script was: " + this.toString()); - return null; - } -}; - -Script.prototype.getBuffer = function() { - return this.buffer; -}; - -Script.prototype.serialize = Script.prototype.getBuffer; - -Script.prototype.getStringContent = function(truncate, maxEl) { - if (truncate === null) { - truncate = true; - } - - if ('undefined' === typeof maxEl) { - maxEl = 15; - } - - var s = ''; - for (var i = 0, l = this.chunks.length; i < l; i++) { - var chunk = this.chunks[i]; - - if (i > 0) { - s += ' '; - } - - if (Buffer.isBuffer(chunk)) { - s += '0x' + util.formatBuffer(chunk, truncate ? null : 0); - } else { - s += Opcode.reverseMap[chunk]; - } - - if (maxEl && i > maxEl) { - s += ' ...'; - break; - } - } - return s; -}; - -Script.prototype.toString = function(truncate, maxEl) { - var script = " - - - - - - diff --git a/examples/node-client.js b/examples/node-client.js deleted file mode 100644 index 57d5735..0000000 --- a/examples/node-client.js +++ /dev/null @@ -1,34 +0,0 @@ -var io = require('socket.io-client'); - -var bitcore = require('bitcore'); -var util = bitcore.util; -var Key = bitcore.Key; -var AuthMessage = bitcore.AuthMessage; -var Buffer = bitcore.Buffer; - -var socket = io.connect('http://localhost:3001', { - reconnection: false -}); - -var pk = Key.generateSync(); -var pubkey = pk.public.toString('hex'); -socket.emit('subscribe', pubkey); -socket.emit('sync'); - - - -socket.on('connect', function() { - console.log('connected as ' + pubkey); -}); - -socket.on('message', function(m) { - var data = AuthMessage.decode(pk, m); - console.log('message received ' + data.payload); - var echo = AuthMessage.encode(m.pubkey, pk, data.payload); - socket.emit('message', echo); -}); - - -socket.on('error', function(err) { - console.log(err); -}); diff --git a/insight.js b/insight.js deleted file mode 100755 index 52d6739..0000000 --- a/insight.js +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env node - -'use strict'; -//Set the node enviornment variable if not set before -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var fs = require('fs'); -var PeerSync = require('./lib/PeerSync'); -var HistoricSync = require('./lib/HistoricSync'); - -var http = require('http'); -var https = require('https'); -var express = require('express'); -var program = require('commander'); - -var config = require('./config/config'); -var logger = require('./lib/logger').logger; -program - .version(config.version); - -// text title -console.log( - '\n\ - ____ _ __ __ ___ _ \n\ - / _/___ _____(_)___ _/ /_ / /_ / | ____ (_)\n\ - / // __ \\/ ___/ / __ `/ __ \\/ __/ / /\| \| / __ \\/ / \n\ - _/ // / / (__ ) / /_/ / / / / /_ / ___ |/ /_/ / / \n\ -/___/_/ /_/____/_/\\__, /_/ /_/\\__/ /_/ |_/ .___/_/ \n\ - /____/ /_/ \n\ -\n\t\t\t\t\t\tv%s\n', config.version); -program.on('--help', function() { - logger.info('\n# Configuration:\n\ -\tINSIGHT_NETWORK (Network): %s\n\ -\tINSIGHT_DB (Database Path): %s\n\ -\tINSIGHT_SAFE_CONFIRMATIONS (Safe Confirmations): %s\n\ -\tINSIGHT_IGNORE_CACHE (Ignore Cache): %s\n\ - # Bicoind Connection configuration:\n\ -\tRPC Username: %s\t\tBITCOIND_USER\n\ -\tRPC Password: %s\tBITCOIND_PASS\n\ -\tRPC Protocol: %s\t\tBITCOIND_PROTO\n\ -\tRPC Host: %s\t\tBITCOIND_HOST\n\ -\tRPC Port: %s\t\t\tBITCOIND_PORT\n\ -\tP2P Port: %s\t\t\tBITCOIND_P2P_PORT\n\ -\tBITCOIND_DATADIR: %s\n\ -\t%s\n\ -\nChange setting by assigning the enviroment variables above. Example:\n\ - $ INSIGHT_NETWORK="testnet" BITCOIND_HOST="123.123.123.123" ./insight.js\ -\n\n', - config.network, config.leveldb, config.safeConfirmations, config.ignoreCache ? 'yes' : 'no', - config.bitcoind.user, - config.bitcoind.pass ? 'Yes(hidden)' : 'No', - config.bitcoind.protocol, - config.bitcoind.host, - config.bitcoind.port, - config.bitcoind.p2pPort, - config.bitcoind.dataDir + (config.network === 'testnet' ? '*' : ''), (config.network === 'testnet' ? '* (/testnet3 is added automatically)' : '') - ); -}); - -program.parse(process.argv); - -// create express app -var expressApp = express(); - -// setup headers -require('./config/headers')(expressApp); - -// setup http/https base server -var server; -if (config.enableHTTPS) { - var serverOpts = {}; - serverOpts.key = fs.readFileSync('./etc/test-key.pem'); - serverOpts.cert = fs.readFileSync('./etc/test-cert.pem'); - server = https.createServer(serverOpts, expressApp); -} else { - server = http.createServer(expressApp); -} - -// Bootstrap models -var models_path = __dirname + '/app/models'; -var walk = function(path) { - fs.readdirSync(path).forEach(function(file) { - var newPath = path + '/' + file; - var stat = fs.statSync(newPath); - if (stat.isFile()) { - if (/(.*)\.(js$)/.test(file)) { - require(newPath); - } - } else if (stat.isDirectory()) { - walk(newPath); - } - }); -}; - -walk(models_path); - -// p2pSync process -var peerSync = new PeerSync({ - shouldBroadcast: true -}); - -if (!config.disableP2pSync) { - peerSync.run(); -} - -// historic_sync process -var historicSync = new HistoricSync({ - shouldBroadcastSync: true -}); -peerSync.historicSync = historicSync; - -if (!config.disableHistoricSync) { - historicSync.start({}, function(err) { - if (err) { - var txt = 'ABORTED with error: ' + err.message; - console.log('[historic_sync] ' + txt); - } - if (peerSync) peerSync.allowReorgs = true; - }); -} else -if (peerSync) peerSync.allowReorgs = true; - - - -// socket.io -var ios = require('socket.io')(server, config); -require('./app/controllers/socket.js').init(ios); - -// plugins -if (config.enableRatelimiter) { - require('./plugins/ratelimiter').init(expressApp, config.ratelimiter); -} - -if (config.enableEmailstore) { - require('./plugins/emailstore').init(config.emailstore); -} - -if (config.enableCurrencyRates) { - require('./plugins/currencyrates').init(config.currencyrates); -} - -// express settings -require('./config/express')(expressApp, historicSync, peerSync); -require('./config/routes')(expressApp); - - -//Start the app by listening on -server.listen(config.port, function() { - logger.info('insight server listening on port %d in %s mode', server.address().port, process.env.NODE_ENV); -}); - -//expose app -exports = module.exports = expressApp; diff --git a/lib/BlockDb.js b/lib/BlockDb.js deleted file mode 100644 index 41c5b86..0000000 --- a/lib/BlockDb.js +++ /dev/null @@ -1,519 +0,0 @@ -'use strict'; -var imports = require('soop').imports(); -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 - -// 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. - */ -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 async = require('async'); - - -var logger = require('./logger').logger; -var info = logger.info; - -var BlockDb = function(opts) { - this.txDb = require('./TransactionDb').default(); - this.safeConfirmations = config.safeConfirmations || DEFAULT_SAFE_CONFIRMATIONS; - BlockDb.super(this, arguments); -}; - -BlockDb.prototype.close = function(cb) { - db.close(cb); -}; - -BlockDb.prototype.drop = function(cb) { - var path = config.leveldb + '/blocks'; - db.close(function() { - require('leveldown').destroy(path, function() { - db = levelup(path, { - maxOpenFiles: MAX_OPEN_FILES - }); - return cb(); - }); - }); -}; - - -BlockDb.prototype._addBlockScript = function(b, height) { - var time_key = TIMESTAMP_PREFIX + - (b.time || Math.round(new Date().getTime() / 1000)); - - 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._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._changeBlockHeight = function(hash, height, cb) { - var self = this; - var dbScript1 = this._setHeightScript(hash, height); - - logger.log('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); - logger.info('\t%s %d Txs', 'Confirming', bi.info.tx.length); - } else { - dbScript2 = self._delTxsScript(bi.info.tx); - logger.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) { - var txs = typeof b.tx[0] === 'string' ? b.tx : b.tx.map(function(o) { - return o.txid; - }); - - var dbScript = this._addBlockScript(b, height); - dbScript = dbScript.concat(this._addTxsScript(txs, 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) { - return cb(err); - }); -}; - -BlockDb.prototype.getPrev = function(hash, cb) { - db.get(PREV_PREFIX + hash, function(err, val) { - if (err && err.notFound) { - err = null; - val = null; - } - return cb(err, val); - }); -}; - - -BlockDb.prototype.setLastFileIndex = function(idx, cb) { - var self = this; - if (this.lastFileIndexSaved === idx) return cb(); - - db.put(LAST_FILE_INDEX, idx, function(err) { - self.lastFileIndexSaved = idx; - return cb(err); - }); -}; - -BlockDb.prototype.getLastFileIndex = function(cb) { - db.get(LAST_FILE_INDEX, function(err, val) { - if (err && err.notFound) { - err = null; - val = null; - } - return cb(err, val); - }); -}; - -BlockDb.prototype.getNext = function(hash, cb) { - db.get(NEXT_PREFIX + hash, function(err, val) { - if (err && err.notFound) { - err = null; - val = null; - } - return cb(err, val); - }); -}; - -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._setHeightScript = function(hash, height) { - logger.log('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); - }); -}; - -// Unused -BlockDb.prototype.countConnected = function(cb) { - var c = 0; - console.log('Counting connected blocks. This could take some minutes'); - db.createReadStream({ - start: MAIN_PREFIX, - end: MAIN_PREFIX + '~' - }) - .on('data', function(data) { - if (data.value !== 0) c++; - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(null, c); - }); -}; - -// .has() return true orphans also -BlockDb.prototype.has = function(hash, cb) { - var k = PREV_PREFIX + hash; - db.get(k, function(err) { - var ret = true; - if (err && err.notFound) { - err = null; - ret = false; - } - return cb(err, ret); - }); -}; - -BlockDb.prototype.fromHashWithInfo = function(hash, cb) { - var self = this; - - Rpc.getBlock(hash, function(err, info) { - if (err || !info) return cb(err); - - //TODO can we get this from RPC .height? - self.getHeight(hash, function(err, height) { - if (err) return cb(err); - - info.isMainChain = height >= 0 ? true : false; - - return cb(null, { - hash: hash, - info: info, - }); - }); - }); -}; - -BlockDb.prototype.getBlocksByDate = function(start_ts, end_ts, limit, cb) { - var list = []; - var opts = { - start: TIMESTAMP_PREFIX + end_ts, //Inverted since list is reversed - end: TIMESTAMP_PREFIX + start_ts, - limit: limit, - reverse: 1, - }; - - db.createReadStream(opts) - .on('data', function(data) { - var k = data.key.split('-'); - list.push({ - ts: k[1], - hash: data.value, - }); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(null, list.reverse()); - }); -}; - -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) { - // Only one will be confirmed - self.getBlockForTx(oi.txid, function(err, hash, height) { - if (err) return; - if (height >= 0) { - o.spentTxId = oi.txid; - o.index = oi.index; - o.spentIsConfirmed = chainHeight >= height; - o.spentConfirmations = chainHeight - height + 1; - } - return e_c(); - }); - }, cb); - } else { - self.getBlockForTx(o.spentTxId, function(err, hash, height) { - if (err) return cb(err); - if (height >= 0) { - o.spentIsConfirmed = chainHeight >= height; - o.spentConfirmations = chainHeight - height + 1; - } - return cb(); - }); - } -}; - - -BlockDb.prototype._fillConfirmationsOneVin = function(o, chainHeight, cb) { - var self = this; - - self.getBlockForTx(o.txid, function(err, hash, height) { - if (err) return cb(err); - o.isConfirmed = false; - o.confirmations = 0; - if (height >= 0) { - o.isConfirmed = chainHeight >= height; - o.confirmations = chainHeight - height + 1; - } - o.unconfirmedInput = ! o.isConfirmed; - 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); - if (height >= 0) { - o.isConfirmed = chainHeight >= height; - o.confirmations = chainHeight - height + 1; - return self._fillConfirmationsOneSpent(o, chainHeight, cb); - } else return 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 partial cached but not spent - }); - //console.log('[BlockDb.js.373:txs:]',txs.length, txs.slice(0,5)); //TODO - - async.eachLimit(txs, CONCURRENCY, function(txout, e_c) { - if (txout.isConfirmedCached) { - self._fillConfirmationsOneSpent(txout, height, e_c); - } else { - self._fillConfirmationsOne(txout, height, e_c); - } - - }, cb); - }); -}; - -BlockDb.prototype.fillVinConfirmations = function(tx, cb) { - var self = this; - this.getTip(function(err, hash, height) { - var vin = tx.vin; - if (!vin) return cb(); - - async.eachLimit(vin, CONCURRENCY, function(v, e_c) { - self._fillConfirmationsOneVin(v, height, e_c); - }, cb); - }); -}; - - -/* this is only for migration scripts */ -BlockDb.prototype._runScript = function(script, cb) { - db.batch(script, cb); -}; - -BlockDb.prototype.migrateV02 = function(cb) { - var k = 'txb-'; - var dbScript = []; - var c = 0; - var c2 = 0; - var N = 50000; - this.txDb._db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - var v = data.value.split(':'); - dbScript.push({ - type: 'put', - key: IN_BLK_PREFIX + k[1], - value: data.value, - }); - if (c++ > N) { - console.log('\t%dM txs processed', ((c2 += N) / 1e6).toFixed(3)); - db.batch(dbScript, function() { - c = 0; - dbScript = []; - }); - } - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(); - }); - - -}; - -BlockDb.prototype.migrateV02cleanup = function(cb) { - var self = this; - console.log('## deleting txb- from txs db'); //todo - - var k = 'txb-'; - var d = this.txDb._db; - d.createReadStream({ - start: k, - end: k + '~' - }) - .pipe(d.createWriteStream({ - type: 'del' - })) - .on('close', function(err) { - if (err) return cb(err); - console.log('## deleting tx- from txs db'); //todo - - var k = 'tx-'; - var d = self.txDb._db; - d.createReadStream({ - start: k, - end: k + '~' - }) - .pipe(d.createWriteStream({ - type: 'del' - })) - .on('close', function(err) { - if (err) return cb(err); - var k = 'txa-'; - var d = self.txDb._db; - d.createReadStream({ - start: k, - end: k + '~' - }) - .pipe(d.createWriteStream({ - type: 'del' - })) - .on('close', cb); - }); - }); -}; - - -module.exports = require('soop')(BlockDb); diff --git a/lib/BlockExtractor.js b/lib/BlockExtractor.js deleted file mode 100644 index 91e40b1..0000000 --- a/lib/BlockExtractor.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; -var bitcore = require('bitcore'), - Block = bitcore.Block, - networks = bitcore.networks, - Parser = bitcore.BinaryParser, - fs = require('fs'), - Buffer = bitcore.Buffer, - glob = require('glob'), - async = require('async'); - -function BlockExtractor(dataDir, network) { - var path = dataDir + '/blocks/blk*.dat'; - - this.dataDir = dataDir; - this.files = glob.sync(path); - this.nfiles = this.files.length; - - if (this.nfiles === 0) - throw new Error('Could not find block files at: ' + path); - - this.currentFileIndex = 0; - this.isCurrentRead = false; - this.currentBuffer = null; - this.currentParser = null; - this.network = network === 'testnet' ? networks.testnet: networks.livenet; - this.magic = this.network.magic.toString('hex'); -} - -BlockExtractor.prototype.currentFile = function() { - return this.files[this.currentFileIndex]; -}; - - -BlockExtractor.prototype.nextFile = function() { - if (this.currentFileIndex < 0) return false; - - var ret = true; - - this.isCurrentRead = false; - this.currentBuffer = null; - this.currentParser = null; - - if (this.currentFileIndex < this.nfiles - 1) { - this.currentFileIndex++; - } - else { - this.currentFileIndex=-1; - ret = false; - } - return ret; -}; - -BlockExtractor.prototype.readCurrentFileSync = function() { - if (this.currentFileIndex < 0 || this.isCurrentRead) return; - - this.isCurrentRead = true; - - var fname = this.currentFile(); - if (!fname) return; - - - var stats = fs.statSync(fname); - - var size = stats.size; - var mb = parseInt(size/1024/1024); - - console.log('Reading Blockfile %s [%d MB]', - fname, mb); - - if(mb > 1023) - throw new Error('CRITICAL ERROR: file size greater than 1023MB, use cat blk*.dat > bootstrap.dat to create new ' - + 'dat files @128MB. (https://github.com/bitpay/insight-api/issues/35)'); - - var fd = fs.openSync(fname, 'r'); - - var buffer = new Buffer(size); - - fs.readSync(fd, buffer, 0, size, 0); - - this.currentBuffer = buffer; - this.currentParser = new Parser(buffer); -}; - - - - -BlockExtractor.prototype._getMagic = function() { - if (!this.currentParser) - return null; - - var byte0 = this.currentParser ? this.currentParser.buffer(1).toString('hex') : null; - - - - // Grab 3 bytes from block without removing them - var p = this.currentParser.pos; - var bytes123 = this.currentParser.subject.toString('hex',p,p+3); - var magic = byte0 + bytes123; - - if (magic !=='00000000' && magic !== this.magic) { - if(this.errorCount++ > 4) - throw new Error('CRITICAL ERROR: Magic number mismatch: ' + - magic + '!=' + this.magic); - magic=null; - } - - if (magic==='00000000') - magic =null; - - return magic; -}; - -BlockExtractor.prototype.getNextBlock = function(cb) { - var b; - var magic; - var isFinished = 0; - - while(!magic && !isFinished) { - this.readCurrentFileSync(); - magic= this._getMagic(); - - if (!this.currentParser || this.currentParser.eof() ) { - - if (this.nextFile()) { - console.log('Moving forward to file:' + this.currentFile() ); - magic = null; - } else { - console.log('Finished all files'); - isFinished = 1; - } - } - } - if (isFinished) - return cb(); - - // Remove 3 bytes from magic and spacer - this.currentParser.buffer(3+4); - - b = new Block(); - b.parse(this.currentParser); - b.getHash(); - this.errorCount=0; - return cb(null,b); -}; - -module.exports = require('soop')(BlockExtractor); - diff --git a/lib/HistoricSync.js b/lib/HistoricSync.js deleted file mode 100644 index 505ce4c..0000000 --- a/lib/HistoricSync.js +++ /dev/null @@ -1,466 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); -var util = require('util'); -var async = require('async'); - -var bitcore = require('bitcore'); -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 bitcoreUtil = bitcore.util; -var logger = require('./logger').logger; -var info = logger.info; -var error = logger.error; -var PERCENTAGE_TO_START_FROM_RPC = 0.96; - -// TODO TODO TODO -//var PERCENTAGE_TO_START_FROM_RPC = 0.98; - -// 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:'; - -function HistoricSync(opts) { - opts = opts || {}; - this.shouldBroadcast = opts.shouldBroadcastSync; - - this.network = config.network === 'testnet' ? networks.testnet : networks.livenet; - - var genesisHashReversed = new Buffer(32); - this.network.genesisBlock.hash.copy(genesisHashReversed); - buffertools.reverse(genesisHashReversed); - this.genesis = genesisHashReversed.toString('hex'); - - var bitcore = require('bitcore'); - - var RpcClient = bitcore.RpcClient; - - this.rpc = new RpcClient(config.bitcoind); - - this.getBitcoinCoreVersion(function(bitcoinVersion) { - if (bitcoinVersion > 100000 && !config.forceRPCsync) { - info('-------------------------------------------------------'); - info('- Bitcoin Core version >0.10 only works with RPC sync -'); - info('- Set the env variable INSIGHT_FORCE_RPC_SYNC = 1 -'); - info('-------------------------------------------------------'); - process.exit(1); - } else { - info('Bitcoin Core version ', bitcoinVersion); - info('Using RPC sync '); - } - }); - - - this.sync = new Sync(opts); - this.height = 0; -} - -HistoricSync.prototype.getBitcoinCoreVersion = function(cb) { - var self = this; - self.rpc.getInfo(function(err, info) { - if (err) { - error('ERROR ', err); - process.exit(-1); - }; - return cb(info.result.version); - }); -}; - -HistoricSync.prototype.showProgress = function() { - var self = this; - - if (self.status === 'syncing' && - (self.height) % self.step !== 1) return; - - if (self.error) - error(self.error); - - else { - self.updatePercentage(); - info(util.format('status: [%d%%]', self.syncPercentage)); - } - if (self.shouldBroadcast) { - sockets.broadcastSyncInfo(self.info()); - } - // - // if (self.syncPercentage > 10) { - // process.exit(-1); - // } -}; - - -HistoricSync.prototype.setError = function(err) { - var self = this; - self.error = err.message ? err.message : err.toString(); - self.status = 'error'; - self.showProgress(); - return err; -}; - - - -HistoricSync.prototype.close = function() { - this.sync.close(); -}; - - -HistoricSync.prototype.info = function() { - this.updatePercentage(); - return { - status: this.status, - blockChainHeight: this.blockChainHeight, - syncPercentage: this.syncPercentage, - height: this.height, - syncTipHash: this.sync.tip, - error: this.error, - type: this.type, - startTs: this.startTs, - endTs: this.endTs, - }; -}; - -HistoricSync.prototype.updatePercentage = function() { - var r = this.height / this.blockChainHeight; - this.syncPercentage = parseFloat(100 * r).toFixed(3); - if (this.syncPercentage > 100) this.syncPercentage = 100; -}; - -HistoricSync.prototype.getBlockFromRPC = function(cb) { - var self = this; - - if (!self.currentRpcHash) return cb(); - - var blockInfo; - self.rpc.getBlock(self.currentRpcHash, function(err, ret) { - if (err) return cb(err); - if (ret) { - blockInfo = ret.result; - // this is to match block retreived from file - if (blockInfo.hash === self.genesis) - blockInfo.previousblockhash = - self.network.genesisBlock.prev_hash.toString('hex'); - - self.currentRpcHash = blockInfo.nextblockhash; - } else { - blockInfo = null; - } - return cb(null, blockInfo); - }); -}; - -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; - - var blockInfo; - - //get Info - self.blockExtractor.getNextBlock(function(err, b) { - if (err || !b) return cb(err); - blockInfo = self.getStandardizedBlock(b); - self.sync.bDb.setLastFileIndex(self.blockExtractor.currentFileIndex, function(err) { - return cb(err, blockInfo); - }); - }); -}; - -HistoricSync.prototype.updateBlockChainHeight = function(cb) { - var self = this; - - self.rpc.getBlockCount(function(err, res) { - self.blockChainHeight = res.result; - return cb(err); - }); -}; - - -HistoricSync.prototype.checkNetworkSettings = function(next) { - var self = this; - - self.hasGenesis = false; - - // check network config - self.rpc.getBlockHash(0, function(err, res) { - if (!err && (res && res.result !== self.genesis)) { - err = new Error(BAD_GEN_ERROR + config.network); - } - if (err) return next(err); - self.sync.bDb.has(self.genesis, function(err, b) { - if (!err && (res && res.result !== self.genesis)) { - err = new Error(BAD_GEN_ERROR_DB + config.network); - } - self.hasGenesis = b ? true : false; - return next(err); - }); - }); -}; - -HistoricSync.prototype.updateStartBlock = function(opts, next) { - var self = this; - - self.startBlock = self.genesis; - - if (opts.startAt) { - self.sync.bDb.fromHashWithInfo(opts.startAt, function(err, bi) { - var blockInfo = bi ? bi.info : {}; - if (blockInfo.height) { - self.startBlock = opts.startAt; - self.height = blockInfo.height; - info('Resuming sync from block: %s #%d', opts.startAt, self.height); - return next(err); - } - }); - } else { - self.sync.bDb.getTip(function(err, tip, height) { - if (!tip) return next(); - - var blockInfo; - var oldtip; - - //check that the tip is still on the mainchain - async.doWhilst( - function(cb) { - self.sync.bDb.fromHashWithInfo(tip, function(err, bi) { - blockInfo = bi ? bi.info : {}; - if (oldtip) - self.sync.bDb.setBlockNotMain(oldtip, cb); - else - return cb(); - }); - }, - function(err) { - if (err) return next(err); - var ret = false; - - var d = Math.abs(height - blockInfo.height); - var limit = self.network == 'livenet' ? 6 : 100; - if (d > limit) { - error('Previous Tip block height differs by %d. Please delete and resync (-D)', d); - process.exit(1); - } - if (self.blockChainHeight === blockInfo.height || - blockInfo.confirmations > 0) { - ret = false; - } 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; - info('Previous TIP is now orphan. Back to:' + tip); - ret = true; - } - return ret; - }, - function(err) { - self.startBlock = tip; - self.height = height; - info('Resuming sync from block: %s #%d', tip, height); - return next(err); - } - ); - }); - } -}; - -HistoricSync.prototype.prepareFileSync = function(opts, next) { - var self = this; - - if (config.forceRPCsync) return next(); - - if (opts.forceRPC || !config.bitcoind.dataDir || - self.height > self.blockChainHeight * PERCENTAGE_TO_START_FROM_RPC) return next(); - - - try { - self.blockExtractor = new BlockExtractor(config.bitcoind.dataDir, config.network); - } catch (e) { - info(e.message + '. Disabling file sync.'); - return next(); - } - - self.getFn = self.getBlockFromFile; - self.allowReorgs = true; - self.sync.bDb.getLastFileIndex(function(err, idx) { - - if (opts.forceStartFile) - self.blockExtractor.currentFileIndex = opts.forceStartFile; - else if (idx) self.blockExtractor.currentFileIndex = idx; - - var h = self.genesis; - - info('Seeking file to:' + self.startBlock); - //forward till startBlock - async.whilst( - function() { - return h !== self.startBlock; - }, - function(w_cb) { - self.getBlockFromFile(function(err, b) { - if (!b) return w_cb('Could not find block ' + self.startBlock); - h = b.hash; - setImmediate(function() { - return w_cb(err); - }); - }); - }, function(err) { - console.log('\tFOUND Starting Block!'); - - // TODO SET HEIGHT - return next(err); - }); - }); -}; - -//NOP -HistoricSync.prototype.prepareRpcSync = function(opts, next) { - var self = this; - - if (self.blockExtractor) return next(); - self.getFn = self.getBlockFromRPC; - self.allowReorgs = true; - self.currentRpcHash = self.startBlock; - return next(); -}; - -HistoricSync.prototype.showSyncStartMessage = function() { - var self = this; - - info('Got ' + self.height + - ' blocks in current DB, out of ' + self.blockChainHeight + ' block at bitcoind'); - - if (self.blockExtractor) { - info('bitcoind dataDir configured...importing blocks from .dat files'); - info('First file index: ' + self.blockExtractor.currentFileIndex); - } else { - info('syncing from RPC (slow)'); - } - - info('Starting from: ', self.startBlock); - self.showProgress(); -}; - - -HistoricSync.prototype.setupSyncStatus = function() { - var self = this; - - var step = parseInt((self.blockChainHeight - self.height) / 1000); - if (step < 10) step = 10; - - self.step = step; - self.type = self.blockExtractor ? 'from .dat Files' : 'from RPC calls'; - self.status = 'syncing'; - self.startTs = Date.now(); - self.endTs = null; - this.error = null; - this.syncPercentage = 0; -}; - -HistoricSync.prototype.checkDBVersion = function(cb) { - this.sync.txDb.checkVersion02(function(isOk) { - if (!isOk) { - console.log('\n#############################\n\n ## Insight API DB is older that v0.2. Please resync using:\n $ util/sync.js -D\n More information at Insight API\'s Readme.md'); - process.exit(1); - } - // Add more test here in future changes. - return cb(); - }); -}; - - -HistoricSync.prototype.prepareToSync = function(opts, next) { - var self = this; - - self.status = 'starting'; - async.series([ - - function(s_c) { - self.checkDBVersion(s_c); - }, - function(s_c) { - self.checkNetworkSettings(s_c); - }, - function(s_c) { - self.updateBlockChainHeight(s_c); - }, - function(s_c) { - self.updateStartBlock(opts, s_c); - }, - function(s_c) { - self.prepareFileSync(opts, s_c); - }, - function(s_c) { - self.prepareRpcSync(opts, s_c); - }, - ], - function(err) { - if (err) return (self.setError(err)); - - self.showSyncStartMessage(); - self.setupSyncStatus(); - return next(); - }); -}; - - -HistoricSync.prototype.start = function(opts, next) { - var self = this; - - if (self.status === 'starting' || self.status === 'syncing') { - error('## Wont start to sync while status is %s', self.status); - return next(); - } - - self.prepareToSync(opts, function(err) { - if (err) return next(self.setError(err)); - - async.whilst( - function() { - self.showProgress(); - return self.status === 'syncing'; - }, - function(w_cb) { - self.getFn(function(err, blockInfo) { - if (err) return w_cb(self.setError(err)); - - if (blockInfo && blockInfo.hash && (!opts.stopAt || opts.stopAt !== blockInfo.hash)) { - self.sync.storeTipBlock(blockInfo, self.allowReorgs, function(err, height) { - if (err) return w_cb(self.setError(err)); - if (height >= 0) self.height = height; - setImmediate(function() { - return w_cb(err); - }); - }); - } else { - self.endTs = Date.now(); - self.status = 'finished'; - var info = self.info(); - logger.debug('Done Syncing blockchain', info.type, 'to height', info.height); - return w_cb(err); - } - }); - }, next); - }); -}; - -module.exports = require('soop')(HistoricSync); diff --git a/lib/MessageDb.js b/lib/MessageDb.js deleted file mode 100644 index 380c5a1..0000000 --- a/lib/MessageDb.js +++ /dev/null @@ -1,182 +0,0 @@ -'use strict'; -var soop = require('soop'); -var imports = soop.imports(); -var levelup = require('levelup'); -var config = require('../config/config'); -var Rpc = imports.rpc || require('./Rpc'); -var async = require('async'); -var logger = require('./logger').logger; -var util = require('util'); -var EventEmitter = require('events').EventEmitter; -var microtime = require('microtime'); -var bitcore = require('bitcore'); -var AuthMessage = bitcore.AuthMessage; -var preconditions = require('preconditions').singleton(); - -var MESSAGE_PREFIX = 'msg-'; // msg-- => - -var MAX_OPEN_FILES = 500; -var CONCURRENCY = 5; - - -var db; -var MessageDb = function(opts) { - opts = opts || {}; - this.path = config.leveldb + '/messages' + (opts.name ? ('-' + opts.name) : ''); - this.db = opts.db || db || levelup(this.path, { - maxOpenFiles: MAX_OPEN_FILES, - valueEncoding: 'json' - }); - this.initEvents(); - db = this.db; -}; -util.inherits(MessageDb, EventEmitter); - -MessageDb.prototype.initEvents = function() { - if (db) return; - var self = this; - this.db.on('put', function(key, value) { - var data = {}; - data.key = key; - data.value = value; - var message = MessageDb.fromStorage(data); - self.emit('message', message); - }); - this.db.on('ready', function() { - //console.log('Database ready!'); - }); -}; - -MessageDb.prototype.close = function(cb) { - this.db.close(cb); -}; - - -var messageKey = function(to, ts) { - preconditions.checkArgument(typeof to === 'string'); - preconditions.checkArgument(to.length === 66); - preconditions.checkArgument(!ts || typeof ts === 'number'); - if (!ts) ts = Math.round(microtime.now()); - return MESSAGE_PREFIX + to.toString() + '-' + ts; -}; - -MessageDb.prototype.addMessage = function(m, cb) { - - if (!this.authenticate(m)) { - cb(new Error('Authentication failed')); - return; - } - - var key; - try { - key = messageKey(m.to); - } catch (e) { - cb(new Error('Bad message')); - return; - }; - - var value = m; - this.db.put(key, value, cb); -}; - -MessageDb.prototype.authenticate = function(m) { - preconditions.checkArgument(m.pubkey); - preconditions.checkArgument(m.sig); - preconditions.checkArgument(m.encrypted); - - var frompubkey = new Buffer(m.pubkey, 'hex'); - var sig = new Buffer(m.sig, 'hex'); - var encrypted = new Buffer(m.encrypted, 'hex'); - return AuthMessage._verify(frompubkey, sig, encrypted); -}; - -MessageDb.parseKey = function(key) { - var ret = {}; - var spl = key.split('-'); - - ret.to = spl[1]; - ret.ts = +spl[2]; - - return ret; -}; - -MessageDb.fromStorage = function(data) { - var parsed = MessageDb.parseKey(data.key); - var message = data.value; - message.ts = parsed.ts; - message.to = parsed.to; - return message; -}; - -MessageDb.prototype.getMessages = function(to, lower_ts, upper_ts, cb) { - var list = [], - opts; - lower_ts = lower_ts || 1; - try { - opts = { - start: messageKey(to, lower_ts), - end: messageKey(to, upper_ts), - // limit: limit, TODO - reverse: false, - }; - } catch (e) { - cb(new Error('Bad message range')); - return; - }; - - db.createReadStream(opts) - .on('data', function(data) { - var message = MessageDb.fromStorage(data); - list.push(message); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(null, list); - }); -}; - -MessageDb.prototype.getAll = function(cb) { - var list = []; - db.createReadStream() - .on('data', function(data) { - list.push(MessageDb.fromStorage(data)); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(null, list); - }); -}; - -MessageDb.prototype.removeUpTo = function(ts, cb) { - preconditions.checkArgument(ts); - preconditions.checkArgument(typeof ts === 'number'); - var opts = {}; - var dels = []; - db.createKeyStream(opts) - .on('data', function(key) { - var parsed = MessageDb.parseKey(key); - if (parsed.ts < ts) { - logger.verbose('Deleting message ' + key); - dels.push({ - type: 'del', - key: key - }); - } - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - db.batch(dels, function(err) { - if (err) return cb(err); - else cb(null, dels.length); - }) - }); - -}; - -module.exports = soop(MessageDb); diff --git a/lib/PeerSync.js b/lib/PeerSync.js deleted file mode 100644 index d3e8d7c..0000000 --- a/lib/PeerSync.js +++ /dev/null @@ -1,150 +0,0 @@ -'use strict'; -var fs = require('fs'); -var bitcore = require('bitcore'); -var bitcoreUtil = bitcore.util; -var Sync = require('./Sync'); -var Peer = bitcore.Peer; -var PeerManager = bitcore.PeerManager; -var config = require('../config/config'); -var networks = bitcore.networks; -var sockets = require('../app/controllers/socket.js'); - -var peerdb_fn = 'peerdb.json'; - -function PeerSync(opts) { - opts = opts|| {}; - this.shouldBroadcast = opts.shouldBroadcast; - this.connected = false; - this.peerdb = undefined; - this.allowReorgs = false; - var pmConfig = { - network: config.network - }; - this.peerman = new PeerManager(pmConfig); - this.load_peers(); - this.sync = new Sync(opts); - this.verbose = opts.verbose || false; -} - -PeerSync.prototype.log = function() { - if (this.verbose) console.log(arguments); -}; - -PeerSync.prototype.load_peers = function() { - this.peerdb = [{ - ipv4: config.bitcoind.p2pHost, - port: config.bitcoind.p2pPort - }]; - - fs.writeFileSync(peerdb_fn, JSON.stringify(this.peerdb)); -}; - -PeerSync.prototype.info = function() { - return { - connected: this.connected, - host: this.peerdb[0].ipv4, - port: this.peerdb[0].port - }; -}; - -PeerSync.prototype.handleInv = function(info) { - var invs = info.message.invs; - info.conn.sendGetData(invs); -}; - -PeerSync.prototype._broadcastAddr = function(txid, addrs) { - if (addrs) { - for(var ii in addrs){ - sockets.broadcastAddressTx(txid, ii); - } - } -}; - - -PeerSync.prototype.handleTx = function(info) { - var self =this; - var tx = this.sync.txDb.getStandardizedTx(info.message.tx); - self.log('[p2p_sync] Handle tx: ' + tx.txid); - tx.time = tx.time || Math.round(new Date().getTime() / 1000); - - this.sync.storeTx(tx, function(err, relatedAddrs) { - if (err) { - self.log('[p2p_sync] Error in handle TX: ' + JSON.stringify(err)); - } - else if (self.shouldBroadcast) { - sockets.broadcastTx(tx); - self._broadcastAddr(tx.txid, relatedAddrs); - } - }); -}; - - -PeerSync.prototype.handleBlock = function(info) { - var self = this; - var block = info.message.block; - var blockHash = bitcoreUtil.formatHashFull(block.calcHash()); - self.log('[p2p_sync] Handle block: %s (allowReorgs: %s)', blockHash, self.allowReorgs); - - var tx_hashes = block.txs.map(function(tx) { - return bitcoreUtil.formatHashFull(tx.hash); - }); - - self.sync.storeTipBlock({ - 'hash': blockHash, - 'tx': tx_hashes, - 'previousblockhash': bitcoreUtil.formatHashFull(block.prev_hash), - }, self.allowReorgs, function(err, height) { - if (err && err.message.match(/NEED_SYNC/) && self.historicSync) { - self.log('[p2p_sync] Orphan block received. Triggering sync'); - self.historicSync.start({forceRPC:1}, function(){ - self.log('[p2p_sync] Done resync.'); - }); - } - else if (err) { - self.log('[p2p_sync] Error in handle Block: ', err); - } - else { - if (self.shouldBroadcast) { - sockets.broadcastBlock(blockHash); - // broadcasting address here is a bad idea. listening to new block - // should be enoght - } - } - }); -}; - -PeerSync.prototype.handleConnected = function(data) { - var peerman = data.pm; - var peers_n = peerman.peers.length; - this.log('[p2p_sync] Connected to ' + peers_n + ' peer' + (peers_n !== 1 ? 's' : '')); -}; - -PeerSync.prototype.run = function() { - var self = this; - - this.peerdb.forEach(function(datum) { - var peer = new Peer(datum.ipv4, datum.port); - self.peerman.addPeer(peer); - }); - - this.peerman.on('connection', function(conn) { - self.connected = true; - conn.on('inv', self.handleInv.bind(self)); - conn.on('block', self.handleBlock.bind(self)); - conn.on('tx', self.handleTx.bind(self)); - }); - this.peerman.on('connect', self.handleConnected.bind(self)); - - this.peerman.on('netDisconnected', function() { - self.connected = false; - }); - - this.peerman.start(); -}; - -PeerSync.prototype.close = function() { - this.sync.close(); -}; - - -module.exports = require('soop')(PeerSync); diff --git a/lib/PoolMatch.js b/lib/PoolMatch.js deleted file mode 100644 index 7c52690..0000000 --- a/lib/PoolMatch.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); -var fs = require('fs'); -var buffertools = require('buffertools'); -var db = imports.db || JSON.parse( fs.readFileSync(imports.poolMatchFile || './poolMatchFile.json')); - -var PoolMatch = function() { - var self = this; - - self.strings = {}; - db.forEach(function(pool) { - pool.searchStrings.forEach(function(s) { - self.strings[s] = { - poolName: pool.poolName, - url: pool.url - }; - }); - }); -}; - - -PoolMatch.prototype.match = function(buffer) { - var self = this; - for(var k in self.strings) { - if (buffertools.indexOf(buffer, k) >= 0) { - return self.strings[k]; - } - } -}; - -module.exports = require('soop')(PoolMatch); diff --git a/lib/Rpc.js b/lib/Rpc.js deleted file mode 100644 index f81f372..0000000 --- a/lib/Rpc.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); - -var bitcore = require('bitcore'), - RpcClient = bitcore.RpcClient, - BitcoreBlock = bitcore.Block, - util = require('util'), - config = require('../config/config'); - -var bitcoreRpc = imports.bitcoreRpc || new RpcClient(config.bitcoind); - -function Rpc() { -} - -Rpc._parseTxResult = function(info) { - var b = new Buffer(info.hex,'hex'); - - // remove fields we dont need, to speed and adapt the information - delete info.hex; - - // Inputs => add index + coinBase flag - var n =0; - info.vin.forEach(function(i) { - i.n = n++; - if (i.coinbase) info.isCoinBase = true; - }); - - // Outputs => add total - var valueOutSat = 0; - info.vout.forEach( function(o) { - o.value = o.value.toFixed(8); - valueOutSat += o.value * bitcore.util.COIN; - }); - info.valueOut = valueOutSat.toFixed(0) / bitcore.util.COIN; - info.size = b.length; - - return info; -}; - - -Rpc.errMsg = function(err) { - var e = err; - e.message += util.format(' [Host: %s:%d User:%s Using password:%s]', - bitcoreRpc.host, - bitcoreRpc.port, - bitcoreRpc.user, - bitcoreRpc.pass?'yes':'no' - ); - return e; -}; - -Rpc.getTxInfo = function(txid, doNotParse, cb) { - var self = this; - - if (typeof doNotParse === 'function') { - cb = doNotParse; - doNotParse = false; - } - - bitcoreRpc.getRawTransaction(txid, 1, function(err, txInfo) { - // Not found? - if (err && err.code === -5) return cb(); - if (err) return cb(self.errMsg(err)); - - var info = doNotParse ? txInfo.result : self._parseTxResult(txInfo.result); - return cb(null,info); - }); -}; - - -Rpc.blockIndex = function(height, cb) { - var self = this; - - bitcoreRpc.getBlockHash(height, function(err, bh){ - if (err) return cb(self.errMsg(err)); - cb(null, { blockHash: bh.result }); - }); -}; - -Rpc.getBlock = function(hash, cb) { - var self = this; - - bitcoreRpc.getBlock(hash, function(err,info) { - // Not found? - if (err && err.code === -5) return cb(); - if (err) return cb(self.errMsg(err)); - - - if (info.result.height) - info.result.reward = BitcoreBlock.getBlockValue(info.result.height) / bitcore.util.COIN ; - - return cb(err,info.result); - }); -}; - -Rpc.sendRawTransaction = function(rawtx, cb) { - bitcoreRpc.sendRawTransaction(rawtx, function(err, txid) { - if (err) return cb(err); - - return cb(err, txid.result); - }); -}; - -Rpc.verifyMessage = function(address, signature, message, cb) { - var self = this; - bitcoreRpc.verifyMessage(address, signature, message, function(err, message) { - if (err && (err.code === -3 || err.code === -5)) - return cb(err); // -3 = invalid address, -5 = malformed base64 / etc. - if (err) - return cb(self.errMsg(err)); - - return cb(err, message.result); - }); -}; - -module.exports = require('soop')(Rpc); - - diff --git a/lib/Sync.js b/lib/Sync.js deleted file mode 100644 index 36b0fa7..0000000 --- a/lib/Sync.js +++ /dev/null @@ -1,300 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); - -var config = imports.config || require('../config/config'); -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) { - this.id = syncId++; - this.opts = 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) { - var self = this; - self.txDb.close(function() { - self.bDb.close(cb); - }); -}; - - -Sync.prototype.destroy = function(next) { - var self = this; - async.series([ - - function(b) { - self.bDb.drop(b); - }, - function(b) { - self.txDb.drop(b); - }, - ], next); -}; - -/* - * Arrives a NEW block, which is the new TIP - * - * Case 0) Simple case - * A-B-C-D-E(TIP)-NEW - * - * Case 1) - * A-B-C-D-E(TIP) - * \ - * NEW - * - * 1) Declare D-E orphans (and possible invalidate TXs on them) - * - * Case 2) - * A-B-C-D-E(TIP) - * \ - * F-G-NEW - * 1) Set F-G as connected (mark TXs as valid) - * 2) Set new heights in F-G-NEW - * 3) Declare D-E orphans (and possible invalidate TXs on them) - * - * - * Case 3) - * - * A-B-C-D-E(TIP) ... NEW - * - * NEW is ignored (if allowReorgs is false) - * - * - */ - -Sync.prototype.storeTipBlock = function(b, allowReorgs, cb) { - - if (typeof allowReorgs === 'function') { - cb = allowReorgs; - allowReorgs = true; - } - if (!b) return cb(); - var self = this; - - if ( self.storingBlock ) { - logger.debug('Storing a block already. Delaying storeTipBlock with:' + - b.hash); - return setTimeout( function() { - logger.debug('Retrying storeTipBlock with: ' + b.hash); - self.storeTipBlock(b,allowReorgs,cb); - }, 1000); - } - - self.storingBlock=1; - var oldTip, oldNext, oldHeight, needReorg = false, height = -1; - var newPrev = b.previousblockhash; - async.series([ - - // This seems unnecesary. - // 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 || 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) { - if (!allowReorgs) return c(); - self.bDb.getTip(function(err, hash, h) { - oldTip = hash; - oldHeight = hash ? (h || 0) : -1 - if (oldTip && newPrev !== oldTip) { - needReorg = true; - logger.debug('REORG Triggered, tip mismatch'); - } - return c(); - }); - }, - - function(c) { - if (!needReorg) return c(); - self.bDb.getNext(newPrev, function(err, val) { - if (err) return c(err); - oldNext = val; - return 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) { - 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, height, function(err) { - return c(err); - }); - }, - function(c) { - self.bDb.setNext(newPrev, b.hash, function(err) { - return c(err); - }); - } - - ], - function(err) { - if (err && err.toString().match(/WARN/)) { - err = null; - } - self.storingBlock=0; - return cb(err, height); - }); -}; - -Sync.prototype.processReorg = function(oldTip, oldNext, newPrev, oldHeight, cb) { - var self = this; - - var orphanizeFrom, newHeight; - - async.series([ - - function(c) { - self.bDb.getHeight(newPrev, function(err, height) { - if (!height) { - // Case 3 + allowReorgs = true - return c(new Error('Could not found block:' + newPrev)); - } - if (height<0) return c(); - - newHeight = height + 1; - info('Reorg Case 1) OldNext: %s NewHeight: %d', oldNext, newHeight); - orphanizeFrom = oldNext; - return c(err); - }); - }, - function(c) { - if (orphanizeFrom) return c(); - - 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); - }); - }); - }); - }, - function(c) { - if (!orphanizeFrom) return c(); - self._setBranchOrphan(orphanizeFrom, function(err) { - return c(err); - }); - }, - ], - function(err) { - return cb(err, newHeight); - }); -}; - -Sync.prototype._setBranchOrphan = function(fromHash, cb) { - var self = this, - hashInterator = fromHash; - - async.whilst( - function() { - return hashInterator; - }, - function(c) { - self.bDb.setBlockNotMain(hashInterator, function(err) { - if (err) return cb(err); - self.bDb.getNext(hashInterator, function(err, val) { - hashInterator = val; - return c(err); - }); - }); - }, cb); -}; - -Sync.prototype.setBranchConnectedBackwards = function(fromHash, cb) { - //console.log('[Sync.js.219:setBranchConnectedBackwards:]',fromHash); //TODO - var self = this, - hashInterator = fromHash, - lastHash = fromHash, - yHeight, - branch = []; - - async.doWhilst( - function(c) { - branch.unshift(hashInterator); - - self.bDb.getPrev(hashInterator, function(err, val) { - if (err) return c(err); - lastHash = hashInterator; - hashInterator = val; - self.bDb.getHeight(hashInterator, function(err, height) { - yHeight = height; - return c(); - }); - }); - }, - function() { - return hashInterator && yHeight<=0; - }, - 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.storeTx = function(tx, cb) { - this.txDb.add(tx, cb); -}; - - -module.exports = require('soop')(Sync); diff --git a/lib/TransactionDb.js b/lib/TransactionDb.js deleted file mode 100644 index c80c132..0000000 --- a/lib/TransactionDb.js +++ /dev/null @@ -1,758 +0,0 @@ -'use strict'; - -var imports = require('soop').imports(); - - - -// to show tx outs -var OUTS_PREFIX = 'txo-'; //txo-- => [addr, btc_sat] -var SPENT_PREFIX = 'txs-'; //txs---- = ts - -// to sum up addr balance (only outs, spents are gotten later) -var ADDR_PREFIX = 'txa2-'; //txa---- -// tsr = 1e13-js_timestamp -// => + btc_sat [:isConfirmed:[scriptPubKey|isSpendConfirmed:SpentTxid:SpentVout:SpentTs] -// |balance:txApperances - - -// TODO: use bitcore networks module -var genesisTXID = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b'; -var CONCURRENCY = 5; -var DEFAULT_SAFE_CONFIRMATIONS = 6; - -var MAX_OPEN_FILES = 500; -var END_OF_WORLD_TS = 1e13; -// var CONFIRMATION_NR_TO_NOT_CHECK = 10; //Spend -/** - * Module dependencies. - */ - -var bitcore = require('bitcore'), - Rpc = imports.rpc || require('./Rpc'), - util = bitcore.util, - networks = bitcore.networks, - levelup = require('levelup'), - async = require('async'), - config = require('../config/config'), - assert = require('assert'), - Script = bitcore.Script, - bitcoreUtil = bitcore.util, - buffertools = require('buffertools'); - -var logger = require('./logger').logger; - -var db = imports.db || levelup(config.leveldb + '/txs', { - maxOpenFiles: MAX_OPEN_FILES -}); -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; - - this._db = db; // this is only exposed for migration script -}; - -TransactionDb.prototype.close = function(cb) { - db.close(cb); -}; - -TransactionDb.prototype.drop = function(cb) { - var path = config.leveldb + '/txs'; - db.close(function() { - require('leveldown').destroy(path, function() { - db = levelup(path, { - maxOpenFiles: 500 - }); - return cb(); - }); - }); -}; - -TransactionDb.prototype._addSpentInfo = function(r, txid, index, ts) { - if (r.spentTxId) { - if (!r.multipleSpentAttempts) { - r.multipleSpentAttempts = [{ - txid: r.spentTxId, - index: r.index, - }]; - } - r.multipleSpentAttempts.push({ - txid: txid, - index: parseInt(index), - }); - } else { - r.spentTxId = txid; - r.spentIndex = parseInt(index); - r.spentTs = parseInt(ts); - } -}; - - -// This is not used now -TransactionDb.prototype.fromTxId = function(txid, cb) { - var self = this; - var k = OUTS_PREFIX + txid; - var ret = []; - var idx = {}; - var i = 0; - - // outs. - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - var v = data.value.split(':'); - ret.push({ - addr: v[0], - value_sat: parseInt(v[1]), - index: parseInt(k[2]), - }); - idx[parseInt(k[2])] = i++; - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - - var k = SPENT_PREFIX + txid + '-'; - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - var j = idx[parseInt(k[2])]; - - assert(typeof j !== 'undefined', 'Spent could not be stored: tx ' + txid + - 'spent in TX:' + k[1] + ',' + k[2] + ' j:' + j); - - self._addSpentInfo(ret[j], k[3], k[4], data.value); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function(err) { - return cb(err, ret); - }); - }); -}; - - -TransactionDb.prototype._fillSpent = function(info, cb) { - var self = this; - - if (!info) return cb(); - - var k = SPENT_PREFIX + info.txid + '-'; - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - self._addSpentInfo(info.vout[k[2]], k[3], k[4], data.value); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function(err) { - return cb(err); - }); -}; - - -TransactionDb.prototype._fillOutpoints = function(txInfo, cb) { - var self = this; - - if (!txInfo || txInfo.isCoinBase) return cb(); - - var valueIn = 0; - var incompleteInputs = 0; - - async.eachLimit(txInfo.vin, CONCURRENCY, function(i, c_in) { - self.fromTxIdN(i.txid, i.vout, function(err, ret) { - if (!ret || !ret.addr || !ret.valueSat) { - logger.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 - } - - i.addr = ret.addr; - i.valueSat = ret.valueSat; - i.value = ret.valueSat / util.COIN; - valueIn += i.valueSat; - - if (ret.multipleSpentAttempt || !ret.spentTxId || - (ret.spentTxId && ret.spentTxId !== txInfo.txid) - ) { - if (ret.multipleSpentAttempts) { - ret.multipleSpentAttempts.forEach(function(mul) { - if (mul.spentTxId !== txInfo.txid) { - - i.doubleSpentTxID = ret.spentTxId; - i.doubleSpentIndex = ret.spentIndex; - } - }); - } else if (!ret.spentTxId) { - i.dbError = 'Input spent not registered'; - } else { - - i.doubleSpentTxID = ret.spentTxId; - i.doubleSpentIndex = ret.spentIndex; - } - } else { - i.doubleSpentTxID = null; - } - return c_in(); - }); - }, - function() { - if (!incompleteInputs) { - txInfo.valueIn = valueIn / util.COIN; - txInfo.fees = (valueIn - (txInfo.valueOut * util.COIN)).toFixed(0) / util.COIN; - } else { - txInfo.incompleteInputs = 1; - } - return cb(); - }); -}; - -TransactionDb.prototype._getInfo = function(txid, next) { - var self = this; - - Rpc.getTxInfo(txid, function(err, txInfo) { - if (err) return next(err); - self._fillOutpoints(txInfo, function() { - self._fillSpent(txInfo, function() { - return next(null, txInfo); - }); - }); - }); -}; - - -// Simplified / faster Info version: No spent / outpoints info. -TransactionDb.prototype.fromIdInfoSimple = function(txid, cb) { - Rpc.getTxInfo(txid, true, function(err, info) { - if (err) return cb(err); - if (!info) return cb(); - return cb(err, info); - }); -}; - -TransactionDb.prototype.fromIdWithInfo = function(txid, cb) { - var self = this; - - self._getInfo(txid, function(err, info) { - if (err) return cb(err); - if (!info) return cb(); - return cb(err, { - txid: txid, - info: info - }); - }); -}; - -// Gets address info from an outpoint -TransactionDb.prototype.fromTxIdN = function(txid, n, cb) { - var self = this; - var k = OUTS_PREFIX + txid + '-' + n; - - db.get(k, function(err, val) { - var ret; - - if (!val || (err && err.notFound)) { - err = null; - ret = { - unconfirmedInput: 1 - }; - } else { - var a = val.split(':'); - ret = { - addr: a[0], - valueSat: parseInt(a[1]), - }; - } - - // spent? - var k = SPENT_PREFIX + txid + '-' + n + '-'; - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - self._addSpentInfo(ret, k[3], k[4], data.value); - }) - .on('error', function(error) { - return cb(error); - }) - .on('end', function() { - return cb(null, ret); - }); - }); -}; - - -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[0], - }); - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - db.batch(dbScript, cb); - }); -}; - -TransactionDb.prototype.cacheConfirmations = function(txouts, cb) { - var self = this; - - var dbScript = []; - for (var ii in txouts) { - var txout = txouts[ii]; - - //everything already cached? - if (txout.spentIsConfirmedCached) { - continue; - } - - var infoToCache = []; - if (txout.confirmations >= self.safeConfirmations) { - - if (txout.spentConfirmations >= self.safeConfirmations) { - // if spent, we overwrite scriptPubKey cache (not needed anymore) - // First 1 = txout.isConfirmedCached (must be equal to 1 at this point) - infoToCache = [1, 1, txout.spentTxId, txout.spentIndex, txout.spentTs]; - } else { - if (!txout.isConfirmedCached) { - infoToCache.push(1); - txout.confirmedWillBeCached = 1; - } - } - //console.log('[TransactionDb.js.352:infoToCache:]',infoToCache); //TODO - if (infoToCache.length) { - - infoToCache.unshift(txout.value_sat); - 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) { - // console.log('[TransactionDb.js.381:cacheScriptPubKey:]'); //TODO - 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.isConfirmedCached || txout.confirmedWillBeCached) ? 1 : 0, txout.scriptPubKey]; - dbScript.push({ - type: 'put', - key: txout.key, - value: infoToCache.join(':'), - }); - } - } - db.batch(dbScript, cb); -}; - - - - -TransactionDb.prototype._parseAddrData = function(k, data, ignoreCache) { - var v = data.value.split(':'); - // console.log('[TransactionDb.js.375]',data.key,data.value); - var item = { - key: data.key, - ts: END_OF_WORLD_TS - parseInt(k[2]), - txid: k[3], - index: parseInt(k[4]), - value_sat: parseInt(v[0]), - }; - - if (ignoreCache) - return item; - - // Cache: - // v[1]== isConfirmedCached - // v[2]=== '1' -> is SpendCached -> [4]=spendTxId [5]=spentIndex [6]=spendTs - // v[2]!== '1' -> is ScriptPubkey -> [[2] = scriptPubkey - if (v[1] === '1') { - item.isConfirmed = 1; - item.isConfirmedCached = 1; - // console.log('[TransactionDb.js.356] CACHE HIT CONF:', item.key); - // Sent, confirmed - if (v[2] === '1') { - // console.log('[TransactionDb.js.356] CACHE HIT SPENT:', item.key); - item.spentIsConfirmed = 1; - item.spentIsConfirmedCached = 1; - item.spentTxId = v[3]; - item.spentIndex = parseInt(v[4]); - item.spentTs = parseInt(v[5]); - } - // Scriptpubkey cached - else if (v[2]) { - item.scriptPubKey = v[2]; - item.scriptPubKeyCached = 1; - // console.log('[TransactionDb.js.356] CACHE HIT SCRIPTPUBKEY:', item.key, v, item.scriptPubKey); - } - } - return item; -}; - - -TransactionDb.prototype.fromAddr = function(addr, opts, cb) { - opts = opts || {}; - var self = this; - var k = ADDR_PREFIX + addr + '-'; - var ret = []; - var unique = {}; - - db.createReadStream({ - start: k, - end: k + '~', - limit: opts.txLimit > 0 ? opts.txLimit : -1, // -1 means not limit - }) - .on('data', function(data) { - var k = data.key.split('-'); - var index = k[3] + k[4]; - if (!unique[index]) { - unique[index] = self._parseAddrData(k, data, opts.ignoreCache); - ret.push(unique[index]); - } else { - // add first seen - unique[index].firstSeenTs = END_OF_WORLD_TS - parseInt(k[2]); - } - }) - .on('error', cb) - .on('end', function() { - - // This is a bad idea. ADDR_PREFIX ONLY indexes tx in outputs - // it is still necesarry for search for inputs - // if (opts.dontFillSpent) { - // return cb(null, ret) - //} - - 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, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - self._addSpentInfo(o, k[3], k[4], data.value); - }) - .on('error', e_c) - .on('end', e_c); - }, - 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 + '-', - end: OUTS_PREFIX + txid + '~', - }).pipe( - db.createWriteStream({ - type: 'del' - }) - ).on('close', c); - }, - function(c) { - db.createReadStream({ - start: SPENT_PREFIX + txid + '-', - end: SPENT_PREFIX + txid + '~' - }) - .pipe( - db.createWriteStream({ - type: 'del' - }) - ).on('close', c); - } - ], - function(err) { - cb(err); - }); - -}; - - -// relatedAddrs is an optional hash, to collect related addresses in the transaction -TransactionDb.prototype._addScript = function(tx, 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, - }); - } - } - - 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 (relatedAddrs) relatedAddrs[addr] = 1; - var k = OUTS_PREFIX + txid + '-' + o.n; - var tsr = END_OF_WORLD_TS - ts; - dbScript.push({ - type: 'put', - key: k, - value: addr + ':' + sat, - }, { - type: 'put', - key: ADDR_PREFIX + addr + '-' + tsr + '-' + txid + '-' + o.n, - value: sat, - }); - } - } - return dbScript; -}; - -// adds an unconfimed TX -TransactionDb.prototype.add = function(tx, cb) { - var relatedAddrs = {}; - var dbScript = this._addScript(tx, relatedAddrs); - db.batch(dbScript, function(err) { - return cb(err, relatedAddrs); - }); -}; - -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; - - Rpc.getTxInfo(txid, function(err, txInfo) { - if (err) return cb(false); - var ret; - - if (txInfo && txInfo.isCoinBase) - ret = self.poolMatch.match(new Buffer(txInfo.vin[0].coinbase, 'hex')); - - return cb(ret); - }); -}; - - -TransactionDb.prototype.checkVersion02 = function(cb) { - var k = 'txa-'; - var isV2 = 1; - db.createReadStream({ - start: k, - end: k + '~', - limit: 1, - }) - .on('data', function(data) { - isV2 = 0; - }) - .on('end', function() { - return cb(isV2); - }); -}; - -TransactionDb.prototype.migrateV02 = function(cb) { - var k = 'txa-'; - var dbScript = []; - var c = 0; - var c2 = 0; - var N = 50000; - db.createReadStream({ - start: k, - end: k + '~' - }) - .on('data', function(data) { - var k = data.key.split('-'); - var v = data.value.split(':'); - dbScript.push({ - type: 'put', - key: ADDR_PREFIX + k[1] + '-' + (END_OF_WORLD_TS - parseInt(v[1])) + '-' + k[2] + '-' + k[3], - value: v[0], - }); - if (c++ > N) { - console.log('\t%dM txs outs processed', ((c2 += N) / 1e6).toFixed(3)); //TODO - db.batch(dbScript, function() { - c = 0; - dbScript = []; - }); - } - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(); - }); -}; - - - -module.exports = require('soop')(TransactionDb); diff --git a/bitcore-node/addresses.js b/lib/addresses.js similarity index 100% rename from bitcore-node/addresses.js rename to lib/addresses.js diff --git a/bitcore-node/blocks.js b/lib/blocks.js similarity index 100% rename from bitcore-node/blocks.js rename to lib/blocks.js diff --git a/app/controllers/common.js b/lib/common.js similarity index 100% rename from app/controllers/common.js rename to lib/common.js diff --git a/bitcore-node/index.js b/lib/index.js similarity index 100% rename from bitcore-node/index.js rename to lib/index.js diff --git a/lib/logger.js b/lib/logger.js deleted file mode 100644 index 2368092..0000000 --- a/lib/logger.js +++ /dev/null @@ -1,13 +0,0 @@ -var winston = require('winston'); -var config = require('../config/config'); - -var logger = new winston.Logger({ - transports: [ - new winston.transports.Console({ - level: 'error' - }), - ] -}); -logger.transports.console.level = config.loggerLevel; - -module.exports.logger = logger; diff --git a/bitcore-node/service.js b/lib/service.js similarity index 100% rename from bitcore-node/service.js rename to lib/service.js diff --git a/bitcore-node/status.js b/lib/status.js similarity index 100% rename from bitcore-node/status.js rename to lib/status.js diff --git a/bitcore-node/transactions.js b/lib/transactions.js similarity index 100% rename from bitcore-node/transactions.js rename to lib/transactions.js diff --git a/package.json b/package.json index 78a20a3..51e12e9 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,9 @@ }, { "name": "Ivan Socolsky", "email": "jungans@gmail.com" + }, { + "name": "Patrick Nagurny", + "email": "patrick@bitpay.com" }], "bugs": { "url": "https://github.com/bitpay/insight-api/issues" @@ -39,50 +42,18 @@ "engines": { "node": "*" }, - "bin": "insight.js", "scripts": { - "start": "node insight.js" + "test": "NODE_ENV=test mocha -R spec --recursive" }, - "bitcoreNode": "bitcore-node", + "bitcoreNode": "lib", "dependencies": { "async": "*", - "base58-native": "0.1.2", - "bignum": "*", - "morgan": "*", - "bitcore": "git://github.com/bitpay/bitcore.git#51c53b16ced6bcaf4b78329955d6814579fe4ee9", - "bufferput": "git://github.com/bitpay/node-bufferput.git", - "buffertools": "*", - "commander": "^2.3.0", - "connect-ratelimit": "git://github.com/dharmafly/connect-ratelimit.git#0550eff209c54f35078f46445000797fa942ab97", - "cron": "^1.0.4", - "express": "~3.4.7", - "glob": "*", - "leveldown": "~0.10.0", - "levelup": "~0.19.0", - "lodash": "^2.4.1", - "microtime": "^0.6.0", - "mkdirp": "^0.5.0", - "moment": "~2.5.0", - "preconditions": "^1.0.7", - "request": "^2.48.0", - "socket.io": "1.0.6", - "socket.io-client": "1.0.6", - "soop": "=0.1.5", - "winston": "*", - "xmlhttprequest": "~1.6.0" + "bitcore": "^0.13.2", + "lodash": "^2.4.1" }, "devDependencies": { + "mocha": "~1.16.2", "chai": "*", - "grunt": "~0.4.2", - "grunt-cli": "~0.1.11", - "grunt-concurrent": "~0.4.2", - "grunt-contrib-jshint": "~0.8.0", - "grunt-contrib-watch": "~0.5.3", - "grunt-env": "~0.4.1", - "grunt-markdown": "~0.5.0", - "grunt-mocha-test": "~0.8.1", - "grunt-nodemon": "~0.2.0", - "memdown": "^0.10.2", "should": "^2.1.1", "sinon": "^1.10.3" } diff --git a/plugins/config-credentialstore.js b/plugins/config-credentialstore.js deleted file mode 100644 index 7be35b6..0000000 --- a/plugins/config-credentialstore.js +++ /dev/null @@ -1,2 +0,0 @@ -module.exports = { -}; diff --git a/plugins/config-currencyrates.js b/plugins/config-currencyrates.js deleted file mode 100644 index 45758fd..0000000 --- a/plugins/config-currencyrates.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - fetchIntervalInMinutes: 60, - defaultSource: 'BitPay', -}; diff --git a/plugins/config-monitor.js b/plugins/config-monitor.js deleted file mode 100644 index 1958a96..0000000 --- a/plugins/config-monitor.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - cronTime: '* * * * *', // run each minute -}; diff --git a/plugins/config-ratelimiter.js b/plugins/config-ratelimiter.js deleted file mode 100644 index f4d6253..0000000 --- a/plugins/config-ratelimiter.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - -}; diff --git a/plugins/currencyRates/bitpay.js b/plugins/currencyRates/bitpay.js deleted file mode 100644 index fb9a442..0000000 --- a/plugins/currencyRates/bitpay.js +++ /dev/null @@ -1,15 +0,0 @@ -var _ = require('lodash'); - -module.exports.id = 'BitPay'; -module.exports.url = 'https://bitpay.com/api/rates/'; - -module.exports.parseFn = function(raw) { - var rates = _.compact(_.map(raw, function(d) { - if (!d.code || !d.rate) return null; - return { - code: d.code, - rate: d.rate, - }; - })); - return rates; -}; diff --git a/plugins/currencyRates/bitstamp.js b/plugins/currencyRates/bitstamp.js deleted file mode 100644 index 1743c2b..0000000 --- a/plugins/currencyRates/bitstamp.js +++ /dev/null @@ -1,11 +0,0 @@ -var _ = require('lodash'); - -module.exports.id = 'Bitstamp'; -module.exports.url = 'https://www.bitstamp.net/api/ticker/'; - -module.exports.parseFn = function(raw) { - return [{ - code: 'USD', - rate: parseFloat(raw.last) - }]; -}; diff --git a/plugins/currencyrates.js b/plugins/currencyrates.js deleted file mode 100644 index cc53eba..0000000 --- a/plugins/currencyrates.js +++ /dev/null @@ -1,199 +0,0 @@ -(function() { - 'use strict'; - - var _ = require('lodash'); - var async = require('async'); - var levelup = require('levelup'); - var request = require('request'); - var preconditions = require('preconditions').singleton(); - - var logger = require('../lib/logger').logger; - var globalConfig = require('../config/config'); - - var currencyRatesPlugin = {}; - - function getCurrentTs() { - return Math.floor(new Date() / 1000); - }; - - function getKey(sourceId, code, ts) { - var key = sourceId + '-' + code.toUpperCase(); - if (ts) { - key += '-' + ts; - } - return key; - }; - - function returnError(error, res) { - res.status(error.code).json({ - error: error.message, - }).end(); - }; - - currencyRatesPlugin.init = function(config) { - logger.info('Using currencyrates plugin'); - - config = config || {}; - - var path = globalConfig.leveldb + '/currencyRates' + (globalConfig.name ? ('-' + globalConfig.name) : ''); - currencyRatesPlugin.db = config.db || globalConfig.db || levelup(path); - - if (_.isArray(config.sources)) { - currencyRatesPlugin.sources = config.sources; - } else { - currencyRatesPlugin.sources = [ - require('./currencyRates/bitpay'), - require('./currencyRates/bitstamp'), - ]; - } - currencyRatesPlugin.request = config.request || request; - currencyRatesPlugin.defaultSource = config.defaultSource || globalConfig.defaultSource; - - currencyRatesPlugin.initialized = true; - - var interval = config.fetchIntervalInMinutes || globalConfig.fetchIntervalInMinutes; - if (interval) { - currencyRatesPlugin._fetch(); - setInterval(function() { - currencyRatesPlugin._fetch(); - }, interval * 60 * 1000); - } - }; - - currencyRatesPlugin._retrieve = function(source, cb) { - logger.debug('Fetching data for ' + source.id); - currencyRatesPlugin.request.get({ - url: source.url, - json: true - }, function(err, res, body) { - if (err || !body) { - logger.warn('Error fetching data for ' + source.id, err); - return cb(err); - } - - logger.debug('Data for ' + source.id + ' fetched successfully'); - - if (!source.parseFn) { - return cb('No parse function for source ' + source.id); - } - var rates = source.parseFn(body); - - return cb(null, rates); - }); - }; - - currencyRatesPlugin._store = function(source, rates, cb) { - logger.debug('Storing data for ' + source.id); - var ts = getCurrentTs(); - var ops = _.map(rates, function(r) { - return { - type: 'put', - key: getKey(source.id, r.code, ts), - value: r.rate, - }; - }); - - currencyRatesPlugin.db.batch(ops, function(err) { - if (err) { - logger.warn('Error storing data for ' + source.id, err); - return cb(err); - } - logger.debug('Data for ' + source.id + ' stored successfully'); - return cb(); - }); - }; - - currencyRatesPlugin._dump = function(opts) { - var all = []; - currencyRatesPlugin.db.readStream(opts) - .on('data', console.log); - }; - - currencyRatesPlugin._fetch = function(cb) { - cb = cb || function() {}; - - preconditions.shouldNotBeFalsey(currencyRatesPlugin.initialized); - - async.each(currencyRatesPlugin.sources, function(source, cb) { - currencyRatesPlugin._retrieve(source, function(err, res) { - if (err) { - logger.warn(err); - return cb(); - } - currencyRatesPlugin._store(source, res, function(err, res) { - return cb(); - }); - }); - }, function(err) { - return cb(err); - }); - }; - - currencyRatesPlugin._getOneRate = function(sourceId, code, ts, cb) { - var result = null; - - currencyRatesPlugin.db.createValueStream({ - lte: getKey(sourceId, code, ts), - gte: getKey(sourceId, code) + '!', - reverse: true, - limit: 1, - }) - .on('data', function(data) { - var num = parseFloat(data); - result = _.isNumber(num) && !_.isNaN(num) ? num : null; - }) - .on('error', function(err) { - return cb(err); - }) - .on('end', function() { - return cb(null, result); - }); - }; - - currencyRatesPlugin._getRate = function(sourceId, code, ts, cb) { - preconditions.shouldNotBeFalsey(currencyRatesPlugin.initialized); - preconditions.shouldNotBeEmpty(code); - preconditions.shouldBeFunction(cb); - - ts = ts || getCurrentTs(); - - if (!_.isArray(ts)) { - return currencyRatesPlugin._getOneRate(sourceId, code, ts, function(err, rate) { - if (err) return cb(err); - return cb(null, { - rate: rate - }); - }); - } - - async.map(ts, function(ts, cb) { - currencyRatesPlugin._getOneRate(sourceId, code, ts, function(err, rate) { - if (err) return cb(err); - return cb(null, { - ts: parseInt(ts), - rate: rate - }); - }); - }, function(err, res) { - if (err) return cb(err); - return cb(null, res); - }); - }; - - currencyRatesPlugin.getRate = function(req, res) { - var source = req.param('source') || currencyRatesPlugin.defaultSource; - var ts = req.param('ts'); - if (_.isString(ts) && ts.indexOf(',') !== -1) { - ts = ts.split(','); - } - currencyRatesPlugin._getRate(source, req.param('code'), ts, function(err, result) { - if (err) returnError({ - code: 500, - message: err, - }); - res.json(result); - }); - }; - - module.exports = currencyRatesPlugin; -})(); diff --git a/plugins/emailTemplates/copay.html b/plugins/emailTemplates/copay.html deleted file mode 100644 index 3639b0d..0000000 --- a/plugins/emailTemplates/copay.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - <%= title%> - - - - - - - - - - - - - - - -
- - - - - - - -
- - -

Hi, <%= email %>

- -

You are now using Insight to store an encrypted Copay backup. This is a free -service that we are providing that you can turn off from Copay's preferences.

- -

In order to prevent abuse, we need you to confirm that this email is valid and -that you requested this backup. Please follow this link if you agree on -backing up your Copay profile within our servers:

- -

- - Confirm your email (click here). -

-

If the above link doesn't work, head to: <%= confirm_url %>

- -

We would also like you to know that:

-
    - -
  • We only store information encrypted by your Copay app. We can't retrieve your private keys, help you remember the password, or collect any information about your wallet.
  • - -
  • In case that one of our servers is compromised, intruders may be able to brute-force their way into your private keys unless you use a strong password.
  • - -
  • Our code is open source and can be audited here: -
      -
    • https://github.com/bitpay/insight
    • -
    • https://github.com/bitpay/copay
    • -
    -
  • -
- -

Thanks!

- -

The Copay Team

- -
- - - diff --git a/plugins/emailTemplates/copay.plain b/plugins/emailTemplates/copay.plain deleted file mode 100644 index f6ee162..0000000 --- a/plugins/emailTemplates/copay.plain +++ /dev/null @@ -1,27 +0,0 @@ -Hi, <%= email %> - -You are now using Insight to store an encrypted Copay backup. This is a free -service that we are providing that you can turn off from Copay's preferences. - -In order to prevent abuse, we need you to confirm that this email is valid and -that you requested this backup. Please follow this link if you agree on -backing up your Copay profile within our servers: - - <%= confirm_url %> - -We would also like you to take note of these: - - * We only store information encrypted by your Copay app. We can't retrieve - your private keys, help you remember the password, or collect any information - about your wallet. - - * In case of a service compromise, intruders may be able to brute-force their - way into your private keys. Please use a strong password to avoid this. - - * Our code is open source and can be audited here: - https://github.com/bitpay/insight - https://github.com/bitpay/copay - -Thanks! - -The Copay Team diff --git a/plugins/emailstore.js b/plugins/emailstore.js deleted file mode 100644 index 05c7f88..0000000 --- a/plugins/emailstore.js +++ /dev/null @@ -1,288 +0,0 @@ -/** - * GIST: https://gist.github.com/eordano/3e80ee3383554e94a08e - */ -(function() { - - 'use strict'; - - var _ = require('lodash'); - var async = require('async'); - var bitcore = require('bitcore'); - var crypto = require('crypto'); - var fs = require('fs'); - var levelup = require('levelup'); - var querystring = require('querystring'); - var moment = require('moment'); - - var logger = require('../lib/logger').logger; - var globalConfig = require('../config/config'); - - var emailPlugin = {}; - - /** - * Constant enum with the errors that the application may return - */ - emailPlugin.errors = { - MISSING_PARAMETER: { - code: 400, - message: 'Missing required parameter' - }, - INVALID_REQUEST: { - code: 400, - message: 'Invalid request parameter' - }, - NOT_FOUND: { - code: 404, - message: 'Email already confirmed or credentials not found' - }, - INTERNAL_ERROR: { - code: 500, - message: 'Unable to save to database' - }, - EMAIL_TAKEN: { - code: 409, - message: 'That email is already registered' - }, - INVALID_CODE: { - code: 403, - message: 'The provided code is invalid' - }, - OVER_QUOTA: { - code: 406, - message: 'User quota exceeded', - }, - ERROR_SENDING_EMAIL: { - code: 501, - message: 'Could not send verification email', - }, - }; - - var EMAIL_TO_PASSPHRASE = 'email-to-passphrase-'; - var STORED_VALUE = 'emailstore-'; - var ITEMS_COUNT = 'itemscount-'; - var PENDING = 'pending-'; - var VALIDATED = 'validated-'; - - var SEPARATOR = '#'; - - var UNCONFIRMED_PER_ITEM_QUOTA = 1024 * 150; /* 150 kb */ - var CONFIRMED_PER_ITEM_QUOTA = 1024 * 300; /* 300 kb */ - - var UNCONFIRMED_ITEMS_LIMIT = 6; - var CONFIRMED_ITEMS_LIMIT = 11; - - var POST_LIMIT = 1024 * 300 /* Max POST 300 kb */ ; - - var valueKey = function(email, key) { - return STORED_VALUE + bitcore.util.twoSha256(email + SEPARATOR + key).toString('hex'); - }; - - - var countKey = function(email) { - return ITEMS_COUNT + bitcore.util.twoSha256(email).toString('hex'); - }; - - var pendingKey = function(email) { - return PENDING + email; - }; - - var validatedKey = function(email) { - return VALIDATED + bitcore.util.twoSha256(email).toString('hex'); - }; - - var emailToPassphrase = function(email) { - return EMAIL_TO_PASSPHRASE + bitcore.util.twoSha256(email).toString('hex'); - }; - - /** - * Initializes the plugin - * - * @param {Object} config - */ - emailPlugin.init = function(config) { - logger.info('Using emailstore plugin'); - config = config || {}; - - var path = globalConfig.leveldb + '/emailstore' + (globalConfig.name ? ('-' + globalConfig.name) : ''); - emailPlugin.db = config.db || globalConfig.db || levelup(path); - emailPlugin.crypto = config.crypto || crypto; - }; - - /** - * Helper function that ends a requests showing the user an error. The response body will be a JSON - * encoded object with only one property with key "error" and value error.message, one of - * the parameters of the function - * - * @param {Object} error - The error that caused the request to be terminated - * @param {number} error.code - the HTTP code to return - * @param {string} error.message - the message to send in the body - * @param {Express.Response} response - the express.js response. the methods status, json, and end - * will be called, terminating the request. - */ - emailPlugin.returnError = function(error, response) { - response.status(error.code).json({ - error: error.message - }).end(); - }; - - /** - * @param {string} email - * @param {string} passphrase - * @param {Function(err, boolean)} callback - */ - emailPlugin.checkPassphrase = function(email, passphrase, callback) { - emailPlugin.db.get(emailToPassphrase(email), function(err, retrievedPassphrase) { - if (err) { - if (err.notFound) { - return callback(emailPlugin.errors.INVALID_CODE); - } - logger.error('error checking passphrase', email, err); - return callback(emailPlugin.errors.INTERNAL_ERROR); - } - return callback(err, passphrase === retrievedPassphrase); - }); - }; - - - /** - * @param {string} email - * @param {string} passphrase - * @param {Function(err)} callback - */ - emailPlugin.savePassphrase = function(email, passphrase, callback) { - emailPlugin.db.put(emailToPassphrase(email), passphrase, function(err) { - if (err) { - logger.error('error saving passphrase', err); - return callback(emailPlugin.errors.INTERNAL_ERROR); - } - return callback(null); - }); - }; - - - /** - * @param {string} email - * @param {string} key - * @param {string} record - * @param {Function(err)} callback - */ - emailPlugin.saveEncryptedData = function(email, key, record, callback) { - emailPlugin.db.put(valueKey(email, key), record, function(err) { - if (err) { - logger.error('error saving encrypted data', email, key, record, err); - return callback(emailPlugin.errors.INTERNAL_ERROR); - } - return callback(); - }); - }; - - /** - * @param {string} email - * @param {Function(err)} callback - */ - emailPlugin.retrieveByEmailAndKey = function(email, key, callback) { - emailPlugin.db.get(valueKey(email, key), function(error, value) { - if (error) { - if (error.notFound) { - return callback(emailPlugin.errors.NOT_FOUND); - } - return callback(emailPlugin.errors.INTERNAL_ERROR); - } - return callback(null, value); - }); - }; - - emailPlugin.getCredentialsFromRequest = function(request) { - var auth = request.header('authorization'); - if (!auth) { - return emailPlugin.errors.INVALID_REQUEST; - } - var authHeader = new Buffer(auth, 'base64').toString('utf8'); - var splitIndex = authHeader.indexOf(':'); - if (splitIndex === -1) { - return emailPlugin.errors.INVALID_REQUEST; - } - var email = authHeader.substr(0, splitIndex); - var passphrase = authHeader.substr(splitIndex + 1); - - return { - email: email, - passphrase: passphrase - }; - }; - - - /** - * @param {string} email - * @param {Function(err, boolean)} callback - */ - emailPlugin.isConfirmed = function(email, callback) { - emailPlugin.db.get(validatedKey(email), function(err, isConfirmed) { - if (err && err.notFound) { - return callback(null, false); - } else if (err) { - return callback(emailPlugin.errors.INTERNAL_ERROR); - } - return callback(null, !!isConfirmed); - }); - }; - - - emailPlugin.authorizeRequest = function(request, withKey, callback) { - var credentialsResult = emailPlugin.getCredentialsFromRequest(request); - if (_.contains(emailPlugin.errors, credentialsResult)) { - return callback(credentialsResult); - } - - var email = credentialsResult.email; - var passphrase = credentialsResult.passphrase; - var key; - if (withKey) { - key = request.param('key'); - } - - if (!passphrase || !email || (withKey && !key)) { - return callback(emailPlugin.errors.MISSING_PARAMETER); - } - - emailPlugin.checkPassphrase(email, passphrase, function(err, matches) { - if (err) { - return callback(err); - } - - if (!matches) { - return callback(emailPlugin.errors.INVALID_CODE); - } - - return callback(null, email, key); - }); - }; - - emailPlugin.authorizeRequestWithoutKey = function(request, callback) { - emailPlugin.authorizeRequest(request, false, callback); - }; - - emailPlugin.authorizeRequestWithKey = function(request, callback) { - emailPlugin.authorizeRequest(request, true, callback); - }; - - /** - * Retrieve a record from the database - */ - emailPlugin.retrieve = function(request, response) { - emailPlugin.authorizeRequestWithKey(request, function(err, email, key) { - if (err) - return emailPlugin.returnError(err, response); - - emailPlugin.retrieveByEmailAndKey(email, key, function(err, value) { - if (err) - return emailPlugin.returnError(err, response); - - response.send(value).end(); - }); - }); - }; - - module.exports = emailPlugin; - -})(); diff --git a/plugins/monitor.js b/plugins/monitor.js deleted file mode 100644 index e5d0ac3..0000000 --- a/plugins/monitor.js +++ /dev/null @@ -1,26 +0,0 @@ -var mdb = require('../lib/MessageDb').default(); -var logger = require('../lib/logger').logger; -var preconditions = require('preconditions').singleton(); -var microtime = require('microtime'); -var cron = require('cron'); -var CronJob = cron.CronJob; - - -module.exports.init = function(config) { - var cronTime = config.cronTime || '0 * * * *'; - logger.info('Using monitor plugin with cronTime ' + cronTime); - var onTick = function() { - mdb.getAll(function(err, messages) { - if (err) logger.error(err); - else { - logger.info('Message db size = ' + messages.length); - } - }); - }; - var job = new CronJob({ - cronTime: cronTime, - onTick: onTick - }); - onTick(); - job.start(); -}; diff --git a/plugins/publicInfo/config.js b/plugins/publicInfo/config.js deleted file mode 100644 index 7be35b6..0000000 --- a/plugins/publicInfo/config.js +++ /dev/null @@ -1,2 +0,0 @@ -module.exports = { -}; diff --git a/plugins/publicInfo/publicInfo.js b/plugins/publicInfo/publicInfo.js deleted file mode 100644 index ddafb03..0000000 --- a/plugins/publicInfo/publicInfo.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Module to allow Copay users to publish public information about themselves - * - * It uses BitAuth to verify the authenticity of the request. - * - */ -(function() { - -'use strict'; - -var logger = require('../../lib/logger').logger, - levelup = require('levelup'), - bitauth = require('bitauth'), - globalConfig = require('../../config/config'), - querystring = require('querystring'); - -var publicInfo = {}; - -/** - * Constant enum with the errors that the application may return - */ -var errors = { - MISSING_PARAMETER: { - code: 400, - message: 'Missing required parameter' - }, - UNAUTHENTICATED: { - code: 401, - message: 'SIN validation error' - }, - NOT_FOUND: { - code: 404, - message: 'There\'s no record of public information for the public key requested' - } -}; - -var NAMESPACE = 'public-info-'; -var MAX_ALLOWED_STORAGE = 64 * 1024 /* no more than 64 kb of data is allowed to be stored */; - -/** - * Initializes the plugin - * - * @param {Express} expressApp - * @param {Object} config - */ -publicInfo.init = function(expressApp, config) { - logger.info('Using publicInfo plugin'); - - var path = globalConfig.leveldb + '/publicinfo' + (globalConfig.name ? ('-' + globalConfig.name) : ''); - publicInfo.db = config.db || globalConfig.db || levelup(path); - - expressApp.post(globalConfig.apiPrefix + '/public', publicInfo.post); - expressApp.get(globalConfig.apiPrefix + '/public/:sin', publicInfo.get); -}; - -/** - * Helper function that ends a requests showing the user an error. The response body will be a JSON - * encoded object with only one property with key "error" and value error.message, one of - * the parameters of the function - * - * @param {Object} error - The error that caused the request to be terminated - * @param {number} error.code - the HTTP code to return - * @param {string} error.message - the message to send in the body - * @param {Express.Response} response - the express.js response. the methods status, json, and end - * will be called, terminating the request. - */ -var returnError = function(error, response) { - response.status(error.code).json({error: error.message}).end(); -}; - -/** - * Store a record in the database. The underlying database is merely a levelup instance (a key - * value store) that uses the SIN to store the body of the message. - * - * @param {Express.Request} request - * @param {Express.Response} response - */ -publicInfo.post = function(request, response) { - - var record = ''; - request.on('data', function(data) { - record += data; - if (record.length > MAX_ALLOWED_STORAGE) { - record = ''; - response.writeHead(413, {'Content-Type': 'text/plain'}).end(); - request.connection.destroy(); - } - }).on('end', function() { - var fullUrl = request.protocol + '://' + request.get('host') + request.url; - var data = fullUrl + record; - - bitauth.verifySignature(data, request.headers['x-identity'], request.headers['x-signature'], - function(err, result) { - if(err || !result) { - return returnError(errors.UNAUTHENTICATED, response); - } - - // Get the SIN from the public key - var sin = bitauth.getSinFromPublicKey(request.headers['x-identity']); - if (!sin) { - return returnError(errors.UNAUTHENTICATED, response); - } - publicInfo.db.put(NAMESPACE + sin, record, function (err) { - if (err) { - return returnError({code: 500, message: err}, response); - } - response.json({success: true}).end(); - if (request.testCallback) { - request.testCallback(); - } - }); - } - ); - }); -}; - -/** - * Retrieve a record from the database. - * - * The request is expected to contain the parameter "sin" - * - * @param {Express.Request} request - * @param {Express.Response} response - */ -publicInfo.get = function(request, response) { - var sin = request.param('sin'); - if (!sin) { - return returnError(errors.MISSING_PARAMETER, response); - } - - publicInfo.db.get(NAMESPACE + sin, function (err, value) { - if (err) { - if (err.notFound) { - return returnError(errors.NOT_FOUND, response); - } - return returnError({code: 500, message: err}, response); - } - response.send(value).end(); - }); -}; - -module.exports = publicInfo; - -})(); diff --git a/plugins/ratelimiter.js b/plugins/ratelimiter.js deleted file mode 100644 index 1633652..0000000 --- a/plugins/ratelimiter.js +++ /dev/null @@ -1,35 +0,0 @@ -var logger = require('../lib/logger').logger; -var preconditions = require('preconditions').singleton(); - -var limiter = require('connect-ratelimit'); -var THREE_HOURS = 3* 60 * 60 * 1000; - -module.exports.init = function(app, config) { - preconditions.checkArgument(app); - logger.info('Using ratelimiter plugin'); - - config = config || {}; - config.whitelistRPH = config.whitelistRPH || 3*60*60*10; - config.normalRPH = config.normalRPH || 3*60*60; - config.blacklistRPH = config.blacklistRPH || 0; - - app.use(limiter({ - whitelist: [], - end: true, - blacklist: [], // 'example.com' - categories: { - whitelist: { - totalRequests: config.whitelistRPH, - every: THREE_HOURS - }, - blacklist: { - totalRequests: config.blacklistRPH, - every: THREE_HOURS - }, - normal: { - totalRequests: config.normalRPH, - every: THREE_HOURS - } - } - })); -}; diff --git a/test/bitcore-node/addresses.js b/test/addresses.js similarity index 99% rename from test/bitcore-node/addresses.js rename to test/addresses.js index ef26d82..83ffd4b 100644 --- a/test/bitcore-node/addresses.js +++ b/test/addresses.js @@ -1,7 +1,7 @@ 'use strict'; var sinon = require('sinon'); var should = require('should'); -var AddressController = require('../../bitcore-node/addresses'); +var AddressController = require('../lib/addresses'); var _ = require('lodash'); var bitcore = require('bitcore'); diff --git a/test/bitcore-node/blocks.js b/test/blocks.js similarity index 99% rename from test/bitcore-node/blocks.js rename to test/blocks.js index d74eb70..07ef4e3 100644 --- a/test/bitcore-node/blocks.js +++ b/test/blocks.js @@ -2,7 +2,7 @@ var should = require('should'); var sinon = require('sinon'); -var BlockController = require('../../bitcore-node/blocks'); +var BlockController = require('../lib/blocks'); var bitcore = require('bitcore'); var _ = require('lodash'); diff --git a/test/integration/01-transactionouts.js b/test/integration/01-transactionouts.js deleted file mode 100644 index 732c3c8..0000000 --- a/test/integration/01-transactionouts.js +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - - - -var should = require('chai'); -var assert = require('assert'), - fs = require('fs'), - util = require('util'), - TransactionDb = require('../../lib/TransactionDb').default(); - -var txItemsValid = JSON.parse(fs.readFileSync('test/integration/txitems.json')); -var txDb; - -describe('TransactionDb fromIdWithInfo', function(){ - - before(function(c) { - txDb = TransactionDb; - return c(); - }); - - - var txid = '7e621eeb02874ab039a8566fd36f4591e65eca65313875221842c53de6907d6c'; - it('tx info ' + txid, function(done) { - txDb.fromIdWithInfo(txid, function(err, tx) { - - if (err) done(err); - assert.equal(tx.txid, txid); - assert(!tx.info.isCoinBase); - - for(var i=0; i<20; i++) { - assert(parseFloat(tx.info.vin[i].value) === parseFloat(50), 'input '+i); - } - - - tx.info.vin[0].addr.should.equal('msGKGCy2i8wbKS5Fo1LbWUTJnf1GoFFG59'); - tx.info.vin[1].addr.should.equal('mfye7oHsdrHbydtj4coPXCasKad2eYSv5P'); - done(); - }); - }); - - it('tx info', function(done) { - var txid = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237'; - txDb.fromIdWithInfo(txid, function(err, tx) { - if (err) done(err); - assert.equal(tx.txid, txid); - assert(!tx.info.isCoinBase); - done(); - }); - }); - - it('should pool tx\'s info from bitcoind', function(done) { - var txid = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237'; - txDb.fromIdWithInfo(txid, function(err, tx) { - if (err) done(err); - assert.equal(tx.info.txid, txid); - assert.equal(tx.info.blockhash, '000000000185678d3d7ecc9962c96418174431f93fe20bf216d5565272423f74'); - assert.equal(tx.info.valueOut, 1.66174); - assert.equal(tx.info.fees, 0.0005 ); - assert.equal(tx.info.size, 226 ); - assert(!tx.info.isCoinBase); - done(); - }); - }); - - var txid1 = '2a104bab1782e9b6445583296d4a0ecc8af304e4769ceb64b890e8219c562399'; - it('test a coinbase TX ' + txid1, function(done) { - txDb.fromIdWithInfo(txid1, function(err, tx) { - if (err) done(err); - assert(tx.info.isCoinBase); - assert.equal(tx.info.txid, txid1); - assert(!tx.info.feeds); - done(); - }); - }); - var txid22 = '666'; - it('test invalid TX ' + txid22, function(done) { - txDb.fromIdWithInfo(txid22, function(err, tx) { - if (err && err.message.match(/must.be.hexadecimal/)) { - return done(); - } - else { - return done(err); - } - }); - }); - - var txid23 = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca227'; - it('test unexisting TX ' + txid23, function(done) { - - txDb.fromIdWithInfo(txid23, function(err, tx) { - assert(!err); - assert(!tx); - return done(); - }); - }); - - - - var txid2 = '64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608'; - it('create TX on the fly ' + txid2, function(done) { - txDb.fromIdWithInfo(txid2, function(err, tx) { - if (err) return done(err); - assert.equal(tx.info.txid, txid2); - done(); - }); - }); - - txid2 = '64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608'; - it('test a broken TX ' + txid2, function(done) { - txDb.fromIdWithInfo(txid2, function(err, tx) { - if (err) return done(err); - assert.equal(tx.info.txid, txid2); - assert.equal(tx.info.vin[0].addr, 'n1JagbRWBDi6VMvG7HfZmXX74dB9eiHJzU'); - done(); - }); - }); -}); - -describe('TransactionDb Outs', function(){ - - before(function(c) { - txDb = TransactionDb; - return c(); - }); - - txItemsValid.forEach( function(v) { - if (v.disabled) return; - it('test a processing tx ' + v.txid, function(done) { - this.timeout(60000); - - // Remove first - txDb.removeFromTxId(v.txid, function() { - - txDb.fromTxId( v.txid, function(err, readItems) { - assert.equal(readItems.length,0); - - var unmatch=[]; - txDb.addMany([v.txid], function(err) { - if (err) return done(err); - - txDb.fromTxId( v.txid, function(err, readItems) { - - v.items.forEach(function(validItem){ - unmatch[validItem.addr] =1; - }); - assert.equal(readItems.length,v.items.length); - - v.items.forEach(function(validItem){ - var readItem = readItems.shift(); - - assert.equal(readItem.addr,validItem.addr); - assert.equal(readItem.value_sat,validItem.value_sat); - assert.equal(readItem.index,validItem.index); - assert.equal(readItem.spendIndex, null); - assert.equal(readItem.spendTxIdBuf, null); - delete unmatch[validItem.addr]; - }); - - var valid = util.inspect(v.items, { depth: null }); - assert(!Object.keys(unmatch).length,'\n\tUnmatchs:' + Object.keys(unmatch) + "\n\n" +valid + '\nvs.\n' + readItems); - return done(); - - }); - }); - }); - }); - }); - }); -}); - - diff --git a/test/integration/02-transactionouts.js b/test/integration/02-transactionouts.js deleted file mode 100644 index 78a363f..0000000 --- a/test/integration/02-transactionouts.js +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - - - -var - assert = require('assert'), - fs = require('fs'), - util = require('util'), - async = require('async'), - config = require('../../config/config'), - TransactionDb = require('../../lib/TransactionDb').default(); - -var spentValid = JSON.parse(fs.readFileSync('test/integration/spent.json')); - -var txDb; - -describe('TransactionDb Expenses', function(){ - - before(function(c) { - txDb = TransactionDb; - - // lets spend! - async.each(Object.keys(spentValid), - function(txid,c_out) { - async.each(spentValid[txid], - function(i,c_in) { - txDb.addMany([i.txid], function(err) { - return c_in(); - }); - }, - function(err) { - return c_out(); - } - ); - }, - function(err) { - return c(); - } - ); - }); - - Object.keys(spentValid).forEach( function(txid) { - it('test result of spending tx ' + txid, function(done) { - var s = spentValid[txid]; - var c=0; - txDb.fromTxId( txid, function(err, readItems) { - s.forEach( function(v) { - assert.equal(readItems[c].spentTxId,v.txid); - assert.equal(readItems[c].spentIndex,v.n); - c++; - }); - done(); - }); - }); - }); -}); diff --git a/test/integration/99-sync.js.descructive-test b/test/integration/99-sync.js.descructive-test deleted file mode 100644 index 4a9c605..0000000 --- a/test/integration/99-sync.js.descructive-test +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/env node -'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'); - -var s; -var b = [ - '00000000c4cbd75af741f3a2b2ff72d9ed4d83a048462c1efe331be31ccf006b', //0 B#16 - '00000000fe198cce4c8abf9dca0fee1182cb130df966cc428ad2a230df8da743', //1 - '000000008d55c3e978639f70af1d2bf1fe6f09cb3143e104405a599215c89a48', //2 - '000000009b3bca4909f38313f2746120129cce4a699a1f552390955da470c5a9', //3 - '00000000ede57f31cc598dc241d129ccb4d8168ef112afbdc870dc60a85f5dd3', //4 B#20 - '000000001a29aff8154de6230a4909a3a971c52ae590006e00fddff33f9e3773', //5 B#21 -]; -var t = [ - 'd08582d3711f75d085c618874fb0d049ae09d5ec95ec6f5abd289f4b54712c54', // TX from B#16 - '1729001087e0cebea8d14de1653d5cf59628d9746bc1ae65f776f1cbaff7ebad', //1 - 'cf53d7ccd83a099acfbc319ee10c1e3b10e3d42ba675b569fdd6b69cb8d2db4e', //2 - '73a4988adf462b6540cfa59097804174b298cfa439f73c1a072c2c6fbdbe57c7', //3 - 'd45f9da73619799e9d7bd03cc290e70875ea4cbad56b8bffa15135fbbb3df9ea', //4 Tx from B20 -]; - -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(); - }); - }, function() { - async.each([0,1,2,3,4], function(i,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.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); - }); - }); - }); - }); -}; - - - -/* - * TEST CASES - * - * b0 height = 16; - * - * Blocks: 0-1-2-3-4 - * case 1) - * 0-1-2-3-4 - * \ - * C1* (height should be 19) - * - * case 2) - * 0-1-2---3-4 - * \ \ - * C1 C2* - * - * case 2b) - * 0-1-2---3-4 - * \ \ - * C1 C2-C2b(TX=C1.TX)* - * case 2c) - * 0-1-2---3-4 - * \ \ - * C1 C2-C2b(TX=C1.TX) - * \ - * C2c(TX=C2.TX)* - * - */ - -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.sync.destroy(done); - }); - - it('simple RPC forward syncing', function(done) { - s.start(opts, function(err) { - if (err) return done(err); - initialTest(done); - }); - }); - - var case1 = { - hash: '0000000042d3db6c529dd8f1b085367cb6d907b534f5b1a5dfdd3a34a3459886', - tx: [ '2dc27c8d4b98f5e2ed009cfc164ac4990f18e03c4d5b71e780f9c8b7b2c5f151' ], - time: 1296690099, - previousblockhash: b[2], - }; - - - describe('reorg, case 1', function() { - 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]); - - 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], - }; - - -// * case 2) -// * 0-1-2---3-4 -// * \ \ -// * C1 C2* - - - describe('reorg, case 2', function() { - checkTxs([t[0], t[1], t[2], t[3], t[4],case1.tx[0]],[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]); - it('trigger reorg case 2', function(done1){ - s.sync.storeTipBlock(case2, function(err) { - assert(!err, 'shouldnt return error' + err); - return done1(); - }); - }); - checkBlocks([b[0], b[1], b[2],b[3],b[4],case2.hash],[16,17,18,19,-1,20]); - checkTxs([t[0], t[1], t[2],t[3],t[4],case2.tx[0]],[16,17,18,19,-1,20]); - it('next from block 2', function(done1){ - s.sync.bDb.getNext(b[2], function(err, val) { - assert(!err); - assert.equal(val,b[3]); - return done1(); - }); - }); - }); - - -// * case 2b) -// * 0-1-2---3-4 -// * \ \ -// * C1 C2-C2b(TX=C1.TX)* - - - var case2b = { - hash: '0000000022bb34bc09f8d8d0ae26b86c87f8483e54b9c3addfe6f30b12bc656a', - tx: case1.tx, - time: 1296690099, - previousblockhash: case2.hash, - }; - - describe('reorg, case 2', function() { - it('reorg case 2b', function(done1){ - s.sync.storeTipBlock(case2b, function(err) { - assert(!err, 'shouldnt return error' + err); - return done1(); - }); - }); - checkBlocks([b[0], b[1], b[2],b[3],b[4],case2.hash, case2b.hash, case1.hash],[16,17,18,19,-1,20, 21, -1]); - checkTxs([t[0], t[1], t[2],t[3],t[4],case2.tx[0], case1.tx],[16,17,18,19,-1,20, 21]); - }); - - var case2c = { - hash: '0000000000000000000000000000000000000000000000000000000000000004', - tx: case2.tx, - time: 1296690099, - previousblockhash: case1.hash, - }; - -// * case 2c) -// * 0-1-2---3-4 -// * \ \ -// * C1 C2-C2b(TX=C1.TX) -// * \ -// * C2c(TX=C2.TX)* - - describe('reorg, case 2c', function() { - it('trigger reorg case 2c', function(done1){ - s.sync.storeTipBlock(case2c, function(err) { - assert(!err, 'shouldnt return error' + err); - return done1(); - }); - }); - checkBlocks([b[0], b[1], b[2], - b[3],b[4],case2.hash, case2b.hash, - case1.hash, case2c.hash], - [16,17,18, - -1,-1,-1, -1, - 19, 20 - ]); - checkTxs( - [t[0], t[1], t[2], - t[3],t[4], case2.tx[0], - case1.tx, case2c.tx[0]], - [16,17,18, - -1,-1, 20, - 19, 20]); - }); - - -// * case 3) -// * 0-1-2---3-4 -// * \ \ -// * C1 C2-C2b(TX=C1.TX) -// * \ -// * C2c(TX=C2.TX) -// -// (orphan)-C3* -// -> returns error - - var case3 = { - hash: '0000000000000000000000000000000000000000000000000000000000000005', - tx: case2.tx, - time: 1296690099, - previousblockhash: '666', - }; - - describe('reorg, case 3)', function() { - it('case 3). Should return an error', function(done1){ - s.sync.storeTipBlock(case3, function(err) { - assert(err, 'should return error' + err); - return done1(); - }); - }); - //shoudnt change anything - checkBlocks([b[0], b[1], b[2], - b[3],b[4],case2.hash, case2b.hash, - case1.hash, case2c.hash], - [16,17,18, - -1,-1,-1, -1, - 19, 20 - ]); - checkTxs( - [t[0], t[1], t[2], - t[3],t[4], case2.tx[0], - case1.tx, case2c.tx[0]], - [16,17,18, - -1,-1, 20, - 19, 20]); - }); - - var p2p = { - hash: '0000000000000000000000000000000000000000000000000000000000000006', - tx: ['f6c2901f39fd07f2f2e503183d76f73ecc1aee9ac9216fde58e867bc29ce674e'], - time: 1296690099, - previousblockhash: '111', - }; - - describe('p2p sync. no reorgs', function() { - it('Should return an error', function(done1){ - s.sync.storeTipBlock(p2p, false, function(err) { - assert(!err, 'shouldnt return error' + err); - return done1(); - }); - it('Block should be stored', function(done1){ - s.sync.bDb.has(p2p.hash, function(err,is) { - assert(!err); - assert(is); - return done1(); - }); - }); - //shoudnt change anything - checkBlocks([b[0], b[1], b[2], - b[3],b[4],case2.hash, case2b.hash, - case1.hash, case2c.hash, - p2p.hash], - [16,17,18, - -1,-1,-1, -1, - 19, 20, - -1 - ]); - }); - it('next Block should be stored', function(done1){ - s.sync.bDb.getNext(p2p.hash, function(err,v) { - assert(!err); - assert.equal(v,p2p.nextblockhash); - return done1(); - }); - }); - it('next Block should be stored', function(done1){ - s.sync.bDb.getNext(p2p.previousblockhash, function(err,v) { - assert(!err); - assert.equal(v,p2p.hash); - return done1(); - }); - }); - }); -}); - - diff --git a/test/integration/addr.js b/test/integration/addr.js deleted file mode 100644 index 70d80fd..0000000 --- a/test/integration/addr.js +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var assert = require('assert'), - fs = require('fs'), - Address = require('../../app/models/Address'), - TransactionDb = require('../../lib/TransactionDb').default(), - 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; - - var l =addrValid.length; - var i =0; - addrValid.forEach(function(v) { - TransactionDb.deleteCacheForAddress(v.addr, function() { - if (++i===l) return c(); - }); - }); - }); - - addrValid.forEach(function(v) { - if (v.disabled) { - console.log(v.addr + ' => disabled in JSON'); - } else { - it('Address info 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); - - if (v.unconfirmedTxApperances) - a.unconfirmedTxApperances.should.equal(v.unconfirmedTxApperances || 0, 'unconfirmedTxApperances'); - if (v.unconfirmedBalanceSat) - 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); - - if (v.transactions) { - - v.transactions.forEach(function(tx) { - a.transactions.should.include(tx); - }); - } - 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(); - },{txLimit:0}); - }); - } - }); - -}); - -//tested against https://api.biteasy.com/testnet/v1/addresses/2N1pLkosf6o8Ciqs573iwwgVpuFS6NbNKx5/unspent-outputs?per_page=40 -describe('Address unspent', 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 unspent for: ' + v.addr, function(done) { - this.timeout(2000); - var a = new Address(v.addr, txDb); - a.update(function(err) { - if (err) done(err); - assert.equal(v.addr, a.addrStr); - if (v.length) a.unspent.length.should.equal(v.length, 'Unspent count'); - if (v.tx0id) { - var x=a.unspent.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(); - }, {onlyUnspent:1}); - }); - it('Address unspent (cached) for: ' + v.addr, function(done) { - this.timeout(2000); - var a = new Address(v.addr, txDb); - a.update(function(err) { - if (err) done(err); - assert.equal(v.addr, a.addrStr); - if (v.length) a.unspent.length.should.equal(v.length, 'Unspent count'); - if (v.tx0id) { - var x=a.unspent.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(); - }, {onlyUnspent:1}); - }); - } - }); -}); diff --git a/test/integration/addr.json b/test/integration/addr.json deleted file mode 100644 index c973ce6..0000000 --- a/test/integration/addr.json +++ /dev/null @@ -1,138 +0,0 @@ -[ - { - "addr": "mm8CDNJnk8PtQPEtTns2ah5nmxN63ENHtY", - "balance": 1.4, - "txApperances": 3 - }, - - { - "addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS", - "balance": 0, - "totalReceived": 50, - "totalSent": 50.0, - "txApperances": 2 - }, - { - "addr": "muyg1K5WsHkfMVCkUXU2y7Xp5ZD6RGzCeH", - "balance": 0.38571339, - "totalReceived": 0.38571339, - "totalSent": 0, - "txApperances": 1 - }, - { - "addr": "mhPEfAmeKVwT7arwMYbhwnL2TfwuWbP4r4", - "totalReceived": 1069, - "txApperances": 13, - "balance": 1065, - "totalSent": 4 - }, - { - "addr": "n47CfqnKWdNwqY1UWxTmNJAqYutFxdH3zY", - "balance": 0, - "totalReceived":26.4245, - "totalSent": 26.4245, - "txApperances": 4 - }, - { - "addr": "mzSyyXgofoBxpr6gYcU3cV345G8hJpixRd", - "balance": 0, - "totalReceived":3.9775, - "totalSent": 3.9775, - "txApperances": 2 - }, - { - "addr": "mgqvRGJMwR9JU5VhJ3x9uX9MTkzTsmmDgQ", - "txApperances": 27, - "balance": 0, - "totalReceived": 54.81284116 - }, - { - "disabled": 1, - "addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29", - "balance": 1363.14677867, - "totalReceived": 1363.14677867, - "totalSent": 0, - "txApperances": 7947, - "unconfirmedTxApperances": 5, - "unconfirmedBalanceSat": 149174913 - }, - { - "addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H", - "txApperances": 7166, - "balance": 6513, - "totalReceived": 357130.17644359, - "totalSent": 350617.17644359 - }, - { - "addr": "mgKY35SXqxFpcKK3Dq9mW9919N7wYXvcFM", - "txApperances": 2, - "balance": 0, - "totalReceived": 0.01979459, - "totalSent": 0, - "transactions": [ "91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5" ] - }, - { - "addr": "mmvP3mTe53qxHdPqXEvdu8WdC7GfQ2vmx5", - "balance": 5524.61806422, - "totalReceived": 12157.65075053, - "totalSent": 6633.03268631, - "txApperances": 443, - "transactions": [ - "91800d80bb4c69b238c9bfd94eb5155ab821e6b25cae5c79903d12853bbb4ed5", - "f6e80d4fd1a2377406856c67d0cee5ac7e5120993ff97e617ca9aac33b4c6b1e", - "bc27f31caae86750b126d9b09e969362b85b7c15f41421387d682064544bf7e7", - "2cd6a1cb26880276fbc9851396f1bd8081cb2b9107ff6921e8fd65ed2df3df79", - "8bea41f573bccb7b648bc0b1bbfeba8a96da05b1d819ff4a33d39fbcd334ecfd", - "cb0d55c37acc57f759255193673e13858b5ab3d8fdfa7ee8b25f9964bdaa11e3", - "7b007aeace2299d27b6bb6c24d0a8040d6a87e4c2601216c34d226462b75f915", - "a9f40fbaecd2b28a05405e28b95566d7b3bd8ac38a2853debd72517f2994c6fc", - "4123255b7678e37c168b9e929927760bc5d9363b0c78ec61a7b4a78b2a07adab", - "cb3760529c2684c32047a2fddf0e2534c9241e5d72011aac4a8982e0c7b46df3", - "e8d00d8cc744381233dbc95e2d657345084dfb6df785b81285183f4c89b678d4", - "7a748364255c5b64979d9d3da35ea0fbef0114e0d7f96fccd5bea76f6d19f06b", - "d0b7e087040f67ef9bd9f21ccf53d1b5410400351d949cabf127caf28a6e7add", - "209f97873265652b83922921148cad92d7e048c6822e4864e984753e04181470", - "3a4af7755d3061ecced2f3707c2623534104f08aa73a52ca243d7ddecf5fe86d", - "4a4b5c8d464a77814ed35a37e2a28e821d467a803761427c057f67823309b725", - "d85f5265618fb694c3ea3ca6f73eba93df8a644bc1c7286cec2fbc2fbf7d895e", - "0d2c778ed9976b52792c941cac126bda37d3b1453082022d5e36ac401be3b249", - "daf03d666047ca0b5340b4a0027f8562b7c5bac87dca3727093b5393176a541a", - "a0dc03a870e589ea51e3d3a8aed0d34f4f1ae6844acad26dae48fe523b26e764", - "3df1a50e2e5d8525f04bd21a66bad824364a975449fa24fd5c2537d0f713919b", - "7bc26c1f3b4ab5ca57677593d28d13bff468a658f4d5efc379c1612554cf668e", - "ded4cbc9c52fd5599b6a93f89a79cde9aeb5a7f8f56732bb67ae9554325b3666", - "91224a219196a3f6e6f40ad2137b13fe54109e57aaed7527ea34aa903e6b8313", - "ee899a182bbb75e98ef14d83489e631dd66a8c5059dc8255692dd8ca9efba01f", - "0a61590c7548bd4f6a0df1575b268057e5e3e295a44eaeeb1dfbd01332c585ed", - "d56c22950ad2924f404b5b0baa6e49b0df1aaf09d1947842aed9d0178958eb9d", - "c6b5368c5a256141894972fbd02377b3894aa0df7c35fab5e0eca90de064fdc1", - "158e1f9c3f8ec44e88052cadef74e8eb99fbad5697d0b005ba48c933f7d96816", - "7f6191c0f4e3040901ef0d5d6e76af4f16423061ca1347524c86205e35d904d9", - "2c2e20f976b98a0ca76c57eca3653699b60c1bd9503cc9cc2fb755164a679a26", - "59bc81733ff0eaf2b106a70a655e22d2cdeff80ada27b937693993bf0c22e9ea", - "7da38b66fb5e8582c8be85abecfd744a6de89e738dd5f3aaa0270b218ec424eb", - "393d51119cdfbf0a308c0bbde2d4c63546c0961022bad1503c4bbaed0638c837", - "4518868741817ae6757fd98de27693b51fad100e89e5206b9bbf798aeebb804c", - "c58bce14de1e3016504babd8bbe8175207d75074134a2548a71743fa3e56c58d", - "6e69ec4a97515a8fd424f123a5fc1fdfd3c3adcd741292cbc09c09a2cc433bea", - "0e15f2498362050e5ceb6157d0fbf820fdcaf936e447207d433ee7701d7b99c2", - "a3789e113041db907a1217ddb5c3aaf0eff905cc3d913e68d977e1ab4d19acea", - "80b460922faf0ad1e8b8a55533654c9a9f3039bfff0fff2bcf8536b8adf95939" - ] - }, - { - "addr": "mtA6woo1wjCeu1dLkWgpSD3tRnRfrHt3FL", - "balance": 349.845, - "totalReceived": 349.845, - "totalSent": 0, - "txApperances": 13, - "transactions": [ - "794eafc0ad68a3576034eb137d7d20d3bdf1777ecf27e0e20e96e1adcfc66659", - "0130721f29f50b773858c3c9081678bdddebcd18078c5fa2436d979b54ed5cef", - "fb1024947b48d90255aedd3f0f1df3673a7e98d06346bb2ac89b116aa19c5db4" - ] - } - -] - - diff --git a/test/integration/addrCache.js b/test/integration/addrCache.js deleted file mode 100644 index 815e76e..0000000 --- a/test/integration/addrCache.js +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var assert = require('assert'), - fs = require('fs'), - Address = require('../../app/models/Address'), - TransactionDb = require('../../lib/TransactionDb').default(), - 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 cache ', function() { - this.timeout(5000); - - before(function(c) { - txDb = TransactionDb; - txDb.deleteCacheForAddress('muAt5RRqDarPFCe6qDXGZc54xJjXYUyepG',function(){ - txDb.deleteCacheForAddress('mt2AzeCorSf7yFckj19HFiXJgh9aNyc4h3',function(){ - txDb.deleteCacheForAddress('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk',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('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk', txDb); - a.update(function(err) { - if (err) done(err); - a.balance.should.equal(0.23, 'balance'); - a.totalReceived.should.equal(0.23, 'totalReceived'); - a.txApperances.should.equal(1, 'txApperances'); - return done(); - }); - }); - - it('cache case 2 w cache', function(done) { - var a = new Address('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk', txDb); - a.update(function(err) { - if (err) done(err); - a.balance.should.equal(0.23, 'balance'); - a.totalReceived.should.equal(0.23, 'totalReceived'); - a.txApperances.should.equal(1, 'txApperances'); - return done(); - }); - }); - - it('cache case 2 unspent wo cache', function(done) { - txDb.deleteCacheForAddress('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk',function() { - var a = new Address('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk', txDb); - a.update(function(err) { - if (err) done(err); - a.unspent.length.should.equal(1); - a.unspent[0].scriptPubKey.should.equal('a914a1d5be9f72224b5e83d00d7f5b9b674d456c573f87'); - a.unspent[0].confirmations.should.be.above(15000); - a.unspent[0].confirmationsFromCache.should.equal(false); - a.update(function(err) { - a.balance.should.equal(0.23, 'balance'); - a.totalReceived.should.equal(0.23, 'totalReceived'); - a.txApperances.should.equal(1, 'txApperances'); - return done(); - }); - }, {onlyUnspent:1}); - }); - }); - - it('cache case 2 unspent w cache', function(done) { - - var a = new Address('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk', txDb); - a.update(function(err) { - if (err) done(err); - a.unspent.length.should.equal(1); - a.unspent[0].confirmationsFromCache.should.equal(true); - a.unspent[0].confirmations.should.equal(6); - a.unspent[0].scriptPubKey.should.equal('a914a1d5be9f72224b5e83d00d7f5b9b674d456c573f87'); - a.update(function(err) { - a.balance.should.equal(0.23, 'balance'); - a.totalReceived.should.equal(0.23, 'totalReceived'); - a.txApperances.should.equal(1, 'txApperances'); - return done(); - }); - - }, {onlyUnspent:1}); - }); - - - - it('cache case 3 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 4 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(); - },{txLimit:0}); - }); - it('cache case 4 w ignore 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(); - },{txLimit:0, ignoreCache:1}); - }); - - it('cache case 5 unspent w cache', function(done) { - var a = new Address('2NBuTjjZrURxLaMyPUu2sJwNrtpt7GtPX2p', txDb); - a.update(function(err) { - if (err) done(err); - a.unspent.length.should.equal(1); - a.unspent[0].confirmationsFromCache.should.equal(true); - a.unspent[0].confirmations.should.equal(6); - return done(); - }, {onlyUnspent:1}); - }); - - it('cache fix broken cases', function(done) { - txDb._db.put('txa2-2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk-9998599199253-16c0287dbea7e323431caff7f7e490da6de66530717f86f8dae9549b3355301a-0', '23000000:1399232338:0:a914a1d5be9f72224b5e83d00d7f5b9b674d456c573f87', function(){ - var a = new Address('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk', txDb); - a.update(function(err) { - if (err) done(err); - a.balance.should.equal(0.23, 'balance'); - a.totalReceived.should.equal(0.23, 'totalReceived'); - a.txApperances.should.equal(1, 'txApperances'); - a.transactions.length.should.equal(1); - a.transactions[0].should.equal('16c0287dbea7e323431caff7f7e490da6de66530717f86f8dae9549b3355301a'); - return done(); - }); - }); - }); - it('cache fix broken cases 2)', function(done) { - txDb._db.put('txa2-2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk-9998599199253-16c0287dbea7e323431caff7f7e490da6de66530717f86f8dae9549b3355301a-0', '23000000:1399232338:0:a914a1d5be9f72224b5e83d00d7f5b9b674d456c573f87', function(){ - var a = new Address('2N7zvqQTUYFfhYvFs1NEzureMLvhwk5FSsk', txDb); - a.update(function(err) { - if (err) done(err); - a.unspent.length.should.equal(1); - a.unspent[0].confirmationsFromCache.should.equal(false); - a.unspent[0].confirmations.should.above(6); - a.unspent[0].scriptPubKey.should.equal('a914a1d5be9f72224b5e83d00d7f5b9b674d456c573f87'); - a.update(function(err) { - if (err) done(err); - a.unspent.length.should.equal(1); - a.unspent[0].confirmationsFromCache.should.equal(true); - a.unspent[0].confirmations.should.equal(6); - a.unspent[0].scriptPubKey.should.equal('a914a1d5be9f72224b5e83d00d7f5b9b674d456c573f87'); - return done(); - }, {onlyUnspent:1}); - }, {onlyUnspent:1}); - }); - }); - - -}); - - diff --git a/test/integration/block.js b/test/integration/block.js deleted file mode 100644 index 0d6e5e4..0000000 --- a/test/integration/block.js +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - - -var TESTING_BLOCK = '000000000185678d3d7ecc9962c96418174431f93fe20bf216d5565272423f74'; - -var -assert = require('assert'), - // config = require('../../config/config'), - BlockDb = require('../../lib/BlockDb').default(); - -var bDb; - -describe('BlockDb fromHashWithInfo', function() { - - before(function(c) { - bDb = BlockDb; - return c(); - }); - - it('should poll block\'s info from bitcoind', function(done) { - bDb.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { - if (err) done(err); - assert.equal(b2.hash, TESTING_BLOCK, 'hash'); - assert.equal(b2.info.hash, TESTING_BLOCK, 'info.hash'); - assert.equal(b2.info.height, 71619); - assert.equal(b2.info.nonce, 3960980741); - assert.equal(b2.info.bits, '1c018c14'); - assert.equal(b2.info.merkleroot, '9a326cb524aa2e5bc926b8c1f6de5b01257929ee02158054b55aae93a55ec9dd'); - assert.equal(b2.info.nextblockhash, '000000000121941b3b10d76fbe67b35993df91eb3398e9153e140b4f6213cb84'); - done(); - }); - }); - it('return true in has', function(done) { - bDb.has(TESTING_BLOCK, function(err, has) { - assert.equal(has, true); - done(); - }); - }); -}); diff --git a/test/integration/blockExtractor.js b/test/integration/blockExtractor.js deleted file mode 100644 index 3f5f360..0000000 --- a/test/integration/blockExtractor.js +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - - - -var assert = require('assert'), - config = require('../../config/config'), - BlockExtractor = require('../../lib/BlockExtractor'), - networks = require('bitcore/networks'), - util = require('bitcore/util/util'); - -var should = require('chai'); -//var txItemsValid = JSON.parse(fs.readFileSync('test/model/txitems.json')); - -describe('BlockExtractor', function(){ - - var be = new BlockExtractor(config.bitcoind.dataDir, config.network); - - var network = config.network === 'testnet' ? networks.testnet: networks.livenet; - - it('should glob block files ', function(done) { - assert(be.files.length>0); - done(); - }); - - var lastTs; - - it('should read genesis block ', function(done) { - be.getNextBlock(function(err,b) { - assert(!err); - var genesisHashReversed = new Buffer(32); - network.genesisBlock.hash.copy(genesisHashReversed); - var genesis = util.formatHashFull(network.genesisBlock.hash); - - assert.equal(util.formatHashFull(b.hash),genesis); - assert.equal(b.nounce,network.genesisBlock.nounce); - assert.equal(b.timestamp,network.genesisBlock.timestamp); - assert.equal(b.merkle_root.toString('hex'),network.genesisBlock.merkle_root.toString('hex')); - - lastTs = b.timestamp; - done(); - }); - }); - - it('should read next '+config.network+' block ', function(done) { - be.getNextBlock(function(err,b) { - assert(!err); - // 2nd block of testnet3 - util.formatHashFull(b.hash).should.equal('00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206'); - assert(b.timestamp > lastTs, 'timestamp > genesis_ts'); - done(); - }); - }); - - it.skip('should read 100000 blocks with no error ', function(done) { - - var i=0; - while(i++<100000) { - be.getNextBlock(function(err,b) { - assert(!err,err); - assert(lastTs < b.timestamp, 'genesisTS < b.timestamp: ' + lastTs + '<' + b.timestamp + ":" + i); - if(i % 1000 === 1) process.stdout.write('.'); - if(i === 100000) done(); - }); - } - }); - - - -}); - - - diff --git a/test/integration/blocklist.js b/test/integration/blocklist.js deleted file mode 100644 index 19b104a..0000000 --- a/test/integration/blocklist.js +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var TESTING_BLOCK0 = '00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206'; -var TESTING_BLOCK1 = '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943'; -var START_TS = 1; -var END_TS = '1296688928~'; // 2/2/2011 23:23PM - -var assert = require('assert'), - BlockDb = require('../../lib/BlockDb').default(); - -var bDb; - -describe('BlockDb getBlocksByDate', function(){ - - - before(function(c) { - bDb = BlockDb; - return c(); - }); - - it('Get Hash by Date', function(done) { - - bDb.getBlocksByDate(START_TS, END_TS, 2, function(err, list) { - if (err) done(err); - assert(list, 'returns list'); - assert.equal(list.length,2, 'list has 2 items'); - assert.equal(list[1].hash, TESTING_BLOCK0); - assert.equal(list[0].hash, TESTING_BLOCK1); - done(); - }); - }); -}); - diff --git a/test/integration/messages.js b/test/integration/messages.js deleted file mode 100644 index d51ccba..0000000 --- a/test/integration/messages.js +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var assert = require('assert'), - config = require('../../config/config'), - messages = require('../../app/controllers/messages'), - correctMessage = 'test2', - correctAddress, - correctSignature; - -if(config.network === 'livenet') { - correctAddress = '16Q7eRty2LrpAWvP3VTtaXXCMZj2v4xm57', - correctSignature = 'HERpcxkyOezkBPPwvUUAaxYXR/9X/8eyVjp8WKGYl7Aw8' - + 'pMsiMXDWXf8G1t/SOUEWy94I+KA/SrBKYs2LfIHA0Q='; -} else { - correctAddress = 'mhtJo5nZLcreM5Arrf8EDABpCevp2MfmCW', - correctSignature = 'G/y2UhjZ4qBPLQGmOhl/4p/EIwTHIO1iq95kPxDk9RjYr' - + '1JKL6dsCSuhXat7VLTGwAM3PdgRh/jwGxi6x6dNeSE='; -} - -function createMockReq(body) { - // create a simplified mock of express' request object, suitable for the - // needs of test cases in this file - return { - body: body, - param: function(name) { - return this.body[name]; - } - }; -} - -describe('messages.verify', function() { - - it('should return true with correct message', function(done) { - var mockReq = createMockReq({ - address: correctAddress, - signature: correctSignature, - message: correctMessage - }); - var mockRes = { - json: function(data) { - assert.deepEqual(data, { - result: true, - }); - done(); - } - }; - messages.verify(mockReq, mockRes); - }); - - it('should return false with incorrect message', function(done) { - var mockReq = createMockReq({ - address: correctAddress, - signature: correctSignature, - message: 'NOPE' - }); - var mockRes = { - json: function(data) { - assert.deepEqual(data, { - result: false, - }); - done(); - } - }; - - messages.verify(mockReq, mockRes); - }); - - it('should return error with incorrect parameters', function(done) { - var mockReq = createMockReq({ - address: correctAddress, - message: correctMessage - }); - var mockRes = { - status: function(code) { - assert.equal(code, 400); - return this; - }, - send: function(data) { - assert.ok(data.match(/^Missing parameters/), - "Match not found, got '" + data + "' instead") - done(); - } - }; - messages.verify(mockReq, mockRes); - }); - -}); diff --git a/test/integration/nodecheck.js b/test/integration/nodecheck.js deleted file mode 100644 index 2e2973c..0000000 --- a/test/integration/nodecheck.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -var BlockDb = require('../../lib/BlockDb').default(); -var height_needed = 180000; -var bDb = BlockDb; - -var expect = require('chai').expect; - -describe('Node check', function() { - it('should contain block ' + height_needed, function(done) { - bDb.blockIndex(height_needed, function(err, b) { - expect(err).to.equal(null); - expect(b).to.not.equal(null); - done(); - }); - }); -}); diff --git a/test/integration/spent.json b/test/integration/spent.json deleted file mode 100644 index 351661b..0000000 --- a/test/integration/spent.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237": [ - { - "txid": "bcd8da8ee847da377f8aaca92502c05e5f914c6a2452753146013b0e642a25a0", - "n": 0 - }, - { - "txid": "deb7bddc67e936ae49b97a97885d29e60afc6f6784f6d871f2904614a67250f5", - "n": 0 - } - ], - "b633a6249d4a2bc123e7f8a151cae2d4afd17aa94840009f8697270c7818ceee": [ - { - "txid": "c0c46d6be0183f52c88afe2d649800ecdaa7594ee390c77bafbd06322e6c823d", - "n": 11 - }, - { - "txid": "d60e980419c5a8abd629fdea5032d561678b62e23b3fdba62b42f410c5a29560", - "n": 1 - } - ], - "ca2f42e44455b8a84434de139efea1fe2c7d71414a8939e0a20f518849085c3b": [ - { - "txid": "aa21822f1a69bc54e5a4ab60b25c09503702a821379fd2dfbb696b8ada4ce5b9", - "n": 0 - }, - { - "txid": "a33bd24a47ab6f23758ed09e05716f809614f2e280e5a05a317ec6d839e81225", - "n": 1 - } - ] -} diff --git a/test/integration/status.js b/test/integration/status.js deleted file mode 100644 index d912fa0..0000000 --- a/test/integration/status.js +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var assert = require('assert'), - Status = require('../../app/models/Status'); - -describe('Status', function(){ - - it('getInfo', function(done) { - var d = new Status(); - - d.getInfo(function(err) { - if (err) done(err); - assert.equal('number', typeof d.info.difficulty); - done(); - }); - }); - - it('getDifficulty', function(done) { - var d = new Status(); - - d.getDifficulty(function(err) { - if (err) done(err); - assert.equal('number', typeof d.difficulty); - done(); - }); - }); - - it('getLastBlockHash', function(done) { - var d = new Status(); - - d.getLastBlockHash(function(err) { - if (err) done(err); - assert.equal('string', typeof d.lastblockhash); - done(); - }); - }); - - -}); - diff --git a/test/integration/txitems.json b/test/integration/txitems.json deleted file mode 100644 index 283e873..0000000 --- a/test/integration/txitems.json +++ /dev/null @@ -1,62 +0,0 @@ -[ - { - "disabled": 1, - "txid": "75c5ffe6dc2eb0f6bd011a08c041ef115380ccd637d859b379506a0dca4c26fc" - }, - { - "txid": "21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237", - "toRm": [ - "txs-86a03cac7d87f596008c6d5a8d3fd8b88842932ea6f0337673eda16f6b472f7f-0", - "txs-bcd8da8ee847da377f8aaca92502c05e5f914c6a2452753146013b0e642a25a0-0" - ], - "items": [ - { - "addr": "mzjLe62faUqCSjkwQkwPAL5nYyR8K132fA", - "value_sat": 134574000, - "index": 0 - }, - { - "addr": "n28wb1cRGxPtfmsenYKFfsvnZ6kRapx3jF", - "value_sat": 31600000, - "index": 1 - } - ] - }, - { - "txid": "b633a6249d4a2bc123e7f8a151cae2d4afd17aa94840009f8697270c7818ceee", - "toRm": [ - "txs-01621403689cb4a95699a3dbae029d7031c5667678ef14e2054793954fb27917-0" - ], - "items": [ - { - "addr": "mhfQJUSissP6nLM5pz6DxHfctukrrLct2T", - "value_sat": 19300000, - "index": 0 - }, - { - "addr": "mzcDhbL877ES3MGftWnc3EuTSXs3WXDDML", - "value_sat": 21440667, - "index": 1 - } - ] - }, - { - "txid": "ca2f42e44455b8a84434de139efea1fe2c7d71414a8939e0a20f518849085c3b", - "toRm": [ - "txs-2d7b680fb06e4d7eeb65ca49ac7522276586e0090b7fe662fc708129429c5e6a-0" - ], - "items": [ - { - "addr": "mhqyL1nDQDo1WLH9qH8sjRjx2WwrnmAaXE", - "value_sat": 1327746, - "index": 0 - }, - { - "addr": "mkGrySSnxcqRbtPCisApj3zXCQVmUUWbf1", - "value_sat": 1049948, - "index": 1 - } - ] - } - -] diff --git a/test/integration/txs.js b/test/integration/txs.js deleted file mode 100644 index 0fc18f9..0000000 --- a/test/integration/txs.js +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var _ = require('lodash'); -var async = require('async'); -var assert = require('assert'); -var fs = require('fs'); -var Address = require('../../app/models/Address'); -var addresses = require('../../app/controllers/addresses'); -var TransactionDb = require('../../lib/TransactionDb').default(); -var fixture = JSON.parse(fs.readFileSync('test/integration/txs.json')); -var should = require('chai'); -var sinon = require('sinon'); - -var txDb; -describe('Transactions for multiple addresses', function() { - this.timeout(5000); - - var req, res; - before(function(c) { - txDb = TransactionDb; - - var i = 0; - _.each(_.flatten(_.pluck(fixture, 'addrs')), function(addr) { - TransactionDb.deleteCacheForAddress(addr, function() { - if (++i === fixture.length) return c(); - }); - }); - }); - - beforeEach(function(c) { - req = {}; - res = {}; - return c(); - }); - - describe('Transactions from multiple addresses', function () { - _.each(fixture, function (f) { - it(f.test, function (done) { - var checkResult = function(txs) { - var paginated = !_.isUndefined(f.from) || !_.isUndefined(f.to); - txs.should.exist; - if (paginated) { - txs.totalItems.should.equal(f.totalTransactions); - txs.items.length.should.equal(f.returnedTransactions); - if (f.transactions) { - JSON.stringify(_.pluck(txs.items, 'txid')).should.equal(JSON.stringify(f.transactions)); - } - } else { - txs.should.be.instanceof(Array); - txs.length.should.equal(f.returnedTransactions); - } - done(); - }; - - res.jsonp = checkResult; - req.param = sinon.stub(); - req.param.withArgs('addrs').returns(f.addrs.join(',')); - req.param.withArgs('from').returns(f.from); - req.param.withArgs('to').returns(f.to); - - addresses.multitxs(req, res); - }); - }); - }); -}); diff --git a/test/integration/txs.json b/test/integration/txs.json deleted file mode 100644 index 88abb2b..0000000 --- a/test/integration/txs.json +++ /dev/null @@ -1,32 +0,0 @@ -[{ - "test": "should return non-paginated txs for single address", - "addrs": ["mtA6woo1wjCeu1dLkWgpSD3tRnRfrHt3FL"], - "totalTransactions": 13, - "returnedTransactions": 13 -},{ - "test": "should return paginated txs for single address", - "addrs": ["mtA6woo1wjCeu1dLkWgpSD3tRnRfrHt3FL"], - "totalTransactions": 13, - "from": 8, - "to": 12, - "returnedTransactions": 4 -},{ - "test": "should return non-paginated txs for multiple addresses", - "addrs": ["mqtYvjsUg59XpngBAYjFF51Xauc28a6Ckd","myDZmGN9euuRhM1mniSaXhQjNdqFmUzUkj"], - "totalTransactions": 4, - "returnedTransactions": 4 -},{ - "test": "should return paginated txs for multiple addresses", - "addrs": ["mqtYvjsUg59XpngBAYjFF51Xauc28a6Ckd","myDZmGN9euuRhM1mniSaXhQjNdqFmUzUkj", "n2NbTWCuUyTvpA2YKTpVD4SmCouFLcm8rS"], - "totalTransactions": 6, - "from": 2, - "to": 6, - "returnedTransactions": 4, - "transactions": [ - "3e81723d069b12983b2ef694c9782d32fca26cc978de744acbc32c3d3496e915", - "b701b0680bc2b6f8b58f13d035a754486ecefd2438e3495cd8f395ab7f5e7ba9", - "80fb4fd2a6e5e795a4f30aebeda49424e7ed4d3630b128efb946aa964e0bc9c0", - "855e881892d7cd4a8fa81dbd8f6e9d142d02bffc10ffbe5428036ee55c3e3e0f" - ] -} -] diff --git a/test/integration/utxo.json b/test/integration/utxo.json deleted file mode 100644 index f45dfb6..0000000 --- a/test/integration/utxo.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "addr": "muyg1K5WsHkfMVCkUXU2y7Xp5ZD6RGzCeH", - "length": 1, - "tx0id": "eeabc70063d3f266e190e8735bc4599c811d3a79d138da1364e88502069b029c", - "tx0scriptPubKey": "76a9149e9f6515c70db535abdbbc983c7d8d1bff6c20cd88ac", - "tx0amount": 0.38571339 - }, - { - "addr": "2N1pLkosf6o8Ciqs573iwwgVpuFS6NbNKx5", - "length": 13, - "tx0id": "b9cc61b55814a0f972788e9025db1013157f83716e08239026a156efe892a05c", - "tx0scriptPubKey": "a9145e0461e38796367580305e3615fc1b70e4c3307687", - "tx0amount": 0.001 - } -] diff --git a/test/lib/PeerSync.js b/test/lib/PeerSync.js deleted file mode 100644 index 9c29b11..0000000 --- a/test/lib/PeerSync.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; -var chai = require('chai'), - expect = chai.expect, - sinon = require('sinon'); - -var PeerSync = require('../../lib/PeerSync.js'); -describe('PeerSync', function() { - var ps; - - beforeEach(function(done) { - ps = new PeerSync(); - done(); - }); - afterEach(function() { - ps.close(); - }); - - - describe('#handleInv()', function() { - var inv_info = { - message: { - invs: [] - }, - conn: { - sendGetData: sinon.spy() - } - }; - it('should return with no errors', function() { - expect(function() { - ps.handleInv(inv_info); - }).not.to.throw(Error); - }); - it('should call sendGetData', function() { - ps.handleInv(inv_info); - expect(inv_info.conn.sendGetData.calledTwice).to.be.ok; - }); - }); - - describe('#run()', function() { - it('should setup peerman', function() { - var startSpy = sinon.spy(ps.peerman, 'start'); - var onSpy = sinon.spy(ps.peerman, 'on'); - ps.run(); - - expect(startSpy.called).to.be.ok; - expect(onSpy.called).to.be.ok; - }); - }); -}); diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index a9caeb4..0000000 --- a/test/mocha.opts +++ /dev/null @@ -1,5 +0,0 @@ ---require should --R spec ---ui bdd ---recursive - diff --git a/test/test.CredentialStore.js b/test/test.CredentialStore.js deleted file mode 100644 index 608453d..0000000 --- a/test/test.CredentialStore.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var assert = require('assert'); -var sinon = require('sinon'); -var should = chai.should; -var expect = chai.expect; - -describe('credentialstore test', function() { - - var globalConfig = require('../config/config'); - var leveldb_stub = sinon.stub(); - leveldb_stub.post = sinon.stub(); - leveldb_stub.get = sinon.stub(); - var plugin = require('../plugins/credentialstore'); - var express_mock = null; - var request = null; - var response = null; - - beforeEach(function() { - - express_mock = sinon.stub(); - express_mock.post = sinon.stub(); - express_mock.get = sinon.stub(); - - plugin.init(express_mock, {db: leveldb_stub}); - - request = sinon.stub(); - request.on = sinon.stub(); - request.param = sinon.stub(); - response = sinon.stub(); - response.send = sinon.stub(); - response.status = sinon.stub(); - response.json = sinon.stub(); - response.end = sinon.stub(); - }); - - it('initializes correctly', function() { - assert(plugin.db === leveldb_stub); - assert(express_mock.post.calledWith( - globalConfig.apiPrefix + '/credentials', plugin.post - )); - assert(express_mock.get.calledWith( - globalConfig.apiPrefix + '/credentials/:username', plugin.get - )); - }); - - it('writes a message correctly', function() { - - var data = 'username=1&secret=2&record=3'; - request.on.onFirstCall().callsArgWith(1, data); - request.on.onFirstCall().returnsThis(); - request.on.onSecondCall().callsArg(1); - leveldb_stub.put = sinon.stub(); - - leveldb_stub.put.onFirstCall().callsArg(2); - response.json.returnsThis(); - - plugin.post(request, response); - - assert(leveldb_stub.put.firstCall.args[0] === 'credentials-store-12'); - assert(leveldb_stub.put.firstCall.args[1] === '3'); - assert(response.json.calledWith({success: true})); - }); - - it('retrieves a message correctly', function() { - - request.param.onFirstCall().returns('username'); - request.param.onSecondCall().returns('secret'); - - var returnValue = '!@#$%'; - leveldb_stub.get.onFirstCall().callsArgWith(1, null, returnValue); - response.send.returnsThis(); - - plugin.get(request, response); - - assert(leveldb_stub.get.firstCall.args[0] === 'credentials-store-usernamesecret'); - assert(response.send.calledWith(returnValue)); - assert(response.end.calledOnce); - }); - - it('fails with messages that are too long', function() { - - response.writeHead = sinon.stub(); - request.connection = {}; - request.connection.destroy = sinon.stub(); - var data = 'blob'; - for (var i = 0; i < 2048; i++) { - data += '----'; - } - request.on.onFirstCall().callsArgWith(1, data); - request.on.onFirstCall().returnsThis(); - response.writeHead.returnsThis(); - - plugin.post(request, response); - - assert(response.writeHead.calledWith(413, {'Content-Type': 'text/plain'})); - assert(response.end.calledOnce); - assert(request.connection.destroy.calledOnce); - }); -}); diff --git a/test/test.CurrencyRates.js b/test/test.CurrencyRates.js deleted file mode 100644 index ce22556..0000000 --- a/test/test.CurrencyRates.js +++ /dev/null @@ -1,265 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var assert = require('assert'); -var sinon = require('sinon'); -var should = chai.should; -var expect = chai.expect; - -var levelup = require('levelup'); -var memdown = require('memdown'); -var logger = require('../lib/logger').logger; -logger.transports.console.level = 'non'; - -var rates = require('../plugins/currencyrates'); - -var db; - -describe('Rates service', function() { - beforeEach(function() { - db = levelup(memdown); - }); - - describe('#getRate', function() { - beforeEach(function() { - rates.init({ - db: db, - }); - }); - it('should get rate with exact ts', function(done) { - db.batch([{ - type: 'put', - key: 'bitpay-USD-10', - value: 123.45 - }, ]); - rates._getRate('bitpay', 'USD', 10, function(err, res) { - expect(err).to.not.exist; - res.rate.should.equal(123.45); - done(); - }); - }); - it('should get rate with approximate ts', function(done) { - db.batch([{ - type: 'put', - key: 'bitpay-USD-10', - value: 123.45, - }, { - type: 'put', - key: 'bitpay-USD-20', - value: 200.00, - }]); - rates._getRate('bitpay', 'USD', 25, function(err, res) { - res.rate.should.equal(200.00); - done(); - }); - }); - it('should return null when no rate found', function(done) { - db.batch([{ - type: 'put', - key: 'bitpay-USD-20', - value: 123.45, - }, { - type: 'put', - key: 'bitpay-USD-30', - value: 200.00, - }]); - rates._getRate('bitpay', 'USD', 10, function(err, res) { - expect(res.rate).to.be.null; - done(); - }); - }); - it('should get rate from specified source', function(done) { - db.batch([{ - type: 'put', - key: 'bitpay-USD-10', - value: 123.45, - }, { - type: 'put', - key: 'bitstamp-USD-10', - value: 200.00, - }]); - rates._getRate('bitpay', 'USD', 12, function(err, res) { - res.rate.should.equal(123.45); - done(); - }); - }); - it('should get rate for specified currency', function(done) { - db.batch([{ - type: 'put', - key: 'bitpay-USD-10', - value: 123.45, - }, { - type: 'put', - key: 'bitpay-EUR-10', - value: 200.00, - }]); - rates._getRate('bitpay', 'EUR', 12, function(err, res) { - res.rate.should.equal(200.00); - done(); - }); - }); - it('should get multiple rates', function(done) { - db.batch([{ - type: 'put', - key: 'bitpay-USD-10', - value: 100.00, - }, { - type: 'put', - key: 'bitpay-USD-20', - value: 200.00, - }, { - type: 'put', - key: 'bitstamp-USD-30', - value: 300.00, - }, { - type: 'put', - key: 'bitpay-USD-30', - value: 400.00, - }]); - rates._getRate('bitpay', 'USD', [10, 20, 35], function(err, res) { - expect(err).to.not.exist; - res.length.should.equal(3); - res[0].ts.should.equal(10); - res[1].ts.should.equal(20); - res[2].ts.should.equal(35); - res[0].rate.should.equal(100.00); - res[1].rate.should.equal(200.00); - res[2].rate.should.equal(400.00); - done(); - }); - }); - }); - - describe('#fetch', function() { - it('should fetch from all sources', function(done) { - var sources = []; - sources.push({ - id: 'id1', - url: 'http://dummy1', - parseFn: function(raw) { - return raw; - }, - }); - sources.push({ - id: 'id2', - url: 'http://dummy2', - parseFn: function(raw) { - return raw; - }, - }); - - var ds1 = [{ - code: 'USD', - rate: 123.45, - }, { - code: 'EUR', - rate: 200.00, - }]; - var ds2 = [{ - code: 'USD', - rate: 126.39, - }]; - - var request = sinon.stub(); - request.get = sinon.stub(); - request.get.withArgs({ - url: 'http://dummy1', - json: true - }).yields(null, null, ds1); - request.get.withArgs({ - url: 'http://dummy2', - json: true - }).yields(null, null, ds2); - - rates.init({ - db: db, - sources: sources, - request: request, - }); - - var clock = sinon.useFakeTimers(1400000000 * 1000); - - rates._fetch(function(err, res) { - clock.restore(); - - expect(err).to.not.exist; - - var result = []; - db.readStream() - .on('data', function(data) { - result.push(data); - }) - .on('close', function() { - result.length.should.equal(3); - result[0].key.should.equal('id1-EUR-1400000000'); - result[1].key.should.equal('id1-USD-1400000000'); - result[2].key.should.equal('id2-USD-1400000000'); - parseFloat(result[0].value).should.equal(200.00); - parseFloat(result[1].value).should.equal(123.45); - parseFloat(result[2].value).should.equal(126.39); - done(); - }); - }); - }); - - it('should not stop when failing to fetch source', function(done) { - var sources = []; - sources.push({ - id: 'id1', - url: 'http://dummy1', - parseFn: function(raw) { - return raw; - }, - }); - sources.push({ - id: 'id2', - url: 'http://dummy2', - parseFn: function(raw) { - return raw; - }, - }); - - var ds2 = [{ - code: 'USD', - rate: 126.39, - }]; - - var request = sinon.stub(); - request.get = sinon.stub(); - request.get.withArgs({ - url: 'http://dummy1', - json: true - }).yields('dummy error', null, null); - request.get.withArgs({ - url: 'http://dummy2', - json: true - }).yields(null, null, ds2); - - rates.init({ - db: db, - sources: sources, - request: request, - }); - - var clock = sinon.useFakeTimers(1400000000 * 1000); - - rates._fetch(function(err, res) { - clock.restore(); - - expect(err).to.not.exist; - - var result = []; - db.readStream() - .on('data', function(data) { - result.push(data); - }) - .on('close', function() { - result.length.should.equal(1); - result[0].key.should.equal('id2-USD-1400000000'); - parseFloat(result[0].value).should.equal(126.39); - done(); - }); - }); - }); - }); -}); diff --git a/test/test.EmailStore.js b/test/test.EmailStore.js deleted file mode 100644 index 16b5e2a..0000000 --- a/test/test.EmailStore.js +++ /dev/null @@ -1,683 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var assert = require('assert'); -var sinon = require('sinon'); -var crypto = require('crypto'); -var bitcore = require('bitcore'); -var logger = require('../lib/logger').logger; -var should = chai.should; -var expect = chai.expect; -var moment = require('moment'); - -logger.transports.console.level = 'non'; - -describe('emailstore test', function() { - - var globalConfig = require('../config/config'); - - // Mock components of plugin - var leveldb_stub = sinon.stub(); - leveldb_stub.put = sinon.stub(); - leveldb_stub.get = sinon.stub(); - leveldb_stub.del = sinon.stub(); - var email_stub = sinon.stub(); - email_stub.sendMail = sinon.stub().callsArg(1); - - var cryptoMock = { - randomBytes: sinon.stub() - }; - - var plugin = require('../plugins/emailstore'); - var express_mock = null; - var request = null; - var response = null; - - beforeEach(function() { - - plugin.init({ - db: leveldb_stub, - emailTransport: email_stub, - crypto: cryptoMock - }); - - request = sinon.stub(); - request.on = sinon.stub(); - request.param = sinon.stub(); - response = sinon.stub(); - response.send = sinon.stub(); - response.status = sinon.stub().returns({ - json: function() { - return { - end: function() { - } - } - } - }); - response.json = sinon.stub(); - response.end = sinon.stub(); - response.redirect = sinon.stub(); - }); - - it('initializes correctly', function() { - assert(plugin.db === leveldb_stub); - }); - - describe('database queries', function() { - - describe('exists', function() { - var fakeEmail = 'fake@email.com'; - var fakeEmailKey = 'email-to-passphrase-' + bitcore.util.twoSha256(fakeEmail).toString('hex'); - - beforeEach(function() { - leveldb_stub.get.reset(); - }); - - it('validates that an email is already registered', function(done) { - leveldb_stub.get.onFirstCall().callsArg(1); - - plugin.exists(fakeEmail, function(err, exists) { - leveldb_stub.get.firstCall.args[0].should.equal(fakeEmailKey); - exists.should.equal(true); - done(); - }); - }); - - it('returns false when an email doesn\'t exist', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, { - notFound: true - }); - - plugin.exists(fakeEmail, function(err, exists) { - leveldb_stub.get.firstCall.args[0].should.equal(fakeEmailKey); - exists.should.equal(false); - done(); - }); - }); - - it('returns an internal error if database query couldn\'t be made', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, 'error'); - plugin.exists(fakeEmail, function(err, exists) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - }); - - describe('passphrase', function() { - var fakeEmail = 'fake@email.com'; - var fakePassphrase = 'secretPassphrase123'; - - beforeEach(function() { - leveldb_stub.get.reset(); - leveldb_stub.put.reset(); - }); - - it('returns true if passphrase matches', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, null, fakePassphrase); - - plugin.checkPassphrase(fakeEmail, fakePassphrase, function(err, result) { - result.should.equal(true); - done(); - }); - }); - - it('returns false if passphrsase doesn\'t match', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, null, 'invalid passphrase'); - - plugin.checkPassphrase(fakeEmail, fakePassphrase, function(err, result) { - result.should.equal(false); - done(); - }); - }); - - it('returns an internal error if database query couldn\'t be made', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, 'error'); - - plugin.checkPassphrase(fakeEmail, fakePassphrase, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - - it('stores passphrase correctly', function(done) { - leveldb_stub.put.onFirstCall().callsArg(2); - - plugin.savePassphrase(fakeEmail, fakePassphrase, function(err) { - expect(err).to.equal(null); - done(); - }); - }); - - it('doesn\'t store the email in the key', function(done) { - leveldb_stub.put.onFirstCall().callsArg(2); - - plugin.savePassphrase(fakeEmail, fakePassphrase, function(err) { - leveldb_stub.put.firstCall.args[0].should.not.contain(fakeEmail); - done(); - }); - }); - - it('returns internal error on database error', function(done) { - leveldb_stub.put.onFirstCall().callsArgWith(2, 'error'); - - plugin.savePassphrase(fakeEmail, fakePassphrase, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - }); - - describe('saving encrypted data', function() { - var fakeEmail = 'fake@email.com'; - var fakeKey = 'nameForData'; - var fakeRecord = 'fakeRecord'; - var expectedKey = 'emailstore-' + bitcore.util.twoSha256(fakeEmail + '#' + fakeKey).toString('hex'); - - beforeEach(function() { - leveldb_stub.get.reset(); - leveldb_stub.put.reset(); - }); - - it('saves data under the expected key', function(done) { - leveldb_stub.put.onFirstCall().callsArgWith(2); - - plugin.saveEncryptedData(fakeEmail, fakeKey, fakeRecord, function(err) { - leveldb_stub.put.firstCall.args[0].should.equal(expectedKey); - done(); - }); - }); - - it('fails with INTERNAL_ERROR on database error', function(done) { - leveldb_stub.put.onFirstCall().callsArgWith(2, 'error'); - - plugin.saveEncryptedData(fakeEmail, fakeKey, fakeRecord, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - }); - - describe('creating verification secret', function() { - var fakeEmail = 'fake@email.com'; - var fakeRandom = 'fakerandom'; - var randomBytes = { - toString: function() { - return fakeRandom; - } - }; - - beforeEach(function() { - leveldb_stub.get.reset(); - leveldb_stub.put.reset(); - plugin.email.sendMail.reset(); - - cryptoMock.randomBytes = sinon.stub(); - cryptoMock.randomBytes.onFirstCall().returns(randomBytes); - }); - - var setupLevelDb = function() { - leveldb_stub.get.onFirstCall().callsArgWith(1, { - notFound: true - }); - leveldb_stub.put.onFirstCall().callsArg(2); - }; - - it('saves data under the expected key', function(done) { - setupLevelDb(); - var clock = sinon.useFakeTimers(); - plugin.createVerificationSecretAndSendEmail(fakeEmail, function(err) { - var arg = JSON.parse(leveldb_stub.put.firstCall.args[1]); - arg.secret.should.equal(fakeRandom); - arg.created.should.equal(moment().unix()); - clock.restore(); - done(); - }); - }); - it('sends verification email', function(done) { - setupLevelDb(); - - plugin.createVerificationSecretAndSendEmail(fakeEmail, function(err) { - plugin.email.sendMail.calledOnce.should.be.true; - done(); - }); - }); - it('returns internal error on put database error', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, { - notFound: true - }); - leveldb_stub.put.onFirstCall().callsArgWith(2, 'error'); - plugin.createVerificationSecretAndSendEmail(fakeEmail, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - it('returns internal error on get database error', function(done) { - leveldb_stub.get.onFirstCall().callsArgWith(1, 'error'); - plugin.createVerificationSecretAndSendEmail(fakeEmail, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - }); - }); - - describe('on registration', function() { - var emailParam = 'email'; - var secretParam = 'secret'; - var keyParam = 'key'; - var recordParam = 'record'; - beforeEach(function() { - var data = ('email=' + emailParam + '&secret=' + secretParam + '&record=' + recordParam + '&key=' + keyParam); - request.on.onFirstCall().callsArgWith(1, data); - request.on.onFirstCall().returnsThis(); - request.on.onSecondCall().callsArg(1); - response.json.returnsThis(); - }); - - it('should allow new registrations', function() { - var originalCredentials = plugin.getCredentialsFromRequest; - plugin.getCredentialsFromRequest = sinon.mock(); - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: emailParam, - passphrase: secretParam - }); - plugin.exists = sinon.stub(); - plugin.exists.onFirstCall().callsArgWith(1, null, false); - plugin.savePassphrase = sinon.stub(); - plugin.savePassphrase.onFirstCall().callsArg(2); - plugin.isConfirmed = sinon.stub(); - plugin.isConfirmed.onFirstCall().callsArgWith(1, null, false); - plugin.checkSizeQuota = sinon.stub(); - plugin.checkSizeQuota.onFirstCall().callsArgWith(3, null); - plugin.checkAndUpdateItemQuota = sinon.stub(); - plugin.checkAndUpdateItemQuota.onFirstCall().callsArgWith(3, null); - plugin.saveEncryptedData = sinon.stub(); - plugin.saveEncryptedData.onFirstCall().callsArg(3); - plugin.createVerificationSecretAndSendEmail = sinon.stub(); - plugin.createVerificationSecretAndSendEmail.onFirstCall().callsArg(1); - response.send.onFirstCall().returnsThis(); - - plugin.save(request, response); - - assert(plugin.exists.firstCall.args[0] === emailParam); - assert(plugin.savePassphrase.firstCall.args[0] === emailParam); - assert(plugin.savePassphrase.firstCall.args[1] === secretParam); - assert(plugin.saveEncryptedData.firstCall.args[0] === emailParam); - assert(plugin.saveEncryptedData.firstCall.args[1] === keyParam); - assert(plugin.saveEncryptedData.firstCall.args[2] === recordParam); - assert(plugin.createVerificationSecretAndSendEmail.firstCall.args[0] === emailParam); - plugin.getCredentialsFromRequest = originalCredentials; - }); - - it('should allow to overwrite data', function() { - var originalCredentials = plugin.getCredentialsFromRequest; - plugin.getCredentialsFromRequest = sinon.mock(); - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: emailParam, - passphrase: secretParam - }); - plugin.exists = sinon.stub(); - plugin.exists.onFirstCall().callsArgWith(1, null, true); - plugin.checkPassphrase = sinon.stub(); - plugin.checkPassphrase.onFirstCall().callsArgWith(2, null, true); - plugin.isConfirmed = sinon.stub(); - plugin.isConfirmed.onFirstCall().callsArgWith(1, null, false); - plugin.checkSizeQuota = sinon.stub(); - plugin.checkSizeQuota.onFirstCall().callsArgWith(3, null); - plugin.checkAndUpdateItemQuota = sinon.stub(); - plugin.checkAndUpdateItemQuota.onFirstCall().callsArgWith(3, null); - plugin.saveEncryptedData = sinon.stub(); - plugin.saveEncryptedData.onFirstCall().callsArg(3); - plugin.createVerificationSecretAndSendEmail = sinon.stub(); - response.send.onFirstCall().returnsThis(); - - plugin.save(request, response); - - assert(plugin.exists.firstCall.args[0] === emailParam); - assert(plugin.checkPassphrase.firstCall.args[0] === emailParam); - assert(plugin.checkPassphrase.firstCall.args[1] === secretParam); - assert(plugin.saveEncryptedData.firstCall.args[0] === emailParam); - assert(plugin.saveEncryptedData.firstCall.args[1] === keyParam); - assert(plugin.saveEncryptedData.firstCall.args[2] === recordParam); - plugin.createVerificationSecretAndSendEmail.called.should.be.false; - plugin.getCredentialsFromRequest = originalCredentials; - }); - - it('should delete profile on error sending verification email', function() { - var originalCredentials = plugin.getCredentialsFromRequest; - plugin.getCredentialsFromRequest = sinon.mock(); - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: emailParam, - passphrase: secretParam - }); - plugin.exists = sinon.stub(); - plugin.exists.onFirstCall().callsArgWith(1, null, false); - plugin.savePassphrase = sinon.stub(); - plugin.savePassphrase.onFirstCall().callsArg(2); - plugin.isConfirmed = sinon.stub(); - plugin.isConfirmed.onFirstCall().callsArgWith(1, null, false); - plugin.checkSizeQuota = sinon.stub(); - plugin.checkSizeQuota.onFirstCall().callsArgWith(3, null); - plugin.checkAndUpdateItemQuota = sinon.stub(); - plugin.checkAndUpdateItemQuota.onFirstCall().callsArgWith(3, null); - plugin.saveEncryptedData = sinon.stub(); - plugin.saveEncryptedData.onFirstCall().callsArg(3); - plugin.createVerificationSecretAndSendEmail = sinon.stub(); - plugin.createVerificationSecretAndSendEmail.onFirstCall().callsArgWith(1, 'error'); - var deleteWholeProfile = sinon.stub(plugin, 'deleteWholeProfile'); - deleteWholeProfile.onFirstCall().callsArg(1); - response.send.onFirstCall().returnsThis(); - - plugin.save(request, response); - - assert(plugin.exists.firstCall.args[0] === emailParam); - assert(plugin.savePassphrase.firstCall.args[0] === emailParam); - assert(plugin.savePassphrase.firstCall.args[1] === secretParam); - assert(plugin.saveEncryptedData.firstCall.args[0] === emailParam); - assert(plugin.saveEncryptedData.firstCall.args[1] === keyParam); - assert(plugin.saveEncryptedData.firstCall.args[2] === recordParam); - assert(plugin.createVerificationSecretAndSendEmail.firstCall.args[0] === emailParam); - assert(deleteWholeProfile.firstCall.args[0] === emailParam); - plugin.getCredentialsFromRequest = originalCredentials; - }); - - after(function () { - plugin.deleteWholeProfile.restore(); - }); - }); - - describe('when validating email', function() { - - var email = '1'; - var secret = '2'; - beforeEach(function() { - - request.param.onFirstCall().returns(email); - request.param.onSecondCall().returns(secret); - leveldb_stub.put = sinon.stub(); - leveldb_stub.get = sinon.stub(); - leveldb_stub.put.onFirstCall().callsArg(2); - leveldb_stub.del.onFirstCall().callsArg(1); - response.json.returnsThis(); - }); - - it('should validate correctly an email if the secret matches (secret only)', function() { - leveldb_stub.get.onFirstCall().callsArgWith(1, null, secret); - leveldb_stub.del = sinon.stub().yields(null); - response.redirect = sinon.stub(); - - plugin.validate(request, response); - - assert(response.redirect.firstCall.calledWith(plugin.redirectUrl)); - }); - - it('should validate correctly an email if the secret matches (secret + creation date)', function() { - leveldb_stub.get.onFirstCall().callsArgWith(1, null, JSON.stringify({ - secret: secret, - created: moment().unix(), - })); - leveldb_stub.del = sinon.stub().yields(null); - response.redirect = sinon.stub(); - - plugin.validate(request, response); - - assert(response.redirect.firstCall.calledWith(plugin.redirectUrl)); - }); - - it('should fail to validate an email if the secret doesn\'t match', function() { - var invalid = '3'; - leveldb_stub.get.onFirstCall().callsArgWith(1, null, invalid); - response.status.returnsThis(); - response.json.returnsThis(); - - plugin.validate(request, response); - - assert(response.status.firstCall.calledWith(plugin.errors.INVALID_CODE.code)); - assert(response.json.firstCall.calledWith({ - error: 'The provided code is invalid' - })); - assert(response.end.calledOnce); - }); - }); - - describe('resend validation email', function () { - var email = 'fake@email.com'; - var secret = '123'; - beforeEach(function() { - leveldb_stub.get.reset(); - request.param.onFirstCall().returns(email); - response.json.returnsThis(); - response.redirect = sinon.stub(); - }); - - it('should resend validation email when pending', function () { - plugin.authorizeRequestWithoutKey = sinon.stub().callsArgWith(1, null, email); - leveldb_stub.get.onFirstCall().callsArgWith(1, null, JSON.stringify({ secret: secret, created: new Date() })); - plugin.sendVerificationEmail = sinon.spy(); - plugin.resendEmail(request, response); - plugin.sendVerificationEmail.calledOnce.should.be.true; - plugin.sendVerificationEmail.calledWith(email, secret).should.be.true; - }); - - it('should resend validation email when pending (old style secret)', function () { - plugin.authorizeRequestWithoutKey = sinon.stub().callsArgWith(1, null, email); - leveldb_stub.get.onFirstCall().callsArgWith(1, null, secret); - plugin.sendVerificationEmail = sinon.spy(); - plugin.resendEmail(request, response); - plugin.sendVerificationEmail.calledOnce.should.be.true; - plugin.sendVerificationEmail.calledWith(email, secret).should.be.true; - }); - - it('should not resend when email is no longer pending', function () { - plugin.authorizeRequestWithoutKey = sinon.stub().callsArgWith(1, null, email); - leveldb_stub.get.onFirstCall().callsArgWith(1, { notFound: true }); - plugin.sendVerificationEmail = sinon.spy(); - plugin.resendEmail(request, response); - plugin.sendVerificationEmail.should.not.be.called; - }); - }); - - describe('removing items', function() { - var fakeEmail = 'fake@email.com'; - var fakeKey = 'nameForData'; - beforeEach(function() { - leveldb_stub.del = sinon.stub(); - }); - it('deletes a stored element (key)', function(done) { - leveldb_stub.del.onFirstCall().callsArg(1); - - plugin.checkAndUpdateItemCounter = sinon.stub(); - plugin.checkAndUpdateItemCounter.onFirstCall().callsArg(3); - - plugin.deleteByEmailAndKey(fakeEmail, fakeKey, function(err) { - expect(err).to.be.undefined; - done(); - }); - }); - it('returns NOT FOUND if trying to delete a stored element by key', function(done) { - leveldb_stub.del.onFirstCall().callsArgWith(1, {notFound: true}); - plugin.deleteByEmailAndKey(fakeEmail, fakeKey, function(err) { - err.should.equal(plugin.errors.NOT_FOUND); - done(); - }); - }); - it('returns INTERNAL_ERROR if an unexpected error ocurrs', function(done) { - leveldb_stub.del.onFirstCall().callsArgWith(1, {unexpected: true}); - plugin.deleteByEmailAndKey(fakeEmail, fakeKey, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - it('can delete a whole profile (validation data and passphrase)', function(done) { - leveldb_stub.del.callsArg(1); - plugin.deleteWholeProfile(fakeEmail, function(err) { - expect(err).to.be.undefined; - leveldb_stub.del.callCount.should.equal(3); - done(); - }); - }); - it('dismisses not found errors', function(done) { - leveldb_stub.del.callsArg(1); - leveldb_stub.del.onSecondCall().callsArgWith(1, {notFound: true}); - plugin.deleteWholeProfile(fakeEmail, function(err) { - expect(err).to.be.undefined; - done(); - }); - }); - it('returns internal error if something goes awry', function(done) { - leveldb_stub.del.callsArg(1); - leveldb_stub.del.onSecondCall().callsArgWith(1, {unexpected: true}); - plugin.deleteWholeProfile(fakeEmail, function(err) { - err.should.equal(plugin.errors.INTERNAL_ERROR); - done(); - }); - }); - }); - - describe('when retrieving data', function() { - - it('should validate the secret and return the data', function() { - request.param.onFirstCall().returns('key'); - - plugin.authorizeRequestWithKey = sinon.stub().callsArgWith(1,null, 'email','key'); - plugin.retrieveByEmailAndKey = sinon.stub().yields(null, 'encrypted'); - - response.send.onFirstCall().returnsThis(); - plugin.addValidationHeader = sinon.stub().callsArg(2); - plugin.addValidationAndQuotaHeader = sinon.stub().callsArg(2); - - plugin.retrieve(request, response); - - response.send.calledOnce.should.equal(true); - - assert(plugin.retrieveByEmailAndKey.firstCall.args[0] === 'email'); - assert(plugin.retrieveByEmailAndKey.firstCall.args[1] === 'key'); - assert(response.send.firstCall.args[0] === 'encrypted'); - assert(response.end.calledOnce); - }); - }); - - - describe('authorizing requests', function() { - var originalCredentials; - beforeEach(function() { - originalCredentials = plugin.getCredentialsFromRequest; - - plugin.getCredentialsFromRequest = sinon.mock(); - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: 'email', - passphrase: 'pass' - }); - request.param.onFirstCall().returns('key'); - - request.on = sinon.stub(); - request.on.onFirstCall().callsArgWith(1, 'newPassphrase=newPassphrase'); - request.on.onFirstCall().returns(request); - request.on.onSecondCall().callsArg(1); - plugin.checkPassphrase = sinon.stub().callsArgWith(2,null, true); - - }); - - it('should authorize a request', function(done){ - plugin.authorizeRequest(request, false, function(err, email, key) { - expect(err).to.be.null; - expect(key).to.be.undefined; - email.should.be.equal('email'); - done(); - }); - }); - it('should authorize a request with key', function(done){ - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: 'email', - passphrase: 'pass', - }); - plugin.authorizeRequest(request, true, function(err, email, key) { - expect(err).to.be.null; - email.should.be.equal('email'); - key.should.be.equal('key'); - done(); - }); - }); - - it('should not authorize a request when param are missing', function(done){ - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: 'email', - }); - - plugin.authorizeRequest(request, false, function(err, email, key) { - expect(err).not.to.be.null; - expect(key).to.be.undefined; - expect(email).to.be.undefined; - done(); - }); - }); - it('should not authorize a request when param are missing (case2)', function(done){ - plugin.getCredentialsFromRequest.onFirstCall().returns({ - passphrase: 'pass' - }); - - plugin.authorizeRequest(request, false, function(err, email, key) { - expect(err).not.to.be.null; - expect(key).to.be.undefined; - expect(email).to.be.undefined; - done(); - }); - }); - it('should not authorize a request when param are missing (case3)', function(done){ - request.param.onFirstCall().returns(undefined); - plugin.getCredentialsFromRequest.onFirstCall().returns({ - email: 'email', - passphrase: 'pass' - }); - plugin.authorizeRequest(request, true, function(err, email, key) { - expect(err).not.to.be.null; - expect(key).to.be.undefined; - expect(email).to.be.undefined; - done(); - }); - }); - - - after(function() { - plugin.getCredentialsFromRequest = originalCredentials; - }); - }); - - describe('changing the user password', function() { - - - beforeEach(function() { - request.on = sinon.stub(); - request.on.onFirstCall().callsArgWith(1, 'newPassphrase=newPassphrase'); - request.on.onFirstCall().returns(request); - request.on.onSecondCall().callsArg(1); - response.status.onFirstCall().returnsThis(); - plugin.checkPassphrase = sinon.stub(); - plugin.savePassphrase = sinon.stub(); - }); - - it('should validate the previous passphrase', function() { - response.status.onFirstCall().returnsThis(); - response.json.onFirstCall().returnsThis(); - plugin.authorizeRequestWithoutKey = sinon.stub().callsArgWith(1,'error'); - - plugin.changePassphrase(request, response); - - assert(response.status.calledOnce); - assert(response.json.calledOnce); - assert(response.end.calledOnce); - }); - - it('should change the passphrase', function() { - response.json.onFirstCall().returnsThis(); - plugin.authorizeRequestWithoutKey = sinon.stub().callsArgWith(1,null, 'email'); - plugin.checkPassphrase.onFirstCall().callsArgWith(2, null); - plugin.savePassphrase.onFirstCall().callsArgWith(2, null); - - plugin.changePassphrase(request, response); - assert(response.json.calledOnce); - assert(response.end.calledOnce); - }); - }); -}); diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js deleted file mode 100644 index 960fc84..0000000 --- a/test/test.MessageDb.js +++ /dev/null @@ -1,133 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var should = chai.should; -var expect = chai.expect; - -var levelup = require('levelup'); -var memdown = require('memdown'); -var microtime = require('microtime'); -var MessageDb = require('../lib/MessageDb'); -var bitcore = require('bitcore'); -var SIN = bitcore.SIN; -var Key = bitcore.Key; -var AuthMessage = bitcore.AuthMessage; - -describe('MessageDb', function() { - var opts = { - name: 'test-MessageDb', - db: levelup({ - db: memdown, - sync: true, - valueEncoding: 'json' - }) - }; - it('should be able to create instance', function() { - var mdb = new MessageDb(opts); - expect(mdb).to.exist; - }); - it('should be able to create default instance', function() { - var mdb = MessageDb.default(); - expect(mdb).to.exist; - }); - var fpk = Key.generateSync(); - var tpk = Key.generateSync(); - var from = fpk.public.toString('hex'); - var to = tpk.public.toString('hex'); - var messageData = { - a: 1, - b: 2 - }; - var messageData2 = {}; - var messageData3 = ['a', 'b']; - var message = AuthMessage.encode(to, fpk, messageData); - var message2 = AuthMessage.encode(to, fpk, messageData2); - var message3 = AuthMessage.encode(to, fpk, messageData3); - it('should be able to add and read a message', function(done) { - var mdb = new MessageDb(opts); - var lower_ts = microtime.now(); - mdb.addMessage(message, function(err) { - expect(err).to.not.exist; - var upper_ts = microtime.now(); - mdb.getMessages(to, lower_ts, upper_ts, function(err, messages) { - expect(err).to.not.exist; - messages.length.should.equal(1); - messages[0].ts.should.be.below(upper_ts); - messages[0].ts.should.be.above(lower_ts); - var m = AuthMessage.decode(tpk, messages[0]).payload; - m.a.should.equal(1); - m.b.should.equal(2); - done(); - }); - }); - }); - var sharedMDB; - it('should be able to add many messages and read some', function(done) { - var mdb = new MessageDb(opts); - sharedMDB = mdb; - var lower_ts = microtime.now(); - mdb.addMessage(message, function(err) { - expect(err).to.not.exist; - mdb.addMessage(message2, function(err) { - expect(err).to.not.exist; - var upper_ts = microtime.now(); - setTimeout(function() { - mdb.addMessage(message3, function(err) { - expect(err).to.not.exist; - mdb.getMessages(to, lower_ts, upper_ts, function(err, messages) { - expect(err).to.not.exist; - messages.length.should.equal(2); - messages[0].ts.should.be.below(upper_ts); - messages[0].ts.should.be.above(lower_ts); - var m0 = AuthMessage.decode(tpk, messages[0]).payload; - JSON.stringify(m0).should.equal('{"a":1,"b":2}'); - messages[1].ts.should.be.below(upper_ts); - messages[1].ts.should.be.above(lower_ts); - var m1 = AuthMessage.decode(tpk, messages[1]).payload; - JSON.stringify(m1).should.equal('{}'); - done(); - }); - }); - }, 10); - }); - }); - }); - it('should be able to add many messages and read all', function(done) { - var mdb = sharedMDB; - mdb.getMessages(to, null, null, function(err, messages) { - expect(err).to.not.exist; - messages.length.should.equal(4); - var m0 = AuthMessage.decode(tpk, messages[0]).payload; - JSON.stringify(m0).should.equal('{"a":1,"b":2}'); - var m1 = AuthMessage.decode(tpk, messages[1]).payload; - JSON.stringify(m1).should.equal('{"a":1,"b":2}'); - var m2 = AuthMessage.decode(tpk, messages[2]).payload; - JSON.stringify(m2).should.equal('{}'); - var m3 = AuthMessage.decode(tpk, messages[3]).payload; - JSON.stringify(m3).should.equal('["a","b"]'); - done(); - }); - }); - it('should be able #removeUpTo', function(done) { - var mdb = sharedMDB; - var upper_ts = microtime.now(); - mdb.addMessage(message, function(err) { - expect(err).to.not.exist; - mdb.removeUpTo(upper_ts, function(err, n) { - expect(err).to.not.exist; - n.should.equal(4); - mdb.getAll(function(error, all) { - expect(error).to.not.exist; - all.length.should.equal(1); - done(); - }); - - }); - }); - }); - it('should be able to close instance', function() { - var mdb = new MessageDb(opts); - mdb.close(); - expect(mdb).to.exist; - }); -}); diff --git a/test/test.PublicProfile.js b/test/test.PublicProfile.js deleted file mode 100644 index 5444b2e..0000000 --- a/test/test.PublicProfile.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var assert = require('assert'); -var sinon = require('sinon'); -var should = chai.should; -var expect = chai.expect; -var bitauth = require('bitauth'); - -describe('public profile test', function() { - - var globalConfig = require('../config/config'); - var leveldb_stub = sinon.stub(); - leveldb_stub.put = sinon.stub(); - leveldb_stub.get = sinon.stub(); - var plugin = require('../plugins/publicInfo/publicInfo.js'); - var express_mock = null; - var request = null; - var response = null; - - beforeEach(function() { - - express_mock = sinon.stub(); - express_mock.post = sinon.stub(); - express_mock.get = sinon.stub(); - - plugin.init(express_mock, {db: leveldb_stub}); - - request = sinon.stub(); - request.on = sinon.stub(); - request.param = sinon.stub(); - response = sinon.stub(); - response.send = sinon.stub(); - response.status = sinon.stub(); - response.json = sinon.stub(); - response.end = sinon.stub(); - }); - - it('initializes correctly', function() { - assert(plugin.db === leveldb_stub); - assert(express_mock.post.calledWith( - globalConfig.apiPrefix + '/public', plugin.post - )); - assert(express_mock.get.calledWith( - globalConfig.apiPrefix + '/public/:sin', plugin.get - )); - }); - - it('writes a message correctly', function(done) { - - var privateKey = bitauth.generateSin(); - var protocol = 'https'; - var dataToSign = protocol + '://hosturlSTUFF'; - var signature = bitauth.sign(dataToSign, privateKey.priv); - request.get = function() { return 'host'; }; - request.protocol = protocol; - request.url = 'url'; - request.headers = { - 'x-identity': privateKey.pub, - 'x-signature': signature - }; - request.on.onFirstCall().callsArgWith(1, 'STUFF'); - request.on.onFirstCall().returnsThis(); - request.on.onSecondCall().callsArg(1); - - leveldb_stub.put.onFirstCall().callsArg(2); - response.status.returns(response); - response.json.returns(response); - - request.testCallback = function() { - assert(leveldb_stub.put.firstCall.args[0] === 'public-info-' + privateKey.sin); - assert(leveldb_stub.put.firstCall.args[1] === 'STUFF'); - assert(response.json.calledOnce); - assert(response.end.calledOnce); - done(); - }; - - plugin.post(request, response); - }); - - it('fails if the signature is invalid', function() { - var data = 'uecord3'; - request.get = function() { return ''; }; - request.headers = {}; - request.on.onFirstCall().callsArgWith(1, data); - request.on.onFirstCall().returnsThis(); - request.on.onSecondCall().callsArg(1); - leveldb_stub.put = sinon.stub(); - - leveldb_stub.put.onFirstCall().callsArg(2); - response.json.returnsThis(); - response.status.returnsThis(); - - plugin.post(request, response); - - assert(response.end.calledOnce); - }); - - it('retrieves a message correctly', function() { - - request.param.onFirstCall().returns('SIN'); - - var returnValue = '!@#$%'; - leveldb_stub.get.onFirstCall().callsArgWith(1, null, returnValue); - response.send.returnsThis(); - - plugin.get(request, response); - - assert(leveldb_stub.get.firstCall.args[0] === 'public-info-SIN'); - assert(response.send.calledWith(returnValue)); - assert(response.end.calledOnce); - }); -}); diff --git a/test/test.socket-server.js b/test/test.socket-server.js deleted file mode 100644 index 6920889..0000000 --- a/test/test.socket-server.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -var chai = require('chai'); -var should = chai.should; -var expect = chai.expect; -var sinon = require('sinon'); - -var socket = require('../app/controllers/socket'); -var bitcore = require('bitcore'); -var EventEmitter = require('events').EventEmitter; - -describe('socket server', function() { - it('should be able to call init with no args', function() { - socket.init.should.not.throw(); - }); - it('should register socket handlers', function() { - var io = { - sockets: new EventEmitter(), - } - socket.init(io); - - var mockSocket = {}; - mockSocket.on = sinon.spy(); - io.sockets.emit('connection', mockSocket); - mockSocket.on.calledWith('subscribe'); - mockSocket.on.calledWith('sync'); - mockSocket.on.calledWith('message'); - }); - -}); diff --git a/test/bitcore-node/transactions.js b/test/transactions.js similarity index 99% rename from test/bitcore-node/transactions.js rename to test/transactions.js index bbe521f..a7b4331 100644 --- a/test/bitcore-node/transactions.js +++ b/test/transactions.js @@ -2,7 +2,7 @@ var should = require('should'); var sinon = require('sinon'); var bitcore = require('bitcore'); -var TxController = require('../../bitcore-node/transactions'); +var TxController = require('../lib/transactions'); var _ = require('lodash'); /*var diff = function(a, b) { diff --git a/util/migration.js b/util/migration.js deleted file mode 100644 index e670e32..0000000 --- a/util/migration.js +++ /dev/null @@ -1,63 +0,0 @@ -var levelup = require('levelup'); -var bitcore = require('bitcore'); -var _ = require('lodash'); - -var home = process.env['HOME']; -var db = new levelup(process.argv[2] || (home + '/.insight/testnet/emailstore')); -var newDb = new levelup(process.argv[3] || (home + '/.insight/testnet/emailstore.migrated')); - -var transformStoredValue = function(key) { - var oldKey = key.substr('credentials-store-'.length); - return 'emailstore-' + bitcore.util.twoSha256(oldKey).toString('hex'); -}; - -var transformPending = function(key) { - var oldKey = key.substr('validation-code-'.length); - return 'pending-' + oldKey; -}; - -var transformPassphrase = function(key) { - var oldKey = key.substr('map-email-'.length); - return 'email-to-passphrase-' + bitcore.util.twoSha256(oldKey).toString('hex'); -}; - -var transformValidated = function(key) { - var oldKey = key.substr('validated-email-'.length); - return 'validated-' + bitcore.util.twoSha256(oldKey).toString('hex'); -}; - -var checks = { - 'credentials-store-': transformStoredValue, - 'validation-code-': transformPending, - 'map-email-': transformPassphrase, - 'validated-email': transformValidated -}; - -db.createReadStream() - .on('data', function(data) { - console.log('- Analizing key: ' + data.key); - _.each(checks, function(checkFunction, checkName) { - - if (data.key.indexOf(checkName) === 0) { - db.get('migration-' + data.key, function(err, value) { - if ((err && err.notFound) || data.value !== value) { - - var newKey = checkFunction(data.key); - if (data.value !== value) { - console.log(' - ' + newKey + ' outdated, migrating...') - } else { - console.log(' - ' + data.key + ' not migrated, migrating to ' + newKey); - } - - newDb.put(newKey, data.value, function(err) { - if (err) { - console.log(' - Error migrating ' + data.key + '!', err); - } else { - db.put('migration-' + data.key, data.value, function() {}); - } - }); - } - }); - } - }); - }); diff --git a/util/p2p.js b/util/p2p.js deleted file mode 100755 index 0d1d885..0000000 --- a/util/p2p.js +++ /dev/null @@ -1,18 +0,0 @@ -#! /usr/bin/env node -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var PeerSync = require('../lib/PeerSync'); - -var PROGRAM_VERSION = '0.1'; -var program = require('commander'); - -program - .version(PROGRAM_VERSION) - .parse(process.argv); - -var ps = new PeerSync(); -ps.run(); - - diff --git a/util/sync.js b/util/sync.js deleted file mode 100755 index 2bb11cd..0000000 --- a/util/sync.js +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env node - - -'use strict'; - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var SYNC_VERSION = '0.1'; -var program = require('commander'); -var HistoricSync = require('../lib/HistoricSync'); -var async = require('async'); - -program - .version(SYNC_VERSION) - .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('--start [hash]', 'StartAt block') - .option('--stop [hash]', 'StopAt block') - .option('-v --verbose', 'Verbose 0/1', 0) - .parse(process.argv); - -var historicSync = new HistoricSync({ - shouldBroadcastSync: true, -}); - - -async.series([ - function(cb) { - if (!program.destroy) return cb(); - console.log('Deleting Sync DB...'); - historicSync.sync.destroy(cb); - }, - function(cb) { - var opts= { - forceStartFile: program.startfile, - forceRPC: program.rpc, - startAt: program.start, - stopAt: program.stop, - }; - console.log('[options]',opts); //TODO - historicSync.start(opts,cb); - }, - ], - function(err) { - historicSync.close(); - if (err) console.log('CRITICAL ERROR: ', historicSync.info()); -}); - diff --git a/util/upgradeV0.2js b/util/upgradeV0.2js deleted file mode 100755 index abdf99d..0000000 --- a/util/upgradeV0.2js +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env node - -'use strict'; - -var HistoricSync = require('../lib/HistoricSync'); -var async = require('async'); - - -var historicSync = new HistoricSync({ shouldBroadcastSync: false }); -var txDb=historicSync.sync.txDb; -var bDb=historicSync.sync.bDb; - -var height = 0; -var hash = historicSync.genesis; -var tipHash; - -async.series([ - function(c){ - txDb.checkVersion02(function(isV2){ - var err; - if(isV2) err='Already in v0.2!'; - return c(err); - }); - }, - function(c){ - console.log('[1/3] Migrating txs ... (this will take some minutes...)'); //TODO - txDb.migrateV02(c); - }, - function(c){ - var script=[]; - async.whilst( - function() { - return hash; - }, - function (w_cb) { - script=script.concat(bDb._setHeightScript(hash,height)); - bDb.getNext(hash,function(err,val){ - if (err) return w_cb(err); - tipHash = hash; - hash = val; - if (hash) height++; - if (!(height%1000) || !hash) { - console.log('[2/3] migrating blocks \t%d blocks processed', height); - bDb._runScript(script, function(err) { - script=[]; - return w_cb(err); - }); - } - else return w_cb(); - }); - }, c); - }, - function(c){ - console.log('[3/3] Migrating txs... (this will take some minutes...)'); //TODO - bDb.migrateV02(c); - }, - function(c){ - bDb.setTip(tipHash, height, c); - }, - function(c){ - bDb.migrateV02cleanup(c); - }, - ],function(err){ - if (err) - console.log('## '+err); - else - console.log('Finished OK.'); -});