Skip to content

Commit dbe80cc

Browse files
committed
feat: new bitswap
1 parent 27fe1f7 commit dbe80cc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1989
-1514
lines changed

API.md

-82
This file was deleted.

README.md

+113-3
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,21 @@
3131
### npm
3232

3333
```sh
34-
> npm i ipfs-bitswap
34+
> npm install ipfs-bitswap --save
3535
```
3636

3737
### Use in Node.js
3838

3939
```js
40-
const bitswap = require('ipfs-bitswap')
40+
const Bitswap = require('ipfs-bitswap')
4141
```
4242

4343
### Use in a browser with browserify, webpack or any other bundler
4444

4545
The code published to npm that gets loaded on require is in fact a ES5 transpiled version with the right shims added. This means that you can require it and use with your favourite bundler without having to adjust asset management process.
4646

4747
```js
48-
const bitswap = require('ipfs-bitswap')
48+
const Bitswap = require('ipfs-bitswap')
4949
```
5050

5151
### Use in a browser using a script tag
@@ -62,6 +62,116 @@ Loading this module through a script tag will make the `IpfsBitswap` object avai
6262

6363
For the documentation see [API.md](API.md).
6464

65+
### API
66+
67+
#### `new Bitswap(libp2p, blockstore)`
68+
69+
- `libp2p: Libp2p`, instance of the local network stack.
70+
- `blockstore: Blockstore`, instance of the local database (`IpfsRepo.blockstore`)
71+
72+
Create a new instance.
73+
74+
#### `getStream(cid)`
75+
76+
- `cid: CID|Array`
77+
78+
Returns a source `pull-stream`. Values emitted are the received blocks.
79+
80+
Example:
81+
82+
```js
83+
// Single block
84+
pull(
85+
bitswap.getStream(cid),
86+
pull.collect((err, blocks) => {
87+
// blocks === [block]
88+
})
89+
)
90+
91+
// Many blocks
92+
pull(
93+
bitswap.getStream([cid1, cid2, cid3]),
94+
pull.collect((err, blocks) => {
95+
// blocks === [block1, block2, block3]
96+
})
97+
)
98+
```
99+
100+
> Note: This is safe guarded so that the network is not asked
101+
> for blocks that are in the local `datastore`.
102+
103+
#### `unwant(cids)`
104+
105+
- `cids: CID|[]CID`
106+
107+
Cancel previously requested keys, forcefully. That means they are removed from the
108+
wantlist independent of how many other resources requested these keys. Callbacks
109+
attached to `getBlock` are errored with `Error('manual unwant: key')`.
110+
111+
#### `cancelWants(cids)`
112+
113+
- `cid: CID|[]CID`
114+
115+
Cancel previously requested keys.
116+
117+
#### `putStream()`
118+
119+
Returns a duplex `pull-stream` that emits an object `{key: Multihash}` for every written block when it was stored.
120+
Objects passed into here should be of the form `{data: Buffer, key: Multihash}`
121+
122+
#### `put(blockAndCid, callback)`
123+
124+
- `blockAndKey: {data: Buffer, cid: CID}`
125+
- `callback: Function`
126+
127+
Announce that the current node now has the block containing `data`. This will store it
128+
in the local database and attempt to serve it to all peers that are known
129+
to have requested it. The callback is called when we are sure that the block
130+
is stored.
131+
132+
#### `wantlistForPeer(peerId)`
133+
134+
- `peerId: PeerId`
135+
136+
Get the wantlist for a given peer.
137+
138+
#### `stat()`
139+
140+
Get stats about about the current state of the bitswap instance.
141+
142+
## Development
143+
144+
### Structure
145+
146+
![](/img/architecture.png)
147+
148+
```sh
149+
» tree src
150+
src
151+
├── components
152+
│   ├── decision
153+
│   │   ├── engine.js
154+
│   │   ├── index.js
155+
│   │   ├── ledger.js
156+
│   │   ├── peer-request-queue.js
157+
│   │   └── pq.js
158+
│   ├── network # Handles peerSet and open new conns
159+
│   │   └── index.js
160+
│   └── want-manager # Keeps track of all blocks the peer wants (not the others which it is connected)
161+
│   ├── index.js
162+
│   └── msg-queue.js # Messages to send queue, one per peer
163+
├── constants.js
164+
├── index.js
165+
└── types
166+
├── message # (Type) message that is put in the wire
167+
│   ├── entry.js
168+
│   ├── index.js
169+
│   └── message.proto.js
170+
└── wantlist # (Type) track wanted blocks
171+
├── entry.js
172+
└── index.js
173+
```
174+
65175
## Contribute
66176

