···2323todo
24242525- [x] car file test fixtures & validation tests
2626-- [ ] make sure we can get the did and signature out for verification
2626+- [x] make sure we can get the did and signature out for verification
2727+ -> yeah the commit is returned from init
2728- [ ] spec compliance todos
2828- - [ ] assert that keys are ordered and fail if not
2929+ - [x] assert that keys are ordered and fail if not
2930 - [ ] verify node mst depth from key (possibly pending [interop test fixes](https://github.com/bluesky-social/atproto-interop-tests/issues/5))
3031- [ ] performance todos
3131- - [ ] consume the serialized nodes into a mutable efficient format
3232+ - [x] consume the serialized nodes into a mutable efficient format
3233 - [ ] maybe customize the deserialize impl to do that directly?
3334 - [x] benchmark and profile
3435- [ ] robustness todos
3536 - [ ] swap the blocks hashmap for a BlockStore trait that can be dumped to redb
3637 - [ ] maybe keep the redb function behind a feature flag?
3738 - [ ] can we assert a max size for node blocks?
3838- - [ ] figure out why asserting the upper nibble of the fourth byte of a node fails fingerprinting
3939+ - [x] figure out why asserting the upper nibble of the fourth byte of a node fails fingerprinting
4040+ -> because it's the upper 3 bytes, not upper 4 byte nibble, oops.
3941 - [ ] max mst depth (there is actually a hard limit but a malicious repo could do anything)
4040- - [ ] i don't think we need a max recursion depth for processing cbor contents since we leave records to the user to decode
4242+ - [ ] i don't *think* we need a max recursion depth for processing cbor contents since we leave records to the user to decode
41434244newer ideas
4345
+11-8
src/drive.rs
···1010pub enum DriveError<E: Error> {
1111 #[error("Failed to initialize CarReader: {0}")]
1212 CarReader(#[from] iroh_car::Error),
1313- #[error("CAR file requires a root to be present")]
1414- MissingRoot,
1513 #[error("Car block stream error: {0}")]
1614 CarBlockError(Box<dyn Error>),
1715 #[error("Failed to decode commit block: {0}")]
1816 BadCommit(Box<dyn Error>),
1919- #[error("Failed to decode record block: {0}")]
2020- BadRecord(Box<dyn Error>),
2117 #[error("The Commit block reference by the root was not found")]
2218 MissingCommit,
2319 #[error("The MST block {0} could not be found")]
2420 MissingBlock(Cid),
2521 #[error("Failed to walk the mst tree: {0}")]
2622 Tripped(#[from] Trip<E>),
2727- #[error("Not finished walking, but no more blocks are available to continue")]
2828- Dnf,
2323+ #[error("Encountered an rkey out of order while walking the MST")]
2424+ RkeyOutOfOrder,
2925}
30263127type CarBlock<E> = Result<(Cid, Vec<u8>), E>;
···7571 blocks: HashMap<Cid, MaybeProcessedBlock<T, PE>>,
7672 walker: Walker,
7773 process: P,
7474+ prev_rkey: String,
7875}
79768077impl<SE, S, T: Clone, P, PE> Vehicle<SE, S, T, P, PE>
···10299 let c: Commit = serde_ipld_dagcbor::from_slice(&data)
103100 .map_err(|e| DriveError::BadCommit(e.into()))?;
104101 commit = Some(c);
105105- break; // inner while
102102+ break;
106103 } else {
107104 blocks.insert(
108105 cid,
···125122 blocks,
126123 walker,
127124 process,
125125+ prev_rkey: "".to_string(),
128126 };
129127 Ok((commit, me))
130128 }
···159157 let cid_needed = match self.walker.walk(&mut self.blocks, &self.process)? {
160158 Step::Rest(cid) => cid,
161159 Step::Finish => return Ok(None),
162162- Step::Step { rkey, data } => return Ok(Some((Rkey(rkey), data))),
160160+ Step::Step { rkey, data } => {
161161+ if rkey <= self.prev_rkey {
162162+ return Err(DriveError::RkeyOutOfOrder);
163163+ }
164164+ return Ok(Some((Rkey(rkey), data)));
165165+ }
163166 };
164167165168 // load blocks until we reach that cid