dkls23/keygen/
types.rs

1// Copyright (c) Silence Laboratories Pte. Ltd. All Rights Reserved.
2// This software is licensed under the Silence Laboratories License Agreement.
3
4//! This module defines the error types and common types used throughout the DKG protocol.
5//! It includes error handling for various protocol operations and test utilities for
6//! polynomial operations used in the protocol.
7
8use crate::proto::tags::Error;
9use sl_mpc_mate::coord::MessageSendError;
10
11/// Error type for distributed key generation protocol operations.
12///
13/// This enum defines all possible errors that can occur during the execution of the
14/// DKG protocol, including message handling, cryptographic operations, and protocol
15/// state management.
16#[derive(Debug, thiserror::Error)]
17pub enum KeygenError {
18    /// Error while serializing or deserializing message data, or invalid message length
19    #[error(
20        "Error while deserializing message or invalid message data length"
21    )]
22    InvalidMessage,
23
24    /// The commitment hash provided does not match the expected value
25    #[error("Invalid commitment hash")]
26    InvalidCommitmentHash,
27
28    /// The discrete logarithm proof provided is invalid
29    #[error("Invalid DLog proof")]
30    InvalidDLogProof,
31
32    /// The polynomial point provided is invalid
33    #[error("Invalid Polynomial Point")]
34    InvalidPolynomialPoint,
35
36    /// The key refresh operation failed
37    #[error("Invalid key refresh")]
38    InvalidKeyRefresh,
39
40    /// The quorum change operation failed
41    #[error("Invalid Quorum Change")]
42    InvalidQuorumChange,
43
44    /// The x_i values provided are not unique
45    #[error("Not unique x_i values")]
46    NotUniqueXiValues,
47
48    /// The Big F vector does not match the expected value
49    #[error("Big F vec mismatch")]
50    BigFVecMismatch,
51
52    /// The Feldman verification failed
53    #[error("Failed feldman verify")]
54    FailedFelmanVerify,
55
56    /// The public key in the message does not match the party's public key
57    #[error("Public key mismatch between the message and the party")]
58    PublicKeyMismatch,
59
60    /// The Big S value does not match the expected value
61    #[error("Big S value mismatch")]
62    BigSMismatch,
63
64    /// An error occurred in the PPRF (Pseudorandom Function) operation
65    #[error("PPRF error")]
66    PPRFError(&'static str),
67
68    /// A required message is missing
69    #[error("Missing message")]
70    MissingMessage,
71
72    /// Failed to send a message
73    #[error("Send message")]
74    SendMessage,
75
76    /// A party has decided to abort the protocol
77    #[error("Abort protocol by party {0}")]
78    AbortProtocol(usize),
79}
80
81impl From<MessageSendError> for KeygenError {
82    fn from(_err: MessageSendError) -> Self {
83        KeygenError::SendMessage
84    }
85}
86
87impl From<Error> for KeygenError {
88    fn from(err: Error) -> Self {
89        match err {
90            Error::Abort(p) => KeygenError::AbortProtocol(p as _),
91            Error::Recv => KeygenError::MissingMessage,
92            Error::Send => KeygenError::SendMessage,
93            Error::InvalidMessage => KeygenError::InvalidMessage,
94        }
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use k256::{
101        elliptic_curve::{scalar::FromUintUnchecked, Curve},
102        ProjectivePoint, Scalar, Secp256k1, U256,
103    };
104    use sl_mpc_mate::math::{GroupPolynomial, Polynomial};
105
106    /// Test the derivative calculation for large values
107    ///
108    /// This test verifies that the derivative calculation works correctly with values
109    /// close to the curve order. It tests the polynomial f(x) = 1 + 2x + (p-1)x^2
110    /// where p is the curve order.
111    #[test]
112    fn test_derivative_large() {
113        // order of the curve
114        let order = Secp256k1::ORDER;
115        // f(x) = 1 + 2x + (p-1)x^2
116        // p is the curve order
117        let u_i_k = vec![
118            Scalar::from(1_u64),
119            Scalar::from(2_u64),
120            Scalar::from_uint_unchecked(order.wrapping_sub(&U256::ONE)),
121        ];
122
123        // f'(x) = 2 + 2(p-1)x
124        // f'(2) = (4p-2) mod p => p - 2
125        let poly = Polynomial::<ProjectivePoint>::new(u_i_k);
126        let n = 1;
127
128        let result = poly.derivative_at(n, &Scalar::from(2_u64));
129
130        assert_eq!(
131            result,
132            Scalar::from_uint_unchecked(
133                order.wrapping_sub(&U256::from(2_u64))
134            )
135        );
136    }
137
138    /// Test the derivative calculation for normal values
139    ///
140    /// This test verifies that the derivative calculation works correctly with normal
141    /// polynomial coefficients. It tests the polynomial f(x) = 1 + 2x + 3x^2 + 4x^3.
142    #[test]
143    fn test_derivative_normal() {
144        // f(x) = 1 + 2x + 3x^2 + 4x^3
145        let u_i_k = vec![
146            Scalar::from(1_u64),
147            Scalar::from(2_u64),
148            Scalar::from(3_u64),
149            Scalar::from(4_u64),
150        ];
151
152        let poly = Polynomial::<ProjectivePoint>::new(u_i_k);
153
154        // f''(x) = 6 + 24x
155        let n = 2;
156        // f''(2) = 6 + 24(2) = 54
157        let result = poly.derivative_at(n, &Scalar::from(2_u64));
158
159        assert_eq!(result, Scalar::from(54_u64));
160    }
161
162    /// Test the derivative coefficients calculation
163    ///
164    /// This test verifies that the derivative coefficients are calculated correctly
165    /// for both first and second derivatives of a polynomial with group elements.
166    #[test]
167    fn test_derivative_coeffs() {
168        // f(x) = 1 + 2x + 3x^2 + 4x^3
169        let g = ProjectivePoint::GENERATOR;
170        let u_i_k = vec![
171            (g * Scalar::from(1_u64)),
172            (g * Scalar::from(2_u64)),
173            (g * Scalar::from(3_u64)),
174            (g * Scalar::from(4_u64)),
175        ];
176
177        let poly = GroupPolynomial::<ProjectivePoint>::new(u_i_k);
178
179        // f''(x) = 6 + 24x
180        let n = 2;
181        let coeffs = poly.derivative_coeffs(n).collect::<Vec<_>>();
182
183        assert_eq!(coeffs.len(), 2);
184        assert_eq!(coeffs[0], g * Scalar::from(6_u64));
185        assert_eq!(coeffs[1], g * Scalar::from(24_u64));
186
187        // f'(x) = 2 + 6x + 12x^2
188        let coeffs = poly.derivative_coeffs(1).collect::<Vec<_>>();
189
190        assert_eq!(coeffs.len(), 3);
191        assert_eq!(coeffs[0], g * Scalar::from(2_u64));
192        assert_eq!(coeffs[1], g * Scalar::from(6_u64));
193        assert_eq!(coeffs[2], g * Scalar::from(12_u64));
194    }
195}