multi_party_schnorr/keygen/
refresh.rs1use elliptic_curve::{group::GroupEncoding, Group};
5use ff::Field;
6
7use crate::common::traits::GroupElem;
8
9#[cfg(feature = "serde")]
10use crate::common::{ser::Serializable, utils::serde_point};
11
12#[cfg_attr(
13 feature = "serde",
14 derive(serde::Serialize, serde::Deserialize),
15 serde(bound(
16 serialize = "G: Group + GroupEncoding, G::Scalar: Serializable",
17 deserialize = "G: Group + GroupEncoding, G::Scalar: Serializable"
18 ))
19)]
20pub struct KeyRefreshData<G>
21where
22 G: Group + GroupEncoding,
23{
24 pub party_id: u8,
26 pub threshold: u8,
27 pub total_parties: u8,
28 pub(crate) s_i_0: G::Scalar,
33
34 pub(crate) lost_keyshare_party_ids: Vec<u8>,
37
38 #[cfg_attr(feature = "serde", serde(with = "serde_point"))]
40 pub expected_public_key: G,
41 pub root_chain_code: [u8; 32],
42}
43
44impl<G> KeyRefreshData<G>
45where
46 G: GroupElem,
47{
48 pub fn recovery_data_for_lost(
50 lost_keyshare_party_ids: Vec<u8>,
51 expected_public_key: G,
52 party_id: u8,
53 threshold: u8,
54 total_parties: u8,
55 ) -> Self {
56 KeyRefreshData {
57 threshold,
58 total_parties,
59 party_id,
60 s_i_0: <G::Scalar as Field>::ZERO,
61 lost_keyshare_party_ids,
62 expected_public_key,
63 root_chain_code: [0; 32],
64 }
65 }
66
67 pub fn make_refresh_data_migrate(
68 party_id: u8,
69 threshold: u8,
70 total_parties: u8,
71 s_i_0: G::Scalar,
72 expected_public_key: G,
73 root_chain_code: [u8; 32],
74 ) -> Self {
75 KeyRefreshData {
76 threshold,
77 total_parties,
78 party_id,
79 s_i_0,
80 lost_keyshare_party_ids: vec![],
81 expected_public_key,
82 root_chain_code,
83 }
84 }
85
86 pub fn s_i(&self) -> &G::Scalar {
88 &self.s_i_0
89 }
90
91 pub fn lost_party_ids(&self) -> &[u8] {
93 &self.lost_keyshare_party_ids
94 }
95}
96
97#[cfg(test)]
98mod test {
99 #[cfg(any(feature = "eddsa", feature = "taproot"))]
100 use crate::{
101 common::utils::support::run_keygen,
102 keygen::utils::{run_import, run_recovery, run_refresh},
103 };
104
105 #[cfg(feature = "eddsa")]
106 use curve25519_dalek::EdwardsPoint;
107
108 #[cfg(feature = "taproot")]
109 use k256::ProjectivePoint;
110
111 #[cfg(feature = "eddsa")]
112 #[test]
113 fn refresh_curve25519() {
114 let _ = run_refresh::<3, 5, EdwardsPoint>();
115 let _ = run_refresh::<2, 3, EdwardsPoint>();
116 let _ = run_refresh::<5, 10, EdwardsPoint>();
117 let _ = run_refresh::<9, 20, EdwardsPoint>();
118 }
119
120 #[cfg(feature = "eddsa")]
121 #[test]
122 fn key_import_curve25519() {
123 let _ = run_import::<3, 5, EdwardsPoint>();
124 let _ = run_import::<2, 3, EdwardsPoint>();
125 let _ = run_import::<5, 10, EdwardsPoint>();
126 let _ = run_import::<9, 20, EdwardsPoint>();
127 }
128
129 #[cfg(feature = "eddsa")]
130 #[test]
131 fn recovery_curve25519() {
132 let keyshares = run_keygen::<3, 5, EdwardsPoint>();
133 run_recovery::<3, 5, EdwardsPoint>(&keyshares, vec![0]).unwrap();
134 run_recovery::<3, 5, EdwardsPoint>(&keyshares, vec![1, 2]).unwrap();
135 run_recovery::<3, 5, EdwardsPoint>(&keyshares, vec![3, 4]).unwrap();
136 run_recovery::<3, 5, EdwardsPoint>(&keyshares, vec![2, 3]).unwrap();
137 run_recovery::<3, 5, EdwardsPoint>(&keyshares, vec![4, 1]).unwrap();
138 }
139
140 #[cfg(feature = "eddsa")]
141 #[test]
142 #[should_panic(expected = "Error during key refresh or recovery protocol")]
143 fn recovery_invalid_curve25519() {
144 let keyshares = run_keygen::<3, 5, EdwardsPoint>();
145 if let Err(e) = run_recovery::<3, 5, EdwardsPoint>(&keyshares, vec![1, 2, 3]) {
146 panic!("{}", e);
147 }
148 }
149
150 #[cfg(feature = "taproot")]
151 #[test]
152 fn refresh_taproot() {
153 let _ = run_refresh::<3, 5, ProjectivePoint>();
154 let _ = run_refresh::<2, 3, ProjectivePoint>();
155 let _ = run_refresh::<5, 10, ProjectivePoint>();
156 let _ = run_refresh::<9, 20, ProjectivePoint>();
157 }
158
159 #[cfg(feature = "taproot")]
160 #[test]
161 fn recovery_taproot() {
162 let keyshares = run_keygen::<3, 5, ProjectivePoint>();
163 run_recovery::<3, 5, ProjectivePoint>(&keyshares, vec![0]).unwrap();
164 run_recovery::<3, 5, ProjectivePoint>(&keyshares, vec![1, 2]).unwrap();
165 run_recovery::<3, 5, ProjectivePoint>(&keyshares, vec![3, 4]).unwrap();
166 run_recovery::<3, 5, ProjectivePoint>(&keyshares, vec![2, 3]).unwrap();
167 run_recovery::<3, 5, ProjectivePoint>(&keyshares, vec![4, 1]).unwrap();
168 }
169
170 #[cfg(feature = "taproot")]
171 #[test]
172 #[should_panic(expected = "Error during key refresh or recovery protocol")]
173 fn recovery_invalid_taproot() {
174 let keyshares = run_keygen::<3, 5, ProjectivePoint>();
175 if let Err(e) = run_recovery::<3, 5, ProjectivePoint>(&keyshares, vec![1, 2, 3]) {
176 panic!("{}", e);
177 }
178 }
179
180 #[cfg(feature = "taproot")]
181 #[test]
182 fn key_import_taproot() {
183 let _ = run_import::<3, 5, ProjectivePoint>();
184 let _ = run_import::<2, 3, ProjectivePoint>();
185 let _ = run_import::<5, 10, ProjectivePoint>();
186 let _ = run_import::<9, 20, ProjectivePoint>();
187 }
188}