soft3/bbg/rs/src/lib.rs

// ---
// tags: bbg, rust
// crystal-type: source
// crystal-domain: cyber
// ---
//! bbg โ€” Big Badass Graph: authenticated state with polynomial commitments.
//!
//! BBG has one operation: insert(signal).
//! All semantic validation (A1โ€“A3, focus sufficiency, box ownership,
//! conservation, VDF) is the responsibility of cybergraph.
//! BBG only enforces the structural double-spend invariant via N(x).

pub mod checkpoint;
pub mod dim;
pub mod proof;
pub mod prune;
pub mod query;
pub mod signal;
pub mod state;
pub mod stats;
pub mod storage;
pub mod types;

pub use checkpoint::Checkpoint;
pub use proof::{
    QueryProof, prove_axons_in, prove_axons_out, prove_balances, prove_card, prove_coin,
    prove_commitment, prove_file, prove_location, prove_neuron, prove_particle, prove_signal,
    prove_time, verify_particle,
};
pub use prune::{PruneConfig, PruneState};
pub use query::{
    BbgLookProvider, Dim, ProofLookProvider, bbg_query, collect_look_openings, verify_opening,
    verify_query,
};
pub use signal::{BoxMove, Cyberlink, InsertError, Signal};
pub use state::{BbgState, balance_key};
pub use stats::{GraphStats, STAT_RELATIONS};
pub use types::{IntentRecord, NeuronId, NeuronRecord, Particle, SignalRecord};

/// The BBG facade: state + checkpoint + pruning policy as a single unit.
pub struct Bbg {
    pub state: BbgState,
    pub checkpoint: Checkpoint,
    pub prune_config: PruneConfig,
    pub prune_state: PruneState,
}

impl Bbg {
    pub fn new() -> Self {
        let state = BbgState::new();
        let checkpoint = Checkpoint::new(&state);
        Self {
            state,
            checkpoint,
            prune_config: PruneConfig::default(),
            prune_state: PruneState::default(),
        }
    }

    pub fn with_prune_config(mut self, config: PruneConfig) -> Self {
        self.prune_config = config;
        self
    }

    /// Insert a pre-validated signal. Fails only on structural double-spend.
    /// Updates pruning state (last_touched) on success.
    pub fn insert(&mut self, signal: &Signal) -> Result<(), InsertError> {
        self.state.insert(signal)?;
        let epoch = self.state.height / state::EPOCH_BLOCKS;
        for link in &signal.links {
            let aid = state::axon_id(&link.from, &link.to);
            self.prune_state.touch(aid, epoch);
        }
        Ok(())
    }

    /// Finalize the current block: record a time snapshot, increment height,
    /// and run pruning at epoch boundaries.
    pub fn finalize_block(&mut self) {
        let h = self.state.height;
        let root = self.state.root();
        self.state.time.insert(h, root);
        self.state.refresh_root();
        self.state.height += 1;
        if self.state.height % state::EPOCH_BLOCKS == 0 {
            let epoch = self.state.height / state::EPOCH_BLOCKS;
            prune::prune(
                &mut self.state,
                &mut self.prune_state,
                &self.prune_config,
                epoch,
            );
        }
        self.checkpoint = self.checkpoint.advance(&self.state);
    }

    pub fn prove_particle(&self, particle: &Particle) -> Option<QueryProof> {
        prove_particle(&self.state, particle)
    }

    pub fn prove_neuron(&self, id: &NeuronId) -> Option<QueryProof> {
        prove_neuron(&self.state, id)
    }

    pub fn prove_axons_out(&self, particle: &Particle) -> Option<QueryProof> {
        prove_axons_out(&self.state, particle)
    }

    pub fn prove_axons_in(&self, particle: &Particle) -> Option<QueryProof> {
        prove_axons_in(&self.state, particle)
    }

    pub fn prove_location(&self, particle: &Particle) -> Option<QueryProof> {
        prove_location(&self.state, particle)
    }

    pub fn prove_coin(&self, denom: &Particle) -> Option<QueryProof> {
        prove_coin(&self.state, denom)
    }

    pub fn prove_card(&self, card_id: &Particle) -> Option<QueryProof> {
        prove_card(&self.state, card_id)
    }

