-
Notifications
You must be signed in to change notification settings - Fork 47
feat: add F3 proofs cache #1457
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
karlem
wants to merge
36
commits into
main
Choose a base branch
from
f3-proofs-cache
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
95ee4d3
feat: add f3 cert actor
karlem fbe0db6
feat: add fetching from parent
karlem 4c6bf4e
feat: add extra checks and tests
karlem 5f3eb8a
feat: multiple epochs in certificate
karlem fbee757
fix: clippy
karlem 8a5533e
feat: fix comments
karlem 59ab3bc
feat: fix comment
karlem e69da3f
fix: e2e tests
karlem d0c1e99
feat: implement coments changes
karlem 0cb4a42
feat: add proofs service skeleton
karlem 784b599
feat: rebase
karlem 2ed6931
feat: add persistence and include proofs libraryr
karlem d25d646
feat: add perstance, real libraries, wather
karlem 9df2716
feat: implement cache e2e
karlem 6cfde38
feat: add missing feature
karlem bc8076d
feat: debug issues + make functional
karlem 8495902
feat: prepare for review, add debug tooling, add observibility
karlem e2a7de6
feat: remove dead code
karlem d59aece
feat: fix clippy and bug
karlem 3b84809
fix: clippy
karlem 279aacd
fix: ci clippy
karlem e174661
feat: fix comment
karlem ac527de
feat: rebase main
karlem 25a029a
feat: fix test
karlem 221baa3
feat: comments
karlem d77f568
feat: fix comments
karlem 495d7f0
fix: comments
karlem 2fe7b60
feat: fix based on comments and improvements
karlem a4e27bd
feat: fix verifier
karlem 1747f78
feat: fixed cmd
karlem be9c28e
feat: fix most of comments
karlem 0e9612e
feat: re-work cache, generates proofs for epoch, certify child tipssets
karlem ab2ba27
feat: cleanup code, optimize logic
karlem d40e5f4
feat: simplify proofs generation and simplify cache
karlem 7192140
feat: fix minor comments
karlem 7aef2f2
fix: CI
karlem File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Copyright 2022-2025 Protocol Labs | ||
| // SPDX-License-Identifier: Apache-2.0, MIT | ||
|
|
||
| use clap::{Args, Subcommand}; | ||
| use std::path::PathBuf; | ||
|
|
||
| #[derive(Debug, Args)] | ||
| #[command(name = "proof-cache", about = "Inspect and debug F3 proof cache")] | ||
| pub struct ProofCacheArgs { | ||
| #[command(subcommand)] | ||
| pub command: ProofCacheCommands, | ||
| } | ||
|
|
||
| #[derive(Debug, Subcommand)] | ||
| pub enum ProofCacheCommands { | ||
| /// Inspect cache contents | ||
| Inspect { | ||
| /// Database path | ||
| #[arg(long, env = "FM_PROOF_CACHE_DB")] | ||
| db_path: PathBuf, | ||
| }, | ||
| /// Show cache statistics | ||
| Stats { | ||
| /// Database path | ||
| #[arg(long, env = "FM_PROOF_CACHE_DB")] | ||
| db_path: PathBuf, | ||
| }, | ||
| /// Get specific proof by instance ID | ||
| Get { | ||
| /// Database path | ||
| #[arg(long, env = "FM_PROOF_CACHE_DB")] | ||
| db_path: PathBuf, | ||
|
|
||
| /// Instance ID to fetch | ||
| #[arg(long)] | ||
| instance_id: u64, | ||
| }, | ||
| /// Clear the cache | ||
| Clear { | ||
| /// Database path | ||
| #[arg(long, env = "FM_PROOF_CACHE_DB")] | ||
| db_path: PathBuf, | ||
| }, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,194 @@ | ||
| // Copyright 2022-2025 Protocol Labs | ||
| // SPDX-License-Identifier: Apache-2.0, MIT | ||
|
|
||
| use crate::cmd; | ||
| use crate::options::proof_cache::{ProofCacheArgs, ProofCacheCommands}; | ||
| use fendermint_vm_topdown_proof_service::persistence::ProofCachePersistence; | ||
| use std::path::Path; | ||
|
|
||
| cmd! { | ||
| ProofCacheArgs(self) { | ||
| handle_proof_cache_command(self) | ||
| } | ||
| } | ||
|
|
||
| fn handle_proof_cache_command(args: &ProofCacheArgs) -> anyhow::Result<()> { | ||
| match &args.command { | ||
| ProofCacheCommands::Inspect { db_path } => inspect_cache(db_path), | ||
| ProofCacheCommands::Stats { db_path } => show_stats(db_path), | ||
| ProofCacheCommands::Get { | ||
| db_path, | ||
| instance_id, | ||
| } => get_proof(db_path, *instance_id), | ||
| ProofCacheCommands::Clear { db_path } => clear_cache(db_path), | ||
| } | ||
| } | ||
|
|
||
| fn inspect_cache(db_path: &Path) -> anyhow::Result<()> { | ||
| println!("=== Proof Cache Inspection ==="); | ||
| println!("Database: {}", db_path.display()); | ||
| println!(); | ||
|
|
||
| let persistence = ProofCachePersistence::open(db_path)?; | ||
| let entries = persistence.load_all_entries()?; | ||
|
|
||
| if entries.is_empty() { | ||
| println!("\nCache is empty."); | ||
| return Ok(()); | ||
| } | ||
|
|
||
| println!("\nEntries:"); | ||
| println!( | ||
| "{:<12} {:<20} {:<15} {:<15}", | ||
| "Instance ID", "Epochs", "Proof Size", "Signers" | ||
| ); | ||
| println!("{}", "-".repeat(70)); | ||
|
|
||
| for entry in &entries { | ||
| let proof_size = fvm_ipld_encoding::to_vec(&entry.proof_bundle) | ||
| .map(|v| v.len()) | ||
| .unwrap_or(0); | ||
|
|
||
| println!( | ||
| "{:<12} {:<20?} {:<15} {:<15}", | ||
| entry.certificate.gpbft_instance, | ||
| entry.certificate.ec_chain.suffix(), | ||
| format!("{} bytes", proof_size), | ||
| format!("{} signers", entry.certificate.signers.len()) | ||
| ); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| fn show_stats(db_path: &Path) -> anyhow::Result<()> { | ||
| println!("=== Proof Cache Statistics ==="); | ||
| println!("Database: {}", db_path.display()); | ||
| println!(); | ||
|
|
||
| let persistence = ProofCachePersistence::open(db_path)?; | ||
| let entries = persistence.load_all_entries()?; | ||
|
|
||
| if entries.is_empty() { | ||
| println!("Cache is empty."); | ||
| return Ok(()); | ||
| } | ||
|
|
||
| println!("Count: {}", entries.len()); | ||
| println!( | ||
| "Instances: {} - {}", | ||
| entries | ||
| .first() | ||
| .map(|e| e.certificate.gpbft_instance) | ||
| .unwrap_or(0), | ||
| entries | ||
| .last() | ||
| .map(|e| e.certificate.gpbft_instance) | ||
| .unwrap_or(0) | ||
| ); | ||
| println!(); | ||
|
|
||
| // Proof size statistics | ||
| let total_proof_size: usize = entries | ||
| .iter() | ||
| .map(|e| { | ||
| fvm_ipld_encoding::to_vec(&e.proof_bundle) | ||
| .map(|v| v.len()) | ||
| .unwrap_or(0) | ||
| }) | ||
| .sum(); | ||
| let avg_proof_size = total_proof_size / entries.len(); | ||
|
|
||
| println!("Proof Bundle Statistics:"); | ||
| println!( | ||
| " Total Size: {} bytes ({:.2} MB)", | ||
| total_proof_size, | ||
| total_proof_size as f64 / 1024.0 / 1024.0 | ||
| ); | ||
| println!( | ||
| " Average Size: {} bytes ({:.2} KB)", | ||
| avg_proof_size, | ||
| avg_proof_size as f64 / 1024.0 | ||
| ); | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| fn get_proof(db_path: &Path, instance_id: u64) -> anyhow::Result<()> { | ||
| println!("=== Get Proof for Instance {} ===", instance_id); | ||
| println!("Database: {}", db_path.display()); | ||
| println!(); | ||
|
|
||
| let persistence = ProofCachePersistence::open(db_path)?; | ||
| let entries = persistence.load_all_entries()?; | ||
|
|
||
| if entries.is_empty() { | ||
| println!("Cache is empty."); | ||
| return Ok(()); | ||
| } | ||
|
|
||
| let entry = entries | ||
| .iter() | ||
| .find(|e| e.certificate.gpbft_instance == instance_id); | ||
|
|
||
| if let Some(entry) = entry { | ||
| println!("Found proof for instance {}", instance_id); | ||
| println!(); | ||
|
|
||
| // Certificate Details | ||
| println!("F3 Certificate:"); | ||
| println!(" Instance ID: {}", entry.certificate.gpbft_instance); | ||
| println!( | ||
| " Finalized Epochs: {:?}", | ||
| &entry.certificate.ec_chain.suffix() | ||
| ); | ||
| println!( | ||
| " BLS Signature: {} bytes", | ||
| entry.certificate.signature.len() | ||
| ); | ||
| println!(" Signers: {} validators", entry.certificate.signers.len()); | ||
| println!(); | ||
|
|
||
| // Proof Bundle Summary | ||
| let proof_bundle_size = fvm_ipld_encoding::to_vec(&entry.proof_bundle) | ||
| .map(|v| v.len()) | ||
| .unwrap_or(0); | ||
| println!("Proof Bundle:"); | ||
| println!( | ||
| " Total Size: {} bytes ({:.2} KB)", | ||
| proof_bundle_size, | ||
| proof_bundle_size as f64 / 1024.0 | ||
| ); | ||
|
|
||
| if let Some(proof_bundle) = &entry.proof_bundle { | ||
| println!(" Storage Proofs: {}", proof_bundle.storage_proofs.len()); | ||
| println!(" Event Proofs: {}", proof_bundle.event_proofs.len()); | ||
| println!(" Witness Blocks: {}", proof_bundle.blocks.len()); | ||
| println!(); | ||
| } else { | ||
| println!(" No proof bundle found"); | ||
| } | ||
|
|
||
| // Metadata | ||
| println!("Metadata:"); | ||
| println!(" Generated At: {:?}", entry.generated_at); | ||
| println!(" Source RPC: {}", entry.source_rpc); | ||
| } else { | ||
| println!("No proof found for instance {}", instance_id); | ||
| println!(); | ||
| println!("Available instances: {:?}", entries.len()); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| fn clear_cache(db_path: &Path) -> anyhow::Result<()> { | ||
| println!("=== Clear Cache ==="); | ||
| println!("Database: {}", db_path.display()); | ||
| println!(); | ||
|
|
||
| let persistence = ProofCachePersistence::open(db_path)?; | ||
| persistence.clear_all_entries()?; | ||
|
|
||
| Ok(()) | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Misleading CLI output shows count instead of instance IDs
In the
get_prooffunction, when a proof is not found, the error message displays "Available instances: X" where X isentries.len()(the count of entries). This is misleading because the label "Available instances" suggests the user will see a list of instance IDs they can query, but instead they only see a number. Compare this toshow_statswhich correctly labels the count as "Count" and shows actual instance IDs separately. Users who see "Available instances: 5" would reasonably expect to see something like[100, 101, 102, 103, 104]so they know which specific instances to query.