From f4dbc0ee33500a8191d3de30b06b09f38d8e6e27 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 May 2014 08:49:52 -0500 Subject: [PATCH 01/15] parser: parse transactions in regular blocks. --- lib/bcoin/block.js | 20 ++++++++++++++++++++ lib/bcoin/pool.js | 4 ++++ lib/bcoin/protocol/parser.js | 17 +++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 2b4d67f0..330259ea 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -23,6 +23,21 @@ function Block(data, subtype) { this.tx = []; this.invalid = false; + if (this.subtype === 'block') { + var self = this; + this.txs = data.txs || []; + this.txs = this.txs.map(function(tx) { + tx = bcoin.tx(tx); + tx.block = self.hash('hex'); + tx.ts = tx.ts || self.ts; + return tx; + }); + this.hashes = this.txs.map(function(tx) { + return tx.hash('hex'); + }); + this.tx = this.hashes.slice(); + } + this._hash = null; // Verify partial merkle tree and fill `ts` array @@ -64,6 +79,11 @@ Block.prototype.hasTX = function hasTX(hash) { Block.prototype._verifyMerkle = function verifyMerkle() { var height = 0; + if (this.subtype === 'block') { + this.invalid = !utils.testTarget(this.bits, this.hash()); + return; + } + // Count leafs for (var i = this.totalTX; i > 0; i >>= 1) height++; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 471eafe0..39757250 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -293,6 +293,10 @@ Pool.prototype._addPeer = function _addPeer(backoff) { self.emit('block', block, peer); }); + peer.on('block', function(block) { + self.emit('block', block, peer); + }); + // Just FYI peer.on('reject', function(payload) { self.emit('reject', payload, peer); diff --git a/lib/bcoin/protocol/parser.js b/lib/bcoin/protocol/parser.js index 8238b436..4bceca0f 100644 --- a/lib/bcoin/protocol/parser.js +++ b/lib/bcoin/protocol/parser.js @@ -218,6 +218,17 @@ Parser.prototype.parseBlock = function parseBlock(p) { if (p.length < 84) return this._error('Invalid block size'); + var result = readIntv(p, 80); + var off = result.off; + var totalTX = result.r; + var txs = []; + + for (var i = 0; i < totalTX; i++) { + var tx = this.parseTX(p.slice(off)); + off += tx._off; + txs.push(tx); + } + return { version: readU32(p, 0), prevBlock: p.slice(4, 36), @@ -225,7 +236,8 @@ Parser.prototype.parseBlock = function parseBlock(p) { ts: readU32(p, 68), bits: readU32(p, 72), nonce: readU32(p, 76), - totalTX: readU32(p, 80) + totalTX: totalTX, + txs: txs }; }; @@ -316,7 +328,8 @@ Parser.prototype.parseTX = function parseTX(p) { version: readU32(p, 0), inputs: txIn, outputs: txOut, - lock: readU32(p, off) + lock: readU32(p, off), + _off: off + 4 }; }; From 7de69646286a1fde3f5f0f185fa9ed33b43333ff Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 May 2014 10:06:29 -0500 Subject: [PATCH 02/15] allow usage of the original non-spv pre BIP-37 satoshi protocol. --- lib/bcoin/peer.js | 8 ++++++++ lib/bcoin/pool.js | 14 +++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index e6770e75..a30d8ea5 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -161,6 +161,7 @@ Peer.prototype.broadcast = function broadcast(items) { }; Peer.prototype.updateWatch = function updateWatch() { + if (this.options.satoshi) return; if (this.ack) this._write(this.framer.filterLoad(this.bloom, 'none')); }; @@ -417,6 +418,13 @@ Peer.prototype._handleInv = function handleInv(items) { }); this.emit('blocks', blocks); + if (this.options.satoshi) { + this.getData(items.filter(function(item) { + return item.type === 'block'; + })); + return; + } + if (txs.length === 0) return; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index 39757250..ab26a657 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -105,7 +105,8 @@ Pool.prototype._addLoader = function _addLoader() { return; var peer = new bcoin.peer(this, this.createConnection, { - backoff: 750 * Math.random() + backoff: 750 * Math.random(), + satoshi: this.options.satoshi }); this.peers.load = peer; @@ -242,7 +243,8 @@ Pool.prototype._addPeer = function _addPeer(backoff) { return; var peer = new bcoin.peer(this, this.createConnection, { - backoff: backoff + backoff: backoff, + satoshi: this.options.satoshi }); this.peers.pending.push(peer); @@ -293,9 +295,11 @@ Pool.prototype._addPeer = function _addPeer(backoff) { self.emit('block', block, peer); }); - peer.on('block', function(block) { - self.emit('block', block, peer); - }); + if (this.options.satoshi) { + peer.on('block', function(block) { + self.emit('block', block, peer); + }); + } // Just FYI peer.on('reject', function(payload) { From e66f2f50bf3246d858147ac2e59e2b3c9b8a8490 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 May 2014 23:08:59 -0500 Subject: [PATCH 03/15] block: build merkleTree to verify merkleRoot on regular blocks. --- lib/bcoin/block.js | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 330259ea..40435029 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -1,4 +1,5 @@ var bcoin = require('../bcoin'); +var hash = require('hash.js'); var utils = bcoin.utils; function Block(data, subtype) { @@ -36,6 +37,7 @@ function Block(data, subtype) { return tx.hash('hex'); }); this.tx = this.hashes.slice(); + this.invalid = !this._checkBlock(); } this._hash = null; @@ -80,7 +82,6 @@ Block.prototype._verifyMerkle = function verifyMerkle() { var height = 0; if (this.subtype === 'block') { - this.invalid = !utils.testTarget(this.bits, this.hash()); return; } @@ -158,3 +159,38 @@ Block.fromJSON = function fromJSON(json) { return block; }; + +Block.prototype._phash = function phash(p1begin, p1end, p2begin, p2end) { + var pblank = ''; + var hash1 = hash.sha256(); + hash1.update(p1begin === p1end ? pblank : p1begin, 'hex'); + hash1.update(p2begin === p2end ? pblank : p2begin, 'hex'); + hash1 = hash1.digest('hex'); + var hash2 = hash.sha256(); + hash2.update(hash1, 'hex'); + hash2 = hash2.digest('hex'); + return hash2; +}; + +Block.prototype._buildMerkle = function buildMerkle() { + var merkleTree = []; + for (var i = 0; i < this.txs.length; i++) { + merkleTree.push(this.txs[i].hash('hex')); + } + var j = 0; + for (var size = this.txs.length; size > 1; size = ((size + 1) / 2) | 0) { + for (var i = 0; i < size; i += 2) { + var i2 = Math.min(i + 1, size - 1); + merkleTree.push( + this._phash(merkleTree[j+i], merkleTree[j+i+1], + merkleTree[j+i2], merkleTree[j+i2+1])); + } + j += size; + } + return merkleTree; +}; + +Block.prototype._checkBlock = function checkBlock() { + this.merkleTree = this._buildMerkle(); + return this.merkleTree[this.merkleTree.length-1] === this.merkleRoot; +}; From 44774e7c6b8bc155a084963c4f365667172198fe Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 May 2014 23:10:29 -0500 Subject: [PATCH 04/15] block: follow the behavior of bitcoind's CheckBlock(). --- lib/bcoin/block.js | 68 +++++++++++++++++++++++++++++++++ lib/bcoin/protocol/constants.js | 6 +++ 2 files changed, 74 insertions(+) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 40435029..ecafb236 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -190,7 +190,75 @@ Block.prototype._buildMerkle = function buildMerkle() { return merkleTree; }; +// This mimics the behavior of CheckBlockHeader() +// and CheckBlock() in bitcoin/src/main.cpp. Block.prototype._checkBlock = function checkBlock() { + // Check proof of work matches claimed amount + if (!utils.testTarget(this.bits, this.hash())) { + return false; + } + + // Check timestamp + if (+new Date(this.ts) > Date.now() + 2 * 60 * 60 * 1000) { + return false; + } + + // Size of all txs cant be bigger than MAX_BLOCK_SIZE + if (this.txs.length > bcoin.protocol.constants.block.maxSize) { + return false; + } + + // First TX must be a coinbase + if (this.txs[0].inputs.length !== 1 || +this.txs[0].inputs[0].out.hash !== 0) { + return false; + } + + // The rest of the txs must not be coinbases + for (var i = 1; i < this.txs.length; i++) { + if (this.txs[i].inputs.length === 1 && +this.txs[i].inputs[0].out.hash === 0) { + return false; + } + } + + // Check transactions + // TODO: + // for (var i = 0; i < this.txs.length; i++) { + // if (!this.txs[i].verify()) { + // return false; + // } + // } + + // Build MerkleTree this.merkleTree = this._buildMerkle(); + + // Check for duplicate tx ids + var unique = []; + for (var i = 0; i < this.txs.length; i++) { + if (!~unique.indexOf(this.txs[i].hash('hex'))) { + unique.push(this.txs[i].hash('hex')); + } + } + if (unique.length !== this.txs.length) { + return false; + } + + // Check to make sure block does not have more opcodes than MAX_BLOCK_SIGOPS + var sigops = 0; + // TODO: + // for (var i = 0; this.txs.length; i++) { + // for (var j = 0; j < this.txs.inputs.length; j++) { + // var script = this.txs.inputs[j].script; + // sigops += countSigops(script); + // } + // for (var j = 0; j < this.txs.outputs.length; j++) { + // var script = this.txs.outputs[j].script; + // sigops += countSigops(script); + // } + // } + if (sigops > bcoin.protocol.constants.block.maxSigops) { + return false; + } + + // Check merkle root return this.merkleTree[this.merkleTree.length-1] === this.merkleRoot; }; diff --git a/lib/bcoin/protocol/constants.js b/lib/bcoin/protocol/constants.js index a3be0e7b..0842b379 100644 --- a/lib/bcoin/protocol/constants.js +++ b/lib/bcoin/protocol/constants.js @@ -147,3 +147,9 @@ exports.hashType = { single: 3, anyonecaypay: 0x80 }; + +exports.block = { + maxSize: 1000000, + maxSigops: 1000000 / 50, + maxOrphanTx: 1000000 / 100 +}; From e3e324441b0adc3e1e4e7814e5eb6848683d3e6d Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 May 2014 23:13:16 -0500 Subject: [PATCH 05/15] block: improve performance of duplicate tx check. --- lib/bcoin/block.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index ecafb236..c21d16cb 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -232,14 +232,11 @@ Block.prototype._checkBlock = function checkBlock() { this.merkleTree = this._buildMerkle(); // Check for duplicate tx ids - var unique = []; + var unique = {}; for (var i = 0; i < this.txs.length; i++) { - if (!~unique.indexOf(this.txs[i].hash('hex'))) { - unique.push(this.txs[i].hash('hex')); - } - } - if (unique.length !== this.txs.length) { - return false; + var hash = this.txs[i].hash('hex'); + if (unique[hash]) return false; + unique[hash] = true; } // Check to make sure block does not have more opcodes than MAX_BLOCK_SIGOPS From 60a9e556f89f8f295153ac76f0ae7859eb110457 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Fri, 23 May 2014 23:26:47 -0500 Subject: [PATCH 06/15] framer: frame regular blocks with transactions correctly. --- lib/bcoin/protocol/framer.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index d75b80c0..1f9ca4ff 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -303,11 +303,11 @@ Framer.block = function _block(block, type) { assert.equal(off, 76); off += writeU32(p, block.nonce, off); - // txn_count (spec says this is a varint for some reason) assert.equal(off, 80); - off += writeU32(p, block.totalTX, off); if (type === 'merkleblock') { + // txn_count + off += writeU32(p, block.totalTX, off); // hash count assert.equal(off, 84); off += varint(p, block.hashes.length, off); @@ -323,6 +323,15 @@ Framer.block = function _block(block, type) { block.flags.forEach(function(flag) { p[off++] = flag; }); + } else if (type === 'block') { + // txn_count + off += varint(p, block.totalTX, off); + // txs + block.txs.forEach(function(tx) { + tx._raw.forEach(function(ch) { + p[off++] = ch; + }); + }); } return p; From 2d7599d2d3bd043dd71de0d5551cda648908047f Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 24 May 2014 01:19:32 -0500 Subject: [PATCH 07/15] block: use utils.dsha256 instead of hash.js for merkle tree building. --- lib/bcoin/block.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index c21d16cb..451cb66a 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -1,5 +1,4 @@ var bcoin = require('../bcoin'); -var hash = require('hash.js'); var utils = bcoin.utils; function Block(data, subtype) { @@ -160,18 +159,6 @@ Block.fromJSON = function fromJSON(json) { return block; }; -Block.prototype._phash = function phash(p1begin, p1end, p2begin, p2end) { - var pblank = ''; - var hash1 = hash.sha256(); - hash1.update(p1begin === p1end ? pblank : p1begin, 'hex'); - hash1.update(p2begin === p2end ? pblank : p2begin, 'hex'); - hash1 = hash1.digest('hex'); - var hash2 = hash.sha256(); - hash2.update(hash1, 'hex'); - hash2 = hash2.digest('hex'); - return hash2; -}; - Block.prototype._buildMerkle = function buildMerkle() { var merkleTree = []; for (var i = 0; i < this.txs.length; i++) { @@ -181,9 +168,8 @@ Block.prototype._buildMerkle = function buildMerkle() { for (var size = this.txs.length; size > 1; size = ((size + 1) / 2) | 0) { for (var i = 0; i < size; i += 2) { var i2 = Math.min(i + 1, size - 1); - merkleTree.push( - this._phash(merkleTree[j+i], merkleTree[j+i+1], - merkleTree[j+i2], merkleTree[j+i2+1])); + var hash = utils.dsha256(merkleTree[j+i] + merkleTree[j+i2], 'hex'); + merkleTree.push(utils.toHex(hash)); } j += size; } From c1fbab35e1a949b829721fe5a14d250f474188c6 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 24 May 2014 13:44:10 -0500 Subject: [PATCH 08/15] block: remove some unused code from checkBlock. --- lib/bcoin/block.js | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 451cb66a..ac5adda1 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -206,14 +206,6 @@ Block.prototype._checkBlock = function checkBlock() { } } - // Check transactions - // TODO: - // for (var i = 0; i < this.txs.length; i++) { - // if (!this.txs[i].verify()) { - // return false; - // } - // } - // Build MerkleTree this.merkleTree = this._buildMerkle(); @@ -225,23 +217,6 @@ Block.prototype._checkBlock = function checkBlock() { unique[hash] = true; } - // Check to make sure block does not have more opcodes than MAX_BLOCK_SIGOPS - var sigops = 0; - // TODO: - // for (var i = 0; this.txs.length; i++) { - // for (var j = 0; j < this.txs.inputs.length; j++) { - // var script = this.txs.inputs[j].script; - // sigops += countSigops(script); - // } - // for (var j = 0; j < this.txs.outputs.length; j++) { - // var script = this.txs.outputs[j].script; - // sigops += countSigops(script); - // } - // } - if (sigops > bcoin.protocol.constants.block.maxSigops) { - return false; - } - // Check merkle root return this.merkleTree[this.merkleTree.length-1] === this.merkleRoot; }; From 1052b7361cb6aaef91a9ad5ca470ff29a4c05023 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 24 May 2014 18:05:20 -0500 Subject: [PATCH 09/15] block: fix timestamp check in checkBlock. --- lib/bcoin/block.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index ac5adda1..2460df32 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -185,7 +185,7 @@ Block.prototype._checkBlock = function checkBlock() { } // Check timestamp - if (+new Date(this.ts) > Date.now() + 2 * 60 * 60 * 1000) { + if (this.ts > (Date.now() + 2 * 60 * 60) / 1000) { return false; } From 8546cc7e33344b70de2c1d34feee71094f00f792 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sat, 24 May 2014 18:06:52 -0500 Subject: [PATCH 10/15] block: fix timestamp check...again. --- lib/bcoin/block.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 2460df32..ad581d40 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -185,7 +185,7 @@ Block.prototype._checkBlock = function checkBlock() { } // Check timestamp - if (this.ts > (Date.now() + 2 * 60 * 60) / 1000) { + if (this.ts > (Date.now() / 1000) + 2 * 60 * 60) { return false; } From 6d2c1bd9f13ba284932f99726462a78f5916289d Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sun, 25 May 2014 08:02:33 -0500 Subject: [PATCH 11/15] framer: fix undefined var typo. --- lib/bcoin/protocol/framer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bcoin/protocol/framer.js b/lib/bcoin/protocol/framer.js index 1f9ca4ff..4970e645 100644 --- a/lib/bcoin/protocol/framer.js +++ b/lib/bcoin/protocol/framer.js @@ -128,7 +128,7 @@ function varint(arr, value, off) { arr[off + 4] = value >>> 24; return 5; } else { - p[off] = 0xff; + arr[off] = 0xff; utils.writeU64(arr, value, off + 1); return 9; } From 024350dbe4222a7ee69d1eaacd81433f9024296d Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 26 May 2014 04:03:23 -0500 Subject: [PATCH 12/15] peer/pool: improve handleInv. improve addPeer. --- lib/bcoin/peer.js | 8 +++++--- lib/bcoin/pool.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index a30d8ea5..1368e938 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -419,9 +419,11 @@ Peer.prototype._handleInv = function handleInv(items) { this.emit('blocks', blocks); if (this.options.satoshi) { - this.getData(items.filter(function(item) { - return item.type === 'block'; - })); + if (txs.length) + this.emit('txs', txs.map(function(tx) { + return tx.hash; + })); + this.getData(items); return; } diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index ab26a657..f012700d 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -297,7 +297,7 @@ Pool.prototype._addPeer = function _addPeer(backoff) { if (this.options.satoshi) { peer.on('block', function(block) { - self.emit('block', block, peer); + peer.emit('merkleblock', block); }); } From a3b923ae762acee0fcf2b52606dde8c29a26a95f Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 26 May 2014 04:33:36 -0500 Subject: [PATCH 13/15] peer: have updateWatch getblocks instead of filterload for the satoshi option. --- lib/bcoin/peer.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index 1368e938..7bc7240e 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -161,7 +161,19 @@ Peer.prototype.broadcast = function broadcast(items) { }; Peer.prototype.updateWatch = function updateWatch() { - if (this.options.satoshi) return; + if (this.options.satoshi) { + if (this.ack) { + var self = this; + if (this.pool.block.lastHash) + this.loadBlocks([ self.pool.block.lastHash ], 0); + else + this.pool.chain.getLast(function(hash) { + self.loadBlocks([ hash ], 0); + }); + } + return; + } + if (this.ack) this._write(this.framer.filterLoad(this.bloom, 'none')); }; From 7e38e4de7c35415d976ea555b14b9e8bc47bb712 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 26 May 2014 12:43:41 -0500 Subject: [PATCH 14/15] pool: change pool.options.satoshi to pool.options.relay. --- lib/bcoin/peer.js | 4 ++-- lib/bcoin/pool.js | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index 7bc7240e..cc36a162 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -161,7 +161,7 @@ Peer.prototype.broadcast = function broadcast(items) { }; Peer.prototype.updateWatch = function updateWatch() { - if (this.options.satoshi) { + if (!this.pool.options.relay) { if (this.ack) { var self = this; if (this.pool.block.lastHash) @@ -430,7 +430,7 @@ Peer.prototype._handleInv = function handleInv(items) { }); this.emit('blocks', blocks); - if (this.options.satoshi) { + if (!this.pool.options.relay) { if (txs.length) this.emit('txs', txs.map(function(tx) { return tx.hash; diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index f012700d..b41aa8e5 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -14,6 +14,7 @@ function Pool(options) { this.options = options || {}; this.storage = this.options.storage; + this.options.relay = this.options.relay !== false; this.destroyed = false; this.size = options.size || 32; this.parallel = options.parallel || 2000; @@ -105,8 +106,7 @@ Pool.prototype._addLoader = function _addLoader() { return; var peer = new bcoin.peer(this, this.createConnection, { - backoff: 750 * Math.random(), - satoshi: this.options.satoshi + backoff: 750 * Math.random() }); this.peers.load = peer; @@ -243,8 +243,7 @@ Pool.prototype._addPeer = function _addPeer(backoff) { return; var peer = new bcoin.peer(this, this.createConnection, { - backoff: backoff, - satoshi: this.options.satoshi + backoff: backoff }); this.peers.pending.push(peer); @@ -295,7 +294,7 @@ Pool.prototype._addPeer = function _addPeer(backoff) { self.emit('block', block, peer); }); - if (this.options.satoshi) { + if (!this.options.relay) { peer.on('block', function(block) { peer.emit('merkleblock', block); }); From 1b88b355acab203519cafa30de4a2ee2c1d9b2f4 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 26 May 2014 12:46:04 -0500 Subject: [PATCH 15/15] chain: add a cacheLimit option to chain. --- lib/bcoin/chain.js | 7 ++++--- lib/bcoin/pool.js | 9 +++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index db40ab22..88551ecc 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -17,6 +17,7 @@ function Chain(options) { this.prefix = 'bt/chain/'; this.storage = this.options.storage; this.strict = this.options.strict || false; + this.cacheLimit = this.options.cacheLimit || 2000; this.block = { list: [], @@ -256,12 +257,12 @@ Chain.prototype.add = function add(block) { }; Chain.prototype._compress = function compress() { - // Keep at least 1000 blocks and at most 2000 - if (this.block.list.length < 2000) + // Keep at least 1000 blocks and at most 2000 by default + if (this.block.list.length < this.cacheLimit) return; // Bloom filter rebuilt is needed - this.block.list = this.block.list.slice(-1000); + this.block.list = this.block.list.slice(-(this.cacheLimit / 2 | 0)); this.block.bloom.reset(); for (var i = 0; i < this.block.list.length; i++) diff --git a/lib/bcoin/pool.js b/lib/bcoin/pool.js index b41aa8e5..a21185c9 100644 --- a/lib/bcoin/pool.js +++ b/lib/bcoin/pool.js @@ -13,8 +13,8 @@ function Pool(options) { EventEmitter.call(this); this.options = options || {}; - this.storage = this.options.storage; this.options.relay = this.options.relay !== false; + this.storage = this.options.storage; this.destroyed = false; this.size = options.size || 32; this.parallel = options.parallel || 2000; @@ -36,7 +36,12 @@ function Pool(options) { }; this.maxRetries = options.maxRetries || 42; this.requestTimeout = options.requestTimeout || 10000; - this.chain = new bcoin.chain({ storage: this.storage }); + this.chain = new bcoin.chain({ + storage: this.storage, + // Since regular blocks contain transactions and full merkle + // trees, it's risky to cache 2000 blocks. Let's do 100. + cacheLimit: !this.options.relay ? 100 : null + }); this.watchMap = {}; this.bloom = new bcoin.bloom(8 * 1024, 10,