Skip to content
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

feat(katana): state trie #2607

Merged
merged 2 commits into from
Nov 1, 2024
Merged

feat(katana): state trie #2607

merged 2 commits into from
Nov 1, 2024

Conversation

kariy
Copy link
Member

@kariy kariy commented Nov 1, 2024

implement class and contract trie for computing the global state root using bonsai-trie

Copy link

codecov bot commented Nov 1, 2024

Codecov Report

Attention: Patch coverage is 26.87861% with 253 lines in your changes missing coverage. Please review.

Project coverage is 54.92%. Comparing base (66b76e6) to head (997a626).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
crates/katana/storage/db/src/trie/mod.rs 0.00% 72 Missing ⚠️
...s/katana/storage/provider/src/providers/db/trie.rs 0.00% 70 Missing ⚠️
crates/katana/storage/db/src/trie/contract.rs 0.00% 47 Missing ⚠️
crates/katana/storage/db/src/trie/class.rs 0.00% 26 Missing ⚠️
.../katana/storage/provider/src/providers/fork/mod.rs 0.00% 18 Missing ⚠️
crates/katana/storage/provider/src/lib.rs 0.00% 14 Missing ⚠️
crates/katana/storage/db/src/models/trie.rs 90.00% 4 Missing ⚠️
crates/katana/storage/provider/src/traits/trie.rs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2607      +/-   ##
==========================================
- Coverage   55.12%   54.92%   -0.21%     
==========================================
  Files         385      392       +7     
  Lines       47775    48121     +346     
==========================================
+ Hits        26337    26429      +92     
- Misses      21438    21692     +254     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kariy kariy merged commit 218cac9 into main Nov 1, 2024
12 of 14 checks passed
@kariy kariy deleted the katana/trie branch November 1, 2024 18:27
Copy link

coderabbitai bot commented Nov 1, 2024

Walkthrough

Ohayo! This pull request introduces significant changes across several Cargo.toml files and Rust source files within the katana project. Key modifications include the addition of new crates and dependencies, specifically bitvec, and updates to existing dependencies like starknet-types-core. New modules and types related to trie data structures are introduced, enhancing the database's functionality. The changes also include new trait implementations for handling class and contract state updates, integrating these functionalities into the existing provider architecture.

Changes

File Path Change Summary
Cargo.toml - Added workspace member: "crates/katana/trie"
- Added dependency: bitvec = "1.0.1"
- Updated starknet-types-core from 0.1.6 to 0.1.7, added feature "hash"
crates/katana/storage/db/Cargo.toml - Added dependencies: katana-trie, starknet, starknet-types-core, bitvec, smallvec
- Removed starknet from [dev-dependencies]
- Set workspace = true for new dependencies
crates/katana/storage/db/src/codecs/postcard.rs - Added type: TrieDatabaseValue for compression and decompression implementations
crates/katana/storage/db/src/lib.rs - Added new module: pub mod trie;
crates/katana/storage/db/src/models/mod.rs - Added new module: pub mod trie;
crates/katana/storage/db/src/models/trie.rs - Added enum: TrieDatabaseKeyType
- Added struct: TrieDatabaseKey
- Added type alias: TrieDatabaseValue
- Implemented Encode and Decode traits for TrieDatabaseKey
crates/katana/storage/db/src/tables.rs - Added trait: pub trait Trie
- Implemented Trie for ClassTrie, ContractTrie, ContractStorageTrie
- Updated NUM_TABLES to 26
crates/katana/storage/db/src/trie/class.rs - Added struct: ClassTrie<Tx: DbTxMut>
- Implemented methods for managing class data in a trie
crates/katana/storage/db/src/trie/contract.rs - Added structs: StorageTrie<Tx: DbTxMut>, ContractTrie<Tx: DbTxMut>
- Implemented methods for managing contract state in a trie
crates/katana/storage/db/src/trie/mod.rs - Added struct: TrieDb<Tb: tables::Trie, Tx: DbTxMut>
- Implemented various database methods
crates/katana/storage/provider/Cargo.toml - Added dependencies: katana-trie, bitvec, starknet-types-core with workspace feature
crates/katana/storage/provider/src/lib.rs - Implemented ClassTrieWriter and ContractTrieWriter traits for BlockchainProvider<Db>
crates/katana/storage/provider/src/providers/db/mod.rs - Added new module: pub mod trie;
crates/katana/storage/provider/src/providers/db/trie.rs - Added struct: ContractLeaf
- Implemented insert_updates methods for ClassTrieWriter and ContractTrieWriter
crates/katana/storage/provider/src/providers/fork/mod.rs - Added insert_updates methods for ClassTrieWriter and ContractTrieWriter with placeholder logic
crates/katana/storage/provider/src/traits/mod.rs - Added new module: pub mod trie;
crates/katana/storage/provider/src/traits/trie.rs - Added traits: ClassTrieWriter and ContractTrieWriter, each with insert_updates method
crates/katana/trie/Cargo.toml - New package declaration and dependencies for katana-trie
crates/katana/trie/src/lib.rs - Added trait: BonsaiTrieDb
- Implemented functions for Merkle root and contract state hash computation

