1use std::collections::{BTreeMap, HashMap};
12
13use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
14
15use silent_payments_core::error::CryptoError;
16use silent_payments_core::keys::{ScanSecretKey, SpendPublicKey};
17
18#[derive(Debug, Clone)]
28pub struct LabelManager {
29 labels: HashMap<PublicKey, (Scalar, u32)>,
30}
31
32impl LabelManager {
33 pub fn new() -> Self {
35 Self {
36 labels: HashMap::new(),
37 }
38 }
39
40 pub fn add_label(
51 &mut self,
52 scan_secret: &ScanSecretKey,
53 _spend_pubkey: &SpendPublicKey,
54 m: u32,
55 secp: &Secp256k1<bitcoin::secp256k1::All>,
56 ) -> Result<(), CryptoError> {
57 let label_scalar = bdk_sp::hashes::get_label_tweak(*scan_secret.as_inner(), m);
59
60 let label_sk = SecretKey::from_slice(&label_scalar.to_be_bytes())
62 .map_err(|_| CryptoError::ZeroTweakResult)?;
63 let label_pubkey = label_sk.public_key(secp);
64
65 self.labels.insert(label_pubkey, (label_scalar, m));
66 Ok(())
67 }
68
69 pub fn contains(&self, m: u32) -> bool {
71 self.labels.values().any(|(_, label_m)| *label_m == m)
72 }
73
74 pub fn len(&self) -> usize {
76 self.labels.len()
77 }
78
79 pub fn is_empty(&self) -> bool {
81 self.labels.is_empty()
82 }
83
84 pub fn to_btree(&self) -> BTreeMap<PublicKey, (Scalar, u32)> {
89 self.labels.iter().map(|(k, v)| (*k, *v)).collect()
90 }
91}
92
93impl Default for LabelManager {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use silent_payments_core::keys::{ScanSecretKey, SpendSecretKey};
103
104 const SCAN_SK_BYTES: [u8; 32] = [
106 0xea, 0xdc, 0x78, 0x16, 0x5f, 0xf1, 0xf8, 0xea, 0x94, 0xad, 0x7c, 0xfd, 0xc5, 0x49, 0x90,
107 0x73, 0x8a, 0x4c, 0x53, 0xf6, 0xe0, 0x50, 0x7b, 0x42, 0x15, 0x42, 0x01, 0xb8, 0xe5, 0xdf,
108 0xf3, 0xb1,
109 ];
110
111 const SPEND_SK_BYTES: [u8; 32] = [
112 0x93, 0xf5, 0xed, 0x90, 0x7a, 0xd5, 0xb2, 0xbd, 0xbb, 0xdc, 0xb5, 0xd9, 0x11, 0x6e, 0xbc,
113 0x0a, 0x4e, 0x1f, 0x92, 0xf9, 0x10, 0xd5, 0x26, 0x02, 0x37, 0xfa, 0x45, 0xa9, 0x40, 0x8a,
114 0xad, 0x16,
115 ];
116
117 fn test_keys() -> (ScanSecretKey, SpendPublicKey) {
118 let secp = Secp256k1::new();
119 let scan_sk = ScanSecretKey::from_slice(&SCAN_SK_BYTES).unwrap();
120 let spend_sk = SpendSecretKey::from_slice(&SPEND_SK_BYTES).unwrap();
121 let spend_pk = spend_sk.public_key(&secp);
122 (scan_sk, spend_pk)
123 }
124
125 #[test]
126 fn new_label_manager_is_empty() {
127 let mgr = LabelManager::new();
128 assert!(mgr.is_empty());
129 assert_eq!(mgr.len(), 0);
130 }
131
132 #[test]
133 fn default_is_empty() {
134 let mgr = LabelManager::default();
135 assert!(mgr.is_empty());
136 }
137
138 #[test]
139 fn add_label_and_contains() {
140 let secp = Secp256k1::new();
141 let (scan_sk, spend_pk) = test_keys();
142
143 let mut mgr = LabelManager::new();
144 mgr.add_label(&scan_sk, &spend_pk, 1, &secp).unwrap();
145
146 assert!(mgr.contains(1));
147 assert!(!mgr.contains(0));
148 assert!(!mgr.contains(2));
149 assert_eq!(mgr.len(), 1);
150 }
151
152 #[test]
153 fn add_multiple_labels() {
154 let secp = Secp256k1::new();
155 let (scan_sk, spend_pk) = test_keys();
156
157 let mut mgr = LabelManager::new();
158 mgr.add_label(&scan_sk, &spend_pk, 0, &secp).unwrap();
159 mgr.add_label(&scan_sk, &spend_pk, 1, &secp).unwrap();
160 mgr.add_label(&scan_sk, &spend_pk, 42, &secp).unwrap();
161
162 assert!(mgr.contains(0));
163 assert!(mgr.contains(1));
164 assert!(mgr.contains(42));
165 assert!(!mgr.contains(99));
166 assert_eq!(mgr.len(), 3);
167 }
168
169 #[test]
170 fn to_btree_produces_matching_structure() {
171 let secp = Secp256k1::new();
172 let (scan_sk, spend_pk) = test_keys();
173
174 let mut mgr = LabelManager::new();
175 mgr.add_label(&scan_sk, &spend_pk, 1, &secp).unwrap();
176 mgr.add_label(&scan_sk, &spend_pk, 5, &secp).unwrap();
177
178 let btree = mgr.to_btree();
179 assert_eq!(btree.len(), 2);
180
181 for (pk, (scalar, m)) in &btree {
183 assert!(mgr.contains(*m));
184 let expected_sk = SecretKey::from_slice(&scalar.to_be_bytes()).expect("valid scalar");
186 let expected_pk = expected_sk.public_key(&secp);
187 assert_eq!(pk, &expected_pk);
188 }
189 }
190
191 #[test]
192 fn different_labels_produce_different_keys() {
193 let secp = Secp256k1::new();
194 let (scan_sk, spend_pk) = test_keys();
195
196 let mut mgr = LabelManager::new();
197 mgr.add_label(&scan_sk, &spend_pk, 0, &secp).unwrap();
198 mgr.add_label(&scan_sk, &spend_pk, 1, &secp).unwrap();
199
200 let btree = mgr.to_btree();
201 let keys: Vec<&PublicKey> = btree.keys().collect();
202 assert_ne!(
203 keys[0], keys[1],
204 "different labels must produce different keys"
205 );
206 }
207}