Skip to content
LogoLogo

Metadata

Every tree returns a TreeMetadata snapshot through the MerkleTree trait. It is cheap to build and useful for logging, dashboards, health checks, and benchmarks.

FieldTypeMeaning
leaf_countusizeLogical leaves stored
heightusize0 for an empty tree, 1 for a single leaf
node_countusizeAllocated or materialized nodes (see below)
hash_algorithm&'static strH::algorithm_name(), e.g. "SHA-256"
variant&'static str"BinaryMerkleTree", "SparseMerkleTree", or "MerklePatriciaTrie"
use merkle_core::prelude::*;
use merkle_variants::BinaryMerkleTree;
use merkleforge_hash::Sha256;
 
fn main() -> Result<(), MerkleError> {
    let tree = BinaryMerkleTree::<Sha256>::from_leaves(["a", "b", "c", "d", "e"])?;
    let metadata = tree.metadata();
 
    println!("variant: {}", metadata.variant);
    println!("algorithm: {}", metadata.hash_algorithm);
    println!("leaves: {}", metadata.leaf_count);
    println!("height: {}", metadata.height);
    println!("allocated nodes: {}", metadata.node_count);
 
    assert_eq!(metadata.variant, "BinaryMerkleTree");
    assert_eq!(metadata.hash_algorithm, "SHA-256");
    assert_eq!(metadata.leaf_count, 5);
    assert_eq!(metadata.height, 4); // 5 leaves pad to 8: 8 -> 4 -> 2 -> 1
    assert_eq!(metadata.node_count, 15); // 8 + 4 + 2 + 1
    Ok(())
}

metadata() is a trait method, so bring MerkleTree into scope (the prelude does).

What node_count means per variant

  • Binary: the length of the flat node array, padding included (2 × capacity − 1).
  • Sparse: materialized storage entries (internal, shortcut, and batch nodes). Thanks to shortcut and batch compression this is far smaller than 256 per leaf. Compare with stored_node_count() and unbatched_node_count_estimate().
  • Patricia: materialized trie nodes, also available as node_count().

Serializing metadata

TreeMetadata implements Serialize, so you can log it as JSON:

use merkle_core::prelude::*;
use merkle_variants::SparseMerkleTree;
use merkleforge_hash::Blake3;
 
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut tree = SparseMerkleTree::<Blake3>::new();
    tree.insert([1_u8; 32], b"value")?;
 
    let json = serde_json::to_string(&tree.metadata())?;
    assert!(json.contains("\"variant\":\"SparseMerkleTree\""));
    println!("{json}");
    Ok(())
}

Because its string fields are &'static str, TreeMetadata can't be deserialized from an owned buffer. Treat it as output only.