zakura-network 1.0.0

Networking code for the Zakura node. Internal crate, published to support cargo install zakura
Documentation
//! Block-range download request types.
//!
//! The block-range *request* a peer routine issues and tracks in its
//! `outstanding` set ([`BlockRangeRequest`]), plus the body-size estimate hint
//! ([`BlockSizeEstimate`]) that feeds the receive-path `SizeMismatch` tolerance
//! check. There is no scheduler here: the per-peer routine pulls work from the
//! [`WorkQueue`](super::work_queue::WorkQueue) and builds a request directly (see
//! [`pipe`] for the subsystem map).

use super::{state::*, *};

/// Source of a block-body byte-size estimate hint.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum BlockSizeEstimate {
    /// Confirmed serialized size from committed block metadata.
    Confirmed(u32),
    /// Untrusted advertised size hint from header sync.
    Advertised(u32),
    /// No size hint is known; reserve the per-block worst case.
    Unknown,
}

/// A contiguous block-range request issued to one peer and tracked in its
/// `outstanding` set. Built by the reactor's per-peer issuance path from a chunk
/// taken out of the [`WorkQueue`](super::work_queue::WorkQueue).
#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) struct BlockRangeRequest {
    pub(super) start_height: block::Height,
    pub(super) count: u32,
    pub(super) anchor_hash: block::Hash,
    /// The reserved byte total for this request (released on
    /// timeout/disconnect/send-failure). Equal to the sum of the per-height size
    /// estimates in `expected_blocks`.
    pub(super) estimated_bytes: u64,
    pub(super) expected_blocks: Vec<ExpectedBlock>,
}

/// Per-height metadata needed to validate one body in a range request.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(super) struct ExpectedBlock {
    pub(super) height: block::Height,
    pub(super) hash: block::Hash,
    pub(super) estimated_bytes: u64,
}

impl BlockRangeRequest {
    pub(super) fn end_height(&self) -> block::Height {
        height_after_count(self.start_height, self.count)
            .and_then(previous_height)
            .expect("range request count is non-zero")
    }

    pub(super) fn contains(&self, height: block::Height) -> bool {
        self.start_height <= height && height <= self.end_height()
    }

    pub(super) fn offset_for_height(&self, height: block::Height) -> Option<u32> {
        self.contains(height)
            .then(|| height.0.checked_sub(self.start_height.0))
            .flatten()
    }

    pub(super) fn expected_hash(&self, height: block::Height) -> Option<block::Hash> {
        self.expected_blocks
            .iter()
            .find_map(|expected| (expected.height == height).then_some(expected.hash))
    }

    pub(super) fn estimated_bytes_for_height(&self, height: block::Height) -> Option<u64> {
        self.expected_blocks
            .iter()
            .find_map(|expected| (expected.height == height).then_some(expected.estimated_bytes))
    }
}