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): fetch forked block data #2592

Merged
merged 10 commits into from
Oct 29, 2024
Merged

feat(katana): fetch forked block data #2592

merged 10 commits into from
Oct 29, 2024

Conversation

kariy
Copy link
Member

@kariy kariy commented Oct 28, 2024

resolves #1466

enable fetching block data from the forked chain. current forking feature only covers up to state data only. meaning doing any operations that requires only doing contract executions - estimate fee, tx execution - are allowed.

this is a pretty simple solution as it just forwards the request to the forked network provider but doesn't do any caching of the requested data.

Unsupported methods:

rpc methods that this PR doesn't yet cover.

  • getEvents

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced ForkedClient for enhanced interaction with Starknet blockchain forks.
    • Added methods for fetching transactions and blocks, including support for pending state updates.
  • Bug Fixes

    • Improved error handling in the Starknet API, allowing for better representation of various error types.
  • Documentation

    • Updated method signatures and descriptions to reflect new functionalities and changes.
  • Tests

    • Enhanced testing framework for forking functionality, ensuring robust validation of blockchain interactions.

Copy link

coderabbitai bot commented Oct 28, 2024

Walkthrough

Ohayo, sensei! This pull request introduces significant enhancements across several files in the Katana project, focusing on the integration of a ForkedClient for managing interactions with forked blockchain states. Key changes include updates to method signatures, the addition of new methods for fetching blockchain data, and improvements in error handling. The modifications aim to provide a more robust API for handling transactions and state updates, particularly in the context of forked networks.

Changes

File Path Change Summary
crates/katana/core/src/backend/storage.rs Updated new_from_forked method to return Result<(Self, BlockNumber)> and adjusted logic to include block number.
crates/katana/node/src/lib.rs Added forked_client field to Node struct, modified launch method to accept mutable self, and updated spawn method signature to include Option<ForkedClient>.
crates/katana/rpc/rpc-api/src/starknet.rs Changed return type of get_state_update from RpcResult<StateUpdate> to RpcResult<MaybePendingStateUpdate>.
crates/katana/rpc/rpc-types/src/block.rs Added From trait implementations for converting various MaybePendingBlock types to local types.
crates/katana/rpc/rpc-types/src/error/starknet.rs Enhanced error handling by adding new error types and converting existing ones, changed transaction_index type to u64.
crates/katana/rpc/rpc-types/src/receipt.rs Modified visibility of TxReceiptWithBlockInfo struct and added From trait implementation for conversion from TransactionReceiptWithBlockInfo.
crates/katana/rpc/rpc-types/src/state_update.rs Added From trait implementations for converting MaybePendingStateUpdate and updated existing implementation for StateUpdate.
crates/katana/rpc/rpc-types/src/transaction.rs Added From trait implementation for converting starknet::core::types::Transaction to Tx.
crates/katana/rpc/rpc/Cargo.toml Added tokio and url dependencies to [dependencies], removed url from [dev-dependencies].
crates/katana/rpc/rpc/src/starknet/forking.rs Introduced ForkedClient struct with methods for blockchain interactions and error handling.
crates/katana/rpc/rpc/src/starknet/mod.rs Added new_forked method and updated existing methods to return StarknetApiResult<T>.
crates/katana/rpc/rpc/src/starknet/read.rs Simplified control flow by removing self.on_io_blocking_task and updated get_state_update return type.
crates/katana/rpc/rpc/src/starknet/trace.rs Adjusted transaction_index type in simulate_txs method to u64 for improved type safety.
crates/katana/rpc/rpc/tests/forking.rs Added tests for forking functionality, including block and transaction retrieval methods.

Assessment against linked issues

Objective Addressed Explanation
Fetch non-state data from the fork network (e.g., do_get_events, do_get_block_with_txs)
Fetch transaction details from the fork network (e.g., do_get_transaction_by_hash)
Handle state updates with the new return type in API methods
Enhance error handling for forked client interactions

Possibly related PRs

Feel free to reach out if you need further insights, sensei!


🪧 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: 11

🧹 Outside diff range and nitpick comments (9)
crates/katana/rpc/rpc/src/starknet/trace.rs (2)

99-99: Ohayo sensei! The type conversion looks good.

The change from i to i as u64 for transaction_index aligns well with Starknet's type system and ensures consistency across the codebase. The conversion is safe since the index comes from a Vec iterator and will always be non-negative.

For future consideration, you might want to add a debug assertion to catch any theoretical edge cases:

debug_assert!(i <= u64::MAX as usize, "transaction index exceeds u64::MAX");

Line range hint 1-99: Consider adding fork-related documentation.

Ohayo sensei! Since this PR is part of the forked provider implementation, it would be helpful to add documentation comments explaining how the trace functionality behaves when working with forked data, particularly for methods like block_traces and trace that fetch data through the provider abstraction.

Example documentation:

/// Returns traces for transactions in the specified block.
/// When using a forked provider, traces are fetched from the fork network
/// for blocks that exist before the fork point.
fn block_traces(...)
crates/katana/rpc/rpc-types/src/block.rs (2)

327-338: Consider adding documentation for the conversion implementations, sensei!

While the implementation is correct, adding documentation comments would help explain the purpose of these conversions in the context of forked block data fetching. Consider adding a doc comment like:

/// Converts from Starknet core's MaybePendingBlockWithReceipts to the local type.
/// This conversion is used when fetching block data from the fork network.
impl From<starknet::core::types::MaybePendingBlockWithReceipts> for MaybePendingBlockWithReceipts {

Line range hint 98-338: Well-structured type conversion system for forked block data!

The three From implementations form a complete and consistent set of conversions necessary for fetching different types of block data from the fork network. The modular approach with separate implementations for transactions, transaction hashes, and receipts aligns well with Rust's type system and makes the code maintainable.

crates/katana/core/src/backend/storage.rs (1)

177-178: Consider implementing the TODO suggestion.

The TODO comment raises a valid point about using block numbers for range validation. This would improve the robustness of the forking mechanism.

Would you like me to create a GitHub issue to track this improvement? I can help draft the implementation as well.

crates/katana/rpc/rpc-types/src/transaction.rs (1)

400-404: Ohayo sensei! Consider adding documentation for the From implementation.

The implementation looks correct and aligns with the PR objectives for fetching forked block data. However, it would be helpful to add documentation explaining:

