-
Notifications
You must be signed in to change notification settings - Fork 176
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
Conversation
WalkthroughOhayo, sensei! This pull request introduces significant enhancements across several files in the Katana project, focusing on the integration of a Changes
Assessment against linked issues
Possibly related PRs
Feel free to reach out if you need further insights, sensei! 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 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
toi as u64
fortransaction_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
andtrace
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 sidecrates/katana/rpc/rpc/src/starknet/mod.rs (2)
620-621
: Address the TODO regarding transaction status handlingOhayo, 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 forStarknetApi
Ohayo, sensei!
The
new_forked
method closely mirrors the existingnew
method but adds aforked_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
📒 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 ofurl
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
anddeprecated_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
anddeprecated_declared_classes
as seen in the comments:
crates/saya/provider/src/rpc/state.rs
: "Currently, Katana does not supportreplaced_classes
anddeprecated_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/mapsSetting 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 rustLength 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 usesMaybePendingStateUpdate
- 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 rustLength 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 tasksThe retention of
on_io_blocking_task
andon_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 2Also 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 forMaybePendingBlockWithTxs
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 forMaybePendingBlockWithTxHashes
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:
- This is the right time to address this technical debt?
- The new
From
implementation adds to this problem?Let's analyze the impact:
crates/katana/node/src/lib.rs (7)
38-38
: Ohayo, sensei! ImportingForkedClient
is appropriate.The addition of the
ForkedClient
import is necessary for handling forked clients.
91-91
: Ohayo, sensei! Addition offorked_client
field toNode
struct is correct.Including
Option<ForkedClient>
in theNode
struct properly allows for optional forked client handling.
98-98
: Ohayo, sensei! Changingself
tomut self
inlaunch
method is necessary.Making
self
mutable allows modification ofself.forked_client
within the method.
144-144
: Ohayo, sensei! Verify the use ofself.forked_client.take()
.Using
take()
movesforked_client
out ofself
. Please ensure thatforked_client
is not needed elsewhere after this operation.
242-248
: Ohayo, sensei! Update tospawn
function signature is correct.Including
Option<ForkedClient>
in thespawn
function allows passing the forked client appropriately.
251-251
: Ohayo, sensei! Destructuringnode_components
includesforked_client
correctly.Unpacking
forked_client
fromnode_components
ensures all components are properly accessed.
256-272
: Ohayo, sensei! Conditional initialization ofStarknetApi
is well-implemented.Switching between
StarknetApi::new_forked
andStarknetApi::new
based on the presence offorked_client
is appropriate.crates/katana/rpc/rpc-types/src/error/starknet.rs (3)
10-11
: Ohayo, sensei! Necessary imports added correctlyThe imports of
StarknetRsError
andStarknetRsProviderError
are appropriately added and aliased, ensuring proper error conversion.
246-261
: Ohayo, sensei! Verify error mapping inFrom<StarknetRsProviderError>
implementationEnsure that all variants of
StarknetRsProviderError
are properly mapped toStarknetApiError
. 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 typesChanging
transaction_index
fromusize
tou64
enhances consistency and supports a broader range of indices. Please verify that all instances oftransaction_index
in the codebase are updated tou64
to prevent any type mismatches.You can use the following script to check for any remaining occurrences of
transaction_index
usingusize
:✅ 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 usingu64
. The change fromusize
tou64
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
starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => { | ||
panic!("shouldn't be possible to be pending") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => { | |
panic!("shouldn't be possible to be pending") | |
} | |
starknet::core::types::MaybePendingBlockWithTxs::PendingBlock(_) => { | |
return Err(Error::UnexpectedPendingBlock) | |
} |
starknet::core::types::MaybePendingBlockWithTxHashes::PendingBlock(_) => { | ||
panic!("shouldn't be possible to be pending") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
starknet::core::types::MaybePendingBlockWithReceipts::PendingBlock(_) => { | ||
panic!("shouldn't be possible to be pending") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
BlockIdOrTag::Tag(_) => { | ||
panic!("shouldn't be possible to be tag") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
BlockIdOrTag::Tag(_) => { | ||
panic!("shouldn't be possible to be tag") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Codecov ReportAttention: Patch coverage is
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 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 AssertionsCurrently, 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
📒 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 issueOhayo, 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! Replacepanic!
with error return for pending blocksUsing
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 tagsConsistently handle unexpected tags by returning an appropriate error instead of panicking.
143-145
: Ohayo, sensei! Replacepanic!
with proper error handling for pending blocksTo maintain application stability, avoid using
panic!
and return a descriptive error instead.
161-163
: Ohayo, sensei! Handle unexpected pending blocks without panickingReturning an error instead of panicking improves the robustness of your application.
181-183
: Ohayo, sensei! Replace panic with error handlingConsistently handle unexpected pending blocks by returning errors instead of panicking.
230-232
: Ohayo, sensei! Handle unexpected tags without panickingReturning an error for unexpected tags enhances the reliability of your application.
73-83
: Ohayo, sensei! Simplify asynchronous error handling inget_transaction_status
The current implementation awaits
receipt
andstatus
concurrently, but only usesreceipt
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
?
impl From<Error> for StarknetApiError { | ||
fn from(value: Error) -> Self { | ||
match value { | ||
Error::Provider(provider_error) => provider_error.into(), | ||
Error::BlockOutOfRange => StarknetApiError::BlockNotFound, | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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.
#[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, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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.
#[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, | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 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
📒 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 instarknet.rs
for account-related errorsassert_provider_starknet_err!
is used 8 times inforking.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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 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
📒 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
// 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) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
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 theread()
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 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
📒 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.
.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) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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:
block_with_txs
returnsBlockNotFound
on failureblock_with_receipts
returnsBlockNotFound
on failureblock_with_tx_hashes
returnsBlockNotFound
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.
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(_)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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?;
}
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()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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),
}
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
ForkedClient
for enhanced interaction with Starknet blockchain forks.Bug Fixes
Documentation
Tests