-
Notifications
You must be signed in to change notification settings - Fork 39
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(sdk)!: support errors in mock #2277
base: v1.6-dev-ugly
Are you sure you want to change the base?
Conversation
WalkthroughThe changes in this pull request focus on enhancing the Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 21
🧹 Outside diff range and nitpick comments (40)
packages/rs-sdk/src/platform/transition/broadcast.rs (2)
29-31
: Enhance the TODO comment with specific requirements
While the error handling simplification is good, the TODO comment should be more specific about what aspects of execution error handling need improvement (e.g., specific error cases, recovery strategies, etc.).
Consider updating the comment to be more specific:
- // TODO: We need better way to handle execution errors
+ // TODO: Enhance execution error handling with specific error types and recovery strategies for network/timeout failures
43-48
: Enhance retry logic TODO with specific requirements
The TODO comment about retry logic should be more specific about the retry strategy requirements (e.g., backoff strategy, max attempts, retriable errors).
Consider updating the comment to be more specific:
- // TODO: Implement retry logic
+ // TODO: Implement exponential backoff retry logic with configurable max attempts for transient failures
packages/rs-sdk/src/platform/transition/top_up_identity.rs (2)
54-58
: Implement exponential backoff retry strategy
The TODO about retry logic needs implementation. Consider:
- Using exponential backoff with jitter for retries
- Setting appropriate timeout and max retry attempts
- Handling specific error conditions differently (e.g., temporary vs. permanent failures)
Would you like me to provide a code example implementing a robust retry strategy using tokio's retry utilities?
Line range hint 1-85
: Consider implementing comprehensive error handling strategy
While the transition to into_inner()
simplifies error handling, this critical identity operation would benefit from a more comprehensive error handling strategy:
- Define specific error types for different failure scenarios
- Implement proper error context and chain of custody
- Add logging for debugging and monitoring
- Consider adding metrics for tracking success/failure rates
This would improve maintainability and debugging capabilities.
packages/rs-sdk/Cargo.toml (1)
9-9
: LGTM! Consider using a more flexible version constraint.
The addition of the backon
crate with the tokio-sleep
feature is appropriate for implementing retry logic. However, consider using a more flexible version constraint (e.g., ~1.2
or ^1.2
) to allow for compatible updates while maintaining stability.
-backon = { version = "1.2", features = ["tokio-sleep"] }
+backon = { version = "^1.2", features = ["tokio-sleep"] }
packages/rs-drive-proof-verifier/src/error.rs (1)
90-91
: Consider documenting the serialization behavior.
While the implementation is correct, it would be helpful to add a doc comment explaining that this enum supports serialization when the "mocks" feature is enabled, as this behavior might be important for users implementing mock scenarios.
/// Errors returned by the context provider
+///
+/// When the "mocks" feature is enabled, this enum implements bincode's Encode and Decode traits
+/// to support serialization in mock scenarios.
#[derive(Debug, thiserror::Error)]
#[cfg_attr(feature = "mocks", derive(bincode::Encode, bincode::Decode))]
pub enum ContextProviderError {
packages/rs-dapi-client/src/request_settings.rs (2)
26-27
: Consider enhancing the retries documentation further.
While the current documentation is clear, it could be more comprehensive by:
- Explaining what happens when retries is 0
- Mentioning the default value (5)
- Adding an example to illustrate the retry behavior
Consider updating the documentation like this:
- /// Number of retries in case of failed requests. If max retries reached, the last error is returned.
- /// 1 means one request and one retry in case of error, etc.
+ /// Number of retries in case of failed requests. If max retries reached, the last error is returned.
+ /// - 0 means only one attempt with no retries
+ /// - 1 means one initial request and one retry in case of error
+ /// - n means one initial request and n retries
+ ///
+ /// Defaults to 5 if not specified.
+ ///
+ /// # Example
+ /// ```
+ /// // With retries = 2:
+ /// // 1. Initial request fails
+ /// // 2. First retry fails
+ /// // 3. Second retry succeeds or returns the last error
+ /// ```
84-92
: Consider improving method documentation.
The documentation could be enhanced by:
- Removing the empty line at line 88
- Adding an example showing how different settings are combined
Consider updating the documentation like this:
/// Create [AppliedRequestSettings] from [RequestSettings] with default values.
///
/// Combine provided [RequestSettings] together with [request-level overrides](TransportRequest::SETTINGS_OVERRIDES).
///
- ///
/// # Arguments
///
/// * `global_settings` - global settings for all requests.
/// * `request_settings` - settings for a specific request.
+ ///
+ /// # Example
+ /// ```
+ /// use crate::RequestSettings;
+ ///
+ /// let global = RequestSettings {
+ /// retries: Some(3),
+ /// ..Default::default()
+ /// };
+ ///
+ /// let request = RequestSettings {
+ /// timeout: Some(Duration::from_secs(20)),
+ /// ..Default::default()
+ /// };
+ ///
+ /// // Will use:
+ /// // - retries = 3 (from global)
+ /// // - timeout = 20s (from request)
+ /// // - other values from defaults
+ /// let applied = AppliedRequestSettings::from_settings::<MyRequest>(&global, &request);
+ /// ```
packages/rs-sdk/src/platform/transition/put_identity.rs (2)
60-60
: Enhance the TODO comment with specific requirements
The current TODO comment "We need better way to handle execution errors" is too vague. Consider documenting:
- What specific execution errors need better handling
- What the desired behavior should be
- Any specific error cases that need special treatment
105-105
: Consider implementing a robust retry mechanism
The TODO comment about retry logic should be expanded into a comprehensive retry mechanism that:
- Uses exponential backoff with jitter
- Allows configurable retry attempts and timeouts
- Distinguishes between retryable and non-retryable errors
- Provides proper logging and metrics for retry attempts
Example approach:
pub struct RetryConfig {
max_attempts: u32,
initial_backoff: Duration,
max_backoff: Duration,
jitter_factor: f64,
}
async fn with_retry<F, Fut, T, E>(
config: &RetryConfig,
operation: F,
) -> Result<T, E>
where
F: Fn() -> Fut,
Fut: Future<Output = Result<T, E>>,
E: Error,
{
// Implementation with exponential backoff and jitter
}
packages/rs-sdk/src/platform/transition/put_contract.rs (1)
Line range hint 127-133
: Consider enhancing error handling for state transition verification.
The current error handling for the state transition proof verification could be more specific. Instead of the generic "proved a non document" error message, consider:
- Creating specific error variants for different verification failure cases
- Including more context in the error message
Here's a suggested improvement:
- Err(Error::DapiClientError("proved a non document".to_string())),
+ Err(Error::StateTransitionError(format!(
+ "Expected DataContract proof result, got {:?}",
+ result
+ ))),
packages/rs-sdk/tests/fetch/epoch.rs (1)
28-30
: Consider improving the error message.
The error handling change using into_inner()
looks good, but the error message could be more descriptive to aid in debugging test failures.
Consider using a more descriptive error message:
- .expect("get identity");
+ .expect("failed to get identity for epoch metadata");
packages/rs-sdk/src/platform/transition/update_price_of_document.rs (2)
101-101
: Consider documenting error cases and improving error handling
While the use of into_inner()
simplifies error handling, the TODO comment suggests this is an interim solution. Consider:
- Documenting the specific error cases that can occur
- Implementing more robust error handling with proper error types and recovery strategies
Would you like help designing a more comprehensive error handling strategy to address the TODO comment?
Line range hint 1-165
: Consider implementing a more robust state transition handling pattern
The current implementation could benefit from a more structured approach to state transition handling:
- Consider extracting common retry/timeout logic into a reusable middleware
- Implement a proper state machine for tracking document updates
- Add telemetry for monitoring state transition performance and success rates
This would improve reliability and maintainability of the blockchain operations.
Would you like help designing this improved architecture?
packages/rs-sdk/src/platform/transition/transfer_document.rs (1)
99-99
: TODO comment needs to be addressed.
The comment suggests that the current error handling approach might need improvement. Consider creating a more robust error handling strategy.
Would you like me to help design a more comprehensive error handling solution or create an issue to track this improvement?
packages/rs-sdk/src/platform/transition/put_document.rs (1)
113-117
: Implement retry logic for blockchain operations
The TODO comment about retry logic is crucial for reliability. Given this is a blockchain platform, consider implementing:
- Exponential backoff for network issues
- Maximum retry attempts configuration
- Specific retry conditions for different error types
Would you like me to:
- Generate a retry mechanism implementation using tokio-retry?
- Create a GitHub issue to track this enhancement?
packages/rs-sdk/src/platform/transition/vote.rs (2)
111-115
: Track retry logic implementation
The TODO comment indicates a need for retry logic implementation, which is important for handling transient failures in a distributed system.
Would you like me to help create a GitHub issue to track the implementation of retry logic? This could include:
- Retry count configuration
- Exponential backoff strategy
- Specific error conditions that should trigger retries
Line range hint 1-171
: Consider implementing a robust retry strategy
Given that this code interacts with a distributed blockchain system, implementing a comprehensive retry strategy would improve reliability. Consider:
- Creating a configurable retry policy trait
- Implementing exponential backoff with jitter
- Defining specific error conditions that warrant retries
- Adding metrics/logging for failed attempts
This would be particularly valuable for the put_to_platform_and_wait_for_response
method where transient network issues are more likely to occur.
packages/dapi-grpc/src/mock.rs (2)
80-91
: Document the serialization format for Option.
The serialization format (0 for None, 1 for Some followed by serialized value) should be documented to help maintainers understand the wire format.
Add documentation above the implementation:
/// Serialization format:
/// - None: [0]
/// - Some(value): [1, serialized_value...]
impl<T: Mockable> Mockable for Option<T> {
Based on the code review and search results, I can now provide a final assessment of the test coverage for error scenarios in the mock implementations.
Test coverage for Result<T,E> mock implementation needs improvement
The implementation of Result<T,E> mock serialization/deserialization lacks dedicated test coverage. While the implementation appears sound with proper error handling through SerializableResult enum, there are no explicit test cases verifying:
- Error case serialization/deserialization
- Handling of None cases
- Proper propagation of errors from inner types
Recommended test cases to add:
- Test serialization of Ok and Err variants
- Test deserialization of Ok and Err variants
- Test handling of None results from inner type serialization
- Test error propagation when inner type serialization fails
🔗 Analysis chain
Line range hint 1-205
: Verify test coverage for error scenarios.
The implementation successfully supports error mocking through Result<T, E> and provides comprehensive serialization capabilities. Let's verify the test coverage:
Let me analyze the test coverage for error scenarios in mock implementations by searching for specific test cases.
Let me try a different search pattern to find test coverage for the mock implementations.
Let me check for test files in a broader scope and specifically look for Result-related tests.
Let me check specifically for test coverage of the Result<T,E> mock implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check test coverage for error scenarios in mock implementations
# Test 1: Look for test modules and error test cases
echo "Searching for test modules and error test cases..."
rg -l "#\[cfg\(test\)\]" --type rust
rg "test.*error" --type rust -A 5
# Test 2: Check for Result usage in tests
echo "Checking Result usage in tests..."
rg "Result<.*>" --type rust -g "*test*.rs"
Length of output: 70640
Script:
#!/bin/bash
# Search for test cases related to Result<T,E> mock implementation
echo "Searching for test cases of Result mock implementation..."
rg "test.*Result.*mock" --type rust -A 5
# Search for mock serialization tests
echo "Searching for mock serialization tests..."
rg "test.*mock_serialize" --type rust -A 5
# Search for mock deserialization tests
echo "Searching for mock deserialization tests..."
rg "test.*mock_deserialize" --type rust -A 5
Length of output: 449
Script:
#!/bin/bash
# Search for test modules in the mock.rs file and related files
echo "Searching for test modules in mock implementations..."
rg "#\[cfg\(test\)\]" -A 10 --type rust packages/dapi-grpc/src/mock.rs
# Search for any test functions related to Mockable trait
echo "Searching for Mockable trait tests..."
rg "impl.*Mockable.*\{" -A 20 --type rust packages/dapi-grpc/src/mock.rs
# Look for test files that might contain mock tests
echo "Looking for test files with mock tests..."
fd "test.*\.rs$" packages/dapi-grpc/
Length of output: 3924
Script:
#!/bin/bash
# Search for test files in the entire repository that might test Result serialization
echo "Searching for Result-related tests..."
fd -e rs | xargs rg "test.*Result" -B 2 -A 5
# Look for test modules in mock.rs and related files
echo "Searching for test modules in serde_mockable..."
rg -l "#\[cfg\(test\)\]" packages/dapi-grpc/src/mock/serde_mockable.rs || echo "File not found"
# Check if there are any integration tests
echo "Checking for integration tests..."
fd -e rs -p "tests/" packages/dapi-grpc/
Length of output: 133728
Script:
#!/bin/bash
# Look for test files in dapi-grpc package
echo "Looking for test files in dapi-grpc..."
find packages/dapi-grpc -type f -name "*test*.rs"
# Search for mock-related test functions in mock.rs
echo "Searching for mock-related test functions..."
rg "#\[test\]" -B 2 -A 10 packages/dapi-grpc/src/mock.rs
# Search for any test modules in mock.rs
echo "Searching for test modules..."
rg "mod tests" -A 10 packages/dapi-grpc/src/mock.rs
Length of output: 419
packages/rs-sdk/src/core/transaction.rs (1)
184-184
: Address TODO comment regarding execution error handling.
The TODO comment indicates a need for better execution error handling. Since this PR focuses on error handling improvements, it would be beneficial to address this TODO now.
Would you like me to propose an improved error handling implementation for the execution errors?
packages/rs-sdk/src/sdk.rs (1)
122-124
: Add more detailed documentation for the new field.
The documentation comment "Global settings of dapi client" could be more descriptive to explain the purpose, usage, and impact of these settings.
Consider expanding the documentation:
- /// Global settings of dapi client
+ /// Global request settings for the DAPI client that control timeouts, retries,
+ /// and other request-specific behaviors. These settings are used as defaults
+ /// for all requests made through this SDK instance unless overridden.
pub(crate) dapi_client_settings: RequestSettings,
packages/rs-dapi-client/src/executor.rs (4)
64-70
: Clarify IntoInner
trait to avoid confusion with standard Into
The custom IntoInner
trait may be confused with the standard Into
trait, potentially leading to ambiguity.
Consider renaming IntoInner
to a more distinctive name to prevent confusion, such as ExtractInner
or UnwrapInner
.
Also applies to: 103-111, 130-137
26-27
: Improve documentation clarity and grammar
In the documentation comments for IntoInner<T>
and InnerInto<T>
, consider rephrasing for clarity.
For example, you could rephrase:
-/// This function returns the inner type, dropping additional context information.
+/// Returns the inner type, dropping additional context information.
-/// Convert inner type without losing additional context information of the wrapper.
+/// Converts the inner type without losing the additional context information of the wrapper.
Also applies to: 33-34
69-70
: Add missing documentation for methods
Some method implementations are missing documentation comments, such as fn into_inner(self) -> I
in several places.
Consider adding documentation comments to these methods for consistency and better code readability.
Also applies to: 108-109, 131-132, 144-145
92-101
: Simplify the Default
implementation for ExecutionResponse<R>
Since the Default
trait is being implemented, you can use Default::default()
for fields where appropriate.
Apply this diff to simplify the implementation:
impl<R: Default> Default for ExecutionResponse<R> {
fn default() -> Self {
Self {
retries: Default::default(),
- address: "http://127.0.0.1".parse().expect("create mock address"),
+ address: Default::default(),
inner: Default::default(),
}
}
}
This assumes that Address
implements Default
appropriately for your use case.
packages/rs-sdk/src/platform/fetch_unproved.rs (2)
96-100
: Ensure comprehensive error context in ExecutionError
When mapping errors to ExecutionError
, ensure that all relevant error information is preserved to aid in debugging. Consider including additional context or logging if the inner
error does not provide sufficient details.
75-110
: Consider adding unit tests for retry and error handling logic
To verify that the new retry mechanism and error handling work as intended, it would be beneficial to add unit tests that cover various scenarios, including transient failures, retries, and error propagation.
Would you like assistance in creating these unit tests or setting up test scenarios to ensure robustness?
packages/rs-sdk/tests/fetch/mock_fetch.rs (2)
157-158
: Add a doc comment to the test_mock_fetch_retry
function
Adding a doc comment above the test_mock_fetch_retry
function will enhance code readability and provide a clear explanation of the test's purpose.
164-164
: Re-evaluate the necessity of assert_ne!(query_correct, query_stale);
Since Identifier::random()
generates random identifiers, it's highly unlikely that query_correct
and query_stale
would be equal. The assert_ne!
check may be unnecessary.
packages/rs-dapi-client/src/mock.rs (3)
264-264
: Typographical error in comment
There's a minor typo in the comment. It should read "each of them is serialized to bytes."
Apply this diff to correct the typo:
- // We encode data as vec![inner, address, retries] where each od them is serialized to bytes
+ // We encode data as vec![inner, address, retries] where each of them is serialized to bytes
306-306
: Typographical error in comment
There's a minor typo in the comment. It should read "each of them is serialized to bytes."
Apply this diff to correct the typo:
- // We encode data as vec![inner, address, retries] where each od them is serialized to bytes
+ // We encode data as vec![inner, address, retries] where each of them is serialized to bytes
345-384
: Ensure comprehensive documentation for new traits
The new traits FromInner
and InnerInto
are introduced. To assist other developers and maintain code clarity, please ensure that these traits are thoroughly documented with examples and use cases.
packages/rs-sdk/src/sync.rs (3)
149-149
: Typographical error in documentation
In the "Troubleshooting" section, there's an extraneous comma after the period:
- Original:
- ensure returned value is [
ExecutionResult].,
- Corrected:
- ensure returned value is [
ExecutionResult].
Apply this diff to fix the typo:
- /// - ensure returned value is [`ExecutionResult`].,
+ /// - ensure returned value is [`ExecutionResult`].`
220-222
: Consider adjusting the log level for retry notifications
In the notify
closure, retries are logged at the warn
level:
tracing::warn!(?duration, ?error, "request failed, retrying");
If retries are expected behavior, it might be more appropriate to use the info
level to avoid cluttering logs with warnings during normal operation.
Consider changing the log level:
- tracing::warn!(?duration, ?error, "request failed, retrying");
+ tracing::info!(?duration, ?error, "request failed, retrying");
194-194
: Remove extra space in variable declaration
There's an extra space between let
and result
:
let result = ::backon::Retryable::retry(closure, backoff_strategy)
Apply this diff to correct it:
- let result = ::backon::Retryable::retry(closure, backoff_strategy)
+ let result = ::backon::Retryable::retry(closure, backoff_strategy)
packages/rs-sdk/src/mock/requests.rs (2)
238-238
: Address the TODO: Implement full serialization for Status
The TODO comment indicates that only the code
and message
fields are currently serialized for Status
. For comprehensive error representation, consider implementing full serialization, including any additional relevant fields in Status
.
Do you need assistance in implementing the full serialization for Status
? I can help generate the necessary code or open a GitHub issue to track this task.
310-340
: Add unit tests for MockResponse
implementations
Consider adding unit tests for the new MockResponse
implementations, especially for complex types like Result<T, E>
, tuples, and error types. This will help ensure that serialization and deserialization processes are functioning correctly.
packages/rs-sdk/src/mock/sdk.rs (2)
387-387
: Typo in documentation: "Conveniance" should be "Convenience"
There's a typo in the documentation comment on line 387. The word "Conveniance" should be "Convenience".
435-435
: Typo in documentation: "upstreeam" should be "upstream"
There's a typo in the documentation comment on line 435. "upstreeam" should be corrected to "upstream".
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
Cargo.lock
is excluded by!**/*.lock
📒 Files selected for processing (30)
- packages/dapi-grpc/src/mock.rs (3 hunks)
- packages/rs-dapi-client/Cargo.toml (1 hunks)
- packages/rs-dapi-client/src/address_list.rs (2 hunks)
- packages/rs-dapi-client/src/executor.rs (4 hunks)
- packages/rs-dapi-client/src/lib.rs (1 hunks)
- packages/rs-dapi-client/src/mock.rs (1 hunks)
- packages/rs-dapi-client/src/request_settings.rs (3 hunks)
- packages/rs-drive-proof-verifier/src/error.rs (2 hunks)
- packages/rs-platform-version/src/error.rs (1 hunks)
- packages/rs-sdk/Cargo.toml (1 hunks)
- packages/rs-sdk/src/core/transaction.rs (3 hunks)
- packages/rs-sdk/src/error.rs (2 hunks)
- packages/rs-sdk/src/mock/requests.rs (4 hunks)
- packages/rs-sdk/src/mock/sdk.rs (6 hunks)
- packages/rs-sdk/src/platform/fetch.rs (4 hunks)
- packages/rs-sdk/src/platform/fetch_many.rs (4 hunks)
- packages/rs-sdk/src/platform/fetch_unproved.rs (2 hunks)
- packages/rs-sdk/src/platform/transition/broadcast.rs (3 hunks)
- packages/rs-sdk/src/platform/transition/purchase_document.rs (3 hunks)
- packages/rs-sdk/src/platform/transition/put_contract.rs (3 hunks)
- packages/rs-sdk/src/platform/transition/put_document.rs (3 hunks)
- packages/rs-sdk/src/platform/transition/put_identity.rs (4 hunks)
- packages/rs-sdk/src/platform/transition/top_up_identity.rs (2 hunks)
- packages/rs-sdk/src/platform/transition/transfer_document.rs (3 hunks)
- packages/rs-sdk/src/platform/transition/update_price_of_document.rs (3 hunks)
- packages/rs-sdk/src/platform/transition/vote.rs (4 hunks)
- packages/rs-sdk/src/sdk.rs (4 hunks)
- packages/rs-sdk/src/sync.rs (3 hunks)
- packages/rs-sdk/tests/fetch/epoch.rs (2 hunks)
- packages/rs-sdk/tests/fetch/mock_fetch.rs (3 hunks)
🧰 Additional context used
📓 Learnings (1)
packages/rs-sdk/src/mock/sdk.rs (1)
Learnt from: lklimek
PR: dashpay/platform#2232
File: packages/rs-sdk/src/mock/sdk.rs:90-95
Timestamp: 2024-10-10T10:30:19.883Z
Learning: In `packages/rs-sdk/src/mock/sdk.rs`, the `load_expectations` method in `MockDashPlatformSdk` remains asynchronous (`async`) for backward compatibility, even though it now delegates to the synchronous `load_expectations_sync` method.
🔇 Additional comments (55)
packages/rs-platform-version/src/error.rs (1)
3-3
: LGTM! Adding serialization support enhances error handling capabilities.
The addition of bincode::Encode
and bincode::Decode
traits aligns well with the PR's objective to improve error handling in mock scenarios. This change enables proper serialization of errors, which is essential for testing and error simulation.
Let's verify if other error types in the codebase follow similar patterns:
✅ Verification successful
Inconsistent error serialization patterns across the codebase
Based on the search results, most error types in the codebase only derive Error
and Debug
, while some derive additional traits for specific purposes. Here's what we found:
- Most errors only derive
Error
andDebug
- Some errors derive additional traits for specific features:
rs-drive-proof-verifier
: Uses conditionalbincode
serialization withcfg_attr
rs-dapi-client
: Uses conditionalserde
serializationrs-dpp/consensus
: Uses bothbincode
andserde
serialization
The addition of bincode::Encode
and bincode::Decode
to PlatformVersionError
seems to be part of a targeted enhancement for SDK mocking capabilities, rather than a general pattern that needs to be applied across all error types. The serialization traits are only added where specifically needed for cross-boundary communication or testing purposes.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistency in error type implementations
# Look for other error types and their derive attributes to ensure consistent serialization support
# Search for error types in the codebase
rg -A 1 "#\[derive.*Error.*\]" --type rust
Length of output: 16155
packages/rs-dapi-client/Cargo.toml (1)
22-22
: Verify the tokio-sleep feature usage across the codebase.
The addition of the tokio-sleep
feature to backon
suggests this crate is being used for async retry operations. Let's verify its usage to ensure it's properly integrated.
✅ Verification successful
Let me gather more information about the specific usage of backon in the dapi_client.rs file since it shows the retry implementation.
Based on the gathered information, I can now provide the final response:
The tokio-sleep feature for backon is correctly integrated and necessary
The codebase shows proper usage of backon's async retry capabilities:
- The retry mechanism is implemented in
dapi_client.rs
usingbackon::Retryable
- It uses async retry operations with proper notification callbacks
- The implementation aligns with tokio's async runtime as evidenced by the
async_trait
usage
Since the feature is actively used in the core retry mechanism, its addition to the dependencies is correct and justified.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check how backon is used with tokio-sleep feature
# Expected: Find retry implementations using backon's async capabilities
# Search for backon usage in retry contexts
rg -l 'use.*backon' packages/rs-dapi-client/src/
# Search for retry policy configurations
rg 'backoff|retry|ExponentialBackoff' packages/rs-dapi-client/src/
Length of output: 2029
Script:
#!/bin/bash
# Check the specific implementation of retry logic in dapi_client.rs
rg -A 10 'use.*backon' packages/rs-dapi-client/src/dapi_client.rs
# Look for tokio-related imports and async retry usage
rg -B 2 -A 5 'retry\(retry_settings\)' packages/rs-dapi-client/src/dapi_client.rs
Length of output: 869
packages/rs-sdk/src/platform/transition/broadcast.rs (2)
10-10
: LGTM: Import changes align with new error handling approach
The addition of IntoInner
trait import supports the simplified error handling pattern used throughout the changes.
Line range hint 43-74
: Verify state transition execution and proof verification
The state transition execution and proof verification logic looks correct, but let's verify the usage of this component across the codebase to ensure consistent error handling.
✅ Verification successful
Based on the shell script results, I can now generate the final response:
State transition verification is consistently implemented across the codebase
The verification pattern is uniformly applied across all state transition implementations:
- All modules use the same
verify_state_transition_was_executed_with_proof
method with identical parameter ordering - Error handling with
into_inner()?
is consistently used for response unwrapping - Block info extraction and proof verification follow the same pattern in all transition types
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent error handling patterns in state transition verification
# Test 1: Look for other instances of state transition verification
echo "Checking for state transition verification patterns..."
rg -A 5 "verify_state_transition_was_executed_with_proof"
# Test 2: Check for consistent error handling with into_inner
echo "Checking for consistent error handling patterns..."
rg -A 2 "into_inner\(\)\?" "packages/rs-sdk/src/platform/"
Length of output: 16231
packages/rs-dapi-client/src/lib.rs (2)
24-26
: Verify usage of new traits across the codebase.
Since this is a breaking change that modifies the public API, we should verify that all necessary implementations and usages are properly updated.
24-26
: Verify the new trait exports are properly documented.
The addition of InnerInto
and IntoInner
traits to the public API is aligned with the PR's objective of enhancing error handling. However, since this is a breaking change, proper documentation is crucial.
Let's verify the trait documentation:
Consider adding rustdoc comments for these traits in the source file to help users understand:
- Their purpose in error handling
- How they should be implemented
- Example usage in mock scenarios
packages/rs-sdk/src/platform/transition/top_up_identity.rs (2)
14-14
: LGTM: Import of IntoInner trait
The addition of IntoInner
aligns with the PR's objective to improve error handling across the SDK.
50-51
: Enhance the TODO comment with specific requirements
The TODO comment about handling execution errors is too vague. Please elaborate on:
- What specific execution errors need better handling
- What improvements are needed
- Any specific error cases that need special treatment
Let's check for similar patterns in other files:
packages/rs-drive-proof-verifier/src/error.rs (1)
5-6
: LGTM! Well-structured error handling.
The addition of bincode serialization support for mocking while maintaining good error handling practices (thiserror, descriptive messages) is a solid approach.
packages/rs-dapi-client/src/request_settings.rs (2)
5-5
: LGTM: Import statement is correctly placed and necessary.
The import of TransportRequest
is required for the new from_settings
method.
93-102
: LGTM: Implementation correctly combines settings from multiple sources.
The method properly follows the override chain: default → global → transport → request-specific.
Let's verify that all implementations of TransportRequest have valid SETTINGS_OVERRIDES:
✅ Verification successful
Implementation verified: All TransportRequest implementations have valid SETTINGS_OVERRIDES
The verification shows that:
- All implementations of TransportRequest either:
- Directly implement SETTINGS_OVERRIDES with RequestSettings::default() (e.g., in evonode.rs)
- Use a macro-based implementation that sets SETTINGS_OVERRIDES to RequestSettings::default() (via delegate.rs macro)
This confirms that the from_settings method's override chain is properly supported by all implementations.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Find all implementations of TransportRequest and their SETTINGS_OVERRIDES
ast-grep --pattern 'impl $_ for $type {
$$$
const SETTINGS_OVERRIDES: RequestSettings = $_;
$$$
}'
Length of output: 106
Script:
#!/bin/bash
# Let's try a different approach to find TransportRequest implementations
# First, find the trait definition
echo "=== TransportRequest trait definition ==="
rg "trait TransportRequest" -A 5
echo -e "\n=== Files implementing TransportRequest ==="
rg "impl.*TransportRequest.*for"
echo -e "\n=== Looking for SETTINGS_OVERRIDES constant ==="
rg "SETTINGS_OVERRIDES.*=.*RequestSettings"
Length of output: 2071
packages/rs-sdk/src/platform/transition/put_identity.rs (2)
17-17
: LGTM: Import changes align with new error handling approach
The addition of IntoInner
trait import supports the transition to a more consistent error handling pattern.
85-86
: LGTM: Consistent error handling implementation
The transition to using into_inner()
provides a more uniform approach to error handling across the codebase. The error handling for existing identities is particularly well-implemented with appropriate debug logging.
Also applies to: 109-110
packages/rs-sdk/src/error.rs (3)
8-8
: LGTM: Import addition aligns with PR objectives.
The addition of ExecutionError
to the imports is appropriate for the enhanced error handling support.
13-13
: Consider addressing the TODO in this PR.
Since this PR focuses on error handling improvements, it might be valuable to implement the server address and retry information propagation now. This would provide better debugging context for users.
Let's check if this information is available in the error types:
#!/bin/bash
# Check if server address/retry info exists in related error types
rg -A 5 "struct.*Error" packages/rs-dapi-client/src/
Would you like help implementing this enhancement?
89-97
:
Improve error conversion implementation.
The current implementation has several areas for improvement:
- Converting
ExecutionError
to a string loses valuable error context and type information. - Using
DapiClientError
variant for anExecutionError
might be misleading. - Missing documentation for the implementation.
Consider this alternative implementation:
-impl<T> From<ExecutionError<T>> for Error
-where
- ExecutionError<T>: ToString,
-{
- fn from(value: ExecutionError<T>) -> Self {
- // TODO: Improve error handling
- Self::DapiClientError(value.to_string())
- }
-}
+/// Converts execution errors into SDK errors
+impl<T> From<ExecutionError<T>> for Error
+where
+ T: Debug,
+{
+ fn from(value: ExecutionError<T>) -> Self {
+ match value {
+ ExecutionError::Protocol(e) => Error::Protocol(e),
+ ExecutionError::Client(e) => Error::DapiClientError(e.to_string()),
+ // Add specific mappings for other variants
+ e => Error::Generic(format!("Execution error: {:?}", e))
+ }
+ }
+}
This would:
- Preserve error context through specific variant mapping
- Provide better error handling granularity
- Add documentation
- Remove the temporary TODO
Let's check the structure of ExecutionError to ensure we handle all variants:
packages/rs-sdk/src/platform/transition/put_contract.rs (3)
21-21
: LGTM: Import addition aligns with new error handling pattern.
The addition of IntoInner
trait import is consistent with the PR's objective to improve error handling across the SDK.
90-91
: Consider addressing the TODO comment about execution error handling.
While the simplified error handling using into_inner()
is an improvement, the TODO comment suggests this area needs further refinement. Consider creating a more robust error handling strategy for execution errors.
Would you like me to help design a more comprehensive error handling strategy for execution errors? This could include:
- Custom error types for execution-specific failures
- Detailed error context preservation
- Proper error propagation patterns
106-108
: LGTM: Consistent error handling pattern.
The error handling using into_inner()
maintains consistency with the new pattern across the codebase.
packages/rs-sdk/tests/fetch/epoch.rs (1)
15-15
: LGTM: Import change aligns with new error handling.
The addition of IntoInner
trait import is consistent with the SDK's new error handling mechanism.
packages/rs-sdk/src/platform/transition/update_price_of_document.rs (2)
21-21
: LGTM: Import addition aligns with error handling improvements
The addition of IntoInner
trait import supports the new error handling approach using into_inner()
.
115-119
: Enhance reliability with retry logic and timeout handling
The current implementation could benefit from:
- Implementing retry logic as noted in the TODO
- Adding timeout handling to prevent indefinite waits
- Considering exponential backoff for retries
These improvements would make the implementation more robust for blockchain operations where network instability is common.
Let's verify the timeout handling in similar methods:
packages/rs-sdk/src/platform/transition/transfer_document.rs (4)
21-21
: LGTM: Import addition aligns with error handling improvements.
The addition of IntoInner
trait import supports the transition to a more streamlined error handling approach.
100-100
: LGTM: Simplified error handling approach.
The change to use into_inner()
aligns with the PR's objective to streamline error handling across the SDK.
117-118
: LGTM: Consistent error handling implementation.
The split of await
and into_inner()
into separate lines improves readability while maintaining consistent error handling patterns across the codebase.
21-21
: Verify consistent error handling across the codebase.
Let's ensure that the transition to using into_inner()
is consistently applied across related files.
Also applies to: 100-100, 117-118
✅ Verification successful
Error handling is consistently applied across the transition module
The verification shows that:
- No
map_err
usage remains in the transition module files into_inner()
is consistently used across all files in the module:- broadcast.rs
- purchase_document.rs
- put_contract.rs
- put_document.rs
- put_identity.rs
- top_up_identity.rs
- transfer_document.rs
- update_price_of_document.rs
- vote.rs
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent error handling patterns across related files
# Test 1: Look for any remaining map_err usage that might need updating
echo "Checking for remaining map_err usage in related files..."
rg "map_err" "packages/rs-sdk/src/platform/transition/"
# Test 2: Verify consistent usage of into_inner
echo "Verifying into_inner usage..."
rg "into_inner" "packages/rs-sdk/src/platform/transition/"
Length of output: 2081
packages/rs-sdk/src/platform/transition/put_document.rs (2)
20-20
: LGTM: Import of IntoInner trait aligns with error handling improvements
The addition of IntoInner
trait is consistent with the PR's objective to improve error handling across the SDK.
99-99
: Consider documenting error handling strategy
While the change to use into_inner()
simplifies the code, the TODO comment suggests this is an interim solution. Consider:
- Documenting the expected error types that can be returned
- Specifying how different error cases should be handled
Let's check for similar TODO patterns across the codebase:
✅ Verification successful
Let me check the error handling patterns in these files to better understand the context.
Let me check the error handling implementation in the codebase to better understand the context.
Based on the analysis of the codebase, I can now provide a final response:
Error handling strategy is consistent across transitions
The use of into_inner()
is part of a consistent error handling pattern across all transition modules where:
- Errors are properly propagated through the
Result
type - Domain-specific errors are mapped to the SDK's
Error
enum - Each transition follows the same pattern of handling execution errors and state transition proofs
The TODO comments about "better way to handle execution errors" appear in all transition modules and represent a planned future enhancement rather than an immediate concern.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for similar error handling TODOs
rg "TODO.*handle.*error" --type rust
Length of output: 1477
Script:
#!/bin/bash
# Check error handling patterns in the transition files
rg "into_inner|Result|Error" packages/rs-sdk/src/platform/transition/ -A 2 -B 2
Length of output: 65837
Script:
#!/bin/bash
# Check the Error type definition and implementation
rg "pub enum Error" packages/rs-sdk/src/ -A 10
Length of output: 699
packages/rs-sdk/src/platform/transition/purchase_document.rs (3)
22-22
: LGTM: Import addition aligns with error handling improvements.
The addition of IntoInner
trait import is consistent with the standardized error handling approach being implemented across the SDK.
105-105
: Consider expanding error handling strategy.
While the change to into_inner()?
aligns with the new error handling approach, the TODO comment suggests this is an interim solution. Consider:
- Documenting specific error cases that need handling
- Implementing proper error type mapping for mock scenarios
Let's check for similar patterns in other files:
Would you like assistance in designing a comprehensive error handling strategy that covers both real and mock scenarios?
119-123
: Implement retry logic with proper error handling.
The current implementation has two areas for improvement:
- The TODO about retry logic should be addressed, as state transition operations may require multiple attempts
- The error handling with
into_inner()?
should be enhanced to handle specific failure cases during retries
Consider implementing an exponential backoff strategy with proper error classification for different failure scenarios.
Let's check the codebase for existing retry implementations:
Would you like help implementing a robust retry mechanism with proper error handling for both real and mock scenarios?
✅ Verification successful
Based on the search results, I can now provide a final response regarding the retry logic implementation:
Implement retry logic using the SDK's built-in retry mechanism
The codebase already has a robust retry implementation in the rs-sdk that can be leveraged:
- Use the
retry()
function fromrs-sdk/src/sync.rs
which provides:- Configurable retry attempts via
RequestSettings
- Exponential backoff with the
backon
crate - Proper error handling with
CanRetry
trait
- Configurable retry attempts via
Example usage:
let settings = RequestSettings::default();
retry(settings, |s| async move {
request.execute(sdk, s).await
}).await
The rationale for this response:
- The codebase shows a mature retry implementation in rs-sdk that handles state transition propagation
- The implementation includes proper error classification, backoff strategy, and configurable retry attempts
- The TODO can be addressed by using the existing retry mechanism rather than implementing a new one
- This approach maintains consistency with how retries are handled across the codebase
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Look for existing retry implementations
ast-grep --pattern 'fn $retry_fn($$$) {
$$$
loop {
$$$
}
}'
Length of output: 71
Script:
#!/bin/bash
# Let's search for retry-related patterns more broadly
rg -i "retry|backoff" -A 5 -B 5
# Also search for any loop patterns in async functions that might indicate retry logic
ast-grep --pattern 'async fn $_($$$) {
$$$
while $_ {
$$$
}
$$$
}'
# Look for error handling patterns around request execution
ast-grep --pattern 'execute($$$).await$_'
Length of output: 279885
packages/rs-sdk/src/platform/transition/vote.rs (3)
20-20
: LGTM: Import of IntoInner trait
The addition of IntoInner
trait import aligns with the PR's objective to improve error handling across the SDK.
136-137
: LGTM: Consistent error handling in proof verification
The use of into_inner()
here maintains consistency with the new error handling pattern, which is particularly important in the context of blockchain state verification.
77-77
: Verify consistent error handling pattern
The change from map_err
to into_inner()
improves error handling clarity. Let's verify this pattern is consistently applied across the codebase.
✅ Verification successful
Error handling pattern is consistently applied across transitions
The verification shows that:
- No instances of
map_err
were found in the transition modules into_inner()
is consistently used across all platform transition files:- vote.rs
- update_price_of_document.rs
- top_up_identity.rs
- put_identity.rs
- put_document.rs
- put_contract.rs
- purchase_document.rs
- broadcast.rs
- transfer_document.rs
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consistent error handling pattern across the SDK
# Look for any remaining instances of map_err in platform transitions
echo "Checking for inconsistent error handling patterns..."
rg "map_err" "packages/rs-sdk/src/platform/transition/"
echo "Checking adoption of into_inner..."
rg "into_inner" "packages/rs-sdk/src/platform/transition/"
Length of output: 2083
packages/rs-dapi-client/src/address_list.rs (2)
4-4
: LGTM!
The import is correctly placed and properly scoped.
63-73
: Verify test coverage for mock serialization.
Since this implements new mock functionality, we should ensure it's properly tested.
Let's check for existing tests:
packages/rs-sdk/src/core/transaction.rs (3)
15-15
: LGTM: Import addition aligns with error handling changes.
The addition of IntoInner
trait import is consistent with the PR's objective to enhance error handling capabilities.
59-59
: LGTM: Simplified error handling using IntoInner trait.
The modification streamlines error handling while maintaining proper error type conversion to Error::DapiClientError
.
185-185
: LGTM: Simplified error handling using IntoInner trait.
The modification streamlines error handling while maintaining proper error propagation through the ?
operator.
packages/rs-sdk/src/sdk.rs (3)
140-140
: LGTM!
The new field is correctly included in the Clone implementation.
965-965
: LGTM!
The dapi_client_settings
is properly initialized from the builder settings in the non-mock SDK construction path.
1028-1028
: LGTM!
The dapi_client_settings
is properly initialized from the builder settings in the mock SDK construction path.
packages/rs-sdk/src/platform/fetch_unproved.rs (3)
4-4
: Importing sync::retry
for retry logic
The addition of sync::retry
is appropriate and necessary for implementing the retry mechanism in the fetch_unproved_with_settings
method.
12-12
: Adding imports for enhanced error handling
The inclusion of ExecutionError
, ExecutionResponse
, InnerInto
, and IntoInner
is essential for the improved error handling and response processing. This aligns with the refactored code's requirements.
75-110
: Refactored fetch_unproved_with_settings
method enhances robustness
The method has been effectively refactored to incorporate a closure that enhances error handling and introduces a retry mechanism. The use of ExecutionResponse
and proper error mapping improves the maintainability and reliability of the code.
packages/rs-sdk/src/platform/fetch.rs (4)
124-126
: Refactor promotes code reusability in fetch_with_metadata
By delegating fetch_with_metadata
to fetch_with_metadata_and_proof
, the code adheres to the DRY (Don't Repeat Yourself) principle, enhancing maintainability and reducing potential duplication.
158-192
: Introduction of fetch_with_metadata_and_proof
enhances API flexibility
The new fetch_with_metadata_and_proof
method provides additional functionality by exposing the underlying proof, which can be valuable for debugging and advanced use cases. The implementation includes proper error handling and integrates retry logic effectively.
177-181
: Consistent error mapping enhances error context
Mapping errors into ExecutionError
with inner
, address
, and retries
fields ensures that detailed error information is preserved, aiding in troubleshooting and providing richer context for failure scenarios.
198-198
: Effective use of retry mechanism with retry
function
The application of the retry
function with the specified settings, followed by .await.into_inner()
, correctly implements the retry logic, improving the robustness of network requests and handling transient failures gracefully.
packages/rs-dapi-client/src/mock.rs (1)
326-333
:
Consider handling deserialization errors without panicking
In the mock_deserialize
method for ExecutionError<E>
, the code panics if the expected number of elements is not met. To enhance test robustness and error handling, consider returning a Result<Self, Error>
instead of panicking.
Modify the method as follows:
- let [inner, address, retries] = &deser[0..] else {
- // panics intentionally, as this is just for mocking, and we know these types can be mocked because they were
- // serialized before
- panic!(
- "invalid ExecutionError data: expected 3 elements, got {}",
- deser.len()
- );
- };
+ if deser.len() != 3 {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ format!("invalid ExecutionError data: expected 3 elements, got {}", deser.len()),
+ ));
+ }
+ let inner = &deser[0];
+ let address = &deser[1];
+ let retries = &deser[2];
Likely invalid or redundant comment.
packages/rs-sdk/src/sync.rs (3)
7-14
: Necessary imports added for new functionality
The imports introduced are appropriate and necessary for the implementation of the retry
function and its associated logic.
97-156
: Well-documented retry
function
The added documentation for the retry
function is comprehensive and provides clear guidance on its usage, parameters, and examples. This will be very helpful for developers utilizing this function.
196-215
:
Verify the correctness of retry limit calculation
In the when
closure of the retry logic, the condition for continuing retries is:
if all_requests_sent <= max_retries {
// Retry logic
} else {
// Give up
}
Ensure that all_requests_sent
accurately represents the total number of requests sent and that the comparison with max_retries
correctly enforces the maximum number of retries specified. There may be an off-by-one error, as all_requests_sent
includes the initial request, so using < max_retries
might be more appropriate to prevent exceeding the maximum retries.
Consider adjusting the condition to:
- if all_requests_sent <= max_retries {
+ if all_requests_sent < max_retries {
This change ensures that the total number of retries does not exceed max_retries
.
packages/rs-sdk/src/platform/fetch_many.rs (1)
160-161
: Avoid logging sensitive data in debug traces.
Logging the entire request
and response
objects may expose sensitive information. Consider logging only the necessary details or sanitizing the data before logging to prevent potential security risks.
[security]
Apply this diff to limit logged information:
-tracing::trace!(request = ?request, response = ?response, ?address, retries, object_type, "fetched object from platform");
+tracing::trace!(?address, retries, object_type, "fetched object from platform");
Alternatively, ensure that logging of sensitive data is acceptable and complies with security policies.
packages/rs-sdk/src/mock/sdk.rs (1)
Line range hint 341-488
: Enhancements align with PR objectives and improve mocking capabilities
The added methods expect_from_proof_with_metadata
, expect_from_proof
, and expect_dapi
enhance the mocking capabilities of the SDK by allowing for more comprehensive error handling and flexibility in setting expectations. These changes align with the PR objectives and improve the usability of the SDK for developers requiring error simulation in tests.
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 (7)
packages/rs-dapi-client/src/dapi_client.rs (2)
Line range hint 24-39
: Document the breaking change in the Mock variant.
The implementation of the new Mock variant looks good, but since this is a breaking change as mentioned in the PR description, it should be properly documented.
Consider adding documentation to explain:
- When this error variant occurs
- How it affects existing code
- Migration steps for users
Example documentation:
/// Error happened in mock client
///
/// This variant is only available with the "mocks" feature flag.
/// It represents errors that occur during mock operations, such as
/// serialization failures or mock expectation mismatches.
#[cfg(feature = "mocks")]
#[error("mock error: {0}")]
Mock(#[from] crate::mock::MockError),
Also applies to: 44-54
🧰 Tools
🪛 GitHub Check: Rust packages (dash-sdk) / Linting
[warning] 15-15: unused import: crate::Address
warning: unused import: crate::Address
--> packages/rs-dapi-client/src/dapi_client.rs:15:5
|
15 | use crate::Address;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)]
on by default
Line range hint 57-71
: Improve error handling in mock serialization.
The current implementation uses .expect()
which can panic. Consider returning None
on serialization failures instead, as this better aligns with the Option
return type.
Apply this diff to improve error handling:
impl Mockable for DapiClientError {
#[cfg(feature = "mocks")]
fn mock_serialize(&self) -> Option<Vec<u8>> {
- Some(serde_json::to_vec(self).expect("serialize DAPI client error"))
+ serde_json::to_vec(self).ok()
}
#[cfg(feature = "mocks")]
fn mock_deserialize(data: &[u8]) -> Option<Self> {
- Some(serde_json::from_slice(data).expect("deserialize DAPI client error"))
+ serde_json::from_slice(data).ok()
}
}
🧰 Tools
🪛 GitHub Check: Rust packages (dash-sdk) / Linting
[warning] 15-15: unused import: crate::Address
warning: unused import: crate::Address
--> packages/rs-dapi-client/src/dapi_client.rs:15:5
|
15 | use crate::Address;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)]
on by default
packages/rs-dapi-client/src/mock.rs (4)
260-261
: Fix typo in comment
The comment contains a typo: "od" should be "of".
-- We encode data as vec![inner, address, retries] where each od them is serialized to bytes
++ We encode data as vec![inner, address, retries] where each of them is serialized to bytes
262-271
: Improve error messages in expect calls
The error messages in .expect()
calls could be more descriptive by including the actual values that failed to serialize.
- .expect("unable to serialize ExecutionResponse inner"),
+ .expect("unable to serialize ExecutionResponse inner value"),
- .expect("unable to serialize ExecutionResponse address"),
+ .expect("unable to serialize ExecutionResponse address value"),
- .expect("unable to serialize ExecutionResponse retries"),
+ .expect("unable to serialize ExecutionResponse retries value"),
302-303
: Fix typo in comment
The comment contains a typo: "od" should be "of".
-- We encode data as vec![inner, address, retries] where each od them is serialized to bytes
++ We encode data as vec![inner, address, retries] where each of them is serialized to bytes
260-336
: Consider using a type-safe serialization format
The current implementation uses raw byte vectors for serialization, which is error-prone and relies on panic for error handling. Consider:
- Using a structured format like
serde_json
orbincode
with proper type definitions. - Creating a dedicated error type for serialization failures.
This would improve type safety and error handling while making the code more maintainable.
packages/rs-drive-proof-verifier/src/types.rs (1)
Line range hint 667-679
: Clarify the conversion logic in ProposerBlockCounts
The FromIterator
implementation for ProposerBlockCounts
contains a comment indicating that the conversion logic may need adjustment:
let identifier = Identifier::from(pro_tx_hash.to_byte_array()); // Adjust this conversion logic as needed
Please verify that converting ProTxHash
to Identifier
using to_byte_array()
is the intended approach. If this is a placeholder, consider refining the conversion logic to ensure it accurately represents the proposer's identity. Do you need assistance in updating this implementation?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (11)
- packages/dapi-grpc/src/mock.rs (4 hunks)
- packages/rs-dapi-client/src/dapi_client.rs (1 hunks)
- packages/rs-dapi-client/src/executor.rs (2 hunks)
- packages/rs-dapi-client/src/mock.rs (1 hunks)
- packages/rs-drive-proof-verifier/Cargo.toml (2 hunks)
- packages/rs-drive-proof-verifier/src/provider.rs (1 hunks)
- packages/rs-drive-proof-verifier/src/types.rs (2 hunks)
- packages/rs-sdk/Cargo.toml (2 hunks)
- packages/rs-sdk/src/platform/transition/put_identity.rs (1 hunks)
- packages/rs-sdk/src/sdk.rs (2 hunks)
- packages/rs-sdk/tests/fetch/mock_fetch.rs (3 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/rs-drive-proof-verifier/src/provider.rs
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/dapi-grpc/src/mock.rs
- packages/rs-sdk/Cargo.toml
- packages/rs-sdk/src/platform/transition/put_identity.rs
- packages/rs-sdk/src/sdk.rs
- packages/rs-sdk/tests/fetch/mock_fetch.rs
🧰 Additional context used
🪛 GitHub Check: Rust packages (dash-sdk) / Linting
packages/rs-dapi-client/src/dapi_client.rs
[warning] 15-15: unused import: crate::Address
warning: unused import: crate::Address
--> packages/rs-dapi-client/src/dapi_client.rs:15:5
|
15 | use crate::Address;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)]
on by default
🔇 Additional comments (9)
packages/rs-drive-proof-verifier/Cargo.toml (1)
14-14
: LGTM: Correct specification of bincode serde feature.
The change from dep:bincode
to bincode/serde
properly specifies that we need the serde feature of bincode for mocking capabilities.
packages/rs-dapi-client/src/executor.rs (5)
Line range hint 19-34
: LGTM: Well-designed conversion traits
The new traits IntoInner<T>
and InnerInto<T>
follow Rust's conversion trait patterns well, providing a clear distinction between lossy (IntoInner
) and lossless (InnerInto
) conversions.
Line range hint 37-80
: LGTM: Robust error handling with proper context preservation
The ExecutionError<E>
implementation correctly:
- Adds serialization support for mocks
- Preserves context (retries and address) during conversions
- Maintains error retry behavior
Line range hint 81-120
: LGTM: Response handling with proper serialization support
The ExecutionResponse<R>
implementation correctly adds serialization support for mocks while maintaining consistency with ExecutionError<E>
.
Line range hint 122-155
: LGTM: Well-implemented Result conversions
The ExecutionResult
implementations correctly:
- Handle both success and error cases
- Preserve type safety through appropriate constraints
- Follow Rust's Result handling patterns
Line range hint 1-155
: Verify breaking changes impact
Since this PR introduces breaking changes to the mock API, let's verify that all consumers are properly updated.
✅ Verification successful
Let me analyze the results and generate a final response based on the findings.
Breaking changes are properly handled
The search results show that the mock serialization changes in ExecutionError
, ExecutionResponse
, and ExecutionResult
are properly implemented across the codebase:
- The types are used consistently with their mock implementations
- All consumers properly handle the serialization through the
Mockable
trait - The changes are contained within the rs-dapi-client crate and its test code
- Other crates using these types (like rs-sdk) only use them as generic type parameters with proper trait bounds
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Find all usages of ExecutionError, ExecutionResponse, and ExecutionResult
# to ensure they're compatible with the breaking changes
echo "Searching for direct usages of affected types..."
rg -t rust "ExecutionError|ExecutionResponse|ExecutionResult" --glob '!packages/rs-dapi-client/src/executor.rs'
echo "Searching for mock implementations that might need updates..."
rg -t rust "impl.*Mockable" --glob '!packages/rs-dapi-client/src/executor.rs'
Length of output: 146823
packages/rs-dapi-client/src/dapi_client.rs (1)
Line range hint 24-71
: Verify test coverage for mock error scenarios.
The changes look good overall, but since this introduces breaking changes in mock support, we should ensure comprehensive test coverage.
Let's verify the test coverage:
✅ Verification successful
Mock error handling is properly tested and implemented
The implementation of mock error support is well-tested with:
- Comprehensive test coverage in
mock_dapi_client.rs
that verifies the mock client functionality - Proper feature flag handling with
#[cfg(feature = "mocks")]
- Error propagation through
DapiClientError::Mock
variant - Implementation of
Mockable
trait for error serialization
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check test coverage for mock error scenarios
# Look for test files that might need updates
echo "Searching for affected test files..."
fd -e rs test mock
# Look for existing mock error tests
echo "Checking for mock error test coverage..."
rg -l "Mock\(" $(fd -e rs test)
# Look for potential usage of old mock API that needs updating
echo "Checking for potential breaking changes..."
rg -l "mock_serialize|mock_deserialize" $(fd -e rs test)
Length of output: 4994
Script:
#!/bin/bash
# Let's try a more focused search for mock-related tests in the dapi client
# Look for test modules in the dapi client
echo "Searching for test modules in dapi client..."
fd -e rs . packages/rs-dapi-client | grep -i "test"
# Look for mock-related code in dapi client
echo "Checking mock implementations..."
rg -l "feature.*mocks" packages/rs-dapi-client
# Check test coverage specifically for DapiClientError
echo "Checking DapiClientError test coverage..."
rg -C 5 "DapiClientError" packages/rs-dapi-client
Length of output: 16163
Script:
#!/bin/bash
# Let's check the mock test implementation to verify coverage
# Check mock test implementation
echo "Checking mock test implementation..."
cat packages/rs-dapi-client/tests/mock_dapi_client.rs
# Look for any other test files that might use mocks
echo "Checking other test files for mock usage..."
rg -C 5 "Mock" packages/rs-dapi-client/tests/local_platform_connectivity.rs
Length of output: 1843
🧰 Tools
🪛 GitHub Check: Rust packages (dash-sdk) / Linting
[warning] 15-15: unused import: crate::Address
warning: unused import: crate::Address
--> packages/rs-dapi-client/src/dapi_client.rs:15:5
|
15 | use crate::Address;
| ^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)]
on by default
packages/rs-dapi-client/src/mock.rs (2)
Line range hint 339-374
: LGTM! Well-documented trait implementation
The FromInner
trait and its implementation for ExecutionResponse<R>
are well-documented and appropriately implemented. The documentation clearly indicates this is for test scenarios and marks the conversion as imprecise.
280-287
:
Consider using Result instead of panic
The deserialization method panics when the input data is invalid. Since this is used in tests, returning a Result
would provide better error handling and test diagnostics.
@@ -31,7 +31,7 @@ dpp = { path = "../rs-dpp", features = [ | |||
"extended-document", | |||
"core-types-serialization", | |||
], default-features = false } | |||
bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } | |||
bincode = { version = "2.0.0-rc.3", optional = false } |
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.
Review bincode dependency configuration.
Setting optional = false
for bincode while it's under the mocks
feature seems inconsistent. This could cause bincode to be always included in the binary even when the mocks
feature is disabled.
Consider this fix to maintain consistency:
-bincode = { version = "2.0.0-rc.3", optional = false }
+bincode = { version = "2.0.0-rc.3", optional = true }
Committable suggestion was skipped due to low confidence.
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.
optional = false
sounds a bit strange
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.
@shumkov, you're correct. Setting optional = false
here can cause bincode
to be included in the binary even when the mocks
feature is disabled. Changing it to optional = true
ensures that bincode
is only included when the mocks
feature is enabled, maintaining consistency.
(^‿^)/
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.
Removed optional
, as it's in use even without mocks
feature.
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.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (2)
packages/rs-sdk/tests/fetch/data_contract.rs (1)
Based on the analysis of the codebase, I can now provide the final response:
Error scenario tests needed for data contract history fetch
The current test suite lacks error scenario coverage for DataContractHistory::fetch
. While there are mock capabilities available (as seen in mock/
directory) and error handling for mocks (via DapiMocksError
), the current test only covers the success path. Add tests for:
- Network errors using
DapiMocksError
- Invalid contract ID scenarios (already tested for single fetch but not for history)
- Rate limiting scenarios
- Malformed history responses
Example locations needing tests:
packages/rs-sdk/tests/fetch/data_contract.rs
: Add new test cases alongsidetest_data_contract_history_read
🔗 Analysis chain
Line range hint 134-157
: Consider adding error scenario tests.
Given that this PR adds support for mocking errors, this test should be enhanced to verify error handling scenarios. For example:
- Network errors during fetching
- Invalid/malformed history responses
- Rate limiting scenarios
Let's check if there are any existing error scenario tests:
Would you like me to help generate additional test cases for these error scenarios using the new mocking capabilities?
Let me check the content of these files to see if they cover error scenarios for data contracts specifically.
Let me check if there are any mock implementations available that could be used for error testing.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for error-related test cases in data contract tests
rg -l "test.*error|error.*test" --type rust packages/rs-sdk/tests/
Length of output: 214
Script:
#!/bin/bash
# Check content of error-related tests in these files
echo "=== fetch/mod.rs ==="
rg "test.*error|error.*test" -B2 -A5 packages/rs-sdk/tests/fetch/mod.rs
echo -e "\n=== fetch/contested_resource.rs ==="
rg "test.*error|error.*test" -B2 -A5 packages/rs-sdk/tests/fetch/contested_resource.rs
echo -e "\n=== fetch/contested_resource_vote_state.rs ==="
rg "test.*error|error.*test" -B2 -A5 packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs
# Also check if there are any error handling tests in data_contract.rs that our pattern might have missed
echo -e "\n=== fetch/data_contract.rs ==="
rg "test.*" -B2 -A5 packages/rs-sdk/tests/fetch/data_contract.rs
Length of output: 10308
Script:
#!/bin/bash
# Check for mock implementations
echo "=== Checking mock implementations ==="
rg -l "mock" packages/rs-sdk/src/
# Check the specific mock implementations
echo -e "\n=== Checking mock content ==="
rg "mock.*error|error.*mock" -B2 -A5 packages/rs-sdk/src/
Length of output: 1628
packages/rs-sdk/tests/fetch/config.rs (1)
25-30
: Enhance documentation for test vector constants.
While the comment indicates these values change with test vector regeneration, additional documentation would be valuable:
- Document what each constant represents (e.g., what kind of identity, what type of contract)
- Document the process or conditions that require updating these values
- Consider adding a TODO to automate test vector generation to avoid manual updates
Add detailed documentation above each constant:
// Variables that change every time we regenerate test vectors
+
+/// Base58-encoded Identity ID used for testing.
+/// This value must be updated when:
+/// 1. Test vectors are regenerated
+/// 2. The test identity is recreated
const DEFAULT_IDENTITY_ID_BASE58: &str = "9diBT6EQt3BfX5aMm9ryfEDQ4FAdMEWjGWwvM1Wciqei";
+
+/// Hex-encoded ProTxHash of an existing masternode used for testing.
+/// This value must be updated when:
+/// 1. Test vectors are regenerated
+/// 2. The test masternode changes
const DEFAULT_PROTXHASH_HEX: &str =
"069dcb6e829988af0edb245f30d3b1297a47081854a78c3cdea9fddb8fbd07eb";
+
+/// Hex-encoded ID of a data contract with history used for testing.
+/// This value must be updated when:
+/// 1. Test vectors are regenerated
+/// 2. The test contract is redeployed
pub(crate) const DEFAULT_DATA_CONTRACT_WITH_HISTORY_HEX: &str =
"3013742faada429308e22a83c72e19310b3dc93db1ceefda78fc2e8965b0805a";
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
- packages/rs-dapi-client/src/dapi_client.rs (1 hunks)
- packages/rs-sdk/tests/fetch/config.rs (3 hunks)
- packages/rs-sdk/tests/fetch/data_contract.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/rs-dapi-client/src/dapi_client.rs
🔇 Additional comments (1)
packages/rs-sdk/tests/fetch/data_contract.rs (1)
138-138
: LGTM! Good refactoring to use the constant.
The change improves maintainability by using DEFAULT_DATA_CONTRACT_WITH_HISTORY_HEX
constant instead of a hardcoded string.
@@ -257,32 +257,83 @@ impl Expectations { | |||
|
|||
impl<R: Mockable> Mockable for ExecutionResponse<R> { |
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.
We need to decided, either we keep mockable implementation in their modules, like address, or in mock, like execution types. I would say they should be in their modules otherwise the mock module will be a mess eventually.
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.
To be refactored in separate PR.
/// | ||
/// * `global_settings` - global settings for all requests. | ||
/// * `request_settings` - settings for a specific request. | ||
pub fn from_settings<R: TransportRequest>( |
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.
From<(&RequestSettings, &RequestSettings)>
? ))
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.
Function is not used, removed.
@@ -31,7 +31,7 @@ dpp = { path = "../rs-dpp", features = [ | |||
"extended-document", | |||
"core-types-serialization", | |||
], default-features = false } | |||
bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } | |||
bincode = { version = "2.0.0-rc.3", optional = false } |
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.
optional = false
sounds a bit strange
@@ -2,6 +2,7 @@ use dpp::ProtocolError; | |||
|
|||
/// Errors | |||
#[derive(Debug, thiserror::Error)] | |||
#[cfg_attr(feature = "mocks", derive(bincode::Encode, bincode::Decode))] |
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.
We use serde in dapi client
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.
It's all under mocks
feature atm, we should introduce separate serde
feature. TBD in next PR.
@@ -1,6 +1,6 @@ | |||
use thiserror::Error; | |||
|
|||
#[derive(Error, Debug)] | |||
#[derive(Error, Debug, bincode::Encode, bincode::Decode)] |
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.
I'm not sure about this
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.
Maybe refactor into serde in next PR? With serde feature?
@@ -22,6 +22,12 @@ const DPNS_DASH_TLD_DOCUMENT_ID: [u8; 32] = [ | |||
68, 209, 224, 212, 242, 106, 141, 142, 255, 55, 207, | |||
]; | |||
|
|||
// Variables that change every time we regenerate test vectors |
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.
is it possible to get it from env? we could pass masternode identity then
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.
It is read from env. However, for offline testing, we don't have the env, so we must hardcode defaults each time we generate test vectors.
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 (7)
packages/rs-sdk/tests/fetch/mock_fetch.rs (1)
169-170
: Simplify comments for better readability.
The comments could be more concise while maintaining clarity.
- // On DAPI level, we mock some response that will indicate to the SDK that the node is behind and we should retry
- // First, we return height 10 to indicate current tip
+ // Mock response for current node (height 10)
packages/rs-sdk/src/core/transaction.rs (2)
21-21
: Consider tracking the TODO in a GitHub issue.
The TODO comment indicates a planned refactor to return ExecutionResult
. This aligns with the effort to standardize error handling across the codebase. Consider creating a GitHub issue to track this technical debt.
Would you like me to help create a GitHub issue to track this refactoring task?
65-65
: Consider comprehensive error handling improvements.
The TODOs indicate two areas for improvement:
- Refactoring to use
ExecutionResult
for standardized error handling - Adding retry logic for stream message errors
These improvements would enhance reliability and maintain consistency with the codebase's error handling patterns.
Consider:
- Implementing a retry mechanism with backoff for transient stream errors
- Standardizing error handling using
ExecutionResult
- Creating a GitHub issue to track these improvements comprehensively
Would you like me to help outline a detailed implementation plan for these improvements?
Also applies to: 84-84
packages/rs-sdk/src/platform/document_query.rs (1)
Line range hint 290-290
: Remove outdated TODO comment.
The TODO comment about implementing where and order_by clause can be removed as these features are already implemented in the TryFrom<DocumentQuery>
implementation below.
packages/rs-sdk/src/mock/requests.rs (2)
158-212
: Add documentation for tuple serialization format.
While the implementation is correct, it would be helpful to add documentation explaining the serialization format for tuples. This helps maintainers understand how the data is structured in the byte array.
Add documentation like this:
impl<T, U> MockResponse for (T, U)
where
T: MockResponse,
U: MockResponse,
{
+ /// Serializes a 2-tuple by first serializing each component separately
+ /// and then combining them into a single byte vector using bincode.
+ /// The resulting format is: (bytes_of_T, bytes_of_U)
fn mock_serialize(&self, mock_sdk: &MockDashPlatformSdk) -> Vec<u8> {
229-257
: Address TODO for full Status serialization.
The current implementation only serializes the code and message, but there's a TODO indicating that full serialization should be implemented.
Would you like me to help implement full serialization for the Status type or create a GitHub issue to track this task?
packages/rs-sdk/src/mock/sdk.rs (1)
484-486
: Consider enhancing error messages
The error handling in expect_dapi
could be more specific by wrapping the error from guard.expect()
with additional context about the request type.
- guard.expect(request, result)?;
+ guard.expect(request, result).map_err(|e| Error::Config(
+ format!("Failed to set expectation for {}: {}",
+ std::any::type_name::<R>(), e)
+ ))?;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (10)
- packages/rs-dapi-client/src/executor.rs (4 hunks)
- packages/rs-drive-proof-verifier/Cargo.toml (2 hunks)
- packages/rs-sdk/Cargo.toml (2 hunks)
- packages/rs-sdk/src/core/transaction.rs (2 hunks)
- packages/rs-sdk/src/mock/requests.rs (4 hunks)
- packages/rs-sdk/src/mock/sdk.rs (7 hunks)
- packages/rs-sdk/src/platform/document_query.rs (1 hunks)
- packages/rs-sdk/src/platform/fetch_many.rs (1 hunks)
- packages/rs-sdk/src/sync.rs (1 hunks)
- packages/rs-sdk/tests/fetch/mock_fetch.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/rs-dapi-client/src/executor.rs
- packages/rs-drive-proof-verifier/Cargo.toml
- packages/rs-sdk/Cargo.toml
🧰 Additional context used
📓 Learnings (2)
packages/rs-sdk/src/mock/sdk.rs (1)
Learnt from: lklimek
PR: dashpay/platform#2232
File: packages/rs-sdk/src/mock/sdk.rs:90-95
Timestamp: 2024-10-10T10:30:19.883Z
Learning: In `packages/rs-sdk/src/mock/sdk.rs`, the `load_expectations` method in `MockDashPlatformSdk` remains asynchronous (`async`) for backward compatibility, even though it now delegates to the synchronous `load_expectations_sync` method.
packages/rs-sdk/tests/fetch/mock_fetch.rs (1)
Learnt from: lklimek
PR: dashpay/platform#2277
File: packages/rs-sdk/tests/fetch/mock_fetch.rs:159-159
Timestamp: 2024-10-30T11:04:54.154Z
Learning: In Rust tests, only include `setup_logs()` when logging is necessary; there's no need to add it to every test.
🔇 Additional comments (12)
packages/rs-sdk/tests/fetch/mock_fetch.rs (2)
Line range hint 3-25
: LGTM!
The imports are well-organized and all are utilized in the new test implementation.
157-246
: LGTM! Well-structured test for stale node handling.
The test effectively verifies the SDK's behavior when encountering nodes with different heights. The mock setup is comprehensive, covering both success and failure scenarios.
packages/rs-sdk/src/sync.rs (1)
332-334
: LGTM! Improved retry calculation logic
The implementation now uses min
function to calculate retries, which is more idiomatic and clearer than the previous if-else logic. This change maintains correct behavior while improving code readability.
packages/rs-sdk/src/mock/requests.rs (1)
143-156
: LGTM! Implementation follows best practices.
The MockResponse
implementation for ResponseMetadata
correctly uses the predefined BINCODE_CONFIG
and includes appropriate error messages in .expect()
calls.
packages/rs-sdk/src/platform/fetch_many.rs (1)
255-268
: LGTM! Variable renaming improves consistency.
The renaming of document_query
to request
aligns with the pattern used in other FetchMany
implementations, making the code more consistent and easier to understand. The error handling and logging remain robust.
packages/rs-sdk/src/mock/sdk.rs (7)
21-31
: LGTM: Import changes are well-organized
The new imports support the enhanced error handling capabilities and are properly organized.
279-279
: LGTM: Consistent parameter passing
The change to pass grpc_request
by reference aligns with the previous review feedback and maintains consistency across the codebase.
Also applies to: 336-336
Line range hint 355-383
: LGTM: Enhanced error handling in mock expectations
The updated signature of expect_from_proof_with_metadata
now properly supports error cases through the Result type, improving the robustness of the mocking system.
385-400
: LGTM: Well-implemented convenience wrapper
The expect_from_proof
method provides a clean interface for simple cases while maintaining full functionality through proper delegation to expect_from_proof_with_metadata
.
476-488
: LGTM: Well-implemented DAPI expectations
The new expect_dapi
method:
- Is properly documented
- Correctly handles concurrent access through mutex
- Has appropriate trait bounds for type safety
355-358
: Verify impact of breaking changes
The signature changes in expect_from_proof_with_metadata
and expect
methods are breaking changes. Ensure that:
- All callers are updated to pass references
- All implementations handle the new Result type
#!/bin/bash
# Search for existing calls to these methods
ast-grep --pattern 'expect_from_proof_with_metadata($_, $_)'
ast-grep --pattern 'expect($_, $_)'
Also applies to: 402-407
420-424
: Verify the usage of default URI in fake response
The use of Uri::default()
for the fake response address might need verification to ensure it doesn't cause issues in error scenarios or logging.
✅ Verification successful
The previous search might have failed due to special characters. Let's try a broader search to understand the usage of Uri and ExecutionResponse, particularly in test contexts where mock SDK is used.
Based on the search results, I can now provide a final response regarding the usage of Uri::default()
in the mock SDK:
Using Uri::default()
in mock response is appropriate
The usage of Uri::default()
in the mock SDK's fake response is appropriate because:
- It's used only in test scenarios within the mock SDK implementation
- The
ExecutionResponse
is properly handled in tests and mock scenarios across the codebase - The address field is primarily used for tracking which node responded in real scenarios, but in mocks, this information is not critical
- Other test files also use dummy URIs (like "http://127.0.0.1:1") showing that precise URI values aren't critical in test contexts
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for URI usage in error handling or logging
rg -A 3 "Uri::" --type rust
Length of output: 100
Script:
#!/bin/bash
# Search for Uri usage with ripgrep using word boundary
rg -w "Uri" --type rust -A 3
# Search for ExecutionResponse usage
rg "ExecutionResponse" --type rust -A 3
# Search for specific test files that might use mock SDK
fd "test.*\.rs$" --type f --exec rg -l "mock.*sdk"
Length of output: 24421
DataContract::fetch(&sdk, query_correct) | ||
.await | ||
.expect("first fetch should succeed") | ||
.expect("object should exist"); | ||
|
||
let e = DataContract::fetch(&sdk, query_stale) | ||
.await | ||
.expect_err("second fetch should fail"); | ||
|
||
match e { | ||
dash_sdk::Error::StaleNode(StaleNodeError::Height { | ||
expected_height, | ||
received_height, | ||
tolerance_blocks, | ||
}) => { | ||
assert_eq!(expected_height, 10); | ||
assert_eq!(received_height, 2); | ||
assert_eq!(tolerance_blocks, 1); | ||
} | ||
_ => panic!("unexpected error: {:?}", e), | ||
} |
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
Enhance test robustness with constants and better assertions.
Consider these improvements:
- Add a constant for
tolerance_blocks
to make the test more maintainable - Assert the successful fetch result
- Use a constant for the expected height
+ const TOLERANCE_BLOCKS: u32 = 1;
+ const CURRENT_HEIGHT: u64 = 10;
+
// In mock configuration
let metadata = ResponseMetadata {
- height: 10,
+ height: CURRENT_HEIGHT,
..Default::default()
};
// In test execution
- DataContract::fetch(&sdk, query_correct)
+ let result = DataContract::fetch(&sdk, query_correct)
.await
- .expect("first fetch should succeed")
- .expect("object should exist");
+ .expect("first fetch should succeed");
+ assert!(result.is_none(), "Expected no data contract to be returned");
// In error assertion
match e {
dash_sdk::Error::StaleNode(StaleNodeError::Height {
expected_height,
received_height,
tolerance_blocks,
}) => {
- assert_eq!(expected_height, 10);
+ assert_eq!(expected_height, CURRENT_HEIGHT);
assert_eq!(received_height, 2);
- assert_eq!(tolerance_blocks, 1);
+ assert_eq!(tolerance_blocks, TOLERANCE_BLOCKS);
}
Committable suggestion was skipped due to low confidence.
@@ -380,7 +380,7 @@ fn serialize_vec_to_cbor<T: Into<Value>>(input: Vec<T>) -> Result<Vec<u8>, Error | |||
|
|||
let mut serialized = Vec::new(); | |||
ciborium::ser::into_writer(&cbor_values, &mut serialized) | |||
.map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?; | |||
.map_err(|e| dpp::ProtocolError::EncodingError(e.to_string()))?; |
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.
Fix type mismatch in error handling.
The error mapping on this line will cause a compilation error due to type mismatch. The function returns Result<Vec<u8>, Error>
, but the error is being mapped to dpp::ProtocolError
. Additionally, this change creates inconsistency with the error handling pattern used above where Error::Protocol
wrapper is used.
Apply this fix to maintain consistency and fix the type mismatch:
- .map_err(|e| dpp::ProtocolError::EncodingError(e.to_string()))?;
+ .map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?;
📝 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.
.map_err(|e| dpp::ProtocolError::EncodingError(e.to_string()))?; | |
.map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?; |
impl<T, E> MockResponse for Result<T, E> | ||
where | ||
T: MockResponse, | ||
E: MockResponse, | ||
{ | ||
fn mock_serialize(&self, mock_sdk: &MockDashPlatformSdk) -> Vec<u8> { | ||
match self { | ||
Ok(value) => { | ||
let mut data = vec![0]; | ||
data.extend(value.mock_serialize(mock_sdk)); | ||
data | ||
} | ||
Err(err) => { | ||
let mut data = vec![1]; | ||
data.extend(err.mock_serialize(mock_sdk)); | ||
data | ||
} | ||
} | ||
} | ||
|
||
fn mock_deserialize(mock_sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self | ||
where | ||
Self: Sized, | ||
{ | ||
match buf.first() { | ||
Some(0) => Ok(T::mock_deserialize(mock_sdk, &buf[1..])), | ||
Some(1) => Err(E::mock_deserialize(mock_sdk, &buf[1..])), | ||
other => panic!("invalid result data {:?}", other), | ||
} | ||
} | ||
} |
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.
Improve error handling in Result deserialization.
The current implementation panics with a generic message when encountering invalid data. Consider providing more context in the error message and handling empty buffers.
Apply this improvement:
fn mock_deserialize(mock_sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self
where
Self: Sized,
{
+ if buf.is_empty() {
+ panic!("Cannot deserialize Result from empty buffer");
+ }
match buf.first() {
Some(0) => Ok(T::mock_deserialize(mock_sdk, &buf[1..])),
Some(1) => Err(E::mock_deserialize(mock_sdk, &buf[1..])),
- other => panic!("invalid result data {:?}", other),
+ other => panic!(
+ "Invalid Result variant byte: expected 0 or 1, got {:?}",
+ other
+ ),
}
}
📝 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.
impl<T, E> MockResponse for Result<T, E> | |
where | |
T: MockResponse, | |
E: MockResponse, | |
{ | |
fn mock_serialize(&self, mock_sdk: &MockDashPlatformSdk) -> Vec<u8> { | |
match self { | |
Ok(value) => { | |
let mut data = vec![0]; | |
data.extend(value.mock_serialize(mock_sdk)); | |
data | |
} | |
Err(err) => { | |
let mut data = vec![1]; | |
data.extend(err.mock_serialize(mock_sdk)); | |
data | |
} | |
} | |
} | |
fn mock_deserialize(mock_sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self | |
where | |
Self: Sized, | |
{ | |
match buf.first() { | |
Some(0) => Ok(T::mock_deserialize(mock_sdk, &buf[1..])), | |
Some(1) => Err(E::mock_deserialize(mock_sdk, &buf[1..])), | |
other => panic!("invalid result data {:?}", other), | |
} | |
} | |
} | |
impl<T, E> MockResponse for Result<T, E> | |
where | |
T: MockResponse, | |
E: MockResponse, | |
{ | |
fn mock_serialize(&self, mock_sdk: &MockDashPlatformSdk) -> Vec<u8> { | |
match self { | |
Ok(value) => { | |
let mut data = vec![0]; | |
data.extend(value.mock_serialize(mock_sdk)); | |
data | |
} | |
Err(err) => { | |
let mut data = vec![1]; | |
data.extend(err.mock_serialize(mock_sdk)); | |
data | |
} | |
} | |
} | |
fn mock_deserialize(mock_sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self | |
where | |
Self: Sized, | |
{ | |
if buf.is_empty() { | |
panic!("Cannot deserialize Result from empty buffer"); | |
} | |
match buf.first() { | |
Some(0) => Ok(T::mock_deserialize(mock_sdk, &buf[1..])), | |
Some(1) => Err(E::mock_deserialize(mock_sdk, &buf[1..])), | |
other => panic!( | |
"Invalid Result variant byte: expected 0 or 1, got {:?}", | |
other | |
), | |
} | |
} | |
} |
Issue being fixed or feature implemented
Rust SDK mocks don't support mocking of errors.
What was done?
Refactored SDK mocking API so that now it accepts
Result
orMockResult
type.How Has This Been Tested?
Run unit tests.
Breaking Changes
Public methods that define mock expectations have changed,
Checklist:
For repository code-owners and collaborators only
Summary by CodeRabbit
New Features
Option<T>
,Vec<T>
, andDapiClientError
.DapiClientError
for better error categorization.Bug Fixes
PutIdentity
trait implementation and theDocumentQuery
serialization function.Documentation
Chores
Cargo.toml
files to manage features effectively.