Skip to content

Voyager verification support - #3287

Closed
ametel01 wants to merge 14 commits into
dojoengine:mainfrom
ametel01:voyager-verification-support
Closed

Voyager verification support#3287
ametel01 wants to merge 14 commits into
dojoengine:mainfrom
ametel01:voyager-verification-support

Conversation

@ametel01

@ametel01 ametel01 commented Jul 22, 2025

Copy link
Copy Markdown
Contributor

Description

Adds contract verification to Sozo migrations using the Voyager API.

This change introduces contract verification functionality to the Sozo migration process, allowing users to automatically verify deployed contracts against the Voyager API. It refactors verification options and integrates a new sozo-voyager crate for handling verification logic.

Changes

  • Introduces the sozo-voyager crate for contract verification. This crate handles interaction with the Voyager API, project analysis, and file collection.
  • Adds VerifyOptions struct to bin/sozo/src/commands/options/verify.rs for command-line arguments related to verification, including service selection and API URL configuration.
  • Modifies the migrate command in bin/sozo/src/commands/migrate.rs to incorporate the verification process. A VerificationConfig is created based on the provided options, and the Migration struct is extended to support optional verification. Verification results are displayed after the migration.
  • Updates crates/sozo/ops/Cargo.toml and crates/sozo/ops/src/migrate/mod.rs to include and use the sozo-voyager crate. The Migration struct and Migration::migrate function are modified to optionally perform contract verification using the sozo-voyager crate.
  • Modifies Cargo.toml and Cargo.lock to include and update dependencies related to the new sozo-voyager crate, including reqwest, serde, toml, and url.

Impact

  • Adds the ability to verify contracts deployed during Sozo migrations, enhancing transparency and trust.
  • Introduces a new sozo-voyager crate as a dependency, encapsulating verification logic.
  • Introduces new command-line options for the migrate command, allowing users to configure verification settings.
  • Changes the structure of the Migration struct and Migration::migrate function to accommodate the new verification functionality.
  • No immediate breaking changes are apparent, but the new dependency on sozo-voyager might introduce compatibility issues in the future if the crate's API changes.

Tests

  • Yes
  • No, because they aren't needed
  • No, because I need help

Added to documentation?

  • README.md
  • Dojo Book
  • No documentation needed

Checklist

  • I've formatted my code (scripts/rust_fmt.sh, scripts/cairo_fmt.sh)
  • I've linted my code (scripts/clippy.sh, scripts/docs.sh)
  • I've commented my code
  • I've requested a review after addressing the comments

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added optional contract verification during migration, including support for selecting verification services and tracking verification status.
    • Introduced new command-line options for contract verification, such as service selection, custom API URLs, and watch mode.
    • Integrated verification results summary into migration output, with clear success, failure, or warning indicators.
    • Added a new verification module supporting project analysis, artifact discovery, source file collection, and robust verification job management.
    • Introduced a new HTTP client for interacting with contract verification APIs, including resilient error handling and circuit breaker logic.
    • Added utilities to detect project roots and retrieve Cairo and Scarb versions for verification context.
  • Bug Fixes

    • Improved handling and reporting of verification errors without affecting migration success.
  • Chores

    • Updated and reorganized workspace dependencies and formatting for improved maintainability.
    • Added new internal crates to the workspace to support verification features.
  • Tests

    • Adjusted migration tests to support new verification result fields in migration outcomes.
  • Documentation

    • Enhanced user-facing feedback and messages related to contract verification within migration flows.

ametel01 added 11 commits July 21, 2025 13:04
Adds support for verifying contracts after they are migrated, allowing for increased confidence in the deployed code.

This includes fetching source files, interacting with a verification API, and displaying results to the user.
Enables users to verify deployed contracts using services like Voyager.

Adds flags to specify the verification service and a custom API URL.

Supports watching the verification progress until completion.
Adds support for verifying deployed contracts via external services.

This change introduces contract verification functionality by adding necessary dependencies and implementing the verification logic. It allows users to verify their deployed contracts using services like Voyager. A separate function `create_verification_config` is created to handle constructing verification configurations based on user-provided service options.
The `verify` and `verify_url` parameters from `MigrateArgs` are passed into this function to generate a service specific configuration.
Improves the display of contract verification results by adding color-coding to indicate success, failure, or warnings.

It also ensures that verification failures do not halt the migration process and displays a warning message, allowing users to continue even if some contracts fail verification.
Moves the verification configuration logic into a dedicated `VerifyOptions` struct.

This change promotes modularity and improves the organization of the code by encapsulating verification-related options and their associated logic within a separate module.
Refactors contract verification to use the manifest file for discovering contracts, models, and events.

This change eliminates the need to manually collect declared classes and allows the verifier to automatically verify all deployed artifacts.
It also introduces project root discovery by searching upwards for manifest files and includes all project source files for accurate verification.
Implements contract verification after deployment using a 3rd party API.

Introduces a new module for interacting with the contract verification service,
allowing automated verification of deployed contracts.

Includes retry logic with exponential backoff and a circuit breaker to handle
potential API issues.

Adds new configuration options to control the verification process, such as
timeouts and retry attempts.

Improves source file collection logic to better support various project layouts
and ensure all necessary files are included.
@ametel01
ametel01 marked this pull request as ready for review July 23, 2025 00:04
@coderabbitai

