1use crate::errors::ImplicitPublicKeyError;
2use crate::{KeyType, PublicKey};
3use borsh::BorshDeserialize;
4use curve25519_dalek::ristretto::CompressedRistretto;
5use curve25519_dalek::traits::VartimeMultiscalarMul;
6
7pub use curve25519_dalek::ristretto::RistrettoPoint as Point;
8pub use curve25519_dalek::scalar::Scalar;
9
10use unc_account_id::AccountType;
11
12pub fn vmul2(s1: Scalar, p1: &Point, s2: Scalar, p2: &Point) -> Point {
13 Point::vartime_multiscalar_mul(&[s1, s2], [p1, p2].iter().copied())
14}
15
16pub trait Packable: Sized {
17 type Packed;
18 fn unpack(data: &Self::Packed) -> Option<Self>;
19 fn pack(&self) -> Self::Packed;
20}
21
22pub fn unpack<T: Packable>(data: &T::Packed) -> Option<T> {
23 Packable::unpack(data)
24}
25
26impl Packable for [u8; 32] {
27 type Packed = [u8; 32];
28
29 fn unpack(data: &[u8; 32]) -> Option<Self> {
30 Some(*data)
31 }
32
33 fn pack(&self) -> [u8; 32] {
34 *self
35 }
36}
37
38impl Packable for Point {
39 type Packed = [u8; 32];
40
41 fn unpack(data: &[u8; 32]) -> Option<Self> {
42 CompressedRistretto(*data).decompress()
43 }
44
45 fn pack(&self) -> [u8; 32] {
46 self.compress().to_bytes()
47 }
48}
49
50impl Packable for Scalar {
51 type Packed = [u8; 32];
52
53 fn unpack(data: &[u8; 32]) -> Option<Self> {
54 Scalar::from_canonical_bytes(*data).into()
55 }
56
57 fn pack(&self) -> [u8; 32] {
58 self.to_bytes()
59 }
60}
61
62impl<T1: Packable<Packed = [u8; 32]>, T2: Packable<Packed = [u8; 32]>> Packable for (T1, T2) {
63 type Packed = [u8; 64];
64
65 fn unpack(data: &[u8; 64]) -> Option<Self> {
66 let (d1, d2) = stdx::split_array::<64, 32, 32>(data);
67 Some((unpack(d1)?, unpack(d2)?))
68 }
69
70 fn pack(&self) -> [u8; 64] {
71 stdx::join_array(self.0.pack(), self.1.pack())
72 }
73}
74
75impl<
76 T1: Packable<Packed = [u8; 32]>,
77 T2: Packable<Packed = [u8; 32]>,
78 T3: Packable<Packed = [u8; 32]>,
79 > Packable for (T1, T2, T3)
80{
81 type Packed = [u8; 96];
82
83 fn unpack(data: &[u8; 96]) -> Option<Self> {
84 let (d1, d2) = stdx::split_array::<96, 32, 64>(data);
85 let (d2, d3) = stdx::split_array::<64, 32, 32>(d2);
86 Some((unpack(d1)?, unpack(d2)?, unpack(d3)?))
87 }
88
89 fn pack(&self) -> [u8; 96] {
90 let mut res = [0; 96];
91 let (d1, d2) = stdx::split_array_mut::<96, 32, 64>(&mut res);
92 let (d2, d3) = stdx::split_array_mut::<64, 32, 32>(d2);
93 *d1 = self.0.pack();
94 *d2 = self.1.pack();
95 *d3 = self.2.pack();
96 res
97 }
98}
99
100impl PublicKey {
101 pub fn from_unc_implicit_account(
107 account_id: &unc_account_id::AccountId,
108 ) -> Result<Self, ImplicitPublicKeyError> {
109 if account_id.get_account_type() != AccountType::UtilityAccount {
110 return Err(ImplicitPublicKeyError::AccountIsNotNearImplicit {
111 account_id: account_id.clone(),
112 });
113 }
114 let mut public_key_data = Vec::with_capacity(33);
115 public_key_data.push(KeyType::ED25519 as u8);
116 public_key_data.extend(
117 hex::decode(account_id.as_bytes())
118 .expect("account id was a valid hex of length 64 resulting in 32 bytes"),
119 );
120 debug_assert_eq!(public_key_data.len(), 33);
121 let public_key = PublicKey::try_from_slice(&public_key_data)
122 .expect("we should be able to deserialize ED25519 public key");
123 Ok(public_key)
124 }
125}
126
127macro_rules! unwrap_or_return_false {
128 ($e:expr) => {
129 match $e {
130 ::std::option::Option::Some(v) => v,
131 ::std::option::Option::None => return false,
132 }
133 };
134}