diff --git a/config/testnet.yml b/config/testnet.yml new file mode 100644 index 00000000..313e99cd --- /dev/null +++ b/config/testnet.yml @@ -0,0 +1,16 @@ +BitcoreNode: + LevelUp: ./testnet-db + network: testnet + NetworkMonitor: + host: localhost + port: 18333 +Reporter: none # none, simple, matrix +BitcoreHTTP: + host: localhost + port: 8080 +RPC: + user: user + pass: password + protocol: http + host: 127.0.0.1 + port: 18332 diff --git a/lib/networkmonitor.js b/lib/networkmonitor.js index 437dff24..2bfbd692 100644 --- a/lib/networkmonitor.js +++ b/lib/networkmonitor.js @@ -9,13 +9,16 @@ var $ = bitcore.util.preconditions; var _ = bitcore.deps._; var p2p = require('bitcore-p2p'); var Peer = p2p.Peer; -var messages = new p2p.Messages(); function NetworkMonitor(eventBus, peer) { $.checkArgument(eventBus); $.checkArgument(peer); this.bus = eventBus; this.peer = peer; + this.messages = new p2p.Messages({ + network: this.peer.network, + magicNumber: this.peer.network.networkMagic.readUInt32LE(0) + }); this.setupPeer(peer); } util.inherits(NetworkMonitor, EventEmitter); @@ -41,7 +44,7 @@ NetworkMonitor.prototype.setupPeer = function(peer) { peer.on('inv', function(m) { self.emit('inv', m.inventory); // TODO only ask for data if tx or block is unknown - peer.sendMessage(messages.GetData(m.inventory)); + peer.sendMessage(self.messages.GetData(m.inventory)); }); peer.on('tx', function(m) { self.bus.process(m.transaction) @@ -69,8 +72,7 @@ NetworkMonitor.prototype.requestBlocks = function(locator) { $.checkArgument(_.isArray(locator) && _.isUndefined(locator[0]) || _.isString(locator[0]), 'start must be a block hash string array'); - console.log('request blocks', locator); - this.peer.sendMessage(messages.GetBlocks({ + this.peer.sendMessage(this.messages.GetBlocks({ starts: locator, //stop: '000000002c05cc2e78923c34df87fd108b22221ac6076c18f3ade378a4d915e9' // TODO: remove this!!! })); diff --git a/lib/node.js b/lib/node.js index 767cea7b..e1c6f8e3 100644 --- a/lib/node.js +++ b/lib/node.js @@ -76,6 +76,8 @@ BitcoreNode.prototype.initialize = function() { var self = this; + var prevHeight = 0; + var statTimer = 5 * 1000; setInterval(function() { if (!self.blockchain) { // not ready yet @@ -83,8 +85,10 @@ BitcoreNode.prototype.initialize = function() { } var tipHash = self.blockchain.tip; var block = self.blockCache[tipHash]; - console.log('block', block.id, 'height', block.height); - }, 5 * 1000); + var delta = block.height - prevHeight; + prevHeight = block.height; + console.log(block.id, block.height, 'vel', delta * 1000 / statTimer, 'b/s'); + }, statTimer); this.bus.register(bitcore.Block, function(block) { @@ -100,7 +104,8 @@ BitcoreNode.prototype.initialize = function() { // Annotate block with extra data from the chain block.height = self.blockchain.height[block.id]; block.work = self.blockchain.work[block.id]; - console.log('>block', block.id, 'height', block.height); + + //console.log('block', block.id, block.height); return Promise.each(blockchainChanges.unconfirmed, function(hash) { return self.blockService.unconfirm(self.blockCache[hash]); diff --git a/lib/services/block.js b/lib/services/block.js index e360ef1b..0353685b 100644 --- a/lib/services/block.js +++ b/lib/services/block.js @@ -200,7 +200,9 @@ BlockService.prototype.getLatest = function() { return self.getBlock(blockHash); }).catch(LevelUp.errors.NotFoundError, function() { + return null; + }); }; @@ -251,6 +253,7 @@ BlockService.prototype.confirm = function(block, ops) { //console.log(4); self._setBlockByTs(ops, block); + //console.log(4.1); self._setTip(ops, block); //console.log(5); @@ -471,23 +474,23 @@ BlockService.prototype.getBlockchain = function() { }; return self.database.getAsync(Index.tip) - .catch(function(err) { - if (err.notFound) { - return undefined; - } - throw err; - }) - .then(function(tip) { - if (!tip) { - console.log('No tip found'); - return; - } - console.log('Tip is', tip); - blockchain.tip = tip; - return fetchUnlessGenesis(tip).then(function() { - return blockchain; + .catch(function(err) { + if (err.notFound) { + return undefined; + } + throw err; + }) + .then(function(tip) { + if (!tip) { + console.log('No tip found'); + return; + } + console.log('Tip is', tip); + blockchain.tip = tip; + return fetchUnlessGenesis(tip).then(function() { + return blockchain; + }); }); - }); }; module.exports = BlockService; diff --git a/lib/services/transaction.js b/lib/services/transaction.js index a704bc12..b0b01d76 100644 --- a/lib/services/transaction.js +++ b/lib/services/transaction.js @@ -25,7 +25,7 @@ var _ = bitcore.deps._; var $ = bitcore.util.preconditions; var NULLTXHASH = bitcore.util.buffer.emptyBuffer(32).toString('hex'); -var GENESISTX = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b' +var GENESISTX = '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b'; var helper = function(name) { return function(txId, output) { @@ -50,15 +50,15 @@ var helperAddress = function(index) { }; var Index = { - output: 'txo-', // txo-- -> serialized Output - spent: 'txs-', // txo---- -> block height of confirmation for spend - address: 'txa-', // txa-
-- -> Output + output: 'txo-', // txo-- -> serialized Output + spent: 'txs-', // txo---- -> block height of confirmation for spend + address: 'txa-', // txa-
-- -> Output addressSpent: 'txas-', // txa-
-- -> { - // heightSpent: number, (may be -1 for unconfirmed tx) - // spentTx: string, spentTxInputIndex: number, spendInput: Input - // } - transaction: 'btx-' // btx- -> block in main chain that confirmed the tx -} + // heightSpent: number, (may be -1 for unconfirmed tx) + // spentTx: string, spentTxInputIndex: number, spendInput: Input + // } + transaction: 'btx-' // btx- -> block in main chain that confirmed the tx +}; _.extend(Index, { getOutput: helper(Index.output), @@ -76,7 +76,7 @@ _.extend(Index, { } }); -function TransactionService (opts) { +function TransactionService(opts) { opts = _.extend({}, opts); this.database = opts.database || Promise.promisifyAll(new LevelUp(config.get('LevelUp'))); this.rpc = opts.rpc || Promise.promisifyAll(new RPC(config.get('RPC'))); @@ -91,7 +91,6 @@ TransactionService.transactionRPCtoBitcore = function(rpcResponse) { }; TransactionService.prototype.getTransaction = function(transactionId) { - var self = this; if (transactionId === GENESISTX) { @@ -106,27 +105,24 @@ TransactionService.prototype.getTransaction = function(transactionId) { }; TransactionService.prototype._confirmOutput = function(ops, block, transaction) { + var txid = transaction.id; return function(output, index) { ops.push({ type: 'put', - key: Index.getOutput(transaction.id, index), + key: Index.getOutput(txid, index), value: output.toJSON() }); var address; - // TODO: Move this logic to bitcore - if (output.script.isPublicKeyOut()) { - var hash = bitcore.crypto.Hash.sha256ripemd160(output.script.chunks[0].buf); - address = new bitcore.Address(hash, bitcore.Networks.defaultNetwork, bitcore.Address.PayToPublicKeyHash); - } else if (output.script.isPublicKeyHashOut() || output.script.isScriptHashOut()) { + if (output.script.isPublicKeyHashOut() || output.script.isScriptHashOut()) { address = output.script.toAddress(); } if (address) { + var out4addr = output.toObject(); + out4addr.heightConfirmed = block.height; ops.push({ type: 'put', - key: Index.getOutputsForAddress(address, transaction.id, index), - value: JSON.stringify(_.extend(output.toObject(), { - heightConfirmed: block.height - })) + key: Index.getOutputsForAddress(address, txid, index), + value: JSON.stringify(out4addr) }); } }; @@ -134,13 +130,14 @@ TransactionService.prototype._confirmOutput = function(ops, block, transaction) TransactionService.prototype._confirmInput = function(ops, block, transaction) { var self = this; + var txid = transaction.id; return function(input, index) { if (input.prevTxId.toString('hex') === NULLTXHASH) { return Promise.resolve(); } ops.push({ type: 'put', - key: Index.getOutput(transaction.id, index), + key: Index.getOutput(txid, index), value: JSON.stringify(_.extend(input.toObject(), { heightConfirmed: block.height })) @@ -151,15 +148,14 @@ TransactionService.prototype._confirmInput = function(ops, block, transaction) { } return Promise.try(function() { - return self._getAddressForInput(input) - }).then(function(address) { + var address = self._getAddressForInput(input); if (address) { ops.push({ type: 'put', - key: Index.getSpentOutputsForAddress(address, transaction.id, index), + key: Index.getSpentOutputsForAddress(address, txid, index), value: JSON.stringify({ heightSpent: block.height, - spentTx: transaction.id, + spentTx: txid, spentTxInputIndex: index, spendInput: input.toObject() }) @@ -171,29 +167,8 @@ TransactionService.prototype._confirmInput = function(ops, block, transaction) { TransactionService.prototype._getAddressForInput = function(input) { var script = input.script; - var self = this; - - if (script.isPublicKeyHashIn()) { - var hash = bitcore.crypto.Hash.sha256ripemd160(script.chunks[0].buf); - return new bitcore.Address( - hash, bitcore.Networks.defaultNetwork, bitcore.Address.PayToPublicKeyHash - ); - } else if (script.isPublicKeyIn()) { - /* - return self.getTransaction(input.prevTxId.toString('hex')).then(function(transaction) { - var outputScript = transaction.outputs[input.outputIndex].script; - if (outputScript.isPublicKeyOut()) { - return new bitcore.Address( - bitcore.crypto.Hash.sha256ripemd160(outputScript.chunks[0].buf), - bitcore.Networks.defaultNetwork, bitcore.Address.PayToPublicKeyHash - ); - } - return; - }); - */ - } else { - return new bitcore.Script(script.chunks[script.chunks.length - 1]).toAddress(); - } + // TODO: move this to bitcore + return new bitcore.Script(script.chunks[script.chunks.length - 1]).toAddress(); }; TransactionService.prototype._confirmTransaction = function(ops, block, transaction) { @@ -203,11 +178,12 @@ TransactionService.prototype._confirmTransaction = function(ops, block, transact key: Index.getBlockForTransaction(transaction), value: block.id }); - return Promise.all( + var confirmFunctions = _.map(transaction.outputs, self._confirmOutput(ops, block, transaction)) - .concat( - _.map(transaction.inputs, self._confirmInput(ops, block, transaction)) - )); + .concat( + _.map(transaction.inputs, self._confirmInput(ops, block, transaction)) + ); + return Promise.all(confirmFunctions); }; TransactionService.prototype._unconfirmTransaction = function(ops, block, transaction) { @@ -219,9 +195,9 @@ TransactionService.prototype._unconfirmTransaction = function(ops, block, transa }); return Promise.all( _.map(transaction.outputs, self._unconfirmOutput(ops, block, transaction)) - .concat( - _.map(transaction.inputs, self._unconfirmInput(ops, block, transaction)) - )); + .concat( + _.map(transaction.inputs, self._unconfirmInput(ops, block, transaction)) + )); }; module.exports = TransactionService;