coderabbitai Bot commented Jul 23, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Ohayo sensei! This PR integrates contract verification into the Dojo migration workflow by adding verification options to the migration command, embedding verification logic in the migration process, and introducing the new sozo-voyager crate. It includes configuration, HTTP client, project analysis, verification orchestration, and updates workspace members and dependencies.

Changes

File(s) Change Summary
Cargo.toml Reordered workspace members and dependencies; added crates/sozo/mcp and crates/sozo/voyager; updated dependency formatting; reorganized patch declarations without version changes.
bin/sozo/src/commands/migrate.rs Added VerifyOptions to migration command args; integrated verification config creation; constructed migration with optional verification; extended migration result with verification outcomes; printed color-coded verification summaries; clarified verification failures do not affect migration success.
bin/sozo/src/commands/options/mod.rs Added verify module declaration.
bin/sozo/src/commands/options/verify.rs Introduced VerifyOptions struct with CLI args for verification service, URL, and watch flag; added method to create optional VerificationConfig with validation and defaults.
crates/sozo/ops/Cargo.toml Removed dependencies: async-trait, colored_json, serde, serde_with, toml; added scarb-interop, sozo-voyager; adjusted tokio features; added [package.metadata.cargo-machete] with ignored crate; rearranged dependencies and dev-dependencies.
crates/sozo/ops/src/migrate/mod.rs Added optional verification_config field to Migration; extended MigrationResult with verification_results; added with_verification constructor; modified migrate to conditionally verify contracts asynchronously; added verify_contracts method invoking ContractVerifier and handling verification errors without failing migration.
crates/sozo/ops/src/migration_ui.rs Implemented VerificationUi trait for MigrationUi forwarding update_text_boxed calls.
crates/sozo/ops/src/tests/migration.rs Updated test destructuring patterns to include ignored fields in MigrationResult to accommodate new verification results field.
crates/sozo/voyager/Cargo.toml Added new manifest for sozo-voyager crate with workspace settings and dependencies including reqwest with multipart, serde derive, and tokio time feature; added dev-dependency on tempfile.
crates/sozo/voyager/src/analyzer.rs Added ProjectAnalyzer struct with methods to extract Dojo version, package name, license; discover contract artifacts; find Starknet artifacts; collect and validate source files; and locate contract source files using heuristics and pattern matching.
crates/sozo/voyager/src/client.rs Added VerificationClient for interacting with verification API: sending multipart contract verification requests, polling job status, handling HTTP errors, and parsing responses; implemented CircuitBreaker to manage API failure state and recovery timing.
crates/sozo/voyager/src/config.rs Defined configuration and data types for verification: VerificationConfig, FileInfo, ContractArtifact, ArtifactType, ProjectMetadata; API job status enums and DTOs; conversion from raw job DTO to typed job; error struct; Starknet artifact and manifest structs; and VerificationResult enum with display and success-check methods.
crates/sozo/voyager/src/lib.rs Created new sozo-voyager library crate exposing modules: analyzer, client, config, utils, verifier; publicly re-exported key types and traits including ProjectAnalyzer, VerificationClient, config types, utility functions, and verification components; included comprehensive unit tests for various aspects of verification and project analysis.
crates/sozo/voyager/src/verifier.rs Added ContractVerifier struct to orchestrate contract verification with project analysis and client calls; supports async verification of multiple contracts with UI updates; implements polling with exponential backoff and jitter; returns detailed verification results; added VerificationUi trait for UI updates.
crates/sozo/voyager/src/utils.rs Added utility functions get_project_root to find project root by searching for Scarb.toml or manifest_dev.json, and get_project_versions to retrieve Cairo and Scarb versions with fallback defaults on failure.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI (sozo)
    participant Migration
    participant ContractVerifier
    participant VerificationClient
    participant Verification API

    User->>CLI (sozo): Run migrate command with --verify
    CLI (sozo)->>Migration: Start migration with verification config
    Migration->>Migration: Perform migration steps
    alt Verification enabled
        Migration->>ContractVerifier: verify_deployed_contracts()
        ContractVerifier->>VerificationClient: verify_contract (for each contract)
        VerificationClient->>Verification API: POST /verify
        Verification API-->>VerificationClient: job_id
        loop Polling
            ContractVerifier->>VerificationClient: check_verification_status(job_id)
            VerificationClient->>Verification API: GET /status/{job_id}
            Verification API-->>VerificationClient: status
            alt Success/Failure/Timeout
                ContractVerifier->>Migration: Return verification result
            end
        end
    end
    Migration->>CLI (sozo): Return migration and verification results
    CLI (sozo)->>User: Display migration and verification summary
Loading

Estimated code review effort

5 (~2+ hours)

Possibly related PRs

  • feat(sozo): add MCP sever #3256: Adds the sozo-mcp crate to the workspace and dependencies, closely related to this PR's workspace reorganization and additions.

Suggested reviewers

  • glihm
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (7)
bin/sozo/src/commands/options/verify.rs (2)

28-30: Consider making service URLs configurable, sensei.

The hardcoded service URLs could be made configurable through environment variables for better flexibility in different deployment environments.

-                "voyager" => Url::parse("https://api.voyager.online/beta")?,
-                "voyager-sepolia" => Url::parse("https://sepolia-api.voyager.online/beta")?,
-                "voyager-dev" => Url::parse("https://dev-api.voyager.online/beta")?,
+                "voyager" => Url::parse(
+                    &std::env::var("VOYAGER_API_URL").unwrap_or_else(|_| "https://api.voyager.online/beta".to_string())
+                )?,
+                "voyager-sepolia" => Url::parse(
+                    &std::env::var("VOYAGER_SEPOLIA_API_URL").unwrap_or_else(|_| "https://sepolia-api.voyager.online/beta".to_string())
+                )?,
+                "voyager-dev" => Url::parse(
+                    &std::env::var("VOYAGER_DEV_API_URL").unwrap_or_else(|_| "https://dev-api.voyager.online/beta".to_string())
+                )?,

