Skip to content

Commit

Permalink
docs: cleanup Bitswap
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Sep 19, 2023
1 parent 0b49dfb commit ae158cb
Showing 1 changed file with 114 additions and 68 deletions.
182 changes: 114 additions & 68 deletions src/architecture/bitswap.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,102 @@
# ![Status: WIP](https://img.shields.io/badge/status-wip-orange.svg?style=flat-square) Bitswap
---
title: Bitswap
description: >
Bitswap is a data exchange protocol for sending and receiving content addressed
blocks of data. It attempts to acquire blocks from the network that have been
requested by the client, and also send blocks to others who want them.
date: 2022-08-26
maturity: reliable
editors:
- name: Adin Schmahmann
github: aschmahmann
affiliation:
name: Protocol Labs
url: https://protocol.ai/
- name: David Dias
github: daviddias
affiliation:
name: Protocol Labs
url: https://protocol.ai/
- name: Jeromy Johnson
github: whyrusleeping
affiliation:
name: Protocol Labs
url: https://protocol.ai/
- name: Juan Benet
github: jbenet
affiliation:
name: Protocol Labs
url: https://protocol.ai/
tags: ['architecture']
order: 1
---

Bitswap is a data exchange protocol for sending and receiving content addressed blocks of data.
Bitswap has two primary jobs:

**Author(s)**:
- Adin Schmahmann
- David Dias
- Jeromy Johnson
- Juan Benet

**Maintainer(s)**:

* * *

**Abstract**

Bitswap is a data exchange protocol for sending and receiving content addressed blocks of data. Bitswap has two primary jobs:
1. Attempt to acquire blocks from the network that have been requested by the client.
2. Send blocks in its possession to other peers who want them.

## Organization of this document

