snarkvm_console_account/signature/
mod.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
16mod bitwise;
17mod bytes;
18mod from_bits;
19mod parse;
20mod serialize;
21mod size_in_bits;
22mod size_in_bytes;
23mod to_bits;
24mod to_fields;
25mod verify;
26
27#[cfg(feature = "private_key")]
28mod sign;
29
30#[cfg(feature = "compute_key")]
31use crate::ComputeKey;
32#[cfg(feature = "private_key")]
33use crate::PrivateKey;
34
35use crate::address::Address;
36use snarkvm_console_network::prelude::*;
37use snarkvm_console_types::{Boolean, Field, Scalar};
38
39#[derive(Copy, Clone, PartialEq, Eq, Hash)]
40pub struct Signature<N: Network> {
41    /// The verifier challenge to check against.
42    challenge: Scalar<N>,
43    /// The prover response to the challenge.
44    response: Scalar<N>,
45    /// The compute key of the prover.
46    compute_key: ComputeKey<N>,
47}
48
49impl<N: Network> From<(Scalar<N>, Scalar<N>, ComputeKey<N>)> for Signature<N> {
50    /// Derives the account signature from a tuple `(challenge, response, compute_key)`.
51    fn from((challenge, response, compute_key): (Scalar<N>, Scalar<N>, ComputeKey<N>)) -> Self {
52        Self { challenge, response, compute_key }
53    }
54}
55
56impl<N: Network> From<&(Scalar<N>, Scalar<N>, ComputeKey<N>)> for Signature<N> {
57    /// Derives the account signature from a tuple `(challenge, response, compute_key)`.
58    fn from((challenge, response, compute_key): &(Scalar<N>, Scalar<N>, ComputeKey<N>)) -> Self {
59        Self { challenge: *challenge, response: *response, compute_key: *compute_key }
60    }
61}
62
63impl<N: Network> Signature<N> {
64    /// Returns the verifier challenge.
65    pub const fn challenge(&self) -> Scalar<N> {
66        self.challenge
67    }
68
69    /// Returns the prover response.
70    pub const fn response(&self) -> Scalar<N> {
71        self.response
72    }
73
74    /// Returns the signer compute key.
75    pub const fn compute_key(&self) -> ComputeKey<N> {
76        self.compute_key
77    }
78
79    /// Returns the signer address.
80    pub fn to_address(&self) -> Address<N> {
81        self.compute_key.to_address()
82    }
83}
84
85impl<N: Network> TypeName for Signature<N> {
86    /// Returns the type name as a string.
87    #[inline]
88    fn type_name() -> &'static str {
89        "signature"
90    }
91}
92
93impl<N: Network> Signature<N> {
94    /// Initializes a `zero` signature.
95    #[cfg(any(test, feature = "test"))]
96    pub fn zero() -> Self {
97        Self::from((
98            Scalar::zero(),
99            Scalar::zero(),
100            ComputeKey::try_from((crate::Group::zero(), crate::Group::zero())).unwrap(),
101        ))
102    }
103
104    /// Initializes a "random" signature.
105    #[cfg(any(test, feature = "test"))]
106    pub fn rand<R: Rng>(rng: &mut R) -> Self {
107        Self::from((
108            Scalar::rand(rng),
109            Scalar::rand(rng),
110            ComputeKey::try_from((crate::Group::rand(rng), crate::Group::rand(rng))).unwrap(),
111        ))
112    }
113}
114
115#[cfg(test)]
116mod test_helpers {
117    use super::*;
118    use snarkvm_console_network::MainnetV0;
119
120    type CurrentNetwork = MainnetV0;
121
122    /// Samples a random signature.
123    pub(super) fn sample_signature(num_fields: u64, rng: &mut TestRng) -> Signature<CurrentNetwork> {
124        // Sample an address and a private key.
125        let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
126        let address = Address::try_from(&private_key).unwrap();
127
128        // Generate a signature.
129        let message: Vec<_> = (0..num_fields).map(|_| Uniform::rand(rng)).collect();
130        let signature = Signature::sign(&private_key, &message, rng).unwrap();
131        assert!(signature.verify(&address, &message));
132        signature
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139
140    const ITERATIONS: u64 = 100;
141
142    #[test]
143    fn test_from() -> Result<()> {
144        let mut rng = TestRng::default();
145
146        for i in 0..ITERATIONS {
147            // Sample a new signature.
148            let signature = test_helpers::sample_signature(i, &mut rng);
149
150            // Check that the signature can be reconstructed from its parts.
151            let candidate = Signature::from((signature.challenge(), signature.response(), signature.compute_key()));
152            assert_eq!(signature, candidate);
153        }
154        Ok(())
155    }
156}