Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk)!: support errors in mock #2277

Open
wants to merge 55 commits into
base: v1.6-dev-ugly
Choose a base branch
from

Conversation

lklimek
Copy link
Contributor

@lklimek lklimek commented Oct 24, 2024

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 or MockResult type.

How Has This Been Tested?

Run unit tests.

Breaking Changes

Public methods that define mock expectations have changed,

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • New Features

    • Enhanced serialization and deserialization capabilities for various data types, including Option<T>, Vec<T>, and DapiClientError.
    • Introduced new methods for handling mock responses and expectations in the SDK.
    • Added a new variant to the DapiClientError for better error categorization.
    • Added constants for default values in test configurations.
  • Bug Fixes

    • Improved error handling in the PutIdentity trait implementation and the DocumentQuery serialization function.
  • Documentation

    • Updated and clarified comments across various files to enhance understanding and maintainability.
  • Chores

    • Reorganized import statements for better clarity and structure.
    • Updated dependency configurations in Cargo.toml files to manage features effectively.
    • Removed obsolete test files and added new ones for better test coverage.

Copy link
Contributor

coderabbitai bot commented Oct 24, 2024

Walkthrough

The changes in this pull request focus on enhancing the Mockable trait and its implementations across various files, particularly for serialization and deserialization of mockable types. Key updates include the introduction of new methods for handling Option<T>, Vec<T>, and primitive types, along with improvements to error handling and documentation. The DapiClientError enum has been modified to include a new Mock variant. Additionally, several files have seen updates to improve clarity and maintainability, particularly in error handling and response processing.

Changes

File Path Change Summary
packages/dapi-grpc/src/mock.rs Updated Mockable trait methods for conditional compilation with mocks feature. Enhanced serialization/deserialization for Option<T> and added implementations for Vec<T>. Introduced mockable_number! macro.
packages/rs-dapi-client/src/address_list.rs Added Mockable trait implementation for Address struct, including mock_serialize and mock_deserialize methods.
packages/rs-dapi-client/src/executor.rs Enhanced documentation and error handling in ExecutionError and ExecutionResponse structs; added conditional serialization traits.
packages/rs-dapi-client/src/mock.rs Updated mock_serialize and mock_deserialize methods for ExecutionResponse and ExecutionError. Introduced FromInner trait for creating wrapping objects.
packages/rs-drive-proof-verifier/src/error.rs Added bincode::Encode and bincode::Decode traits to Error and ContextProviderError enums for serialization.
packages/rs-platform-version/src/error.rs Updated PlatformVersionError enum to include bincode traits for serialization.
packages/rs-sdk/Cargo.toml Modified dependency configurations for drive-proof-verifier and rs-dapi-client to disable default features.
packages/rs-sdk/src/mock/requests.rs Added MockResponse trait implementations for multiple types and expanded tuple support for serialization/deserialization.
packages/rs-sdk/src/mock/sdk.rs Updated MockDashPlatformSdk methods for handling mock expectations; reorganized imports.
packages/rs-sdk/src/platform/transition/put_identity.rs Simplified error handling in PutIdentity trait methods by using into_inner() directly.
packages/rs-sdk/src/sdk.rs Consolidated mock-related imports; added dapi_client_settings field to Sdk struct.
packages/rs-sdk/tests/fetch/mock_fetch.rs Introduced test_mock_fetch_retry to evaluate SDK behavior with different node heights.
packages/rs-dapi-client/src/dapi_client.rs Enhanced DapiClientError enum with a new Mock variant; updated serialization methods for the Mockable implementation.
packages/rs-drive-proof-verifier/Cargo.toml Updated version and modified bincode dependency handling.
packages/rs-drive-proof-verifier/src/provider.rs Reorganized imports in provider.rs without altering logic.
packages/rs-drive-proof-verifier/src/types.rs Removed encode_to_vec method from ContestedResource and removed ContestedVote struct; updated VotePollsGroupedByTimestamp.
packages/rs-sdk/tests/fetch/config.rs Added constants for default values in Config struct; updated methods to use these constants.
packages/rs-sdk/tests/fetch/data_contract.rs Updated test_data_contract_history_read to use a constant for data contract ID.
packages/rs-sdk/src/core/transaction.rs Added comments regarding future refactoring in start_instant_send_lock_stream and wait_for_asset_lock_proof_for_transaction methods.
packages/rs-sdk/src/platform/document_query.rs Simplified error mapping in serialize_vec_to_cbor function.
packages/rs-sdk/src/platform/fetch_many.rs Renamed variable from document_query to request in fetch_many method for clarity.
packages/rs-sdk/src/sync.rs Simplified retry logic in retry_test_function to ensure clarity in retry count.