- [Introduction](#introduction)
- [Bitswap Protocol Versions](#bitswap-protocol-versions)
- [Bitswap 1.0.0](#bitswap-100)
- [Bitswap 1.1.0](#bitswap-110)
- [Bitswap 1.2.0](#bitswap-120)
- [Implementations](#implementations)

## Introduction

Bitswap is a message-based protocol, as opposed to request-response. All messages contain wantlists, and/or blocks.
Upon receiving a wantlist, a Bitswap server should eventually process and respond to the requester with either information about the block or the block itself.
Upon receiving blocks, the client should send a `Cancel` notification to peers that have asked for the data, signifying that the client no longer wants the block.
Bitswap is a message-based protocol, as opposed to request-response. All messages
contain wantlists, and/or blocks. Upon receiving a wantlist, a Bitswap server SHOULD
eventually process and respond to the requester with either information about the
block or the block itself. Upon receiving blocks, the client SHOULD send a `Cancel`
notification to peers that have asked for the data, signifying that the client no
longer wants the block.

Bitswap aims to be a simple protocol, so that implementations can balance aspects such as throughput, latency, fairness, memory usage, etc. for their specific requirements.
Bitswap aims to be a simple protocol, so that implementations can balance aspects
such as throughput, latency, fairness, memory usage, etc. for their specific
requirements.

## Bitswap Protocol Versions

There are multiple Bitswap versions and more may evolve over time. We give brief overviews as to the changes behind each protocol version.
There are multiple Bitswap versions and more may evolve over time. We give brief
overviews as to the changes behind each protocol version:

- `/ipfs/bitswap/1.0.0` - Initial version
- `/ipfs/bitswap/1.1.0` - Support CIDv1
- `/ipfs/bitswap/1.2.0` - Support Wantlist Have's and Have/DontHave responses
- `/ipfs/bitswap/1.1.0` - Support [CIDv1](https://docs.ipfs.io/concepts/glossary/#cid-v1)
- `/ipfs/bitswap/1.2.0` - Support Wantlist `Have`'s and `Have`/`DontHave` responses

## Block Sizes

Bitswap implementations must support sending and receiving individual blocks of sizes less than or equal to 2MiB. Handling blocks larger than 2MiB is not recommended so as to keep compatibility with implementations which only support up to 2MiB.
Bitswap implementations MUST support sending and receiving individual blocks of
sizes less than or equal to 2MiB. Handling blocks larger than 2MiB is not recommended
so as to keep compatibility with implementations which only support up to 2MiB.

## Bitswap 1.0.0

### Bitswap 1.0.0: Interaction Pattern

Given that a client C wants to fetch data from some server S:
Given that a client *C* wants to fetch data from some server *S*:

1. C sends a message to S for the blocks it wants, via a stream `s_want`
1. C may either send a complete wantlist, or an update to an outstanding wantlist
2. C may reuse this stream to send new wants
2. S sends back blocks on a stream `s_receive`. S may reuse this stream to send back subsequent responses.
1. S should respect the relative priority of wantlist requests from C, with wants that have higher `priority` values being responded to first.
3. When C no longer needs a block it previously asked for, it should send a `Cancel` message for that block to all peers from which it has not received a response about that block
1. *C* sends a message to *S* for the blocks it wants, via a stream `s_want`
1. *C* MAY either send a complete wantlist, or an update to an outstanding wantlist
2. *C* MAY reuse this stream to send new wants
2. *S* sends back blocks on a stream `s_receive`. *S* MAY reuse this stream to send
back subsequent responses.
1. *S* SHOULD respect the relative priority of wantlist requests from *C*, with
wants that have higher `priority` values being responded to first.
3. When *C* no longer needs a block it previously asked for, it SHOULD send a `Cancel`
message for that block to all peers from which it has not received a response
about that block

### Bitswap 1.0.0: Message

A single Bitswap message may contain any of the following content:
A single Bitswap message MAY contain any of the following content:

1. The sender’s wantlist. This wantlist may either be the sender’s complete wantlist or just the changes to the sender’s wantlist that the receiver needs to know.
2. Data blocks. These are meant to be blocks that the receiver has requested (i.e., blocks that are on the receiver’s wantlist as far as the sender is aware at the time of sending).
1. The sender’s wantlist. This wantlist MAY either be the sender’s complete wantlist
or just the changes to the sender’s wantlist that the receiver needs to know.
2. Data blocks. These are meant to be blocks that the receiver has requested (i.e.,
blocks that are on the receiver’s wantlist as far as the sender is aware at the
time of sending).

#### Bitswap 1.0.0: Wire Format

The wire format for Bitswap is simply a stream of Bitswap messages. The following protobuf describes the form of these messages. Note: all protobufs are described using proto3 syntax.
The wire format for Bitswap is simply a stream of Bitswap messages. The following
protobuf describes the form of these messages. Note: all protobufs are described
using [proto3](https://protobuf.dev/programming-guides/proto3/) syntax.

```protobuf
message Message {
Expand All @@ -84,25 +113,25 @@ message Message {
Wantlist wantlist = 1;
repeated bytes blocks = 2;
}
```

### Bitswap 1.0.0: Protocol Format

All protocol messages sent over a stream are prefixed with the message length in
bytes, encoded as an unsigned variable length integer as defined by the
[multiformats unsigned-varint spec](https://github.com/multiformats/unsigned-varint).
bytes, encoded as an unsigned variable length integer as defined by the multiformats
[unsigned-varint] spec.

All protocol messages must be less than or equal to 4MiB in size
All protocol messages MUST be less than or equal to 4MiB in size.

## Bitswap 1.1.0

Bitswap 1.1.0 introduces a 'payload' field to the protobuf message and deprecates the
existing 'blocks' field. The 'payload' field is an array of pairs of cid
prefixes and block data. The cid prefixes are used to ensure the correct
codecs and hash functions are used to handle the block on the receiving
end.
Bitswap 1.1.0 introduces a `payload` field to the protobuf message and deprecates the
existing 'blocks' field. The 'payload' field is an array of pairs of CID prefixes
and block data. The CID prefixes are used to ensure the correct codecs and hash
functions are used to handle the block on the receiving end.

It is otherwise identical to 1.0.0
It is otherwise identical to 1.0.0.

### Bitswap 1.1.0: Wire Format

Expand Down Expand Up @@ -131,24 +160,39 @@ message Message {
## Bitswap 1.2.0

Bitswap 1.2.0 extends the Bitswap 1.1.0 protocol with the three changes:
1. Being able to ask if a peer has the data, not just to send the data
2. A peer can respond that it does not have some data rather than just not responding
3. Nodes can indicate on messages how much data they have queued to send to the peer they are sending the message to

### Bitswap 1.2.0: Interaction Pattern
1. Being able to ask if a peer has the data, not just to send the data.
2. A peer can respond that it does not have some data rather than just not responding.
3. Nodes can indicate on messages how much data they have queued to send to the peer
they are sending the message to.

Given that a client C wants to fetch data from some server S:
### Bitswap 1.2.0: Interaction Pattern

1. C opens a stream `s_want` to S and sends a message for the blocks it wants
1. C may either send a complete wantlist, or an update to an outstanding wantlist
2. C may reuse this stream to send new wants
3. For each of the items in the wantlist C may ask if S has the block (i.e. a Have request) or for S to send the block (i.e. a block request). C may also ask S to send back a DontHave message in the event it doesn't have the block
2. S responds back on a stream `s_receive`. S may reuse this stream to send back subsequent responses
1. If C sends S a Have request for data S has (and is willing to give to C) it should respond with a Have, although it may instead respond with the block itself (e.g. if the block is very small)
2. If C sends S a Have request for data S does not have (or has but is not willing to give to C) and C has requested for DontHave responses then S should respond with DontHave
3. S may choose to include the number of bytes that are pending to be sent to C in the response message
4. S should respect the relative priority of wantlist requests from C, with wants that have higher `priority` values being responded to first.
3. When C no longer needs a block it previously asked for it should send a Cancel message for that request to any peers that have not already responded about that particular block. It should particularly send Cancel messages for Block requests (as opposed to Have requests) that have not yet been answered.
Given that a client *C* wants to fetch data from some server *S*:

1. *C* opens a stream `s_want` to *S* and sends a message for the blocks it wants:
1. *C* MAY either send a complete wantlist, or an update to an outstanding wantlist.
2. *C* MAY reuse this stream to send new wants.
3. For each of the items in the wantlist *C* MAY ask if *S* has the block
(i.e. a `Have` request) or for *S* to send the block (i.e. a `Block` request).
*C* MAY also ask *S* to send back a `DontHave` message in the event it doesn't
have the block.
2. *S* responds back on a stream `s_receive`. *S* MAY reuse this stream to send
back subsequent responses:
1. If *C* sends *S* a `Have` request for data *S* has (and is willing to give
to *C*) it SHOULD respond with a `Have`, although it MAY instead respond
with the block itself (e.g. if the block is very small).
2. If *C* sends *S* a `Have` request for data *S* does not have (or has but
is not willing to give to *C*) and *C* has requested for `DontHave` responses
then *S* SHOULD respond with `DontHave`.
3. *S* MAY choose to include the number of bytes that are pending to be sent
to *C* in the response message.
4. *S* SHOULD respect the relative priority of wantlist requests from *C*,
with wants that have higher `priority` values being responded to first.
3. When *C* no longer needs a block it previously asked for it SHOULD send a
`Cancel` message for that request to any peers that have not already responded
about that particular block. It SHOULD particularly send `Cancel` messages for
`Block` requests (as opposed to `Have` requests) that have not yet been answered.

### Bitswap 1.2.0: Wire Format

Expand Down Expand Up @@ -194,5 +238,7 @@ message Message {

## Implementations

- <https://github.com/ipfs/go-bitswap>
- <https://github.com/ipfs/js-ipfs-bitswap>
- [Boxo Bitswap](https://github.com/ipfs/boxo/tree/main/bitswap)
- [js-ipfs-bitswap](https://github.com/ipfs/js-ipfs-bitswap)

[unsigned-varint]: https://github.com/multiformats/unsigned-varint

0 comments on commit ae158cb

Please sign in to comment.