unc_crypto/
util.rs

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    /// Create the implicit public key from an UNC-implicit account ID.
102    ///
103    /// Returns `ImplicitPublicKeyError::AccountIsNotNearImplicit` if the given
104    /// account id is not a valid UNC-implicit account ID.
105    /// See [`unc_account_id::AccountId#is_unc_implicit`] for the definition.
106    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}