Skip to content

Commit 789122b

Browse files
committed
fix(crdt): admit self-written snapshots via a local import path
import_snapshot routed through import_remote's untrusted-peer size ceilings even for a collection's own snapshot restored at cold start. Those ceilings bound how much work an untrusted peer may cause; against a store's own data they instead cap how large a document may be reloaded after being written, with no in-library recovery once a store grows past the limit. Route self-written snapshots through import_local instead, keeping import_remote's caps for peer-originated snapshots via sync.
1 parent 92f4de0 commit 789122b

1 file changed

Lines changed: 20 additions & 7 deletions

File tree

‎nodedb-lite/src/engine/crdt/engine/lifecycle.rs‎

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,20 @@ impl CrdtEngine {
137137

138138
// ─── Snapshot & Persistence ──────────────────────────────────────
139139

140-
/// Import a full Loro snapshot into a collection's document.
140+
/// Import a full Loro snapshot this device wrote itself — a collection
141+
/// restored from durable storage at cold start.
142+
///
143+
/// Admitted as local. The size ceilings on [`Self::import_remote`] bound
144+
/// how much work an untrusted peer may cause; applied to a store's own
145+
/// snapshot they instead cap how large a document this device may reload
146+
/// after writing it, and the export side has no such bound. A store that
147+
/// grew past the ceiling by succeeding at writes would refuse to open, with
148+
/// no way to recover from inside the library — raising one limit only moves
149+
/// the wall to the next. Every structural check still runs: authenticated
150+
/// metadata, per-peer ranges that do not regress, pending dependencies.
151+
///
152+
/// Peer snapshots do not come through here — sync routes them to
153+
/// [`Self::import_remote`], which stays capped.
141154
///
142155
/// See [`Self::import_remote`] for why the admission is returned rather
143156
/// than discarded.
@@ -146,12 +159,12 @@ impl CrdtEngine {
146159
collection: &str,
147160
snapshot: &[u8],
148161
) -> Result<ImportAdmission, LiteError> {
149-
let admission =
150-
self.state_mut(collection)?
151-
.import(snapshot)
152-
.map_err(|e| LiteError::Storage {
153-
detail: format!("snapshot import for '{collection}' failed: {e}"),
154-
})?;
162+
let admission = self
163+
.state_mut(collection)?
164+
.import_local(snapshot)
165+
.map_err(|e| LiteError::Storage {
166+
detail: format!("snapshot import for '{collection}' failed: {e}"),
167+
})?;
155168
warn_if_fully_trimmed(collection, "snapshot", &admission);
156169
Ok(admission)
157170
}

0 commit comments

Comments
 (0)