1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::errors::ImplicitPublicKeyError;
use crate::{KeyType, PublicKey};
use borsh::BorshDeserialize;
use curve25519_dalek::ristretto::CompressedRistretto;
use curve25519_dalek::traits::VartimeMultiscalarMul;

pub use curve25519_dalek::ristretto::RistrettoPoint as Point;
pub use curve25519_dalek::scalar::Scalar;

use near_account_id::AccountType;

pub fn vmul2(s1: Scalar, p1: &Point, s2: Scalar, p2: &Point) -> Point {
    Point::vartime_multiscalar_mul(&[s1, s2], [p1, p2].iter().copied())
}

pub trait Packable: Sized {
    type Packed;
    fn unpack(data: &Self::Packed) -> Option<Self>;
    fn pack(&self) -> Self::Packed;
}

pub fn unpack<T: Packable>(data: &T::Packed) -> Option<T> {
    Packable::unpack(data)
}

impl Packable for [u8; 32] {
    type Packed = [u8; 32];

    fn unpack(data: &[u8; 32]) -> Option<Self> {
        Some(*data)
    }

    fn pack(&self) -> [u8; 32] {
        *self
    }
}

impl Packable for Point {
    type Packed = [u8; 32];

    fn unpack(data: &[u8; 32]) -> Option<Self> {
        CompressedRistretto(*data).decompress()
    }

    fn pack(&self) -> [u8; 32] {
        self.compress().to_bytes()
    }
}

impl Packable for Scalar {
    type Packed = [u8; 32];

    fn unpack(data: &[u8; 32]) -> Option<Self> {
        Scalar::from_canonical_bytes(*data).into()
    }

    fn pack(&self) -> [u8; 32] {
        self.to_bytes()
    }
}

impl<T1: Packable<Packed = [u8; 32]>, T2: Packable<Packed = [u8; 32]>> Packable for (T1, T2) {
    type Packed = [u8; 64];

    fn unpack(data: &[u8; 64]) -> Option<Self> {
        let (d1, d2) = stdx::split_array::<64, 32, 32>(data);
        Some((unpack(d1)?, unpack(d2)?))
    }

    fn pack(&self) -> [u8; 64] {
        stdx::join_array(self.0.pack(), self.1.pack())
    }
}

impl<
        T1: Packable<Packed = [u8; 32]>,
        T2: Packable<Packed = [u8; 32]>,
        T3: Packable<Packed = [u8; 32]>,
    > Packable for (T1, T2, T3)
{
    type Packed = [u8; 96];

    fn unpack(data: &[u8; 96]) -> Option<Self> {
        let (d1, d2) = stdx::split_array::<96, 32, 64>(data);
        let (d2, d3) = stdx::split_array::<64, 32, 32>(d2);
        Some((unpack(d1)?, unpack(d2)?, unpack(d3)?))
    }

    fn pack(&self) -> [u8; 96] {
        let mut res = [0; 96];
        let (d1, d2) = stdx::split_array_mut::<96, 32, 64>(&mut res);
        let (d2, d3) = stdx::split_array_mut::<64, 32, 32>(d2);
        *d1 = self.0.pack();
        *d2 = self.1.pack();
        *d3 = self.2.pack();
        res
    }
}

impl PublicKey {
    /// Create the implicit public key from an NEAR-implicit account ID.
    ///
    /// Returns `ImplicitPublicKeyError::AccountIsNotNearImplicit` if the given
    /// account id is not a valid NEAR-implicit account ID.
    /// See [`near_account_id::AccountId#is_near_implicit`] for the definition.
    pub fn from_near_implicit_account(
        account_id: &near_account_id::AccountId,
    ) -> Result<Self, ImplicitPublicKeyError> {
        if account_id.get_account_type() != AccountType::NearImplicitAccount {
            return Err(ImplicitPublicKeyError::AccountIsNotNearImplicit {
                account_id: account_id.clone(),
            });
        }
        let mut public_key_data = Vec::with_capacity(33);
        public_key_data.push(KeyType::ED25519 as u8);
        public_key_data.extend(
            hex::decode(account_id.as_bytes())
                .expect("account id was a valid hex of length 64 resulting in 32 bytes"),
        );
        debug_assert_eq!(public_key_data.len(), 33);
        let public_key = PublicKey::try_from_slice(&public_key_data)
            .expect("we should be able to deserialize ED25519 public key");
        Ok(public_key)
    }
}

macro_rules! unwrap_or_return_false {
    ($e:expr) => {
        match $e {
            ::std::option::Option::Some(v) => v,
            ::std::option::Option::None => return false,
        }
    };
}