    pub fn prove_file(&self, particle: &Particle) -> Option<QueryProof> {
        prove_file(&self.state, particle)
    }

    pub fn prove_signal(&self, step: u64) -> Option<QueryProof> {
        prove_signal(&self.state, step)
    }

    pub fn prove_time(&self, height: u64) -> Option<QueryProof> {
        prove_time(&self.state, height)
    }

    pub fn prove_commitment(&self, point: &[u8; 32]) -> Option<QueryProof> {
        prove_commitment(&self.state, point)
    }

    pub fn prove_balances(&self, owner: &[u8; 32], token: &[u8; 32]) -> Option<QueryProof> {
        prove_balances(&self.state, owner, token)
    }

    /// Persist an unsealed intent. Validation (identity signature) is sync's job.
    /// Returns the intent key = H(ฮฝ โ€– h0 โ€– scope_hash).
    pub fn apply_intent(&mut self, intent: &IntentRecord) -> Particle {
        self.state.apply_intent(intent)
    }

    /// Persist a signal header without applying its cyberlinks.
    /// Used when sealing follows a separate intent โ†’ seal lifecycle.
    pub fn apply_signal_record(&mut self, step: u64, record: SignalRecord) {
        self.state.apply_signal_record(step, record);
    }

    /// Committed graph statistics โ€” the bbg โ†’ inf cost/recursion interface.
    /// Authenticated by inclusion in BBG_root.
    pub fn statistics(&self) -> GraphStats {
        self.state.statistics()
    }

    /// Install a tighter (proven) diameter bound from tru. Takes effect on the
    /// next `finalize_block`.
    pub fn set_diameter_bound(&mut self, bound: u64) {
        self.state.set_diameter_bound(bound);
    }
}

impl Default for Bbg {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use signal::BoxMove;
    use types::NeuronRecord;

    fn neuron_id(seed: u8) -> NeuronId {
        [seed; 32]
    }
    fn particle(seed: u8) -> Particle {
        [seed; 32]
    }

    fn seed_neuron(bbg: &mut Bbg, id: NeuronId, focus: u64) {
        bbg.state.neurons.insert(
            id,
            NeuronRecord {
                focus,
                karma: 0,
                stake: 0,
            },
        );
    }

    fn one_link(neuron: NeuronId, from: Particle, to: Particle) -> Signal {
        Signal {
            neuron,
            links: vec![Cyberlink {
                from,
                to,
                token: particle(0),
                amount: 1,
                valence: 1,
            }],
            box_moves: vec![],
            height: 0,
        }
    }

    #[test]
    fn empty_root_is_deterministic() {
        assert_eq!(BbgState::new().root(), BbgState::new().root());
    }

    #[test]
    fn compute_root_is_deterministic() {
        let mut a = Bbg::new();
        let mut b = Bbg::new();
        seed_neuron(&mut a, neuron_id(1), 100);
        seed_neuron(&mut b, neuron_id(1), 100);
        a.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();
        b.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();
        assert_eq!(a.state.compute_root(), b.state.compute_root());
    }

    #[test]
    fn cyberlink_changes_root() {
        let mut bbg = Bbg::new();
        seed_neuron(&mut bbg, neuron_id(1), 100);
        let root_before = bbg.state.root();
        bbg.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();
        assert_ne!(bbg.state.root(), root_before);
    }

    #[test]
    fn finalize_block_increments_height() {
        let mut bbg = Bbg::new();
        assert_eq!(bbg.state.height, 0);
        bbg.finalize_block();
        assert_eq!(bbg.state.height, 1);
        bbg.finalize_block();
        assert_eq!(bbg.state.height, 2);
    }

    #[test]
    fn double_spend_is_rejected() {
        let mut bbg = Bbg::new();
        let nullifier = particle(42);
        let mk_signal = || Signal {
            neuron: neuron_id(1),
            links: vec![],
            box_moves: vec![BoxMove {
                nullifier,
                commitment: None,
            }],
            height: 0,
        };
        bbg.insert(&mk_signal()).unwrap();
        assert_eq!(bbg.insert(&mk_signal()), Err(InsertError::DoubleSpend));
    }

