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

🧹 Outside diff range and nitpick comments (40)
packages/ciphernode/data/src/lib.rs (1)

8-13: Consider reviewing the granularity of public exports

The public exports make the new functionality readily available, which is good for usability. However, consider reviewing whether all items from each module need to be public. You might want to be more selective about what's exposed in the public API to maintain better encapsulation and control over future changes.

For example, instead of pub use data_store::*;, you could export specific items:

pub use data_store::{DataStore, DataStoreError};

This approach can provide better control over the public API and make it clearer what's intended for external use.

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

15-20: LGTM: InMemStore struct aligns with PR objectives.

The InMemStore struct effectively implements an in-memory data store with logging capabilities. The use of BTreeMap for key-value storage is appropriate.

Consider adding documentation comments to explain the purpose of each field, especially capture, to improve code readability.


Line range hint 35-45: LGTM with a minor comment: Handler<Insert> implementation is correct.

The implementation correctly handles data insertion and logging. However, there's an inconsistent comment:

The comment "insert data into sled" seems out of place for an in-memory implementation. Consider updating or removing this comment to avoid confusion.


Line range hint 55-60: LGTM with optimization suggestion: Handler<GetLog> implementation is correct.

The GetLog handler correctly returns a clone of the entire operation log, which aligns with the PR objectives for implementing logging functionality.

Consider adding an option to retrieve a subset of the log or implementing pagination for large logs to optimize performance and memory usage in production scenarios.

packages/ciphernode/enclave/src/main.rs (2)

29-30: LGTM: New optional data_location argument added.

The addition of the data_location field to the Args struct aligns with the PR objectives for implementing hydration and data persistence. The field is correctly marked as optional, providing flexibility in usage.

Consider adding a brief comment explaining the purpose of the data_location field for better code documentation.


45-47: LGTM: Improved shutdown signal handling implemented.

The new implementation spawns a separate task for handling shutdown signals, which is a good practice for non-blocking operations. Using std::future::pending() keeps the main thread alive indefinitely, which is appropriate for a long-running service.

Consider adding a brief log message before std::future::pending() to indicate that the service is ready and waiting for shutdown signals. This could help with debugging and monitoring.

Example:

info!("Ciphernode service started and ready. Waiting for shutdown signal.");
std::future::pending::<()>().await;
packages/ciphernode/enclave_node/src/ciphernode.rs (1)

64-70: LGTM: Flexible data store initialization implemented.

The implementation allows for both disk-based (Sled) and in-memory storage, aligning well with the PR objectives. The use of repositories also supports the goal of establishing domain-specific repositories.

Consider adding error handling for InMemStore::new() to be consistent with SledStore::new():

None => (&InMemStore::new(true).start()).into(),

Could be changed to:

None => (&InMemStore::new(true).map_err(|e| anyhow::anyhow!("Failed to create InMemStore: {}", e))?.start()).into(),

This ensures consistent error handling across both storage types.

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

35-35: LGTM: Simplified bus field in MainAggregator.

Removing the Option wrapper from the bus field improves type safety and simplifies the API, which aligns with the PR objectives. This change implies that bus is now always expected to be present.

Consider adding a comment explaining why bus is now always present, to provide context for future developers.

Also applies to: 42-42


52-53: LGTM: Updated attach method signature supports hydration and improves API.

The addition of the data_location parameter and the change in return type align well with the PR objectives. These changes support the implementation of hydration and improve the API by returning the EventBus address directly.

Consider adding a brief comment explaining the significance of the data_location parameter and why the return type was changed to Addr<EventBus>.


59-62: LGTM: DataStore initialization implements hydration feature.

The new code block effectively implements the hydration feature by creating either a SledStore or InMemStore based on the data_location. The repositories initialization suggests a new abstraction layer for data access, which aligns with the PR objectives of simplifying the API and enhancing type safety.

Consider adding error handling for the SledStore::new call to provide more context in case of failure.

Also applies to: 64-64

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

26-31: Well-structured parameter encapsulation

The introduction of KeyshareParams improves code organization and follows the builder pattern, which is a good practice. This makes it easier to extend the Keyshare initialization process in the future.

Consider adding a builder method for KeyshareParams to further improve its usage:

impl KeyshareParams {
    pub fn new() -> Self {
        Self {
            bus: Default::default(),
            store: Default::default(),
            fhe: Default::default(),
            address: Default::default(),
        }
    }

    pub fn with_bus(mut self, bus: Addr<EventBus>) -> Self {
        self.bus = bus;
        self
    }

    // Add similar methods for other fields
}

This would allow for a more flexible and readable instantiation of KeyshareParams.


132-160: Improved error handling with minor security consideration

The changes to the CiphertextOutputPublished handler demonstrate several improvements:

  • Checking for the presence of self.secret prevents potential runtime errors.
  • Enhanced error handling provides better context for debugging.
  • The overall flow of the handler is more robust and clear.

These changes significantly improve the reliability and maintainability of the code.

However, there's a minor security consideration:

  • Using secret.to_vec() creates an unnecessary copy of sensitive data in memory.

Consider the following improvement:

let Ok(decryption_share) = self.fhe.decrypt_ciphertext(DecryptCiphertext {
    ciphertext: ciphertext_output.clone(),
    unsafe_secret: secret.as_slice(), // Use a reference instead of cloning
}) else {
    // ... error handling ...
};

This change would minimize the exposure of the secret in memory.

tests/basic_integration/test.sh (3)

79-86: LGTM! Consider adding error handling.

The launch_ciphernode function is well-structured and improves code reusability. It encapsulates the logic for launching a ciphernode with consistent parameters.

Consider adding basic error handling, such as checking if the yarn ciphernode:launch command was successful:

launch_ciphernode() {
    local address="$1"
    heading "Launch ciphernode $address"
    if ! yarn ciphernode:launch \
      --address "$address" \
      --config "$SCRIPT_DIR/lib/ciphernode_config.yaml" \
      --data-location "$SCRIPT_DIR/output/$address.db" &
    then
        echo "Failed to launch ciphernode $address" >&2
        return 1
    fi
}

88-94: LGTM! Consider adding error handling.

The launch_aggregator function is well-structured and improves code reusability. It encapsulates the logic for launching the aggregator with consistent parameters.

Consider adding basic error handling, similar to the suggestion for launch_ciphernode:

launch_aggregator() {
    local private_key="$1"
    if ! PRIVATE_KEY=$private_key yarn ciphernode:aggregator \
      --config "$SCRIPT_DIR/lib/ciphernode_config.yaml" \
      --pubkey-write-path "$SCRIPT_DIR/output/pubkey.bin" \
      --plaintext-write-path "$SCRIPT_DIR/output/plaintext.txt" &
    then
        echo "Failed to launch aggregator" >&2
        return 1
    fi
}