67177
Feel free to join in. All welcome. Open an [issue](https://github.com/ipfs/js-ipfs-bitswap/issues)!

benchmarks/index.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const Block = require('ipfs-block')
1111
const pull = require('pull-stream')
1212
const assert = require('assert')
1313
const crypto = require('crypto')
14+
const CID = require('cids')
1415

1516
const utils = require('../test/utils')
1617

@@ -54,6 +55,7 @@ function round (nodeArr, blockFactor, n, cb) {
5455
if (err) {
5556
return cb(err)
5657
}
58+
const cids = keys.map((k) => new CID(k))
5759
let d
5860
series([
5961
// put blockFactor amount of blocks per node
@@ -63,8 +65,8 @@ function round (nodeArr, blockFactor, n, cb) {
6365
const data = _.map(_.range(blockFactor), (j) => {
6466
const index = i * blockFactor + j
6567
return {
66-
data: blocks[index].data,
67-
key: keys[index]
68+
block: blocks[index],
69+
cid: cids[index]
6870
}
6971
})
7072
each(
@@ -80,7 +82,7 @@ function round (nodeArr, blockFactor, n, cb) {
8082
// fetch all blocks on every node
8183
(cb) => parallel(_.map(nodeArr, (node, i) => (callback) => {
8284
pull(
83-
node.bitswap.getStream(keys),
85+
node.bitswap.getStream(cids),
8486
pull.collect((err, res) => {
8587
if (err) {
8688
return callback(err)

benchmarks/put-get.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const assert = require('assert')
77
const pull = require('pull-stream')
88
const series = require('async/series')
99
const crypto = require('crypto')
10+
const CID = require('cids')
11+
1012
const utils = require('../test/utils')
1113

1214
const suite = new Benchmark.Suite('put-get')
@@ -64,7 +66,7 @@ function put (blocks, bs, callback) {
6466
if (err) {
6567
return cb(err)
6668
}
67-
cb(null, {key: key, data: b.data})
69+
cb(null, {cid: new CID(key), block: b})
6870
})
6971
}),
7072
bs.putStream(),
@@ -76,7 +78,7 @@ function get (blocks, bs, callback) {
7678
pull(
7779
pull.values(blocks),
7880
pull.asyncMap((b, cb) => b.key(cb)),
79-
pull.map((k) => bs.getStream(k)),
81+
pull.map((k) => bs.getStream(new CID(k))),
8082
pull.flatten(),
8183
pull.collect((err, res) => {
8284
if (err) {

img/architecture.monopic

4.18 KB
Binary file not shown.

img/architecture.png

101 KB
Loading

img/architecture.txt

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
┌────────────────────────────────────────────────────────────────────────────┐
3+
│ Bitswap API │
4+
└────────────────────────────────────────────────────────────────────────────┘
5+
│ ▲
6+
│register wants │yields the
7+
│and unwants │received
8+
│ │blocks
9+
│ │
10+
│ send block to other nodes┌───────────────────────────┐
11+
│ by adding them to their │ Decision Engine │
12+
│ buckets │ │
13+
│ ┌─────────◀├ ─ ─ ─ │
14+
│ │ │Ledger│ │
15+
│ │ └───────────────────────────┘
16+
│ │ ▲
17+
▼ │ │
18+
┌────────────────────┐ │ │
19+
│ │ │ │
20+
│ Want Manager │ │ │
21+
│ │ │ │
22+
├───────────┬──┬─────┘ │ │
23+
│my wantlist│ │ │ │
24+
└───────────┘ │update wantlist │ │
25+
│messages │ receive a block │
26+
└─────┬───────┬───────┤ │
27+
│ │ │ │
28+
▼ ▼ ▼ │
29+
┌───────┬───────┬───────┐ │
30+
│Message│Message│... │ │
31+
│Queue/ │Queue/ │ │ │
32+
│peer │peer │ │ │
33+
└───────┴───────┴───────┘ │
34+
│ │ │ │
35+
│ │ │ │
36+
│ │ │ │
37+
└───────┴───────┴─┐ │
38+
│ │
39+
│ │
40+
▼ │
41+
┌────────────────────────────────────────┐
42+
│ Network │
43+
└────────────────────────────────────────┘
44+
│ ▲ │ ▲
45+
▼ │ │ │
46+
┌─────────┐ ▼ │
47+
│Transform│ /ipfs/bitswap/1.1.0
48+
└─────────┘
49+
│ ▲
50+
▼ │
51+
/ipfs/bitswap/1.0.0

package.json

+6-5
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
},
3737
"homepage": "https://github.com/ipfs/js-ipfs-bitswap#readme",
3838
"devDependencies": {
39-
"aegir": "9.2.2",
39+
"aegir": "9.3.0",
4040
"benchmark": "^2.1.2",
4141
"buffer-loader": "0.0.1",
4242
"chai": "^3.5.0",
@@ -56,8 +56,8 @@
5656
},
5757
"dependencies": {
5858
"async": "^2.1.4",
59-
"cids": "^0.3.4",
60-
"debug": "^2.3.3",
59+
"cids": "^0.3.5",
60+
"debug": "^2.4.4",
6161
"heap": "^0.2.6",
6262
"ipfs-block": "^0.5.3",
6363
"lodash.debounce": "^4.0.8",
@@ -68,13 +68,14 @@
6868
"lodash.pullallwith": "^4.7.0",
6969
"lodash.uniqwith": "^4.5.0",
7070
"lodash.values": "^4.3.0",
71-
"multihashes": "^0.3.0",
71+
"multihashes": "^0.3.1",
7272
"protocol-buffers": "^3.2.1",
7373
"pull-defer": "^0.2.2",
7474
"pull-length-prefixed": "^1.2.0",
7575
"pull-paramap": "^1.2.1",
7676
"pull-pushable": "^2.0.1",
77-
"pull-stream": "^3.5.0"
77+
"pull-stream": "^3.5.0",
78+
"varint-decoder": "^0.1.1"
7879
},
7980
"contributors": [
8081
"David Dias <daviddias.p@gmail.com>",

0 commit comments

Comments
 (0)