1use crate::{Error, Result};
2use lit_rust_crypto::{
3 blsful::inner_types as bls,
4 curve25519_dalek, decaf377,
5 ed448_goldilocks::{self, sha3},
6 elliptic_curve::{
7 bigint::{
8 ArrayEncoding, ByteArray, Encoding, NonZero, Random, RandomMod, U256, U512, U768, U896,
9 },
10 ops::Reduce,
11 rand_core::{CryptoRng, RngCore},
12 scalar::FromUintUnchecked,
13 },
14 jubjub,
15 k256::{
16 self,
17 sha2::{self, Digest},
18 },
19 p256, p384, pallas, vsss_rs,
20};
21use serde::{Deserialize, Deserializer, Serialize, Serializer};
22use std::fmt::{self, Debug, Display, Formatter};
23use std::hash::{Hash, Hasher};
24use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
25use std::str::FromStr;
26
27macro_rules! from_impl_peer_id {
28 ($($primitive:ident),+$(,)*) => {
29 $(
30 impl TryFrom<$primitive> for PeerId {
31 type Error = Error;
32
33 fn try_from(value: $primitive) -> Result<Self> {
34 PeerId::try_from(U256::from(value))
35 }
36 }
37 )+
38 };
39}
40
41macro_rules! from_impl_nonzero_peer_id {
42 ($($nonzero:ident => $primitive:ident),+$(,)*) => {
43 $(
44 impl TryFrom<PeerId> for $nonzero {
45 type Error = Error;
46
47 fn try_from(value: PeerId) -> Result<Self> {
48 let value = $primitive::try_from(value)?;
49 $nonzero::new(value).ok_or_else(|| Error::Parse("PeerId is zero".to_string()))
50 }
51 }
52
53 impl TryFrom<&PeerId> for $nonzero {
54 type Error = Error;
55
56 fn try_from(value: &PeerId) -> Result<Self> {
57 Self::try_from(*value)
58 }
59 }
60 )+
61 };
62}
63
64from_impl_peer_id!(u128, u64, u32, u16, u8);
65from_impl_nonzero_peer_id!(
66 NonZeroUsize => usize,
67 NonZeroU128 => u128,
68 NonZeroU64 => u64,
69 NonZeroU32 => u32,
70 NonZeroU16 => u16,
71 NonZeroU8 => u8,
72);
73
74pub trait FromPeerIdDirect {
75 fn from_peer_id(peer_id: PeerId) -> Self;
76}
77
78#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
86#[repr(transparent)]
87pub struct PeerId(pub NonZero<U256>);
88
89impl Serialize for PeerId {
90 fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>
91 where
92 S: Serializer,
93 {
94 if s.is_human_readable() {
95 s.serialize_str(&self.to_string())
96 } else {
97 s.serialize_bytes(&self.0.to_be_byte_array())
98 }
99 }
100}
101
102impl<'de> Deserialize<'de> for PeerId {
103 fn deserialize<D>(d: D) -> std::result::Result<Self, D::Error>
104 where
105 D: Deserializer<'de>,
106 {
107 if d.is_human_readable() {
108 let value = <&str>::deserialize(d)?;
109 value.parse().map_err(serde::de::Error::custom)
110 } else {
111 let bytes = Vec::<u8>::deserialize(d)?;
112 PeerId::from_slice(&bytes).map_err(serde::de::Error::custom)
113 }
114 }
115}
116
117impl Default for PeerId {
118 fn default() -> Self {
119 PeerId::NOT_ASSIGNED
120 }
121}
122
123impl Hash for PeerId {
124 fn hash<H: Hasher>(&self, state: &mut H) {
125 (*self.0).hash(state);
126 }
127}
128
129impl TryFrom<U256> for PeerId {
130 type Error = Error;
131
132 fn try_from(value: U256) -> Result<Self> {
133 Option::<PeerId>::from(NonZero::new(value).map(PeerId))
134 .ok_or_else(|| Error::Parse("PeerId is zero".to_string()))
135 }
136}
137
138impl TryFrom<&U256> for PeerId {
139 type Error = Error;
140
141 fn try_from(value: &U256) -> Result<Self> {
142 PeerId::try_from(*value)
143 }
144}
145
146impl From<PeerId> for U256 {
147 fn from(value: PeerId) -> Self {
148 *value.0
149 }
150}
151
152impl From<&PeerId> for U256 {
153 fn from(value: &PeerId) -> Self {
154 *value.0
155 }
156}
157
158impl From<PeerId> for ethers::types::U256 {
159 fn from(value: PeerId) -> Self {
160 ethers::types::U256::from(value.0.to_be_bytes())
161 }
162}
163
164impl TryFrom<ethers::types::U256> for PeerId {
165 type Error = Error;
166 fn try_from(value: ethers::types::U256) -> Result<Self> {
167 #[cfg(target_pointer_width = "32")]
168 {
169 Self::try_from(U256::from_words([
170 value.0[0] as u32,
171 (value.0[0] >> 32) as u32,
172 value.0[1] as u32,
173 (value.0[1] >> 32) as u32,
174 value.0[2] as u32,
175 (value.0[2] >> 32) as u32,
176 value.0[3] as u32,
177 (value.0[3] >> 32) as u32,
178 ]))
179 }
180 #[cfg(target_pointer_width = "64")]
181 Self::try_from(U256::from_words(value.0))
182 }
183}
184
185impl TryFrom<usize> for PeerId {
186 type Error = Error;
187
188 fn try_from(value: usize) -> Result<Self> {
189 PeerId::try_from(U256::from_u64(value as u64))
190 }
191}
192
193impl From<NonZeroU128> for PeerId {
194 fn from(value: NonZeroU128) -> Self {
195 PeerId(NonZero::from(value))
196 }
197}
198
199impl From<NonZeroU64> for PeerId {
200 fn from(value: NonZeroU64) -> Self {
201 PeerId(NonZero::from(value))
202 }
203}
204
205impl From<NonZeroU32> for PeerId {
206 fn from(value: NonZeroU32) -> Self {
207 PeerId(NonZero::from(value))
208 }
209}
210
211impl From<NonZeroU16> for PeerId {
212 fn from(value: NonZeroU16) -> Self {
213 PeerId(NonZero::from(value))
214 }
215}
216
217impl From<NonZeroU8> for PeerId {
218 fn from(value: NonZeroU8) -> Self {
219 PeerId(NonZero::from(value))
220 }
221}
222
223impl TryFrom<PeerId> for usize {
224 type Error = Error;
225
226 fn try_from(value: PeerId) -> Result<Self> {
227 if value.0.bits() > 64 {
228 return Err(Error::Parse(format!(
229 "PeerId too large to convert to usize: {}",
230 value.0
231 )));
232 }
233 Ok(value.0.as_words()[0] as usize)
234 }
235}
236
237impl TryFrom<&PeerId> for usize {
238 type Error = Error;
239
240 fn try_from(value: &PeerId) -> Result<Self> {
241 Self::try_from(*value)
242 }
243}
244
245impl TryFrom<PeerId> for u128 {
246 type Error = Error;
247
248 fn try_from(value: PeerId) -> Result<Self> {
249 if value.0.bits() > 128 {
250 return Err(Error::Parse(format!(
251 "PeerId too large to convert to u128: {}",
252 value.0
253 )));
254 }
255 let words = value.0.as_words();
256 Ok((words[0] as u128) | ((words[1] as u128) << 64))
257 }
258}
259
260impl TryFrom<&PeerId> for u128 {
261 type Error = Error;
262
263 fn try_from(value: &PeerId) -> Result<Self> {
264 Self::try_from(*value)
265 }
266}
267
268impl TryFrom<PeerId> for u64 {
269 type Error = Error;
270
271 fn try_from(value: PeerId) -> Result<Self> {
272 if value.0.bits() > 64 {
273 return Err(Error::Parse(format!(
274 "PeerId too large to convert to u64: {}",
275 value.0
276 )));
277 }
278 #[cfg(target_pointer_width = "32")]
279 {
280 let words = value.0.as_words();
281 Ok((words[0] as u64) | ((words[1] as u64) << 32))
282 }
283 #[cfg(target_pointer_width = "64")]
284 Ok(value.0.as_words()[0])
285 }
286}
287
288impl TryFrom<&PeerId> for u64 {
289 type Error = Error;
290
291 fn try_from(value: &PeerId) -> Result<Self> {
292 Self::try_from(*value)
293 }
294}
295
296impl TryFrom<PeerId> for u32 {
297 type Error = Error;
298
299 fn try_from(value: PeerId) -> Result<Self> {
300 value.0.as_words()[0].try_into().map_err(|_| Error::Parse(format!("unable to convert PeerId '{}' to 32-bit integer. PeerId is too large to convert to u32", value)))
301 }
302}
303
304impl TryFrom<&PeerId> for u32 {
305 type Error = Error;
306
307 fn try_from(value: &PeerId) -> Result<Self> {
308 Self::try_from(*value)
309 }
310}
311
312impl TryFrom<PeerId> for u16 {
313 type Error = Error;
314
315 fn try_from(value: PeerId) -> Result<Self> {
316 value.0.as_words()[0].try_into().map_err(|_| Error::Parse(format!("unable to convert PeerId '{}' to 16-bit integer. PeerId is too large to convert to u16", value)))
317 }
318}
319
320impl TryFrom<&PeerId> for u16 {
321 type Error = Error;
322
323 fn try_from(value: &PeerId) -> Result<Self> {
324 Self::try_from(*value)
325 }
326}
327
328impl TryFrom<PeerId> for u8 {
329 type Error = Error;
330
331 fn try_from(value: PeerId) -> Result<Self> {
332 value.0.as_words()[0].try_into().map_err(|_| Error::Parse(format!("unable to convert PeerId '{}' to 8-bit integer. PeerId is too large to convert to u8", value)))
333 }
334}
335
336impl TryFrom<&PeerId> for u8 {
337 type Error = Error;
338
339 fn try_from(value: &PeerId) -> Result<Self> {
340 Self::try_from(*value)
341 }
342}
343
344impl TryFrom<Vec<u8>> for PeerId {
345 type Error = Error;
346
347 fn try_from(value: Vec<u8>) -> Result<Self> {
348 Self::try_from(value.as_slice())
349 }
350}
351
352impl TryFrom<&Vec<u8>> for PeerId {
353 type Error = Error;
354
355 fn try_from(value: &Vec<u8>) -> Result<Self> {
356 Self::try_from(value.as_slice())
357 }
358}
359
360impl TryFrom<&[u8]> for PeerId {
361 type Error = Error;
362
363 fn try_from(value: &[u8]) -> Result<Self> {
364 Self::from_slice(value)
365 }
366}
367
368impl TryFrom<Box<[u8]>> for PeerId {
369 type Error = Error;
370
371 fn try_from(value: Box<[u8]>) -> Result<Self> {
372 Self::try_from(value.as_ref())
373 }
374}
375
376impl TryFrom<&[u8; 32]> for PeerId {
377 type Error = Error;
378
379 fn try_from(value: &[u8; 32]) -> Result<Self> {
380 Ok(PeerId::from_be_slice(value))
381 }
382}
383
384impl TryFrom<[u8; 32]> for PeerId {
385 type Error = Error;
386 fn try_from(value: [u8; 32]) -> Result<Self> {
387 Ok(PeerId::from_be_slice(&value))
388 }
389}
390
391impl TryFrom<&ByteArray<U256>> for PeerId {
392 type Error = Error;
393
394 fn try_from(value: &ByteArray<U256>) -> Result<Self> {
395 Self::try_from(*value)
396 }
397}
398
399impl TryFrom<ByteArray<U256>> for PeerId {
400 type Error = Error;
401
402 fn try_from(value: ByteArray<U256>) -> Result<Self> {
403 PeerId::try_from(U256::from_be_byte_array(value))
404 }
405}
406
407impl From<PeerId> for Vec<u8> {
408 fn from(value: PeerId) -> Self {
409 value.0.to_be_byte_array().to_vec()
410 }
411}
412
413impl From<&PeerId> for Vec<u8> {
414 fn from(value: &PeerId) -> Self {
415 value.0.to_be_byte_array().to_vec()
416 }
417}
418
419impl Debug for PeerId {
420 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
421 if self == &PeerId::NOT_ASSIGNED {
422 return write!(f, "PeerId({})", self);
423 }
424 write!(f, "PeerId(NonZero(Uint({}))", self)
425 }
426}
427
428impl Display for PeerId {
429 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
430 if self == &PeerId::NOT_ASSIGNED {
431 return write!(f, "NotAssigned");
432 }
433 let bytes = self.0.to_be_byte_array();
435 let mut index = bytes.len() - 1;
436 for (i, byte) in bytes.iter().enumerate() {
437 if *byte != 0 {
438 index = i;
439 break;
440 }
441 }
442 let output = hex::encode(&bytes[index..]);
443 index = output.chars().position(|c| c != '0').unwrap_or(0);
444 write!(f, "{}", &output[index..])
445 }
446}
447
448impl FromStr for PeerId {
449 type Err = Error;
450
451 fn from_str(s: &str) -> Result<Self> {
452 if s.len() > 64 {
453 return Err(Error::Parse(format!(
454 "PeerId too large to convert from string: PeerId: {}",
455 s
456 )));
457 }
458 let mut padded = s.to_string();
459 if padded.len() & 1 == 1 {
460 padded.insert(0, '0');
461 }
462 let bytes = hex::decode(padded)?;
463 let mut array = [0u8; 32];
464 let start = array.len().saturating_sub(bytes.len());
465 array[start..].copy_from_slice(&bytes);
466 PeerId::try_from(U256::from_be_slice(&array))
467 }
468}
469
470impl From<PeerId> for k256::Scalar {
471 fn from(value: PeerId) -> Self {
472 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
473 <k256::Scalar as Reduce<U512>>::reduce(U512::from_be_byte_array(digest))
474 }
475}
476
477impl From<PeerId> for k256::NonZeroScalar {
478 fn from(value: PeerId) -> Self {
479 let scalar = k256::Scalar::from(value);
480 k256::NonZeroScalar::new(scalar).expect("scalar is somehow zero")
481 }
482}
483
484impl From<PeerId> for p256::Scalar {
485 fn from(value: PeerId) -> Self {
486 const N: NonZero<U512> = NonZero::from_uint(U512::from_be_hex(
487 "0000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
488 ));
489 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
490 let wide_value = U512::from_be_byte_array(digest);
491 let scalar = wide_value % N;
492 let (_, lo) = scalar.split();
493
494 p256::Scalar::from_uint_unchecked(lo)
495 }
496}
497
498impl From<PeerId> for p256::NonZeroScalar {
499 fn from(value: PeerId) -> Self {
500 let scalar = p256::Scalar::from(value);
501 p256::NonZeroScalar::new(scalar).expect("scalar is somehow zero")
502 }
503}
504
505impl From<PeerId> for curve25519_dalek::Scalar {
506 fn from(value: PeerId) -> Self {
507 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
508 let digest: [u8; 64] = digest
509 .as_slice()
510 .try_into()
511 .expect("digest is the wrong length");
512 curve25519_dalek::Scalar::from_bytes_mod_order_wide(&digest)
513 }
514}
515
516impl From<PeerId> for vsss_rs::curve25519::WrappedScalar {
517 fn from(value: PeerId) -> Self {
518 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
519 let digest: [u8; 64] = digest
520 .as_slice()
521 .try_into()
522 .expect("digest is the wrong length");
523 Self(vsss_rs::curve25519_dalek::Scalar::from_bytes_mod_order_wide(&digest))
524 }
525}
526
527impl From<PeerId> for p384::Scalar {
528 fn from(value: PeerId) -> Self {
529 use sha3::digest::{ExtendableOutput, Update};
530 const N: NonZero<U768> = NonZero::from_uint(U768::from_be_hex(
531 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973",
532 ));
533 let mut hasher = sha3::Shake128::default();
534 hasher.update(&value.0.to_be_byte_array());
535 let digest = hasher.finalize_boxed(96);
536 let wide_value = U768::from_be_slice(digest.as_ref());
537
538 let scalar = wide_value % N;
539 let (_, lo) = scalar.split();
540 p384::Scalar::from_uint_unchecked(lo)
541 }
542}
543
544impl From<PeerId> for p384::NonZeroScalar {
545 fn from(value: PeerId) -> Self {
546 let scalar = p384::Scalar::from(value);
547 p384::NonZeroScalar::new(scalar).expect("scalar is somehow zero")
548 }
549}
550
551impl From<PeerId> for ed448_goldilocks::Scalar {
552 fn from(value: PeerId) -> Self {
553 use sha3::digest::{ExtendableOutput, Update};
554
555 let mut hasher = sha3::Shake128::default();
556 hasher.update(&value.0.to_be_byte_array());
557 let digest = hasher.finalize_boxed(114);
558 let wide_bytes = ed448_goldilocks::WideScalarBytes::from_slice(digest.as_ref());
559 <ed448_goldilocks::Scalar as Reduce<U896>>::reduce_bytes(wide_bytes)
560 }
561}
562
563impl From<PeerId> for jubjub::Scalar {
564 fn from(value: PeerId) -> Self {
565 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
566 <jubjub::Scalar as Reduce<U512>>::reduce(U512::from_be_byte_array(digest))
567 }
568}
569
570impl From<PeerId> for bls::Scalar {
571 fn from(value: PeerId) -> Self {
572 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
573 <bls::Scalar as Reduce<U512>>::reduce(U512::from_be_byte_array(digest))
574 }
575}
576
577impl From<PeerId> for decaf377::Fr {
578 fn from(value: PeerId) -> Self {
579 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
580 Self::from_le_bytes_mod_order(&digest)
581 }
582}
583
584impl From<PeerId> for pallas::Scalar {
585 fn from(value: PeerId) -> Self {
586 let digest = sha2::Sha512::digest(value.0.to_be_byte_array());
587 let n = U512::from_be_byte_array(digest);
588 Self::reduce(n)
589 }
590}
591
592impl FromPeerIdDirect for k256::Scalar {
593 fn from_peer_id(peer_id: PeerId) -> Self {
594 Self::from_uint_unchecked(*peer_id.0.as_ref())
595 }
596}
597
598impl FromPeerIdDirect for k256::NonZeroScalar {
599 fn from_peer_id(peer_id: PeerId) -> Self {
600 let scalar = k256::Scalar::from_peer_id(peer_id);
601 #[allow(dead_code)]
603 struct NZScalar {
604 scalar: k256::Scalar,
605 }
606 let t = NZScalar { scalar };
607 unsafe { std::mem::transmute(t) }
608 }
609}
610
611impl FromPeerIdDirect for p256::Scalar {
612 fn from_peer_id(peer_id: PeerId) -> Self {
613 Self::from_uint_unchecked(*peer_id.0.as_ref())
614 }
615}
616
617impl FromPeerIdDirect for p256::NonZeroScalar {
618 fn from_peer_id(peer_id: PeerId) -> Self {
619 let scalar = p256::Scalar::from_peer_id(peer_id);
620 #[allow(dead_code)]
622 struct NZScalar {
623 scalar: p256::Scalar,
624 }
625 let t = NZScalar { scalar };
626 unsafe { std::mem::transmute(t) }
627 }
628}
629
630impl FromPeerIdDirect for p384::Scalar {
631 fn from_peer_id(peer_id: PeerId) -> Self {
632 Self::from_uint_unchecked(peer_id.0.as_ref().resize())
633 }
634}
635
636impl FromPeerIdDirect for p384::NonZeroScalar {
637 fn from_peer_id(peer_id: PeerId) -> Self {
638 let scalar = p384::Scalar::from_peer_id(peer_id);
639 #[allow(dead_code)]
641 struct NZScalar {
642 scalar: p384::Scalar,
643 }
644 let t = NZScalar { scalar };
645 unsafe { std::mem::transmute(t) }
646 }
647}
648
649impl FromPeerIdDirect for curve25519_dalek::Scalar {
650 fn from_peer_id(peer_id: PeerId) -> Self {
651 Self::from_uint_unchecked(*peer_id.0.as_ref())
652 }
653}
654
655impl FromPeerIdDirect for vsss_rs::curve25519::WrappedScalar {
656 fn from_peer_id(peer_id: PeerId) -> Self {
657 Self::from_uint_unchecked(*peer_id.0.as_ref())
658 }
659}
660
661impl FromPeerIdDirect for ed448_goldilocks::Scalar {
662 fn from_peer_id(peer_id: PeerId) -> Self {
663 Self::from_uint_unchecked(peer_id.0.as_ref().resize())
664 }
665}
666
667impl FromPeerIdDirect for bls::Scalar {
668 fn from_peer_id(peer_id: PeerId) -> Self {
669 Self::from_uint_unchecked(peer_id.0.as_ref().resize())
670 }
671}
672
673impl FromPeerIdDirect for jubjub::Scalar {
674 fn from_peer_id(peer_id: PeerId) -> Self {
675 #[cfg(target_pointer_width = "32")]
676 {
677 let words = *peer_id.0.as_ref().as_words();
678 let raw_words = [
679 words[0] as u64 | (words[1] as u64) << 32,
680 words[2] as u64 | (words[3] as u64) << 32,
681 words[4] as u64 | (words[5] as u64) << 32,
682 words[6] as u64 | (words[7] as u64) << 32,
683 ];
684 Self::from_raw(raw_words)
685 }
686 #[cfg(target_pointer_width = "64")]
687 Self::from_raw(*peer_id.0.as_ref().as_words())
688 }
689}
690
691impl FromPeerIdDirect for decaf377::Fr {
692 fn from_peer_id(peer_id: PeerId) -> Self {
693 let bytes = peer_id.0.as_ref().to_le_bytes();
694 Self::from_bytes_checked(&bytes).expect("to be small enough to work")
695 }
696}
697
698impl FromPeerIdDirect for pallas::Scalar {
699 fn from_peer_id(peer_id: PeerId) -> Self {
700 Self::from_uint_unchecked(*peer_id.0.as_ref())
701 }
702}
703
704impl PeerId {
705 pub const ONE: Self = PeerId(NonZero::<U256>::ONE);
706 pub const NOT_ASSIGNED: Self = PeerId(NonZero::<U256>::from_uint(U256::MAX));
707
708 pub fn is_not_assigned(&self) -> bool {
709 self.0 == Self::NOT_ASSIGNED.0
710 }
711
712 pub const fn from_u8(value: u8) -> Self {
713 PeerId(NonZero::<U256>::from_uint(U256::from_u8(value)))
714 }
715
716 pub const fn from_u16(value: u16) -> Self {
717 PeerId(NonZero::<U256>::from_uint(U256::from_u16(value)))
718 }
719
720 pub const fn from_u32(value: u32) -> Self {
721 PeerId(NonZero::<U256>::from_uint(U256::from_u32(value)))
722 }
723
724 pub const fn from_u64(value: u64) -> Self {
725 PeerId(NonZero::<U256>::from_uint(U256::from_u64(value)))
726 }
727
728 pub const fn from_u128(value: u128) -> Self {
729 PeerId(NonZero::<U256>::from_uint(U256::from_u128(value)))
730 }
731
732 pub const fn from_usize(value: usize) -> Self {
733 PeerId(NonZero::<U256>::from_uint(U256::from_u64(value as u64)))
734 }
735
736 pub const fn from_be_slice(bytes: &[u8; 32]) -> Self {
738 Self(NonZero::from_uint(U256::from_be_slice(bytes)))
739 }
740
741 pub fn from_slice(value: &[u8]) -> Result<Self> {
742 if value.is_empty() {
743 return Err(Error::Parse("PeerId slice cannot be empty".to_string()));
744 }
745 let array = if value.len() > 32 {
746 sha2::Sha512_256::digest(value).into()
747 } else {
748 let start = 32usize.saturating_sub(value.len());
749 let mut array = [0u8; 32];
750 array[start..].copy_from_slice(value);
751 array
752 };
753 PeerId::try_from(U256::from_be_slice(&array))
754 }
755
756 pub fn random(mut rng: impl RngCore + CryptoRng) -> Self {
757 PeerId(NonZero::<U256>::from_uint(U256::random(&mut rng)))
758 }
759
760 pub fn random_less_than(mut rng: impl RngCore + CryptoRng, upper: U256) -> Self {
761 let upper = NonZero::new(upper).expect("upper bound must be non-zero");
762 PeerId(NonZero::<U256>::from_uint(U256::random_mod(
763 &mut rng, &upper,
764 )))
765 }
766}
767
768#[test]
769fn test_parse_peer_id() {
770 let peer_id = PeerId::random(vsss_rs::elliptic_curve::rand_core::OsRng);
771 let u256: ethers::types::U256 = peer_id.into();
772 let peer_id2 = u256.try_into().unwrap();
773 assert_eq!(peer_id, peer_id2);
774}
775
776#[test]
777fn test_into_scalar_pallas() {
778 use rand_core::SeedableRng;
779
780 let rng = rand_chacha::ChaChaRng::seed_from_u64(0);
781 let peer_id = PeerId::random(rng);
782 let id: pallas::Scalar = peer_id.into();
783 let limbs = id.to_raw();
784 assert_eq!(
785 limbs,
786 [
787 0x3fd0ff79135bb946,
788 0xcacf6941e56db2e4,
789 0xa49547659cb1baa7,
790 0x04e7181b6f5533de,
791 ]
792 );
793}