#ipfs #cid #protocols #block #block-store #query #bitswap

libp2p-bitswap-next

ipfs bitswap协议的实现

5个版本

0.26.4 2024年5月17日
0.26.3 2024年5月2日
0.26.2 2024年4月15日
0.26.1 2023年12月19日
0.26.0 2023年12月19日

#985 in 网络编程

Download history 92/week @ 2024-04-26 49/week @ 2024-05-03 149/week @ 2024-05-17 8/week @ 2024-05-24 3/week @ 2024-05-31 4/week @ 2024-06-07 4/week @ 2024-06-14 1/week @ 2024-06-21

980 每月下载量
用于 rust-ipfs

MIT/Apache

105KB
2.5K SLoC

Crates.io docs.rs

libp2p-bitswap

bitswap协议的实现。

高效同步块dags

Bitswap是一个非常简单的协议。它被修改并简化为ipfs-embed。消息格式可以用以下枚举表示。

pub enum BitswapRequest {
    Have(Cid),
    Block(Cid),
}

pub enum BitswapResponse {
    Have(bool),
    Block(Vec<u8>),
}

定位提供者的机制可以抽象化。可以插入一个dht或集中式数据库查询。bitswap api看起来如下所示

#[derive(Debug)]
pub enum BitswapEvent {
    /// Received a block from a peer. Includes the number of known missing blocks for a
    /// sync query. When a block is received and missing blocks is not empty the counter
    /// is increased. If missing blocks is empty the counter is decremented.
    Progress(QueryId, usize),
    /// A get or sync query completed.
    Complete(QueryId, Result<()>),
}

pub trait BitswapStore: Send + Sync + 'static {
    /// The store params.
    type Params: StoreParams;
    /// A have query needs to know if the block store contains the block.
    fn contains(&mut self, cid: &Cid) -> Result<bool>;
    /// A block query needs to retrieve the block from the store.
    fn get(&mut self, cid: &Cid) -> Result<Option<Vec<u8>>>;
    /// A block response needs to insert the block into the store.
    fn insert(&mut self, block: &Block<Self::Params>) -> Result<()>;
    /// A sync query needs a list of missing blocks to make progress.
    fn missing_blocks(&mut self, cid: &Cid) -> Result<Vec<Cid>>;
}

pub struct BitswapConfig {
    /// Timeout of a request.
    pub request_timeout: Duration,
    /// Time a connection is kept alive.
    pub connection_keep_alive: Duration,
}

impl<P: StoreParams> Bitswap<P> {
    /// Creates a new `Bitswap` behaviour.
    pub fn new(config: BitswapConfig) -> Self;

    /// Adds an address for a peer.
    pub fn add_address(&mut self, peer_id: &PeerId, addr: Multiaddr);

    /// Removes an address for a peer.
    pub fn remove_address(&mut self, peer_id: &PeerId, addr: &Multiaddr);

    /// Starts a get query with an initial guess of providers.
    pub fn get(&mut self, cid: Cid, peers: impl Iterator<Item = PeerId>) -> QueryId;

    /// Starts a sync query with an the initial set of missing blocks.
    pub fn sync(&mut self, cid: Cid, peers: Vec<PeerId>, missing: impl Iterator<Item = Cid>) -> QueryId;

    /// Cancels an in progress query. Returns true if a query was cancelled.
    pub fn cancel(&mut self, id: QueryId) -> bool;

    /// Register bitswap stats in a prometheus registry.
    pub fn register_metrics(&self, registry: &Registry) -> Result<()>;
}

那么当你创建一个get请求时会发生什么?首先使用have请求查询初始集中的所有提供者。作为一个优化,在每次查询批次中发送一个块请求。如果get查询找到一个块,它返回一个查询完成。如果块没有在初始集中找到,则发出一个Providers事件。这就是bitswap消费者尝试通过例如执行dht查找来定位提供者的地方。在定位提供者完成后,通过调用inject_providers来发出信号。然后查询管理器使用新的提供者集执行bitswap请求,结果是找到块或返回一个BlockNotFound错误。

我们经常想要同步整个块的dag。我们可以通过添加一个同步查询来有效地同步块的dag,该查询并行地对块的引用执行get查询。使用具有块的提供者集作为引用查询的初始集。

许可证

MIT OR Apache-2.0

依赖项

~11–18MB
~271K SLoC