47-54: Consider making timeout values configurable, sensei.

The hardcoded timeout values might not be suitable for all network conditions or project sizes. With max_attempts=30 and exponential backoff, the total wait time could be excessive.

Consider adding CLI options for these values or using environment variables:

             Ok(Some(VerificationConfig {
                 api_url,
                 watch: self.verify_watch,
                 include_tests: true, // Default to including tests for Dojo projects
-                timeout: 300,        // 5 minutes default timeout
-                verification_timeout: 1800, // 30 minutes total for verification
-                max_attempts: 30,    // Maximum retry attempts
+                timeout: std::env::var("VERIFY_TIMEOUT").ok()
+                    .and_then(|v| v.parse().ok()).unwrap_or(300),
+                verification_timeout: std::env::var("VERIFY_TOTAL_TIMEOUT").ok()
+                    .and_then(|v| v.parse().ok()).unwrap_or(1800),
+                max_attempts: std::env::var("VERIFY_MAX_ATTEMPTS").ok()
+                    .and_then(|v| v.parse().ok()).unwrap_or(30),
             }))
crates/sozo/voyager/src/verifier.rs (1)

34-50: Ohayo! The jitter implementation could be improved, sensei.

While the current implementation works, using system time for randomness isn't ideal for cryptographic or distributed systems use cases.

Consider using a proper random number generator:

+use rand::Rng;
+
     fn add_jitter(&self, duration: Duration) -> Duration {
-        // Use a simple linear congruential generator for jitter
-        // This avoids needing external random dependencies
-        let seed = SystemTime::now()
-            .duration_since(UNIX_EPOCH)
-            .unwrap_or(Duration::from_secs(0))
-            .as_nanos() as u64;
-
-        let jitter_ms = seed % 1000; // 0-999ms jitter
+        let mut rng = rand::thread_rng();
         let base_ms = duration.as_millis() as u64;
 
         // Add ±25% jitter
         let jitter_range = base_ms / 4; // 25% of base duration
-        let actual_jitter = (jitter_ms % (jitter_range * 2)).saturating_sub(jitter_range);
+        let jitter = rng.gen_range(0..jitter_range * 2);
+        let actual_jitter = jitter.saturating_sub(jitter_range);
 
         Duration::from_millis(base_ms.saturating_add(actual_jitter))
     }
crates/sozo/voyager/src/client.rs (1)

26-34: Consider making circuit breaker parameters configurable

Ohayo sensei! The circuit breaker implementation uses hard-coded values for failure_threshold and recovery_timeout. Consider making these configurable through VerificationConfig to allow different environments to tune these parameters based on their needs.