  • The purpose of this conversion
  • How it differs from the From<TxWithHash> implementation above
  • When to use this implementation vs the other one

Add documentation like this:

+/// Implements direct conversion from starknet core Transaction type.
+/// This implementation is primarily used when fetching transactions from the fork network,
+/// where we already have the complete transaction data and don't need the complex
+/// conversion logic used in `From<TxWithHash>`.
 impl From<starknet::core::types::Transaction> for Tx {
     fn from(value: starknet::core::types::Transaction) -> Self {
         Self(value)
     }
 }
crates/katana/node/src/lib.rs (1)

187-187: Ohayo, sensei! Correct the typo in the comment.

There's a typo in the comment: "it'd bee nice" should be "it'd be nice".

Apply this diff to fix the typo:

-    // TODO: it'd bee nice if the client can be shared on both the rpc and forked backend side
+    // TODO: it'd be nice if the client can be shared on both the rpc and forked backend side
crates/katana/rpc/rpc/src/starknet/mod.rs (2)

620-621: Address the TODO regarding transaction status handling

Ohayo, sensei!

The TODO comment indicates potential issues when querying for failed transactions from the provider. Implementing proper handling for failed transactions will improve the accuracy of the transaction_status method.

Would you like assistance in implementing this functionality, or should I open a new GitHub issue to track this task?


85-93: Unify initialization methods for StarknetApi

Ohayo, sensei!

The new_forked method closely mirrors the existing new method but adds a forked_client parameter. Consider unifying these methods or using default parameters to streamline object creation and reduce redundancy.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7addea8 and f2b1067.

📒 Files selected for processing (13)
  • crates/katana/core/src/backend/storage.rs (5 hunks)
  • crates/katana/node/src/lib.rs (6 hunks)
  • crates/katana/rpc/rpc-api/src/starknet.rs (2 hunks)
  • crates/katana/rpc/rpc-types/src/block.rs (3 hunks)
  • crates/katana/rpc/rpc-types/src/error/starknet.rs (3 hunks)
  • crates/katana/rpc/rpc-types/src/receipt.rs (1 hunks)
  • crates/katana/rpc/rpc-types/src/state_update.rs (4 hunks)
  • crates/katana/rpc/rpc-types/src/transaction.rs (1 hunks)
  • crates/katana/rpc/rpc/Cargo.toml (1 hunks)
  • crates/katana/rpc/rpc/src/starknet/forking.rs (1 hunks)
  • crates/katana/rpc/rpc/src/starknet/mod.rs (19 hunks)
  • crates/katana/rpc/rpc/src/starknet/read.rs (3 hunks)
  • crates/katana/rpc/rpc/src/starknet/trace.rs (1 hunks)
🔇 Additional comments (28)
crates/katana/rpc/rpc/Cargo.toml (1)

26-26: Ohayo sensei! Dependencies look good for forked provider implementation.

The addition of tokio and migration of url to main dependencies aligns perfectly with the requirements for implementing the forked provider functionality. These dependencies are essential for:

  • Async operations when fetching remote block data
  • URL handling for fork network connections

Also applies to: 28-28

crates/katana/rpc/rpc-types/src/state_update.rs (4)

13-24: Ohayo! Clean implementation of MaybePendingStateUpdate conversion, sensei!

The pattern matching approach ensures proper handling of both variants while maintaining type safety through explicit conversions.


40-40: Clean use of Self for better maintainability!

The change to use Self instead of explicit type name follows Rust best practices.


90-94: Clean and consistent implementation!

The From trait implementation follows the established pattern in the codebase.


Line range hint 79-88: Verify the default values for new fields, sensei!

The implementation sets replaced_classes and deprecated_declared_classes to default values. Please confirm if this is the intended behavior for forked block data.

✅ Verification successful

Based on the search results, I can now generate the final response since I have found clear evidence about the intended behavior.

Ohayo! These default values are actually the correct implementation, sensei!

The codebase explicitly documents that Katana does not support replaced_classes and deprecated_declared_classes as seen in the comments:

  • crates/saya/provider/src/rpc/state.rs: "Currently, Katana does not support replaced_classes and deprecated_declared_classes"
  • The same file shows multiple instances where these fields are consistently set to default values
  • Other implementations (like in torii/grpc) initialize these fields as empty vectors/maps

Setting these fields to default values is the correct approach since Katana intentionally does not handle contract upgrades via the replace_class syscall at this time.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any usage of these fields to verify if they should always be default
rg -A 5 "replaced_classes|deprecated_declared_classes" --type rust

Length of output: 7934

crates/katana/rpc/rpc-api/src/starknet.rs (2)

15-15: Ohayo! Import change looks good, sensei!

The update to use MaybePendingStateUpdate aligns well with the forked provider implementation, allowing for pending state handling.


64-64: Method signature update is well-crafted, sensei!

The change to return RpcResult<MaybePendingStateUpdate> enhances the API's capability to handle both finalized and pending state updates from the fork network.

Let's verify the consistency of this change across the codebase:

✅ Verification successful

The change to MaybePendingStateUpdate is consistently implemented across the codebase!

The verification shows that:

  • The trait definition in rpc-api/src/starknet.rs correctly uses MaybePendingStateUpdate
  • The implementation in rpc/src/starknet/read.rs matches the trait signature
  • The type is properly defined in rpc-types/src/state_update.rs with correct variants
  • All related code paths handle both regular and pending state updates appropriately
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all implementations of get_state_update are updated
# to use MaybePendingStateUpdate

# Search for get_state_update implementations
ast-grep --pattern 'fn get_state_update($$$) -> $result {
  $$$
}'

# Search for any remaining StateUpdate usages that might need updating
rg "StateUpdate" --type rust

Length of output: 18670

crates/katana/rpc/rpc-types/src/receipt.rs (2)

124-128: Clean From implementation, sensei! ✨

The From trait implementation provides a type-safe way to convert from the core Starknet type, which is perfect for the forking functionality.


122-122: Ohayo! Verify the necessity of making the inner field public.

Making the inner field public weakens encapsulation. While this change enables direct access needed for forking functionality, we should verify that this is the most appropriate approach.

✅ Verification successful

Let me gather more context about the usage of TxReceiptWithBlockInfo to understand if making it public is justified.


Ohayo! The public field is justified and well-used, sensei!

The public field in TxReceiptWithBlockInfo is necessary because:

  • It's used in the forking functionality where direct access is needed for conversion from the provider's receipt type
  • The struct is part of the public API and is used across multiple crates (rpc, rpc-types-builder, rpc-api)
  • The implementation provides a clean conversion layer between starknet core types and Katana's RPC types

The encapsulation concern is mitigated by the type's focused responsibility as a wrapper for starknet core types in the RPC layer.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for direct access to the inner field to confirm necessity
rg -l "TxReceiptWithBlockInfo" | xargs rg "\.0\s*"

