Node

Struct Node 

Source
pub struct Node { /* private fields */ }
Expand description

IPFRS unified node combining all layers

Implementations§

Source§

impl Node

Source

pub fn new(config: NodeConfig) -> Result<Self>

Create a new IPFRS node

Source

pub async fn start(&mut self) -> Result<()>

Start the IPFRS node

Source

pub async fn stop(&mut self) -> Result<()>

Stop the IPFRS node

Source

pub fn warmup(&self) -> Result<()>

Pre-initialize lazy components for faster first access

By default, semantic router and TensorLogic store are initialized lazily on first use. This method forces their initialization upfront, which can be useful for:

  • Warmup scenarios where you want predictable latency
  • Load testing where you want to measure steady-state performance
  • Detecting configuration errors early at startup
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Pre-initialize all components for faster first access
node.warmup()?;

// Now semantic and tensorlogic calls will be instant
Source

pub fn status(&self) -> NodeStatus

Get node status

Source

pub async fn diagnostics(&self) -> Result<NodeDiagnostics>

Get comprehensive node diagnostics

Collects detailed diagnostic information about node health, resource usage, and performance. This is useful for monitoring, troubleshooting, and optimization.

§Example
use ipfrs::{Node, NodeConfig, DiagnosticAnalyzer};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Get diagnostics
let diagnostics = node.diagnostics().await?;

// Analyze and get recommendations
let recommendations = DiagnosticAnalyzer::analyze(&diagnostics);
for rec in recommendations {
    println!("{:?}: {}", rec.severity, rec.message);
}

// Or get a human-readable report
let report = DiagnosticAnalyzer::health_report(&diagnostics);
println!("{}", report);
Source

pub fn is_semantic_enabled(&self) -> bool

Check if semantic routing is enabled

Returns true if the semantic router is configured to be enabled. Note: The router will be lazily initialized on first use.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if node.is_semantic_enabled() {
    println!("Semantic search is available");
}
Source

pub fn is_tensorlogic_enabled(&self) -> bool

Check if TensorLogic is enabled

Returns true if the TensorLogic store is configured to be enabled. Note: The store will be lazily initialized on first use.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if node.is_tensorlogic_enabled() {
    println!("Logic programming is available");
}
Source

pub fn is_running(&self) -> bool

Check if the node is running

Returns true if the node has been started and the network component is active.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;

assert!(!node.is_running());

node.start().await?;
assert!(node.is_running());
Source

pub fn is_semantic_initialized(&self) -> bool

Check if semantic router has been initialized

Returns true if the semantic router has been lazily initialized. This is different from is_semantic_enabled() which checks if it’s configured.

Source

pub fn is_tensorlogic_initialized(&self) -> bool

Check if TensorLogic store has been initialized

Returns true if the TensorLogic store has been lazily initialized. This is different from is_tensorlogic_enabled() which checks if it’s configured.

Source

pub fn auth_manager(&self) -> Result<Arc<AuthManager>>

Get the authentication manager if enabled

Source

pub fn is_auth_enabled(&self) -> bool

Check if authentication is enabled

Source

pub fn create_user( &self, username: String, email: Option<String>, roles: HashSet<Role>, ) -> Result<User>

Create a new user (requires auth enabled)

Source

pub fn verify_token(&self, token: &str) -> Result<AuthToken>

Verify an authentication token

Source

pub fn check_permission( &self, token: &AuthToken, permission: Permission, ) -> Result<()>

Check if a token has a specific permission

Source

pub fn tls_manager(&self) -> Result<Arc<TlsManager>>

Get the TLS manager if enabled

Source

pub fn is_tls_enabled(&self) -> bool

Check if TLS is enabled

Source

pub async fn add_file(&self, path: impl AsRef<Path>) -> Result<Cid>

Add a file from the filesystem

Source

pub async fn add_bytes(&self, data: impl Into<Bytes>) -> Result<Cid>

Add bytes directly to storage

Source

pub async fn add_reader<R>(&self, reader: R) -> Result<Cid>
where R: AsyncRead + Unpin,

Add content from an async reader

Reads all data from the provided reader, stores it as a block, and returns the CID. This is useful for streaming data from files, network streams, or other async sources.

§Example
use ipfrs::{Node, NodeConfig};
use tokio::fs::File;

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

let file = File::open("data.bin").await?;
let cid = node.add_reader(file).await?;
println!("Stored with CID: {}", cid);
Source

pub async fn get(&self, cid: &Cid) -> Result<Option<Bytes>>

