1#![warn(missing_docs)]
2
3use std::num::NonZeroU32;
41use std::ops::Add;
42use std::ops::Deref;
43use std::ops::Neg;
44use std::ops::Sub;
45use std::str::FromStr;
46
47use ethereum_types::H160;
48use num_bigint::BigUint;
49use serde::Deserialize;
50use serde::Serialize;
51
52use crate::algebra::AbelianGroup;
53use crate::algebra::Zero;
54use crate::ecc::HashStr;
55use crate::error::Error;
56use crate::error::Result;
57
58const FULL_ROTATION_DENOMINATOR: NonZeroU32 = NonZeroU32::MIN.saturating_add(359);
60
61#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Debug, Serialize, Deserialize, Hash)]
72pub struct Did(H160);
73
74impl std::fmt::Display for Did {
75 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76 let inner = &self.0;
77 write!(f, "0x{inner:x}")
78 }
79}
80
81#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize, Hash)]
93pub struct BiasId {
94 bias: Did,
96 did: Did,
98}
99
100pub trait Rotate<Rhs = u16> {
105 type Output;
107 fn rotate(&self, angle: Rhs) -> Self::Output;
109}
110
111impl Rotate<u16> for Did {
112 type Output = Self;
113 fn rotate(&self, angle: u16) -> Self::Output {
114 *self + Did::dyadic_fraction(angle.into(), FULL_ROTATION_DENOMINATOR)
115 }
116}
117
118impl BiasId {
119 pub fn new(bias: Did, did: Did) -> BiasId {
121 BiasId {
122 bias,
123 did: did - bias,
124 }
125 }
126
127 pub fn to_did(self) -> Did {
129 self.did + self.bias
130 }
131
132 pub fn pos(&self) -> Did {
134 self.did
135 }
136}
137
138impl PartialOrd for BiasId {
139 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
140 Some(self.cmp(other))
141 }
142}
143
144impl PartialEq<Did> for BiasId {
145 fn eq(&self, rhs: &Did) -> bool {
146 let id: Did = self.into();
147 id == *rhs
148 }
149}
150
151impl Ord for BiasId {
152 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
153 if other.bias != self.bias {
154 let did: Did = other.into();
155 let bid = BiasId::new(self.bias, did);
156 self.did.cmp(&bid.did)
157 } else {
158 self.did.cmp(&other.did)
159 }
160 }
161}
162
163impl From<BiasId> for Did {
164 fn from(id: BiasId) -> Did {
165 BiasId::to_did(id)
166 }
167}
168
169impl From<&BiasId> for Did {
170 fn from(id: &BiasId) -> Did {
171 BiasId::to_did(*id)
172 }
173}
174
175impl From<u32> for Did {
176 fn from(id: u32) -> Did {
177 let bytes = id.to_be_bytes();
178 let mut out = [0u8; Self::BYTE_LEN];
179 for (dst, src) in out.iter_mut().rev().zip(bytes.iter().rev()) {
180 *dst = *src;
181 }
182 Self::from_be_bytes(out)
183 }
184}
185
186impl TryFrom<HashStr> for Did {
187 type Error = Error;
188 fn try_from(s: HashStr) -> Result<Self> {
189 Did::from_str(&s.inner())
190 }
191}
192
193impl Did {
194 const BITS: usize = 160;
195
196 const BYTE_LEN: usize = 20;
197
198 const ZERO: Self = Self(H160([0u8; Self::BYTE_LEN]));
199
200 fn from_be_bytes(bytes: [u8; Self::BYTE_LEN]) -> Self {
201 Self(H160::from(bytes))
202 }
203
204 fn to_be_bytes(self) -> [u8; Self::BYTE_LEN] {
205 self.0.to_fixed_bytes()
206 }
207
208 pub fn in_range(&self, base_id: Self, a: Self, b: Self) -> bool {
215 *self - base_id > a - base_id && b - base_id > *self - base_id
217 }
218
219 pub fn bias(&self, did: Self) -> BiasId {
221 BiasId::new(did, *self)
222 }
223
224 pub fn rotate_affine(&self, scalar: u16) -> Result<Vec<Did>> {
236 let Some(denominator) = NonZeroU32::new(u32::from(scalar)) else {
237 return Err(Error::InvalidAffineScalar);
238 };
239
240 Ok((0..scalar)
241 .map(|i| {
242 let offset = Did::dyadic_fraction(i.into(), denominator);
243 *self + offset
244 })
245 .collect())
246 }
247
248 pub fn power_of_two(bit: usize) -> Self {
253 if bit >= Self::BITS {
254 return Self::ZERO;
255 }
256
257 let mut bytes = [0u8; Self::BYTE_LEN];
258 set_ring_bit(&mut bytes, bit);
259 Self::from_be_bytes(bytes)
260 }
261
262 fn dyadic_fraction(numerator: u32, denominator: NonZeroU32) -> Self {
266 let denominator = u64::from(denominator.get());
267 let mut remainder = u64::from(numerator) % denominator;
268 let mut bytes = [0u8; Self::BYTE_LEN];
269
270 for bit in (0..Self::BITS).rev() {
271 remainder *= 2;
272 if remainder >= denominator {
273 set_ring_bit(&mut bytes, bit);
274 remainder -= denominator;
275 }
276 }
277
278 Self::from_be_bytes(bytes)
279 }
280
281 fn add_mod(self, rhs: Self) -> Self {
285 let lhs = self.to_be_bytes();
286 let rhs = rhs.to_be_bytes();
287 let mut out = [0u8; Self::BYTE_LEN];
288 let mut carry = 0u16;
289
290 for ((dst, lhs), rhs) in out
291 .iter_mut()
292 .rev()
293 .zip(lhs.iter().rev())
294 .zip(rhs.iter().rev())
295 {
296 let sum = u16::from(*lhs) + u16::from(*rhs) + carry;
297 let [low, _] = sum.to_le_bytes();
298 *dst = low;
299 carry = sum >> 8;
300 }
301
302 Self::from_be_bytes(out)
303 }
304
305 fn additive_inverse(self) -> Self {
309 let mut out = self.to_be_bytes();
310 for byte in &mut out {
311 *byte = !*byte;
312 }
313
314 let mut carry = 1u16;
315 for byte in out.iter_mut().rev() {
316 let sum = u16::from(*byte) + carry;
317 let [low, _] = sum.to_le_bytes();
318 *byte = low;
319 carry = sum >> 8;
320 }
321
322 Self::from_be_bytes(out)
323 }
324}
325
326pub trait SortRing {
329 fn sort(&mut self, did: Did);
331}
332
333impl SortRing for Vec<Did> {
334 fn sort(&mut self, did: Did) {
335 self.sort_by(|a, b| {
336 let (da, db) = (*a - did, *b - did);
337 da.cmp(&db)
338 });
339 }
340}
341
342impl Deref for Did {
343 type Target = H160;
344 fn deref(&self) -> &Self::Target {
345 &self.0
346 }
347}
348
349impl From<Did> for H160 {
350 fn from(a: Did) -> Self {
351 a.0
352 }
353}
354
355impl From<Did> for BigUint {
356 fn from(did: Did) -> BigUint {
357 BigUint::from_bytes_be(did.as_bytes())
358 }
359}
360
361impl From<BigUint> for Did {
362 fn from(a: BigUint) -> Self {
363 let bytes = a.to_bytes_be();
364 let mut out = [0u8; Self::BYTE_LEN];
365
366 for (dst, src) in out
369 .iter_mut()
370 .rev()
371 .zip(bytes.iter().rev().take(Self::BYTE_LEN))
372 {
373 *dst = *src;
374 }
375
376 Self::from_be_bytes(out)
377 }
378}
379
380impl From<H160> for Did {
381 fn from(addr: H160) -> Self {
382 Self(addr)
383 }
384}
385
386impl FromStr for Did {
387 type Err = Error;
388 fn from_str(s: &str) -> Result<Self> {
389 Ok(Self(H160::from_str(s).map_err(|_| Error::BadCHexInCache)?))
390 }
391}
392
393impl Default for Did {
394 fn default() -> Self {
395 Self::ZERO
396 }
397}
398
399impl Zero for Did {
400 fn zero() -> Self {
401 Self::ZERO
402 }
403
404 fn is_zero(&self) -> bool {
405 *self == Self::ZERO
406 }
407}
408
409impl AbelianGroup for Did {}
410
411impl Neg for Did {
412 type Output = Self;
413 fn neg(self) -> Self {
414 self.additive_inverse()
415 }
416}
417
418impl Neg for &Did {
419 type Output = Did;
420
421 fn neg(self) -> Self::Output {
422 (*self).neg()
423 }
424}
425
426impl Add for Did {
427 type Output = Self;
428 fn add(self, rhs: Self) -> Self {
429 self.add_mod(rhs)
430 }
431}
432
433impl Sub for Did {
434 type Output = Self;
435 fn sub(self, rhs: Self) -> Self {
436 self + (-rhs)
437 }
438}
439
440fn set_ring_bit(bytes: &mut [u8; Did::BYTE_LEN], bit: usize) {
444 let Some(byte) = (Did::BYTE_LEN - 1).checked_sub(bit / 8) else {
445 return;
446 };
447
448 if let Some(slot) = bytes.get_mut(byte) {
449 *slot |= 1u8 << (bit % 8);
450 }
451}
452
453#[cfg(test)]
454mod tests {
455 use std::collections::BTreeSet;
456 use std::str::FromStr;
457
458 use super::*;
459 use crate::algebra::assert_abelian_group_laws;
460
461 fn ring_size() -> BigUint {
462 BigUint::from(1u8) << 160usize
463 }
464
465 fn samples() -> Vec<Did> {
466 vec![
467 Did::zero(),
468 Did::from(1u32),
469 Did::from(10u32),
470 Did::from(ring_size() - BigUint::from(1u8)),
471 Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap(),
472 ]
473 }
474
475 #[test]
476 fn did_abelian_group_laws_hold_on_representative_set() {
477 assert_abelian_group_laws(&samples());
478 }
479
480 #[test]
481 fn did_addition_matches_biguint_ring_oracle() {
482 for lhs in samples() {
483 for rhs in samples() {
484 let expected = Did::from((BigUint::from(lhs) + BigUint::from(rhs)) % ring_size());
485 assert_eq!(lhs + rhs, expected);
486 }
487 }
488 }
489
490 #[test]
491 fn did_dyadic_fraction_matches_biguint_oracle() {
492 for denominator in [1u32, 2, 3, 7, 17, 360, 361, u16::MAX.into()] {
493 let Some(nonzero_denominator) = NonZeroU32::new(denominator) else {
494 continue;
495 };
496
497 for numerator in [
498 0,
499 1,
500 denominator / 2,
501 denominator.saturating_sub(1),
502 denominator,
503 denominator.saturating_add(1),
504 denominator.saturating_mul(2).saturating_add(1),
505 ] {
506 let expected =
507 Did::from(ring_size() * BigUint::from(numerator) / BigUint::from(denominator));
508 assert_eq!(
509 Did::dyadic_fraction(numerator, nonzero_denominator),
510 expected
511 );
512 }
513 }
514 }
515
516 #[test]
517 fn test_did() {
518 let a = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
519 let b = Did::from_str("0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E").unwrap();
520 let c = Did::from_str("0xc0ffee254729296a45a3885639AC7E10F9d54979").unwrap();
521 assert!(c > b && b > a);
522 }
523
524 #[test]
525 fn test_finate_ring_neg() {
526 let zero = Did::from_str("0x0000000000000000000000000000000000000000").unwrap();
527 let a = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
528 assert_eq!(-a + a, zero);
529 assert_eq!(-(-a), a);
530 }
531
532 #[test]
533 fn test_sort() {
534 let a = Did::from_str("0xaaE807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
535 let b = Did::from_str("0xbb9999cf1046e68e36E1aA2E0E07105eDDD1f08E").unwrap();
536 let c = Did::from_str("0xccffee254729296a45a3885639AC7E10F9d54979").unwrap();
537 let d = Did::from_str("0xdddfee254729296a45a3885639AC7E10F9d54979").unwrap();
538 let mut v = vec![c, b, a, d];
539 v.sort(a);
540 assert_eq!(v, vec![a, b, c, d]);
541 v.sort(b);
542 assert_eq!(v, vec![b, c, d, a]);
543 v.sort(c);
544 assert_eq!(v, vec![c, d, a, b]);
545 v.sort(d);
546 assert_eq!(v, vec![d, a, b, c]);
547 }
548
549 #[test]
550 fn rotate_transformation() {
551 assert_eq!(Did::from(0u32), Did::from(BigUint::from(2u16).pow(160)));
552 let did = Did::from(10u32);
553 let result = did.rotate(360);
554 assert_eq!(result, did);
555 }
556
557 #[test]
558 fn right_shift() {
559 let did = Did::from(10u32);
560 let ret: Did = did.rotate(180);
561 assert_eq!(ret, did + Did::from(BigUint::from(2u16).pow(159)));
562 }
563
564 #[test]
565 fn did_fixed_width_arithmetic_matches_biguint_ring_oracle() -> Result<()> {
566 let zero = Did::from(0u32);
567 let one = Did::from(1u32);
568 let max = Did::from(ring_size() - BigUint::from(1u8));
569 let sample = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0")?;
570
571 assert_eq!(max + one, zero);
572 assert_eq!(zero - one, max);
573 assert_eq!(-zero, zero);
574 assert_eq!(-sample + sample, zero);
575
576 for (lhs, rhs) in [(zero, one), (one, max), (sample, max), (sample, sample)] {
577 let expected = Did::from((BigUint::from(lhs) + BigUint::from(rhs)) % ring_size());
578 assert_eq!(lhs + rhs, expected);
579 }
580 Ok(())
581 }
582
583 #[test]
584 fn did_rotate_matches_biguint_dyadic_offset_oracle() {
585 let did = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
586
587 for angle in [0u16, 1, 90, 180, 359, 360, 361, u16::MAX] {
588 let expected_offset =
589 Did::from(ring_size() * BigUint::from(angle) / BigUint::from(360u32));
590 assert_eq!(did.rotate(angle), did + expected_offset);
591 }
592 }
593
594 #[test]
595 fn did_power_of_two_matches_biguint_oracle() {
596 for bit in [0usize, 1, 8, 31, 32, 63, 64, 127, 128, 159, 160, 255] {
597 let expected = Did::from(BigUint::from(1u8) << bit);
598 assert_eq!(Did::power_of_two(bit), expected);
599 }
600 }
601
602 #[test]
603 fn test_did_affine() -> Result<()> {
604 let did = Did::from(10u32);
605 let affine_dids = did.rotate_affine(4)?;
606 assert_eq!(affine_dids.len(), 4);
607 assert_eq!(affine_dids, vec![
608 did.rotate(0),
609 did.rotate(90),
610 did.rotate(180),
611 did.rotate(270)
612 ]);
613 Ok(())
614 }
615
616 #[test]
617 fn rotate_affine_rejects_zero_scalar() {
618 let did = Did::from(10u32);
619
620 assert!(matches!(
621 did.rotate_affine(0),
622 Err(Error::InvalidAffineScalar)
623 ));
624 }
625
626 #[test]
627 fn rotate_affine_supports_non_degree_divisors() -> Result<()> {
628 let did = Did::from(10u32);
629 let affine_dids = did.rotate_affine(7)?;
630 let unique_dids = affine_dids.iter().copied().collect::<BTreeSet<_>>();
631
632 assert_eq!(affine_dids.len(), 7);
633 assert_eq!(unique_dids.len(), 7);
634 assert_eq!(affine_dids.first(), Some(&did));
635 Ok(())
636 }
637
638 #[test]
639 fn rotate_affine_supports_more_than_360_replicas() -> Result<()> {
640 let did = Did::from(10u32);
641 let affine_dids = did.rotate_affine(361)?;
642 let unique_dids = affine_dids.iter().copied().collect::<BTreeSet<_>>();
643
644 assert_eq!(affine_dids.len(), 361);
645 assert_eq!(unique_dids.len(), 361);
646 assert_eq!(affine_dids.first(), Some(&did));
647 Ok(())
648 }
649
650 #[test]
651 fn test_dump_and_load() {
652 assert!(Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab").is_err());
654 assert!(Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab00").is_err());
655
656 assert_eq!(
658 Did::from_str("11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap(),
659 Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap(),
660 );
661
662 let did = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
664 assert_eq!(
665 did.to_string(),
666 "0x11e807fcc88dd319270493fb2e822e388fe36ab0"
667 );
668
669 let did = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
671 assert_eq!(
672 serde_json::to_string(&did).unwrap(),
673 "\"0x11e807fcc88dd319270493fb2e822e388fe36ab0\""
674 );
675
676 let did =
678 serde_json::from_str::<Did>("\"0x11e807fcc88dd319270493fb2e822e388fe36ab0\"").unwrap();
679 assert_eq!(
680 did,
681 Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap()
682 );
683
684 let did = Did::from_str("0x11E807fcc88dD319270493fB2e822e388Fe36ab0").unwrap();
686 assert_eq!(
687 format!("{did}"),
688 "0x11e807fcc88dd319270493fb2e822e388fe36ab0"
689 );
690 assert_eq!(
691 format!("{did:?}"),
692 "Did(0x11e807fcc88dd319270493fb2e822e388fe36ab0)"
693 );
694 }
695}