commit
deb566758b
45
lib/blockchain.js
Normal file
45
lib/blockchain.js
Normal 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
13
lib/data/genesis.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
livenet: new Buffer('010000000000000000000000000000000000000000000000000000000000' +
|
||||||
|
'0000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a5132' +
|
||||||
|
'3a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c01010000000100000000' +
|
||||||
|
'00000000000000000000000000000000000000000000000000000000ffff' +
|
||||||
|
'ffff4d04ffff001d0104455468652054696d65732030332f4a616e2f3230' +
|
||||||
|
'3039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f' +
|
||||||
|
'6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01' +
|
||||||
|
'000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a6' +
|
||||||
|
'7962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b' +
|
||||||
|
'8d578a4c702b6bf11d5fac00000000', 'hex'),
|
||||||
|
testnet: new Buffer('')
|
||||||
|
}
|
||||||
@ -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() {
|
NetworkMonitor.prototype.start = function() {
|
||||||
this.peer.connect();
|
this.peer.connect();
|
||||||
};
|
};
|
||||||
@ -76,9 +81,4 @@ NetworkMonitor.prototype.abort = function(reason) {
|
|||||||
throw 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;
|
module.exports = NetworkMonitor;
|
||||||
|
|||||||
22
lib/node.js
22
lib/node.js
@ -19,6 +19,9 @@ var BlockService = require('./services/block');
|
|||||||
var TransactionService = require('./services/transaction');
|
var TransactionService = require('./services/transaction');
|
||||||
var AddressService = require('./services/address');
|
var AddressService = require('./services/address');
|
||||||
|
|
||||||
|
var BlockChain = require('./blockchain');
|
||||||
|
var genesisBlocks = require('./data/genesis');
|
||||||
|
|
||||||
var BitcoreNode = function(bus, networkMonitor, blockService, transactionService, addressService) {
|
var BitcoreNode = function(bus, networkMonitor, blockService, transactionService, addressService) {
|
||||||
$.checkArgument(bus);
|
$.checkArgument(bus);
|
||||||
$.checkArgument(networkMonitor);
|
$.checkArgument(networkMonitor);
|
||||||
@ -26,6 +29,8 @@ var BitcoreNode = function(bus, networkMonitor, blockService, transactionService
|
|||||||
this.bus = bus;
|
this.bus = bus;
|
||||||
this.networkMonitor = networkMonitor;
|
this.networkMonitor = networkMonitor;
|
||||||
|
|
||||||
|
this.tip = null;
|
||||||
|
|
||||||
this.addressService = addressService;
|
this.addressService = addressService;
|
||||||
this.transactionService = transactionService;
|
this.transactionService = transactionService;
|
||||||
this.blockService = blockService;
|
this.blockService = blockService;
|
||||||
@ -82,18 +87,17 @@ BitcoreNode.prototype.start = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
BitcoreNode.prototype.sync = 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;
|
var self = this;
|
||||||
this.networkMonitor.on('ready', function() {
|
this.networkMonitor.on('ready', function() {
|
||||||
console.log('ready');
|
self.blockService.getBlockchain().then(function(blockchain) {
|
||||||
self.blockService.getLatest().then(function(latest) {
|
if (blockchain) {
|
||||||
var start = genesis.hash;
|
self.blockchain = blockchain;
|
||||||
console.log('latest', latest);
|
} else {
|
||||||
if (latest) {
|
self.blockchain = new BlockChain();
|
||||||
start = latest.hash;
|
self.blockchain.setTip(genesis);
|
||||||
}
|
}
|
||||||
console.log('Starting sync from', start);
|
self.networkMonitor.requestBlocks(self.blockchain.tip);
|
||||||
self.networkMonitor.syncFrom(start);
|
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
self.networkMonitor.stop();
|
self.networkMonitor.stop();
|
||||||
|
|||||||
@ -39,7 +39,8 @@ var Index = {
|
|||||||
prev: 'prev-', // prev-<hash> -> parent hash
|
prev: 'prev-', // prev-<hash> -> parent hash
|
||||||
next: 'nxt-', // nxt-<hash> -> hash for the next block in the main chain that is a child
|
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)
|
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, {
|
_.extend(Index, {
|
||||||
getNextBlock: helper(Index.next),
|
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;
|
module.exports = BlockService;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user