Get content by CID

Source

pub async fn get_range( &self, cid: &Cid, offset: usize, length: Option<usize>, ) -> Result<Option<Bytes>>

Get a byte range from content

Retrieves a specific byte range from a block, similar to HTTP 206 Partial Content. This is useful for streaming large files or implementing range requests.

§Parameters
  • cid: The content identifier
  • offset: Starting byte position (0-indexed)
  • length: Number of bytes to read (None for all remaining bytes)
§Returns
  • Ok(Some(bytes)) - The requested byte range
  • Ok(None) - Block not found
  • Err(_) - Invalid range or other error
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Get bytes 100-199 (100 bytes starting at offset 100)
if let Some(data) = node.get_range(&cid, 100, Some(100)).await? {
    println!("Retrieved {} bytes", data.len());
}
Source

pub async fn get_to_file(&self, cid: &Cid, path: impl AsRef<Path>) -> Result<()>

Get content and write to file

Source

pub async fn add_directory(&self, dir_path: impl AsRef<Path>) -> Result<Cid>

Add a directory recursively

Traverses a directory tree, stores all files as blocks, and creates a directory structure using IPLD. Returns the root CID.

§Directory Structure

Directories are stored as IPLD maps where:

  • Keys are file/directory names
  • Values are either:
    • Links to file blocks (for files)
    • Nested maps (for subdirectories)
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

let root_cid = node.add_directory("/path/to/directory").await?;
println!("Directory stored with root CID: {}", root_cid);
Source

pub async fn get_directory( &self, cid: &Cid, output_path: impl AsRef<Path>, ) -> Result<()>

Get a directory and write all files to the filesystem

Retrieves a directory DAG from storage and recreates the directory structure on the filesystem.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

node.get_directory(&dir_cid, "/path/to/output").await?;
Source

pub async fn dag_put(&self, data: Ipld) -> Result<Cid>

Store an IPLD DAG node

Serializes the IPLD data structure, stores it as a block, and returns the CID. This is useful for storing structured data with links to other blocks.

§Example
use ipfrs::{Node, NodeConfig};
use ipfrs_core::Ipld;
use std::collections::BTreeMap;

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

let mut map = BTreeMap::new();
map.insert("name".to_string(), Ipld::String("Alice".to_string()));
map.insert("age".to_string(), Ipld::Integer(30));

let cid = node.dag_put(Ipld::Map(map)).await?;
Source

pub async fn dag_get(&self, cid: &Cid) -> Result<Option<Ipld>>

Retrieve an IPLD DAG node

Fetches a block by CID and deserializes it as IPLD.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if let Some(data) = node.dag_get(&cid).await? {
    println!("Retrieved DAG node: {:?}", data);
}
Source

pub async fn dag_resolve(&self, root: &Cid, path: &str) -> Result<Option<Cid>>

Resolve an IPLD path

Navigates through IPLD structures following a path like “/key1/key2/0”. Returns the CID if the path leads to a link.

§Path Format
  • Map keys: “/key”
  • List indices: “/0”, “/1”, etc.
  • Nested: “/map_key/0/nested_key”
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Resolve path: /users/0/profile
if let Some(cid) = node.dag_resolve(&root_cid, "/users/0/profile").await? {
    println!("Resolved to CID: {}", cid);
}
Source

pub async fn dag_traverse( &self, root: &Cid, max_depth: Option<usize>, ) -> Result<Vec<Cid>>

Traverse a DAG and collect all reachable CIDs

Performs a breadth-first traversal starting from the root CID, following all links and collecting all reachable CIDs.

§Parameters
  • root: The starting CID
  • max_depth: Maximum depth to traverse (None for unlimited)
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Traverse up to depth 10
let cids = node.dag_traverse(&root_cid, Some(10)).await?;
println!("Found {} reachable blocks", cids.len());
Source

pub async fn put_block(&self, block: &Block) -> Result<()>

Store a raw block

Source

pub async fn put_blocks(&self, blocks: &[Block]) -> Result<()>

Store multiple blocks atomically

Source

pub async fn get_block(&self, cid: &Cid) -> Result<Option<Block>>

Retrieve a block by CID

Source

pub async fn get_blocks(&self, cids: &[Cid]) -> Result<Vec<Option<Block>>>

Retrieve multiple blocks

Source

pub async fn has_block(&self, cid: &Cid) -> Result<bool>

Check if a block exists

Source

pub async fn has_blocks(&self, cids: &[Cid]) -> Result<Vec<bool>>

