diff --git a/lib/blockchain.js b/lib/blockchain.js new file mode 100644 index 00000000..49cbafc8 --- /dev/null +++ b/lib/blockchain.js @@ -0,0 +1,45 @@ +'use strict'; + +var bitcore = require('bitcore'); +var $ = bitcore.util.preconditions; +var _ = bitcore.deps._; + +function BlockChain() { + this.tip = null; + this.headers = {}; + this.next = {}; + this.prev = {}; +} + +BlockChain.fromObject = function(obj) { + var blockchain = new BlockChain(); + blockchain.tip = obj.tip; + blockchain.headers = obj.headers; + blockchain.next = obj.next; + blockchain.prev = obj.prev; + return blockchain; +}; + +BlockChain.prototype.setTip = function(block) { + $.checkArgument(block instanceof bitcore.Block, 'Argument is not a Block instance'); + this.tip = block.hash; + this.headers[block.hash] = block.header; + var prevHash = bitcore.util.buffer.reverse(block.header.prevHash).toString('hex'); + this.next[prevHash] = block.hash; + this.prev[block.hash] = prevHash; +}; + +BlockChain.prototype.toObject = function() { + return { + tip: this.tip, + headers: _.map(this.headers, function(header) { return header.toObject(); }), + next: this.next, + prev: this.prev + }; +}; + +BlockChain.prototype.toJSON = function() { + return JSON.stringify(this.toObject()); +}; + +module.exports = BlockChain; diff --git a/lib/node.js b/lib/node.js index bd6b9f54..49a6a1a3 100644 --- a/lib/node.js +++ b/lib/node.js @@ -19,6 +19,7 @@ var BlockService = require('./services/block'); var TransactionService = require('./services/transaction'); var AddressService = require('./services/address'); +var BlockChain = require('./blockchain'); var genesisBlocks = require('./data/genesis'); var BitcoreNode = function(bus, networkMonitor, blockService, transactionService, addressService) { @@ -89,16 +90,14 @@ BitcoreNode.prototype.sync = function() { var genesis = bitcore.Block.fromBuffer(genesisBlocks[bitcore.Networks.defaultNetwork.name]); var self = this; this.networkMonitor.on('ready', function() { - console.log('ready'); - self.blockService.getLatest().then(function(latest) { - var start = genesis.hash; - console.log('latest', latest); - if (latest) { - start = latest.hash; + self.blockService.getBlockchain().then(function(blockchain) { + if (blockchain) { + self.blockchain = blockchain; + } else { + self.blockchain = new BlockChain(); + self.blockchain.setTip(genesis); } - console.log('Starting sync from', start); - self.tip = latest; - self.networkMonitor.requestBlocks(start); + self.networkMonitor.requestBlocks(self.blockchain.tip); }) .catch(function(err) { self.networkMonitor.stop(); diff --git a/lib/services/block.js b/lib/services/block.js index 39468652..3c614035 100644 --- a/lib/services/block.js +++ b/lib/services/block.js @@ -39,7 +39,8 @@ var Index = { prev: 'prev-', // prev- -> parent hash next: 'nxt-', // nxt- -> hash for the next block in the main chain that is a child height: 'bh-', // bh- -> height (-1 means disconnected) - tip: 'tip' // tip -> { hash: hex, height: int }, the latest tip + tip: 'tip', // tip -> { hash: hex, height: int }, the latest tip + blockchain: 'chain' }; _.extend(Index, { getNextBlock: helper(Index.next), @@ -381,4 +382,26 @@ BlockService.prototype.getBlockForTransaction = function(transaction) { }); }; +BlockService.prototype.getBlockchain = function() { + var self = this; + return new Promise(function(resolve, reject) { + self.database.getAsync(Index.blockchain).then(function(blockchain) { + blockchain = BlockChain.fromObject(JSON.parse(blockchain)); + return resolve(blockchain); + }).catch(function(arg) { + if (arg.message.indexOf('Key not found in database') !== -1) { + return resolve(); + } + return reject(arg); + }); + }); +}; + +BlockService.prototype.saveBlockchain = function(blockchain) { + return this.database.putAsync({ + key: Index.blockchain, + value: blockchain.toJSON() + }); +}; + module.exports = BlockService;