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