Skip to content

Commit

Permalink
Merge pull request #2072 from maqi/logging_register_update_history
Browse files Browse the repository at this point in the history
Logging register update history
  • Loading branch information
maqi authored Aug 29, 2024
2 parents 66de2b5 + 2cbe716 commit 7c58573
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
2 changes: 1 addition & 1 deletion sn_client/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use xor_name::XorName;
pub struct ClientRegister {
#[debug(skip)]
client: Client,
pub(crate) register: Register,
pub register: Register,
pub ops: LinkedList<RegisterCmd>, // Cached operations.
}

Expand Down
6 changes: 6 additions & 0 deletions sn_node/tests/storage_payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,12 @@ async fn storage_payment_register_creation_succeeds() -> Result<()> {

assert_eq!(retrieved_reg.read().iter().next().unwrap().1, random_entry);

println!("Current fetched register is {:?}", retrieved_reg.register);
println!(
"Fetched register has update history of {}",
retrieved_reg.register.log_update_history()
);

std::thread::sleep(std::time::Duration::from_millis(1000));
}

Expand Down
80 changes: 78 additions & 2 deletions sn_registers/src/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::{
};

use bls::{PublicKey, SecretKey, Signature};
use crdts::merkle_reg::MerkleReg;
use crdts::merkle_reg::{Hash, MerkleReg};
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
use std::collections::{BTreeSet, HashSet};
use xor_name::XorName;

/// Arbitrary maximum size of a register entry.
Expand Down Expand Up @@ -262,6 +262,82 @@ impl Register {
self.crdt.merkle_reg()
}

/// Log the structure of the MerkleReg within this Register's CRDT as a tree view.
/// This is actually being the `update history` of the register.
pub fn log_update_history(&self) -> String {
let mut output = "MerkleReg Structure:\n".to_string();
let merkle_reg = self.crdt.merkle_reg();
output = format!(
"{output}Total entries: {}\n",
merkle_reg.num_nodes() + merkle_reg.num_orphans()
);

// Find root nodes (entries with no parents)
let roots: Vec<_> = merkle_reg.read().hashes().into_iter().collect();

// Print the tree starting from each root
for (i, root) in roots.iter().enumerate() {
let mut visited = HashSet::new();
Self::print_tree(
root,
merkle_reg,
&mut output,
"",
i == roots.len() - 1,
&mut visited,
);
}

output
}

// Helper function to recursively print the MerkleReg tree
fn print_tree(
hash: &Hash,
merkle_reg: &MerkleReg<Entry>,
output: &mut String,
prefix: &str,
is_last: bool,
visited: &mut HashSet<Hash>,
) {
let pretty_hash = format!("{}", XorName::from_content(hash));
if !visited.insert(*hash) {
*output = format!(
"{}{prefix}{}* {pretty_hash} (cycle detected)\n",
output,
if is_last { "└── " } else { "├── " },
);
return;
}

let entry = if let Some(node) = merkle_reg.node(*hash) {
format!("value: {}", XorName::from_content(&node.value))
} else {
"value: None".to_string()
};
*output = format!(
"{}{prefix}{}{pretty_hash}: {entry}\n",
output,
if is_last { "└── " } else { "├── " },
);

let children: Vec<_> = merkle_reg.children(*hash).hashes().into_iter().collect();
let new_prefix = format!("{prefix}{} ", if is_last { " " } else { "│" });

for (i, child) in children.iter().enumerate() {
Self::print_tree(
child,
merkle_reg,
output,
&new_prefix,
i == children.len() - 1,
visited,
);
}

visited.remove(hash);
}

// Private helper to check the given Entry's size is within define limit,
// as well as check the Register hasn't already reached the maximum number of entries.
fn check_entry_and_reg_sizes(&self, entry: &Entry) -> Result<()> {
Expand Down

0 comments on commit 7c58573

Please sign in to comment.