snarkvm_circuit_account/signature/
mod.rsmod equal;
mod helpers;
mod ternary;
mod verify;
#[cfg(test)]
use snarkvm_circuit_types::environment::{assert_count, assert_output_mode, assert_scope};
use crate::ComputeKey;
use snarkvm_circuit_network::Aleo;
use snarkvm_circuit_types::{Address, Boolean, Field, Scalar, environment::prelude::*};
#[derive(Clone)]
pub struct Signature<A: Aleo> {
challenge: Scalar<A>,
response: Scalar<A>,
compute_key: ComputeKey<A>,
}
#[cfg(feature = "console")]
impl<A: Aleo> Inject for Signature<A> {
type Primitive = console::Signature<A::Network>;
fn new(mode: Mode, signature: Self::Primitive) -> Signature<A> {
Self {
challenge: Scalar::new(mode, signature.challenge()),
response: Scalar::new(mode, signature.response()),
compute_key: ComputeKey::new(mode, signature.compute_key()),
}
}
}
impl<A: Aleo> Signature<A> {
pub const fn challenge(&self) -> &Scalar<A> {
&self.challenge
}
pub const fn response(&self) -> &Scalar<A> {
&self.response
}
pub const fn compute_key(&self) -> &ComputeKey<A> {
&self.compute_key
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Eject for Signature<A> {
type Primitive = console::Signature<A::Network>;
fn eject_mode(&self) -> Mode {
(&self.challenge, &self.response, &self.compute_key).eject_mode()
}
fn eject_value(&self) -> Self::Primitive {
Self::Primitive::from((&self.challenge, &self.response, &self.compute_key).eject_value())
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Parser for Signature<A> {
#[inline]
fn parse(string: &str) -> ParserResult<Self> {
let (string, signature) = console::Signature::parse(string)?;
let (string, mode) = opt(pair(tag("."), Mode::parse))(string)?;
match mode {
Some((_, mode)) => Ok((string, Signature::new(mode, signature))),
None => Ok((string, Signature::new(Mode::Constant, signature))),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo> FromStr for Signature<A> {
type Err = Error;
#[inline]
fn from_str(string: &str) -> Result<Self> {
match Self::parse(string) {
Ok((remainder, object)) => {
ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
Ok(object)
}
Err(error) => bail!("Failed to parse string. {error}"),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo> TypeName for Signature<A> {
#[inline]
fn type_name() -> &'static str {
console::Signature::<A::Network>::type_name()
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Debug for Signature<A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(self, f)
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Display for Signature<A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.eject_value(), self.eject_mode())
}
}
#[cfg(all(test, feature = "console"))]
mod tests {
use super::*;
use crate::{Circuit, helpers::generate_account};
use snarkvm_utilities::{TestRng, Uniform};
use anyhow::Result;
const ITERATIONS: u64 = 250;
fn check_new(
mode: Mode,
num_constants: u64,
num_public: u64,
num_private: u64,
num_constraints: u64,
) -> Result<()> {
let rng = &mut TestRng::default();
let (private_key, _compute_key, _view_key, _address) = generate_account()?;
for i in 0..ITERATIONS {
let message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
let signature = console::Signature::sign(&private_key, &message, rng)?;
Circuit::scope(format!("New {mode}"), || {
let candidate = Signature::<Circuit>::new(mode, signature);
assert_eq!(signature, candidate.eject_value());
if i > 0 {
assert_scope!(num_constants, num_public, num_private, num_constraints);
}
});
Circuit::reset();
}
Ok(())
}
#[test]
fn test_signature_new_constant() -> Result<()> {
check_new(Mode::Constant, 276, 0, 0, 0)
}
#[test]
fn test_signature_new_public() -> Result<()> {
check_new(Mode::Public, 9, 6, 869, 873)
}
#[test]
fn test_signature_new_private() -> Result<()> {
check_new(Mode::Private, 9, 0, 875, 873)
}
}