Possibly related PRs

Suggested reviewers

  • glihm

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 21

🧹 Outside diff range and nitpick comments (14)
crates/katana/trie/Cargo.toml (1)

8-17: Consider using workspace inheritance for slab dependency.

Ohayo sensei! While most dependencies properly use workspace inheritance, the slab = "0.4.9" dependency has a hard-coded version. This could lead to version inconsistencies if slab is used across multiple crates in the workspace.

Consider moving the slab dependency to the workspace root and using .workspace = true here for consistent version management:

-slab = "0.4.9"
+slab.workspace = true
crates/katana/storage/provider/src/traits/trie.rs (3)

1-8: Add module-level documentation.

Ohayo! Consider adding a module-level documentation comment (//!) explaining the purpose of these traits and their role in the state trie implementation.

+//! Traits for implementing state trie writers for both class and contract states.
+//! These traits are used by the blockchain provider to maintain the global state root.
+
 use std::collections::BTreeMap;

10-17: Document trait and method specifications.

The trait implementation looks solid, sensei! However, it would benefit from comprehensive documentation:

 #[auto_impl::auto_impl(&, Box, Arc)]
+/// Trait for writing class updates to a trie structure and computing state roots.
 pub trait ClassTrieWriter: Send + Sync {
+    /// Inserts class hash updates for a given block and computes the new state root.
+    ///
+    /// # Arguments
+    /// * `block_number` - The block number for which these updates apply
+    /// * `updates` - Map of class hashes to their compiled class hashes
+    ///
+    /// # Returns
+    /// * `ProviderResult<Felt>` - The new state root after applying the updates
+    /// 
+    /// # Errors
+    /// Returns error if the trie operation fails or if there are invalid state transitions
     fn insert_updates(
         &self,
         block_number: BlockNumber,
         updates: &BTreeMap<ClassHash, CompiledClassHash>,
     ) -> ProviderResult<Felt>;
 }

1-26: Consider future extensibility of the trie system.

Ohayo sensei! The trait design looks solid, but here are some architectural considerations:

  1. Consider adding a common base trait for shared trie operations
  2. You might want to add methods for trie verification and root computation without updates
  3. Consider adding batch operation support for better performance

Would you like assistance in designing these extensions?

crates/katana/storage/db/Cargo.toml (1)

28-30: Consider version constraints for new dependencies.

Ohayo sensei! While bitvec follows workspace versioning, smallvec has a hard-coded version "1.13.2". For consistency:

-smallvec = "1.13.2"
+smallvec.workspace = true

This would help maintain version consistency across the workspace and make updates easier.

crates/katana/storage/db/src/models/trie.rs (2)

7-21: Ohayo! Consider adding documentation for public types.

The type definitions look clean, but as public API elements, they would benefit from documentation comments explaining their purpose and usage.

Add rustdoc comments like this:

+/// Represents the different types of keys that can be stored in the trie database
 #[repr(u8)]
 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
 pub enum TrieDatabaseKeyType {
     Trie = 0,
     Flat,
     TrieLog,
 }

+/// A composite key used in the trie database, consisting of a type and the actual key bytes
 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
 pub struct TrieDatabaseKey {
     pub r#type: TrieDatabaseKeyType,
     pub key: Vec<u8>,
 }

54-81: Enhance test coverage with error cases.

The current tests cover the happy path well, but we should also test error handling.

Add these test cases:

#[test]
fn test_decode_empty_buffer() {
    let result = TrieDatabaseKey::decode(vec![]);
    assert!(matches!(result, Err(CodecError::InvalidInput(_))));
}

#[test]
fn test_decode_invalid_type() {
    let result = TrieDatabaseKey::decode(vec![255, 1, 2, 3]);
    assert!(matches!(result, Err(CodecError::InvalidInput(_))));
}
crates/katana/storage/db/src/lib.rs (1)

16-16: Ohayo sensei! The trie module addition looks good! ✨

The new trie module aligns perfectly with the PR's objective of implementing state trie functionality for computing the global state root. Its placement alongside other core modules like tables, models, and codecs follows the established architectural patterns.

Consider documenting the module's purpose and its relationship with other modules in the codebase, especially its interaction with the existing database abstraction layer.

crates/katana/storage/provider/src/lib.rs (1)

399-410: Solid implementation of ContractTrieWriter, sensei!

The implementation maintains consistency with the ClassTrieWriter pattern and properly handles state updates for contract trie computation.

A few architectural considerations:

  1. The returned Felt is likely the root hash, which could be used for state verification
  2. This implementation enables efficient state root computation as part of the PR objectives
  3. The delegation pattern allows for future optimizations in the underlying provider

Consider adding documentation comments that explain:

  • The relationship between class and contract tries
  • The significance of the returned Felt value
  • The impact on global state root computation
crates/katana/storage/db/src/tables.rs (1)

173-176: Consider adding documentation for the trie tables, sensei!

While the table definitions are correct, they would benefit from documentation explaining their specific roles in state management:

  • What kind of data each trie stores
  • How they relate to the global state root computation
  • Any specific constraints or invariants

Apply this diff to add documentation:

-    /// Class trie
+    /// Stores the merkle patricia trie nodes for class state.
+    /// Used for computing the global state root for declared classes.
     ClassTrie: (TrieDatabaseKey) => TrieDatabaseValue,
-    /// Contract trie
+    /// Stores the merkle patricia trie nodes for contract state.
+    /// Used for computing the global state root for deployed contracts.
     ContractTrie: (TrieDatabaseKey) => TrieDatabaseValue,
-    /// Contract storage trie
+    /// Stores the merkle patricia trie nodes for contract storage state.
+    /// Used for computing the global state root for contract storage.
     ContractStorageTrie: (TrieDatabaseKey) => TrieDatabaseValue

Also applies to: 233-238

crates/katana/storage/provider/src/providers/fork/mod.rs (1)

589-611: Consider documenting the implementation strategy, sensei

Both ClassTrieWriter and ContractTrieWriter implementations appear to be placeholders. For better maintainability and clarity, consider:

  1. Adding TODO comments explaining the implementation plan
  2. Documenting whether the actual implementation belongs in a different provider
  3. Creating GitHub issues to track the actual implementation tasks
  4. Adding tests to verify the expected behavior once implemented

This will help other developers understand the implementation strategy and track progress.

crates/katana/storage/db/src/trie/class.rs (1)

40-40: Ohayo sensei! Clarify the key derivation logic

The slicing operation [5..] on the bit representation of the hash may not be immediately clear. Adding a comment to explain why the first five bits are skipped would enhance code readability.

You could add an explanatory comment like this:

 let key: BitVec<u8, Msb0> = hash.to_bytes_be().as_bits()[5..].to_owned();
+// Skip the first 5 bits to align with the specific trie key format
crates/katana/trie/src/lib.rs (2)

24-24: Consider using a more descriptive IDENTIFIER constant.

Ohayo sensei, using a more meaningful IDENTIFIER, instead of b"1", can improve code readability and maintainability.


62-88: Enhance test coverage with additional unit tests.

Ohayo sensei, consider adding more unit tests to cover edge cases and different input scenarios. This will ensure the robustness and reliability of the implemented functions.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 712422f and 997a626.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • Cargo.toml (3 hunks)
  • crates/katana/storage/db/Cargo.toml (2 hunks)
  • crates/katana/storage/db/src/codecs/postcard.rs (2 hunks)
  • crates/katana/storage/db/src/lib.rs (1 hunks)
  • crates/katana/storage/db/src/models/mod.rs (1 hunks)
  • crates/katana/storage/db/src/models/trie.rs (1 hunks)
  • crates/katana/storage/db/src/tables.rs (7 hunks)
  • crates/katana/storage/db/src/trie/class.rs (1 hunks)
  • crates/katana/storage/db/src/trie/contract.rs (1 hunks)
  • crates/katana/storage/db/src/trie/mod.rs (1 hunks)
  • crates/katana/storage/provider/Cargo.toml (1 hunks)
  • crates/katana/storage/provider/src/lib.rs (3 hunks)
  • crates/katana/storage/provider/src/providers/db/mod.rs (1 hunks)
  • crates/katana/storage/provider/src/providers/db/trie.rs (1 hunks)
  • crates/katana/storage/provider/src/providers/fork/mod.rs (4 hunks)
  • crates/katana/storage/provider/src/traits/mod.rs (1 hunks)
  • crates/katana/storage/provider/src/traits/trie.rs (1 hunks)
  • crates/katana/trie/Cargo.toml (1 hunks)
  • crates/katana/trie/src/lib.rs (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • crates/katana/storage/db/src/models/mod.rs
  • crates/katana/storage/provider/src/providers/db/mod.rs
  • crates/katana/storage/provider/src/traits/mod.rs
🔇 Additional comments (19)
crates/katana/trie/Cargo.toml (2)

1-7: LGTM! Package metadata follows workspace conventions.

Ohayo! The package metadata section properly inherits workspace-level configurations while maintaining package-specific name. This is the recommended approach for workspace management.


19-23: Verify git dependency revision and consider vendoring.

The bonsai-trie dependency is fetched from a git repository with a specific revision. While this works, it has several implications:

  1. Build reproducibility depends on the git repository's availability
  2. The specific revision 56d7d62 needs verification for security and stability
  3. Future maintenance might be affected if the repository becomes unavailable

Let's verify the git dependency:

Consider either:

  1. Vendoring the dependency in your repository if the upstream is not actively maintained
  2. Using a published version from crates.io if available
  3. Adding a comment explaining why this specific revision is needed
✅ Verification successful

Let me gather more information about the dependency and its maintenance status.


Let me check one more thing about the dependency usage in the codebase.


Ohayo sensei! Git dependency is actively maintained but needs documentation

The bonsai-trie repository shows healthy maintenance:

  • Active development with recent commits (last commit Oct 23, 2024)
  • Specific revision 56d7d62 is a stable commit with core functionality
  • Repository is part of the madara-alliance organization, suggesting official maintenance

However, recommend adding a comment in Cargo.toml explaining why this specific revision is needed for better maintainability.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the bonsai-trie git dependency
# Test: Check if the repository and commit are accessible
gh repo view madara-alliance/bonsai-trie --json url,description
gh api repos/madara-alliance/bonsai-trie/commits/56d7d62 --jq '.sha'

Length of output: 310


Script:

#!/bin/bash
# Check recent activity and maintenance status
gh api repos/madara-alliance/bonsai-trie/commits --jq 'length'
gh api repos/madara-alliance/bonsai-trie/commits --jq '.[0:3] | .[] | {sha: .sha[0:7], date: .commit.author.date, message: .commit.message}'

# Check if it's published on crates.io
curl -s https://crates.io/api/v1/crates/bonsai-trie | jq '.crate?.max_version'

# Check for any cargo.toml comments about this dependency
rg -A 2 "bonsai-trie" "$(fd -t f Cargo.toml)"

Length of output: 4180


Script:

#!/bin/bash
# Check for any comments or documentation about bonsai-trie usage
rg -B 2 -A 2 "bonsai-trie" --type rust

# Check the specific commit's changes
gh api repos/madara-alliance/bonsai-trie/commits/56d7d62 --jq '.files[].filename'

Length of output: 566

crates/katana/storage/db/Cargo.toml (2)

11-11: LGTM! Trie dependency addition aligns with PR objectives.

Ohayo! The addition of katana-trie as a workspace dependency perfectly aligns with the PR's goal of implementing class and contract trie functionality.


21-22: Verify Starknet dependency migration impact.

The starknet dependency has been moved from dev-dependencies to main dependencies, and starknet-types-core has been added. While this makes sense for the trie implementation, we should verify the impact.

✅ Verification successful

Let me check the actual usage of these dependencies in the storage/db crate to verify if they are correctly placed in main dependencies.


Let me check the actual content of these files to understand how these dependencies are used.


Ohayo sensei! After analyzing the usage, I can now provide a conclusive response:

Dependencies are correctly placed in main dependencies ✨

The starknet and starknet-types-core dependencies are used in core functionality of the storage/db crate:

  • Used in contract and class trie implementations
  • Required for hash computations using Poseidon
  • Used in storage models and table definitions
  • None of the usages are test-only

These dependencies are essential for the core functionality of the storage/db crate, particularly in the trie implementation and hash computations, so they are correctly placed in the main dependencies section rather than dev-dependencies.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if starknet is used in test files only
# If it's only used in tests, it should remain in dev-dependencies

rg -l "use starknet::" --type rust

Length of output: 8623


Script:

#!/bin/bash
# Check actual usage of starknet and starknet-types-core in the storage/db crate
rg -l "use starknet::|use starknet_types_core::" "crates/katana/storage/db/src/"

Length of output: 296


Script:

#!/bin/bash
# Get the content of relevant files to understand the usage context
ast-grep --pattern 'use starknet::$$$'  "crates/katana/storage/db/src/trie/class.rs"

Length of output: 83


Script:

#!/bin/bash
# Check if there are any test files using these dependencies
find crates/katana/storage/db/src -type f -name "*test*.rs" -exec rg -l "use starknet::|use starknet_types_core::" {} \;

Length of output: 125


Script:

#!/bin/bash
# Check the actual usage in the files
rg "use starknet::|use starknet_types_core::" -A 5 "crates/katana/storage/db/src/trie/contract.rs" "crates/katana/storage/db/src/trie/class.rs" "crates/katana/storage/db/src/tables.rs" "crates/katana/storage/db/src/models/storage.rs" "crates/katana/storage/db/src/mdbx/mod.rs"

Length of output: 2533

crates/katana/storage/provider/Cargo.toml (2)

12-12: LGTM! Well-organized dependency additions.

Ohayo! The new dependencies are properly organized following the workspace-first pattern, and all are correctly using workspace versions. Nice work, sensei!

Also applies to: 20-21


12-12: Verify version compatibility with existing dependencies.

Let's ensure these new dependencies don't introduce any version conflicts in the workspace.

Also applies to: 20-21

✅ Verification successful

Let me gather more information to verify workspace dependencies.


Dependencies are properly configured in workspace sensei!

The verification shows that:

  • katana-trie is correctly defined in workspace dependencies and used with .workspace = true
  • bitvec and starknet-types-core are also using workspace inheritance with .workspace = true
  • All dependencies are properly managed at the workspace level with no version conflicts

Ohayo! Everything looks perfectly aligned with the workspace configuration, sensei! 🍜

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential version conflicts in workspace dependencies

# Test: Look for any duplicate dependency versions in workspace
rg -A 1 "^\[dependencies\]|^(katana-trie|bitvec|starknet-types-core)\s*=" Cargo.toml **/Cargo.toml

# Test: Check if workspace versions are properly defined
rg "^\[workspace\.dependencies\]" -A 20 Cargo.toml

Length of output: 1117


Script:

#!/bin/bash
# Check workspace dependencies in the specific crate's Cargo.toml
cat crates/katana/storage/provider/Cargo.toml

# Check for katana-trie in workspace dependencies
rg "katana-trie" Cargo.toml

# Look for any version specifications of these dependencies in workspace
rg "^\[workspace\.dependencies\]" -A 50 Cargo.toml

Length of output: 3687

crates/katana/storage/db/src/codecs/postcard.rs (2)

14-14: LGTM! Clean import addition.

Ohayo! The import follows the existing grouping pattern nicely, sensei.


42-42: LGTM! Consistent implementation for TrieDatabaseValue.

Ohayo! The addition of TrieDatabaseValue to the macro implementation list is well-placed. The implementation will provide consistent serialization behavior with proper error handling through postcard.

Let's verify the TrieDatabaseValue type definition:

✅ Verification successful

Ohayo! The TrieDatabaseValue implementation is properly integrated and used consistently

The verification confirms that TrieDatabaseValue is:

  • Defined as a ByteVec type alias in models/trie.rs
  • Used consistently in the Trie trait and table definitions
  • Properly imported in the postcard codec implementation

The implementation aligns perfectly with the database's type system and serialization requirements.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify TrieDatabaseValue type definition and usage
# Expected: Find the type definition and any direct usage

# Search for type definition
echo "=== Searching for TrieDatabaseValue type definition ==="
rg -p "type\s+TrieDatabaseValue" 

# Search for usage patterns
echo "=== Searching for TrieDatabaseValue usage patterns ==="
rg -p "TrieDatabaseValue"

Length of output: 965

crates/katana/storage/db/src/models/trie.rs (1)

23-32: LGTM! Clean and efficient encoding implementation.

The encoding logic is straightforward and correctly preserves both the type and key data.

Cargo.toml (2)

38-38: Ohayo! New trie module addition looks good, sensei!

The addition of "crates/katana/trie" to workspace members aligns perfectly with the PR objectives for implementing the state trie functionality.


259-261: Dependencies are well-chosen for trie implementation!

The changes look good:

  • Upgrading starknet-types-core and adding the "hash" feature is appropriate for trie operations
  • Adding bitvec is a solid choice for efficient bit manipulation in trie implementations

However, let's verify the dependency usage:

✅ Verification successful

Dependencies are properly utilized in trie implementation, sensei!

The verification confirms both dependencies are actively used in the implementation:

  • bitvec: Used for key representation in the trie with BitVec::from_iter
  • starknet-types-core hash features: Extensively used for Pedersen hashing in contract state computation and merkle root calculations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of new dependencies in the trie implementation

# Check for bitvec usage in the new trie module
echo "Checking bitvec usage:"
rg -l "use.*bitvec" "crates/katana/trie"

# Check for starknet_types_core hash feature usage
echo "Checking starknet_types_core hash feature usage:"
rg -l "use.*starknet_types_core.*hash" "crates/katana/trie"

Length of output: 322


Script:

#!/bin/bash
# Let's check the actual usage patterns of these dependencies in the trie implementation

echo "Checking specific bitvec usage patterns:"
rg "use.*bitvec" -A 5 "crates/katana/trie/src/lib.rs"

echo -e "\nChecking starknet_types_core hash usage patterns:"
rg "use.*starknet_types_core.*hash" -A 5 "crates/katana/trie/src/lib.rs"

echo -e "\nChecking actual usage of bitvec types:"
rg "BitVec|BitSlice" "crates/katana/trie/src/lib.rs"

echo -e "\nChecking actual usage of hash features:"
rg "Hash|hash" "crates/katana/trie/src/lib.rs"

Length of output: 2503

crates/katana/storage/provider/src/lib.rs (1)

22-22: Ohayo! Import looks good, sensei!

The import of trie-related traits aligns perfectly with the PR's objective of implementing class and contract trie functionality.

crates/katana/storage/db/src/tables.rs (3)

13-13: Ohayo! The Trie trait definition looks clean and well-constrained.

The trait is properly bounded to specific key and value types, which ensures type safety and consistency across implementations.

Also applies to: 39-40


241-243: LGTM! Clean trait implementations.

The Trie trait implementations for the three new table types are concise and correct.


276-277: Verify test coverage for trie tables, sensei!

While the basic table existence tests are added, consider enhancing the test coverage:

  1. Add compress/decompress tests for TrieDatabaseValue
  2. Add encode/decode tests for TrieDatabaseKey

Let's verify if these types are already tested elsewhere:

If not found, consider adding these test cases to test_key_encode_decode and test_value_compress_decompress:

 assert_key_encode_decode! {
     (BlockNumber, 100),
     (BlockHash, felt!("0x123456789")),
+    (TrieDatabaseKey, TrieDatabaseKey::default()),
     // ... other cases
 }

 assert_value_compress_decompress! {
     (Header, Header::default()),
     (BlockHash, BlockHash::default()),
+    (TrieDatabaseValue, TrieDatabaseValue::default()),
     // ... other cases
 }

Also applies to: 302-303

crates/katana/storage/provider/src/providers/fork/mod.rs (3)

4-4: Ohayo! The new imports look good, sensei!

The additions of BTreeMap, Felt, and trie-related traits align perfectly with the PR's objective of implementing class and contract tries for state root computation.

Also applies to: 20-20, 41-41


601-611: Verify if this is intended to be a placeholder implementation, sensei

Similar to the ClassTrieWriter, the ContractTrieWriter::insert_updates implementation doesn't perform any state root computation. Both trait implementations appear to be placeholders.

If you need assistance implementing the actual trie operations and state root computation, I'd be happy to help!

#!/bin/bash
# Check if there are any TODO comments or related issues about implementing this properly
rg -g '!target' -g '!*.lock' "TODO.*contract.*trie|FIXME.*contract.*trie" .

# Check if there are any other implementations of ContractTrieWriter that might be the actual implementation
ast-grep --pattern 'impl ContractTrieWriter for $_ {
  $$$
}'

589-599: Verify if this is intended to be a placeholder implementation, sensei

The current implementation of ClassTrieWriter::insert_updates doesn't perform any state root computation and simply returns Felt::ZERO. This seems to diverge from the PR's objective of implementing class trie for state root computation.

crates/katana/storage/provider/src/providers/db/trie.rs (1)

108-108: Ohayo sensei! Verify that defaulting to zero is appropriate when provider returns None

When the provider returns None for nonce or class_hash, the code defaults to Felt::default(). Please confirm that defaulting to zero is acceptable in these cases and will not lead to incorrect state computations.

Also applies to: 112-112

Comment on lines +19 to +26
#[auto_impl::auto_impl(&, Box, Arc)]
pub trait ContractTrieWriter: Send + Sync {
fn insert_updates(
&self,
block_number: BlockNumber,
state_updates: &StateUpdates,
) -> ProviderResult<Felt>;
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Ohayo sensei! After analyzing the implementation details, I can now provide a final response about the ContractTrieWriter trait.

Documentation looks good, but implementation needs validation

The trait implementation shows two concerning patterns:

  • ForkedProvider has a no-op implementation that ignores state updates and returns ZERO
  • DbProvider has a real implementation but lacks validation of the state updates

Here's what needs attention:

  • Add validation of state updates in DbProvider before processing them
  • Add error handling for invalid state transitions
  • Consider adding validation tests for the contract trie writer
🔗 Analysis chain

Document trait and verify state update handling.

The trait looks good, but needs documentation and potential verification:

 #[auto_impl::auto_impl(&, Box, Arc)]
+/// Trait for writing contract state updates to a trie structure and computing state roots.
 pub trait ContractTrieWriter: Send + Sync {
+    /// Inserts contract state updates for a given block and computes the new state root.
+    ///
+    /// # Arguments
+    /// * `block_number` - The block number for which these updates apply
+    /// * `state_updates` - Collection of state updates to be applied
+    ///
+    /// # Returns
+    /// * `ProviderResult<Felt>` - The new state root after applying the updates
+    /// 
+    /// # Errors
+    /// Returns error if the trie operation fails or if there are invalid state transitions
     fn insert_updates(
         &self,
         block_number: BlockNumber,
         state_updates: &StateUpdates,
     ) -> ProviderResult<Felt>;
 }

Let's verify the StateUpdates type definition and its handling:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify StateUpdates type definition and usage
# Expected: Find the type definition and any validation logic

# Search for StateUpdates type definition
echo "Searching for StateUpdates definition..."
rg -t rust "struct StateUpdates" -A 10

# Search for any validation logic
echo "Searching for validation logic..."
rg -t rust "impl.*StateUpdates" -A 10

Length of output: 3066


Script:

#!/bin/bash
# Let's check for any validation or error handling in the ContractTrieWriter implementations

# Search for ContractTrieWriter implementations and their error handling
echo "Searching for ContractTrieWriter implementations..."
rg -t rust "impl.*ContractTrieWriter" -B 2 -A 15

# Search for any ProviderResult error definitions
echo "Searching for ProviderResult error definitions..."
rg -t rust "ProviderResult|ProviderError" -A 5

# Check if there are any tests validating state updates
echo "Searching for related tests..."
rg -t rust "test.*insert_updates|test.*ContractTrieWriter" -B 2 -A 10

Length of output: 180029


Script:

#!/bin/bash
# Let's check for any validation or error handling in the implementation
# and any tests related to state updates

# Search for state update validation logic
echo "Searching for state update validation..."
rg -t rust "fn.*validate.*StateUpdates" -B 2 -A 10

# Search for state update error handling
echo "Searching for state update error handling..."
rg -t rust "Error.*StateUpdates|StateUpdates.*Error" -B 2 -A 10

# Search for contract trie writer tests in test modules
echo "Searching for contract trie tests..."
ast-grep --pattern 'mod tests {
  $$$
  #[test]
  fn $_($$) {
    $$$
    ContractTrieWriter
    $$$
  }
  $$$
}'

Length of output: 1617


Script:

#!/bin/bash
# Let's check the implementation details of ContractTrieWriter

# Search for ContractTrieWriter implementations
echo "Searching for ContractTrieWriter implementations..."
rg -t rust "impl.*ContractTrieWriter" -B 5 -A 15

# Search for state update handling in the trie module
echo "Searching for state update handling in trie..."
rg -t rust "fn insert.*state_updates.*StateUpdates" -B 5 -A 15

# Search for any test files in the trie module
echo "Searching for trie test files..."
fd -t f "trie.*test.*rs$"

Length of output: 4745

Comment on lines +34 to +52
impl Decode for TrieDatabaseKey {
fn decode<B: AsRef<[u8]>>(bytes: B) -> Result<Self, CodecError> {
let bytes = bytes.as_ref();
if bytes.is_empty() {
panic!("emptyy buffer")
}

let r#type = match bytes[0] {
0 => TrieDatabaseKeyType::Trie,
1 => TrieDatabaseKeyType::Flat,
2 => TrieDatabaseKeyType::TrieLog,
_ => panic!("Invalid trie database key type"),
};

let key = bytes[1..].to_vec();

Ok(TrieDatabaseKey { r#type, key })
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve error handling and code clarity, sensei!

A few suggestions to enhance robustness and maintainability:

  1. Fix the typo in the panic message
  2. Consider using Result instead of panic for error cases
  3. Use enum variants directly in the match statement

Here's how to improve it:

 impl Decode for TrieDatabaseKey {
     fn decode<B: AsRef<[u8]>>(bytes: B) -> Result<Self, CodecError> {
         let bytes = bytes.as_ref();
         if bytes.is_empty() {
-            panic!("emptyy buffer")
+            return Err(CodecError::InvalidInput("empty buffer".into()));
         }
 
         let r#type = match bytes[0] {
-            0 => TrieDatabaseKeyType::Trie,
-            1 => TrieDatabaseKeyType::Flat,
-            2 => TrieDatabaseKeyType::TrieLog,
-            _ => panic!("Invalid trie database key type"),
+            x if x == TrieDatabaseKeyType::Trie as u8 => TrieDatabaseKeyType::Trie,
+            x if x == TrieDatabaseKeyType::Flat as u8 => TrieDatabaseKeyType::Flat,
+            x if x == TrieDatabaseKeyType::TrieLog as u8 => TrieDatabaseKeyType::TrieLog,
+            _ => return Err(CodecError::InvalidInput("invalid trie database key type".into())),
         };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
impl Decode for TrieDatabaseKey {
fn decode<B: AsRef<[u8]>>(bytes: B) -> Result<Self, CodecError> {
let bytes = bytes.as_ref();
if bytes.is_empty() {
panic!("emptyy buffer")
}
let r#type = match bytes[0] {
0 => TrieDatabaseKeyType::Trie,
1 => TrieDatabaseKeyType::Flat,
2 => TrieDatabaseKeyType::TrieLog,
_ => panic!("Invalid trie database key type"),
};
let key = bytes[1..].to_vec();
Ok(TrieDatabaseKey { r#type, key })
}
}
impl Decode for TrieDatabaseKey {
fn decode<B: AsRef<[u8]>>(bytes: B) -> Result<Self, CodecError> {
let bytes = bytes.as_ref();
if bytes.is_empty() {
return Err(CodecError::InvalidInput("empty buffer".into()));
}
let r#type = match bytes[0] {
x if x == TrieDatabaseKeyType::Trie as u8 => TrieDatabaseKeyType::Trie,
x if x == TrieDatabaseKeyType::Flat as u8 => TrieDatabaseKeyType::Flat,
x if x == TrieDatabaseKeyType::TrieLog as u8 => TrieDatabaseKeyType::TrieLog,
_ => return Err(CodecError::InvalidInput("invalid trie database key type".into())),
};
let key = bytes[1..].to_vec();
Ok(TrieDatabaseKey { r#type, key })
}
}

Comment on lines +386 to +397
impl<Db> ClassTrieWriter for BlockchainProvider<Db>
where
Db: ClassTrieWriter,
{
fn insert_updates(
&self,
block_number: BlockNumber,
updates: &BTreeMap<ClassHash, CompiledClassHash>,
) -> ProviderResult<Felt> {
self.provider.insert_updates(block_number, updates)
}
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Ohayo! Found an issue with the ForkedProvider implementation, sensei!

The ForkedProvider implementation of ClassTrieWriter is not properly handling the updates - it's ignoring the inputs and always returning Felt::ZERO. This could lead to incorrect class trie computation in forked environments.

  • crates/katana/storage/provider/src/providers/fork/mod.rs: The implementation discards both block_number and updates parameters using let _ = ... and returns a constant zero value.
🔗 Analysis chain

Clean implementation of ClassTrieWriter, sensei!

The implementation follows the established delegation pattern and correctly handles the class hash updates for trie computation. Let's verify the trait implementation in the underlying provider.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the ClassTrieWriter trait implementation in the underlying provider
# Expected: Find the trait implementation details in the trie module

# Search for the ClassTrieWriter trait definition and implementation
ast-grep --pattern 'trait ClassTrieWriter {
    $$$
}'

# Search for the implementation in the db provider
ast-grep --pattern 'impl ClassTrieWriter for $_ {
    $$$
}'

Length of output: 1081


Script:

#!/bin/bash
# Let's search for the trait definition and any other implementations
rg -A 5 "trait ClassTrieWriter" 

# Also search for any other implementations
rg -A 10 "impl ClassTrieWriter for"

# Let's also check if there are any tests or documentation
rg -A 5 "ClassTrieWriter.*test"

Length of output: 1526

Comment on lines +38 to +42
pub fn insert(&mut self, hash: ClassHash, compiled_hash: CompiledClassHash) {
let value = Poseidon::hash(&CONTRACT_CLASS_LEAF_V0, &compiled_hash);
let key: BitVec<u8, Msb0> = hash.to_bytes_be().as_bits()[5..].to_owned();
self.inner.insert(self.bonsai_identifier(), &key, &value).unwrap();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ohayo sensei! Handle errors when inserting into the trie

Using unwrap() in self.inner.insert(...).unwrap(); may lead to a panic if the insertion fails. It's better to handle the error or propagate it to ensure the stability of the application.

Consider modifying the code to handle potential errors:

 pub fn insert(&mut self, hash: ClassHash, compiled_hash: CompiledClassHash) {
     let value = Poseidon::hash(&CONTRACT_CLASS_LEAF_V0, &compiled_hash);
     let key: BitVec<u8, Msb0> = hash.to_bytes_be().as_bits()[5..].to_owned();
-    self.inner.insert(self.bonsai_identifier(), &key, &value).unwrap();
+    if let Err(e) = self.inner.insert(self.bonsai_identifier(), &key, &value) {
+        // Handle the error appropriately, e.g., log it or return it
+    }
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +48 to +50
pub fn root(&self) -> Felt {
self.inner.root_hash(self.bonsai_identifier()).unwrap()
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ohayo sensei! Ensure proper error handling in the root method

Using unwrap() in self.inner.root_hash(...).unwrap(); might lead to a panic if retrieving the root hash fails. It's recommended to handle the potential error to prevent crashes.

Modify the code to handle the error:

 pub fn root(&self) -> Felt {
-    self.inner.root_hash(self.bonsai_identifier()).unwrap()
+    match self.inner.root_hash(self.bonsai_identifier()) {
+        Ok(root) => root,
+        Err(e) => {
+            // Handle the error, possibly returning a default value or propagating the error
+        }
+    }
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +76 to +82
fn get_by_prefix(
&self,
prefix: &DatabaseKey<'_>,
) -> Result<Vec<(ByteVec, ByteVec)>, Self::DatabaseError> {
let _ = prefix;
todo!()
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement the get_by_prefix method

Ohayo sensei! The get_by_prefix method is marked as todo!() and needs to be implemented to retrieve values by a given prefix. I can assist with implementing this functionality if you'd like.

type DatabaseError = Error;
type Transaction = TrieDb<Tb, Tx>;

fn snapshot(&mut self, _: BasicId) {}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement the snapshot method

Ohayo sensei! The snapshot method is currently empty and should be implemented to support snapshot functionality for transactions. Happy to help implement this if needed.

Comment on lines +129 to +131
fn merge(&mut self, _: Self::Transaction) -> Result<(), Self::DatabaseError> {
todo!();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement the merge method

Ohayo sensei! The merge method is currently marked as todo!() and requires implementation to handle merging of transactions. I can help with this implementation if needed.

Comment on lines +133 to +135
fn transaction(&self, _: BasicId) -> Option<Self::Transaction> {
todo!();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement the transaction method

Ohayo sensei! The transaction method is currently marked as todo!() and needs to be implemented to support transaction handling. Let me know if you'd like assistance with this.

Comment on lines +51 to +69
fn remove_by_prefix(&mut self, prefix: &DatabaseKey<'_>) -> Result<(), Self::DatabaseError> {
let mut cursor = self.tx.cursor_mut::<Tb>()?;
let walker = cursor.walk(None)?;

let mut keys_to_remove = Vec::new();
// iterate over all entries in the table
for entry in walker {
let (key, _) = entry?;
if key.key.starts_with(prefix.as_slice()) {
keys_to_remove.push(key);
}
}

for key in keys_to_remove {
let _ = self.tx.delete::<Tb>(key, None)?;
}

Ok(())
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize remove_by_prefix to improve performance

Ohayo sensei! Currently, remove_by_prefix iterates over all entries in the table, which might be inefficient for large datasets. Consider using cursor.seek to directly navigate to the prefix and iterate from there to improve performance.

Here's how you might adjust the code:

 fn remove_by_prefix(&mut self, prefix: &DatabaseKey<'_>) -> Result<(), Self::DatabaseError> {
     let mut cursor = self.tx.cursor_mut::<Tb>()?;
-    let walker = cursor.walk(None)?;
+    let walker = cursor.walk(Some(to_db_key(prefix)))?;

     let mut keys_to_remove = Vec::new();
     // iterate over entries starting from the prefix
     for entry in walker {
         let (key, _) = entry?;
         if key.key.starts_with(prefix.as_slice()) {
             keys_to_remove.push(key);
         } else {
             break;
         }
     }

     for key in keys_to_remove {
         let _ = self.tx.delete::<Tb>(key, None)?;
     }

     Ok(())
 }

Committable suggestion skipped: line range outside the PR's diff.

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.

1 participant