qualia_core_db/modalities/
identity_fabric.rs1#[inline]
15pub fn identity_survives_loss(total_anchors: usize, lost_anchors: usize, quorum: usize) -> bool {
16 quorum > 0 && total_anchors.saturating_sub(lost_anchors) >= quorum
17}
18
19#[inline]
21pub fn surviving_anchors(total_anchors: usize, lost_anchors: usize) -> usize {
22 total_anchors.saturating_sub(lost_anchors)
23}
24
25pub fn recompute_fabric(all_anchors: &[u64], lost: &[u64], out: &mut [u64]) -> usize {
28 let mut n = 0usize;
29 for &a in all_anchors {
30 if !lost.contains(&a) {
31 if n >= out.len() {
32 break;
33 }
34 out[n] = a;
35 n += 1;
36 }
37 }
38 n
39}
40
41#[inline]
43pub const fn identifier_is_not_identity() -> bool {
44 true
45}
46
47pub fn enumerated_identity_confidence(present: usize, total: usize) -> f32 {
52 if total == 0 {
53 0.0
54 } else {
55 present as f32 / total as f32
56 }
57}
58
59pub const SHAMIR_PRIME: u64 = (1u64 << 61) - 1;
67
68#[inline]
69fn m_add(a: u64, b: u64) -> u64 {
70 ((a as u128 + b as u128) % SHAMIR_PRIME as u128) as u64
71}
72#[inline]
73fn m_sub(a: u64, b: u64) -> u64 {
74 ((a as u128 + SHAMIR_PRIME as u128 - (b % SHAMIR_PRIME) as u128) % SHAMIR_PRIME as u128) as u64
75}
76#[inline]
77fn m_mul(a: u64, b: u64) -> u64 {
78 ((a as u128 * b as u128) % SHAMIR_PRIME as u128) as u64
79}
80fn m_pow(mut base: u64, mut exp: u64) -> u64 {
81 base %= SHAMIR_PRIME;
82 let mut r = 1u64;
83 while exp > 0 {
84 if exp & 1 == 1 {
85 r = m_mul(r, base);
86 }
87 base = m_mul(base, base);
88 exp >>= 1;
89 }
90 r
91}
92#[inline]
93fn m_inv(a: u64) -> u64 {
94 m_pow(a, SHAMIR_PRIME - 2) }
96
97fn poly_eval(secret: u64, coeffs: &[u64], x: u64) -> u64 {
99 let mut y = 0u64;
100 for &c in coeffs.iter().rev() {
101 y = m_add(m_mul(y, x), c);
102 }
103 m_add(m_mul(y, x), secret)
104}
105
106pub fn shamir_split(secret: u64, coeffs: &[u64], n: usize, ys: &mut [u64]) -> usize {
110 let s = secret % SHAMIR_PRIME;
111 let mut written = 0usize;
112 for i in 0..n {
113 if i >= ys.len() {
114 break;
115 }
116 ys[i] = poly_eval(s, coeffs, (i + 1) as u64);
117 written += 1;
118 }
119 written
120}
121
122pub fn shamir_reconstruct(xs: &[u64], ys: &[u64], k: usize) -> u64 {
125 let k = k.min(xs.len()).min(ys.len());
126 let mut secret = 0u64;
127 for i in 0..k {
128 let mut num = 1u64; let mut den = 1u64; for j in 0..k {
131 if j == i {
132 continue;
133 }
134 num = m_mul(num, m_sub(0, xs[j]));
135 den = m_mul(den, m_sub(xs[i], xs[j]));
136 }
137 let term = m_mul(ys[i], m_mul(num, m_inv(den)));
138 secret = m_add(secret, term);
139 }
140 secret
141}
142
143#[inline]
149pub fn zkp_capability_granted(trait_proven: bool, identifier_revealed: bool) -> bool {
150 trait_proven && !identifier_revealed
151}
152
153pub fn web_of_trust_confidence(base: f32, depth: u32, decay: f32) -> f32 {
157 base * decay.powi(depth as i32)
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::q_hash;
164
165 #[test]
166 fn shamir_k_of_n_recovers_the_secret() {
167 let secret = 0x0BADC0DE_1234u64;
168 let coeffs = [98765u64, 4242u64]; let mut ys = [0u64; 5];
170 let n = shamir_split(secret, &coeffs, 5, &mut ys); assert_eq!(n, 5);
172 assert_eq!(
174 shamir_reconstruct(&[1, 2, 3], &[ys[0], ys[1], ys[2]], 3),
175 secret
176 );
177 assert_eq!(
178 shamir_reconstruct(&[2, 4, 5], &[ys[1], ys[3], ys[4]], 3),
179 secret
180 );
181 assert_ne!(shamir_reconstruct(&[1, 2], &[ys[0], ys[1]], 2), secret);
183 }
184
185 #[test]
186 fn enumerated_identity_zkp_and_web_of_trust() {
187 assert!((enumerated_identity_confidence(3, 4) - 0.75).abs() < 1e-6);
189 assert_eq!(enumerated_identity_confidence(1, 0), 0.0);
190 assert!(zkp_capability_granted(true, false));
192 assert!(
193 !zkp_capability_granted(true, true),
194 "revealing the identifier defeats the point"
195 );
196 assert!(!zkp_capability_granted(false, false));
197 assert!((web_of_trust_confidence(0.9, 0, 0.5) - 0.9).abs() < 1e-6);
199 assert!((web_of_trust_confidence(0.9, 2, 0.5) - 0.225).abs() < 1e-6);
200 }
201
202 #[test]
203 fn identity_survives_key_loss_with_quorum() {
204 assert!(identity_survives_loss(5, 1, 3));
206 assert!(identity_survives_loss(5, 2, 3));
208 assert!(!identity_survives_loss(5, 3, 3));
210 assert!(!identity_survives_loss(5, 0, 0));
212 }
213
214 #[test]
215 fn fabric_recomputes_from_survivors() {
216 let key = q_hash("anchor:primaryKey");
217 let social = q_hash("anchor:socialAttestation");
218 let bio = q_hash("anchor:biometric");
219 let device = q_hash("anchor:device");
220 let all = [key, social, bio, device];
221 let lost = [key, device]; let mut out = [0u64; 8];
223 let n = recompute_fabric(&all, &lost, &mut out);
224 assert_eq!(
225 n, 2,
226 "identity re-computes from the surviving relational fabric"
227 );
228 assert!(out[..n].contains(&social) && out[..n].contains(&bio));
229 assert!(!out[..n].contains(&key));
230 assert!(identifier_is_not_identity());
231 }
232}