snarkvm_console_account/compute_key/
try_from.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18#[cfg(feature = "private_key")]
19impl<N: Network> TryFrom<PrivateKey<N>> for ComputeKey<N> {
20    type Error = Error;
21
22    /// Derives the account compute key from an account private key.
23    fn try_from(private_key: PrivateKey<N>) -> Result<Self, Self::Error> {
24        Self::try_from(&private_key)
25    }
26}
27
28#[cfg(feature = "private_key")]
29impl<N: Network> TryFrom<&PrivateKey<N>> for ComputeKey<N> {
30    type Error = Error;
31
32    /// Derives the account compute key from an account private key.
33    fn try_from(private_key: &PrivateKey<N>) -> Result<Self, Self::Error> {
34        // Compute pk_sig := G^sk_sig.
35        let pk_sig = N::g_scalar_multiply(&private_key.sk_sig());
36        // Compute pr_sig := G^r_sig.
37        let pr_sig = N::g_scalar_multiply(&private_key.r_sig());
38        // Output the compute key.
39        Self::try_from((pk_sig, pr_sig))
40    }
41}
42
43impl<N: Network> TryFrom<(Group<N>, Group<N>)> for ComputeKey<N> {
44    type Error = Error;
45
46    /// Derives the account compute key from a tuple `(pk_sig, pr_sig)`.
47    fn try_from((pk_sig, pr_sig): (Group<N>, Group<N>)) -> Result<Self> {
48        // Compute sk_prf := HashToScalar(pk_sig || pr_sig).
49        let sk_prf = N::hash_to_scalar_psd4(&[pk_sig.to_x_coordinate(), pr_sig.to_x_coordinate()])?;
50        // Output the compute key.
51        Ok(Self { pk_sig, pr_sig, sk_prf })
52    }
53}
54
55impl<N: Network> TryFrom<&(Group<N>, Group<N>)> for ComputeKey<N> {
56    type Error = Error;
57
58    /// Derives the account compute key from a tuple `(pk_sig, pr_sig)`.
59    fn try_from((pk_sig, pr_sig): &(Group<N>, Group<N>)) -> Result<Self> {
60        Self::try_from((*pk_sig, *pr_sig))
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use snarkvm_console_network::MainnetV0;
68
69    type CurrentNetwork = MainnetV0;
70
71    const ITERATIONS: u64 = 1000;
72
73    #[test]
74    fn test_try_from() -> Result<()> {
75        let mut rng = TestRng::default();
76
77        for _ in 0..ITERATIONS {
78            // Sample a new compute key.
79            let private_key = PrivateKey::<CurrentNetwork>::new(&mut rng)?;
80            let candidate = ComputeKey::try_from(private_key)?;
81
82            // Check that sk_prf matches.
83            // Compute sk_prf := HashToScalar(pk_sig || pr_sig).
84            let candidate_sk_prf = CurrentNetwork::hash_to_scalar_psd4(&[
85                candidate.pk_sig().to_x_coordinate(),
86                candidate.pr_sig().to_x_coordinate(),
87            ])?;
88            assert_eq!(candidate.sk_prf(), candidate_sk_prf);
89
90            // Check that compute key is derived correctly from the tuple `(pk_sig, pr_sig)`.
91            assert_eq!(candidate, ComputeKey::try_from((candidate.pk_sig(), candidate.pr_sig()))?);
92        }
93        Ok(())
94    }
95}