180-184: Good improvement in the cleanup process. Consider using wait.

The use of pkill -15 instead of pkill -9 allows for a more graceful shutdown of processes, which is a good practice. The added sleep command ensures that processes have time to terminate properly.

Instead of using a fixed sleep duration, consider using the wait command to ensure all background processes have finished:

pkill -15 -f "target/debug/enclave" || true
pkill -15 -f "target/debug/aggregator" || true

wait $(jobs -p) 2>/dev/null || true

This approach will wait for all background processes to finish, regardless of how long they take, and will not unnecessarily delay the script if processes terminate quickly.

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

Line range hint 14-41: LGTM: Serialization and initialization improvements.

The addition of serde::Serialize and serde::Deserialize traits to PlaintextAggregatorState aligns with the hydration requirements. The new init method provides a convenient way to initialize the state.

Consider adding documentation comments to the init method to explain its purpose and parameters.


53-78: LGTM: Improved state management and API flexibility.

The addition of the store field and the introduction of PlaintextAggregatorParams align well with the PR objectives for hydration and improved state management. The refactored new method using PlaintextAggregatorParams enhances API flexibility.

Consider adding documentation comments to the PlaintextAggregatorParams struct to explain its purpose and fields.


238-242: LGTM: Checkpoint trait implementation.

The implementation of the Checkpoint trait for PlaintextAggregator is correct and aligns with the PR objectives for hydration functionality.

Consider adding a brief comment explaining why we're cloning the store here, as it might not be immediately obvious to future readers why a clone is necessary.

packages/ciphernode/core/src/events.rs (3)

123-129: LGTM. Consider adding documentation for the Shutdown event.

The addition of the Shutdown event to the EnclaveEvent enum is well-structured and consistent with the existing code. This is likely used for graceful termination of the system, which is a good practice.

Consider adding a brief comment explaining the purpose and usage of the Shutdown event for better code documentation.


315-322: LGTM. Consider adding a brief comment for the From implementation.

The implementation of From<Shutdown> for EnclaveEvent is correct and consistent with the pattern established for other event types. It properly creates an EnclaveEvent::Shutdown variant with a unique EventId.

Consider adding a brief comment explaining the purpose of this implementation, similar to the TODO comment above it. This would enhance code readability and maintain consistency with the documentation style in the rest of the file.


524-532: LGTM. Consider adding documentation for the Shutdown struct.

The Shutdown struct is well-defined with appropriate trait implementations. The Display implementation is simple and suitable for a shutdown event.