Check if multiple blocks exist

Source

pub async fn delete_block(&self, cid: &Cid) -> Result<()>

Delete a block

Source

pub async fn delete_blocks(&self, cids: &[Cid]) -> Result<()>

Delete multiple blocks

Source

pub async fn block_stat(&self, cid: &Cid) -> Result<Option<BlockStat>>

Get detailed statistics about a block

Returns comprehensive information about a block including its size, CID details, and storage metadata.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if let Some(stat) = node.block_stat(&cid).await? {
    println!("Block size: {} bytes", stat.size);
    println!("CID: {}", stat.cid);
}
Source

pub async fn block_rm(&self, cid: &Cid) -> Result<()>

Remove a block from storage

Removes a block if it’s safe to do so. This method checks pinning status and refuses to remove pinned blocks to prevent accidental data loss.

§Safety

This operation is irreversible. The block will be permanently deleted from storage. Pinned blocks are protected and cannot be removed until unpinned.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

node.block_rm(&cid).await?;
println!("Block removed");
Source

pub fn list_blocks(&self) -> Result<Vec<Cid>>

List all CIDs in storage

Source

pub fn storage_stats(&self) -> Result<StorageStats>

Get storage statistics

Source

pub async fn flush(&self) -> Result<()>

Flush pending writes to disk

Source

pub fn semantic_stats(&self) -> Result<SemanticStats>

Get semantic router statistics

Returns comprehensive statistics about the semantic index including vector count, dimension, distance metric, and cache performance.

§Returns

Statistics about the semantic router

§Errors

Returns error if semantic routing is not enabled

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

let stats = node.semantic_stats()?;
println!("Indexed vectors: {}", stats.num_vectors);
println!("Vector dimension: {}", stats.dimension);
println!("Cache size: {}/{}", stats.cache_size, stats.cache_capacity);
Source

pub fn tensorlogic_stats(&self) -> Result<TensorLogicStats>

Get TensorLogic statistics

Returns information about the TensorLogic store including counts of stored terms, predicates, and rules.

§Returns

Statistics about TensorLogic storage

§Errors

Returns error if TensorLogic is not enabled

§Note

Currently returns basic statistics. Future versions will include knowledge base statistics, inference metrics, and proof counts.

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

let stats = node.tensorlogic_stats()?;
println!("TensorLogic enabled: {}", stats.enabled);
Source

pub async fn index_content(&self, cid: &Cid, embedding: &[f32]) -> Result<()>

Index content with its semantic embedding

Adds content to the semantic index for similarity search. The embedding should be a vector representation of the content (e.g., from a sentence transformer model).

§Arguments
  • cid - Content identifier to index
  • embedding - Vector embedding of the content
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Index content with 768-dimensional embedding (e.g., from BERT)
let embedding = vec![0.5; 768];
node.index_content(&cid, &embedding).await?;
Source

pub async fn search_similar( &self, query_embedding: &[f32], k: usize, ) -> Result<Vec<SearchResult>>

Search for similar content by semantic similarity

Performs k-nearest neighbor search over indexed content using vector similarity. Returns the top k most similar items.

§Arguments
  • query_embedding - Query vector to search for
  • k - Number of results to return
§Returns

Vector of search results ordered by similarity (highest first)

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Search for top 10 similar documents
let query_embedding = vec![0.3; 768];
let results = node.search_similar(&query_embedding, 10).await?;

for result in results {
    println!("CID: {}, Score: {}", result.cid, result.score);
}
Source

pub async fn search_hybrid( &self, query_embedding: &[f32], k: usize, filter: QueryFilter, ) -> Result<Vec<SearchResult>>

Search with advanced filtering options

Performs semantic search with additional filters like minimum score threshold, CID prefix matching, and result limits.

§Arguments
  • query_embedding - Query vector to search for
  • k - Number of results to return
  • filter - Query filter options
§Returns

Vector of filtered search results ordered by similarity

§Example
use ipfrs::{Node, NodeConfig, QueryFilter};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Search with filters
let query_embedding = vec![0.3; 768];
let filter = QueryFilter {
    min_score: Some(0.8),  // Only results with score >= 0.8
    max_score: None,        // No max score filter
    max_results: Some(5),   // Limit to 5 results
    cid_prefix: None,       // No CID filtering
};

let results = node.search_hybrid(&query_embedding, 20, filter).await?;

for result in results {
    println!("High-confidence match: {} ({})", result.cid, result.score);
}
Source