Length of output: 2426


Script:

#!/bin/bash
# Search for usages of TxReceiptWithBlockInfo
rg -A 3 "TxReceiptWithBlockInfo" --type rust

# Also check for any implementations or trait bounds
ast-grep --pattern 'impl $_ for TxReceiptWithBlockInfo { $$ }'

Length of output: 7596

crates/katana/rpc/rpc/src/starknet/read.rs (3)

2-2: Ohayo sensei! Import changes look good!

The new imports align perfectly with the PR objectives for fetching forked block data and support the updated return types.

Also applies to: 9-9, 14-15


Line range hint 121-150: Architectural consistency check for blocking tasks

The retention of on_io_blocking_task and on_cpu_blocking_task in these complex methods appears intentional and appropriate, given their CPU-intensive nature (especially for fee estimation) and complex state management requirements.

Let's verify that these methods require blocking operations:

#!/bin/bash
# Description: Check for CPU-intensive or blocking operations in these methods

echo "Checking for executor usage in these methods..."
rg "executor\." -B 2 -A 2

echo "Checking for complex state operations..."
rg "state\." -B 2 -A 2

Also applies to: 166-181, 182-197, 198-244, 245-289


43-43: Ohayo sensei! Nice simplification of the RPC methods!

The removal of on_io_blocking_task wrappers across these methods creates a more streamlined implementation. The consistent pattern of using direct async calls with proper error propagation is clean and maintainable.

Let's verify that all the underlying methods being called are properly async-safe:

Also applies to: 47-47, 70-70, 78-78, 85-85, 92-92, 95-96, 103-103

crates/katana/rpc/rpc-types/src/block.rs (2)

98-109: Ohayo sensei! Clean and correct implementation!

The From trait implementation for MaybePendingBlockWithTxs follows Rust's best practices for type conversion with proper variant mapping and exhaustive pattern matching.


197-208: Implementation maintains consistency with the type conversion pattern!

The From trait implementation for MaybePendingBlockWithTxHashes correctly mirrors the established pattern, ensuring consistent behavior across the codebase.

crates/katana/core/src/backend/storage.rs (3)

6-6: LGTM! Clean import addition.

The BlockNumber import is properly grouped with related block primitives.


152-153: LGTM! Clean block number extraction.

The block number is properly extracted from the forked block and stored with a clear variable name.


200-201: LGTM! Proper tuple return implementation.

The return statement correctly includes both the blockchain instance and block number, maintaining consistency with the method signature.

crates/katana/rpc/rpc-types/src/transaction.rs (1)

Line range hint 547-550: Ohayo sensei! Consider addressing the TODO comment.

The TODO comment suggests avoiding conversions between types. Since this PR adds another conversion implementation, it might be a good time to consider a more comprehensive solution.

Could you clarify if:

  1. This is the right time to address this technical debt?
  2. The new From implementation adds to this problem?

Let's analyze the impact:

crates/katana/node/src/lib.rs (7)

38-38: Ohayo, sensei! Importing ForkedClient is appropriate.

The addition of the ForkedClient import is necessary for handling forked clients.


91-91: Ohayo, sensei! Addition of forked_client field to Node struct is correct.

Including Option<ForkedClient> in the Node struct properly allows for optional forked client handling.


98-98: Ohayo, sensei! Changing self to mut self in launch method is necessary.

Making self mutable allows modification of self.forked_client within the method.


144-144: Ohayo, sensei! Verify the use of self.forked_client.take().

Using take() moves forked_client out of self. Please ensure that forked_client is not needed elsewhere after this operation.


242-248: Ohayo, sensei! Update to spawn function signature is correct.

Including Option<ForkedClient> in the spawn function allows passing the forked client appropriately.


251-251: Ohayo, sensei! Destructuring node_components includes forked_client correctly.

Unpacking forked_client from node_components ensures all components are properly accessed.


256-272: Ohayo, sensei! Conditional initialization of StarknetApi is well-implemented.

Switching between StarknetApi::new_forked and StarknetApi::new based on the presence of forked_client is appropriate.

crates/katana/rpc/rpc-types/src/error/starknet.rs (3)

10-11: Ohayo, sensei! Necessary imports added correctly

The imports of StarknetRsError and StarknetRsProviderError are appropriately added and aliased, ensuring proper error conversion.


246-261: Ohayo, sensei! Verify error mapping in From<StarknetRsProviderError> implementation

Ensure that all variants of StarknetRsProviderError are properly mapped to StarknetApiError. Providing more specific error messages, when possible, can aid in debugging and improve usability.

You can use the following script to verify all variants are covered:

#!/bin/bash
# Description: Verify all variants of 'StarknetRsProviderError' are mapped.

# Test: List variants of 'StarknetRsProviderError'
rg -A 5 'pub enum ProviderError' | grep '^\s\+\w\+,' | sed 's/,$//' > provider_variants.txt

# List mapped variants in the 'From' implementation
rg 'StarknetRsProviderError::' | sed 's/.*StarknetRsProviderError::\(\w\+\).*=>.*/\1/' > mapped_variants.txt

# Compare the two lists
echo "Variants not mapped:"
comm -23 <(sort provider_variants.txt) <(sort mapped_variants.txt)

45-47: Ohayo, sensei! Ensure consistency in transaction index types

Changing transaction_index from usize to u64 enhances consistency and supports a broader range of indices. Please verify that all instances of transaction_index in the codebase are updated to u64 to prevent any type mismatches.

You can use the following script to check for any remaining occurrences of transaction_index using usize:

✅ Verification successful

Let me search for both the usage and type declarations to get a better understanding of the consistency across the codebase.


Ohayo, sensei! All transaction indices are consistently using u64

After checking the entire codebase, I can confirm that all instances of transaction_index are already using u64. The change from usize to u64 has been consistently applied across:

  • Error types in error/starknet.rs
  • Transaction cursor in transaction.rs
  • All usages in RPC implementations and tests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all declarations of 'transaction_index' are using 'u64'.

# Test: Search for declarations of 'transaction_index' with type 'usize'.
rg 'transaction_index:\s*usize'

Length of output: 371


Script:

#!/bin/bash
# Let's search for transaction_index with broader context
rg -B 2 -A 2 'transaction_index'

# Also search for struct definitions containing transaction_index
ast-grep --pattern 'struct $_ {
  $$$
  transaction_index: $_,
  $$$
}'

Length of output: 13429

