diff options
| author | tv <tv@krebsco.de> | 2026-10-24 18:18:29 +0200 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-24 18:18:29 +0200 |
| commit | 09f2dfd083c4fcdce4c5ca7376353906eb025c42 (patch) | |
| tree | e13141f10e3854408bd70d18d1bf31581abe5458 /src/swarm | |
| parent | 371e52cb48bae99232547f6fae6a0487a85c2d04 (diff) | |
put remake content into blobs
Diffstat (limited to 'src/swarm')
| -rw-r--r-- | src/swarm/blob.rs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/src/swarm/blob.rs b/src/swarm/blob.rs index 6ff1618..8c891ae 100644 --- a/src/swarm/blob.rs +++ b/src/swarm/blob.rs @@ -2,8 +2,9 @@ //! //! Large transfers can't go in one Mycelium message (it must arrive within Mycelium's //! five-minute deadline), and a blob every node holds identically can come from many -//! of them. Today the only kind of blob is an Automerge change by its hash, e.g. an -//! epoch's snapshot change, which every node on that epoch holds byte for byte. +//! of them. A blob is an Automerge change by its hash (e.g. an epoch's snapshot change, +//! which every node on that epoch holds byte for byte), or content by its BLAKE3 hash +//! (e.g. the new document of a `replace` or `import` remake). //! //! * Serving: a request without chunks gets the manifest (size, chunk size, a BLAKE3 //! hash per chunk); one with chunks gets each chunk as a message of its own. A node @@ -62,7 +63,7 @@ pub(crate) struct Blobs { } struct Prepared { - bytes: Vec<u8>, + bytes: Arc<Vec<u8>>, hashes: Vec<[u8; 32]>, } @@ -152,8 +153,10 @@ async fn prepare(state: &AppState, id: BlobId) -> Option<Arc<Prepared>> { }) .await .ok() - .flatten()? + .flatten() + .map(Arc::new)? } + BlobId::Content(hash) => state.remake.content(&hash)?, }; let chunk_size = state.blobs.chunk_size; let prepared = tokio::task::spawn_blocking(move || { @@ -454,6 +457,20 @@ fn expected_len(manifest: &Manifest, slot: usize) -> usize { } /// Downloads change `hash` from `peers` and checks it. +/// Downloads the content with BLAKE3 hash `hash` from `peers` and checks it. +pub(crate) async fn fetch_content( + state: &AppState, + hash: [u8; 32], + peers: Vec<String>, +) -> Result<Vec<u8>> { + let id = BlobId::Content(hash); + let bytes = fetch(state, id, peers).await?; + if *blake3::hash(&bytes).as_bytes() != hash { + bail!("downloaded {id} doesn't match its hash"); + } + Ok(bytes) +} + pub(crate) async fn fetch_change( state: &AppState, hash: ChangeHash, |
