diff --git a/package.json b/package.json index 1a3cbb1d..c8142f13 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "dirty-chai": "^2.0.1", "ipfs-repo": "~0.26.3", "libp2p": "~0.24.2", - "libp2p-kad-dht": "~0.14.8", + "libp2p-kad-dht": "~0.15.0", "libp2p-mplex": "~0.8.4", "libp2p-secio": "~0.11.1", "libp2p-tcp": "~0.13.0", diff --git a/src/index.js b/src/index.js index fddfac23..6cb299fd 100644 --- a/src/index.js +++ b/src/index.js @@ -87,28 +87,31 @@ class Bitswap { const blocks = Array.from(incoming.blocks.values()) // quickly send out cancels, reduces chances of duplicate block receives - const toCancel = blocks + const wanted = blocks .filter((b) => this.wm.wantlist.contains(b.cid)) .map((b) => b.cid) - this.wm.cancelWants(toCancel) + this.wm.cancelWants(wanted) each( blocks, - (b, cb) => this._handleReceivedBlock(peerId, b, cb), + (b, cb) => { + const wasWanted = wanted.includes(b.cid) + this._handleReceivedBlock(peerId, b, wasWanted, cb) + }, callback ) }) } - _handleReceivedBlock (peerId, block, callback) { + _handleReceivedBlock (peerId, block, wasWanted, callback) { this._log('received block') waterfall([ (cb) => this.blockstore.has(block.cid, cb), (has, cb) => { this._updateReceiveCounters(peerId.toB58String(), block, has) - if (has) { + if (has || !wasWanted) { return nextTick(cb) } diff --git a/test/bitswap-mock-internals.js b/test/bitswap-mock-internals.js index 24c39d92..51c179af 100644 --- a/test/bitswap-mock-internals.js +++ b/test/bitswap-mock-internals.js @@ -64,6 +64,8 @@ describe('bitswap with mocks', function () { const b1 = blocks[0] const b2 = blocks[1] + bs.wm.wantBlocks([b1.cid, b2.cid]) + const msg = new Message(false) msg.addBlock(b1) msg.addBlock(b2) @@ -140,7 +142,7 @@ describe('bitswap with mocks', function () { map(_.range(5), (i, cb) => { const msg = new Message(false) msg.addBlock(blocks[i]) - msg.addBlock(blocks[5 + 1]) + msg.addBlock(blocks[i + 5]) cb(null, msg) }, (err, messages) => { expect(err).to.not.exist() @@ -148,6 +150,10 @@ describe('bitswap with mocks', function () { eachSeries(others, (other, cb) => { const msg = messages[i] i++ + + const cids = [...msg.blocks.values()].map(b => b.cid) + bs.wm.wantBlocks(cids) + bs._receiveMessage(other, msg, (err) => { expect(err).to.not.exist() storeHasBlocks(msg, repo.blocks, cb) @@ -157,6 +163,52 @@ describe('bitswap with mocks', function () { } }) }) + + it('ignore unwanted blocks', (done) => { + const bs = new Bitswap(mockLibp2pNode(), repo.blocks) + bs.start((err) => { + expect(err).to.not.exist() + + const other = ids[1] + + const b1 = blocks[2] + const b2 = blocks[3] + const b3 = blocks[4] + + bs.wm.wantBlocks([b2.cid]) + + const msg = new Message(false) + msg.addBlock(b1) + msg.addBlock(b2) + msg.addBlock(b3) + + bs._receiveMessage(other, msg, (err) => { + expect(err).to.not.exist() + + map([b1.cid, b2.cid, b3.cid], (cid, cb) => repo.blocks.has(cid, cb), (err, res) => { + expect(err).to.not.exist() + + expect(res).to.eql([false, true, false]) + + const ledger = bs.ledgerForPeer(other) + expect(ledger.peer).to.equal(other.toPrint()) + expect(ledger.value).to.equal(0) + + // Note: Keeping track of received bytes for blocks affects the + // debt ratio, which in future may be used as part of fairness + // algorithms when prioritizing who to send blocks to. + // So we may want to revise whether we record received blocks from + // a peer even if we didn't ask for the blocks. + // For now keeping it liks this to match the go implementation: + // https://github.com/ipfs/go-bitswap/blob/acc22c283722c15436120ae522c8e8021d0b06f8/bitswap.go#L293 + expect(ledger.sent).to.equal(0) + expect(ledger.recv).to.equal(144) + expect(ledger.exchanged).to.equal(3) + done() + }) + }) + }) + }) }) describe('get', () => { diff --git a/test/bitswap-stats.js b/test/bitswap-stats.js index 73c27a48..5e0a8521 100644 --- a/test/bitswap-stats.js +++ b/test/bitswap-stats.js @@ -87,6 +87,7 @@ describe('bitswap stats', () => { statsComputeThrottleTimeout: 500 // fast update interval for tests })) bs = bitswaps[0] + bs.wm.wantBlocks(blocks.map(b => b.cid)) }) // start the first bitswap