Skip to content

Commit 47084e0

Browse files
committed
feat: support want-have & want-block in engine
1 parent bdab029 commit 47084e0

File tree

14 files changed

+871
-216
lines changed

14 files changed

+871
-216
lines changed

src/decision-engine/index.js

Lines changed: 207 additions & 114 deletions
Large diffs are not rendered by default.

src/decision-engine/ledger.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ class Ledger {
2828
this.accounting.bytesRecv += n
2929
}
3030

31-
wants (cid, priority) {
32-
this.wantlist.add(cid, priority)
31+
wants (cid, priority, wantType) {
32+
this.wantlist.add(cid, priority, wantType)
3333
}
3434

3535
cancelWant (cid) {

src/index.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ class Bitswap {
6666

6767
// handle messages received through the network
6868
async _receiveMessage (peerId, incoming) {
69+
// TODO: Need to add block to blockstore _before_ calling engine.messageReceived
6970
try {
7071
await this.engine.messageReceived(peerId, incoming)
7172
} catch (err) {
72-
// Only logging the issue to process as much as possible
73-
// of the message. Currently `messageReceived` does not
73+
// Log instead of throwing an error so as to process as much as
74+
// possible of the message. Currently `messageReceived` does not
7475
// throw any errors, but this could change in the future.
7576
this._log('failed to receive message', incoming)
7677
}
@@ -279,22 +280,28 @@ class Bitswap {
279280
async putMany (blocks) { // eslint-disable-line require-await
280281
const self = this
281282

282-
return this.blockstore.putMany(async function * () {
283+
// Add any new blocks to the blockstore
284+
const newBlocks = []
285+
await this.blockstore.putMany(async function * () {
283286
for await (const block of blocks) {
284287
if (await self.blockstore.has(block.cid)) {
285288
continue
286289
}
287290

288291
yield block
289-
290-
self.notifications.hasBlock(block)
291-
self.engine.receivedBlocks([block.cid])
292-
// Note: Don't wait for provide to finish before returning
293-
self.network.provide(block.cid).catch((err) => {
294-
self._log.error('Failed to provide: %s', err.message)
295-
})
292+
newBlocks.push(block)
296293
}
297294
}())
295+
296+
// Notify listeners that we have received the new blocks
297+
for (const block of newBlocks) {
298+
self.notifications.hasBlock(block)
299+
self.engine.receivedBlocks([block])
300+
// Note: Don't wait for provide to finish before returning
301+
self.network.provide(block.cid).catch((err) => {
302+
self._log.error('Failed to provide: %s', err.message)
303+
})
304+
}
298305
}
299306

300307
/**

src/types/message/entry.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
const WantlistEntry = require('../wantlist').Entry
44

55
module.exports = class BitswapMessageEntry {
6-
constructor (cid, priority, cancel) {
7-
this.entry = new WantlistEntry(cid, priority)
6+
constructor (cid, priority, wantType, cancel, sendDontHave) {
7+
this.entry = new WantlistEntry(cid, priority, wantType)
88
this.cancel = Boolean(cancel)
9+
this.sendDontHave = Boolean(sendDontHave)
910
}
1011

1112
get cid () {
@@ -24,13 +25,23 @@ module.exports = class BitswapMessageEntry {
2425
this.entry.priority = val
2526
}
2627

28+
get wantType () {
29+
return this.entry.wantType
30+
}
31+
32+
set wantType (val) {
33+
this.entry.wantType = val
34+
}
35+
2736
get [Symbol.toStringTag] () {
2837
const cidStr = this.cid.toString('base58btc')
2938
return `BitswapMessageEntry ${cidStr} <cancel: ${this.cancel}, priority: ${this.priority}>`
3039
}
3140

3241
equals (other) {
3342
return (this.cancel === other.cancel) &&
43+
(this.sendDontHave === other.sendDontHave) &&
44+
(this.wantType === other.wantType) &&
3445
this.entry.equals(other.entry)
3546
}
3647
}

src/types/message/index.js

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,43 @@ class BitswapMessage {
1515
this.full = full
1616
this.wantlist = new Map()
1717
this.blocks = new Map()
18+
this.blockPresences = new Map()
1819
this.pendingBytes = 0
1920
}
2021

2122
get empty () {
2223
return this.blocks.size === 0 &&
23-
this.wantlist.size === 0
24+
this.wantlist.size === 0 &&
25+
this.blockPresences.size === 0
2426
}
2527

26-
addEntry (cid, priority, cancel) {
28+
addEntry (cid, priority, wantType, cancel, sendDontHave) {
29+
if (wantType == null) {
30+
wantType = BitswapMessage.WantType.Block
31+
}
2732
const cidStr = cid.toString('base58btc')
2833

2934
const entry = this.wantlist.get(cidStr)
3035

3136
if (entry) {
32-
entry.priority = priority
33-
entry.cancel = Boolean(cancel)
37+
// Only change priority if want is of the same type
38+
if (entry.wantType === wantType) {
39+
entry.priority = priority
40+
}
41+
// Only change from "dont cancel" to "do cancel"
42+
if (cancel) {
43+
entry.cancel = Boolean(cancel)
44+
}
45+
// Only change from "dont send" to "do send" DONT_HAVE
46+
if (sendDontHave) {
47+
entry.sendDontHave = Boolean(sendDontHave)
48+
}
49+
// want-block overrides existing want-have
50+
if (wantType === BitswapMessage.WantType.Block && entry.wantType === BitswapMessage.WantType.Have) {
51+
entry.wantType = wantType
52+
}
3453
} else {
35-
this.wantlist.set(cidStr, new Entry(cid, priority, cancel))
54+
this.wantlist.set(cidStr, new Entry(cid, priority, wantType, cancel, sendDontHave))
3655
}
3756
}
3857

@@ -41,10 +60,24 @@ class BitswapMessage {
4160
this.blocks.set(cidStr, block)
4261
}
4362

63+
addHave (cid) {
64+
const cidStr = cid.toString('base58btc')
65+
if (!this.blockPresences.has(cidStr)) {
66+
this.blockPresences.set(cidStr, BitswapMessage.BlockPresenceType.Have)
67+
}
68+
}
69+
70+
addDontHave (cid) {
71+
const cidStr = cid.toString('base58btc')
72+
if (!this.blockPresences.has(cidStr)) {
73+
this.blockPresences.set(cidStr, BitswapMessage.BlockPresenceType.DontHave)
74+
}
75+
}
76+
4477
cancel (cid) {
4578
const cidStr = cid.toString('base58btc')
4679
this.wantlist.delete(cidStr)
47-
this.addEntry(cid, 0, true)
80+
this.addEntry(cid, 0, BitswapMessage.WantType.Block, true, false)
4881
}
4982

5083
setPendingBytes (size) {
@@ -106,6 +139,13 @@ class BitswapMessage {
106139
})
107140
})
108141

142+
for (const [cidStr, bpType] of this.blockPresences) {
143+
msg.blockPresences.push({
144+
cid: new CID(cidStr).buffer,
145+
type: bpType
146+
})
147+
}
148+
109149
if (this.pendingBytes > 0) {
110150
msg.pendingBytes = this.pendingBytes
111151
}
@@ -115,8 +155,10 @@ class BitswapMessage {
115155

116156
equals (other) {
117157
if (this.full !== other.full ||
158+
this.pendingBytes !== other.pendingBytes ||
118159
!isMapEqual(this.wantlist, other.wantlist) ||
119-
!isMapEqual(this.blocks, other.blocks)
160+
!isMapEqual(this.blocks, other.blocks) ||
161+
!isMapEqual(this.blockPresences, other.blockPresences)
120162
) {
121163
return false
122164
}
@@ -141,7 +183,7 @@ BitswapMessage.deserialize = async (raw) => {
141183
decoded.wantlist.entries.forEach((entry) => {
142184
// note: entry.block is the CID here
143185
const cid = new CID(entry.block)
144-
msg.addEntry(cid, entry.priority, entry.cancel)
186+
msg.addEntry(cid, entry.priority, entry.wantType, entry.cancel, entry.sendDontHave)
145187
})
146188
}
147189

@@ -178,5 +220,18 @@ BitswapMessage.deserialize = async (raw) => {
178220
return msg
179221
}
180222

223+
BitswapMessage.blockPresenceSize = (cid) => {
224+
// It doesn't really matter if this is not exactly right
225+
return cid.buffer.length + 1
226+
}
227+
181228
BitswapMessage.Entry = Entry
229+
BitswapMessage.WantType = {
230+
Block: pbm.Message.Wantlist.WantType.Block,
231+
Have: pbm.Message.Wantlist.WantType.Have
232+
}
233+
BitswapMessage.BlockPresenceType = {
234+
Have: pbm.Message.BlockPresenceType.Have,
235+
DontHave: pbm.Message.BlockPresenceType.DontHave
236+
}
182237
module.exports = BitswapMessage

src/types/wantlist/entry.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
'use strict'
22

33
class WantListEntry {
4-
constructor (cid, priority) {
4+
constructor (cid, priority, wantType) {
55
// Keep track of how many requests we have for this key
66
this._refCounter = 1
77

88
this.cid = cid
99
this.priority = priority || 1
10+
this.wantType = wantType
1011
}
1112

1213
inc () {
@@ -30,7 +31,8 @@ class WantListEntry {
3031
equals (other) {
3132
return (this._refCounter === other._refCounter) &&
3233
this.cid.equals(other.cid) &&
33-
this.priority === other.priority
34+
this.priority === other.priority &&
35+
this.wantType === other.wantType
3436
}
3537
}
3638

src/types/wantlist/index.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,23 @@ class Wantlist {
1313
return this.set.size
1414
}
1515

16-
add (cid, priority) {
16+
add (cid, priority, wantType) {
17+
// Have to import here to avoid circular reference
18+
const Message = require('../message')
19+
1720
const cidStr = cid.toString('base58btc')
1821
const entry = this.set.get(cidStr)
1922

2023
if (entry) {
2124
entry.inc()
2225
entry.priority = priority
26+
27+
// We can only overwrite want-have with want-block
28+
if (entry.wantType === Message.WantType.Have && wantType === Message.WantType.Block) {
29+
entry.wantType = wantType
30+
}
2331
} else {
24-
this.set.set(cidStr, new Entry(cid, priority))
32+
this.set.set(cidStr, new Entry(cid, priority, wantType))
2533
if (this._stats) {
2634
this._stats.push(null, 'wantListSize', 1)
2735
}

src/want-manager/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module.exports = class WantManager {
2020

2121
_addEntries (cids, cancel, force) {
2222
const entries = cids.map((cid, i) => {
23-
return new Message.Entry(cid, CONSTANTS.kMaxPriority - i, cancel)
23+
return new Message.Entry(cid, CONSTANTS.kMaxPriority - i, Message.WantType.Block, cancel)
2424
})
2525

2626
entries.forEach((e) => {

test/bitswap-mock-internals.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ describe('bitswap with mocks', function () {
7979

8080
const msg = new Message(false)
8181

82-
msg.addEntry(b1.cid, 1, false)
83-
msg.addEntry(b2.cid, 1, false)
82+
msg.addEntry(b1.cid, 1)
83+
msg.addEntry(b2.cid, 1)
8484

8585
await bs._receiveMessage(other, msg)
8686

0 commit comments

Comments
 (0)