Skip to content

Conversation

@SimonRastikian
Copy link
Contributor

@SimonRastikian SimonRastikian commented Aug 1, 2025

This part concerns code refactoring from PR #15.
Closes #6

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a major code refactoring as described in the title, addressing issue #6. The refactoring consolidates cryptographic functionality, removes deprecated modules, and restructures the codebase around FROST-based implementations while eliminating the legacy cait-sith specific curve trait.

Key changes include:

  • Removal of deprecated modules (serde.rs, proof modules, triple generation)
  • Consolidation of cryptographic functionality under crypto/ module structure
  • Migration from custom CSCurve trait to FROST library types
  • Restructuring of ECDSA implementation to use FROST primitives

Reviewed Changes

Copilot reviewed 47 out of 51 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/serde.rs Complete removal of serialization utilities module
src/proofs/dlogeq.rs Removal of discrete log equality proof implementation
src/proofs/dlog.rs Removal of discrete log proof implementation
src/participants.rs Updated to use FROST types and consolidated Lagrange coefficient computation
src/lib.rs Simplified module structure removing deprecated components
src/generic_dkg.rs Refactored to use new crypto module structure and FROST polynomials
src/eddsa/test.rs Updated import paths for hash utilities
src/eddsa/sign.rs Updated import paths and method names for FROST compatibility
src/ecdsa/test.rs Simplified test utilities and updated type definitions
src/ecdsa/mod.rs Major restructuring to define ECDSA types using FROST primitives

Copy link
Contributor

@kevindeforth kevindeforth left a comment

Choose a reason for hiding this comment

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

Partial review. Some things that I noticed:

  • some of the protocols have no reference pseudocode (e.g. ecdsa/ot_based_ecdsa/triples/mta)
  • quite a bit of dead code.

}

/// Run the batch random OT protocol between two parties.
#[allow(dead_code)]
Copy link
Contributor

Choose a reason for hiding this comment

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

is this code still used? Why don't we delete it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Used only in unit test, moved there.

Copy link
Contributor Author

@SimonRastikian SimonRastikian Aug 6, 2025

Choose a reason for hiding this comment

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

This created extra "deadcode".
This dead code is not fully dead as:

  1. it is tested
  2. it is used in the MPC repo
  3. Should be 100% used when benchmarking the implementation.
    I push this problem to be solved in [Task] Benchmark implementation #8 and Fix remaining clippy issues and Erase #allow() #12

For the moment I kept allow deadcode for clippy

Copy link
Collaborator

Choose a reason for hiding this comment

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

How is this used in the MPC repo if the function is private to the crate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@netrome not sure what you're asking here. But if it is about run_batch_random_ot function then this has been moved to test module. This code version is outdated see https://github.com/near/threshold-signatures/pull/22/files#diff-828c7600c9ca003925b4117ddedc488adc75289ad104297547edefabda01be56R352-R378

Copy link
Contributor

@kevindeforth kevindeforth left a comment

Choose a reason for hiding this comment

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

Thank you @SimonRastikian for all the hard work!

This is a solid improvement to the code base!

I approve, conditional on:

  • The minor comments (especially the ones related to panics) from this review to be addressed;
  • the remaining unresolved conversations to be followed-up with fixes, or by opening issues for them;
  • @netrome approving to merge.

Disclaimer: I did not properly review the cryptographic protocols. I assumed those were re-factor, not changed. So please lmk if you want me to dive into those as well.

Breaking Changes with MPC node (@netrome):
There are a few breaking changes with respect to the node. I did not investigate in detail. Seems like most of them are imports that changed, and maybe a few visibility issues. But there is a risk of surprises.