pub async fn put_term(&self, term: &Term) -> Result<Cid>

Store a logical term

Serializes and stores a TensorLogic term as a content-addressed block. Terms can be constants, variables, functions, or references to other CIDs.

§Arguments
  • term - The logical term to store
§Returns

CID of the stored term

§Example
use ipfrs::{Node, NodeConfig, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Store a constant term
let term = Term::Const(Constant::String("Alice".to_string()));
let cid = node.put_term(&term).await?;
println!("Stored term with CID: {}", cid);
Source

pub async fn get_term(&self, cid: &Cid) -> Result<Option<Term>>

Retrieve a logical term by CID

Fetches and deserializes a TensorLogic term from storage.

§Arguments
  • cid - Content identifier of the term
§Returns

The term if found, None otherwise

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if let Some(term) = node.get_term(&cid).await? {
    println!("Retrieved term: {}", term);
}
Source

pub async fn store_predicate(&self, predicate: &Predicate) -> Result<Cid>

Store a logical predicate

Stores a predicate (named relation with arguments) as a content-addressed block.

§Arguments
  • predicate - The predicate to store
§Returns

CID of the stored predicate

§Example
use ipfrs::{Node, NodeConfig, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Store a predicate: parent("Alice", "Bob")
let predicate = Predicate::new(
    "parent".to_string(),
    vec![
        Term::Const(Constant::String("Alice".to_string())),
        Term::Const(Constant::String("Bob".to_string())),
    ],
);

let cid = node.store_predicate(&predicate).await?;
println!("Stored predicate with CID: {}", cid);
Source

pub async fn get_predicate(&self, cid: &Cid) -> Result<Option<Predicate>>

Retrieve a logical predicate by CID

Fetches and deserializes a predicate from storage.

§Arguments
  • cid - Content identifier of the predicate
§Returns

The predicate if found, None otherwise

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if let Some(predicate) = node.get_predicate(&cid).await? {
    println!("Retrieved predicate: {}", predicate);
}
Source

pub async fn store_rule(&self, rule: &Rule) -> Result<Cid>

Store a logical rule

Stores a Horn clause (head :- body) as a content-addressed block.

§Arguments
  • rule - The rule to store
§Returns

CID of the stored rule

§Example
use ipfrs::{Node, NodeConfig, Rule, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Store a fact: parent("Alice", "Bob")
let fact = Rule::fact(Predicate::new(
    "parent".to_string(),
    vec![
        Term::Const(Constant::String("Alice".to_string())),
        Term::Const(Constant::String("Bob".to_string())),
    ],
));

let cid = node.store_rule(&fact).await?;
println!("Stored rule with CID: {}", cid);
Source

pub async fn get_rule(&self, cid: &Cid) -> Result<Option<Rule>>

Retrieve a logical rule by CID

Fetches and deserializes a rule from storage.

§Arguments
  • cid - Content identifier of the rule
§Returns

The rule if found, None otherwise

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if let Some(rule) = node.get_rule(&cid).await? {
    println!("Retrieved rule: head={}, body_len={}", rule.head, rule.body.len());
}
Source

pub fn add_fact(&self, fact: Predicate) -> Result<()>

Add a fact to the knowledge base

Adds a logical fact (predicate with no body) to the in-memory knowledge base. Facts are used during inference queries.

§Arguments
  • fact - The predicate to add as a fact
§Example
use ipfrs::{Node, NodeConfig, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Add fact: parent("Alice", "Bob")
let fact = Predicate::new(
    "parent".to_string(),
    vec![
        Term::Const(Constant::String("Alice".to_string())),
        Term::Const(Constant::String("Bob".to_string())),
    ],
);

node.add_fact(fact)?;
Source

pub fn add_rule(&self, rule: Rule) -> Result<()>

Add a rule to the knowledge base

Adds a logical rule (Horn clause) to the in-memory knowledge base. Rules are used during inference queries.

§Arguments
  • rule - The rule to add
§Example
use ipfrs::{Node, NodeConfig, Rule, Predicate, Term};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Add rule: grandparent(X, Z) :- parent(X, Y), parent(Y, Z)
let head = Predicate::new("grandparent".to_string(), vec![
    Term::Var("X".to_string()),
    Term::Var("Z".to_string()),
]);
let body = vec![
    Predicate::new("parent".to_string(), vec![
        Term::Var("X".to_string()),
        Term::Var("Y".to_string()),
    ]),
    Predicate::new("parent".to_string(), vec![
        Term::Var("Y".to_string()),
        Term::Var("Z".to_string()),
    ]),
];

node.add_rule(Rule::new(head, body))?;
Source

pub fn infer(&self, goal: &Predicate) -> Result<Vec<Substitution>>

Run inference query

Executes a logical query using backward chaining inference. Returns all variable substitutions that satisfy the goal.

§Arguments
  • goal - The query predicate to prove
§Returns

Vector of variable substitutions (bindings) that satisfy the goal

§Example
use ipfrs::{Node, NodeConfig, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Add some facts
node.add_fact(Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]))?;

// Query: parent("Alice", X)?
let goal = Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Var("X".to_string()),
]);

let solutions = node.infer(&goal)?;
for solution in solutions {
    println!("Solution: {:?}", solution);
}
Source

pub fn prove(&self, goal: &Predicate) -> Result<Option<Proof>>

Generate proof tree

Constructs a formal proof for a given goal predicate using backward chaining. Returns the proof if one can be found, None otherwise.

§Arguments
  • goal - The goal to prove
§Returns

Proof object if goal can be proven, None otherwise

§Example
use ipfrs::{Node, NodeConfig, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Add some facts
node.add_fact(Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]))?;