Possibly related PRs

Suggested labels

enhancement, js-sdk

Suggested reviewers

  • QuantumExplorer
  • shumkov

🐇 In the meadow, changes bloom bright,
Mockable traits take graceful flight.
Serialization's dance, errors refined,
In our code, clarity we find.
With every hop, we improve our way,
Cheers to the changes, hip-hip-hooray! 🎉


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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

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

@lklimek lklimek changed the title Refactor/sdk mock errors feat(sdk)!: support errors in mock Oct 24, 2024
Base automatically changed from feat/sdk-retry to v1.4-dev October 28, 2024 14:32
@lklimek lklimek marked this pull request as ready for review October 29, 2024 08:00
@lklimek lklimek self-assigned this Oct 29, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 21

🧹 Outside diff range and nitpick comments (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:

  1. Using exponential backoff with jitter for retries
  2. Setting appropriate timeout and max retry attempts
  3. 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:

  1. Define specific error types for different failure scenarios
  2. Implement proper error context and chain of custody
  3. Add logging for debugging and monitoring
  4. 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:

  1. Removing the empty line at line 88
  2. 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:

  1. Creating specific error variants for different verification failure cases
  2. 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:

  1. Documenting the specific error cases that can occur
  2. 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:

  1. Consider extracting common retry/timeout logic into a reusable middleware
  2. Implement a proper state machine for tracking document updates
  3. 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:

  1. Exponential backoff for network issues
  2. Maximum retry attempts configuration
  3. Specific retry conditions for different error types

Would you like me to:

  1. Generate a retry mechanism implementation using tokio-retry?
  2. 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:

  1. Creating a configurable retry policy trait
  2. Implementing exponential backoff with jitter
  3. Defining specific error conditions that warrant retries
  4. 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

📥 Commits

Files that changed from the base of the PR and between 4dbdc1f and 4f2bb21.

⛔ 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 and Debug
  • Some errors derive additional traits for specific features:
    • rs-drive-proof-verifier: Uses conditional bincode serialization with cfg_attr
    • rs-dapi-client: Uses conditional serde serialization
    • rs-dpp/consensus: Uses both bincode and serde 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 using backon::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:

  1. What specific execution errors need better handling
  2. What improvements are needed
  3. 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: ⚠️ Potential issue

Improve error conversion implementation.

The current implementation has several areas for improvement:

  1. Converting ExecutionError to a string loses valuable error context and type information.
  2. Using DapiClientError variant for an ExecutionError might be misleading.
  3. 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:

  1. Custom error types for execution-specific failures
  2. Detailed error context preservation
  3. 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:

  1. Implementing retry logic as noted in the TODO
  2. Adding timeout handling to prevent indefinite waits
  3. 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:

  1. Documenting the expected error types that can be returned
  2. 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:

  1. Errors are properly propagated through the Result type
  2. Domain-specific errors are mapped to the SDK's Error enum
  3. 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:

  1. Documenting specific error cases that need handling
  2. 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:

  1. The TODO about retry logic should be addressed, as state transition operations may require multiple attempts
  2. 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:

  1. Use the retry() function from rs-sdk/src/sync.rs which provides:
    • Configurable retry attempts via RequestSettings
    • Exponential backoff with the backon crate
    • Proper error handling with CanRetry trait

Example usage:

let settings = RequestSettings::default();
retry(settings, |s| async move {
    request.execute(sdk, s).await
}).await

The rationale for this response:

  1. The codebase shows a mature retry implementation in rs-sdk that handles state transition propagation
  2. The implementation includes proper error classification, backoff strategy, and configurable retry attempts
  3. The TODO can be addressed by using the existing retry mechanism rather than implementing a new one
  4. 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: ⚠️ Potential issue

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: ⚠️ Potential issue

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.

packages/rs-dapi-client/Cargo.toml Outdated Show resolved Hide resolved
packages/dapi-grpc/src/mock.rs Show resolved Hide resolved
packages/dapi-grpc/src/mock.rs Show resolved Hide resolved
packages/dapi-grpc/src/mock.rs Show resolved Hide resolved
packages/rs-dapi-client/src/address_list.rs Show resolved Hide resolved
packages/rs-sdk/src/sync.rs Outdated Show resolved Hide resolved
packages/rs-sdk/src/mock/requests.rs Outdated Show resolved Hide resolved
packages/rs-sdk/src/platform/fetch_many.rs Outdated Show resolved Hide resolved
packages/rs-sdk/src/platform/fetch_many.rs Outdated Show resolved Hide resolved
packages/rs-sdk/src/mock/sdk.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (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:

  1. When this error variant occurs
  2. How it affects existing code
  3. 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:

  1. Using a structured format like serde_json or bincode with proper type definitions.
  2. 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

📥 Commits

Files that changed from the base of the PR and between 4f2bb21 and 98bebee.

📒 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: ⚠️ Potential issue

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 }
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 29, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Copy link
Member

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

Copy link
Contributor

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.

(^‿^)/

Copy link
Contributor Author

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.

Copy link
Contributor

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!

packages/rs-dapi-client/src/dapi_client.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 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 alongside test_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:

  1. Document what each constant represents (e.g., what kind of identity, what type of contract)
  2. Document the process or conditions that require updating these values
  3. 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

📥 Commits

Files that changed from the base of the PR and between 98bebee and e5f827c.

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

packages/rs-sdk/tests/fetch/config.rs Show resolved Hide resolved
@shumkov shumkov added this to the 1.4.2 milestone Oct 30, 2024
@@ -257,32 +257,83 @@ impl Expectations {

impl<R: Mockable> Mockable for ExecutionResponse<R> {
Copy link
Member

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.

Copy link
Contributor Author

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>(
Copy link
Member

Choose a reason for hiding this comment

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

From<(&RequestSettings, &RequestSettings)> ? ))

Copy link
Contributor Author

@lklimek lklimek Oct 30, 2024

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 }
Copy link
Member

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))]
Copy link
Member

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

Copy link
Contributor Author

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)]
Copy link
Member

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

Copy link
Contributor Author

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
Copy link
Member

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

Copy link
Contributor Author

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.

@shumkov shumkov modified the milestones: 1.5.0, v1.5.x Oct 30, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (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:

  1. Refactoring to use ExecutionResult for standardized error handling
  2. 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

📥 Commits

Files that changed from the base of the PR and between e5f827c and bf07db8.

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

  1. All callers are updated to pass references
  2. 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

Comment on lines +225 to +245
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),
}
Copy link
Contributor

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:

  1. Add a constant for tolerance_blocks to make the test more maintainable
  2. Assert the successful fetch result
  3. 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()))?;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

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.

Suggested change
.map_err(|e| dpp::ProtocolError::EncodingError(e.to_string()))?;
.map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?;

Comment on lines +308 to +338
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),
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve error handling 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.

Suggested change
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
),
}
}
}

@shumkov shumkov changed the base branch from v1.4-dev to v1.6-dev November 1, 2024 01:53
@shumkov shumkov removed this from the v1.5.x milestone Nov 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

2 participants