```bash error[E0432]: unresolved import `threshold_signatures::ecdsa::sign` --> node/src/indexer/types.rs:16:34 | 16 | use threshold_signatures::ecdsa::sign::FullSignature; | ^^^^ could not find `sign` in `ecdsa`

error[E0432]: unresolved import threshold_signatures::ecdsa::triples
--> node/src/primitives.rs:8:34
|
8 | use threshold_signatures::ecdsa::triples::TripleGenerationOutput;
| ^^^^^^^ could not find triples in ecdsa

error[E0432]: unresolved import threshold_signatures::ecdsa::presign
--> node/src/providers/ecdsa/presign.rs:21:34
|
21 | use threshold_signatures::ecdsa::presign::{presign, PresignArguments, PresignOutput};
| ^^^^^^^ could not find presign in ecdsa

error[E0432]: unresolved import threshold_signatures::ecdsa::triples
--> node/src/providers/ecdsa/presign.rs:22:34
|
22 | use threshold_signatures::ecdsa::triples::TripleGenerationOutput;
| ^^^^^^^ could not find triples in ecdsa

error[E0432]: unresolved import threshold_signatures::ecdsa::presign
--> node/src/providers/ecdsa/sign.rs:17:34
|
17 | use threshold_signatures::ecdsa::presign::PresignOutput;
| ^^^^^^^ could not find presign in ecdsa

error[E0432]: unresolved import threshold_signatures::ecdsa::sign
--> node/src/providers/ecdsa/sign.rs:18:34
|
18 | use threshold_signatures::ecdsa::sign::FullSignature;
| ^^^^ could not find sign in ecdsa

error[E0432]: unresolved import threshold_signatures::ecdsa::triples
--> node/src/providers/ecdsa/triple.rs:18:34
|
18 | use threshold_signatures::ecdsa::triples::TripleGenerationOutput;
| ^^^^^^^ could not find triples in ecdsa

error[E0432]: unresolved import threshold_signatures::ecdsa::sign
--> node/src/providers/ecdsa/mod.rs:28:34
|
28 | use threshold_signatures::ecdsa::sign::FullSignature;
| ^^^^ could not find sign in ecdsa

error[E0433]: failed to resolve: could not find sign in ecdsa
--> node/src/providers/ecdsa/sign.rs:152:53
|
152 | let protocol = threshold_signatures::ecdsa::sign::sign(
| ^^^^ could not find sign in ecdsa
|
help: consider importing one of these modules
|
1 + use threshold_signatures::ecdsa::ot_based_ecdsa::sign;
|
1 + use threshold_signatures::eddsa::sign;
|
help: if you import sign, refer to it directly
|
152 - let protocol = threshold_signatures::ecdsa::sign::sign(
152 + let protocol = sign::sign(
|

error[E0433]: failed to resolve: could not find triples in ecdsa
--> node/src/providers/ecdsa/triple.rs:225:53
|
225 | let protocol = threshold_signatures::ecdsa::triples::generate_triple_many::<Secp256k1, N>(
| ^^^^^^^ could not find triples in ecdsa
|
help: consider importing this module
|
1 + use threshold_signatures::ecdsa::ot_based_ecdsa::triples;
|
help: if you import triples, refer to it directly
|
225 - let protocol = threshold_signatures::ecdsa::triples::generate_triple_many::<Secp256k1, N>(
225 + let protocol = triples::generate_triple_many::<Secp256k1, N>(
|

error[E0599]: no method named num_owned_ready found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:80:68
|
80 | metrics::MPC_OWNED_NUM_TRIPLES_ONLINE.set(triple_store.num_owned_ready() as i64);
| ^^^^^^^^^^^^^^^ method not found in Arc<TripleStorage>

error[E0599]: no method named num_owned_offline found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:82:35
|
82 | .set(triple_store.num_owned_offline() as i64);
| ^^^^^^^^^^^^^^^^^ method not found in Arc<TripleStorage>

error[E0599]: no method named num_owned found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:83:49
|
83 | let my_triples_count = triple_store.num_owned();
| ^^^^^^^^^
|
help: there is a method to_owned with a similar name
|
83 - let my_triples_count = triple_store.num_owned();
83 + let my_triples_count = triple_store.to_owned();
|

error[E0599]: no method named generate_and_reserve_id_range found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:111:22
|
110 | let id_start = triple_store
| ___________-
111 | | .generate_and_reserve_id_range(SUPPORTED_TRIPLE_GENERATION_BATCH_SIZE as u32);
| | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in Arc<TripleStorage>
| |
|
|

error[E0599]: no method named add_owned found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:137:38
|
137 | triple_store.add_owned(id_start.add_to_counter(i as u32)?, paired_triple);
| ^^^^^^^^^
|
help: there is a method to_owned with a similar name, but with different arguments
--> /home/kevin/.rustup/toolchains/1.86.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/borrow.rs:58:5
|
58 | fn to_owned(&self) -> Self::Owned;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: no method named maybe_discard_owned found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:155:30
|
155 | triple_store.maybe_discard_owned(32).await;
| ^^^^^^^^^^^^^^^^^^^ method not found in Arc<TripleStorage>

error[E0599]: no method named take_owned found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/presign.rs:106:75
|
106 | let (paired_triple_id, (triple0, triple1)) = triple_store.take_owned().await;
| ^^^^^^^^^^
|
help: there is a method to_owned with a similar name
|
106 - let (paired_triple_id, (triple0, triple1)) = triple_store.take_owned().await;
106 + let (paired_triple_id, (triple0, triple1)) = triple_store.to_owned().await;
|

error[E0599]: no method named take_unowned found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/presign.rs:257:52
|
257 | let (triple0, triple1) = self.triple_store.take_unowned(self.paired_triple_id)?;
| ^^^^^^^^^^^^
|
help: there is a method to_owned with a similar name, but with different arguments
--> /home/kevin/.rustup/toolchains/1.86.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/borrow.rs:58:5
|
58 | fn to_owned(&self) -> Self::Owned;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: no method named add_unowned found for struct Arc<TripleStorage> in the current scope
--> node/src/providers/ecdsa/triple.rs:269:35
|
269 | self.out_triple_store.add_unowned(
| ----------------------^^^^^^^^^^^ method not found in Arc<TripleStorage>

Some errors have detailed explanations: E0432, E0433, E0599.
For more information about an error, try rustc --explain E0432.

</details>

}

#[cfg(test)]
mod test {
Copy link
Contributor

Choose a reason for hiding this comment

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

Follow-up: Add checks against known expected values to catch future regressions.

#[cfg(test)]
pub(crate) use test::scalar_hash;

use crate::protocol::ProtocolError;
Copy link
Contributor

Choose a reason for hiding this comment

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

lets move the import to the top of the file

if let Some(x) = x {
for x_j in points_set.iter() {
if *x_i == *x_j {
contains_i = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and on line 404, we can do an additional check: if contains_i is already true, then return an error, as the input requirements are not met.

Copy link
Contributor

Choose a reason for hiding this comment

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

The existing code has a few panics and the style could be improved for readability.
Something like the following:

    pub fn put(&mut self, participant: Participant, data: T) {
        let i = self.participants.indices.get(&participant);
        if i.is_none() {
            return;
        }
        let i = *i.unwrap();

        if self.data[i].is_some() {
            return;
        }

        self.data[i] = Some(data);
        self.count += 1;
    }

could be simplified to

pub fn put(&mut self, participant: Participant, data: T) {
    if let Some(&i) = self.participants.indices.get(&participant) {
        if self.data[i].is_none() {
            self.data[i] = Some(data);
            self.count += 1;
        }
    }
}

It might also be worth to investigate if we could simplify a few things by relying on standard library structs, but I haven't looked into that enough to know if that's the case.

@netrome
Copy link
Collaborator

netrome commented Aug 18, 2025

Breaking Changes with MPC node (@netrome):
There are a few breaking changes with respect to the node. I did not investigate in detail. Seems like most of them are imports that changed, and maybe a few visibility issues. But there is a risk of surprises.

I believe these are tackled in near/mpc#867

@kevindeforth
Copy link
Contributor

Breaking Changes with MPC node (@netrome):
There are a few breaking changes with respect to the node. I did not investigate in detail. Seems like most of them are imports that changed, and maybe a few visibility issues. But there is a risk of surprises.

I believe these are tackled in near/mpc#867

Ah, thanks for signaling I was just getting started on that! 😄

Copy link
Collaborator

@netrome netrome left a comment

Choose a reason for hiding this comment

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

Skimmed this now. I created a follow-up for the missing lagrange coefficient tests. Two panics spotted by @kevindeforth remain to be addressed. Please fix these @SimonRastikian and ping me once that's done and I'll approve so we can get this merged.

/// lamda_i(x) = \prod_j (x - x_j)/(x_i - x_j)
/// where j != i
/// If x is None then consider it as 0
pub fn compute_lagrange_coefficient<C: Ciphersuite>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the interest of maintaining our sanity, let's tackle these as a follow-up. Created #40

@SimonRastikian
Copy link
Contributor Author

@netrome I addressed the two comments of yours.
Although I do not find it very clean to have a sending channel fail, I am unsure for the moment what is the best approach to deal with this.

Copy link
Collaborator

@netrome netrome left a comment

Choose a reason for hiding this comment

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

Thank you for fixing the last panics. Let's get this merged!

@netrome
Copy link
Collaborator

netrome commented Aug 19, 2025

Although I do not find it very clean to have a sending channel fail, I am unsure for the moment what is the best approach to deal with this.

Can you elaborate? Is this due to the fallible serialization being used in the send functions, and if so - would it be possible to formulate these in a non-fallible way?

@SimonRastikian
Copy link
Contributor Author

SimonRastikian commented Aug 19, 2025

Yes it is due to the fallible serialization. I currently do not know if there is a way to do this without failing, but understanding the communication layer is to be done. See task #39.

@gilcu3 gilcu3 self-requested a review August 19, 2025 09:04
@SimonRastikian SimonRastikian merged commit 5fd9fe7 into main Aug 19, 2025
1 check passed
@SimonRastikian SimonRastikian deleted the simon/code-refactor branch September 4, 2025 08:14
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.

Make the code uniform across the different schemes

5 participants