dkls23/setup/
sign.rs

1// Copyright (c) Silence Laboratories Pte. Ltd. All Rights Reserved.
2// This software is licensed under the Silence Laboratories License Agreement.
3
4#![allow(missing_docs)]
5
6use core::str::FromStr;
7use std::{marker::PhantomData, sync::Arc, time::Duration};
8
9use derivation_path::DerivationPath;
10use signature::{SignatureEncoding, Signer, Verifier};
11
12use sl_mpc_mate::message::InstanceId;
13
14use crate::{
15    keygen::Keyshare,
16    setup::{
17        keys::{NoSignature, NoSigningKey, NoVerifyingKey},
18        PreSignSetupMessage, ProtocolParticipant, SignSetupMessage,
19    },
20};
21
22/// Default Time-To-Live (TTL) value for messages in seconds
23const DEFAULT_TTL: u64 = 100; // smaller timeout might fail tests
24
25/// A message used for setting up signing operations in a multi-party computation protocol.
26///
27/// This struct encapsulates all necessary information for signing operations,
28/// including participant information, cryptographic keys, and protocol parameters.
29///
30/// # Type Parameters
31/// * `SK` - The type of signing key used for message signatures
32/// * `VK` - The type of verifying key used to verify message signatures
33/// * `MS` - The type of message signature
34/// * `KS` - The type of keyshare used in the protocol
35pub struct SetupMessage<
36    SK = NoSigningKey,
37    VK = NoVerifyingKey,
38    MS = NoSignature,
39    KS = Keyshare,
40> {
41    /// Index of the current party
42    party_idx: usize,
43    /// Signing key for the current party
44    sk: SK,
45    /// Verifying keys for all participants
46    vk: Vec<VK>,
47    /// Instance identifier for the protocol
48    instance: InstanceId,
49    /// Reference to the keyshare used in signing
50    keyshare: Arc<KS>,
51    /// Derivation path for key derivation
52    chain_path: DerivationPath,
53    /// Time-to-live duration for messages
54    ttl: Duration,
55    /// Hash of the message to be signed
56    hash: [u8; 32],
57    /// Phantom data to hold the message signature type
58    marker: PhantomData<MS>,
59}
60
61impl<SK, VK, MS, KS> SetupMessage<SK, VK, MS, KS> {
62    /// Creates a new setup message for signing operations.
63    ///
64    /// # Arguments
65    /// * `instance` - Instance identifier for the protocol
66    /// * `sk` - Signing key for the current party
67    /// * `party_idx` - Index of the current party
68    /// * `vk` - Vector of verifying keys for all participants
69    /// * `share` - Reference to the keyshare used in signing
70    ///
71    /// # Returns
72    /// A new `SetupMessage` instance with default TTL, root derivation path, and zero hash
73    pub fn new(
74        instance: InstanceId,
75        sk: SK,
76        party_idx: usize,
77        vk: Vec<VK>,
78        share: Arc<KS>,
79    ) -> Self {
80        Self {
81            party_idx,
82            sk,
83            vk,
84            instance,
85            keyshare: share.clone(),
86            ttl: Duration::from_secs(DEFAULT_TTL),
87            chain_path: DerivationPath::from_str("m").unwrap(),
88            hash: [0; 32],
89            marker: PhantomData,
90        }
91    }
92
93    /// Sets a custom derivation path for key derivation.
94    ///
95    /// # Arguments
96    /// * `chain_path` - The new derivation path
97    ///
98    /// # Returns
99    /// The modified `SetupMessage` instance
100    pub fn with_chain_path(mut self, chain_path: DerivationPath) -> Self {
101        self.chain_path = chain_path;
102        self
103    }
104
105    /// Sets the hash of the message to be signed.
106    ///
107    /// # Arguments
108    /// * `hash` - The 32-byte hash of the message
109    ///
110    /// # Returns
111    /// The modified `SetupMessage` instance
112    pub fn with_hash(mut self, hash: [u8; 32]) -> Self {
113        self.hash = hash;
114        self
115    }
116
117    /// Optionally sets the hash of the message to be signed.
118    ///
119    /// # Arguments
120    /// * `hash` - Optional 32-byte hash of the message
121    ///
122    /// # Returns
123    /// The modified `SetupMessage` instance
124    pub fn with_hash_opt(mut self, hash: Option<[u8; 32]>) -> Self {
125        if let Some(hash) = hash {
126            self.hash = hash;
127        }
128        self
129    }
130
131    /// Sets a custom time-to-live duration for messages.
132    ///
133    /// # Arguments
134    /// * `ttl` - The new time-to-live duration
135    ///
136    /// # Returns
137    /// The modified `SetupMessage` instance
138    pub fn with_ttl(mut self, ttl: Duration) -> Self {
139        self.ttl = ttl;
140        self
141    }
142
143    /// Returns a clone of the keyshare.
144    pub fn clone_keyshare(&self) -> Arc<KS> {
145        self.keyshare.clone()
146    }
147
148    /// Returns a reference to the derivation path.
149    pub fn get_chain_path(&self) -> &DerivationPath {
150        &self.chain_path
151    }
152}
153
154impl<SK, VK, MS, KS> ProtocolParticipant for SetupMessage<SK, VK, MS, KS>
155where
156    SK: Signer<MS>,
157    MS: SignatureEncoding,
158    VK: AsRef<[u8]> + Verifier<MS>,
159{
160    type MessageSignature = MS;
161    type MessageSigner = SK;
162    type MessageVerifier = VK;
163
164    /// Returns the signing key for the current participant.
165    fn signer(&self) -> &Self::MessageSigner {
166        &self.sk
167    }
168
169    /// Returns the verifying key for a specific participant.
170    ///
171    /// # Arguments
172    /// * `index` - The index of the participant
173    ///
174    /// # Returns
175    /// A reference to the verifying key
176    fn verifier(&self, index: usize) -> &Self::MessageVerifier {
177        &self.vk[index]
178    }
179
180    /// Returns the instance identifier for the protocol.
181    fn instance_id(&self) -> &InstanceId {
182        &self.instance
183    }
184
185    /// Returns the time-to-live duration for messages.
186    fn message_ttl(&self) -> Duration {
187        self.ttl
188    }
189
190    /// Returns the index of the current participant.
191    fn participant_index(&self) -> usize {
192        self.party_idx
193    }
194
195    /// Returns the total number of participants in the protocol.
196    fn total_participants(&self) -> usize {
197        self.vk.len()
198    }
199}
200
201impl<SK, VK, MS> PreSignSetupMessage for SetupMessage<SK, VK, MS, Keyshare>
202where
203    SK: Signer<MS>,
204    MS: SignatureEncoding,
205    VK: AsRef<[u8]> + Verifier<MS>,
206{
207    /// Returns the derivation path for key derivation.
208    fn chain_path(&self) -> &DerivationPath {
209        &self.chain_path
210    }
211
212    /// Returns a reference to the keyshare.
213    fn keyshare(&self) -> &Keyshare {
214        &self.keyshare
215    }
216}
217
218impl<SK, VK, MS> SignSetupMessage for SetupMessage<SK, VK, MS, Keyshare>
219where
220    SK: Signer<MS>,
221    MS: SignatureEncoding,
222    VK: AsRef<[u8]> + Verifier<MS>,
223{
224    /// Returns the hash of the message to be signed.
225    fn message_hash(&self) -> [u8; 32] {
226        self.hash
227    }
228}