bp_pp/range_proof/
u64_proof.rs

1#![allow(non_snake_case)]
2//! Definition and implementation of the u64 range-proof protocol based on reciprocal protocol.
3
4use std::ops::{Add, Mul};
5use k256::{ProjectivePoint, Scalar};
6use k256::elliptic_curve::rand_core::{CryptoRng, RngCore};
7use merlin::Transcript;
8use crate::range_proof::reciprocal::{Proof, ReciprocalRangeProofProtocol, Witness};
9
10#[allow(dead_code)]
11const G_VEC_CIRCUIT_SZ: usize = 16;
12pub const G_VEC_FULL_SZ: usize = 16;
13pub const H_VEC_CIRCUIT_SZ: usize = 26;
14pub const H_VEC_FULL_SZ: usize = 32;
15
16
17/// Represents public information for reciprocal range proof protocol for [0..2^64) range.
18#[derive(Clone, Debug)]
19pub struct U64RangeProofProtocol {
20    /// Will be used for the value commitment as: `commitment = x*g + s*h_vec[0]`
21    pub g: ProjectivePoint,
22    /// Dimension: `16`
23    pub g_vec: Vec<ProjectivePoint>,
24
25    /// Will be used for the value commitment as: `commitment = x*g + s*h_vec[0]`
26    /// Dimension: `26+6=32`
27    pub h_vec: Vec<ProjectivePoint>,
28}
29
30impl U64RangeProofProtocol {
31    /// Count of digits of u64 in hex representation.
32    pub const DIM_ND: usize = 16;
33    /// Base (hex)
34    pub const DIM_NP: usize = 16;
35
36    /// Creates commitment for the private value and blinding: `commitment = x*g + s*h_vec[0]`
37    pub fn commit_value(&self, x: u64, s: &Scalar) -> ProjectivePoint {
38        self.g.mul(&Scalar::from(x)).add(&self.h_vec[0].mul(s))
39    }
40
41    /// Verifies that committed value in `v` lies in range [0..2^64).
42    pub fn verify(&self, v: &ProjectivePoint, proof: Proof, t: &mut Transcript) -> bool {
43        let reciprocal = ReciprocalRangeProofProtocol {
44            dim_nd: Self::DIM_ND,
45            dim_np: Self::DIM_NP,
46            g: self.g,
47            g_vec: self.g_vec.clone(),
48            h_vec: self.h_vec[..H_VEC_CIRCUIT_SZ].to_vec(),
49            g_vec_: vec![],
50            h_vec_: self.h_vec[H_VEC_CIRCUIT_SZ..].to_vec(),
51        };
52
53        reciprocal.verify(v, proof, t)
54    }
55
56    /// Creates proof that values `x` with blinding `s` lies in [0..2^64).
57    pub fn prove<R>(&self, x: u64, s: &Scalar, t: &mut Transcript, rng: &mut R) -> Proof
58        where
59            R: RngCore + CryptoRng
60    {
61        let digits = Self::u64_to_hex(x);
62        let poles = Self::u64_to_hex_mapped(x);
63
64        let reciprocal = ReciprocalRangeProofProtocol {
65            dim_nd: Self::DIM_ND,
66            dim_np: Self::DIM_NP,
67            g: self.g,
68            g_vec: self.g_vec.clone(),
69            h_vec: self.h_vec[..H_VEC_CIRCUIT_SZ].to_vec(),
70            g_vec_: vec![],
71            h_vec_: self.h_vec[H_VEC_CIRCUIT_SZ..].to_vec(),
72        };
73
74        let witness = Witness {
75            x: Scalar::from(x),
76            s: *s,
77            m: poles,
78            digits,
79        };
80
81        reciprocal.prove(&reciprocal.commit_value(&witness.x, &witness.s), witness, t, rng)
82    }
83
84    pub fn u64_to_hex(mut x: u64) -> Vec<Scalar> {
85        (0..16).map(|_| {
86            let val = Scalar::from(x % 16);
87            x /= 16;
88            val
89        }).collect::<Vec<Scalar>>()
90    }
91
92    pub fn u64_to_hex_mapped(mut x: u64) -> Vec<Scalar> {
93        let mut result = vec![Scalar::ZERO; 16];
94
95        (0..16).for_each(|_| {
96            let digit = (x % 16) as usize;
97            result[digit] = result[digit].add(Scalar::ONE);
98            x /= 16;
99        });
100
101        result
102    }
103}