crates/katana/core/src/backend/storage.rs Show resolved Hide resolved
Comment on lines +143 to +145
starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => {
panic!("shouldn't be possible to be pending")
}
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! Consistently handle unexpected pending blocks without panicking.

Similar to the previous instance, replace the panic! with an appropriate error return to prevent crashing.

Apply this diff:

starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => {
-    panic!("shouldn't be possible to be pending")
+    return Err(Error::UnexpectedPendingBlock)
}
📝 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
starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => {
panic!("shouldn't be possible to be pending")
}
starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => {
return Err(Error::UnexpectedPendingBlock)
}

crates/katana/rpc/rpc/src/starknet/forking.rs Outdated Show resolved Hide resolved
Comment on lines +181 to +183
starknet::core::types::MaybePendingBlockWithTxHashes::PendingBlock(_) => {
panic!("shouldn't be possible to be pending")
}
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! Replace panic with error handling for pending blocks.

Consistently handle unexpected cases by returning errors instead of panicking.

Apply this diff:

starknet::core::types::MaybePendingBlockWithTxHashes::PendingBlock(_) => {
-    panic!("shouldn't be possible to be pending")
+    return Err(Error::UnexpectedPendingBlock)
}

Committable suggestion was skipped due to low confidence.

Comment on lines +161 to +163
starknet::core::types::MaybePendingBlockWithReceipts::PendingBlock(_) => {
panic!("shouldn't be possible to be pending")
}
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! Prevent application crash on unexpected pending blocks.

To maintain stability, avoid using panic! and return a meaningful error instead.

Apply this diff:

starknet::core::types::MaybePendingBlockWithReceipts::PendingBlock(_) => {
-    panic!("shouldn't be possible to be pending")
+    return Err(Error::UnexpectedPendingBlock)
}

Committable suggestion was skipped due to low confidence.

Comment on lines +230 to +232
BlockIdOrTag::Tag(_) => {
panic!("shouldn't be possible to be tag")
}
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! Avoid panicking when an unexpected tag is encountered.

Consistently return an error instead of panicking to improve reliability.

Apply this diff:

BlockIdOrTag::Tag(_) => {
-    panic!("shouldn't be possible to be tag")
+    return Err(Error::UnexpectedTag)
}

Committable suggestion was skipped due to low confidence.

crates/katana/rpc/rpc/src/starknet/forking.rs Show resolved Hide resolved
Comment on lines +122 to +124
BlockIdOrTag::Tag(_) => {
panic!("shouldn't be possible to be tag")
}
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 unexpected tags without panicking.

Using panic! may lead to crashes. Return an error to handle unexpected tags gracefully.

Apply this diff:

BlockIdOrTag::Tag(_) => {
-    panic!("shouldn't be possible to be tag")
+    return Err(Error::UnexpectedTag)
}