-    fn new() -> Self {
+    fn new(failure_threshold: u32, recovery_timeout: Duration) -> Self {
         Self {
             failure_count: 0,
             last_failure_time: None,
-            failure_threshold: 5, // Open circuit after 5 consecutive failures
-            recovery_timeout: Duration::from_secs(60), // Wait 1 minute before retry
+            failure_threshold,
+            recovery_timeout,
         }
     }
crates/sozo/ops/src/migrate/mod.rs (1)

136-149: Consider making verification failure behavior configurable

Sensei, while it's good that verification failures don't block migration, some users might want stricter behavior. Consider adding a configuration option to fail the migration on verification errors.

 pub struct VerificationConfig {
     // ... existing fields ...
+    /// Whether to fail migration on verification errors
+    pub fail_on_error: bool,
 }
crates/sozo/voyager/src/analyzer.rs (2)

24-50: Inconsistent error handling between similar methods

Ohayo sensei! The extract_dojo_version returns Option while extract_package_name returns Result, but both perform similar file operations. Consider making them consistent by having both return Result for better error propagation.

-    pub fn extract_dojo_version(&self) -> Option<String> {
+    pub fn extract_dojo_version(&self) -> Result<Option<String>> {
         let scarb_toml_path = self.project_root.join("Scarb.toml");

-        let contents = fs::read_to_string(&scarb_toml_path).ok()?;
-        let parsed: toml::Value = toml::from_str(&contents).ok()?;
+        let contents = fs::read_to_string(&scarb_toml_path)
+            .map_err(|e| anyhow!("Failed to read Scarb.toml: {}", e))?;
+        let parsed: toml::Value = toml::from_str(&contents)
+            .map_err(|e| anyhow!("Failed to parse Scarb.toml: {}", e))?;

         // Look for dependencies.dojo.tag
-        parsed.get("dependencies")?.get("dojo")?.get("tag")?.as_str().map(|s| s.to_string())
+        Ok(parsed.get("dependencies")?.get("dojo")?.get("tag")?.as_str().map(|s| s.to_string()))
     }

589-644: Add debug logging to track which file discovery strategy succeeded

Sensei, the multiple fallback strategies are good, but it would be helpful to log which strategy successfully found the file for debugging purposes.

                 if self.file_contains_definition(&content, contract_name) {
+                    debug!("Found contract definition in file: {}", file.name);
                     return Ok(file.name.clone());
                 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c876437 and 1f4c316.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • Cargo.toml (7 hunks)
  • bin/sozo/src/commands/migrate.rs (4 hunks)
  • bin/sozo/src/commands/options/mod.rs (1 hunks)
  • bin/sozo/src/commands/options/verify.rs (1 hunks)
  • crates/sozo/ops/Cargo.toml (1 hunks)
  • crates/sozo/ops/src/migrate/mod.rs (6 hunks)
  • crates/sozo/ops/src/migration_ui.rs (2 hunks)
  • crates/sozo/ops/src/tests/migration.rs (2 hunks)
  • crates/sozo/voyager/Cargo.toml (1 hunks)
  • crates/sozo/voyager/src/analyzer.rs (1 hunks)
  • crates/sozo/voyager/src/client.rs (1 hunks)
  • crates/sozo/voyager/src/config.rs (1 hunks)
  • crates/sozo/voyager/src/lib.rs (1 hunks)
  • crates/sozo/voyager/src/verifier.rs (1 hunks)
🧠 Learnings (9)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
crates/sozo/ops/src/tests/migration.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
crates/sozo/voyager/src/lib.rs (2)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

bin/sozo/src/commands/options/verify.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
bin/sozo/src/commands/migrate.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
Cargo.toml (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

crates/sozo/voyager/src/analyzer.rs (1)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

crates/sozo/ops/src/migrate/mod.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/config.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
crates/sozo/ops/src/tests/migration.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
crates/sozo/voyager/src/lib.rs (2)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

bin/sozo/src/commands/options/verify.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
bin/sozo/src/commands/migrate.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
Cargo.toml (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

crates/sozo/voyager/src/analyzer.rs (1)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

crates/sozo/ops/src/migrate/mod.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/config.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: fmt
🔇 Additional comments (22)
bin/sozo/src/commands/options/mod.rs (1)

6-6: Ohayo sensei! Clean module addition for verification options.

The new verify module declaration properly exposes the verification CLI options, maintaining consistency with the existing module structure.

crates/sozo/ops/src/migration_ui.rs (2)

5-5: Ohayo sensei! Good integration of verification UI trait.

The import of VerificationUi properly enables the migration UI to support verification status updates.


98-102: Ohayo sensei! Clean trait implementation for verification UI.

The VerificationUi trait implementation correctly forwards to the existing update_text_boxed method, enabling seamless integration between the migration UI and verification workflow without code duplication.

crates/sozo/ops/src/tests/migration.rs (2)

88-89: Ohayo sensei! Proper test update for extended migration result.

The destructuring pattern correctly handles the expanded MigrationResult structure by ignoring the new verification-related fields while preserving access to the required manifest and has_changes fields.


99-100: Ohayo sensei! Consistent test pattern for migration results.

The destructuring approach matches the pattern used in the other test function, maintaining consistency while accommodating the extended result structure.

crates/sozo/voyager/Cargo.toml (1)

1-17: Ohayo sensei! Well-structured manifest for the new voyager crate.

The Cargo.toml properly uses workspace inheritance and includes appropriate dependencies for contract verification functionality. The feature selections (multipart for reqwest, derive for serde, time for tokio) align well with the verification use case.

crates/sozo/ops/Cargo.toml (4)

17-17: Ohayo sensei! Good addition of scarb-interop dependency.

The scarb-interop dependency addition supports project analysis functionality needed for the verification workflow.


19-19: Ohayo sensei! Proper integration of sozo-voyager dependency.

The sozo-voyager dependency correctly enables the ops crate to use the new verification functionality.


25-25: Ohayo sensei! Appropriate tokio feature addition.

Adding the "time" feature to tokio supports timeout functionality that's likely needed for verification operations.


40-41: Ohayo sensei! Smart cargo-machete configuration.

The configuration properly ignores the optional sozo-walnut dependency, preventing false positives from the unused dependency checker.

bin/sozo/src/commands/options/verify.rs (1)

6-21: Ohayo! The struct definition looks good, sensei!

The CLI options are well-structured with clear documentation and appropriate default values.

crates/sozo/voyager/src/lib.rs (1)

1-19: Ohayo! Excellent crate structure, sensei!

The module organization is clean and the re-exports provide a convenient public API. The documentation clearly explains the crate's purpose.

bin/sozo/src/commands/migrate.rs (2)

23-23: Ohayo! Clean integration of verification options, sensei!

The addition of VerifyOptions is properly integrated with the existing command structure.

Also applies to: 42-43, 56-56


76-101: Well-structured conditional migration construction, sensei!

The code correctly creates Migration with or without verification based on the configuration.

crates/sozo/voyager/src/verifier.rs (2)

131-134: Good choice of backoff parameters, sensei!

The exponential backoff with 1.5 multiplier and proper bounds (2s to 30s) provides a good balance between responsiveness and API load.


138-199: Excellent retry logic and error handling, sensei!

The polling mechanism properly handles all verification states and includes backoff even for errors to avoid overwhelming the API.

Cargo.toml (1)

6-6: Ohayo! Workspace configuration updates look good, sensei!

The new crates are properly integrated into the workspace structure and dependency declarations.

Also applies to: 18-19, 22-22, 81-84

crates/sozo/ops/src/migrate/mod.rs (1)

69-115: LGTM! Clean implementation of optional verification

Ohayo! The dual constructor pattern nicely maintains backward compatibility while adding the new verification feature. The optional field approach is well-suited for this use case.

crates/sozo/voyager/src/analyzer.rs (1)

554-587: LGTM! Comprehensive file validation

Ohayo! The file validation logic is well-implemented with appropriate size limits and extension checks. The 20MB limit is reasonable for source files.

crates/sozo/voyager/src/config.rs (3)

26-37: LGTM! Reasonable default configuration values

Ohayo sensei! The default timeout values are well-chosen - 5 minutes for HTTP requests and 30 minutes total for verification should handle most cases without being excessive.


74-91: Well-designed status enum with proper unknown handling

The numeric status code mapping with an Unknown variant for unrecognized values is a good defensive programming practice. This will prevent deserialization failures if the API adds new status codes.


186-222: LGTM! User-friendly result representation

The VerificationResult enum provides clear, emoji-enhanced messages that make it easy for users to understand verification outcomes at a glance. The is_success() helper method is a nice touch.

Comment thread bin/sozo/src/commands/migrate.rs
Comment thread crates/sozo/ops/src/migrate/mod.rs Outdated
Comment thread crates/sozo/ops/src/migrate/mod.rs Outdated
Comment thread crates/sozo/voyager/src/analyzer.rs
Comment thread crates/sozo/voyager/src/client.rs Outdated
Comment thread crates/sozo/voyager/src/client.rs Outdated
Comment thread crates/sozo/voyager/src/client.rs
Comment thread crates/sozo/voyager/src/client.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (6)
bin/sozo/src/commands/migrate.rs (1)

103-103: Great work implementing the enum-based matching, sensei!

The verification results display correctly uses pattern matching on VerificationResult enum variants instead of checking for emoji characters in strings, which makes the code more robust and maintainable.

Also applies to: 106-141

crates/sozo/voyager/src/client.rs (4)

18-79: Ohayo! Excellent work on the error handling improvements, sensei!

The HTTP client constructor now properly returns a Result instead of using expect(), and the CircuitBreaker implementation provides robust failure handling with appropriate thresholds.


101-101: The license is still hardcoded, sensei.

Consider making the license configurable through project metadata instead of defaulting to "MIT".

-            .text("license", metadata.license.as_deref().unwrap_or("MIT").to_string());
+            .text("license", metadata.license.as_deref().unwrap_or("MIT").to_string());

Note: The metadata already has a license field that can be populated from the project configuration.


142-239: Great implementation of DTO-based parsing, sensei!

The verification status checking now uses VerificationJobDto for deserialization with proper error handling and fallback logic, which is much more maintainable than manual JSON field extraction.


242-248: Ohayo! Perfect refactoring of JSON manipulation, sensei!

The remove_files_field method now properly parses JSON into serde_json::Value, removes the field, and re-serializes, which is much more robust than manual string manipulation.

crates/sozo/voyager/src/analyzer.rs (1)

519-574: Excellent implementation of depth limiting, sensei!

The recursive file collection now includes proper depth tracking with a reasonable limit of 20 levels, which prevents potential stack overflow on deeply nested directories.

🧹 Nitpick comments (1)
crates/sozo/voyager/src/utils.rs (1)

31-66: Consider extracting the default version constant, sensei.

The implementation handles errors well, but the hardcoded "2.8.0" appears multiple times. Consider extracting it to a constant for easier maintenance.

+const DEFAULT_VERSION: &str = "2.8.0";
+
 /// Get Cairo and Scarb versions from project configuration.
 pub fn get_project_versions() -> Result<(String, String), anyhow::Error> {
     use std::process::Command;

     // Get Cairo version from scarb metadata
     let cairo_version = if let Ok(output) =
         Command::new("scarb").args(["metadata", "--format-version", "1"]).output()
     {
         if output.status.success() {
             let metadata_str = String::from_utf8(output.stdout)?;
             if let Ok(metadata) = serde_json::from_str::<serde_json::Value>(&metadata_str) {
-                metadata["cairo_version"].as_str().unwrap_or("2.8.0").to_string()
+                metadata["cairo_version"].as_str().unwrap_or(DEFAULT_VERSION).to_string()
             } else {
-                "2.8.0".to_string()
+                DEFAULT_VERSION.to_string()
             }
         } else {
-            "2.8.0".to_string()
+            DEFAULT_VERSION.to_string()
         }
     } else {
-        "2.8.0".to_string()
+        DEFAULT_VERSION.to_string()
     };

     // Get Scarb version
     let scarb_version = if let Ok(output) = Command::new("scarb").args(["--version"]).output() {
         if output.status.success() {
             let version_str = String::from_utf8(output.stdout)?;
             // Parse "scarb 2.8.0" format
-            version_str.split_whitespace().nth(1).unwrap_or("2.8.0").to_string()
+            version_str.split_whitespace().nth(1).unwrap_or(DEFAULT_VERSION).to_string()
         } else {
-            "2.8.0".to_string()
+            DEFAULT_VERSION.to_string()
         }
     } else {
-        "2.8.0".to_string()
+        DEFAULT_VERSION.to_string()
     };

     Ok((cairo_version, scarb_version))
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f4c316 and e8af718.

📒 Files selected for processing (8)
  • bin/sozo/src/commands/migrate.rs (4 hunks)
  • crates/sozo/ops/src/migrate/mod.rs (5 hunks)
  • crates/sozo/voyager/src/analyzer.rs (1 hunks)
  • crates/sozo/voyager/src/client.rs (1 hunks)
  • crates/sozo/voyager/src/config.rs (1 hunks)
  • crates/sozo/voyager/src/lib.rs (1 hunks)
  • crates/sozo/voyager/src/utils.rs (1 hunks)
  • crates/sozo/voyager/src/verifier.rs (1 hunks)
🧠 Learnings (4)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
bin/sozo/src/commands/migrate.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
crates/sozo/voyager/src/client.rs (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/analyzer.rs (1)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

🚧 Files skipped from review as they are similar to previous changes (4)
  • crates/sozo/voyager/src/lib.rs
  • crates/sozo/voyager/src/verifier.rs
  • crates/sozo/ops/src/migrate/mod.rs
  • crates/sozo/voyager/src/config.rs
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
bin/sozo/src/commands/migrate.rs (1)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.
crates/sozo/voyager/src/client.rs (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/analyzer.rs (1)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

🔇 Additional comments (5)
bin/sozo/src/commands/migrate.rs (1)

23-23: Ohayo! The verification integration looks solid, sensei!

The implementation correctly adds verification support to the migration command with proper conditional handling based on whether verification is requested.

Also applies to: 42-44, 56-56, 76-101

crates/sozo/voyager/src/utils.rs (1)

6-28: Ohayo! The project root discovery logic looks good, sensei.

The implementation correctly searches upward for project markers and handles edge cases properly with a fallback to the current directory.

crates/sozo/voyager/src/analyzer.rs (3)

25-66: Ohayo! Clean metadata extraction implementation, sensei.

The methods properly handle optional values and provide good error messages when required fields are missing.


69-137: Solid artifact discovery logic, sensei!

The implementation correctly handles different artifact types with appropriate naming conventions and robust error handling for class hash parsing.


620-760: Ohayo! Comprehensive contract file discovery implementation, sensei.

The multi-step approach with pattern matching and fallback strategies ensures reliable contract file detection across different project structures.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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/sozo/voyager/src/client.rs (2)

101-101: Make license configurable instead of hard-coding

Ohayo! The license is still hard-coded as "MIT", but different projects might use different licenses. This was mentioned in a previous review.

-            .text("license", metadata.license.as_deref().unwrap_or("MIT").to_string());
+            .text("license", metadata.license.as_deref().unwrap_or(&config.default_license).to_string());

Consider adding a default_license field to VerificationConfig to make this configurable.


169-191: Use serde-derived structs for JSON parsing

Ohayo sensei! The manual JSON parsing approach with fallback logic is still present. As mentioned in a previous review, this could be improved by using proper serde deserialization.

The current approach of parsing to VerificationJobDto and falling back to remove_files_field on syntax errors is already close to the recommended pattern from the previous review. However, consider defining the DTO to explicitly exclude the problematic files field:

#[derive(Deserialize)]
struct VerificationJobDto {
    #[serde(rename = "jobid")]
    job_id: String,
    status: u64,
    // ... other fields ...
    // Note: no `files` field - serde will ignore it by default
}

This would eliminate the need for the fallback logic entirely.

🧹 Nitpick comments (6)
crates/sozo/voyager/src/client.rs (1)

26-34: Consider making circuit breaker parameters configurable

Ohayo sensei! The circuit breaker implementation looks solid, but the hardcoded threshold and recovery timeout values could limit flexibility in different deployment scenarios.

Consider accepting these as parameters:

-    pub(crate) fn new() -> Self {
+    pub(crate) fn new(failure_threshold: u32, recovery_timeout_secs: u64) -> Self {
         Self {
             failure_count: 0,
             last_failure_time: None,
-            failure_threshold: 5, // Open circuit after 5 consecutive failures
-            recovery_timeout: Duration::from_secs(60), // Wait 1 minute before retry
+            failure_threshold,
+            recovery_timeout: Duration::from_secs(recovery_timeout_secs),
         }
     }

Then update the usage in VerificationClient:

-        Ok(Self { client, config, circuit_breaker: std::sync::Mutex::new(CircuitBreaker::new()) })
+        Ok(Self { 
+            client, 
+            config: config.clone(),
+            circuit_breaker: std::sync::Mutex::new(CircuitBreaker::new(5, 60))
+        })
crates/sozo/voyager/src/lib.rs (1)

122-124: Improve jitter test assertion precision

Ohayo! The jitter test assertion could be more precise about the expected range.

-            assert!(jittered.as_millis() <= base_duration.as_millis() + 3500); // 25% + 1s max jitter
+            // Jitter adds up to 25% of base + up to 999ms
+            let max_jitter = base_duration.as_millis() * 125 / 100 + 999;
+            assert!(jittered.as_millis() <= max_jitter);
crates/sozo/voyager/src/verifier.rs (2)

35-59: Consider using a proper random number generator for jitter

Ohayo! The current jitter implementation using system time as seed could produce predictable patterns. Consider using a proper RNG for better distribution.

use rand::Rng;

pub(crate) fn add_jitter(&self, duration: Duration) -> Duration {
    let mut rng = rand::thread_rng();
    let base_ms = duration.as_millis() as u64;
    
    if base_ms == 0 {
        return Duration::from_millis(rng.gen_range(0..100));
    }
    
    // Add ±25% jitter
    let jitter_range = base_ms / 4;
    let jitter = if jitter_range > 0 {
        rng.gen_range(0..jitter_range * 2) as i64 - jitter_range as i64
    } else {
        rng.gen_range(0..100) as i64
    };
    
    Duration::from_millis((base_ms as i64 + jitter).max(0) as u64)
}

This would require adding rand to the crate dependencies.


77-104: Consider parallel verification for better performance

Ohayo sensei! The current implementation verifies contracts sequentially, which could be slow when dealing with many contracts.

Consider implementing parallel verification with a configurable concurrency limit to improve performance while avoiding overwhelming the API:

use futures::stream::{self, StreamExt};

// In verify_deployed_contracts:
let max_concurrent = self.config.max_concurrent_verifications.unwrap_or(3);
let results = stream::iter(artifacts)
    .map(|artifact| async move {
        // verification logic here
    })
    .buffer_unordered(max_concurrent)
    .collect::<Vec<_>>()
    .await;

This would allow multiple contracts to be verified simultaneously while respecting API rate limits.

crates/sozo/voyager/src/analyzer.rs (2)

589-622: Comprehensive file validation with good security practices

Ohayo sensei! The file validation implements good security measures with size limits and extension whitelisting.

Consider including the actual file size in the error message for better debugging:

                 return Err(anyhow!(
-                    "File {} exceeds maximum size limit of {}MB",
+                    "File {} exceeds maximum size limit of {}MB (actual size: {}MB)",
                     file.path.display(),
-                    MAX_FILE_SIZE / (1024 * 1024)
+                    MAX_FILE_SIZE / (1024 * 1024),
+                    metadata.len() / (1024 * 1024)
                 ));

715-764: Comprehensive pattern matching for contract definitions

Ohayo! The pattern matching covers a wide range of Cairo constructs including Dojo-specific annotations.

Consider using regex for more efficient pattern matching instead of multiple string contains checks:

use regex::Regex;

lazy_static! {
    static ref DEFINITION_REGEX: Regex = Regex::new(
        r"(?x)
        (?:struct|trait|mod|impl|enum)\s+(?:m_|e_)?Position|
        \#\[derive\((?:Model|Event)\)\]\s*\n\s*struct\s+(?:m_|e_)?Position
        "
    ).unwrap();
}

This would reduce the number of string searches and improve performance for large files.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8af718 and 0692e95.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • crates/sozo/voyager/Cargo.toml (1 hunks)
  • crates/sozo/voyager/src/analyzer.rs (1 hunks)
  • crates/sozo/voyager/src/client.rs (1 hunks)
  • crates/sozo/voyager/src/lib.rs (1 hunks)
  • crates/sozo/voyager/src/verifier.rs (1 hunks)
🧠 Learnings (5)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
crates/sozo/voyager/src/lib.rs (2)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/client.rs (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/verifier.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/analyzer.rs (1)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/sozo/voyager/Cargo.toml
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
crates/sozo/voyager/src/lib.rs (2)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/client.rs (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/verifier.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/analyzer.rs (1)

Learnt from: glihm
PR: #2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in crates/dojo/world/src/contracts/abigen/ is auto-generated and should be excluded from code reviews.

🔇 Additional comments (8)
crates/sozo/voyager/src/client.rs (2)

72-79: Previous HTTP client error handling issue has been resolved ✅

The HTTP client creation now properly returns a Result and handles errors gracefully, addressing the previous review comment.


242-248: JSON field removal properly implemented ✅

The remove_files_field method now correctly uses serde_json::Value for parsing and manipulation, addressing the previous review comment about fragile string manipulation.

crates/sozo/voyager/src/lib.rs (2)

150-278: Comprehensive analyzer test coverage ✅

Ohayo sensei! The analyzer tests provide excellent coverage of the ProjectAnalyzer functionality, including:

  • Metadata extraction (Dojo version, package name, license)
  • Contract artifact discovery with proper prefixing
  • File validation for size limits and allowed extensions
  • Security checks for path traversal attempts

The test structure with create_temp_project() helper is clean and maintainable.


280-336: Well-structured circuit breaker tests ✅

The client tests effectively verify:

  • Circuit breaker state transitions
  • Failure threshold behavior
  • Reset functionality on success
  • Default configuration values
crates/sozo/voyager/src/verifier.rs (1)

136-217: Robust retry logic with exponential backoff ✅

The wait_for_verification implementation demonstrates excellent practices:

  • Exponential backoff with configurable multiplier
  • Jitter to prevent request clustering
  • Proper handling of terminal states (success/failure)
  • Graceful degradation on timeout
crates/sozo/voyager/src/analyzer.rs (3)

523-536: Depth limit properly implemented ✅

Ohayo! The recursive file collection now includes proper depth limiting to prevent stack overflow, addressing the previous review comment.


192-210: Clean artifact name extraction logic ✅

The extract_contract_name_from_tag method properly handles:

  • Package name prefix stripping
  • Type-specific prefixing (m_ for models, e_ for events)
  • Graceful fallback for unexpected tag formats

624-679: Robust contract file discovery with multiple strategies ✅

The find_contract_file method implements a comprehensive multi-step approach:

  1. Special handling for models/events (using lib.cairo)
  2. Content-based search for contract definitions
  3. Filename matching with variations
  4. Convention-based fallbacks
  5. Last resort fallback

This layered approach ensures contracts can be found even in non-standard project structures.

Improves contract verification by handling the scenario
where a contract or class has already been verified, preventing
errors and providing a more informative user experience.

Introduces a `VerificationError` enum to handle specific
verification-related errors, including the
"AlreadyVerified" case.

Modifies the `migrate` command to correctly display
a success message when a contract is already verified.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
crates/sozo/voyager/src/client.rs (1)

125-125: License is still hardcoded as "MIT"

Ohayo sensei! As mentioned in the previous review, the license should be configurable rather than defaulting to "MIT". Different projects use different licenses.

-            .text("license", metadata.license.as_deref().unwrap_or("MIT").to_string());
+            .text("license", metadata.license.as_deref().unwrap_or("").to_string());

Consider requiring the license in ProjectMetadata or making it explicit that no license was provided.

🧹 Nitpick comments (4)
crates/sozo/voyager/src/client.rs (2)

51-52: Consider making circuit breaker parameters configurable

Ohayo sensei! The circuit breaker parameters are hardcoded. Consider making them configurable through VerificationConfig for different deployment environments.

-            failure_threshold: 5, // Open circuit after 5 consecutive failures
-            recovery_timeout: Duration::from_secs(60), // Wait 1 minute before retry
+            failure_threshold: 5, // TODO: Make configurable via VerificationConfig
+            recovery_timeout: Duration::from_secs(60), // TODO: Make configurable via VerificationConfig

222-244: JSON parsing improved but still uses fallback workaround

Ohayo! Good improvement using VerificationJobDto for deserialization. The fallback to remove_files_field appears necessary for handling malformed API responses, though ideally this should be fixed on the API side.

Consider documenting why this workaround is needed and tracking when it can be removed once the API is fixed.

crates/sozo/voyager/src/config.rs (2)

29-29: Document beta API endpoint status

Ohayo! The default API URL points to a beta endpoint. Consider adding a comment about the beta status and when this might change.

-            api_url: Url::parse("https://api.voyager.online/beta").unwrap(),
+            // TODO: Update to stable API endpoint when available
+            api_url: Url::parse("https://api.voyager.online/beta").unwrap(),

75-92: Consider consolidating status code mapping

Ohayo! The status code mapping is duplicated between serde attributes and the From implementation. Consider using a single source of truth to avoid maintenance issues.

You could use a match on the enum discriminant or a constant mapping to avoid duplication:

impl VerifyJobStatus {
    pub fn from_code(code: u64) -> Self {
        match code {
            0 => Self::Submitted,
            1 => Self::Compiled,
            2 => Self::CompileFailed,
            3 => Self::Fail,
            4 => Self::Success,
            5 => Self::InProgress,
            _ => Self::Unknown,
        }
    }
}

Then use this in the From implementation.

Also applies to: 161-169

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0692e95 and 07635fb.

📒 Files selected for processing (4)
  • bin/sozo/src/commands/migrate.rs (4 hunks)
  • crates/sozo/voyager/src/client.rs (1 hunks)
  • crates/sozo/voyager/src/config.rs (1 hunks)
  • crates/sozo/voyager/src/verifier.rs (1 hunks)
🧠 Learnings (3)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
crates/sozo/voyager/src/client.rs (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/config.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

🚧 Files skipped from review as they are similar to previous changes (2)
  • bin/sozo/src/commands/migrate.rs
  • crates/sozo/voyager/src/verifier.rs
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: glihm
PR: dojoengine/dojo#2633
File: crates/dojo/world/src/contracts/abigen/world.rs:3809-0
Timestamp: 2024-11-05T04:30:12.852Z
Learning: Code in `crates/dojo/world/src/contracts/abigen/` is auto-generated and should be excluded from code reviews.
Learnt from: glihm
PR: dojoengine/dojo#2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In `crates/dojo/utils/src/tx/mod.rs`, fee token configurations are verified when the `fee_config` is built, making additional validations in the `send_with_cfg` methods redundant.
crates/sozo/voyager/src/client.rs (2)

Learnt from: glihm
PR: #2650
File: bin/sozo/src/commands/migrate.rs:64-65
Timestamp: 2024-11-07T13:57:57.616Z
Learning: In the codebase, the use of into() and try_into() for converting TransactionOptions is intentional. Conversions that may fail use try_into(), while those that cannot fail use into(). This approach is appropriate and should be preserved.

Examples:

  • try_into() is used in bin/sozo/src/commands/migrate.rs and bin/sozo/src/commands/execute.rs where conversions can fail.
  • into() is used in bin/sozo/src/commands/register.rs and bin/sozo/src/commands/auth.rs where conversions are infallible.

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

crates/sozo/voyager/src/config.rs (1)

Learnt from: glihm
PR: #2650
File: crates/dojo/utils/src/tx/mod.rs:201-272
Timestamp: 2024-11-07T14:43:23.530Z
Learning: In crates/dojo/utils/src/tx/mod.rs, fee token configurations are verified when the fee_config is built, making additional validations in the send_with_cfg methods redundant.

🔇 Additional comments (4)
crates/sozo/voyager/src/client.rs (2)

92-99: Great error handling improvement!

Ohayo! The constructor now properly returns a Result and handles HTTP client creation errors gracefully, addressing the previous review feedback perfectly.


294-301: Excellent refactor of JSON field removal!

Ohayo sensei! The JSON manipulation now uses serde_json::Value as suggested in the previous review. This is much more robust than manual string manipulation.

crates/sozo/voyager/src/config.rs (2)

100-185: Well-designed DTO pattern implementation

Ohayo sensei! Excellent separation between the API DTO and domain model. The field mapping with serde rename attributes and the From trait implementation make the code maintainable and clear.


256-282: Nice user-friendly result display implementation

Ohayo sensei! The VerificationResult enum is well-designed with clear variants and user-friendly display messages. The emoji usage adds great visual feedback for CLI users.

@glihm

glihm commented Jul 25, 2025

Copy link
Copy Markdown
Contributor

Will close in favor of #3288.

@glihm glihm closed this Jul 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants