Something went wrong. Try again.
A public mirror for the whole atmosphere hubble.microcosm.blue
Something went wrong. Try again.
3.0 kB · 95 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596//! atproto commit operations.//!//! fast, synchronous implementation of step 3 of sync 1.1 commit validation,//! operation inversion.//!//! ```no_run//! # use std::collections::HashMap;//! # use hubble_commit::{Cid, Key, Op, OpOrder, invert_ops};//! # fn example(blocks: HashMap<Cid, Vec<u8>>, root: Cid, claimed_prev: Cid)//! # -> Result<(), Box<dyn std::error::Error>> {//! let ops = vec![Op::Create {//! key: Key::new("app.bsky.feed.post/3lrbpi5ot35kpjb")?,//! cid: root,//! }];//! let prev = invert_ops(&blocks, root, &ops, OpOrder::AsGiven)?;//! assert_eq!(prev, claimed_prev);//! # Ok(())//! # }//! ```//!//! (in the future maybe we'll add commit coalescing too)
mod block;mod blocks;pub mod car;mod error;mod key;mod node;mod op;mod tree;
// VENDORED from dasl until it releases the `Hash` derive we need to key// blocks by CID. Re-exported by hubble-sync as `DaslCid`.pub mod cid;
pub use block::{BlockError, verify_block};pub use blocks::Blocks;pub use car::{CarError, CarReader};pub use cid::{Cid, CidParseError};pub use error::{InvertError, NodeFault, OpKind};pub use key::{ Key, KeyError, MAX_COLLECTION_LEN, MAX_KEY_LEN, MAX_LAYER, MAX_RKEY_LEN, layer_of, shared_prefix_len,};pub use op::Op;pub use tree::Tree;
/// How to order operations when inverting more than one.////// In general, just use `AsGiven` (pass `Default::default()` to not even think/// about it).#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]pub enum OpOrder { /// Invert in the order given, reordering nothing (default) /// /// Makes no attempt to optimize ops inversion order, can fail if a producer /// emits a technically-provable but spec-non-compliant minimal block set. /// /// It's good to reject stuff that's not spec compliant. /// /// [spec]: https://www.ietf.org/archive/id/draft-holmgren-at-synchronization-00.html #[default] AsGiven,
/// Invert highest key first: fewest blocks to prove. /// /// Tolerates a producer that sends only the blocks inversion strictly /// needs rather than the ones the spec requires. Out of mst-test-suite's /// 16,384 exhaustive cases this, ordering affects 447. /// /// If there is some PDS emitting commits that don't meet the spec's /// adjacent keys requirement but are technically provable, this order /// should succeed at proving them. /// /// (but please ask the pds implementor to emit spec compliant commits) HighestKeyFirst,}
/// Invert `ops` against the tree at `root`, returning the root it had before.pub fn invert_ops( blocks: &(impl Blocks + Sync), root: Cid, ops: &[Op], order: OpOrder,) -> Result<Cid, InvertError> { let mut tree = Tree::new(blocks, root); let mut ordered: Vec<&Op> = ops.iter().collect(); if order == OpOrder::HighestKeyFirst { ordered.sort_unstable_by(|a, b| b.key().cmp(a.key())); } for op in ordered { tree.invert(op)?; } tree.root()}