// Generate proof
let goal = Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]);

if let Some(proof) = node.prove(&goal)? {
    println!("Proof found: {:?}", proof);
}
Source

pub async fn store_proof(&self, proof: &Proof) -> Result<Cid>

Store a proof and return its CID

Serializes and stores a proof tree as a content-addressed block.

§Arguments
  • proof - The proof to store
§Returns

CID of the stored proof

§Example
use ipfrs::{Node, NodeConfig, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Add fact and generate proof
node.add_fact(Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]))?;

let goal = Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]);

if let Some(proof) = node.prove(&goal)? {
    let cid = node.store_proof(&proof).await?;
    println!("Proof stored with CID: {}", cid);
}
Source

pub async fn get_proof(&self, cid: &Cid) -> Result<Option<Proof>>

Retrieve a proof by CID

Fetches and deserializes a proof from storage.

§Arguments
  • cid - Content identifier of the proof
§Returns

The proof if found, None otherwise

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

if let Some(proof) = node.get_proof(&cid).await? {
    println!("Retrieved proof for goal: {}", proof.goal);
}
Source

pub fn verify_proof(&self, proof: &Proof) -> Result<bool>

Verify a proof against the current knowledge base

Checks if a proof tree is valid by verifying that:

  • All facts exist in the knowledge base
  • All rules exist and are correctly applied
  • All subproofs are valid
§Arguments
  • proof - The proof to verify
§Returns

true if the proof is valid, false otherwise

§Example
use ipfrs::{Node, NodeConfig, Predicate, Term, Constant};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Add fact
node.add_fact(Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]))?;

// Generate and verify proof
let goal = Predicate::new("parent".to_string(), vec![
    Term::Const(Constant::String("Alice".to_string())),
    Term::Const(Constant::String("Bob".to_string())),
]);

if let Some(proof) = node.prove(&goal)? {
    let is_valid = node.verify_proof(&proof)?;
    println!("Proof is valid: {}", is_valid);
}
Source

pub fn kb_stats(&self) -> Result<KnowledgeBaseStats>

Get knowledge base statistics

Returns statistics about the in-memory knowledge base including counts of facts and rules.

§Returns

Knowledge base statistics

§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

let stats = node.kb_stats()?;
println!("Facts: {}, Rules: {}", stats.num_facts, stats.num_rules);
Source

pub async fn save_semantic_index(&self, path: impl AsRef<Path>) -> Result<()>

Save the semantic index to disk

Persists the entire HNSW index including all vectors and CID mappings to a file for later loading.

§Arguments
  • path - Path to save the index file
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Save the semantic index
node.save_semantic_index("semantic.index").await?;
println!("Semantic index saved");
Source

pub async fn load_semantic_index(&self, path: impl AsRef<Path>) -> Result<()>

Load a semantic index from disk

Loads a previously saved HNSW index from disk, replacing the current index.

§Arguments
  • path - Path to the saved index file
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Load the semantic index
node.load_semantic_index("semantic.index").await?;
println!("Semantic index loaded");
Source

pub async fn save_knowledge_base(&self, path: impl AsRef<Path>) -> Result<()>

Save the knowledge base to disk

Persists the entire knowledge base (facts and rules) to a file for later loading.

