-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor State Machine Specification #60
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
Conversation
Summary of ChangesHello @nlordell, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant refactoring of the state machine specification, primarily focusing on improving modularity, type safety, and the robustness of cryptographic ceremonies. Key changes include the extraction of cryptographic and Ethereum-specific logic into dedicated modules, stricter enforcement of participant group sizes for key generation and signing, and a more streamlined handling of preprocessing and participant roles. These updates lay foundational improvements for future features like the complaint flow, making the state machine more maintainable and resilient. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
cc4d908 to
33d9da7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a significant and valuable refactoring of the state machine specification. The changes successfully move cryptographic and Ethereum-specific logic into separate modules, introduce stronger typing for IDs, and refine the state machine logic as described. These improvements enhance modularity, type safety, and clarity. My review has identified a critical bug related to variable shadowing that would prevent secret shares from being distributed, as well as several high-severity issues where physical equality (==) was used instead of structural equality for abstract types, which could lead to incorrect behavior. I have also included a few medium-severity suggestions to improve code correctness and consistency. Overall, this is a solid refactoring, and addressing these points will make it even more robust.
This refactor fixes some of the pending issues that we had previously identified. Namely: 1. We have a minimum group size (derived from the size of the total participation set). 2. We skip key generation and signing ceremonies if we do not have a large enough participant set or signer selection respectively. 3. Preprocess is now an `Option` instead of a `Map`, this is because the state machine only allows a single pending nonces chunk per group, and it simplifies the spec a bit. 4. The `responsible` and `last_participant` are now `Option`s, where `None` is used to indicate that "everyone is responsible". 5. All cryptography and Ethereum specific code has been moved into their own modules to not clutter the `Validator` module. 6. Stronger typing on group and signature IDs. This is a pre-amble to the additions for the new complaint flow. The refac
33d9da7 to
cc3dc1c
Compare
| type preprocess_group = { | ||
| nonces : FROST.nonces IntMap.t; | ||
| pending : FROST.nonces list StringMap.t; | ||
| nonces : (FROST.nonces * MerkleTree.proof) IntMap.t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does the * do here and in the next line? What would be the corresponding ts type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a product type - i.e. a tuple.
So, (int * string) is a type for int-string tuple (42, "the answer").
| rollover : rollover; | ||
| preprocess : preprocess_group StringMap.t; | ||
| signing_ceremonies : signing_ceremony StringMap.t; | ||
| preprocess : preprocess_group GroupMap.t local; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does the "local" do here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 36 to 38 in 6927202
| (** A marker type to indicate state that is local to a specific validator and | |
| only known by them. *) | |
| type 'a local = Local of 'a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just an indicator that the state is only known to the specific validator and not globally derived public state.
| val account : Address.t | ||
| val blocks_per_epoch : int | ||
| val all_participants : Address.t list | ||
| val all_participants : AddressSet.t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: for me a set is not sorted, afaik we do require the participant set to be in some specific order. but I didn't check in detail if the sorting happens elsewhere (couldn't quickly find it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's guaranteed by the Set type in OCaml (it's implemented as binary-tree set specifically). Added a comment in the relevant sections so that it is clear that sorting matters.
|
|
||
| let assert_assumption c m = if c then () else failwith m | ||
| let account_address = Secp256k1.addr Configuration.account | ||
| let participant_identifier participants address = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (so line 148 to 152) is super hard to understand as I am lacking the understanding of the syntax
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a comment to explain what the function does.
| (fun id _ set -> ParticipantSet.add id set) | ||
| items ParticipantSet.empty | ||
|
|
||
| let group_threshold count = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: It would be nice to document the logic about the group size and threshold in "human readable" terms somewhere too
spec/validator.ml
Outdated
| items ParticipantSet.empty | ||
|
|
||
| let group_threshold count = | ||
| let ( /^ ) q d = (q + d - 1) / d in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is Math.ceil?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its ceiling division on integers. Clarified in the code.
| in | ||
| (state', actions) | ||
| | _ -> | ||
| let state' = { state with rollover = Skipped { epoch } } in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment here would be good (similar to how it was done for the signing flow https://github.com/safe-research/shieldnet/pull/60/files#diff-27235707e04ce8bc66a78e46551b0f782475b9fcd817f491fbfc5d546583cd9cR733-R734)
| | Collecting_key_gen_secret_shares { epoch; _ } | ||
| | Signing_epoch_rollover { epoch = { id = epoch; _ }; _ } | ||
| | Signing_epoch_rollover { epoch = { epoch; _ }; _ } | ||
| | Skipped { epoch } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important reminder: This is a new state that we need to implement in the validator
This refactor fixes some of the pending issues that we had previously identified. Namely:
Optioninstead of aMap, this is because the state machine only allows a single pending nonces chunk per group, and it simplifies the spec a bit.responsibleandlast_participantare nowOptions, whereNoneis used to indicate that "everyone is responsible".Validatormodule.This is a pre-amble to the additions for the new complaint flow. The refac