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

Hydration #145

Merged
merged 51 commits into from
Oct 22, 2024
Merged

Hydration #145

merged 51 commits into from
Oct 22, 2024

Conversation

ryardley
Copy link
Contributor

@ryardley ryardley commented Oct 11, 2024

Closes: #123
Closes: #149

Sets up hydration for data persistence

Actors save and hydrate themselves to the db by implementing a set of traits:

/// This trait enables the self type to report their state snapshot
pub trait Snapshot
where
    Self: Sized,
{
    type Snapshot: Serialize + DeserializeOwned;
    fn snapshot(&self) -> Self::Snapshot;
}

/// This trait enables the self type to checkpoint its state by calling the checkpoint() function.
pub trait Checkpoint: Snapshot {
    fn repository(&self) -> Repository<Self::Snapshot>;
    fn checkpoint(&self) {
        self.repository().write(&self.snapshot());
    }
}

/// Enable the self type to be reconstituted from the parameters coupled with the Snapshot
#[async_trait]
pub trait FromSnapshotWithParams: Snapshot {
    type Params: Send + 'static;
    async fn from_snapshot(params: Self::Params, snapshot: Self::Snapshot) -> Result<Self>;
}

/// Enable the self type to be reconstituted from the Snapshot only
#[async_trait]
pub trait FromSnapshot: Snapshot {
    async fn from_snapshot(snapshot: Self::Snapshot) -> Result<Self>;
}

Also I have tidied up the feature section:

/// Format of the hook that needs to be passed to E3RequestRouter
#[async_trait]
pub trait E3Feature: Send + Sync + 'static {
    /// when an Enclave Event is dispatched
    fn on_event(&self, ctx: &mut E3RequestContext, evt: &EnclaveEvent);
    
    /// When the feature is hydrating from snapshot
    async fn hydrate(
        &self,
        ctx: &mut E3RequestContext,
        snapshot: &E3RequestContextSnapshot,
    ) -> Result<()>;
}
  • DataStore
  • Hydration for Keyshare Actor
  • Hydration for E3RequestRouter
  • Hydration for PublicKeyAggregator Actor
  • Hydration for PlaintextAggregator Actor
  • Hydration for CommitteeMeta
  • Hydration for Sortition
  • Setup domain specific repositories to wrap store within feature space - ie. simplify the API and make it typesafe
  • Ensure store has methods to get and set at scope
  • Remove redundant stuff / Tidy up
  • Test hydration
  • Attach db to integration test

This adds a few patterns to our codebase for creating checkpoints of state for our actors as outlined in #123

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced data handling capabilities with the introduction of new data store structures and traits.
    • Added serialization support to various components for improved data management.
    • Implemented a feature-based architecture for better component management and state recovery.
    • Introduced new structs and methods for improved state management in aggregators.
    • New dependencies added to enhance functionality across multiple packages.
    • Added a new Shutdown event type for graceful termination of the actor system.
    • Introduced a new E3RequestContext for better event handling and dependency management.
    • Added new utility functions for improved test setup and event handling.
    • Enhanced the EvmEventReader for better event processing from the Ethereum Virtual Machine.
    • Added new functions to streamline the launch process in integration tests.
    • New IntoKey trait for flexible key handling and conversion.
    • Introduced Repositories struct for managing various repository types.
  • Bug Fixes

    • Improved state transition handling in aggregator implementations.
    • Enhanced error handling during shutdown processes.
  • Chores

    • Updated dependencies across multiple packages to enhance functionality and performance.
    • Cleaned up and refactored test scripts for better maintainability.

@ryardley ryardley changed the title Added DataStore Hydration Oct 15, 2024
@ryardley ryardley marked this pull request as ready for review October 16, 2024 05:52
Copy link
Contributor

coderabbitai bot commented Oct 16, 2024

Walkthrough

The pull request introduces extensive modifications across multiple packages, enhancing the functionality and structure of the codebase. Key updates include the re-exporting of public entities from the plaintext_aggregator and publickey_aggregator modules, significant enhancements to the PlaintextAggregator and PublicKeyAggregator implementations, and the introduction of a DataStore for managing data interactions. Additionally, a shift toward a feature-based architecture is evident in the router and aggregator components, with new traits and methods for state management and serialization being added.

Changes

File Path Change Summary
packages/ciphernode/aggregator/src/lib.rs Re-exported public entities from plaintext_aggregator and publickey_aggregator.
packages/ciphernode/aggregator/src/plaintext_aggregator.rs Enhanced PlaintextAggregator with new methods, fields, and trait implementations for state management and serialization.
packages/ciphernode/aggregator/src/publickey_aggregator.rs Updated PublicKeyAggregator similarly to PlaintextAggregator, adding new methods and traits for state management.
packages/ciphernode/data/Cargo.toml Added dependencies: anyhow, serde, sled, bincode, async-trait.
packages/ciphernode/data/src/data_store.rs Introduced structures and methods for managing a key-value data store, including Insert, Get, and DataStore.
packages/ciphernode/data/src/in_mem.rs Renamed Data to InMemStore, added GetLog, and updated data handling methods.
packages/ciphernode/data/src/lib.rs Modified module structure, removing the previous data module, and adding data_store, in_mem, into_key, repository, sled_store, and snapshot.
packages/ciphernode/enclave_node/src/aggregator.rs Updated MainAggregator to utilize DataStore and modified the attach method.
packages/ciphernode/enclave_node/src/ciphernode.rs Replaced Data type with DataStore in MainCiphernode, updated initialization methods.
packages/ciphernode/enclave_node/src/lib.rs Added shutdown module and updated public exports accordingly.
packages/ciphernode/enclave_node/src/shutdown.rs Introduced listen_for_shutdown function for handling graceful shutdowns.
packages/ciphernode/evm/src/event_reader.rs Added EvmEventReader struct for connecting to EVM and processing events.
packages/ciphernode/router/src/context.rs Introduced E3RequestContext for managing event dependencies and state.
packages/ciphernode/router/src/repositories.rs Added Repositories struct for managing various repository types and their creation.
packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs Enhanced tests with new types, improved event handling, and additional helper functions.

Assessment against linked issues

Objective Addressed Explanation
Provide the data actor as a writer and a reader. (123)
The write should be typed Receiver<Insert>. (123)
The reader should be typed Receiver<Get>. (123)
Gracefully tidy up connections on SIGTERM. (149)

Possibly related PRs

  • Evm Integration and integration script #107: The changes in this PR involve modifications to the Ciphernode struct and its methods, which may relate to the re-exporting of public entities in the main PR, particularly if those entities are used in the context of EVM integration.

  • Remove address from encoding #119: This PR introduces changes to the handling of E3Requested and CiphertextOutputPublished events, which are relevant to the modifications in the main PR that involve the PlaintextAggregator and PublicKeyAggregator entities, as they also deal with event handling and state management.

  • Actor Destruction #142: This PR focuses on ensuring that actors related to E3 requests self-destruct after completing their tasks, which aligns with the changes in the main PR that enhance clarity and management of public entities in the aggregator modules.

Suggested reviewers

  • nginnever
  • auryn-macmillan
  • hmzakhalid
  • samepant

Poem

🐇 In the land where data hops,
New stores and traits, oh how it pops!
With serde's magic, we serialize,
In memory, our secrets lie.
From plain to public, changes abound,
In this code garden, joy is found! 🌼


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.

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

🧹 Outside diff range and nitpick comments (16)
packages/ciphernode/sortition/Cargo.toml (1)

13-20: Changes align well with PR objectives.

The addition of new dependencies and the modular structure with the local 'data' crate align well with the PR objectives of implementing hydration for data persistence. These changes should facilitate better state management and testability.

Consider updating the package description to reflect the new data persistence capabilities, if applicable. For example:

- description = ": coordinates the encryption and decryption of enclave computations"
+ description = ": coordinates the encryption, decryption, and data persistence of enclave computations"
packages/ciphernode/data/src/in_mem.rs (2)

Line range hint 35-42: Potential unbounded memory growth in self.log when capture is true

When capture is enabled, every Insert operation is logged into self.log. If there are a large number of inserts, this could lead to unbounded memory usage.

Consider implementing a mechanism to manage the size of self.log, such as:

  • Limiting the maximum size of self.log and removing the oldest entries when the limit is exceeded.
  • Providing a method to clear or persist the log after processing.

Line range hint 55-59: Inefficient cloning of self.log in GetLog handler

Cloning the entire self.log in the GetLog handler can be inefficient, especially if the log is large.

