Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add @helia/bitswap with sessions #409

Merged
merged 34 commits into from
Apr 4, 2024

Conversation

achingbrain
Copy link
Member

@achingbrain achingbrain commented Jan 30, 2024

Adds a @helia/bitswap module with code ported from ipfs-bitswap and greatly simplified.

  • Supports sessions
  • Only supports bitswap 1.2.0
  • Uses libp2p's metrics system instead of a custom version
  • Uses Helia's routing instead of libp2p to take advantage of http delegated routers that return bitswap providers

@achingbrain achingbrain requested a review from a team as a code owner January 30, 2024 14:31
@achingbrain achingbrain changed the title feat: add block session support to @helia/interface feat: add @helia/bitswap with sessions Jan 30, 2024
@achingbrain achingbrain force-pushed the feat/add-bitswap-with-sessions branch 3 times, most recently from 3e547bb to 6e789da Compare February 5, 2024 17:34
There are no implementations yet but the usage pattern will be something
like:

```javascript
// unixfs cat command
export async function * cat (cid: CID, blockstore: Blocks, options: Partial<CatOptions> = {}): AsyncIterable<Uint8Array> {
  // create a session for the CID if support is available
  const blocks = await (blockstore.createSession != null ? blockstore.createSession(cid) : blockstore)
  const opts: CatOptions = mergeOptions(defaultOptions, options)

  // resolve and export using the session, if created, otherwise fall back to regular blockstore access
  const resolved = await resolve(cid, opts.path, blocks, opts)
  const result = await exporter(resolved.cid, blocks, opts)

  if (result.type !== 'file' && result.type !== 'raw') {
    throw new NotAFileError()
  }

  if (result.content == null) {
    throw new NoContentError()
  }

  yield * result.content(opts)
}
```
@achingbrain achingbrain force-pushed the feat/add-sessions-to-interface branch from b1c5fe9 to 32713ab Compare February 6, 2024 07:59
Adds a `@helia/bitswap` module with code ported from `ipfs-bitswap`
and greatly simplified.

- Supports sessions
- Only supports bitswap 1.2.0
- Uses libp2p's metrics system instead of a custom version
@achingbrain achingbrain force-pushed the feat/add-bitswap-with-sessions branch from 6e789da to 73ab5f9 Compare February 6, 2024 08:19
Copy link
Member

@SgtPooki SgtPooki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14/35 files reviewed. I'm going to have to come back to this one, but it may be more valuable for someone like @lidel or @aschmahmann to peek at this.

packages/bitswap/README.md Show resolved Hide resolved
packages/bitswap/src/bitswap.ts Outdated Show resolved Hide resolved
@@ -0,0 +1,11 @@
export const BITSWAP_120 = '/ipfs/bitswap/1.2.0'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const BITSWAP_120 = '/ipfs/bitswap/1.2.0'
export const BITSWAP_PROTOCOL = '/ipfs/bitswap/1.2.0'

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah? It's Bitswap 1.2.0, plain Bitswap might be 1.0.0?

}

async retrieve (cid: CID, options: BlockRetrievalOptions<BitswapWantBlockProgressEvents> = {}): Promise<Uint8Array> {
return this.bitswap.want(cid, options)
}

async createSession (root: CID, options?: CreateSessionOptions<BitswapWantBlockProgressEvents>): Promise<BlockBroker<BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this used anywhere yet?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been integrating it with helia-http-gateway, it seems to work!

packages/bitswap/src/index.ts Outdated Show resolved Hide resolved
packages/bitswap/src/bitswap.ts Outdated Show resolved Hide resolved
* JavaScript implementation of the Bitswap 'data exchange' protocol
* used by IPFS.
*/
export class Bitswap implements BitswapInterface {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to support provider filtering, or is that done in the routers?

Comment on lines +136 to +144
getWantlist (): WantListEntry[] {
return [...this.wantList.wants.values()]
.filter(entry => !entry.cancel)
.map(entry => ({
cid: entry.cid,
priority: entry.priority,
wantType: entry.wantType
}))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like knowledge of sessions that wantlists are associated with would be valuable, but this is my first time looking deeply at a bitswap protocol implementation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, it's something we could add for introspection later if we need it?

Comment on lines +82 to +83
return createBitswapSession({
wantList: this.wantList,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this associating the global wantlist to all sessions? do we want to do that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, cos we tell the wantlist that a given wants is a session want, the wantlist then keeps track of everything to make sure the right peers are sent the right wants, including upgrading the want from one type to another if the same block is wanted from different contexts (a session, another session, not a session, etc).

Comment on lines +48 to +49
// report stats to libp2p metrics
this.stats = new Stats(components)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we have a toggle for stats like libp2p?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If libp2p metrics aren't enabled everything's a no-op. I wouldn't add a toggle here since we could toggle it on for bitswap, but off for libp2p and then people would wonder why they aren't getting stats.

Base automatically changed from feat/add-sessions-to-interface to main April 4, 2024 10:27
@achingbrain achingbrain merged commit e582c63 into main Apr 4, 2024
18 checks passed
@achingbrain achingbrain deleted the feat/add-bitswap-with-sessions branch April 4, 2024 11:49
@achingbrain achingbrain mentioned this pull request Apr 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants