1use std::collections::HashSet;
8use std::sync::Arc;
9
10use crate::builder::script::{
11 BaseDepositScript, Multisig, ReplacementDepositScript, SpendableScript, TimelockScript,
12};
13use crate::builder::transaction::create_move_to_vault_txhandler;
14use crate::config::protocol::ProtocolParamset;
15use crate::errors::BridgeError;
16use crate::musig2::AggregateFromPublicKeys;
17use crate::operator::RoundIndex;
18use crate::utils::ScriptBufExt;
19use crate::EVMAddress;
20use bitcoin::address::NetworkUnchecked;
21use bitcoin::secp256k1::PublicKey;
22use bitcoin::{Address, OutPoint, Txid, XOnlyPublicKey};
23use eyre::Context;
24
25#[derive(
27 Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Ord, PartialOrd,
28)]
29pub struct KickoffData {
30 pub operator_xonly_pk: XOnlyPublicKey,
31 pub round_idx: RoundIndex,
32 pub kickoff_idx: u32,
33}
34
35#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
41pub struct DepositData {
42 pub nofn_xonly_pk: Option<XOnlyPublicKey>,
44 pub deposit: DepositInfo,
45 pub actors: Actors,
46 pub security_council: SecurityCouncil,
47}
48
49impl PartialEq for DepositData {
50 fn eq(&self, other: &Self) -> bool {
51 self.security_council == other.security_council
55 && self.deposit.deposit_outpoint == other.deposit.deposit_outpoint
56 && self.get_operators() == other.get_operators()
59 && self.get_verifiers() == other.get_verifiers()
60 && self.get_watchtowers() == other.get_watchtowers()
61 && self.deposit.deposit_type == other.deposit.deposit_type
62 }
63}
64
65impl DepositData {
66 pub fn get_move_txid(
68 &mut self,
69 paramset: &'static ProtocolParamset,
70 ) -> Result<Txid, BridgeError> {
71 Ok(*create_move_to_vault_txhandler(self, paramset)?.get_txid())
72 }
73}
74
75#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
77pub struct DepositInfo {
78 pub deposit_outpoint: OutPoint,
79 pub deposit_type: DepositType,
80}
81
82#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
84pub enum DepositType {
85 BaseDeposit(BaseDepositData),
86 ReplacementDeposit(ReplacementDepositData),
87}
88
89impl DepositData {
90 pub fn get_deposit_outpoint(&self) -> OutPoint {
92 self.deposit.deposit_outpoint
93 }
94 pub fn get_nofn_xonly_pk(&mut self) -> Result<XOnlyPublicKey, BridgeError> {
96 if let Some(pk) = self.nofn_xonly_pk {
97 return Ok(pk);
98 }
99 let verifiers = self.get_verifiers();
100 let nofn_xonly_pk = bitcoin::XOnlyPublicKey::from_musig2_pks(verifiers, None)?;
101 self.nofn_xonly_pk = Some(nofn_xonly_pk);
102 Ok(nofn_xonly_pk)
103 }
104 pub fn get_num_verifiers(&self) -> usize {
106 self.actors.verifiers.len()
107 }
108 pub fn get_num_watchtowers(&self) -> usize {
110 self.get_num_verifiers() + self.actors.watchtowers.len()
111 }
112 pub fn get_verifier_index(&self, public_key: &PublicKey) -> Result<usize, eyre::Report> {
114 self.get_verifiers()
115 .iter()
116 .position(|pk| pk == public_key)
117 .ok_or_else(|| eyre::eyre!("Verifier with public key {} not found", public_key))
118 }
119 pub fn get_watchtower_index(&self, xonly_pk: &XOnlyPublicKey) -> Result<usize, eyre::Report> {
121 self.get_watchtowers()
122 .iter()
123 .position(|pk| pk == xonly_pk)
124 .ok_or_else(|| eyre::eyre!("Watchtower with xonly key {} not found", xonly_pk))
125 }
126 pub fn get_operator_index(&self, xonly_pk: XOnlyPublicKey) -> Result<usize, eyre::Report> {
128 self.get_operators()
129 .iter()
130 .position(|pk| pk == &xonly_pk)
131 .ok_or_else(|| eyre::eyre!("Operator with xonly key {} not found", xonly_pk))
132 }
133 pub fn get_verifiers(&self) -> Vec<PublicKey> {
135 let mut verifiers = self.actors.verifiers.clone();
136 verifiers.sort();
137
138 verifiers
139 }
140 pub fn get_watchtowers(&self) -> Vec<XOnlyPublicKey> {
144 let mut watchtowers = self
145 .actors
146 .verifiers
147 .iter()
148 .map(|pk| pk.x_only_public_key().0)
149 .collect::<Vec<_>>();
150 watchtowers.extend(self.actors.watchtowers.iter());
151 watchtowers.sort();
152 watchtowers
153 }
154 pub fn get_operators(&self) -> Vec<XOnlyPublicKey> {
156 let mut operators = self.actors.operators.clone();
157 operators.sort();
158 operators
159 }
160 pub fn get_num_operators(&self) -> usize {
162 self.actors.operators.len()
163 }
164 pub fn get_deposit_scripts(
167 &mut self,
168 paramset: &'static ProtocolParamset,
169 ) -> Result<Vec<Arc<dyn SpendableScript>>, BridgeError> {
170 let nofn_xonly_pk = self.get_nofn_xonly_pk()?;
171
172 match &mut self.deposit.deposit_type {
173 DepositType::BaseDeposit(original_deposit_data) => {
174 let deposit_script = Arc::new(BaseDepositScript::new(
175 nofn_xonly_pk,
176 original_deposit_data.evm_address,
177 ));
178
179 let recovery_script_pubkey = original_deposit_data
180 .recovery_taproot_address
181 .clone()
182 .assume_checked()
183 .script_pubkey();
184
185 let recovery_extracted_xonly_pk = recovery_script_pubkey
186 .try_get_taproot_pk()
187 .wrap_err("Recovery taproot address is not a valid taproot address")?;
188
189 let script_timelock = Arc::new(TimelockScript::new(
190 Some(recovery_extracted_xonly_pk),
191 paramset.user_takes_after,
192 ));
193
194 Ok(vec![deposit_script, script_timelock])
195 }
196 DepositType::ReplacementDeposit(replacement_deposit_data) => {
197 let deposit_script: Arc<dyn SpendableScript> =
198 Arc::new(ReplacementDepositScript::new(
199 nofn_xonly_pk,
200 replacement_deposit_data.old_move_txid,
201 ));
202 let security_council_script: Arc<dyn SpendableScript> = Arc::new(
203 Multisig::from_security_council(self.security_council.clone()),
204 );
205
206 Ok(vec![deposit_script, security_council_script])
207 }
208 }
209 }
210
211 pub fn are_all_verifiers_unique(&self) -> bool {
213 let set: HashSet<_> = self.actors.verifiers.iter().collect();
214 set.len() == self.actors.verifiers.len()
215 }
216
217 pub fn are_all_watchtowers_unique(&self) -> bool {
219 let set: HashSet<_> = self.get_watchtowers().into_iter().collect();
220 set.len() == self.get_num_watchtowers()
221 }
222
223 pub fn are_all_operators_unique(&self) -> bool {
225 let set: HashSet<_> = self.actors.operators.iter().collect();
226 set.len() == self.actors.operators.len()
227 }
228}
229
230#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
232pub struct Actors {
233 pub verifiers: Vec<PublicKey>,
235 pub watchtowers: Vec<XOnlyPublicKey>,
238 pub operators: Vec<XOnlyPublicKey>,
240}
241
242#[derive(Debug, Clone, PartialEq, Eq)]
244pub struct SecurityCouncil {
245 pub pks: Vec<XOnlyPublicKey>,
246 pub threshold: u32,
247}
248
249impl std::str::FromStr for SecurityCouncil {
250 type Err = eyre::Report;
251
252 fn from_str(s: &str) -> Result<Self, Self::Err> {
253 let mut parts = s.split(':');
254 let threshold_str = parts
255 .next()
256 .ok_or_else(|| eyre::eyre!("Missing threshold"))?;
257 let pks_str = parts
258 .next()
259 .ok_or_else(|| eyre::eyre!("Missing public keys"))?;
260
261 if parts.next().is_some() {
262 return Err(eyre::eyre!("Too many parts in security council string"));
263 }
264
265 let threshold = threshold_str
266 .parse::<u32>()
267 .map_err(|e| eyre::eyre!("Invalid threshold: {}", e))?;
268
269 let pks: Result<Vec<XOnlyPublicKey>, _> = pks_str
270 .split(',')
271 .map(|pk_str| {
272 let bytes = hex::decode(pk_str)
273 .map_err(|e| eyre::eyre!("Invalid hex in public key: {}", e))?;
274 XOnlyPublicKey::from_slice(&bytes)
275 .map_err(|e| eyre::eyre!("Invalid public key: {}", e))
276 })
277 .collect();
278
279 let pks = pks?;
280
281 if pks.is_empty() {
282 return Err(eyre::eyre!("No public keys provided"));
283 }
284
285 if threshold > pks.len() as u32 {
286 return Err(eyre::eyre!(
287 "Threshold cannot be greater than number of public keys"
288 ));
289 }
290
291 Ok(SecurityCouncil { pks, threshold })
292 }
293}
294
295impl serde::Serialize for SecurityCouncil {
296 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
297 where
298 S: serde::Serializer,
299 {
300 serializer.serialize_str(&self.to_string())
301 }
302}
303
304impl<'de> serde::Deserialize<'de> for SecurityCouncil {
305 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
306 where
307 D: serde::Deserializer<'de>,
308 {
309 let s = String::deserialize(deserializer)?;
310 s.parse().map_err(serde::de::Error::custom)
311 }
312}
313
314impl std::fmt::Display for SecurityCouncil {
315 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
316 write!(f, "{}:", self.threshold)?;
317 let pks_str = self
318 .pks
319 .iter()
320 .map(|pk| hex::encode(pk.serialize()))
321 .collect::<Vec<_>>()
322 .join(",");
323 write!(f, "{pks_str}")
324 }
325}
326
327#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
329pub struct BaseDepositData {
330 pub evm_address: EVMAddress,
332 pub recovery_taproot_address: bitcoin::Address<NetworkUnchecked>,
334}
335
336#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
339pub struct ReplacementDepositData {
340 pub old_move_txid: Txid,
342}
343
344#[derive(Debug, Clone, serde::Serialize, PartialEq, Eq)]
347pub struct OperatorData {
348 pub xonly_pk: XOnlyPublicKey,
349 pub reimburse_addr: Address,
350 pub collateral_funding_outpoint: OutPoint,
351}
352
353impl<'de> serde::Deserialize<'de> for OperatorData {
354 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
355 where
356 D: serde::Deserializer<'de>,
357 {
358 #[derive(serde::Deserialize)]
359 struct OperatorDataHelper {
360 xonly_pk: XOnlyPublicKey,
361 reimburse_addr: Address<NetworkUnchecked>,
362 collateral_funding_outpoint: OutPoint,
363 }
364
365 let helper = OperatorDataHelper::deserialize(deserializer)?;
366
367 Ok(OperatorData {
368 xonly_pk: helper.xonly_pk,
369 reimburse_addr: helper.reimburse_addr.assume_checked(),
370 collateral_funding_outpoint: helper.collateral_funding_outpoint,
371 })
372 }
373}