-
Notifications
You must be signed in to change notification settings - Fork 13
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
fix: verifying service challenges in InsertProof
#189
Conversation
WalkthroughThis pull request introduces significant modifications to the transaction processing and proof verification mechanisms across multiple crates. The changes focus on streamlining the epoch finalization process, enhancing batch transaction execution, and improving service challenge verification. The modifications primarily affect the Changes
Sequence DiagramsequenceDiagram
participant Prover
participant SnarkableTree
participant Batch
participant Transaction
Prover->>SnarkableTree: execute_batch(transactions)
SnarkableTree->>Transaction: process_transaction
Transaction-->>SnarkableTree: return proofs
SnarkableTree->>Batch: init(prev_root, next_root, proofs)
Batch->>Batch: verify()
Batch-->>Prover: return verified batch
Possibly related PRs
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 0
🧹 Nitpick comments (6)
crates/tree/src/proofs.rs (2)
1-2
: Consider using a different map type if ordering or concurrency might be relevant.
Since the code uses a HashMap, this is fine for typical lookup scenarios, but if an alternative data structure is needed for concurrency or guaranteed ordering, consider exploring a BTreeMap or a thread-safe implementation.
30-38
: Method name clarity and initialization approach.
'init' is straightforward, but consider whether a more descriptive name (e.g., 'from_roots_and_proofs') would better convey the purpose. Also, check if any additional batch setup (e.g., service proofs population) should happen here or remain separate.crates/tree/src/snarkable_tree.rs (1)
Line range hint
329-330
: Clarify usage notes for 'execute_block'.
The docstring states this method is 'for testing and historical sync', which is excellent. Ensure that production code references 'execute_batch' instead.crates/node_types/prover/src/prover/mod.rs (2)
357-365
: Guard your DB updates in “finalize_new_epoch.”
Setting the new epoch and writing the new commitment is correct, but if an error occurs after proof generation and before these writes, the system could be inconsistent. Consider adding an atomic or transactional approach if your DB supports it.
Line range hint
373-392
: Prove and verify in one flow.
You generate the proof and immediately verify it using the same client. This ensures correctness, but keep in mind that a malicious or bugged local ProverClient might pass its own proofs. If distributed, consider verifying with an independent, external verifier.crates/tree/src/tests.rs (1)
108-108
: LGTM! Consider extracting common verification patterns.The changes correctly implement the service challenge verification pattern. Consider extracting these common verification steps into helper functions to reduce duplication across tests.
+ fn verify_service_registration(proof: &InsertProof) { + assert!(proof.verify(None).is_ok()); + } + + fn verify_account_creation(proof: &InsertProof, tx_builder: &TransactionBuilder, service_id: &str) { + let service_challenge = tx_builder.get_account(service_id).unwrap().service_challenge(); + assert!(proof.verify(service_challenge).is_ok()); + }Also applies to: 113-114
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
crates/node_types/prover/src/prover/mod.rs
(3 hunks)crates/tree/src/proofs.rs
(3 hunks)crates/tree/src/snarkable_tree.rs
(3 hunks)crates/tree/src/tests.rs
(3 hunks)crates/zk/sp1/src/main.rs
(1 hunks)
🔇 Additional comments (13)
crates/tree/src/proofs.rs (4)
26-26
: Validate the necessity and usage of the 'services' field.
Storing service proofs in a HashMap is a good approach for quick lookups, but ensure that all potential service IDs are present when verifying proofs and that they’re cleared or updated as needed to avoid stale data.
40-70
: Comprehensive verification method.
The bulk verification logic is clear. Remember to handle errors consistently; any partial verification failure stops the whole process, which seems intended. Also note that 'assert_eq!' will panic rather than returning an error if the roots don't match; consider returning an error for easier error handling upstream.
73-84
: Ensure the service account can’t be mutated externally.
The ServiceProof struct directly stores an Account. If further modifications occur externally, it could invalidate proofs. Consider making the Account fields read-only or ensuring that the verification logic always uses a canonical representation.
114-140
: Robust handling of optional service challenges.
The code checks for a service challenge when creating an account, and gracefully errors out if it’s missing. This is correct. Also ensure that the correct variant (Signed) is always used and that subsequent logic doesn’t bypass verification if the challenge is incorrectly formed.
crates/tree/src/snarkable_tree.rs (4)
30-30
: New batch execution method in trait.
Exposing 'execute_batch' at the trait level is a solid design choice. Ensure all implementors resolve consistent error handling, especially partial transaction failures.
41-91
: Handle partial failures gracefully.
• The loop processes transactions and logs a warning without rolling back upon failure. This can lead to partially applied states (some transactions succeed, some fail). Confirm this is intended.
• Overall approach (HashSet for services, building proofs) is coherent.
Line range hint 357-365
: Potential concurrency race concerns.
After successfully generating the batch, you set the DB commitment and epoch outside of any transaction or synchronization. This is likely acceptable for single-thread usage but ensure no concurrency issues if multiple finalizations might occur in parallel.
Line range hint 373-392
: Robust proof generation approach.
The method properly writes the entire batch to stdin, then runs the proof and verifies it. This is secure and straightforward, though for large batches, watch out for memory overhead. The function is otherwise good.
crates/node_types/prover/src/prover/mod.rs (1)
329-330
: “execute_block” partial success logging.
Transactions that fail are not retried or reverted but merely logged. Carefully consider if partial success could cause inconsistent states in recovery scenarios.
crates/zk/sp1/src/main.rs (2)
4-4
: Removed imports for Digest and Proof.
Removing unused imports is good housekeeping, ensuring code remains tidy.
8-10
: Invoke the batch-level verification.
Replacing per-proof verification with “batch.verify()” centralizes logic. This reduces code duplication and is a solid design improvement.
crates/tree/src/tests.rs (2)
88-88
: LGTM! Correct verification for service registration.
The change to verify(None)
is consistent with the service registration verification pattern.
21-21
: LGTM! Consistent handling of service challenges in proof verification.
The changes correctly differentiate between service registration (no challenge needed) and account creation (requires service challenge).
Let's verify this pattern is consistently applied across the codebase:
Also applies to: 29-30
✅ Verification successful
Verification confirms correct service challenge handling pattern
The search results confirm the consistent pattern across the codebase:
- Service registration proofs are verified with
verify(None)
- Account creation proofs require a service challenge and are verified with
verify(service_challenge)
- The implementation in
proofs.rs
properly enforces this by checking for service challenge presence in account creation
Key evidence:
- In
proofs.rs
, the verification logic explicitly requires service challenge for CreateAccount transactions - Test cases in
tests.rs
follow this pattern consistently - The pattern is properly implemented in the core
InsertProof
verification logic
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent usage of verify(None) for service registration
# and verify(service_challenge) for account creation
# Search for service registration verification patterns
echo "Checking service registration verification patterns:"
rg -A 2 "register_service.*commit\(\)" | rg -A 2 "verify"
# Search for account creation verification patterns
echo "Checking account creation verification patterns:"
rg -A 2 "create_account.*commit\(\)" | rg -A 2 "verify"
Length of output: 335
Script:
#!/bin/bash
# Let's try a different approach to find verification patterns
# Search for verify method calls in test files
echo "Searching for verify method calls in tests:"
rg -A 2 "verify\(" --type rust --glob "**/tests.rs"
# Search for InsertProof usage patterns
echo "Searching for InsertProof patterns:"
rg -A 3 "InsertProof" --type rust
# Search for service challenge related code
echo "Searching for service challenge patterns:"
rg -A 2 "service_challenge" --type rust
Length of output: 9392
d61f0f1
to
4b3f3c7
Compare
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.
Actionable comments posted: 2
🧹 Nitpick comments (3)
crates/tree/src/snarkable_tree.rs (1)
41-91
: Consider optimizing batch processing and error handling.The batch processing implementation could be improved in several ways:
- Consider using a builder pattern for constructing service proofs
- Add transaction count metrics
- More descriptive error messages for service account failures
fn execute_batch(&mut self, transactions: Vec<Transaction>) -> Result<Batch> { debug!("creating block with {} transactions", transactions.len()); let prev_commitment = self.get_commitment()?; let mut services = HashSet::new(); + let mut processed = 0; + let mut failed = 0; let mut proofs = Vec::new(); for transaction in transactions { match self.process_transaction(transaction.clone()) { Ok(proof) => { if let Operation::CreateAccount { service_id, .. } = transaction.operation { services.insert(service_id); } - proofs.push(proof) + proofs.push(proof); + processed += 1; } Err(e) => { // Log the error and continue with the next transaction warn!( - "Failed to process transaction: {:?}. Error: {}", - transaction, e + "Failed to process transaction {}: {:?}. Error: {}", + failed + processed + 1, transaction, e ); + failed += 1; } } } let current_commitment = self.get_commitment()?; let mut batch = Batch::init(prev_commitment, current_commitment, proofs); let mut service_proofs: HashMap<String, ServiceProof> = HashMap::new(); for service in services { let service_key_hash = KeyHash::with::<TreeHasher>(&service); let response = self.get(service_key_hash)?; match response { Found(account, proof) => { let service_proof = ServiceProof { root: current_commitment, service: *account, proof: proof.proof, }; service_proofs.insert(service.clone(), service_proof); } NotFound(proof) => { - bail!("Service account not found: {:?}", proof); + bail!("Service account not found for service ID {}: {:?}", service, proof); } } } batch.services = service_proofs; + debug!("Batch execution complete: {} processed, {} failed", processed, failed); Ok(batch) }crates/node_types/prover/src/prover/mod.rs (2)
329-330
: Improve documentation for execute_block.The comment should explain why this method should only be used for testing and historical sync.
- // should only be called for testing and historical sync, it does not - // generate the Batch object for proof generation. + /// This method should only be used for testing and historical sync because: + /// 1. It does not generate the Batch object required for proof generation + /// 2. It lacks the service challenge verification present in execute_batch + /// 3. It may not maintain consistency guarantees required for production use
357-365
: Consider transaction atomicity in finalize_new_epoch.The database updates should be atomic to prevent inconsistencies in case of failures.
Consider wrapping the commitment and epoch updates in a transaction:
self.db.transaction(|tx| { tx.set_commitment(&new_epoch_height, &batch.new_root)?; tx.set_epoch(&new_epoch_height)?; Ok(()) })?;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
crates/node_types/prover/src/prover/mod.rs
(3 hunks)crates/tree/src/proofs.rs
(3 hunks)crates/tree/src/snarkable_tree.rs
(3 hunks)crates/tree/src/tests.rs
(3 hunks)crates/zk/sp1/src/main.rs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- crates/zk/sp1/src/main.rs
- crates/tree/src/tests.rs
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: integration-test
- GitHub Check: unused dependencies
- GitHub Check: unit-test
🔇 Additional comments (3)
crates/tree/src/proofs.rs (2)
26-27
: LGTM!The new
services
field in theBatch
struct is well-placed to store service proofs for verification.
31-38
: LGTM!The
init
method provides a clean way to construct a newBatch
instance.crates/node_types/prover/src/prover/mod.rs (1)
Line range hint
373-392
: LGTM!The changes to
prove_epoch
simplify the interface by using theBatch
struct and maintain proper error handling.
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.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
crates/node_types/prover/src/prover/mod.rs (1)
Line range hint
329-352
: Consider performance and error handling improvements.The current implementation has several areas for improvement:
- Sequential processing of transactions might be inefficient for large blocks
- Failed transactions are only logged without being collected for analysis
- No batch size limits could lead to memory issues
Consider this improved implementation:
async fn execute_block(&self, transactions: Vec<Transaction>) -> Result<Vec<Proof>> { debug!("executing block with {} transactions", transactions.len()); + if transactions.len() > 1000 { + warn!("Large block size: {} transactions", transactions.len()); + } let mut proofs = Vec::new(); + let mut failed_transactions = Vec::new(); for transaction in transactions { match self.process_transaction(transaction.clone()).await { Ok(proof) => proofs.push(proof), Err(e) => { - // Log the error and continue with the next transaction + failed_transactions.push((transaction.clone(), e.to_string())); warn!( "Failed to process transaction: {:?}. Error: {}", transaction, e ); } } } + if !failed_transactions.is_empty() { + warn!( + "Failed to process {} transactions: {:?}", + failed_transactions.len(), + failed_transactions + ); + } Ok(proofs) }
♻️ Duplicate comments (2)
crates/tree/src/proofs.rs (2)
70-70
: 🛠️ Refactor suggestionReplace
assert_eq!
with error handling inBatch::verify
Using
assert_eq!
will cause a panic if the roots do not match, which is undesirable in a production environment. Instead, return an error to gracefully handle the mismatch and provide a meaningful error message.Apply this diff to replace
assert_eq!
with error handling:- assert_eq!(root, self.new_root); + if root != self.new_root { + return Err(anyhow!("Computed root does not match expected new root")); + }
122-147
: 🛠️ Refactor suggestionAdd error handling for unexpected challenge types in
InsertProof::verify
The current pattern matching on
service_challenge
andchallenge
assumes specific variants, which could lead to panics if different variants are encountered. Implementing exhaustivematch
statements will handle all possible cases and return appropriate errors, enhancing robustness.Apply this diff to improve error handling:
// If we are creating an account, we need to additionally verify the service challenge if let Operation::CreateAccount { id, service_id, challenge, key, } = &self.tx.operation { let hash = Digest::hash_items(&[id.as_bytes(), service_id.as_bytes(), &key.to_bytes()]); - if service_challenge.is_none() { - return Err(anyhow!( - "Service challenge is missing for CreateAccount verification" - )); - } - - let ServiceChallenge::Signed(challenge_vk) = service_challenge.unwrap(); - let ServiceChallengeInput::Signed(challenge_signature) = challenge; + let service_challenge = service_challenge.ok_or_else(|| anyhow!( + "Service challenge is missing for CreateAccount verification" + ))?; + let challenge_vk = match service_challenge { + ServiceChallenge::Signed(vk) => vk, + _ => return Err(anyhow!("Invalid service challenge type")), + }; + let challenge_signature = match challenge { + ServiceChallengeInput::Signed(sig) => sig, + _ => return Err(anyhow!("Invalid challenge input type")), + }; challenge_vk.verify_signature(&hash.to_bytes(), challenge_signature)?; }
🧹 Nitpick comments (2)
crates/tree/src/proofs.rs (1)
47-47
: Remove debug statement left in codeThe
dbg!
macro on line 47 is intended for debugging and should be removed in production code to prevent unnecessary console output and potential performance impacts.Apply this diff to remove the debug statement:
- dbg!("keys: {}", self.services.keys());
crates/tree/src/snarkable_tree.rs (1)
82-82
: Avoid including debug information in error messagesIncluding the debug representation of
proof
in the error message when a service account is not found may expose sensitive internal data. It is recommended to provide a more generic error message.Apply this diff to adjust the error message:
- bail!("Service account not found: {:?}", proof); + bail!("Service account not found for service: {}", service);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
crates/node_types/prover/src/prover/mod.rs
(3 hunks)crates/storage/src/rocksdb.rs
(2 hunks)crates/tree/src/proofs.rs
(3 hunks)crates/tree/src/snarkable_tree.rs
(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: unit-test
- GitHub Check: clippy
- GitHub Check: unused dependencies
- GitHub Check: integration-test
🔇 Additional comments (5)
crates/storage/src/rocksdb.rs (2)
160-167
: Confirm handling ofNone
values when writing to the databaseWhen writing values in
write_node_batch
, aNone
value results in an empty byte array being written to the database. Verify that this behavior aligns with the intended storage semantics and does not introduce ambiguity between an absent key and a key with an empty value. Explicitly handling deletions or using a sentinel value might prevent potential misinterpretations.To ensure consistency, you might want to check how other parts of the codebase handle
None
values and align this method accordingly.
112-126
:⚠️ Potential issueVerify the correctness of key iteration in
get_value_option
The use of
rocksdb::IteratorMode::From
withDirection::Reverse
starting frommax_key
may not yield the expected results whenmax_key
does not exist in the database. This could lead to missing the correct value or encountering incorrect data. Please ensure that the iterator correctly retrieves the closest key less than or equal tomax_key
, especially whenmax_key
isn't present.To verify this concern, consider adding test cases where
max_version
doesn't correspond to an existing key and observe ifget_value_option
still returns the correct value. If discrepancies are found, adjustments to the iteration logic may be necessary.crates/tree/src/snarkable_tree.rs (1)
41-88
: Efficient implementation of transaction batch processingThe
execute_batch
method effectively processes transactions in a batch, collects proofs, and appropriately handles errors by logging warnings without halting the entire batch. This enhances performance and maintains robustness in transaction processing.crates/node_types/prover/src/prover/mod.rs (2)
357-359
: Verify batch execution maintains transaction order.The switch to batch execution looks good, but we should verify that transaction order is preserved as it's crucial for deterministic state transitions.
Also applies to: 361-361
✅ Verification successful
Batch execution correctly maintains transaction order
The implementation in
snarkable_tree.rs
processes transactions sequentially using ordered vectors, ensuring transaction order is preserved. No further changes needed.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Find the implementation of execute_batch to verify order preservation ast-grep --pattern 'fn execute_batch($params) { $$$ }'Length of output: 58
Script:
#!/bin/bash # Try different approaches to find execute_batch implementation # 1. Search for execute_batch definition with context rg "execute_batch" -t rust -A 5 # 2. Look for trait definitions or implementations containing execute_batch ast-grep --pattern 'trait $_ { $$$ fn execute_batch($$$); $$$ }' # 3. Search for tests showing usage rg "execute_batch.*test" -t rustLength of output: 1713
374-374
: Verify batch validation and proof compatibility.The consolidation of parameters into a
Batch
struct improves code organization. However, ensure:
- The batch is properly validated before proof generation
- The proof generation is compatible with the new batch structure
Also applies to: 392-393
✅ Verification successful
Batch validation and proof compatibility verified.
The Batch struct and proof generation are properly integrated:
- Batch contains required fields (prev_root, new_root, services, proofs)
- prove_epoch safely handles the Batch through immutable reference and SP1Stdin
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Find Batch struct definition and validation ast-grep --pattern 'struct Batch { $$$ }' # Find SP1Stdin implementation for Batch ast-grep --pattern 'impl $_ for SP1Stdin { $$$ }'Length of output: 99
Script:
#!/bin/bash # Search for Batch struct definition and usage rg "struct Batch" -A 5 rg "impl.*Batch" -A 5 # Search for proof generation code rg "fn prove_epoch.*Batch" -A 10Length of output: 66302
Script:
#!/bin/bash # Find Batch validation and usage rg "fn.*Batch" -A 5 rg "impl.*Batch" -A 5 # Find where Batch fields are used rg "batch\.(prev_root|new_root|services|proofs)" -A 3Length of output: 69210
830d654
to
ba77c57
Compare
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.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
crates/node_types/prover/src/prover/mod.rs
(3 hunks)crates/storage/src/rocksdb.rs
(2 hunks)crates/tree/src/proofs.rs
(3 hunks)crates/tree/src/snarkable_tree.rs
(3 hunks)crates/tree/src/tests.rs
(3 hunks)crates/zk/sp1/src/main.rs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- crates/zk/sp1/src/main.rs
- crates/tree/src/tests.rs
- crates/storage/src/rocksdb.rs
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: unused dependencies
- GitHub Check: integration-test
- GitHub Check: clippy
- GitHub Check: build-and-push-image
- GitHub Check: unit-test
🔇 Additional comments (8)
crates/tree/src/proofs.rs (4)
31-38
: LGTM!The initialization logic is clean and straightforward.
70-70
: Consider adding error handling for root mismatch.Replace
assert_eq!
with a proper error handling mechanism for better error reporting.
89-91
: LGTM!The delegation to account's service_challenge method is clean and appropriate.
122-147
: Add defensive checks for service challenge verification.The service challenge verification could be more robust.
crates/tree/src/snarkable_tree.rs (1)
41-88
: LGTM! Well-structured batch processing implementation.The implementation has good error handling and thorough service proof generation.
crates/node_types/prover/src/prover/mod.rs (3)
352-353
: Update comment to reflect all usage scenarios.The comment is partially inaccurate. While the method is indeed used for testing and historical sync, it's also used in regular epoch processing through the
process_epoch
method.
380-394
: LGTM! Clean epoch finalization implementation.The implementation properly executes and verifies the batch before finalizing the epoch.
Line range hint
397-423
: LGTM! Well-structured proof generation.The refactored implementation using
Batch
reference improves code clarity.
cf14f70
to
e862bdf
Compare
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.
Actionable comments posted: 3
♻️ Duplicate comments (2)
crates/tree/src/proofs.rs (1)
127-146
: 🛠️ Refactor suggestionImprove error handling and add defensive checks.
The service challenge verification could be more robust:
- Use
bail!
macro for error handling- Add defensive pattern matching
- Early return for non-CreateAccount operations
- if let Operation::CreateAccount { + let operation = match &self.tx.operation { + op @ Operation::CreateAccount { .. } => op, + _ => return Ok(()) // Early return for non-CreateAccount operations + }; + + if let Operation::CreateAccount { id, service_id, challenge, key, - } = &self.tx.operation + } = operation { let hash = Digest::hash_items(&[id.as_bytes(), service_id.as_bytes(), &key.to_bytes()]); if service_challenge.is_none() { - return Err(anyhow!( + bail!( "Service challenge is missing for CreateAccount verification" - )); + ); } - let ServiceChallenge::Signed(challenge_vk) = service_challenge.unwrap(); - let ServiceChallengeInput::Signed(challenge_signature) = challenge; + let challenge_vk = match service_challenge.unwrap() { + ServiceChallenge::Signed(vk) => vk, + _ => bail!("Invalid service challenge type"), + }; + let challenge_signature = match challenge { + ServiceChallengeInput::Signed(sig) => sig, + _ => bail!("Invalid challenge input type"), + }; challenge_vk.verify_signature(&hash.to_bytes(), challenge_signature)?; }crates/node_types/prover/src/prover/mod.rs (1)
352-353
: 🛠️ Refactor suggestionUpdate comment to reflect all usage scenarios.
The comment is partially inaccurate. The method is also used in regular epoch processing through the
process_epoch
method.- // should only be called for testing and historical sync, it does not - // generate the Batch object for proof generation. + /// Executes a block of transactions and generates proofs. + /// + /// Used in three scenarios: + /// 1. Testing + /// 2. Historical sync + /// 3. Regular epoch processing through `process_epoch` + /// + /// Note: This method does not generate the Batch object required for proof generation.
🧹 Nitpick comments (4)
crates/tree/src/proofs.rs (2)
26-26
: Add documentation for theservices
field.The field's purpose and relationship to service proofs should be documented.
+ /// Map of service IDs to their corresponding service proofs, used for verifying + /// service challenges during account creation. pub services: HashMap<String, ServiceProof>,
81-85
: Add documentation for theServiceProof
struct and its fields.The struct and its fields lack documentation explaining their purpose and usage.
+/// Represents a proof of a service account's existence and its challenge. +/// Used during account creation to verify service challenges. pub struct ServiceProof { + /// The root hash at which this proof is valid pub root: Digest, + /// Merkle proof of the service account's existence pub proof: SparseMerkleProof<TreeHasher>, + /// The service account containing the challenge pub service: Account, }crates/tree/src/snarkable_tree.rs (1)
41-88
: Add documentation for theexecute_batch
method.The method lacks documentation explaining its purpose, parameters, and return value.
+ /// Executes a batch of transactions and generates corresponding proofs. + /// + /// # Arguments + /// * `transactions` - Vector of transactions to process + /// + /// # Returns + /// * `Result<Batch>` - A batch containing proofs and service verifications + /// + /// # Errors + /// * When service account retrieval fails + /// * When service account is not found fn execute_batch(&mut self, transactions: Vec<Transaction>) -> Result<Batch> {crates/node_types/prover/src/prover/mod.rs (1)
Line range hint
397-416
: Add documentation for the updatedprove_epoch
method.The method's signature has changed significantly but lacks updated documentation.
+ /// Generates a proof for an epoch using the provided batch. + /// + /// # Arguments + /// * `epoch_height` - The height of the epoch being proved + /// * `batch` - The batch containing proofs and commitments + /// + /// # Returns + /// * `Result<FinalizedEpoch>` - The finalized epoch with proof and signature async fn prove_epoch(&self, epoch_height: u64, batch: &Batch) -> Result<FinalizedEpoch> {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
crates/node_types/prover/src/prover/mod.rs
(3 hunks)crates/storage/src/rocksdb.rs
(2 hunks)crates/tree/src/proofs.rs
(3 hunks)crates/tree/src/snarkable_tree.rs
(3 hunks)crates/tree/src/tests.rs
(3 hunks)crates/zk/sp1/src/main.rs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- crates/zk/sp1/src/main.rs
- crates/tree/src/tests.rs
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: integration-test
- GitHub Check: clippy
- GitHub Check: unused dependencies
- GitHub Check: build-and-push-image
- GitHub Check: unit-test
🔇 Additional comments (2)
crates/tree/src/proofs.rs (1)
69-69
: 🛠️ Refactor suggestionReplace assertion with proper error handling.
Using
assert_eq!
could cause a panic. Consider returning a proper error instead.- assert_eq!(root, self.new_root); + if root != self.new_root { + return Err(anyhow!("Root mismatch: computed={:?}, expected={:?}", root, self.new_root)); + }Likely invalid or redundant comment.
crates/tree/src/snarkable_tree.rs (1)
30-30
: Align method naming with existing conventions.For consistency, consider using either:
process_batch
to align withprocess_transaction
, orexecute_batch
and renameprocess_transaction
toexecute_transaction
Also applies to: 41-41
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.
Actionable comments posted: 0
♻️ Duplicate comments (2)
crates/tree/src/proofs.rs (2)
70-70
: 🛠️ Refactor suggestionConsider adding error handling for root mismatch.
The
assert_eq!
macro should be replaced with a proper error return when the computed root doesn't match the expected new root.- assert_eq!(root, self.new_root); + if root != self.new_root { + bail!("Computed root {:?} does not match expected new root {:?}", root, self.new_root); + }
122-145
: 🛠️ Refactor suggestionAdd defensive checks for service challenge verification.
The service challenge verification could be more robust with early returns and type assertion safety.
pub fn verify(&self, service_challenge: Option<&ServiceChallenge>) -> Result<()> { self.non_membership_proof.verify_nonexistence().context("Invalid NonMembershipProof")?; let mut account = Account::default(); account.process_transaction(&self.tx)?; // If we are creating an account, we need to additionally verify the service challenge - if let Operation::CreateAccount { + let operation = match &self.tx.operation { + op @ Operation::CreateAccount { .. } => op, + _ => return Ok(()) // Early return for non-CreateAccount operations + }; + + if let Operation::CreateAccount { id, service_id, challenge, key, - } = &self.tx.operation + } = operation { let hash = Digest::hash_items(&[id.as_bytes(), service_id.as_bytes(), &key.to_bytes()]); if service_challenge.is_none() { - return Err(anyhow!( + bail!( "Service challenge is missing for CreateAccount verification" - )); + ); } - let ServiceChallenge::Signed(challenge_vk) = service_challenge.unwrap(); - let ServiceChallengeInput::Signed(challenge_signature) = challenge; + let challenge_vk = match service_challenge.unwrap() { + ServiceChallenge::Signed(vk) => vk, + _ => bail!("Invalid service challenge type"), + }; + let challenge_signature = match challenge { + ServiceChallengeInput::Signed(sig) => sig, + _ => bail!("Invalid challenge input type"), + }; challenge_vk.verify_signature(&hash.to_bytes(), challenge_signature)?; }
🧹 Nitpick comments (1)
crates/tree/src/snarkable_tree.rs (1)
41-63
: Add error context for transaction processing failures.Consider adding more context to the error messages to help with debugging.
Err(e) => { // Log the error and continue with the next transaction warn!( - "Failed to process transaction: {:?}. Error: {}", + "Failed to process transaction in batch: {:?}. Error: {}. Skipping...", transaction, e ); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
crates/node_types/prover/src/prover/mod.rs
(3 hunks)crates/tree/src/proofs.rs
(3 hunks)crates/tree/src/snarkable_tree.rs
(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: unused dependencies
- GitHub Check: clippy
- GitHub Check: integration-test
- GitHub Check: unit-test
- GitHub Check: build-and-push-image
🔇 Additional comments (8)
crates/tree/src/proofs.rs (3)
31-38
: LGTM!The initialization logic is clean and straightforward.
71-75
: LGTM!The service proof verification logic is thorough and well-implemented.
89-91
: LGTM!The function is well-named and has a clear purpose.
crates/tree/src/snarkable_tree.rs (1)
69-85
: LGTM!The service proof collection logic is thorough and handles error cases appropriately.
crates/node_types/prover/src/prover/mod.rs (4)
352-353
: Update comment to reflect all usage scenarios.The comment is partially inaccurate. While the method is indeed used for testing and historical sync, it's also used in regular epoch processing through the
process_epoch
method.Run the following script to verify the usage:
#!/bin/bash # Find all usages of execute_block to verify its scope rg -p "execute_block" --type rust
Line range hint
354-371
: LGTM!The transaction processing logic is well-implemented with proper error handling.
380-382
: Add error handling for batch execution and verification.The batch execution and verification could fail. Consider adding proper error context.
let mut tree = self.tree.write().await; - let batch = tree.process_batch(transactions)?; - batch.verify()?; + let batch = tree.process_batch(transactions) + .context("Failed to execute transaction batch")?; + batch.verify() + .context("Failed to verify transaction batch")?;
Line range hint
397-416
: LGTM!The function is well-structured with proper error handling. The consolidation of parameters into a
Batch
object improves code organization.
Summary by CodeRabbit
New Features
process_batch
method for transaction processing.Bug Fixes
Tests