Consider adding a brief doc comment (///) above the struct definition explaining its purpose, usage, and any relevant details about how it's triggered or handled in the system. This would improve code documentation and make it easier for other developers to understand its role in the system.

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

28-28: Enhance logging for clarity during shutdown

The message "Graceful shutdown complete" indicates the shutdown process is finished. For better clarity, consider specifying which components or services have been shut down, especially in a system with multiple asynchronous tasks.

Update the log message for clarity:

-info!("Graceful shutdown complete");
+info!("Shutdown process complete. All services have been stopped.");
packages/ciphernode/data/src/repository.rs (3)

28-32: Reevaluate the implementation of From<Repository<S>> for DataStore

Implementing From<Repository<S>> for DataStore allows for implicit conversion, which might lead to unintentional usage and obscure the structure of the code. It may be clearer to provide an explicit method to extract the DataStore or rely on the existing Deref implementation.

Consider removing the From implementation:

-impl<S> From<Repository<S>> for DataStore {
-    fn from(value: Repository<S>) -> Self {
-        value.store
-    }
-}

21-26: Assess the necessity of the Deref implementation

While implementing Deref for Repository<S> provides convenient access to DataStore methods, it can sometimes blur the abstraction boundaries. Evaluate whether this convenience aligns with the intended design or if it would be better to access store explicitly.

If you decide to remove it, apply this diff:

-impl<S> Deref for Repository<S> {
-    type Target = DataStore;
-    fn deref(&self) -> &Self::Target {
-        &self.store
-    }
-}

35-42: Clarify the comment regarding cloning

The comment "// Clone without phantom data" might be misleading since PhantomData does not contain any data and cloning it is trivial. Consider rephrasing the comment for clarity or removing it if unnecessary.

Apply this diff to update the comment:

-/// Clone without phantom data
+/// Clone the repository, `PhantomData` does not contain data
packages/ciphernode/data/src/sled_store.rs (2)

29-38: Acknowledge successful insert operations or handle them explicitly

The handle method for Insert does not provide any response or acknowledgment when an insert operation succeeds. Depending on your application's requirements, it might be beneficial to confirm successful inserts or handle them explicitly for better transparency.


7-10: Derive Debug and Clone for SledStore for consistency

Consider deriving Debug and Clone for the SledStore struct to maintain consistency with other structs and to facilitate debugging.

 #[derive(Debug, Clone)]
 pub struct SledStore {
     db: Db,
     bus: Addr<EventBus>,
 }
packages/ciphernode/data/src/snapshot.rs (1)

6-6: Fix grammatical issue in documentation

In the comment on line 6, consider changing "their state snapshot" to "its state snapshot" for grammatical correctness.

Apply this diff:

-/// This trait enables the self type to report their state snapshot
+/// This trait enables the self type to report its state snapshot
packages/ciphernode/evm/src/enclave_sol_reader.rs (2)

Line range hint 60-62: Address the TODO comment to enhance error logging

There's a TODO comment suggesting to provide more information in the error message when parsing CiphertextOutputPublished fails. Providing additional context can aid in debugging.

Would you like assistance in improving the error message to include more details, such as the data that caused the parsing error?


Line range hint 66-68: Fix typographical error in trace message

There's a typo in the trace message: "parser buut was ignored" should be "parser but was ignored".

Apply this diff to fix the typo:

-                    "Unknown event was received by Enclave.sol parser buut was ignored"
+                    "Unknown event was received by Enclave.sol parser but was ignored"
packages/ciphernode/evm/src/event_reader.rs (1)

20-20: Use the type alias ExtractorFn for the extractor field

For consistency and readability, consider using the ExtractorFn type alias for the extractor field.

Apply this diff to make the change:

-        extractor: fn(&LogData, Option<&B256>, u64) -> Option<EnclaveEvent>,
+        extractor: ExtractorFn,
packages/ciphernode/evm/src/ciphernode_registry_sol.rs (1)

Line range hint 65-91: Review the visibility of the extractor function

The extractor function has been made public. If this function is only intended for internal use within this module, consider keeping it private to limit the API surface and enhance encapsulation.

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

111-116: Add Logging in Shutdown Handler for Better Observability

It's recommended to log a message when the actor is stopping. This aids in monitoring and debugging by providing clear indications of actor lifecycle events.

Apply this diff to add logging:

 fn handle(&mut self, _: Shutdown, ctx: &mut Self::Context) -> Self::Result {
+    info!("EnclaveSolWriter received Shutdown message and is stopping.");
     ctx.stop();
 }
packages/ciphernode/evm/src/registry_filter_sol.rs (1)

106-111: Add logging when the actor is shutting down

Currently, the handle method for Shutdown stops the actor without any logging. For improved observability and easier debugging, consider adding a log statement when the actor begins the shutdown process.

Apply this diff to add a logging statement:

impl Handler<Shutdown> for RegistryFilterSolWriter {
    type Result = ();
    fn handle(&mut self, _: Shutdown, ctx: &mut Self::Context) -> Self::Result {
+       info!("RegistryFilterSolWriter actor is shutting down.");
        ctx.stop();
    }
}

This addition will help track the shutdown event in the logs, aiding in monitoring and troubleshooting.

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

72-83: Optimize message cloning to reduce overhead

In the forward_message method, msg.clone() is called for each recipient. If EnclaveEvent is large, cloning it multiple times could introduce unnecessary overhead. Consider wrapping EnclaveEvent in an Arc to share the message without cloning.

[performance]

Apply this change:

-    fn forward_message(&self, msg: &EnclaveEvent, buffer: &mut EventBuffer) {
+    fn forward_message(&self, msg: Arc<EnclaveEvent>, buffer: &mut EventBuffer) {
         self.recipients().into_iter().for_each(|(key, recipient)| {
             if let Some(act) = recipient {
-                act.do_send(msg.clone());
+                act.do_send((*msg).clone());
                 for m in buffer.take(&key) {
                     act.do_send(m);
                 }
             } else {
-                buffer.add(&key, msg.clone());
+                buffer.add(&key, (*msg).clone());
             }
         });
     }
packages/ciphernode/router/src/e3_request_router.rs (3)

65-67: Consider initializing buffer using Default trait

In the struct E3RequestRouter, the buffer field is manually initialized with an empty HashMap. You can simplify the code by deriving Default and initializing buffer using EventBuffer::default().

Apply this diff to simplify initialization:

 pub struct E3RequestRouter {
     contexts: HashMap<E3id, E3RequestContext>,
     completed: HashSet<E3id>,
     features: Arc<Vec<Box<dyn E3Feature>>>,
     bus: Addr<EventBus>,
-    buffer: EventBuffer,
+    buffer: EventBuffer::default(),
     store: Repository<E3RequestRouterSnapshot>,
 }

60-60: Address the TODO for implementing typestate pattern

There's a TODO comment indicating the need to set up a typestate pattern for feature dependencies:

// TODO: setup typestate pattern so that we have to place features within correct order of dependencies

Would you like assistance in developing this typestate pattern to enforce correct feature initialization order? Implementing it can enhance the modularity and safety of feature management.


242-243: Rename parameter for consistency in add_feature method

In the add_feature method, the parameter is named listener, but the context refers to features:

pub fn add_feature(mut self, listener: Box<dyn E3Feature>) -> Self {
    self.features.push(listener);
    self
}

Rename listener to feature for consistency and clarity:

-pub fn add_feature(mut self, listener: Box<dyn E3Feature>) -> Self {
-    self.features.push(listener);
+pub fn add_feature(mut self, feature: Box<dyn E3Feature>) -> Self {
+    self.features.push(feature);
    self
}
packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (2)

419-421: Improve Clarity by Explicitly Unpacking Tuple Elements

Using .. in tuple unpacking can reduce code readability and may lead to maintenance issues if the tuple structure changes.

Consider explicitly unpacking all elements or refactoring to use a struct for better clarity:

-let (addr1, data1, ..) = cn1;
-let (addr2, data2, ..) = cn2;
+let (addr1, data1, sortition1, router1, logger1) = cn1;
+let (addr2, data2, sortition2, router2, logger2) = cn2;

Line range hint 497-501: Ensure Thread Safety When Accessing Mutex-Protected Data

In the assertion within the test, the mutex guard is held across an assertion, which is generally safe but could be optimized.

Unlock the mutex before the assertion to minimize the time the mutex is held:

 let msgs_guard = msgs.lock().await;
 assert_eq!(
-    *msgs_guard,
+    msgs_guard.clone(),
     vec![evt_1.to_bytes()?, evt_2.to_bytes()?], // notice no local events
     "P2p did not transmit correct events to the network"
 );
+drop(msgs_guard); // Explicitly drop the mutex guard
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

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

⛔ Files ignored due to path filters (1)
  • packages/ciphernode/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (41)
  • packages/ciphernode/Cargo.toml (1 hunks)
  • packages/ciphernode/aggregator/src/plaintext_aggregator.rs (6 hunks)
  • packages/ciphernode/aggregator/src/publickey_aggregator.rs (7 hunks)
  • packages/ciphernode/core/src/events.rs (8 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/into_key.rs (1 hunks)
  • packages/ciphernode/data/src/lib.rs (1 hunks)
  • packages/ciphernode/data/src/repository.rs (1 hunks)
  • packages/ciphernode/data/src/sled_store.rs (1 hunks)
  • packages/ciphernode/data/src/snapshot.rs (1 hunks)
  • packages/ciphernode/enclave/Cargo.toml (1 hunks)
  • packages/ciphernode/enclave/src/bin/aggregator.rs (3 hunks)
  • packages/ciphernode/enclave/src/main.rs (3 hunks)
  • packages/ciphernode/enclave_node/Cargo.toml (1 hunks)
  • packages/ciphernode/enclave_node/src/aggregator.rs (6 hunks)
  • packages/ciphernode/enclave_node/src/app_config.rs (0 hunks)
  • packages/ciphernode/enclave_node/src/ciphernode.rs (5 hunks)
  • packages/ciphernode/enclave_node/src/lib.rs (1 hunks)
  • packages/ciphernode/enclave_node/src/shutdown.rs (1 hunks)
  • packages/ciphernode/evm/src/ciphernode_registry_sol.rs (3 hunks)
  • packages/ciphernode/evm/src/enclave_sol_reader.rs (3 hunks)
  • packages/ciphernode/evm/src/enclave_sol_writer.rs (6 hunks)
  • packages/ciphernode/evm/src/event_reader.rs (1 hunks)
  • packages/ciphernode/evm/src/helpers.rs (4 hunks)
  • packages/ciphernode/evm/src/lib.rs (1 hunks)
  • packages/ciphernode/evm/src/registry_filter_sol.rs (5 hunks)
  • packages/ciphernode/keyshare/Cargo.toml (1 hunks)
  • packages/ciphernode/keyshare/src/keyshare.rs (3 hunks)
  • packages/ciphernode/router/src/ciphernode_selector.rs (3 hunks)
  • packages/ciphernode/router/src/committee_meta.rs (1 hunks)
  • packages/ciphernode/router/src/context.rs (1 hunks)
  • packages/ciphernode/router/src/e3_request_router.rs (5 hunks)
  • packages/ciphernode/router/src/hooks.rs (1 hunks)
  • packages/ciphernode/router/src/lib.rs (1 hunks)
  • packages/ciphernode/router/src/repositories.rs (1 hunks)
  • packages/ciphernode/sortition/src/sortition.rs (4 hunks)
  • packages/ciphernode/tests/tests/test_aggregation_and_decryption.rs (3 hunks)
  • tests/basic_integration/output/.gitignore (1 hunks)
  • tests/basic_integration/test.sh (3 hunks)
💤 Files with no reviewable changes (1)
  • packages/ciphernode/enclave_node/src/app_config.rs
✅ Files skipped from review due to trivial changes (1)
  • tests/basic_integration/output/.gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ciphernode/keyshare/Cargo.toml
🧰 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 (87)
packages/ciphernode/enclave_node/src/lib.rs (4)

1-9: Summary of changes and request for additional context.

The changes in this file introduce a new shutdown module and adjust the public exports. While these modifications appear to enhance the system's shutdown capabilities and module organization, it would be helpful to have more context about the overall changes in the PR.

Could you please provide:

  1. An overview of how these changes fit into the larger "Hydration" implementation mentioned in the PR description?
  2. Any related changes in other files that work in conjunction with these modifications?

This additional information will help ensure that these changes align with the PR's objectives and integrate well with the rest of the system.


4-4: LGTM: Addition of shutdown module.

The introduction of a dedicated shutdown module is a good practice for managing graceful shutdowns in the system. This can help improve the overall robustness and reliability of the application.

To ensure proper implementation, please run the following script to verify the contents of the shutdown module:

#!/bin/bash
# Description: Verify the contents of the shutdown module

# Test: Check if the shutdown module contains the expected function
rg -p 'async fn listen_for_shutdown' packages/ciphernode/enclave_node/src/shutdown.rs

# Test: Verify if the shutdown function is properly integrated with the actor system
rg -p 'EnclaveEvent::from\(Shutdown\)' packages/ciphernode/enclave_node/src

9-9: LGTM: Exposing shutdown module.

Exposing the shutdown module through public exports is consistent with its purpose of managing system-wide shutdowns. This allows other parts of the application to utilize its functionality when needed.

To ensure this doesn't introduce any security or stability risks, please conduct a security review and run the following script to check its usage:

#!/bin/bash
# Description: Verify the usage of the shutdown module across the codebase

# Test: Find all imports of the shutdown module
rg -p 'use .*shutdown::' packages/ciphernode

# Test: Check for any potential misuse of shutdown functionality
rg -p 'listen_for_shutdown' packages/ciphernode

8-8: Please clarify the re-introduction of the 'ciphernode' module.

The 'ciphernode' module has been re-added to the public exports. Could you please provide context on why this module was previously removed and why it's being re-introduced now? This information will help in understanding the module's importance and its role in the overall architecture.

To assess the impact of this change, please run the following script:

✅ Verification successful

Ciphernode module re-introduction verified.

The 'ciphernode' module has been re-added to public exports without introducing any new usages or dependencies within the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the usage of the ciphernode module in the codebase

# Test: Find all imports of the ciphernode module
rg -p 'use .*ciphernode::' packages/ciphernode

# Test: Check for any potential breaking changes due to the re-introduction
rg -p 'ciphernode::' packages/ciphernode

Length of output: 912


Script:

#!/bin/bash
# Description: Corrected search for the usage of the 'ciphernode' module in the codebase.

# Test 1: Find all imports of the 'ciphernode' module.
rg 'use\s+.*ciphernode::' packages/ciphernode

# Test 2: Find all instances where 'ciphernode' is used to identify potential breaking changes.
rg 'ciphernode::' packages/ciphernode

# Test 3: Check for any function calls or usages related to 'ciphernode'.
rg '\bciphernode::\w+' packages/ciphernode

Length of output: 264

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

1-6: Excellent modular structure for data management

The new module structure effectively separates concerns and aligns well with the PR objectives of implementing hydration for data persistence. This organization enhances maintainability and flexibility:

  • data_store and sled_store likely handle persistent storage
  • in_mem provides in-memory storage options
  • repository introduces an abstraction layer
  • into_key and snapshot offer supporting functionality

This structure should facilitate easier testing and mocking, as mentioned in the linked issue #123.

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

3-3: LGTM! New modules added and exported.

The addition of context and repositories modules, along with their public exports, aligns well with the PR objectives for implementing hydration and data persistence. This change enhances the module structure by incorporating additional components without altering the existing functionality.

Consider verifying if all contents of the new modules need to be publicly exported. Run the following script to check the contents of these modules:

Review the output to ensure that only necessary items are being publicly exported.

Also applies to: 6-6, 10-10, 13-13

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

5-5: LGTM: New module addition is consistent and relevant.

The addition of the event_reader module is well-placed and aligns with the PR objectives for implementing hydration and data persistence.


13-13: LGTM: Public export of EvmEventReader is appropriate.

The public export of EvmEventReader from the event_reader module is consistent with the file structure and aligns with the PR objectives.

To ensure the EvmEventReader is being used as intended, please run the following script:

✅ Verification successful

Verified: EvmEventReader is appropriately used across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of EvmEventReader in the codebase

# Test: Search for EvmEventReader usage
rg "EvmEventReader" --type rust

Length of output: 1188

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

14-14: LGTM: Addition of actix dependency aligns with PR objectives.

The inclusion of the actix dependency is consistent with the PR's goal of implementing hydration for data persistence and enhancing the actor model using Actix. This addition supports the new DataStore implementation and other components that utilize Actix for message handling.

The workspace = true configuration ensures version consistency across the project, which is a good practice.

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

34-34: LGTM: Addition of tracing dependency.

The addition of the tracing crate as a workspace dependency is a good improvement. It will enhance logging and debugging capabilities across the project.

To ensure this dependency is being utilized effectively, please run the following script:

This will help confirm that the tracing crate is being imported and used within the enclave_node package.

✅ Verification successful

Verified: Usage of tracing crate confirmed.

The tracing crate is properly imported and utilized within the enclave_node package, enhancing logging and debugging capabilities.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the tracing crate in the enclave_node package

# Test: Search for imports of the tracing crate
rg -A 5 'use tracing' packages/ciphernode/enclave_node/src

# Test: Search for macros from the tracing crate (e.g., info!, error!, debug!)
rg -A 5 '(info!|error!|debug!)' packages/ciphernode/enclave_node/src

Length of output: 1277

packages/ciphernode/enclave/src/bin/aggregator.rs (4)

3-3: LGTM: Import statement updated correctly.

The addition of listen_for_shutdown import is consistent with its usage in the main function and aligns with the PR objectives.


18-19: LGTM: New command-line argument added correctly.

The addition of the data_location field to the Args struct is well-implemented and aligns with the PR objectives. The optional nature of the field provides flexibility for users.


28-35: LGTM: MainAggregator::attach method call updated correctly.

The addition of args.data_location.as_deref() as an argument and the destructuring of the return value are well-implemented. These changes align with the PR objectives and support the new functionality.


36-39: Control flow changes look good, but verify removal of tokio::join!

The addition of the listen_for_shutdown task and the use of std::future::pending() improve the application's robustness and align with the PR objectives. However, please verify that the removal of tokio::join! doesn't negatively impact the management of other tasks that might have been present.

To ensure no critical tasks were removed, please run the following command:

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

Line range hint 4-14: LGTM: New imports and struct definitions align with PR objectives.

The addition of Get and Insert imports, along with the new GetLog message and DataOp enum, supports the implementation of hydration and logging functionality as outlined in the PR objectives.


21-23: LGTM: Correct Actor implementation for InMemStore.

The Actor trait implementation for InMemStore is correct and necessary for integration with the Actix actor system.


Line range hint 25-33: LGTM: InMemStore::new method correctly initializes the struct.

The constructor method for InMemStore properly initializes all fields, including the BTreeMap, capture flag, and log. This implementation aligns well with the PR objectives for creating an in-memory data store with logging capabilities.


47-53: LGTM: Handler<Get> implementation correctly retrieves data.

The Get handler effectively retrieves data from the BTreeMap, returning a cloned value if the key exists. This implementation aligns well with the PR objectives for data retrieval in the in-memory store.


Line range hint 1-60: Overall, the implementation looks good and aligns well with PR objectives.

The InMemStore successfully implements an in-memory data store with logging capabilities using Actix for actor-based concurrency. The code is well-structured and follows good practices. Minor suggestions have been made for documentation and potential optimizations.

To ensure the implementation is consistent across the codebase, please run the following verification script:

This script will help ensure that the changes are consistently applied across the codebase and that there are no unintended references to the old implementation or inconsistent usage of the new InMemStore.

✅ Verification successful

Verification Successful: The InMemStore implementation is consistent and free from unintended dependencies.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of InMemStore and its handlers across the codebase

# Test 1: Check for any remaining references to the old 'Data' struct
echo "Checking for old 'Data' struct references:"
rg -i '\bData\b' --type rust

# Test 2: Verify consistent usage of InMemStore
echo "Verifying InMemStore usage:"
rg -i '\bInMemStore\b' --type rust

# Test 3: Check for consistent Handler implementations
echo "Checking Handler implementations:"
rg -i 'impl Handler<(Insert|Get|GetLog)> for InMemStore' --type rust

# Test 4: Verify no unintended sled usage in in_mem.rs
echo "Checking for unintended sled usage in in_mem.rs:"
rg -i '\bsled\b' packages/ciphernode/data/src/in_mem.rs

Length of output: 18118

packages/ciphernode/Cargo.toml (1)

46-46: New dependency added: sled

The addition of the sled dependency (version 0.34.7) aligns with the PR objectives for implementing hydration and data persistence. Sled is an embedded database, which is suitable for this purpose.

To ensure this addition is used consistently across the project, let's verify its usage:

This script will help us confirm that sled is being used consistently across the project and that the same version is specified in all relevant Cargo.toml files.

✅ Verification successful

sled dependency verified

The sled dependency has been correctly added to the ciphernode package and is properly utilized within the relevant modules.

  • File: packages/ciphernode/data/src/sled_store.rs
  • File: packages/ciphernode/data/src/lib.rs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of sled across the project

# Test 1: Check for sled imports
echo "Checking for sled imports:"
rg -n "use sled" -g '*.rs'

# Test 2: Check for sled usage in code
echo "Checking for sled usage:"
rg -n "sled::" -g '*.rs'

# Test 3: Verify sled dependency in other Cargo.toml files
echo "Checking for sled in other Cargo.toml files:"
rg -n 'sled = "0.34.7"' -g 'Cargo.toml'

Length of output: 671

packages/ciphernode/enclave/src/main.rs (3)

4-4: LGTM: Import added for new shutdown listener.

The addition of listen_for_shutdown import is consistent with the changes in the main function and aligns with the PR objectives for enhancing the shutdown process.


Line range hint 1-48: Overall: Changes look good and align with PR objectives.

The modifications in this file enhance the configurability of the application by allowing for a data location to be specified and improve the shutdown process with a non-blocking implementation. The changes are well-integrated and consistent with the PR objectives.

To ensure the changes are properly integrated, let's verify the usage of the new data_location parameter in the MainCiphernode::attach method:

#!/bin/bash
# Description: Verify the usage of data_location in MainCiphernode::attach method
rg -A 10 'fn attach.*data_location' packages/ciphernode/enclave_node/src/

This will help confirm that the data_location parameter is being used correctly in the implementation.


42-43: LGTM: MainCiphernode::attach call updated with data_location argument.

The modification correctly passes the data_location argument to the attach method, using as_deref() to convert Option<String> to Option<&str>. This change is consistent with the updated method signature.

To ensure consistency across the codebase, let's verify the attach method signature in the MainCiphernode implementation:

✅ Verification successful

Verified: MainCiphernode::attach method signature includes the data_location parameter.

  • The method is correctly defined with data_location: Option<&str> in packages/ciphernode/enclave_node/src/ciphernode.rs.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the updated signature of MainCiphernode::attach method
rg -A 5 'impl MainCiphernode' packages/ciphernode/enclave_node/src/

Length of output: 75


Script:

#!/bin/bash
# Description: Search for the attach method in MainCiphernode implementation
rg -A 10 'impl MainCiphernode' packages/ciphernode/enclave/src/

Length of output: 65


Script:

#!/bin/bash
# Description: Locate the attach method with the data_location parameter
rg 'fn attach\(.*data_location' packages/ciphernode/enclave/src/

Length of output: 66


Script:

#!/bin/bash
# Description: Broad search for MainCiphernode implementation across the ciphernode package
rg 'impl MainCiphernode' packages/ciphernode/

Length of output: 120


Script:

#!/bin/bash
# Description: Locate the attach method with the data_location parameter using ast-grep
ast-grep --pattern 'fn attach($_, $_, data_location: $_)' 'MainCiphernode' packages/ciphernode/

Length of output: 157


Script:

#!/bin/bash
# Description: Search for the attach method within the MainCiphernode implementation
rg 'fn attach' packages/ciphernode/enclave_node/src/ciphernode.rs -A 5

Length of output: 278


Script:

#!/bin/bash
# Description: Locate the attach method with the data_location parameter using ast-grep
ast-grep --pattern 'fn attach($_, $_, data_location: $_)' packages/ciphernode/enclave_node/src/ciphernode.rs

Length of output: 110

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

4-4: LGTM: Import statements updated correctly.

The new imports for DataStore, InMemStore, SledStore, FheFeature, and KeyshareFeature align well with the changes in the implementation. These additions support the new data persistence and feature-based router approach.

Also applies to: 11-13


26-26: LGTM: MainCiphernode struct updated to use DataStore.

The change from Addr<Data> to DataStore for the data field aligns well with the PR objectives of implementing hydration for data persistence. This direct approach to data management may improve performance and simplify the API.


37-37: LGTM: new method signature updated correctly.

The change in the data parameter type from Addr<Data> to DataStore is consistent with the struct field modification and supports the new data persistence approach. This ensures that the DataStore is passed directly to the MainCiphernode instance.


102-112: LGTM: MainCiphernode instantiation and return value updated correctly.

The changes to the MainCiphernode::new() call and the return value are consistent with the earlier modifications to the struct and method signatures. The inclusion of store and the Ok((bus, join_handle)) return value properly reflect the new data persistence approach and error handling mechanism.


91-95: LGTM: E3RequestRouter initialization updated with feature-based approach.

The new builder pattern with feature additions (FheFeature and KeyshareFeature) aligns well with the PR objectives of implementing a feature-based architecture. This approach improves modularity and extensibility.

Ensure that error handling for the asynchronous build() method is properly implemented throughout the codebase. Run the following script to check for proper error handling:

#!/bin/bash
# Search for E3RequestRouter::builder usage
rg -p "E3RequestRouter::builder" --type rust -A 10 | grep -E "\.await\??|\.expect|\.unwrap"

Review the results to confirm that .await? is used consistently and that there are no unwrapped calls that could lead to panics.


57-58: LGTM: attach method signature updated with improved flexibility and error handling.

The addition of the data_location parameter and the change in return type to Result<(Addr<EventBus>, JoinHandle<()>)> improve flexibility in data store initialization and error handling. These changes align well with the PR objectives.

Please verify that all callers of this method have been updated to handle the new return type (Addr<EventBus> instead of Addr<Self>). Run the following script to check for usages:

✅ Verification successful

Verified: All callers of MainCiphernode::attach have been appropriately updated to handle the new return type.

The search results indicate that only the main.rs file invokes MainCiphernode::attach, and it has been updated to accommodate the changes in the method signature.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for calls to MainCiphernode::attach
rg -p "MainCiphernode::attach" --type rust

Length of output: 195


Script:

#!/bin/bash
# Search for any calls to an attach method in Rust files
rg 'attach\s*\(' --type rust

Length of output: 4303

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

3-3: LGTM: Import statements are consistent with code changes.

The new imports for DataStore, InMemStore, and SledStore, as well as the updated router feature imports, align well with the PR objectives and the implementation of hydration for data persistence.

Also applies to: 13-15


121-121: LGTM: MainAggregator initialization updated to pass bus reference.

The change to pass a reference to bus in the MainAggregator::new call is consistent with the earlier modification of the bus field in the MainAggregator struct. This change may slightly improve performance by avoiding an unnecessary clone.


122-122: LGTM: Return statement updated to match new method signature.

The change in the return statement to (bus, join_handle) is consistent with the updated method signature and aligns with the PR objectives. Returning the EventBus address directly may simplify the API for callers.


95-106: LGTM: E3RequestRouter initialization updated to use DataStore and features.

The changes to the E3RequestRouter::builder call and the replacement of hooks with features align well with the PR objectives. This shift towards a feature-based architecture likely improves modularity and extensibility.

To ensure that all necessary features are properly initialized, please run the following verification script:

✅ Verification successful

Verified: All required features are properly initialized in E3RequestRouter.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all required features are initialized in E3RequestRouter

# Test: Check for the presence of all required features
rg -q 'FheFeature::create' && \
rg -q 'PublicKeyAggregatorFeature::create' && \
rg -q 'PlaintextAggregatorFeature::create' && \
echo "All required features are present in E3RequestRouter initialization." || \
echo "Error: One or more required features are missing in E3RequestRouter initialization."

Length of output: 259

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

1-131: Overall assessment: Solid foundation with room for optimization

The data_store.rs file provides a well-structured implementation of a key-value data store using actor-based message passing. The design is sound and covers essential functionality such as reading, writing, and scope management.

Key strengths:

  1. Clear separation of concerns with Insert, Get, and DataStore structs.
  2. Use of generics and traits for flexibility.
  3. Implementation of From trait for different store types.

Areas for improvement:

  1. Optimize methods to reduce unnecessary cloning and allocations.
  2. Enhance error handling, particularly in the write method.
  3. Reduce code duplication in From implementations.

Implementing the suggested optimizations will improve performance and make the code more robust. Great job on the overall design!

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

2-18: Improved error handling and state management

The changes to imports and the Keyshare struct demonstrate improvements in error handling, asynchronous capabilities, and state management. The introduction of the store field and the optional secret field allows for more flexible and persistent state management.


39-48: Improved constructor with parameter struct

The changes to the Keyshare::new method improve its flexibility and maintainability:

  • Using KeyshareParams simplifies the constructor and makes it easier to extend in the future.
  • Initializing secret as None is consistent with its new optional nature.

These changes align well with good software design practices.


66-78: Effective implementation of FromSnapshotWithParams

The implementation of FromSnapshotWithParams for Keyshare is well-structured and allows for efficient reconstruction of a Keyshare instance from persisted state. It correctly utilizes both the provided parameters and the snapshot data.

This implementation enhances the system's ability to recover state and maintain consistency across restarts or state transfers.


Line range hint 1-170: Summary of Review

The changes to keyshare.rs significantly improve the overall structure, state management, and error handling of the Keyshare module. Key improvements include:

  1. Introduction of KeyshareParams and KeyshareState for better organization.
  2. Implementation of Snapshot and Checkpoint traits for state persistence.
  3. Enhanced error handling using anyhow.
  4. More robust event handling in CiphernodeSelected and CiphertextOutputPublished.

However, there are important security considerations to address:

  1. Secure handling of the secret field in KeyshareState, particularly during serialization and deserialization.
  2. Minimizing unnecessary copying of the secret in memory, especially in the snapshot method and during decryption.
  3. Consider using a secure container like secrecy::Secret to wrap sensitive data.

Please review the specific comments for each section and implement the suggested security improvements. These changes will significantly enhance the security posture of the Keyshare module while maintaining its improved functionality and structure.

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-related modules are appropriate for implementing the hydration functionality as per the PR objectives.


Line range hint 27-47: LGTM: New SortitionModule struct improves modularity.

The introduction of SortitionModule encapsulates node management functionality, improving modularity and aligning with the PR objectives. The implementation of SortitionList trait ensures that core functionality is maintained.


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

The addition of the store field of type Repository<SortitionModule> aligns with the PR objectives of implementing hydration for data persistence. This change enables state management using the new data persistence mechanism.


90-93: LGTM: New SortitionParams struct enhances API clarity.

The introduction of SortitionParams encapsulates the parameters needed for Sortition creation, improving API clarity and type safety. This aligns well with the PR objectives.


96-102: LGTM: Updated new and attach methods use SortitionParams.

The changes to Sortition::new and Sortition::attach methods improve consistency and type safety by using the new SortitionParams struct. The attach method now properly initializes the Sortition instance with the data persistence mechanism, aligning with the PR objectives.

Also applies to: 104-109


123-128: LGTM: Snapshot trait implementation added.

The implementation of the Snapshot trait for Sortition allows for capturing the internal state, which is crucial for the hydration functionality. This aligns well with the PR objectives for data persistence.


130-140: LGTM: FromSnapshotWithParams trait implementation added.

The async implementation of FromSnapshotWithParams for Sortition enables reconstruction of the instance from a snapshot and parameters. This is essential for the hydration functionality and aligns perfectly with the PR objectives for data persistence.


142-146: LGTM: Checkpoint trait implementation added.

The implementation of the Checkpoint trait for Sortition provides access to the Repository<SortitionModule>, supporting the hydration and data persistence objectives of the PR.


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

The changes in this file consistently support the PR objectives of implementing hydration for data persistence. The modifications to the Sortition struct, along with the new SortitionModule, SortitionParams, and trait implementations (Snapshot, FromSnapshotWithParams, Checkpoint), form a cohesive set of changes that significantly enhance the module's capabilities for state management and persistence.

These changes align well with the PR objectives and the overall architecture described in the PR summary. The implementation successfully addresses the need for data persistence while maintaining the existing functionality and improving modularity and type safety.

tests/basic_integration/test.sh (2)

118-122: Great refactoring! The code is now more concise and maintainable.

The use of the launch_ciphernode and launch_aggregator functions has significantly improved the readability and maintainability of the script. This change aligns well with the PR objectives of enhancing the structure and modularity of the testing process.


Line range hint 1-184: Overall, excellent improvements to the integration test script.

The changes in this file significantly enhance the structure and modularity of the testing process, aligning well with the PR objectives. The introduction of launch_ciphernode and launch_aggregator functions improves code reusability and readability. The updated cleanup process with pkill -15 allows for more graceful termination of processes.

While these changes don't directly address the data persistence aspects mentioned in the PR objectives, they do support the overall goal of improving the testing infrastructure. This enhanced script structure will likely make it easier to incorporate and test the hydration and persistence features in the future.

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

3-7: LGTM: New imports support hydration implementation.

The added imports are consistent with the PR objectives and support the new functionality for serialization, checkpointing, and snapshot management.


220-227: LGTM: Snapshot trait implementation.

The implementation of the Snapshot trait for PlaintextAggregator is correct and aligns with the PR objectives for hydration functionality.


229-236: LGTM: FromSnapshotWithParams trait implementation.

The async implementation of the FromSnapshotWithParams trait for PlaintextAggregator is correct and aligns with the PR objectives for hydration functionality. It properly utilizes the new method to create a PlaintextAggregator from a snapshot and parameters.


Line range hint 1-242: Overall assessment: Good implementation with minor improvements needed

The changes in this file successfully implement hydration functionality and improve state management for the PlaintextAggregator, aligning well with the PR objectives. The addition of serialization, checkpointing, and snapshot capabilities enhances the robustness of the system.

Key points:

  1. Proper implementation of necessary traits (Snapshot, FromSnapshotWithParams, Checkpoint).
  2. Introduction of a Repository for state management.
  3. Improved API flexibility with PlaintextAggregatorParams.

Areas for improvement:

  1. Add error handling for checkpoint() calls (lines 169 and 199).
  2. Consider adding documentation comments to new structs and methods.
  3. Add a brief comment explaining the store cloning in the Checkpoint trait implementation.

Once these minor issues are addressed, the implementation will be even more robust and maintainable.

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

3-4: LGTM: New imports for async traits and data management.

The added imports for async_trait and data module are appropriate for the new features implemented in this file.


Line range hint 13-37: LGTM: Enhanced PublicKeyAggregatorState with serialization and initialization.

The changes to PublicKeyAggregatorState are well-implemented:

  1. Deriving serde::Serialize and serde::Deserialize enables state persistence.
  2. The new init method provides a clean way to create the initial state.

These improvements enhance the robustness and usability of the PublicKeyAggregator.


56-70: LGTM: Improved PublicKeyAggregator structure and parameter handling.

The changes to PublicKeyAggregator and the introduction of PublicKeyAggregatorParams are well-designed:

  1. The new store field enables state persistence, meeting the PR objectives.
  2. PublicKeyAggregatorParams improves code organization and flexibility in instantiation.

These changes enhance the maintainability and extensibility of the PublicKeyAggregator.


79-87: LGTM: Updated new method for improved flexibility.

The new method has been appropriately updated to use PublicKeyAggregatorParams and PublicKeyAggregatorState. This change:

  1. Aligns with the new parameter structure.
  2. Allows for flexible state initialization.

The implementation correctly utilizes the provided parameters.


245-252: LGTM: Implemented Snapshot trait for state management.

The Snapshot trait implementation for PublicKeyAggregator is well-designed:

  1. It allows for creating snapshots of the aggregator's state.
  2. Returning a clone of the state ensures snapshot independence.

This implementation enhances the aggregator's state management capabilities, aligning with the PR objectives.


254-267: LGTM: Implemented FromSnapshotWithParams and Checkpoint traits for comprehensive state management.

The implementations of FromSnapshotWithParams and Checkpoint traits are well-designed:

  1. FromSnapshotWithParams is implemented asynchronously, allowing for potential I/O operations during state reconstruction.
  2. Checkpoint correctly returns a clone of the store, enabling state persistence.

These implementations complete the state management feature set, enhancing the robustness and reliability of the PublicKeyAggregator.

packages/ciphernode/core/src/events.rs (5)

153-153: LGTM. Correct classification of Shutdown as a local-only event.

The update to the is_local_only method correctly identifies the Shutdown event as a local-only event, which is consistent with the nature of shutdown operations.


173-173: LGTM. Consistent handling of Shutdown event in EventId conversion.

The update to the From<EnclaveEvent> for EventId implementation correctly handles the Shutdown event, maintaining consistency with the treatment of other event types.


204-204: LGTM. Proper handling of Shutdown event in get_data method.

The update to the get_data method correctly handles the Shutdown event, using the Debug format for its string representation. This is consistent with the treatment of similar event types like EnclaveError.


569-569: LGTM. Please provide more context for the Data error type.

The addition of the Data variant to the EnclaveErrorType enum is noted. This seems to align with the new persistence features mentioned in the PR objectives.

Could you provide more information about what specific data-related errors this new variant is intended to represent? This context would be valuable for understanding its usage and ensuring proper error handling throughout the system.


Line range hint 1-569: Overall, the changes look good with some minor suggestions for improvement.

The additions and modifications related to the new Shutdown event are well-implemented and consistent with the existing code structure. The new Data error type has been noted, though more context would be beneficial. Consider addressing the documentation suggestions to improve code readability and maintainability.

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

6-12: Serialization Added to CommitteeMeta Struct

The addition of serde::Serialize and serde::Deserialize traits to the CommitteeMeta struct enhances its ability to be serialized and deserialized, which is essential for data persistence.


13-19: Implementation of CommitteeMetaFeature::create Method

The create method correctly returns a boxed instance of CommitteeMetaFeature, which aligns with the expected usage patterns for feature instantiation.


23-43: Correct Handling of on_event Method in E3Feature Implementation

The on_event method properly matches the EnclaveEvent::E3Requested event and extracts the necessary data. It then constructs a CommitteeMeta instance and writes it to the repository, followed by updating the context.


45-64: Proper Implementation of Asynchronous hydrate Method

The hydrate method correctly handles the retrieval of CommitteeMeta from the repository. It checks for the presence of metadata in the snapshot and gracefully handles the absence of data, ensuring robust error handling.

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

26-28: ⚠️ Potential issue

Consider making checkpoint an async function if write is async

If the write method on Repository<Self::Snapshot> is asynchronous, then checkpoint should also be marked as async and await the write call. Verify whether write is async and update checkpoint accordingly.

Run the following script to verify whether write is async:

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

41-41: Verify the use of leading double slashes in paths

The path strings in the scope method use leading double slashes (e.g., "//keyshare/{e3_id}"). Confirm whether the extra slash is required for correct path resolution.

Run the following script to check for consistent path usage:

This script counts occurrences of each unique path pattern, helping you determine if the leading double slash is standard across the codebase.

Also applies to: 45-45, 49-49, 53-53, 57-57, 61-61, 65-65, 69-69

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

1-2: Approved

The imports of EvmEventReader and Addr are appropriate and necessary for the updated functionality.

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

41-41: Validate rpc_url with ensure_http_rpc

Good job adding ensure_http_rpc to validate the rpc_url before creating the provider. This ensures that the RPC URL is correctly formatted and helps prevent potential connection issues.


56-60: Subscribe to Shutdown Event

Subscribing to the Shutdown event allows the EnclaveSolWriter actor to handle shutdown signals gracefully, enhancing the robustness of the application.

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

1-1: Import statements updated correctly

The new imports for create_provider_with_signer, ensure_http_rpc, and SignerProvider are appropriately added, aligning with the updated functionality.


12-12: Imports of Shutdown and Subscribe added appropriately

The addition of Shutdown and Subscribe from enclave_core is correct and necessary for handling shutdown events and subscriptions.


37-37: Enhanced RPC URL validation with ensure_http_rpc

Good use of ensure_http_rpc(rpc_url) to validate the RPC URL before creating the provider. This enhances error handling by ensuring that only valid HTTP RPC URLs are used.

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

Line range hint 26-57: Proper handling of shutdown in stream_from_evm

The addition of the shutdown parameter and the use of the select! macro to handle the shutdown signal are well implemented. This ensures that the stream can be gracefully stopped when a shutdown signal is received.


159-177: Unit tests provide good coverage

The unit tests effectively cover the different scenarios for ensure_http_rpc and ensure_ws_rpc, verifying their behavior with various input cases. This helps ensure the correctness of these functions.

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

16-24: Well-defined context structure enhances modularity and readability

The introduction of the E3RequestContext struct provides a clear and organized way to manage dependencies and state within event hooks. This design improves modularity and maintainability by encapsulating related components in a single context.


180-182: Ensure error handling covers all feature hydrations

In the loop where features hydrate the context, if one feature fails to hydrate, the entire context initialization fails. Verify that this is the intended behavior. If partial hydration is acceptable, consider collecting errors and proceeding with the remaining features.

To verify the error handling mechanism, review the hydrate implementations of the features to ensure they fail gracefully and provide meaningful error messages.

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

135-136: Check for concurrent modification risks

Accessing self.features within the event loop should be thread-safe. Ensure that no concurrent modifications can occur that might lead to unexpected behavior.

Consider reviewing the usage of Arc and synchronization primitives to prevent data races.

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

406-407: Check the Result of bus.send for Error Handling

When sending messages with bus.send(GetHistory).await?, ensure that errors are properly handled or propagated.

Confirm that the await? correctly handles potential errors and that the history variable receives the expected data.

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

4-4: Imports updated correctly to include necessary items.

The added imports for E3Requested and Shutdown are appropriate and necessary for the new event handling functionality.


31-31: Subscribed to 'Shutdown' event successfully.

The actor now subscribes to the Shutdown event, ensuring it can handle shutdown signals appropriately.


38-46: Efficient forwarding of EnclaveEvent messages.

The implementation of Handler<EnclaveEvent> now cleanly forwards E3Requested and Shutdown events to their respective handlers using ctx.notify(data), simplifying message processing.


82-88: Implemented Handler<Shutdown> for graceful termination.

The addition of the Shutdown handler allows CiphernodeSelector to stop gracefully, improving the actor's lifecycle management.


51-51: Updated function signature in impl Handler<E3Requested>.

The handle method now directly accepts E3Requested data, enhancing clarity by removing unnecessary pattern matching on EnclaveEvent.

Run the following script to verify that all implementations of Handler<E3Requested> use the updated function signature:

✅ Verification successful

All implementations of Handler<E3Requested> have been updated with the new function signature.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all `Handler<E3Requested>` implementations have the updated signature.

# Search for `impl Handler<E3Requested>` and display the method signatures.
rg -A 3 'impl Handler<E3Requested>' -- 'src/**/*.rs'

Length of output: 106


Script:

#!/bin/bash
# Description: Verify that all `Handler<E3Requested>` implementations have the updated signature by searching within the 'packages' directory.

# Find all Rust source files within the 'packages' directory and search for `impl Handler<E3Requested>` with their method signatures.
fd --extension rs --search-path packages | xargs rg -A 3 'impl Handler<E3Requested>'

Length of output: 480


Script:

#!/bin/bash
# Description: Count the number of `Handler<E3Requested>` implementations to ensure all are updated.

# Find all implementations of `Handler<E3Requested>` within the 'packages' directory and count them.
fd --extension rs --search-path packages | xargs rg 'impl Handler<E3Requested>' -c

Length of output: 140

packages/ciphernode/data/src/lib.rs Show resolved Hide resolved
packages/ciphernode/data/Cargo.toml 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/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: 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
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