§Arguments
  • path - Path to save the knowledge base file
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Save the knowledge base
node.save_knowledge_base("knowledge.kb").await?;
println!("Knowledge base saved");
Source

pub async fn load_knowledge_base(&self, path: impl AsRef<Path>) -> Result<()>

Load a knowledge base from disk

Loads a previously saved knowledge base from disk, replacing the current KB.

§Arguments
  • path - Path to the saved knowledge base file
§Example
use ipfrs::{Node, NodeConfig};

let mut node = Node::new(NodeConfig::default())?;
node.start().await?;

// Load the knowledge base
node.load_knowledge_base("knowledge.kb").await?;
println!("Knowledge base loaded");
Source

pub fn peer_id(&self) -> Result<String>

Get local peer ID

Source

pub async fn peers(&self) -> Result<Vec<String>>

Get connected peers

Source

pub async fn connect(&mut self, addr: &str) -> Result<()>

Connect to a peer

Source

pub async fn disconnect(&mut self, peer_id: &str) -> Result<()>

Disconnect from a peer

Source

pub async fn provide(&mut self, cid: &Cid) -> Result<()>

Announce content to DHT (provide)

Source

pub async fn find_providers(&mut self, cid: &Cid) -> Result<()>

Find providers for content in DHT

Source

pub fn network_stats(&self) -> Result<NetworkStats>

Get network statistics

Source

pub fn bitswap_stats(&self) -> Result<BitswapStats>

Get bitswap statistics

Source

pub async fn ping(&mut self, _peer_id: &str) -> Result<()>

Ping a peer (placeholder implementation)

Source

pub async fn find_peer(&mut self, peer_id: &str) -> Result<Vec<String>>

Find a peer’s addresses in the DHT (placeholder implementation)

Source

pub fn bootstrap_peers(&self) -> Result<Vec<String>>

Get bootstrap peers

Source

pub async fn add_bootstrap_peer(&mut self, addr: &str) -> Result<()>

Add a bootstrap peer

Source

pub async fn remove_bootstrap_peer(&mut self, _addr: &str) -> Result<()>

Remove a bootstrap peer

Source

pub async fn dag_export( &self, root: &Cid, path: impl AsRef<Path>, ) -> Result<DagExportStats>

Export a DAG to CAR (Content Addressable aRchive) format

Source

pub async fn dag_import(&self, path: impl AsRef<Path>) -> Result<DagImportStats>

Import blocks from a CAR file

Source

pub async fn pin_add( &self, cid: &Cid, recursive: bool, name: Option<String>, ) -> Result<()>

Pin a block (prevent it from being garbage collected)

Source

pub async fn pin_rm(&self, cid: &Cid, recursive: bool) -> Result<()>

Unpin a block

Source

pub fn pin_ls(&self) -> Result<Vec<PinInfo>>

List all pinned blocks

Source

pub async fn pin_verify(&self) -> Result<Vec<(Cid, bool)>>

Verify all pins are available

Source

pub async fn pin_save(&self, path: impl AsRef<Path>) -> Result<()>

Save pin index to disk

Source

pub async fn pin_load(&self, path: impl AsRef<Path>) -> Result<()>

Load pin index from disk

Source

pub async fn repo_gc(&self, dry_run: bool) -> Result<GcResult>

Run garbage collection

Source

pub async fn repo_fsck(&self) -> Result<FsckResult>

Verify repository integrity

Source

pub async fn repo_fsck_quick(&self) -> Result<FsckResult>

Run quick filesystem check (only verify CIDs match content)

Source

pub fn gc_stats(&self) -> Result<(usize, usize)>

Get garbage collection statistics (without running GC)

Source

pub async fn repo_stat(&self) -> Result<RepoStats>

Get comprehensive repository statistics

Source

pub async fn block_distribution(&self) -> Result<BlockDistribution>

Get block size distribution

Source

pub async fn find_duplicates(&self) -> Result<Vec<Vec<Cid>>>

Find duplicate blocks (same content, different CIDs)

Source

pub async fn largest_blocks(&self, limit: usize) -> Result<Vec<(Cid, u64)>>

Get largest blocks in the repository

Source

pub async fn find_orphaned(&self) -> Result<Vec<Cid>>

Find orphaned blocks (not pinned and not referenced)

Auto Trait Implementations§

§

impl !Freeze for Node

§

impl !RefUnwindSafe for Node

§

impl Send for Node

§

impl !Sync for Node

§

impl Unpin for Node

§

impl !UnwindSafe for Node

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more