    #[test]
    fn prove_and_verify_particle_roundtrip() {
        let mut bbg = Bbg::new();
        seed_neuron(&mut bbg, neuron_id(1), 100);
        bbg.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();

        let proof = bbg
            .prove_particle(&particle(3))
            .expect("particle proof must exist");
        assert!(verify_particle(&proof, &bbg.state.root(), &particle(3)));
    }

    #[test]
    fn prove_particle_returns_none_for_unknown_cid() {
        assert!(Bbg::new().prove_particle(&particle(255)).is_none());
    }

    #[test]
    fn statistics_count_nodes_and_relations() {
        let mut bbg = Bbg::new();
        seed_neuron(&mut bbg, neuron_id(1), 100);
        bbg.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();

        let s = bbg.statistics();
        // particle(3) target + axon-particle H(2,3) = 2 nodes
        assert_eq!(s.node_count, s.relation_sizes[stats::rel::PARTICLES]);
        assert_eq!(s.relation_sizes[stats::rel::AXONS_OUT], 1);
        assert_eq!(s.relation_sizes[stats::rel::AXONS_IN], 1);
        assert_eq!(s.relation_sizes[stats::rel::NEURONS], 1);
    }

    #[test]
    fn diameter_bound_defaults_to_node_count_minus_one() {
        let mut bbg = Bbg::new();
        seed_neuron(&mut bbg, neuron_id(1), 100);
        bbg.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();
        let s = bbg.statistics();
        assert_eq!(s.diameter_bound, s.node_count.saturating_sub(1));
    }

    #[test]
    fn installed_diameter_bound_is_used_and_changes_root() {
        let mut bbg = Bbg::new();
        seed_neuron(&mut bbg, neuron_id(1), 100);
        bbg.insert(&one_link(neuron_id(1), particle(2), particle(3)))
            .unwrap();
        let root_before = bbg.state.compute_root();
        // Default for 2 nodes is node_count-1 = 1; install a distinct (sound
        // upper) bound to show the committed value flows into the root.
        bbg.set_diameter_bound(8);
        assert_eq!(bbg.statistics().diameter_bound, 8);
        assert_ne!(bbg.state.compute_root(), root_before);
    }

    #[test]
    fn lazy_root_after_bulk_inserts_matches_per_insert_root() {
        // `lazy` reads the root once after N inserts; `eager` materializes it
        // after every insert (the historical per-insert path). Both must land
        // on the same root, and it must equal a direct compute_root().
        let mut lazy = Bbg::new();
        let mut eager = Bbg::new();
        seed_neuron(&mut lazy, neuron_id(1), 10_000);
        seed_neuron(&mut eager, neuron_id(1), 10_000);
        for i in 0..8u8 {
            let sig = one_link(neuron_id(1), particle(10 + i), particle(100 + i));
            lazy.insert(&sig).unwrap();
            eager.insert(&sig).unwrap();
            let _ = eager.state.root(); // force per-insert materialization
        }
        assert_eq!(lazy.state.root(), eager.state.root());
        assert_eq!(lazy.state.root(), lazy.state.compute_root());
    }

    #[test]
    fn empty_graph_stats_are_zero() {
        let s = Bbg::new().statistics();
        assert_eq!(s.node_count, 0);
        assert_eq!(s.max_degree, 0);
        assert_eq!(s.diameter_bound, 0); // node_count.saturating_sub(1) on empty
    }
}

Homonyms

