Merge pull request #3 from eordano/sync

Sync
This commit is contained in:
Manuel Aráoz 2015-04-06 16:13:44 -03:00
commit deb566758b
5 changed files with 100 additions and 15 deletions

45
lib/blockchain.js Normal file
View File

@ -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;

13
lib/data/genesis.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
livenet: new Buffer('010000000000000000000000000000000000000000000000000000000000' +
'0000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a5132' +
'3a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c01010000000100000000' +
'00000000000000000000000000000000000000000000000000000000ffff' +
'ffff4d04ffff001d0104455468652054696d65732030332f4a616e2f3230' +
'3039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f' +
'6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01' +
'000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a6' +
'7962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b' +
'8d578a4c702b6bf11d5fac00000000', 'hex'),
testnet: new Buffer('')
}

View File

@ -64,6 +64,11 @@ NetworkMonitor.prototype.setupPeer = function(peer) {
};
NetworkMonitor.prototype.requestBlocks = function(start) {
$.checkArgument(_.isString(start), 'start must be a block hash string');
this.peer.sendMessage(messages.GetBlocks([start]));
};
NetworkMonitor.prototype.start = function() {
this.peer.connect();
};
@ -76,9 +81,4 @@ NetworkMonitor.prototype.abort = function(reason) {
throw reason;
};
NetworkMonitor.prototype.syncFrom = function(start) {
$.checkArgument(_.isString(start), 'start must be a block hash string');
this.peer.sendMessage(messages.GetBlocks([start]));
};
module.exports = NetworkMonitor;

View File

@ -19,6 +19,9 @@ 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) {
$.checkArgument(bus);
$.checkArgument(networkMonitor);
@ -26,6 +29,8 @@ var BitcoreNode = function(bus, networkMonitor, blockService, transactionService
this.bus = bus;
this.networkMonitor = networkMonitor;
this.tip = null;
this.addressService = addressService;
this.transactionService = transactionService;
this.blockService = blockService;
@ -82,18 +87,17 @@ BitcoreNode.prototype.start = function() {
};
BitcoreNode.prototype.sync = function() {
var genesis = bitcore.Block.fromBuffer(bitcore.Networks.defaultNetwork.genesis);
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.networkMonitor.syncFrom(start);
self.networkMonitor.requestBlocks(self.blockchain.tip);
})
.catch(function(err) {
self.networkMonitor.stop();

View File

@ -39,7 +39,8 @@ var Index = {
prev: 'prev-', // prev-<hash> -> parent hash
next: 'nxt-', // nxt-<hash> -> hash for the next block in the main chain that is a child
height: 'bh-', // bh-<hash> -> 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;