Add the new error variant to the Error enum:

 pub enum Error {
     /// Error originating from the underlying [`Provider`] implementation.
     #[error("Provider error: {0}")]
     Provider(#[from] ProviderError),

     #[error("Block out of range")]
     BlockOutOfRange,

+    #[error("Unexpected tag encountered in block ID")]
+    UnexpectedTag,
 }

Committable suggestion was skipped due to low confidence.

crates/katana/rpc/rpc/src/starknet/mod.rs Outdated Show resolved Hide resolved
Copy link

codecov bot commented Oct 28, 2024

Codecov Report

Attention: Patch coverage is 64.43452% with 239 lines in your changes missing coverage. Please review.

Project coverage is 70.24%. Comparing base (7addea8) to head (36c12fd).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
crates/katana/rpc/rpc/src/starknet/mod.rs 66.92% 129 Missing ⚠️
crates/katana/rpc/rpc/src/starknet/forking.rs 61.76% 52 Missing ⚠️
crates/katana/rpc/rpc-types/src/error/starknet.rs 20.93% 34 Missing ⚠️
crates/katana/rpc/rpc-types/src/state_update.rs 0.00% 12 Missing ⚠️
crates/katana/rpc/rpc-types/src/block.rs 73.91% 6 Missing ⚠️
crates/katana/node/src/lib.rs 90.69% 4 Missing ⚠️
crates/katana/rpc/rpc/src/starknet/read.rs 88.88% 1 Missing ⚠️
crates/katana/rpc/rpc/src/starknet/trace.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2592      +/-   ##
==========================================
+ Coverage   69.65%   70.24%   +0.59%     
==========================================
  Files         401      402       +1     
  Lines       50818    51130     +312     
==========================================
+ Hits        35395    35914     +519     
+ Misses      15423    15216     -207     

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

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: 4

🧹 Outside diff range and nitpick comments (1)
crates/katana/rpc/rpc/tests/forking.rs (1)

88-88: Ohayo, sensei! Verify the Actual Return Values in Assertions

Currently, you're asserting that the result is OK using assert!(result.is_ok());. For more comprehensive tests, consider verifying the actual return values to ensure they match the expected outcomes.

Also applies to: 118-118

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f2b1067 and d9fec48.

📒 Files selected for processing (2)
  • crates/katana/rpc/rpc/src/starknet/forking.rs (1 hunks)
  • crates/katana/rpc/rpc/tests/forking.rs (1 hunks)
🔇 Additional comments (8)
crates/katana/rpc/rpc/tests/forking.rs (1)

138-140: ⚠️ Potential issue

Ohayo, sensei! Missing Assertions for Transaction Hash

You've assigned a transaction hash on line 138 but haven't performed any assertions or operations with it before the function ends. Did you intend to include further tests using this transaction hash?

crates/katana/rpc/rpc/src/starknet/forking.rs (7)

110-112: Ohayo, sensei! Replace panic! with error return for pending blocks

Using panic! may cause the application to crash unexpectedly. It's better to return a meaningful error to handle this case gracefully.


122-124: Ohayo, sensei! Avoid panicking when encountering unexpected tags

Consistently handle unexpected tags by returning an appropriate error instead of panicking.


143-145: Ohayo, sensei! Replace panic! with proper error handling for pending blocks

To maintain application stability, avoid using panic! and return a descriptive error instead.


161-163: Ohayo, sensei! Handle unexpected pending blocks without panicking

Returning an error instead of panicking improves the robustness of your application.


181-183: Ohayo, sensei! Replace panic with error handling

Consistently handle unexpected pending blocks by returning errors instead of panicking.


230-232: Ohayo, sensei! Handle unexpected tags without panicking

Returning an error for unexpected tags enhances the reliability of your application.


73-83: Ohayo, sensei! Simplify asynchronous error handling in get_transaction_status

The current implementation awaits receipt and status concurrently, but only uses receipt for error checking. Consider restructuring for clarity and efficiency.

@@ -0,0 +1,141 @@
use anyhow::Result;
use assert_matches::assert_matches;
use cainome::rs::abigen_legacy;
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! Possible Typo in Import Statement

It appears there may be a typo in the import on line 3. Did you mean to import from cairo::rs::abigen_legacy instead of cainome::rs::abigen_legacy?

crates/katana/rpc/rpc/tests/forking.rs Outdated Show resolved Hide resolved
Comment on lines +241 to +248
impl From<Error> for StarknetApiError {
fn from(value: Error) -> Self {
match value {
Error::Provider(provider_error) => provider_error.into(),
Error::BlockOutOfRange => StarknetApiError::BlockNotFound,
}
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo, sensei! Map new error variants to StarknetApiError

After adding new error variants to the Error enum, ensure they are appropriately mapped to StarknetApiError for consistent API error handling.

Apply this diff to enhance error mapping:

 impl From<Error> for StarknetApiError {
     fn from(value: Error) -> Self {
         match value {
             Error::Provider(provider_error) => provider_error.into(),
-            Error::BlockOutOfRange => StarknetApiError::BlockNotFound,
+            Error::BlockOutOfRange
+            | Error::UnexpectedPendingBlock
+            | Error::UnexpectedTag => StarknetApiError::BlockNotFound,
         }
     }
 }

Committable suggestion was skipped due to low confidence.

Comment on lines +15 to +23
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Error originating from the underlying [`Provider`] implementation.
#[error("Provider error: {0}")]
Provider(#[from] ProviderError),

#[error("Block out of range")]
BlockOutOfRange,
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo, sensei! Consider enhancing the Error enum for comprehensive error handling

The current Error enum only includes Provider and BlockOutOfRange variants. To handle unexpected cases more gracefully and avoid panicking, consider adding variants like UnexpectedPendingBlock and UnexpectedTag.

Apply this diff to expand the Error enum:

 pub enum Error {
     /// Error originating from the underlying [`Provider`] implementation.
     #[error("Provider error: {0}")]
     Provider(#[from] ProviderError),

     #[error("Block out of range")]
     BlockOutOfRange,

+    #[error("Unexpected pending block encountered")]
+    UnexpectedPendingBlock,

+    #[error("Unexpected tag encountered")]
+    UnexpectedTag,
 }
📝 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
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Error originating from the underlying [`Provider`] implementation.
#[error("Provider error: {0}")]
Provider(#[from] ProviderError),
#[error("Block out of range")]
BlockOutOfRange,
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Error originating from the underlying [`Provider`] implementation.
#[error("Provider error: {0}")]
Provider(#[from] ProviderError),
#[error("Block out of range")]
BlockOutOfRange,
#[error("Unexpected pending block encountered")]
UnexpectedPendingBlock,
#[error("Unexpected tag encountered")]
UnexpectedTag,
}

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: 2

🧹 Outside diff range and nitpick comments (4)
crates/katana/rpc/rpc/tests/starknet.rs (1)

Line range hint 1-900: Consider adding test coverage for forked network scenarios.

Ohayo, sensei! While the test file comprehensively covers various error scenarios, it would be beneficial to add specific test cases for the forked network functionality being implemented, as mentioned in the PR objectives.

Would you like me to help generate test cases that cover forked network scenarios for non-state data fetching?

crates/katana/rpc/rpc/src/starknet/mod.rs (2)

663-663: Address TODO for ExecutionResult conversion

Ohayo, sensei! The TODO comment indicates a need for implementing From<ExecutionResult> for TransactionStatus. This would improve code maintainability and reduce the manual match patterns.

Would you like me to help implement the From trait for this conversion?


912-914: Consider adding documentation for pending block limitation

Ohayo, sensei! Consider adding a doc comment explaining why pending blocks are not supported for state updates. This would help future maintainers understand the design decision.

+    // Pending blocks are not supported for state updates as they represent
+    // an intermediate state that hasn't been committed to the chain yet.
     BlockIdOrTag::Tag(BlockTag::Pending) => {
         return Err(StarknetApiError::BlockNotFound);
     }
crates/katana/rpc/rpc/tests/forking.rs (1)

53-53: Ohayo, sensei! Fix typo in comment

There's a typo in your comment on line 53. 'emtpy' should be 'empty'.

Apply this diff to fix the typo:

-            // create some emtpy blocks and dummy transactions
+            // create some empty blocks and dummy transactions
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d9fec48 and e48339c.

📒 Files selected for processing (4)
  • crates/katana/rpc/rpc/src/starknet/mod.rs (19 hunks)
  • crates/katana/rpc/rpc/tests/common/mod.rs (2 hunks)
  • crates/katana/rpc/rpc/tests/forking.rs (1 hunks)
  • crates/katana/rpc/rpc/tests/starknet.rs (7 hunks)
🔇 Additional comments (9)
crates/katana/rpc/rpc/tests/common/mod.rs (2)

74-74: Ohayo sensei! Verify the necessity of the unused function.

The split_felt function is marked as unused. Let's verify if this function is needed for future implementation or can be safely removed.

#!/bin/bash
# Description: Check if split_felt is used anywhere in the codebase
# or mentioned in issues/PRs

# Search for any references to split_felt in the code
echo "Searching for split_felt usage in code..."
rg "split_felt"

# Search for mentions in TODO comments
echo "Searching for related TODOs..."
rg -i "todo.*split.*felt"

75-91: Ohayo sensei! The new assertion macros look great!

The implementation of both macros follows Rust best practices with clear documentation and proper error pattern matching. They provide a clean way to assert Starknet errors in tests.

Let's verify their usage in tests:

✅ Verification successful

The previous results didn't show the actual usage of these macros in tests, so let's specifically look for their usage patterns with some context lines. This will help us verify if they're being used correctly in test cases.


The previous search failed because we were looking in the wrong directory. Let's try with the correct path based on the file location of the macros.


Ohayo sensei! The new assertion macros are being used properly and extensively!

The macros are being actively used in test files with correct error pattern matching:

  • assert_account_starknet_err! is used 7 times in starknet.rs for account-related errors
  • assert_provider_starknet_err! is used 8 times in forking.rs for provider-related errors

All usages follow the intended pattern and correctly match against specific StarknetError variants like:

  • BlockNotFound
  • TransactionHashNotFound
  • InsufficientAccountBalance
  • InvalidTransactionNonce
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of new assertion macros in tests

echo "Checking usage of assert_account_starknet_err..."
rg "assert_account_starknet_err!" --type rust

echo "Checking usage of assert_provider_starknet_err..."
rg "assert_provider_starknet_err!" --type rust

# Check if there are any remaining uses of old assertion patterns
echo "Checking for potential missed migrations..."
rg "assert_matches!.*StarknetError" --type rust

Length of output: 1640


Script:

#!/bin/bash
# Let's search specifically for the usage of our new macros in test files
echo "Searching for macro usages in test files..."
rg "assert_account_starknet_err!" -A 2 -B 2 --type rust tests/
rg "assert_provider_starknet_err!" -A 2 -B 2 --type rust tests/

# Let's also check if these macros are imported in test files
echo "Checking macro imports in test files..."
rg "use.*assert_.*starknet_err" --type rust tests/

Length of output: 510


Script:

#!/bin/bash
# Let's try searching from the repository root with proper path
echo "Searching for macro usages..."
rg "assert_account_starknet_err!" -A 2 -B 2 --type rust crates/katana/rpc/rpc/tests/
rg "assert_provider_starknet_err!" -A 2 -B 2 --type rust crates/katana/rpc/rpc/tests/

# Let's also check macro imports
echo "Checking macro imports..."
rg "use.*assert_.*starknet_err" --type rust crates/katana/rpc/rpc/tests/

# Let's find all test files to make sure we're searching in the right place
echo "Listing test files..."
fd ".*test.*\.rs$" crates/katana/rpc/rpc/tests/

Length of output: 6194

crates/katana/rpc/rpc/tests/starknet.rs (5)

176-176: LGTM! Macro replacement for class declaration error handling.

The change from assert_starknet_err! to assert_account_starknet_err! maintains the error checking behavior while providing better account-specific context.


407-407: LGTM! Enhanced error assertion for insufficient balance validation.

The macro replacement appropriately handles the account-specific insufficient balance error case.


449-449: LGTM! Improved fee-related error assertions.

The macro replacements correctly handle both insufficient max fee and insufficient account balance scenarios in the fee validation tests.

Also applies to: 470-470


526-526: LGTM! Updated signature validation error handling.

The macro replacement properly asserts the account validation failure for invalid signatures.


572-572: LGTM! Enhanced nonce validation error assertions.

The macro replacements correctly handle invalid transaction nonce scenarios, maintaining proper error checking behavior.

Also applies to: 597-597

crates/katana/rpc/rpc/src/starknet/mod.rs (2)

3-3: LGTM! Structural changes for forking support

The addition of the forking module and ForkedClient integration aligns well with the PR objectives to support fetching non-state data from forked networks.

Also applies to: 10-10, 71-72


85-93: LGTM! Well-structured constructor implementation

Ohayo, sensei! The constructor implementation follows good practices:

  • Avoids code duplication by using a shared new_inner method
  • Maintains backward compatibility with the existing new method
  • Properly handles the optional forked_client

Also applies to: 95-107

crates/katana/rpc/rpc/src/starknet/mod.rs Outdated Show resolved Hide resolved
crates/katana/rpc/rpc/tests/forking.rs Outdated Show resolved Hide resolved
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: 4

🧹 Outside diff range and nitpick comments (4)
crates/katana/rpc/rpc/tests/forking.rs (2)

36-36: Ohayo, sensei! Consider a more descriptive type alias.

The type alias LocalTestVector could be more descriptive to better convey its purpose.

-type LocalTestVector = Vec<(BlockNumber, TxHash)>;
+type LocalBlockTransactions = Vec<(BlockNumber, TxHash)>;

104-106: Ohayo, sensei! Consider tracking the TODO in an issue.

The TODO comment about including genesis forked state update should be tracked.

Would you like me to create a GitHub issue to track this TODO item?

crates/katana/rpc/rpc/src/starknet/mod.rs (2)

72-72: Consider adding error handling for forked client initialization.

The new_forked constructor could benefit from additional error handling to ensure the forked client is properly initialized and connected.

Consider adding validation:

 pub fn new_forked(
     backend: Arc<Backend<EF>>,
     pool: TxPool,
     block_producer: BlockProducer<EF>,
     validator: TxValidator,
     forked_client: ForkedClient,
 ) -> Self {
+    // Validate forked client connection
+    if let Err(e) = forked_client.validate_connection() {
+        log::error!("Failed to initialize forked client: {}", e);
+    }
     Self::new_inner(backend, pool, block_producer, validator, Some(forked_client))
 }

Also applies to: 85-93


Line range hint 108-124: Add documentation for blocking task helpers.

Ohayo, sensei! These helper methods would benefit from documentation explaining their purpose and usage patterns.

Consider adding documentation:

+/// Executes CPU-intensive tasks on a dedicated thread pool to avoid blocking the async runtime.
+/// 
+/// # Arguments
+/// * `func` - The function to execute
+/// 
+/// # Returns
+/// The result of the executed function
 async fn on_cpu_blocking_task<F, T>(&self, func: F) -> T
 where
     F: FnOnce(Self) -> T + Send + 'static,
     T: Send + 'static,

+/// Executes IO-bound tasks on a dedicated thread pool.
+/// 
+/// # Arguments
+/// * `func` - The function to execute
+/// 
+/// # Returns
+/// The result of the executed function
 async fn on_io_blocking_task<F, T>(&self, func: F) -> T
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e48339c and 37884c8.

📒 Files selected for processing (2)
  • crates/katana/rpc/rpc/src/starknet/mod.rs (19 hunks)
  • crates/katana/rpc/rpc/tests/forking.rs (1 hunks)
🔇 Additional comments (5)
crates/katana/rpc/rpc/tests/forking.rs (4)

3-3: Ohayo, sensei! Fix the typo in import statement.

The import cainome::rs::abigen_legacy appears to be incorrect.

-use cainome::rs::abigen_legacy;
+use cairo::rs::abigen_legacy;

14-14: Ohayo, sensei! Add missing imports for used types.

The types MaybePendingBlockWithReceipts, MaybePendingBlockWithTxHashes, and MaybePendingStateUpdate are used but not imported.

-use starknet::core::types::{MaybePendingBlockWithTxs, StarknetError};
+use starknet::core::types::{
+    MaybePendingBlockWithTxs,
+    MaybePendingBlockWithReceipts,
+    MaybePendingBlockWithTxHashes,
+    MaybePendingStateUpdate,
+    StarknetError,
+};

59-59: Ohayo, sensei! Add missing import for Uint256.

The type Uint256 is used but not imported.


1-236: Ohayo, sensei! Well-structured test implementation.

The test file provides comprehensive coverage of forking functionality with well-organized test cases, proper error handling, and clear documentation. The test scenarios effectively cover both successful and error cases, making good use of helper functions for reusable assertions.

crates/katana/rpc/rpc/src/starknet/mod.rs (1)

3-3: LGTM! Clean module organization.

The addition of the forking module and its import follows good Rust module organization practices.

Also applies to: 10-10

crates/katana/rpc/rpc/tests/forking.rs Outdated Show resolved Hide resolved
crates/katana/rpc/rpc/tests/forking.rs Show resolved Hide resolved
crates/katana/rpc/rpc/src/starknet/mod.rs Outdated Show resolved Hide resolved
Comment on lines +654 to +683
// seach in the pending block if the transaction is not found
if let Some(pending_executor) = this.pending_executor() {
let pending_executor = pending_executor.read();
let pending_txs = pending_executor.transactions();
let (_, res) = pending_txs
.iter()
.find(|(tx, _)| tx.hash == hash)
.ok_or(StarknetApiError::TxnHashNotFound)?;

// TODO: should impl From<ExecutionResult> for TransactionStatus
let status = match res {
ExecutionResult::Failed { .. } => TransactionStatus::Rejected,
ExecutionResult::Success { receipt, .. } => {
if receipt.is_reverted() {
TransactionStatus::AcceptedOnL2(
TransactionExecutionStatus::Reverted,
)
} else {
TransactionStatus::AcceptedOnL2(
TransactionExecutionStatus::Succeeded,
)
}
}
};

Ok(Some(status))
} else {
// Err(StarknetApiError::TxnHashNotFound)
Ok(None)
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Race condition concern verified in pending transaction handling

Ohayo, sensei! After analyzing the codebase, I can confirm the race condition concern is valid. The PendingExecutor is indeed wrapped in an Arc<RwLock<...>>, and the current implementation has a potential TOCTOU (Time-of-Check-Time-of-Use) issue between acquiring the executor and reading the transactions.

The suggested fix in the review comment is correct:

  • Combining the pending_executor() call with the read() operation into a single atomic read
  • Restructuring the logic to avoid the .ok_or() which could panic if the transaction is removed

The proposed solution would make the code more robust against concurrent modifications of the pending transaction pool.

🔗 Analysis chain

Potential race condition in pending transaction status.

Ohayo, sensei! There's a potential race condition when checking transaction status in the pending block. The transaction might be removed from the pending block between the time we check its existence and when we try to access its result.

Consider using a single atomic read:

-if let Some(pending_executor) = this.pending_executor() {
-    let pending_executor = pending_executor.read();
-    let pending_txs = pending_executor.transactions();
-    let (_, res) = pending_txs
+if let Some(pending_executor) = this.pending_executor().map(|e| e.read()) {
+    if let Some((_, res)) = pending_executor.transactions()
         .iter()
-        .find(|(tx, _)| tx.hash == hash)
-        .ok_or(StarknetApiError::TxnHashNotFound)?;
+        .find(|(tx, _)| tx.hash == hash) {

Let me gather more context about the pending_executor implementation to better understand the concurrency model.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for similar patterns in other files
ast-grep --pattern 'if let Some(pending_executor) = $_.pending_executor() {
    $$$
    let pending_txs = $_.transactions();
    $$$
}'

Length of output: 2866


Script:

#!/bin/bash
# Check the implementation of pending_executor and related types
ast-grep --pattern 'fn pending_executor($$$) -> $$ {
    $$$
}'

# Also check for any RwLock usage
rg "RwLock" -A 2 

Length of output: 12488

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: 3

🧹 Outside diff range and nitpick comments (4)
crates/katana/rpc/rpc-types-builder/src/block.rs (2)

51-53: Ohayo! Nice architectural improvement in block hash retrieval!

The new approach of first fetching the block hash aligns well with the forking functionality objectives. This separation of concerns allows for better handling of forked chain data.


55-56: Consider enhancing error handling, sensei!

While using expect is valid here, consider providing more context in error messages for better debugging, especially when dealing with forked chains.

-            .expect("should exist if block exists");
+            .expect("block should exist as its hash was just verified");
crates/katana/rpc/rpc/tests/forking.rs (2)

33-33: Ohayo, sensei! Grammatical correction in function comment

There's a grammatical error on line 33. It should be "This function will fork Sepolia..." instead of "forked Sepolia".

Apply this diff to fix the grammar:

-/// This function will forked Sepolia at block [`FORK_BLOCK_NUMBER`] and create 10 blocks, each has
+/// This function will fork Sepolia at block [`FORK_BLOCK_NUMBER`] and create 10 blocks, each has

46-46: Ohayo, sensei! Typo in comment

There's a typo on line 46. The word "emtpy" should be "empty".

Apply this diff to correct the typo:

-    // create some emtpy blocks and dummy transactions
+    // create some empty blocks and dummy transactions
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 37884c8 and 36c12fd.

📒 Files selected for processing (4)
  • crates/katana/rpc/rpc-types-builder/src/block.rs (1 hunks)
  • crates/katana/rpc/rpc-types/src/block.rs (5 hunks)
  • crates/katana/rpc/rpc/src/starknet/mod.rs (19 hunks)
  • crates/katana/rpc/rpc/tests/forking.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/katana/rpc/rpc-types/src/block.rs
🔇 Additional comments (5)
crates/katana/rpc/rpc-types-builder/src/block.rs (1)

64-64: Clean and clear BlockWithReceipts construction!

The explicit use of hash in the constructor improves code clarity and maintains consistency with the new block handling approach.

crates/katana/rpc/rpc/src/starknet/mod.rs (4)

Line range hint 3-53: LGTM! Module structure aligns with forking feature.

The new forking module and related imports are well-organized and properly support the PR's objective of enabling forked block data fetching.


Line range hint 72-107: LGTM! Clean implementation of forked client support.

Ohayo, sensei! The changes to support forked clients are well-structured:

  • Optional forked_client allows graceful fallback
  • Common initialization logic extracted to new_inner follows DRY principle

654-683: Race condition in pending transaction handling.

The existing review comment about the race condition is still valid.


909-913: Verify intended behavior for pending state updates.

Ohayo, sensei! The code immediately returns BlockNotFound for pending blocks in state updates. Please verify if this is the intended behavior or if pending state updates should be supported in the future.

Comment on lines +696 to +891
.iter()
.filter_map(|(tx, result)| match result {
ExecutionResult::Success { receipt, .. } => {
Some((tx.clone(), receipt.clone()))
}
ExecutionResult::Failed { .. } => None,
})
.collect::<Vec<_>>();

let block = PendingBlockWithReceipts::new(header, receipts.into_iter());
return Ok(Some(MaybePendingBlockWithReceipts::Pending(block)));
}
}

if let Some(num) = provider.convert_block_id(block_id)? {
let block = katana_rpc_types_builder::BlockBuilder::new(num.into(), provider)
.build_with_receipts()?
.map(MaybePendingBlockWithReceipts::Block);

StarknetApiResult::Ok(block)
} else {
StarknetApiResult::Ok(None)
}
})
.await?;

if let Some(block) = block {
Ok(block)
} else if let Some(client) = &self.inner.forked_client {
Ok(client.get_block_with_receipts(block_id).await?)
} else {
Err(StarknetApiError::BlockNotFound)
}
}

async fn block_with_tx_hashes(
&self,
block_id: BlockIdOrTag,
) -> StarknetApiResult<MaybePendingBlockWithTxHashes> {
let block = self
.on_io_blocking_task(move |this| {
let provider = this.inner.backend.blockchain.provider();

if BlockIdOrTag::Tag(BlockTag::Pending) == block_id {
if let Some(executor) = this.pending_executor() {
let block_env = executor.read().block_env();
let latest_hash = provider.latest_hash().map_err(StarknetApiError::from)?;

let l1_gas_prices = block_env.l1_gas_prices.clone();
let l1_data_gas_prices = block_env.l1_data_gas_prices.clone();

let header = PartialHeader {
l1_da_mode: L1DataAvailabilityMode::Calldata,
l1_data_gas_prices,
l1_gas_prices,
number: block_env.number,
parent_hash: latest_hash,
timestamp: block_env.timestamp,
protocol_version: this.inner.backend.chain_spec.version.clone(),
sequencer_address: block_env.sequencer_address,
};

// TODO(kariy): create a method that can perform this filtering for us
// instead of doing it manually.

// A block should only include successful transactions, we filter out the
// failed ones (didn't pass validation stage).
let transactions = executor
.read()
.transactions()
.iter()
.filter(|(_, receipt)| receipt.is_success())
.map(|(tx, _)| tx.hash)
.collect::<Vec<_>>();

let block = PendingBlockWithTxHashes::new(header, transactions);
return Ok(Some(MaybePendingBlockWithTxHashes::Pending(block)));
}
}

if let Some(num) = provider.convert_block_id(block_id)? {
let block = katana_rpc_types_builder::BlockBuilder::new(num.into(), provider)
.build_with_tx_hash()?
.map(MaybePendingBlockWithTxHashes::Block);

StarknetApiResult::Ok(block)
} else {
StarknetApiResult::Ok(None)
}
})
.await?;

if let Some(block) = block {
Ok(block)
} else if let Some(client) = &self.inner.forked_client {
Ok(client.get_block_with_tx_hashes(block_id).await?)
} else {
Err(StarknetApiError::BlockNotFound)
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider standardizing error handling across block methods.

Ohayo, sensei! While the block-related methods follow a consistent pattern for data retrieval (local → pending → forked), the error handling could be standardized. For example:

  1. block_with_txs returns BlockNotFound on failure
  2. block_with_receipts returns BlockNotFound on failure
  3. block_with_tx_hashes returns BlockNotFound on failure

Consider creating a helper trait to standardize this error handling:

trait BlockResultHandler<T> {
    fn handle_block_result(
        result: Option<T>,
        forked_client: &Option<ForkedClient>,
        block_id: BlockIdOrTag,
    ) -> StarknetApiResult<T>;
}

This would help ensure consistent error handling across all block-related methods.

Comment on lines +141 to +159
for ((num, _), _) in local_only_block {
let id = BlockIdOrTag::Number(num);

let block = provider.get_block_with_txs(id).await?;
assert_matches!(block, MaybePendingBlockWithTxs::Block(b) if b.block_number == num);

let block = provider.get_block_with_receipts(id).await?;
assert_matches!(block, starknet::core::types::MaybePendingBlockWithReceipts::Block(b) if b.block_number == num);

let block = provider.get_block_with_tx_hashes(id).await?;
assert_matches!(block, starknet::core::types::MaybePendingBlockWithTxHashes::Block(b) if b.block_number == num);

let count = provider.get_block_transaction_count(id).await?;
assert_eq!(count, 1, "all the locally generated blocks should have 1 tx");

// TODO: uncomment this once we include genesis forked state update
// let state = provider.get_state_update(id).await?;
// assert_matches!(state, starknet::core::types::MaybePendingStateUpdate::Update(_));
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo, sensei! Consider refactoring repetitive code in block assertions

The assertions within the loop from lines 141 to 159 are repetitive. Refactoring them into a helper function can enhance readability and reduce code duplication.

Here's how you might refactor the code:

async fn assert_block_details(provider: &impl Provider, id: BlockIdOrTag, num: BlockNumber) -> Result<()> {
    let block = provider.get_block_with_txs(id).await?;
    assert_matches!(block, MaybePendingBlockWithTxs::Block(b) if b.block_number == num);

    let block = provider.get_block_with_receipts(id).await?;
    assert_matches!(block, MaybePendingBlockWithReceipts::Block(b) if b.block_number == num);

    let block = provider.get_block_with_tx_hashes(id).await?;
    assert_matches!(block, MaybePendingBlockWithTxHashes::Block(b) if b.block_number == num);

    let count = provider.get_block_transaction_count(id).await?;
    assert_eq!(count, 1, "All the locally generated blocks should have 1 tx");

    Ok(())
}

Then, replace the code within the loop with a call to this function:

for ((num, _), _) in local_only_block {
    let id = BlockIdOrTag::Number(num);
    assert_block_details(&provider, id, num).await?;
}

Comment on lines +361 to +369
let tx = provider.get_transaction_by_hash(tx_hash).await?;
assert_eq!(*tx.transaction_hash(), tx_hash);

let tx = provider.get_transaction_receipt(tx_hash).await?;
assert_eq!(*tx.receipt.transaction_hash(), tx_hash);

let result = provider.get_transaction_status(tx_hash).await;
assert!(result.is_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

Ohayo, sensei! Enhance error handling in transaction status checks

In the loop starting at line 360, the transaction status is checked, but potential errors aren't handled. Consider adding error handling to improve test robustness.

Modify the code to handle errors explicitly:

let result = provider.get_transaction_status(tx_hash).await;
match result {
    Ok(status) => assert!(status.tx_status.is_confirmed()),
    Err(e) => panic!("Failed to get transaction status: {:?}", e),
}

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.

Add fork provider for non-state data
1 participant