diff --git a/app/models/Block.js b/app/models/Block.js new file mode 100644 index 0000000..9440426 --- /dev/null +++ b/app/models/Block.js @@ -0,0 +1,68 @@ +'use strict'; + +/** + * Module dependencies. + */ +var mongoose = require('mongoose'), + Schema = mongoose.Schema; + + +/** + * Block Schema + */ +var BlockSchema = new Schema({ + hash: { + type: String, + index: true, + unique: true, + }, + size: Number, + confirmations: Number, + version: Number, + merkleroot: String, + tx: [ String ], + time: Date, + nonce: Number, + bits: String, + difficulty: Number, + chainwork: String, + previousblockhash: { + type: String, + index: true, + unique: true, + }, + nextblockhash: { + type: String, + index: true, + unique: true, + }, +}); + +/** + * Validations + */ + +/* +BlockSchema.path('title').validate(function(title) { + return title.length; +},'Title cannot be blank'); +*/ + +/** + * Statics + */ + +BlockSchema.statics.load = function(id, cb) { + this.findOne({ + _id: id + }).exec(cb); +}; + + +BlockSchema.statics.fromHash = function(hash, cb) { + this.findOne({ + hash: hash, + }).exec(cb); +}; + +module.exports = mongoose.model('Block', BlockSchema); diff --git a/config/env/development.js b/config/env/development.js index 0ef298c..2ddf0dc 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -4,5 +4,10 @@ module.exports = { db: "mongodb://localhost/mystery-dev", app: { name: "Mystery - Development" + }, + bitcoind: { + user: 'mystery', + pass: 'real_mystery', + protocol: 'http', } -} \ No newline at end of file +} diff --git a/config/routes.js b/config/routes.js index 182a216..1f75a0e 100644 --- a/config/routes.js +++ b/config/routes.js @@ -6,7 +6,9 @@ module.exports = function(app) { var index = require('../app/controllers/index'); app.get('/', index.render); - //TX routes - // + //Block routes + var blocks = require('model/app/controllers/blocks'); + app.get('/block/:block_hash', blocks.show); + }; diff --git a/package.json b/package.json index 110c3e0..0fc2f26 100644 --- a/package.json +++ b/package.json @@ -35,12 +35,14 @@ "postinstall": "node node_modules/bower/bin/bower install" }, "dependencies": { + "classtool": "*", "express": "~3.4.7", "jade": "~1.0.2", "mongoose": "~3.8.3", "lodash": "~2.4.1", "bower": "~1.2.8", "bitcore": "*", + "buffertools": "*", "grunt": "~0.4.2", "grunt-cli": "~0.1.11", "grunt-env": "~0.4.1", diff --git a/util/get_block.js b/util/get_block.js index 27880d8..783d7cf 100755 --- a/util/get_block.js +++ b/util/get_block.js @@ -1,17 +1,15 @@ #!/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 block_hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; -var rpc = new RpcClient({ - user: 'mystery', - pass: 'real_mystery', - protocol: 'http', -}); + +var rpc = new RpcClient(config.bitcoind); var block = rpc.getBlock(block_hash, function(err, block) { diff --git a/util/sync.js b/util/sync.js new file mode 100755 index 0000000..78991de --- /dev/null +++ b/util/sync.js @@ -0,0 +1,89 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; +require('buffertools').extend(); + +var util = require('util'); +var RpcClient = require('../node_modules/bitcore/RpcClient').class(); +var networks = require('../node_modules/bitcore/networks'); + +var Block = require('../app/models/Block'); +var config = require('../config/config'); +var mongoose = require('mongoose'); + +var networkName = process.argv[2] || 'testnet'; +var network = networkName == 'testnet' ? networks.testnet : networks.livenet; + + +function getNextBlock(blockHash,cb) { + + if ( !blockHash ) { + console.log("done"); + return cb(); + } + + rpc.getBlock(blockHash, function(err, blockInfo) { + if (err) { + return cb(err); + } + + if ( ! ( blockInfo.result.height % 1000) ) { + var h = blockInfo.result.height, + d = blockInfo.result.confirmations; + console.log( util.format("Height: %d/%d [%d%%]", h, d, 100*h/(h+d))); + } + + Block.create( blockInfo.result, function(err, inBlock) { + + // E11000 => already exists + if (err && ! err.toString().match(/E11000/)) { + return cb(err); + } + + return getNextBlock(blockInfo.result.nextblockhash); + + }); + }); + +} + +function syncBlocks(network, cb) { + + Block.findOne({}, {}, { sort: { 'height' : -1 } }, function(err, block) { + if (err) { + return cb(err); + } + + + + var nextHash = + block && block.hash + ? block.hash + : network.genesisBlock.hash.reverse().toString('hex') + ; + + + console.log('Starting at hash' + nextHash); + getNextBlock(nextHash, cb); + }); +} + + +mongoose.connect(config.db); + +var db = mongoose.connection; +var rpc = new RpcClient(config.bitcoind); + + +db.on('error', console.error.bind(console, 'connection error:')); +db.once('open', function callback () { + syncBlocks(network, function(err) { + if (err) { + console.log(err); + } + mongoose.connection.close(); + }); +}); + + +