warriors/trisha/wgpu/lib.rs
soft3/glia/run/lib.rs
soft3/mir/src/lib.rs
soft3/foculus/src/lib.rs
cyb/optica/src/lib.rs
soft3/strata/src/lib.rs
warriors/trisha/rs/lib.rs
cyb/shell/src/lib.rs
cyb/core/src/lib.rs
soft3/glia/import/lib.rs
warriors/trisha/honeycrisp/lib.rs
neural/trident/src/lib.rs
soft3/crate/src/lib.rs
cyb/honeycrisp/src/lib.rs
cyb/prysm/rs/lib.rs
soft3/lens/src/lib.rs
soft3/tru/rs/lib.rs
soft3/cybergraph/src/lib.rs
soft3/nox/rs/lib.rs
soft3/mudra/src/lib.rs
soft3/radio/cyber-bao/src/lib.rs
neural/rs/dialect/src/lib.rs
soft3/lens/assayer/src/lib.rs
cyb/honeycrisp/aruminium/src/lib.rs
soft3/lens/brakedown/src/lib.rs
neural/rs/sigil/src/lib.rs
soft3/radio/iroh-willow/src/lib.rs
cyb/crates/cyb/src/lib.rs
neural/rs/link/src/lib.rs
cyb/honeycrisp/unimem/src/lib.rs
soft3/lens/porphyry/src/lib.rs
soft3/radio/iroh-docs/src/lib.rs
soft3/radio/iroh-car/src/lib.rs
soft3/radio/iroh-dns-server/src/lib.rs
soft3/radio/iroh/src/lib.rs
cyb/crates/cyb-reserve/src/lib.rs
soft3/strata/ext/src/lib.rs
soft3/radio/iroh-relay/src/lib.rs
neural/rune/rs/parse/lib.rs
neural/rs/codegen/src/lib.rs
soft3/radio/iroh-blobs/src/lib.rs
soft3/zheng/rs/src/lib.rs
soft3/strata/kuro/rs/lib.rs
soft3/tok/rs/src/lib.rs
soft3/conformance/rs/src/lib.rs
soft3/radio/iroh-base/src/lib.rs
neural/rs/macros/src/lib.rs
neural/rs/darwin-sys/src/lib.rs
soft3/radio/iroh-ffi/src/lib.rs
cyb/honeycrisp/rane/src/lib.rs
neural/rune/rs/prysm/lib.rs
soft3/lens/core/src/lib.rs
neural/rs/mir-format/src/lib.rs
neural/rs/core/src/lib.rs
soft3/strata/nebu/rs/lib.rs
neural/rune/rs/compile/lib.rs
neural/rune/rs/interp/lib.rs
soft3/strata/compute/src/lib.rs
soft3/lens/binius/src/lib.rs
soft3/strata/proof/src/lib.rs
neural/eidos/rs/src/lib.rs
neural/rune/rs/mold/lib.rs
soft3/strata/core/src/lib.rs
soft3/hemera/wgsl/src/lib.rs
neural/rune/rs/subject/lib.rs
soft3/soma/kernel/src/lib.rs
neural/rune/rs/lower/lib.rs
cyb/honeycrisp/acpu/src/lib.rs
neural/rune/rs/parse-pure/lib.rs
soft3/radio/iroh-gossip/src/lib.rs
neural/rune/rs/lex/lib.rs
soft3/hemera/rs/src/lib.rs
neural/rune/rs/ast/lib.rs
soft3/lens/ikat/src/lib.rs
soft3/tape/impl/rust/src/lib.rs
cyb/evy/crates/evy_radio/src/lib.rs
neural/inf/rs/lex/src/lib.rs
cyb/evy/forks/bevy_animation/src/lib.rs
neural/inf/rs/oracle/src/lib.rs
neural/trident/editor/zed/src/lib.rs
warriors/trisha/.vendor/twenty-first/src/lib.rs
warriors/erga/rs/pool/src/lib.rs
cyb/wysm/crates/c_api/src/lib.rs
cyb/evy/forks/bevy_anti_alias/src/lib.rs
soft3/strata/trop/rs/src/lib.rs
cyb/evy/forks/bevy_pbr/src/lib.rs
soft3/radio/quinn/quinn-udp/src/lib.rs
warriors/trisha/.vendor/triton-vm/src/lib.rs
soft3/strata/genies/rs/src/lib.rs
soft3/radio/nettools/portmapper/src/lib.rs
warriors/erga/rs/wallet/src/lib.rs
soft3/lytics/rs/core/src/lib.rs
cyb/wysm/crates/c_api/macro/lib.rs
soft3/strata/kuro/wgsl/src/lib.rs
cyb/evy/forks/bevy_tasks/src/lib.rs
neural/inf/rs/plan/src/lib.rs
cyb/wysm/crates/ir/src/lib.rs
cyb/evy/forks/bevy_gizmos/src/lib.rs
soft3/strata/genies/wgsl/src/lib.rs
warriors/erga/rs/autolykos/src/lib.rs
cyb/evy/forks/bevy_sprite/src/lib.rs
cyb/evy/crates/evy_prysm_core/src/lib.rs
warriors/trisha/.vendor/triton-constraint-circuit/src/lib.rs
cyb/evy/forks/bevy_transform/src/lib.rs
cyb/evy/crates/evy_engine_dispatch/src/lib.rs
warriors/trisha/.vendor/triton-air/src/lib.rs
cyb/evy/forks/bevy_diagnostic/src/lib.rs
cyb/wysm/crates/fuzz/src/lib.rs
neural/inf/rs/source/src/lib.rs
cyb/wysm/crates/wasmi/src/lib.rs
cyb/evy/forks/bevy_ecs/src/lib.rs
soft3/strata/jali/rs/src/lib.rs
warriors/trisha/.vendor/triton-isa/src/lib.rs
soft3/lytics/rs/event/src/lib.rs
soft3/strata/trop/wgsl/src/lib.rs
cyb/evy/crates/evy_dialect/src/lib.rs
warriors/trisha/.vendor/triton-constraint-builder/src/lib.rs
cyb/evy/crates/evy_platform_caps/src/lib.rs
cyb/evy/forks/bevy_sprite_render/src/lib.rs
cyb/evy/forks/bevy_gizmos_render/src/lib.rs
cyb/wysm/crates/collections/src/lib.rs
neural/inf/rs/ast/src/lib.rs
cyb/evy/forks/bevy_mesh/src/lib.rs
soft3/radio/quinn/bench/src/lib.rs
cyb/wysm/crates/c_api/artifact/lib.rs
warriors/erga/rs/rtable-bench/src/lib.rs
cyb/wysm/crates/core/src/lib.rs
soft3/strata/jali/wgsl/src/lib.rs
soft3/radio/iroh/bench/src/lib.rs
warriors/erga/rs/blake-bench/src/lib.rs
neural/inf/rs/parse/src/lib.rs
cyb/evy/forks/bevy_post_process/src/lib.rs
soft3/radio/quinn/quinn/src/lib.rs
cyb/evy/crates/evy_ecs_storage/src/lib.rs
warriors/erga/rs/app/src/lib.rs
neural/inf/rs/lower/src/lib.rs
cyb/evy/forks/bevy_core_pipeline/src/lib.rs
cyb/evy/forks/bevy_render/src/lib.rs
neural/rs/tests/macro-integration/src/lib.rs
soft3/radio/iroh-ffi/iroh-js/src/lib.rs
cyb/evy/forks/bevy_image/src/lib.rs
cyb/evy/crates/evy_engine_tasks/src/lib.rs
warriors/erga/rs/mine-bench/src/lib.rs
soft3/strata/nebu/wgsl/src/lib.rs
soft3/radio/nettools/netwatch/src/lib.rs
warriors/erga/rs/miner/src/lib.rs
neural/inf/rs/value/src/lib.rs
cyb/wysm/crates/wast/src/lib.rs
soft3/radio/tests/integration/src/lib.rs
cyb/wysm/crates/wasi/src/lib.rs
cyb/evy/crates/evy_diagnostic/src/lib.rs
soft3/radio/quinn/perf/src/lib.rs
soft3/radio/quinn/quinn-proto/src/lib.rs
cyb/evy/forks/naga/src/lib.rs
neural/inf/rs/eval/src/lib.rs
cyb/evy/crates/evy_engine_core/src/lib.rs
neural/inf/rs/cozo/cozo-lib-python/src/lib.rs
neural/inf/rs/cozo/cozo-lib-swift/src/lib.rs
neural/inf/rs/cozo/cozorocks/src/lib.rs
neural/inf/rs/cozo/cozo-lib-java/src/lib.rs
neural/inf/rs/cozo/cozo-lib-c/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/src/lib.rs
neural/inf/rs/cozo/cozo-lib-nodejs/src/lib.rs
neural/inf/rs/cozo/cozo-core/src/lib.rs
neural/inf/rs/cozo/cozo-lib-wasm/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/unimem/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/rane/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/unimem/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/acpu/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-ad6c77c38e86bc291/aruminium/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/aruminium/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/rane/src/lib.rs
cyb/honeycrisp/.claude/worktrees/agent-aa1259cb10112b22a/acpu/src/lib.rs

Graph