Consider returning a reference to self.log or using an iterator to avoid cloning:

 impl Handler<GetLog> for InMemDataStore {
-    type Result = Vec<DataOp>;
-    fn handle(&mut self, _: GetLog, _: &mut Self::Context) -> Vec<DataOp> {
-        self.log.clone()
+    type Result = Vec<DataOp>;
+    fn handle(&mut self, _: GetLog, _: &mut Self::Context) -> Vec<DataOp> {
+        self.log.iter().cloned().collect()
     }
 }

Alternatively, if the Handler result allows for references with appropriate lifetimes:

 impl Handler<GetLog> for InMemDataStore {
-    type Result = Vec<DataOp>;
-    fn handle(&mut self, _: GetLog, _: &mut Self::Context) -> Vec<DataOp> {
-        self.log.clone()
+    type Result = &[DataOp];
+    fn handle(&mut self, _: GetLog, _: &mut Self::Context) -> &[DataOp] {
+        &self.log
     }
 }

Ensure that lifetime annotations are correctly specified to prevent borrowing issues.

packages/ciphernode/enclave_node/src/ciphernode.rs (1)

60-60: Reminder: Address the TODO to switch to the Sled actor

The comment indicates an intention to replace the in-memory data store with the Sled actor for persistence:

// TODO: switch to Sled actor

Implementing this will enhance data persistence and reliability.

Would you like assistance in implementing the Sled actor integration or opening a GitHub issue to track this task?

packages/ciphernode/keyshare/src/keyshare.rs (1)

143-152: Enhance Error Logging with Additional Context

When an error occurs during decryption, the error message logs error decrypting ciphertext. Including the e3_id or additional context in the error message can aid in debugging and quickly identifying the affected transaction.

packages/ciphernode/sortition/src/sortition.rs (1)

Line range hint 27-46: Handle potential parsing errors when converting node addresses

In the SortitionModule::contains method, the code uses unwrap() when parsing node addresses:

.map(|b| b.parse().unwrap())

Using unwrap() may cause the program to panic if parsing fails. It's safer to handle this error explicitly to prevent potential runtime crashes.

Consider handling the parsing error as follows:

.map(|b| b.parse())
.collect::<Result<Vec<Address>, _>>()?;

This way, any parsing errors will be propagated as Result errors, allowing for graceful error handling.

packages/ciphernode/data/src/data_store.rs (4)

202-204: Avoid using str as a parameter name to prevent shadowing

The parameter str in the ensure_root_id method shadows Rust's primitive str type. This can lead to confusion and potential errors. It is advisable to rename the parameter.

Apply this diff to rename the parameter:

-    pub fn ensure_root_id(str: &str) -> Result<()> {
-        if !str.starts_with("/") {
+    pub fn ensure_root_id(input: &str) -> Result<()> {
+        if !input.starts_with("/") {

204-204: Correct grammatical error in error message

The error message in ensure_root_id has a grammatical mistake.

Apply this diff to fix the error message:

-            return Err(anyhow!("string doesnt start with slash."));
+            return Err(anyhow!("String doesn't start with a slash."));

155-158: Add Send bound to type T in async read method

The read method is async and may be sent across threads. To ensure thread safety, the type T should implement the Send trait.

Apply this diff to add the Send bound:

         pub async fn read<K, T>(&self, key: K) -> Result<Option<T>>
         where
             K: IntoKey,
-            T: for<'de> Deserialize<'de>,
+            T: for<'de> Deserialize<'de> + Send,
         {

171-173: Avoid cloning messages unnecessarily

In the set method, the message msg is cloned when applying the prefix. This clone may be unnecessary and can be avoided to improve performance.

Apply this diff to avoid cloning:

-            let msg = self.prefix.as_ref().map_or(msg.clone(), |p| msg.prefix(p));
+            let msg = self.prefix.as_ref().map_or(msg, |p| msg.prefix(p));
packages/ciphernode/aggregator/src/publickey_aggregator.rs (1)

29-37: Consider renaming the init method for idiomatic clarity

The init method initializes PublicKeyAggregatorState to the Collecting variant. For better clarity and adherence to Rust conventions, consider renaming the method to reflect the variant it creates, such as collecting, or providing associated functions for each variant.

You might apply the following change:

impl PublicKeyAggregatorState {
-    pub fn init(threshold_m: usize, seed: Seed) -> Self {
+    pub fn collecting(threshold_m: usize, seed: Seed) -> Self {
         PublicKeyAggregatorState::Collecting {
             threshold_m,
             keyshares: OrderedSet::new(),
             seed,
         }
     }
 }
packages/ciphernode/router/src/hooks.rs (2)

93-96: Ensure fhe instance is available before proceeding

Good job checking if the fhe instance is available. However, consider providing more context in the error message to help with debugging.

You might include additional information in the error message, such as the e3_id or other relevant data.


171-179: Correct inconsistent indentation and formatting

There is inconsistent indentation and unnecessary blank lines which may affect code readability.

Ensure consistent use of indentation and remove unnecessary blank lines.

-let Some(fhe) = ctx.get_fhe() else {
-    self.bus.err(EnclaveErrorType::PlaintextAggregation, anyhow!("Could not create PlaintextAggregator because the fhe instance it depends on was not set on the context."));
-
-    return;
-};
+let Some(fhe) = ctx.get_fhe() else {
+    self.bus.err(EnclaveErrorType::PlaintextAggregation, anyhow!("Could not create PlaintextAggregator because the FHE instance it depends on was not set on the context."));
+    return;
+};
packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (1)

39-39: Reminder: Address the TODO comment

The TODO comment suggests replacing InMemDataStore with a sled-backed Data Actor for data persistence. Consider implementing this change to move from in-memory to persistent storage.

Do you want me to help implement the sled-backed Data Actor or open a GitHub issue to track this task?

packages/ciphernode/router/src/e3_request_router.rs (2)

113-142: Correct the method documentation to match the parameters

The documentation comments for set_keyshare, set_plaintext, set_publickey, set_fhe, and set_meta mention accepting a DataStore ID and an address or object, but the methods actually only accept a single parameter. Please update the documentation to accurately reflect the method parameters.


232-232: Address the TODO: Implement typestate pattern for feature dependencies

There is a TODO comment indicating the need to set up a typestate pattern to enforce the correct order of feature dependencies. This would improve the modularity and robustness of the code by ensuring features are initialized in the correct sequence.

Would you like assistance in implementing this pattern or opening a GitHub issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ecfd738 and 61cf59c.

⛔ Files ignored due to path filters (1)
  • packages/ciphernode/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • packages/ciphernode/aggregator/Cargo.toml (1 hunks)
  • packages/ciphernode/aggregator/src/plaintext_aggregator.rs (6 hunks)
  • packages/ciphernode/aggregator/src/publickey_aggregator.rs (7 hunks)
  • packages/ciphernode/data/Cargo.toml (1 hunks)
  • packages/ciphernode/data/src/data_store.rs (1 hunks)
  • packages/ciphernode/data/src/in_mem.rs (4 hunks)
  • packages/ciphernode/data/src/lib.rs (1 hunks)
  • packages/ciphernode/enclave_node/src/aggregator.rs (4 hunks)
  • packages/ciphernode/enclave_node/src/ciphernode.rs (5 hunks)
  • packages/ciphernode/fhe/Cargo.toml (1 hunks)
  • packages/ciphernode/fhe/src/fhe.rs (4 hunks)
  • packages/ciphernode/keyshare/Cargo.toml (1 hunks)
  • packages/ciphernode/keyshare/src/keyshare.rs (2 hunks)
  • packages/ciphernode/router/Cargo.toml (1 hunks)
  • packages/ciphernode/router/src/committee_meta.rs (1 hunks)
  • packages/ciphernode/router/src/e3_request_router.rs (5 hunks)
  • packages/ciphernode/router/src/hooks.rs (1 hunks)
  • packages/ciphernode/sortition/Cargo.toml (1 hunks)
  • packages/ciphernode/sortition/src/sortition.rs (4 hunks)
  • packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (4 hunks)
🧰 Additional context used
🔇 Additional comments (49)
packages/ciphernode/keyshare/Cargo.toml (1)

12-13: LGTM! The new dependencies align well with the PR objectives.

The addition of serde and async-trait dependencies is appropriate for implementing hydration and supporting asynchronous operations in the actor model. These changes are consistent with the PR objectives and the requirements outlined in issue #123.

  • serde will facilitate serialization and deserialization, which is crucial for data persistence.
  • async-trait will enable the use of async methods in traits, supporting the asynchronous nature of the actor model.

Both dependencies are configured to use the workspace version, maintaining consistency across the project.

packages/ciphernode/data/Cargo.toml (1)

10-13: Excellent additions to support hydration and data persistence!

The new dependencies (anyhow, serde, bincode, and async-trait) are well-chosen to support the PR's objective of implementing hydration for data persistence:

  1. anyhow will improve error handling, crucial for robust data operations.
  2. serde enables serialization and deserialization, essential for data persistence.
  3. bincode provides efficient binary encoding, useful for compact data storage.
  4. async-trait allows for asynchronous trait methods, supporting non-blocking operations in the actor model.

Using the workspace configuration for these dependencies ensures consistency across the project.

packages/ciphernode/aggregator/Cargo.toml (1)

9-15: LGTM! New dependencies align with PR objectives.

The addition of serde, async-trait, and data dependencies is appropriate for implementing hydration and data persistence as outlined in the PR objectives. These changes will enhance the aggregator's capabilities for serialization, asynchronous operations, and data management.

To ensure consistency in workspace usage, let's verify all dependencies:

packages/ciphernode/fhe/Cargo.toml (4)

8-8: LGTM: Addition of async-trait dependency.

The addition of async-trait as a workspace dependency is appropriate. It will enable the use of async functions in traits, which aligns with the PR objectives of implementing hydration and improving the actor model.


10-10: LGTM: Addition of local data dependency.

The addition of the local data package as a dependency is appropriate. This aligns well with the PR objectives of implementing hydration and data persistence. Using a local path ensures that the package is part of the same repository, promoting modularity and easier maintenance.


11-11: LGTM: Reordering of enclave-core and fhe_rs dependencies.

The reordering of the enclave-core and fhe_rs dependencies improves the organization and readability of the Cargo.toml file. This change doesn't affect functionality and is a good practice for maintaining clean dependency lists.

Also applies to: 14-14


8-14: Summary: Dependencies updated to support hydration and data persistence.

The changes to the dependencies in this Cargo.toml file align well with the PR objectives of implementing hydration and improving data persistence. The additions of async-trait, bincode, and the local data package provide the necessary tools for these improvements. The reordering of dependencies enhances readability.

Note: There's an inconsistency in the AI-generated summary regarding the bincode dependency. The summary stated it was removed, but it has actually been added.

Overall, these changes support the goals of the PR and should contribute to the implementation of the desired features.

packages/ciphernode/router/Cargo.toml (1)

15-17: LGTM: New dependencies align with PR objectives.

The addition of serde, bincode, and async-trait as dependencies is appropriate and aligns well with the PR objectives:

  1. serde: Enables serialization and deserialization of Rust data structures, which is crucial for implementing hydration and data persistence.
  2. bincode: Complements serde by providing an efficient binary serialization format, further supporting the hydration process.
  3. async-trait: Allows for async functions in traits, which is beneficial for asynchronous operations in the actor-based system using Actix.

These dependencies provide the necessary tools for effective state management and data handling, supporting the implementation of hydration for various components as outlined in the PR objectives.

packages/ciphernode/sortition/Cargo.toml (2)

13-20: Good job on improving dependency organization!

The alphabetical reordering of dependencies and the explicit feature specification for 'alloy' enhance the readability and maintainability of the Cargo.toml file.


13-20: LGTM! New dependencies added appropriately.

The addition of anyhow, async-trait, data, and serde dependencies is well-structured and consistent with the project's workspace setup. This suggests improvements in error handling, asynchronous operations, data management, and serialization capabilities.

To ensure these new dependencies are being utilized effectively, please run the following script:

✅ Verification successful

Dependencies Verified Successfully

All newly added dependencies (anyhow, async-trait, data, and serde) are appropriately utilized within the sortition package:

  • anyhow is used in sortition.rs and distance.rs.
  • async_trait is applied in sortition.rs.
  • data is employed in sortition.rs.
  • serde is utilized for serialization and deserialization in sortition.rs.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of newly added dependencies in the sortition package

# Test: Search for the usage of new dependencies
echo "Searching for 'anyhow' usage:"
rg --type rust 'use anyhow' packages/ciphernode/sortition/src

echo "Searching for 'async_trait' usage:"
rg --type rust '#\[async_trait\]' packages/ciphernode/sortition/src

echo "Searching for 'data' crate usage:"
rg --type rust 'use data::' packages/ciphernode/sortition/src

echo "Searching for 'serde' usage:"
rg --type rust 'use serde' packages/ciphernode/sortition/src

Length of output: 897


Script:

#!/bin/bash
# Description: Further verify the usage of 'serde' in the sortition package

# Test: Search for 'serde' in macros and other contexts
echo "Searching for 'serde' derive macros:"
rg --type rust '#\s*derive\s*\(\s*Serialize\s*,\s*Deserialize\s*\)' packages/ciphernode/sortition/src

echo "Searching for 'serde' attribute usages:"
rg --type rust 'serde::' packages/ciphernode/sortition/src

echo "Searching for 'serde' in Cargo.toml dependencies comments or configurations:"
rg --type toml 'serde' packages/ciphernode/sortition/Cargo.toml

Length of output: 710

packages/ciphernode/data/src/in_mem.rs (2)

15-15: Verify all references to Data are updated to InMemDataStore

Since Data has been renamed to InMemDataStore, it's important to ensure that all references to Data elsewhere in the codebase have been updated to prevent compile-time errors.

Run the following script to find any remaining references to Data:

✅ Verification successful

All references to Data have been successfully updated to InMemDataStore. The only remaining occurrence is within a comment, which does not affect the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find references to the old `Data` struct.

# Test: Search for `Data` in Rust files. Expect: No occurrences related to the old struct.
rg --type rust -w 'Data'

Length of output: 188


15-18: ⚠️ Potential issue

Update the outdated comment to reflect BTreeMap usage

The comment in the handle method mentions inserting data into sled, but the code now uses BTreeMap. This may cause confusion for future maintainers.

Apply this diff to correct the comment:

             fn handle(&mut self, event: Insert, _: &mut Self::Context) {
-                // insert data into sled
+                // insert data into the BTreeMap
                 self.db.insert(event.key(), event.value());

Likely invalid or redundant comment.

packages/ciphernode/enclave_node/src/ciphernode.rs (4)

Line range hint 24-35: Verify the impact of changing data from Addr<Data> to DataStore

Changing the type of data from Addr<Data> to DataStore in the MainCiphernode struct and its constructor may affect how data is shared and accessed across actors. Ensure that:

  • The DataStore provides the necessary concurrency and sharing capabilities required by the actors.
  • All interactions that previously relied on Addr<Data> are updated accordingly to work with DataStore.
  • There are no unintended side effects on data accessibility or message passing between actors.

61-61: Ensure correct initialization of DataStore

The data store is initialized with:

let data = DataStore::from_in_mem(InMemDataStore::new(true).start());

Verify that:

  • The start() method returns the expected type compatible with DataStore::from_in_mem().
  • The in-memory data store initialization aligns with the rest of the application's data management strategy.
  • Any asynchronous operations are correctly handled and awaited where necessary.

62-62: Confirm the updated Sortition::attach method signature

The attach method for Sortition now includes data.clone() as an argument:

let sortition = Sortition::attach(bus.clone(), data.clone());

Ensure that:

  • The Sortition actor's attach method is updated to accept the DataStore parameter.
  • All other calls to Sortition::attach are updated to match the new signature.
  • The data is utilized appropriately within the Sortition actor without introducing any side effects.

82-86: Verify transition from add_hook to add_feature

The builder pattern now uses add_feature instead of add_hook:

.add_feature(FheFeature::create(rng))
.add_feature(KeyshareFeature::create(bus.clone(), &address.to_string()))

Ensure that:

  • The E3RequestRouter is correctly updated to use features instead of hooks.
  • All features conform to the expected interfaces and integrate seamlessly.
  • The change does not break existing functionality dependent on the previous hook system.
packages/ciphernode/enclave_node/src/aggregator.rs (4)

3-3: Added imports for data storage functionality

The addition of DataStore and InMemDataStore imports is appropriate for implementing data persistence.


12-12: Imported features for the router's feature-based architecture

The import of FheFeature, PlaintextAggregatorFeature, and PublicKeyAggregatorFeature aligns with the shift from a hook-based to a feature-based architecture in the router.


55-56: Initialized in-memory data store and attached to Sortition

The DataStore is correctly initialized with an in-memory store and started. Cloning the store when passing it to Sortition::attach is appropriate to ensure that both components have access.


86-97: Updated E3RequestRouter to utilize data store and features

The E3RequestRouter builder now accepts the store, and features are added using the add_feature method. The features FheFeature, PublicKeyAggregatorFeature, and PlaintextAggregatorFeature are properly created with the necessary cloned resources. The asynchronous build and await pattern is correctly implemented.

packages/ciphernode/keyshare/src/keyshare.rs (1)

69-76: Ensure Secure Management of Secret During Deserialization

When reconstructing the Keyshare from a snapshot in from_snapshot, the secret is assigned directly from the deserialized state. Validate that the deserialization process securely handles the secret to prevent potential security risks such as unauthorized access or tampering.

packages/ciphernode/sortition/src/sortition.rs (9)

5-6: Necessary imports for new traits and functionality

The added imports are appropriate and required for implementing async_trait and the traits Snapshot, FromSnapshotWithParams, and Checkpoint.


27-30: Definition of SortitionModule with serialization capabilities

The SortitionModule struct is correctly defined with Clone, Serialize, and Deserialize derived traits, enabling cloning and serialization which are essential for state management and persistence.


87-87: Addition of store: DataStore field to Sortition struct

Including the store field allows Sortition to interact with the DataStore for state persistence. This aligns with the goal of enhancing data persistence capabilities.


90-93: Introduction of SortitionParams struct for cleaner initialization

The SortitionParams struct encapsulates initialization parameters, promoting cleaner code and easier extensibility for future parameters.


96-100: Refactored new method to accept SortitionParams

Updating the new method to accept SortitionParams enhances constructor clarity and parameter management. The initialization of bus and store from params is correctly implemented.


104-109: Updated attach method to include DataStore

The attach method now accepts a DataStore, which is essential for state persistence. Ensure that all calls to attach across the codebase are updated to pass the DataStore instance.


123-128: Implemented Snapshot trait for Sortition

The implementation of the Snapshot trait correctly returns a clone of the list, allowing the current state to be captured for persistence.


130-140: Implemented FromSnapshotWithParams trait for Sortition

The from_snapshot method appropriately reconstructs a Sortition instance from a snapshot and parameters. This facilitates restoring state, which is crucial for hydration.


142-146: Implemented Checkpoint trait for Sortition

The get_store method provides access to the DataStore, enabling checkpointing functionality. Verify that cloning the DataStore does not introduce unnecessary overhead or performance issues.

packages/ciphernode/aggregator/src/plaintext_aggregator.rs (6)

14-14: Implemented Serialize and Deserialize for state enum

Deriving serde::Serialize and serde::Deserialize for PlaintextAggregatorState enables serialization of the aggregator's state, which is essential for snapshotting and state restoration.


32-41: Added init method to PlaintextAggregatorState

The init method provides a clear and concise way to initialize the Collecting state with the necessary parameters.


53-53: Introduced store field to PlaintextAggregator

Adding store: DataStore allows the aggregator to persist its state, aligning with the implementation of the Checkpoint trait.


60-68: Created PlaintextAggregatorParams struct

Encapsulating constructor parameters into PlaintextAggregatorParams enhances code readability and makes parameter management more efficient.


70-78: Refactored new method to accept params struct

Updating the constructor to accept PlaintextAggregatorParams and PlaintextAggregatorState simplifies the instantiation process and improves maintainability.


221-242: Implemented snapshot and restoration traits

The implementations of Snapshot, FromSnapshotWithParams, and Checkpoint enable state saving and restoration, which are crucial for the hydration process described in the PR objectives.

packages/ciphernode/aggregator/src/publickey_aggregator.rs (6)

3-4: Adding necessary imports for trait implementations

The added imports async_trait::async_trait and traits from data module are required for implementing Snapshot, FromSnapshotWithParams, and Checkpoint traits, enabling state serialization and deserialization.


13-13: Deriving Serialize and Deserialize for PublicKeyAggregatorState

By deriving serde::Serialize and serde::Deserialize, the PublicKeyAggregatorState enum can be serialized and deserialized, facilitating state persistence and recovery.


56-56: Adding DataStore to support checkpointing

The addition of the store: DataStore field to PublicKeyAggregator enables state persistence through checkpointing, enhancing data reliability and recovery mechanisms.


63-70: Introducing PublicKeyAggregatorParams for cleaner initialization

The new PublicKeyAggregatorParams struct encapsulates initialization parameters, promoting cleaner code and better separation of concerns by grouping related configuration data.


79-87: Refactoring new method to utilize Params and State

The new method now accepts PublicKeyAggregatorParams and PublicKeyAggregatorState, streamlining the initialization process and improving code maintainability by reducing parameter clutter.


245-267: Implementing state persistence traits for PublicKeyAggregator

The implementations of Snapshot, FromSnapshotWithParams, and Checkpoint enable the PublicKeyAggregator to persist and restore its state, facilitating data hydration and enhancing fault tolerance.

packages/ciphernode/router/src/hooks.rs (2)

117-150: Handle missing dependencies in hydrate method

In the hydrate method, if dependencies like fhe or meta are missing, the method silently returns Ok(()). This could lead to issues if the caller expects the context to be fully hydrated.

Consider logging a warning or error when essential dependencies are missing during hydration.

-let Some(fhe) = ctx.fhe.clone() else {
-    return Ok(());
+if let Some(fhe) = ctx.fhe.clone() {
+    // proceed with hydration
+} else {
+    self.bus.err(EnclaveErrorType::Hydration, anyhow!("Missing FHE instance during hydration"));
+    return Ok(());
}

247-249: Ensure proper error handling in async methods

In the hydrate methods, ensure that all asynchronous operations are properly awaited and potential errors are handled.

Run the following script to check for unhandled await errors:

✅ Verification successful

All asynchronous operations are properly awaited with error handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find instances where `await` may not be properly handling errors.

# Test: Search for `await` without accompanying error handling.
rg --type rust 'await\?\s*;' -A 2

Length of output: 9877

packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (5)

1-1: LGTM!

The import statement appears correct and necessary for the updated data storage mechanism.


11-12: LGTM!

The added imports from the router module are appropriate for integrating the new features.


46-58: LGTM: Feature additions to E3RequestRouter are properly structured

The E3RequestRouter is correctly configured using the builder pattern with the necessary features. This enhances modularity and maintainability.


85-87: Calls to setup_local_ciphernode correctly handle the new return type

The calls to setup_local_ciphernode have been updated to handle the Result<()> return type using await?, ensuring errors are properly propagated.


32-37: Verify function calls to reflect the updated return type

The setup_local_ciphernode function signature now returns Result<()>. Please ensure that all calls to this function have been updated to handle the Result, using await? or appropriate error handling.

Run the following script to verify the function usage:

✅ Verification successful

Further Verification Needed

The current script is capturing function definitions. Please run the following script to exclude function declarations and accurately identify calls to setup_local_ciphernode that do not handle the Result properly:


Further Verification Required

To ensure all calls to setup_local_ciphernode properly handle the Result, please run the following script which accounts for various formatting scenarios of .await?:


All calls to setup_local_ciphernode properly handle the Result

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all calls to `setup_local_ciphernode` handle the `Result` properly.

# Test: Search for calls to `setup_local_ciphernode` not followed by `.await?`, indicating missing error handling.

rg --type rust 'setup_local_ciphernode\(' -A1 | rg -v '\.await\?'

Length of output: 330


Script:

#!/bin/bash
# Description: Verify that all calls to `setup_local_ciphernode` handle the `Result` properly.

# Exclude function declarations and search for calls without `.await?`
rg --type rust 'setup_local_ciphernode\(' \
    | rg -v 'fn setup_local_ciphernode' \
    | rg -v '\.await\?'

Length of output: 99


Script:

#!/bin/bash
# Description: Comprehensive verification of `setup_local_ciphernode` calls handling `Result`.

# Search for calls to `setup_local_ciphernode` excluding its definition
# Then, check if `.await?` follows, accounting for different formatting

rg --type rust 'setup_local_ciphernode\(' \
    | rg -v 'fn setup_local_ciphernode' \
    | grep -P '(?!\.await\?).*setup_local_ciphernode\('

Length of output: 578

packages/ciphernode/data/src/lib.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/committee_meta.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/committee_meta.rs Outdated Show resolved Hide resolved
packages/ciphernode/enclave_node/src/ciphernode.rs Outdated Show resolved Hide resolved
packages/ciphernode/keyshare/src/keyshare.rs Show resolved Hide resolved
packages/ciphernode/router/src/e3_request_router.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/e3_request_router.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/e3_request_router.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/e3_request_router.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: 0

🧹 Outside diff range and nitpick comments (5)
packages/ciphernode/sortition/src/sortition.rs (3)

86-108: LGTM: Sortition struct updated for hydration support.

The changes to the Sortition struct and its initialization are well-implemented:

  • Addition of list: SortitionModule and store: DataStore fields supports hydration.
  • The new SortitionParams struct allows for flexible initialization.
  • The new() and attach() methods are correctly updated to use SortitionParams.

These changes align well with the PR objectives for implementing hydration and data persistence.

Consider adding documentation comments for the SortitionParams struct to explain its purpose and usage.


130-140: LGTM: Correct implementation of FromSnapshotWithParams trait.

The FromSnapshotWithParams trait implementation for Sortition is well-done:

  • It correctly uses the provided snapshot and SortitionParams for reconstruction.
  • The async implementation allows for potential future extensions with async operations.
  • This implementation supports the hydration feature as required by the PR objectives.

Consider adding error handling for potential failure scenarios during reconstruction, such as invalid snapshot data.


193-195: Remove extra empty lines at the end of the file.

There are three unnecessary empty lines at the end of the file. It's a best practice to have only one newline at the end of a file.

Remove the extra empty lines at the end of the file, leaving only one newline.

packages/ciphernode/data/src/data_store.rs (2)

65-66: Update documentation for snapshot method

The documentation for the snapshot method mentions returning a tuple, but the method actually returns Self::Snapshot. Please update the comment to accurately reflect the method's behavior.

Suggested correction:

-        /// Return a tuple with the first element being the id string of the object and the second
-        /// being a representation of the object's state that is easily serialized by the data store
+        /// Returns a snapshot representing the object's state that is easily serialized by the data store

220-220: Fix typo in error message

The error message in the ensure_root_id method has a typo: "string doesnt start with slash." Please correct "doesnt" to "doesn't".

Apply this diff to fix the typo:

-                return Err(anyhow!("string doesnt start with slash."));
+                return Err(anyhow!("string doesn't start with slash."));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 61cf59c and a3a5c5f.

📒 Files selected for processing (2)
  • packages/ciphernode/data/src/data_store.rs (1 hunks)
  • packages/ciphernode/sortition/src/sortition.rs (5 hunks)
🧰 Additional context used
🔇 Additional comments (7)
packages/ciphernode/sortition/src/sortition.rs (6)

5-6: LGTM: New imports added for enhanced functionality.

The new imports for async_trait and data module components are correctly added to support the new features implemented in this file.


Line range hint 27-40: LGTM: Well-designed SortitionModule struct.

The new SortitionModule struct is well-designed:

  • It encapsulates the node list using a HashSet<String>.
  • Correctly implements Clone, Serialize, and Deserialize for data persistence.
  • Includes appropriate new() and default() implementations.

This addition enhances the modularity and maintainability of the code.


123-128: LGTM: Correct implementation of Snapshot trait.

The Snapshot trait implementation for Sortition is correct and efficient:

  • It returns a clone of self.list as the snapshot.
  • This approach ensures that the snapshot is independent of the original data.
  • The implementation supports the hydration feature as required by the PR objectives.

142-146: LGTM: Correct implementation of Checkpoint trait.

The Checkpoint trait implementation for Sortition is correct:

  • It returns a clone of self.store as required.
  • This approach ensures that the returned DataStore is independent of the original.
  • The implementation supports the data persistence feature as required by the PR objectives.

Line range hint 148-192: LGTM: Existing handler implementations remain correct.

The existing handler implementations for EnclaveEvent, CiphernodeAdded, CiphernodeRemoved, GetHasNode, and GetNodes remain unchanged. This is correct as they don't directly interact with the new hydration features. The handlers continue to provide the necessary functionality for managing the sortition list.


Line range hint 1-195: Overall: Well-implemented hydration and data persistence features.

The changes in this file successfully implement hydration and data persistence for the Sortition module, aligning well with the PR objectives. Key improvements include:

  1. Addition of SortitionModule for better encapsulation of the node list.
  2. Updates to the Sortition struct to include DataStore and use SortitionParams for initialization.
  3. Implementation of Snapshot, FromSnapshotWithParams, and Checkpoint traits to support hydration and data persistence.

The code follows Rust best practices and maintains the existing functionality while adding new features. Minor suggestions for improvement include adding documentation for SortitionParams, considering error handling in FromSnapshotWithParams, and removing extra empty lines at the end of the file.

Great job on implementing these new features!

packages/ciphernode/data/src/data_store.rs (1)

1-250: Overall, the code changes look good

The implementation provides flexible key management and supports serialization and snapshot capabilities effectively.

ryardley and others added 3 commits October 16, 2024 18:21
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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: 5

🧹 Outside diff range and nitpick comments (4)
packages/ciphernode/sortition/src/sortition.rs (4)

Line range hint 27-31: LGTM: SortitionModule enhances modularity.

The new SortitionModule struct effectively encapsulates node storage and supports serialization, which is crucial for the snapshot functionality. This change improves modularity and separation of concerns.

Consider adding a brief documentation comment explaining the purpose of this struct.


90-93: LGTM: SortitionParams improves constructor interface.

The new SortitionParams struct effectively encapsulates the dependencies required for creating a Sortition instance. This change improves the constructor's interface and makes it more flexible for future extensions.

Consider adding a brief documentation comment explaining the purpose of this struct and its fields.


130-140: LGTM: FromSnapshotWithParams trait implementation added.

The new FromSnapshotWithParams trait implementation for Sortition is well-structured and correctly uses SortitionParams to provide the necessary dependencies. This implementation enables the reconstruction of a Sortition instance from a snapshot, supporting the hydration functionality.

Consider adding error handling for potential issues during reconstruction, such as invalid snapshot data.


142-146: LGTM: Checkpoint trait implementation added.

The new Checkpoint trait implementation for Sortition correctly provides access to the DataStore instance, supporting the hydration functionality. This allows other components to interact with the persistent storage associated with the Sortition instance.

Consider adding a brief documentation comment explaining the purpose of this trait implementation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a3a5c5f and 0905d13.

📒 Files selected for processing (4)
  • packages/ciphernode/aggregator/src/lib.rs (1 hunks)
  • packages/ciphernode/data/src/data_store.rs (1 hunks)
  • packages/ciphernode/router/src/committee_meta.rs (1 hunks)
  • packages/ciphernode/sortition/src/sortition.rs (4 hunks)
🧰 Additional context used
📓 Learnings (1)
packages/ciphernode/router/src/committee_meta.rs (1)
Learnt from: ryardley
PR: gnosisguild/enclave#145
File: packages/ciphernode/router/src/committee_meta.rs:43-43
Timestamp: 2024-10-16T09:51:10.038Z
Learning: In `packages/ciphernode/router/src/committee_meta.rs`, avoid suggesting making the `on_event` method in `CommitteMetaFeature` asynchronous or adding error handling for the `write` operation to the data store.
🔇 Additional comments (12)
packages/ciphernode/aggregator/src/lib.rs (1)

3-8: Excellent improvement to module exports!

The change from wildcard exports to explicit re-exports is a positive modification that aligns with Rust best practices. This approach offers several benefits:

  1. Improved clarity: It's now immediately clear which items are available for external use.
  2. Better control over the public API: You can easily manage which items are exposed.
  3. Enhanced maintainability: Changes to the public interface are more visible in version control.

This modification will make the codebase more maintainable and easier to understand for other developers working on the project.

packages/ciphernode/sortition/src/sortition.rs (5)

5-6: LGTM: New imports support hydration implementation.

The added imports from async_trait and data modules are appropriate for implementing the hydration functionality, aligning with the PR objectives for data persistence.


86-88: LGTM: Sortition struct updated for data persistence.

The addition of the store: DataStore field to the Sortition struct is in line with the PR objectives for implementing hydration. This change enables the Sortition instance to manage its own data persistence.


96-102: LGTM: Constructor and attach method updated correctly.

The changes to Sortition::new and Sortition::attach methods are consistent with the new Sortition struct and SortitionParams. The attach method now correctly initializes the Sortition instance with both EventBus and DataStore, aligning with the PR objectives for hydration implementation.

Also applies to: 104-109


123-128: LGTM: Snapshot trait implementation added.

The new Snapshot trait implementation for Sortition is a crucial addition for supporting hydration functionality. It correctly uses the SortitionModule as the snapshot representation, enabling efficient state serialization.


Line range hint 1-193: Overall: Excellent implementation of hydration for Sortition module.

The changes in this file effectively implement hydration and data persistence for the Sortition module, aligning well with the PR objectives. Key improvements include:

  1. Introduction of SortitionModule for better encapsulation of node storage.
  2. Addition of DataStore to the Sortition struct for managing persistence.
  3. Implementation of Snapshot, FromSnapshotWithParams, and Checkpoint traits to support state serialization and reconstruction.
  4. Updated constructor and attach methods to accommodate the new persistence-related components.

These changes enhance the module's ability to manage and persist its state, improving overall system reliability and data management capabilities.

packages/ciphernode/data/src/data_store.rs (2)

7-45: LGTM: IntoKey trait and implementations

The IntoKey trait and its implementations for various types (Vec<String>, Vec<&str>, String, &String, and &str) are well-defined and cover common use cases for keys in a key-value store. The use of join("/") for vector types is a good choice for representing hierarchical keys.


1-248: Overall: Well-designed key-value store implementation with room for minor improvements

The data_store.rs file implements a comprehensive and flexible key-value store with good abstractions and trait definitions. The code is well-structured and follows Rust best practices. Here's a summary of the strengths and areas for improvement:

Strengths:

  1. Flexible key types with the IntoKey trait.
  2. Good use of traits for defining behavior (WithPrefix, Snapshot, Checkpoint).
  3. Async traits for potential I/O operations (FromSnapshotWithParams, FromSnapshot).
  4. Clear separation of concerns between different components.

Areas for improvement:

  1. Error handling: Some methods could benefit from better error propagation and handling.
  2. Performance optimizations: Unnecessary cloning and inefficient string concatenations could be optimized.
  3. UTF-8 handling: Improve the handling of non-UTF-8 data in the WithPrefix implementation for Vec<u8>.

Consider addressing these minor issues to further improve the overall quality and robustness of the implementation.

packages/ciphernode/router/src/committee_meta.rs (4)

7-7: Serialization Traits Added to CommitteeMeta

The implementation correctly derives serde::Serialize and serde::Deserialize for CommitteeMeta, enabling serialization which is essential for data persistence.


14-20: Implementation of CommitteeMetaFeature is Correct

The CommitteeMetaFeature struct and its create method are properly defined, facilitating the integration of the feature within the system.


23-45: Event Handling in on_event Method is Appropriate

The on_event method correctly handles the EnclaveEvent::E3Requested event. It extracts the necessary data and stores the CommitteeMeta information as expected.


47-64: Hydration Logic in hydrate Method is Sound

The asynchronous hydrate method appropriately restores the CommitteeMeta from the snapshot if available, ensuring the state is maintained correctly across sessions.

packages/ciphernode/data/src/data_store.rs Outdated Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Outdated Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Outdated Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Outdated Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Outdated Show resolved Hide resolved
@ryardley ryardley marked this pull request as draft October 16, 2024 21:53
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: 8

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f7cdeb8 and e1c3394.

📒 Files selected for processing (4)
  • packages/ciphernode/data/src/repository.rs (1 hunks)
  • packages/ciphernode/router/src/hooks.rs (1 hunks)
  • packages/ciphernode/router/src/repositories.rs (1 hunks)
  • packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ciphernode/data/src/repository.rs
🧰 Additional context used
📓 Learnings (1)
packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (1)
Learnt from: ryardley
PR: gnosisguild/enclave#145
File: packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs:82-83
Timestamp: 2024-10-22T02:10:34.864Z
Learning: In the file `packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs`, when reviewing test functions like `generate_pk_share`, minor performance optimizations (e.g., minimizing mutex locks) are not a priority.
🔇 Additional comments (4)
packages/ciphernode/router/src/repositories.rs (4)

1-11: LGTM: Imports and struct definition are appropriate.

The imports cover all necessary modules and types for the implementation. The Repositories struct definition encapsulating a DataStore aligns well with the PR objectives for implementing hydration and data persistence.


26-30: LGTM: new method implementation is idiomatic.

The new method provides a clear and idiomatic way to create a Repositories instance, consistent with Rust conventions and the PR objectives.


73-75: LGTM: RepositoriesFactory trait is well-defined.

The RepositoriesFactory trait provides a clear and standard interface for types that can produce Repositories instances. This design allows for flexibility and potential future extensions, aligning with good software design practices.


77-81: LGTM: RepositoriesFactory implementation for DataStore is efficient.

The implementation leverages the From trait to provide a concise and efficient way to create Repositories from a DataStore. This approach is both idiomatic and consistent with the overall design.

packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.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: 10

🧹 Outside diff range and nitpick comments (5)
packages/ciphernode/data/src/in_mem.rs (3)

Line range hint 4-14: LGTM! Consider future-proofing the DataOp enum.

The new GetLog message and DataOp enum are well-structured additions that support the logging feature. The import changes also improve modularity.

Consider adding a Get variant to the DataOp enum to account for potential future logging of read operations:

pub enum DataOp {
    Insert(Insert),
    Get(Get),
}

This change would make the logging more comprehensive and flexible for future requirements.


35-45: LGTM! Consider adding error handling for insertions.

The Handler<Insert> implementation correctly handles data insertion and conditional logging. The use of to_vec() ensures proper data isolation.

Consider adding error handling for potential failed insertions. For example:

impl Handler<Insert> for InMemStore {
    type Result = Result<(), std::io::Error>;
    fn handle(&mut self, event: Insert, _: &mut Self::Context) -> Self::Result {
        match self.db.insert(event.key().to_vec(), event.value().to_vec()) {
            Some(_) | None => {
                if self.capture {
                    self.log.push(DataOp::Insert(event));
                }
                Ok(())
            },
            Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
        }
    }
}

This change would provide more robust error handling and allow callers to react to insertion failures.


Line range hint 47-60: LGTM! Consider optimizing GetLog and adding error handling.

Both Handler<Get> and Handler<GetLog> implementations are functionally correct. The Get handler efficiently retrieves and clones the value from the store.

  1. For Handler<GetLog>, consider implementing pagination or returning a reference to avoid cloning the entire log, which could be inefficient for large logs:
impl Handler<GetLog> for InMemStore {
    type Result = &[DataOp];
    fn handle(&mut self, _: GetLog, _: &mut Self::Context) -> Self::Result {
        &self.log
    }
}
  1. Add error handling to both implementations:
impl Handler<Get> for InMemStore {
    type Result = Result<Option<Vec<u8>>, std::io::Error>;
    fn handle(&mut self, event: Get, _: &mut Self::Context) -> Self::Result {
        Ok(self.db.get(event.key()).cloned())
    }
}

impl Handler<GetLog> for InMemStore {
    type Result = Result<&[DataOp], std::io::Error>;
    fn handle(&mut self, _: GetLog, _: &mut Self::Context) -> Self::Result {
        Ok(&self.log)
    }
}

These changes would improve efficiency and provide more robust error handling.

packages/ciphernode/data/src/sled_store.rs (2)

7-10: Add Documentation Comments to SledStore Struct

Consider adding Rust documentation comments (///) to the SledStore struct to explain its purpose, usage, and any important details. This will improve code readability and help other developers understand its role within the system.


52-58: Remove Unnecessary return Statement

In Rust, the last expression in a function is automatically returned. The explicit return statement at line 52 is unnecessary and can be omitted for cleaner code.

Apply this diff to simplify the code:

-        return match res {
+        match res {
             Ok(value) => value.map(|v| v.to_vec()),
             Err(err) => {
                 self.bus.err(EnclaveErrorType::Data, err);
                 None
             }
         };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e1c3394 and c93e962.

⛔ Files ignored due to path filters (1)
  • packages/ciphernode/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • packages/ciphernode/data/Cargo.toml (1 hunks)
  • packages/ciphernode/data/src/data_store.rs (1 hunks)
  • packages/ciphernode/data/src/in_mem.rs (3 hunks)
  • packages/ciphernode/data/src/sled_store.rs (1 hunks)
  • packages/ciphernode/router/src/hooks.rs (1 hunks)
🧰 Additional context used
📓 Learnings (1)
packages/ciphernode/data/Cargo.toml (1)
Learnt from: ryardley
PR: gnosisguild/enclave#145
File: packages/ciphernode/data/Cargo.toml:0-0
Timestamp: 2024-10-22T02:36:01.448Z
Learning: In `packages/ciphernode/data/Cargo.toml`, `actix-rt` is only used in tests and should remain in `[dev-dependencies]`.
🔇 Additional comments (8)
packages/ciphernode/data/Cargo.toml (2)

10-16: LGTM! The added dependencies align well with the PR objectives.

The new dependencies (enclave-core, anyhow, serde, sled, bincode, tracing, async-trait) are well-suited for implementing hydration and data persistence as outlined in the PR objectives. They provide the necessary tools for error handling, serialization, database operations, tracing, and asynchronous programming. The use of workspace-level version management (workspace = true) is a good practice for maintaining consistency across the project.


18-19: LGTM! The placement of actix-rt in [dev-dependencies] is correct.

The addition of actix-rt as a development dependency is appropriate. As per the previous discussion and the learning from @ryardley, actix-rt is only used in tests and should remain in [dev-dependencies]. This placement ensures that it's available for testing purposes without unnecessarily including it in production builds.

packages/ciphernode/data/src/in_mem.rs (3)

15-19: LGTM! Improved struct naming and added logging support.

The renaming of Data to InMemStore is more descriptive and the addition of log and capture fields effectively supports the new logging feature. The use of BTreeMap for db is appropriate for an ordered key-value store.


21-23: LGTM! Correct Actor implementation.

The Actor trait implementation for InMemStore is correct and allows it to be used within the Actix actor system.


Line range hint 25-33: LGTM! Well-implemented constructor.

The new method for InMemStore is well-implemented. It correctly initializes all fields and provides flexibility for logging behavior through the capture parameter.

packages/ciphernode/data/src/data_store.rs (3)

1-35: LGTM: Imports and message structs are well-defined

The imports are appropriate, and the Insert and Get structs are correctly implemented as message types. The methods returning references instead of cloned values are an efficient design choice.


37-43: LGTM: DataStore struct is well-defined

The DataStore struct is correctly defined with appropriate fields for scope and message recipients, following Actix patterns for actor communication.


47-56: LGTM: DataStore::read method is well-implemented

The read method is correctly implemented as an asynchronous function. It properly handles the retrieval and deserialization of data, with appropriate error handling.

packages/ciphernode/data/src/data_store.rs Outdated Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/router/src/hooks.rs Outdated Show resolved Hide resolved
packages/ciphernode/data/src/sled_store.rs 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: 5

🧹 Outside diff range and nitpick comments (19)
packages/ciphernode/router/src/ciphernode_selector.rs (3)

19-22: LGTM: Method signature updated correctly.

The new method has been appropriately updated to accept references and perform cloning within the method. This change improves flexibility and is consistent with updates in other files.

Consider using the to_owned() method for address in line 23 for consistency:

-    address: address.to_owned(),
+    address: address.to_string(),

38-46: LGTM: Event handling simplified and expanded.

The Handler<EnclaveEvent> implementation has been updated to handle both E3Requested and Shutdown messages, simplifying the event handling process. This change aligns well with the overall shift towards more straightforward event handling in the PR.

Consider using a more specific pattern match to avoid the catch-all case:

 match msg {
     EnclaveEvent::E3Requested { data, .. } => ctx.notify(data),
     EnclaveEvent::Shutdown { data, .. } => ctx.notify(data),
-    _ => (),
 }

This change would make the code more robust against future additions to the EnclaveEvent enum.


Line range hint 48-80: LGTM: E3Requested handling simplified.

The Handler<E3Requested> implementation has been updated to directly handle the E3Requested type, simplifying the logic and improving efficiency. This change aligns well with the overall improvements in event handling across the PR.

Consider using tracing::info! instead of info! for consistency with the shutdown handler:

-                    info!(node = address, "Ciphernode was not selected");
+                    tracing::info!(node = address, "Ciphernode was not selected");
packages/ciphernode/enclave_node/src/ciphernode.rs (2)

57-58: LGTM: Updated method signature with improved flexibility

The changes to the attach method signature are appropriate:

  1. The new data_location parameter allows for flexible data store initialization.
  2. Returning Addr<EventBus> instead of Addr<Self> seems more suitable for the current architecture.

These changes align well with the new data management approach and overall architectural changes.

Consider adding a comment explaining the significance of the data_location parameter and its impact on the data store initialization.


64-70: LGTM: Flexible data store initialization

The new data store initialization logic is well-implemented:

  1. It allows for either SledStore or InMemStore based on the data_location.
  2. The repositories abstraction provides a clean interface for data access.

Consider adding error handling for the case where SledStore::new() fails. You might want to provide a fallback to InMemStore or propagate a more informative error message.

packages/ciphernode/enclave_node/src/aggregator.rs (4)

35-35: LGTM: Improved memory management for EventBus.

The change to pass bus as a reference and clone it inside the struct improves memory management by allowing the caller to retain ownership of the EventBus. This is consistent with the PR objectives of enhancing the overall architecture.

Consider using bus.clone() directly in the struct initialization to avoid an extra variable:

Self {
    e3_manager,
    bus: bus.clone(),
    sortition,
    p2p,
}

Also applies to: 42-42


52-53: LGTM: Signature changes enhance flexibility and align with architecture.

The addition of the data_location parameter and the change in return type to Addr<EventBus> align well with the PR objectives of implementing hydration and centralizing communication through the EventBus.

Consider adding documentation for the data_location parameter to clarify its purpose and expected values.


59-65: LGTM: Data store implementation aligns with hydration objectives.

The implementation of DataStore creation based on the data_location parameter directly addresses the PR objectives of implementing hydration for data persistence. The use of SledStore for persistent storage and InMemStore for in-memory storage provides flexibility, and creating repositories from the store aligns with the goal of simplifying the API and enhancing type safety.

Consider adding error handling for the case where SledStore::new() fails:

let store: DataStore = match data_location {
    Some(loc) => match SledStore::new(&bus, loc) {
        Ok(sled_store) => (&sled_store.start()).into(),
        Err(e) => return Err(anyhow::anyhow!("Failed to create SledStore: {}", e)),
    },
    None => (&InMemStore::new(true).start()).into(),
};

80-85: LGTM: Feature-based architecture and consistent bus handling.

The shift to a feature-based architecture in E3RequestRouter aligns well with the PR objectives and improves modularity. The consistent use of passing a reference to bus in MainAggregator::new() improves memory management.

For consistency, consider updating the E3RequestRouter::builder call to use a reference to bus:

let e3_manager = E3RequestRouter::builder(&bus, store)
    .add_feature(FheFeature::create(&bus, &rng))
    .add_feature(PublicKeyAggregatorFeature::create(&bus, &sortition))
    .add_feature(PlaintextAggregatorFeature::create(&bus, &sortition))
    .build()
    .await?;

Also applies to: 100-101

packages/ciphernode/evm/src/ciphernode_registry_sol.rs (2)

Line range hint 65-93: LGTM: extractor function improvements

The changes to the extractor function are good:

  1. Making it public allows for better modularity.
  2. Returning None on errors instead of panicking is a more graceful approach.

Consider using tracing::warn! instead of error! for parsing issues, as they might not always indicate a critical problem.


98-105: LGTM: Updated CiphernodeRegistrySolReader::attach method

The changes to the attach method are well-aligned with the new event handling approach:

  1. Taking a reference to Addr<EventBus> is more flexible.
  2. Returning Addr<EvmEventReader> is consistent with the new implementation.
  3. Using EvmEventReader::attach simplifies the code.

Consider adding a brief comment explaining the purpose of this method, as it now acts more like a factory for EvmEventReader.

packages/ciphernode/evm/src/enclave_sol_writer.rs (1)

35-43: LGTM: Improved memory efficiency and added RPC URL validation.

The changes to the new method are good:

  • Using references for bus and signer improves memory efficiency.
  • Adding ensure_http_rpc enhances input validation.
  • Cloning bus allows for multiple ownership, which is often necessary in the actor model.

Minor suggestion: Consider using bus: bus.clone() instead of bus: bus.clone(), to be consistent with the no-trailing-comma style used elsewhere in the struct initialization.

packages/ciphernode/evm/src/helpers.rs (3)

122-122: Improved thread safety with Arc

The change to use &Arc<PrivateKeySigner> for the signer parameter is a good improvement for thread safety and memory management. This aligns well with best practices for shared ownership in concurrent scenarios.

Consider adding a brief comment explaining the rationale behind using Arc here, as it might not be immediately obvious to all developers why this change was made.

Also applies to: 130-130


141-148: Approved: ensure_http_rpc function

The ensure_http_rpc function effectively converts WebSocket URLs to HTTP URLs, which aligns with the PR objectives. It correctly handles both "ws://" and "wss://" protocols.

Consider using a match statement for slightly more concise and idiomatic Rust code:

pub fn ensure_http_rpc(rpc_url: &str) -> String {
    match rpc_url {
        url if url.starts_with("ws://") => url.replacen("ws://", "http://", 1),
        url if url.starts_with("wss://") => url.replacen("wss://", "https://", 1),
        _ => rpc_url.to_string(),
    }
}

This suggestion maintains the same functionality while potentially improving readability.


159-177: Approved: Comprehensive test coverage for URL conversion functions

The new test module provides excellent coverage for both ensure_http_rpc and ensure_ws_rpc functions. All possible scenarios are tested, which is crucial for ensuring the reliability of these utility functions.

To further enhance the tests, consider adding a negative test case for each function. For example:

#[test]
fn test_ensure_http_rpc_with_invalid_input() {
    assert_eq!(ensure_http_rpc("invalid://foo.com"), "invalid://foo.com");
}

#[test]
fn test_ensure_ws_rpc_with_invalid_input() {
    assert_eq!(ensure_ws_rpc("invalid://foo.com"), "invalid://foo.com");
}

These additional tests would confirm that the functions handle unexpected inputs gracefully.

packages/ciphernode/router/src/e3_request_router.rs (1)

176-199: Good implementation of snapshot and checkpoint functionality

The addition of E3RequestRouterSnapshot and the implementations of Snapshot and Checkpoint traits for E3RequestRouter are well-done. These changes enable state persistence and recovery, which are crucial for system reliability.

Consider using iter().cloned().collect() instead of keys().cloned().collect() for slightly better performance:

-let contexts = self.contexts.keys().cloned().collect();
+let contexts = self.contexts.iter().map(|(k, _)| k.clone()).collect();
packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (2)

17-17: Consider using a more specific import for Address

Instead of importing the entire alloy::primitives module, consider importing Address directly for better clarity.

-use alloy::{primitives::Address, signers::k256::sha2::digest::Reset};
+use alloy::primitives::Address;
+use alloy::signers::k256::sha2::digest::Reset;

180-185: Consider adding a check for total < len

The pad_end function could potentially panic if total is less than input.len(). Consider adding a check to handle this case.

 fn pad_end(input: &[u64], pad: u64, total: usize) -> Vec<u64> {
     let len = input.len();
+    if total < len {
+        return input[..total].to_vec();
+    }
     let mut cop = input.to_vec();
     cop.extend(std::iter::repeat(pad).take(total - len));
     cop
 }
packages/ciphernode/router/src/hooks.rs (1)

17-17: Reminder to address the TODO comment

There's a TODO comment on line 17 indicating:

/// TODO: move these to each package with access on MyStruct::launcher()

Consider implementing this change to improve code organization and maintainability by placing each feature in its respective package.

Would you like assistance in creating a plan to refactor these features or opening a GitHub issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c93e962 and 4344754.

📒 Files selected for processing (15)
  • packages/ciphernode/data/src/data_store.rs (1 hunks)
  • packages/ciphernode/enclave_node/src/aggregator.rs (5 hunks)
  • packages/ciphernode/enclave_node/src/ciphernode.rs (5 hunks)
  • packages/ciphernode/evm/src/ciphernode_registry_sol.rs (3 hunks)
  • packages/ciphernode/evm/src/enclave_sol.rs (1 hunks)
  • packages/ciphernode/evm/src/enclave_sol_reader.rs (3 hunks)
  • packages/ciphernode/evm/src/enclave_sol_writer.rs (5 hunks)
  • packages/ciphernode/evm/src/event_reader.rs (1 hunks)
  • packages/ciphernode/evm/src/helpers.rs (4 hunks)
  • packages/ciphernode/evm/src/registry_filter_sol.rs (6 hunks)
  • packages/ciphernode/router/src/ciphernode_selector.rs (3 hunks)
  • packages/ciphernode/router/src/e3_request_router.rs (5 hunks)
  • packages/ciphernode/router/src/hooks.rs (1 hunks)
  • packages/ciphernode/sortition/src/sortition.rs (4 hunks)
  • packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ciphernode/evm/src/registry_filter_sol.rs
🧰 Additional context used
📓 Learnings (1)
packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (3)
Learnt from: ryardley
PR: gnosisguild/enclave#145
File: packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs:82-83
Timestamp: 2024-10-22T02:10:34.864Z
Learning: In the file `packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs`, when reviewing test functions like `generate_pk_share`, minor performance optimizations (e.g., minimizing mutex locks) are not a priority.
Learnt from: ryardley
PR: gnosisguild/enclave#133
File: packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs:137-139
Timestamp: 2024-10-08T19:45:18.209Z
Learning: In `packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs`, using the same RNG instance `rng_test` for generating multiple key shares without advancing its state is acceptable.
Learnt from: ryardley
PR: gnosisguild/enclave#133
File: packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs:137-139
Timestamp: 2024-10-03T23:02:41.732Z
Learning: In `packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs`, using the same RNG instance `rng_test` for generating multiple key shares without advancing its state is acceptable.
🔇 Additional comments (71)
packages/ciphernode/evm/src/enclave_sol.rs (1)

12-19: Approve changes to attach method signature and implementation.

The updates to the attach method, including the use of references for bus and signer parameters, are improvements that can lead to better memory management and reduced cloning. These changes align with the broader updates mentioned in the PR objectives and AI summary.

To ensure consistency across the codebase, let's verify similar changes in related files:

This script will help verify that similar changes have been made consistently across related files and identify any remaining instances that might need updating.

packages/ciphernode/router/src/ciphernode_selector.rs (3)

4-4: LGTM: Import statement updated correctly.

The import statement has been appropriately updated to include E3Requested and Shutdown, which aligns with the new event types introduced in this PR.


27-31: LGTM: Method updated correctly with new subscription.

The attach method has been appropriately updated to accept references, maintaining consistency with the new method. The addition of the "Shutdown" subscription aligns well with the new shutdown handling capability introduced in this PR.


82-88: LGTM: Shutdown handling added.

The new Handler<Shutdown> implementation adds proper shutdown handling to the CiphernodeSelector actor. This addition improves the actor's lifecycle management and aligns with the introduction of the Shutdown event across various components in the PR.

packages/ciphernode/evm/src/enclave_sol_reader.rs (3)

1-7: LGTM: Import changes reflect architectural shift

The changes in imports, particularly the addition of EvmEventReader and removal of ReadonlyProvider, indicate a shift in the event reading mechanism. This aligns with the broader changes in the module's architecture.


52-52: LGTM: extractor function made public

The extractor function has been made public, allowing for external access. This change aligns with the new architecture and maintains the existing logic for event extraction.


80-80: Consider further simplification of EnclaveSolReader

The EnclaveSolReader struct is now empty, suggesting it's used as a namespace for associated functions. This aligns with the removal of the actor implementation.

As previously suggested, re-evaluate the necessity of the EnclaveSolReader struct. Consider whether it can be replaced with a module or removed entirely if it's no longer providing value beyond grouping functions.

packages/ciphernode/enclave_node/src/ciphernode.rs (5)

4-4: LGTM: Import changes align with new architecture

The new imports for DataStore, InMemStore, SledStore, FheFeature, KeyshareFeature, and RepositoriesFactory are consistent with the transition to a feature-based architecture and the introduction of DataStore for data management.

Also applies to: 11-13


26-26: LGTM: Updated data field type

The change from Addr<Data> to DataStore for the data field is consistent with the new data management approach using DataStore.


37-37: LGTM: Updated constructor parameter type

The change of the data parameter type from Addr<Data> to DataStore in the new method is consistent with the struct field change and supports the new data management approach.


97-107: LGTM: Updated MainCiphernode initialization

The changes in the MainCiphernode::new call are consistent with the updates to the method signature and the overall architectural changes:

  1. The order and number of parameters have been adjusted correctly.
  2. The use of store instead of data aligns with the transition to DataStore.

These changes ensure that the MainCiphernode is initialized correctly with the new data management approach.


86-90: LGTM: Improved E3RequestRouter initialization with feature-based architecture

The new initialization of E3RequestRouter using a builder pattern with feature additions is a significant improvement:

  1. It allows for more flexible and modular configuration.
  2. The use of FheFeature and KeyshareFeature aligns well with the new feature-based architecture.

Ensure that any errors arising from the asynchronous .build().await? are properly propagated and handled. Consider adding specific error handling for this asynchronous operation.

packages/ciphernode/enclave_node/src/aggregator.rs (1)

3-3: LGTM: Import changes align with PR objectives.

The new imports for DataStore, InMemStore, and SledStore, as well as the updated imports from the router module, align well with the PR objectives of implementing hydration for data persistence and shifting towards a feature-based architecture.

Also applies to: 12-15

packages/ciphernode/evm/src/ciphernode_registry_sol.rs (2)

1-1: LGTM: Import of EvmEventReader added

The addition of the EvmEventReader import aligns with the changes in the attach method, which now returns Addr<EvmEventReader>.


95-96: LGTM: Simplified CiphernodeRegistrySolReader struct

The simplification of CiphernodeRegistrySolReader to a unit struct is appropriate given the removal of its fields and new method. This change addresses the previous suggestion to refactor this struct since it no longer contains any fields.

packages/ciphernode/data/src/data_store.rs (4)

1-7: LGTM: Imports are appropriate and concise.

The imports cover all necessary dependencies for the implemented functionality, including error handling, serialization, and actor-based communication.


9-24: LGTM: Insert struct is well-implemented.

The Insert struct is correctly implemented with appropriate trait derivations. The new() method uses the IntoKey trait for flexible key types, and the key() and value() methods efficiently return references to avoid unnecessary cloning.


26-37: LGTM: Get struct is well-implemented.

The Get struct is correctly implemented with appropriate trait derivations. The new() method uses the IntoKey trait for flexible key types, and the key() method efficiently returns a reference to avoid unnecessary cloning.


1-137: Overall, the implementation is well-structured and efficient, with some room for improvement.

The data_store.rs file implements a robust key-value data store using Actix for message handling. The code makes good use of Rust's type system and the actor model. Here are the main points:

  1. The Insert and Get message types are well-implemented with appropriate trait derivations and efficient methods.
  2. The DataStore struct provides a comprehensive interface for interacting with the data store.
  3. There are a few areas where performance could be improved, particularly in the scope and get_scope methods.
  4. Error handling in the write method could be more explicit to allow callers to handle errors.
  5. There's some code duplication in the From implementations that could be reduced using a macro.

Addressing these points would further enhance the quality and maintainability of the code.

packages/ciphernode/evm/src/enclave_sol_writer.rs (5)

4-4: LGTM: Import for RPC URL validation added.

The addition of ensure_http_rpc import is a good practice for validating the RPC URL before use.


15-15: LGTM: Import for Shutdown message added.

The addition of the Shutdown import aligns with the PR objective of implementing graceful termination.


48-60: LGTM: Improved method signature and added Shutdown event subscription.

The changes to the attach method are good:

  • Using references in the method signature is consistent with the new method changes.
  • Adding a subscription to the "Shutdown" event aligns with the PR objectives for implementing graceful termination.

80-80: Consider simplifying the Shutdown event handling.

The addition of the EnclaveEvent::Shutdown match arm is good for implementing graceful termination. However, as suggested in a previous review comment, consider simplifying this to directly call ctx.stop() instead of notifying self with the data.


111-116: LGTM: Shutdown handler implemented.

The addition of the Handler<Shutdown> implementation for EnclaveSolWriter is good:

  • It properly implements the shutdown logic by stopping the actor's context.
  • This is consistent with the PR objectives for implementing graceful termination.
  • The implementation is simple and straightforward.
packages/ciphernode/sortition/src/sortition.rs (9)

5-6: LGTM: New imports for async traits and data management.

The added imports for async_trait and data are appropriate for implementing hydration and data persistence features as outlined in the PR objectives.


Line range hint 27-88: LGTM: New SortitionModule struct and updated Sortition struct.

The introduction of SortitionModule and the updates to Sortition improve modularity and align with the PR objectives for implementing hydration and data persistence. The SortitionList<String> implementation ensures that core node management functionality is maintained.


89-92: LGTM: New SortitionParams struct.

The SortitionParams struct effectively encapsulates the parameters needed for creating a Sortition instance, including the Repository<SortitionModule> for data persistence. This aligns well with the PR objectives.


96-100: LGTM: Updated Sortition::new method.

The new method now accepts SortitionParams, allowing for proper dependency injection of both the event bus and the data store. This change aligns well with the PR objectives for implementing hydration and data persistence.


104-109: LGTM: Updated Sortition::attach method.

The attach method now properly initializes a Sortition instance with both the event bus and data store. This change aligns well with the PR objectives for implementing hydration and data persistence.


123-128: LGTM: New Snapshot trait implementation for Sortition.

The Snapshot trait implementation for Sortition allows for creating a snapshot of the Sortition state. This aligns well with the PR objectives for implementing hydration and data persistence.


130-140: LGTM: New FromSnapshotWithParams trait implementation for Sortition.

The FromSnapshotWithParams trait implementation for Sortition enables the reconstruction of Sortition state from a snapshot and parameters. This aligns well with the PR objectives for implementing hydration and data persistence. The use of async_trait is appropriate for handling potential asynchronous operations during reconstruction.


142-146: LGTM: New Checkpoint trait implementation for Sortition.

The Checkpoint trait implementation for Sortition allows for retrieving the Repository<SortitionModule> from Sortition. This aligns well with the PR objectives for implementing hydration and data persistence, providing a way to access the underlying data store.


Line range hint 1-147: Overall: Excellent implementation of hydration and data persistence for Sortition.

The changes in this file successfully implement hydration and data persistence for the Sortition module, aligning well with the PR objectives. The introduction of SortitionModule, SortitionParams, and the implementations of Snapshot, FromSnapshotWithParams, and Checkpoint traits provide a robust framework for state management and serialization.

These changes are consistent with the broader restructuring effort across multiple files in the PR, as mentioned in the AI-generated summary. The new structure enhances the module's ability to manage and retain its state, supporting the goals of improved data persistence capabilities.

Great job on implementing these features while maintaining the core functionality of the Sortition module!

packages/ciphernode/evm/src/helpers.rs (3)

18-18: Excellent implementation of graceful shutdown mechanism

The changes to the stream_from_evm function effectively implement a graceful shutdown mechanism. The use of the select! macro allows for concurrent handling of incoming logs and the shutdown signal, which aligns well with the PR objective of cleaning up on SIGTERM (issue #149). This improvement enhances the robustness of the streaming process.

Also applies to: 26-26, 36-57, 63-64


150-157: Approved: ensure_ws_rpc function

The ensure_ws_rpc function effectively converts HTTP URLs to WebSocket URLs, complementing the ensure_http_rpc function. It correctly handles both "http://" and "https://" protocols.

As suggested for the ensure_http_rpc function, consider using a match statement here as well for consistency and potentially improved readability.


Line range hint 1-177: Overall: Excellent improvements to EVM helpers

The changes in this file significantly enhance the functionality and robustness of the EVM helpers. Key improvements include:

  1. Implementation of a graceful shutdown mechanism in stream_from_evm.
  2. Enhanced thread safety in create_provider_with_signer.
  3. Addition of URL protocol conversion functions ensure_http_rpc and ensure_ws_rpc.
  4. Comprehensive test coverage for the new functions.

These changes align well with the PR objectives, particularly addressing the cleanup on SIGTERM (issue #149) and improving overall code quality. The minor suggestions provided in the review comments could further refine the implementation.

Great work on these improvements!

packages/ciphernode/router/src/e3_request_router.rs (6)

Line range hint 1-53: Excellent architectural improvements!

The transition to a feature-based architecture with the introduction of the E3Feature trait is a significant improvement. This design choice enhances modularity, extensibility, and maintainability of the codebase. The use of the #[async_trait] attribute for the hydrate method is correct and allows for asynchronous operations in trait methods.


Line range hint 110-163: Improved event handling with feature-based system

The new implementation of Handler<EnclaveEvent> for E3RequestRouter provides better separation of concerns by delegating event handling to features. The early check for the shutdown event is a good practice for graceful termination.

However, there's a potential performance issue:

[performance]
Consider optimizing the feature iteration to avoid cloning self.features in each event handling:

-for feature in self.features.clone().iter() {
+for feature in self.features.iter() {
    feature.on_event(context, &msg);
}

166-174: Improve error handling in shutdown process

The Handler<Shutdown> implementation ensures that all contexts are notified of the shutdown event, which is good for graceful termination. However, there's room for improvement in error handling.
[error_handling]
Consider adding error handling for the forward_message_now calls:

for (_, ctx) in self.contexts.iter() {
-    ctx.forward_message_now(&shutdown_evt)
+    if let Err(e) = ctx.forward_message_now(&shutdown_evt) {
+        log::error!("Failed to forward shutdown event: {:?}", e);
+        // Consider additional error handling or recovery steps
+    }
}

201-235: Enhance error handling in from_snapshot method

The FromSnapshotWithParams implementation for E3RequestRouter is a crucial addition for state recovery. However, the current implementation silently ignores errors during context restoration, which could lead to incomplete state recovery without proper notification.
[error_handling]
Consider collecting and logging errors during context restoration:

+let mut restoration_errors = Vec::new();
 for e3_id in snapshot.contexts {
     let Some(ctx_snapshot) = repositories.context(&e3_id).read().await? else {
+        restoration_errors.push(format!("Missing snapshot for context {}", e3_id));
         continue;
     };

-    contexts.insert(
-        e3_id.clone(),
-        E3RequestContext::from_snapshot(
-            E3RequestContextParams {
-                store: repositories.context(&e3_id),
-                e3_id: e3_id.clone(),
-                features: params.features.clone(),
-            },
-            ctx_snapshot,
-        )
-        .await?,
-    );
+    match E3RequestContext::from_snapshot(
+        E3RequestContextParams {
+            store: repositories.context(&e3_id),
+            e3_id: e3_id.clone(),
+            features: params.features.clone(),
+        },
+        ctx_snapshot,
+    ).await {
+        Ok(context) => { contexts.insert(e3_id.clone(), context); }
+        Err(e) => restoration_errors.push(format!("Failed to restore context {}: {:?}", e3_id, e)),
+    }
 }

+if !restoration_errors.is_empty() {
+    log::warn!("Errors during context restoration: {:?}", restoration_errors);
+}

237-272: Improved E3RequestRouterBuilder with snapshot support

The updates to E3RequestRouterBuilder align well with the new feature-based and snapshot-aware architecture. The default addition of CommitteeMetaFeature ensures that all routers have this essential feature.

[error_handling]
Consider adding error handling for feature addition:

-pub fn add_feature(mut self, listener: Box<dyn E3Feature>) -> Self {
-    self.features.push(listener);
-    self
+pub fn add_feature(mut self, listener: Box<dyn E3Feature>) -> Result<Self> {
+    // Perform any necessary validation on the feature
+    if /* feature is valid */ {
+        self.features.push(listener);
+        Ok(self)
+    } else {
+        Err(anyhow!("Invalid feature"))
+    }
 }

This change would allow for validation of features before they're added and provide better error handling.


60-100: Great improvements to E3RequestRouter structure and initialization!

The updated E3RequestRouter struct and the introduction of E3RequestRouterParams enhance flexibility and separation of concerns. The use of Arc<Vec<Box<dyn E3Feature>>> is an efficient way to share features across contexts.

Consider adding error handling in the from_params method:

packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (22)

1-12: LGTM: Updated imports and type definitions

The new imports and type definitions align well with the changes in the test file. They reflect the addition of new features and components, such as DataStore, InMemStore, and various router features.


20-21: LGTM: Updated FHE imports

The imports for FHE-related types and traits have been updated to include necessary components for the tests.


32-38: LGTM: New LocalCiphernodeTuple type definition

The LocalCiphernodeTuple type definition provides a clear structure for the return value of the setup_local_ciphernode function.


40-65: LGTM: Updated setup_local_ciphernode function

The setup_local_ciphernode function has been updated to include the new DataStore and router features. The changes align well with the new architecture and provide a good setup for the tests.


69-73: LGTM: Updated generate_pk_share function

The generate_pk_share function has been updated to include the addr parameter and return a Result<PkSkShareTuple>. This change aligns with the new requirements and improves error handling.

Also applies to: 76-76


79-90: LGTM: New generate_pk_shares function

The generate_pk_shares function is a helpful addition that generates multiple public key shares. It's well-implemented and uses the generate_pk_share function effectively.


92-96: LGTM: New create_random_eth_addrs function

The create_random_eth_addrs function is a useful helper for generating random Ethereum addresses for testing purposes.


98-104: LGTM: New RNG and seed creation functions

The create_shared_rng_from_u64 and create_seed_from_u64 functions provide consistent ways to create RNGs and seeds for testing, which is good for reproducibility.


106-123: LGTM: New create_crp_bytes_params function

The create_crp_bytes_params function encapsulates the creation of CRP bytes and parameters, which is useful for setting up the test environment.


125-151: LGTM: New AddToCommittee struct and implementation

The AddToCommittee struct and its implementation provide a clean way to add addresses to the committee and create corresponding events. This is a good abstraction for the test setup.


153-166: LGTM: New create_local_ciphernodes function

The create_local_ciphernodes function is a helpful addition for setting up multiple local ciphernodes in the test environment.


168-178: LGTM: New encrypt_ciphertext function

The encrypt_ciphertext function encapsulates the encryption logic and returns both the ciphertext and the expected serialized output, which is useful for testing.


187-195: LGTM: New add_ciphernodes function

The add_ciphernodes function is a useful helper for adding multiple ciphernodes to the test environment and generating the corresponding events.


197-200: LGTM: New type aliases

The PkSkShareTuple and DecryptionShareTuple type aliases improve code readability.


201-207: LGTM: New aggregate_public_key function

The aggregate_public_key function provides a clean way to aggregate public keys from the shares.


209-223: LGTM: New to_decryption_shares function

The to_decryption_shares function is well-implemented and provides a way to generate decryption shares from the public key shares.


225-236: LGTM: New to_keyshare_events function

The to_keyshare_events function is a helpful utility for creating keyshare events from the generated shares.


238-251: LGTM: New to_decryptionshare_events function

The to_decryptionshare_events function is well-implemented and provides a way to create decryption share events from the decryption shares.


253-269: LGTM: New get_common_setup function

The get_common_setup function encapsulates the common setup logic for the tests, which is good for reducing code duplication and improving maintainability.


271-375: LGTM: Updated test_public_key_aggregation_and_decryption test

The test_public_key_aggregation_and_decryption test has been significantly updated to use the new helper functions and test the updated functionality. The test covers the key aspects of public key aggregation and decryption.


377-452: LGTM: New test_stopped_keyshares_retain_state test

The test_stopped_keyshares_retain_state test is a valuable addition that verifies the persistence of keyshare state after a shutdown event. This test helps ensure the robustness of the system in handling state persistence.


Line range hint 1-452: Overall: Well-structured and comprehensive test suite

The updates to this test file are thorough and well-implemented. They cover the new features and components introduced in the system, such as the DataStore, router features, and improved event handling. The new helper functions and type definitions improve code readability and reduce duplication. The tests provide good coverage for the public key aggregation, decryption, and state persistence functionality.

Some minor suggestions for improvement:

  1. Consider adding more detailed comments for complex test scenarios to improve maintainability.
  2. Look into adding more edge cases and error scenarios to further improve test coverage.

Overall, great job on updating and expanding the test suite!

packages/ciphernode/evm/src/event_reader.rs (3)

66-69: Stop the actor context if provider is already taken

When self.provider is None, the actor cannot proceed correctly. Simply returning might leave the actor running in an invalid state. Consider stopping the actor context with ctx.stop() to gracefully shut down the actor.


74-77: Stop the actor context if shutdown has already been called

If self.shutdown_rx is None, it indicates that the shutdown channel has already been consumed. Returning without stopping the actor may leave the actor in an inconsistent state. Consider calling ctx.stop() to gracefully shut down the actor.


79-82: Handle potential errors in the spawned async task

Add error handling to the spawned task to ensure that any errors during event streaming are properly logged, preventing silent failures.

packages/ciphernode/router/src/hooks.rs (4)

18-85: Code Review: FheFeature implementation

The FheFeature struct and its implementation correctly handle the initialization and hydration of the FHE component. Error handling is properly managed, and dependencies are correctly utilized.


87-177: Code Review: KeyshareFeature implementation

The KeyshareFeature struct appropriately handles the creation of the keyshare upon receiving the CiphernodeSelected event. The hydration method manages dependencies and error handling correctly, aligning with the system's requirements.


179-294: Code Review: PlaintextAggregatorFeature implementation

The implementation of PlaintextAggregatorFeature effectively manages the initialization and hydration of the plaintext aggregator. Dependency checks and error reporting are correctly handled, ensuring robustness in the feature's lifecycle.


296-409: Code Review: PublicKeyAggregatorFeature implementation

The PublicKeyAggregatorFeature struct and its methods correctly handle the setup and hydration of the public key aggregator. Dependency management and error handling are appropriately implemented, maintaining consistency with the other features.

packages/ciphernode/data/src/data_store.rs Show resolved Hide resolved
packages/ciphernode/data/src/data_store.rs Show resolved Hide resolved
packages/ciphernode/evm/src/event_reader.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/ciphernode/data/src/sled_store.rs (1)

1-61: Overall implementation is solid with room for improvement.

The SledStore implementation provides a good foundation for database operations using Sled, aligning with the PR objectives for data persistence. The code structure is clear, and error handling is generally well-implemented.

Key strengths:

  1. Proper integration with the Actix framework.
  2. Use of anyhow for comprehensive error handling.
  3. Implementation of both Insert and Get operations.

Areas for improvement:

  1. Consistency in error handling between Insert and Get handlers.
  2. Better handling of binary keys in error messages.
  3. Propagation of errors to callers for more flexible error management.

Next steps:

  1. Implement the suggested improvements for both Insert and Get handlers.
  2. Consider adding unit tests to ensure the reliability of the SledStore operations.
  3. Ensure that this implementation integrates well with the broader hydration strategy outlined in the PR objectives.
packages/ciphernode/router/src/e3_request_router.rs (1)

198-232: Consider enhancing error handling and logging in from_snapshot

The from_snapshot implementation for E3RequestRouter is well-structured and correctly restores the router's state. However, consider enhancing error handling and adding logging for better diagnostics:

  1. Log when a context snapshot is missing (line 208).
  2. Consider collecting and reporting any errors encountered during context restoration, rather than silently continuing.

Example:

let mut errors = Vec::new();
for e3_id in snapshot.contexts {
    match repositories.context(&e3_id).read().await {
        Ok(Some(ctx_snapshot)) => {
            // ... (existing code to restore context)
        },
        Ok(None) => {
            log::warn!("Missing context snapshot for e3_id: {}", e3_id);
            errors.push(anyhow!("Missing context for e3_id: {}", e3_id));
        },
        Err(e) => {
            log::error!("Error reading context snapshot for e3_id: {}: {}", e3_id, e);
            errors.push(e);
        }
    }
}

if !errors.is_empty() {
    log::warn!("Encountered {} errors during snapshot restoration", errors.len());
    // Decide whether to return an error or continue with partial restoration
}

This approach provides more visibility into any issues during the snapshot restoration process.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 4344754 and e3962e2.

📒 Files selected for processing (6)
  • packages/ciphernode/data/src/into_key.rs (1 hunks)
  • packages/ciphernode/data/src/sled_store.rs (1 hunks)
  • packages/ciphernode/data/src/snapshot.rs (1 hunks)
  • packages/ciphernode/enclave_node/src/shutdown.rs (1 hunks)
  • packages/ciphernode/evm/src/event_reader.rs (1 hunks)
  • packages/ciphernode/router/src/e3_request_router.rs (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/ciphernode/data/src/into_key.rs
  • packages/ciphernode/data/src/snapshot.rs
  • packages/ciphernode/enclave_node/src/shutdown.rs
  • packages/ciphernode/evm/src/event_reader.rs
🧰 Additional context used
📓 Learnings (1)
packages/ciphernode/router/src/e3_request_router.rs (2)
Learnt from: ryardley
PR: gnosisguild/enclave#145
File: packages/ciphernode/router/src/e3_request_router.rs:202-235
Timestamp: 2024-10-22T03:47:04.014Z
Learning: In `packages/ciphernode/router/src/e3_request_router.rs`, within the `E3RequestRouter::from_snapshot` method, errors during context restoration propagate upwards due to the `?` operator, and skipping contexts when `repositories.context(&e3_id).read().await?` returns `Ok(None)` is acceptable, as missing snapshots are expected.
Learnt from: ryardley
PR: gnosisguild/enclave#145
File: packages/ciphernode/router/src/e3_request_router.rs:126-133
Timestamp: 2024-10-22T03:44:33.301Z
Learning: In `E3RequestRouter::handle` method in `e3_request_router.rs`, `self.repository()` cannot fail, so it's not necessary to handle errors when accessing repositories via `self.repository().repositories()`.
🔇 Additional comments (10)
packages/ciphernode/data/src/sled_store.rs (4)

1-10: LGTM: Imports and struct definition are appropriate.

The imports cover all necessary components, and the SledStore struct is well-defined with the required fields for database operations and event bus communication.


12-25: LGTM: Actor implementation and constructor are well-implemented.

The Actor trait implementation is correct, and the new method effectively creates a SledStore instance. The error handling has been improved as per the previous suggestion, providing more detailed context when opening the database fails.


27-40: 🛠️ Refactor suggestion

Consider improving error handling in the Insert handler.

While the current implementation is functional, it could be enhanced for better error handling and consistency with the Get handler. Consider the following improvements:

  1. Change the result type to Result<()> to propagate errors to the caller.
  2. Return the error after sending it to the event bus, allowing the caller to handle it if needed.

This change would improve error handling and make the Insert handler more consistent with the Get handler.

Here's a suggested implementation:

impl Handler<Insert> for SledStore {
    type Result = Result<()>;

    fn handle(&mut self, event: Insert, _: &mut Self::Context) -> Self::Result {
        self.db
            .insert(event.key(), event.value().to_vec())
            .context("Could not insert data into db")
            .map_err(|err| {
                self.bus.err(EnclaveErrorType::Data, err.clone());
                err
            })
    }
}

42-61: 🛠️ Refactor suggestion

Improve key handling and error propagation in the Get handler.

The current implementation has a few areas for improvement:

  1. Key conversion: Using String::from_utf8_lossy may not be appropriate for binary keys. Consider using a hexadecimal representation instead.
  2. Error handling: Return a Result<Option<Vec<u8>>> to propagate errors to the caller, allowing for better error handling.

Here's a suggested implementation:

use hex;

impl Handler<Get> for SledStore {
    type Result = Result<Option<Vec<u8>>>;

    fn handle(&mut self, event: Get, _: &mut Self::Context) -> Self::Result {
        let key = event.key();
        let hex_key = hex::encode(&key);
        self.db
            .get(key)
            .with_context(|| format!("Failed to fetch key {}", hex_key))
            .map_err(|err| {
                self.bus.err(EnclaveErrorType::Data, err.clone());
                err
            })
            .map(|opt| opt.map(|v| v.to_vec()))
    }
}

This implementation addresses both the key handling and error propagation issues.

packages/ciphernode/router/src/e3_request_router.rs (6)

43-51: LGTM: Well-designed E3Feature trait

The new E3Feature trait is well-structured and properly uses the #[async_trait] attribute for the async hydrate method. This design allows for a more modular and extensible approach to handling events and hydration.


57-71: LGTM: Improved E3RequestRouter structure

The changes to E3RequestRouter and the introduction of E3RequestRouterParams reflect a well-thought-out transition to a feature-based system. The use of Arc<Vec<Box<dyn E3Feature>>> allows for efficient, thread-safe sharing of features, and the addition of the store field integrates the new DataStore functionality.


Line range hint 107-160: LGTM: Improved event handling with feature-based system

The updated Handler<EnclaveEvent> implementation effectively utilizes the new feature-based system. The logic for handling different event types is clear and modular. The addition of a checkpoint call after handling each event ensures data persistence, which is a good practice for maintaining system state.


Line range hint 1-268: Summary: Significant improvements with some minor enhancement opportunities

The changes to E3RequestRouter and related components represent a substantial improvement in the code's architecture. The transition to a feature-based system and integration with DataStore align well with the PR objectives and should enhance modularity and extensibility.

Key improvements:

  1. Introduction of the E3Feature trait for better modularity.
  2. Integration of DataStore for improved state management.
  3. Implementation of snapshot functionality for persistence.

Suggestions for further enhancement:

  1. Reconsider the public visibility of EventBuffer.
  2. Improve error handling and logging in the from_snapshot method.
  3. Implement more granular event subscriptions.

Overall, these changes significantly improve the codebase, with only minor adjustments recommended for optimal performance and maintainability.


25-25: Consider the implications of making EventBuffer public

The EventBuffer struct is now public. While this change may be intentional to allow external access, consider whether this level of visibility is necessary. If possible, keep internal structures private to maintain encapsulation and prevent unintended usage.

✅ Verification successful

EventBuffer is used in packages/ciphernode/router/src/context.rs.

Making it public allows necessary external access. Ensure this visibility is intended and aligns with encapsulation principles.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if EventBuffer is used outside this file
rg "EventBuffer" --type rust --glob '!**/e3_request_router.rs'

Length of output: 135


Script:

#!/bin/bash
# Check if EventBuffer is used outside this file
rg "EventBuffer" --type rust --glob "!packages/ciphernode/router/src/e3_request_router.rs"

Length of output: 343


84-85: Consider error handling for CommitteeMetaFeature creation

The CommitteeMetaFeature is added by default, which is good for ensuring consistent base functionality. However, consider handling potential errors that might occur during its creation.

If create() can fail, consider updating the code to handle potential errors:

-builder.add_feature(CommitteeMetaFeature::create())
+builder.add_feature(CommitteeMetaFeature::create().map_err(|e| anyhow!("Failed to create CommitteeMetaFeature: {}", e))?)

Copy link
Member

@auryn-macmillan auryn-macmillan left a comment

Choose a reason for hiding this comment

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

lgtm

@ryardley ryardley merged commit 399813d into main Oct 22, 2024
3 checks passed
@ryardley ryardley deleted the ry/123-datastore branch December 5, 2024 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clean up on SIGTERM Add persistence
3 participants