forked from tari-project/bulletproofs-plus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathristretto.rs
175 lines (149 loc) · 6.23 KB
/
ristretto.rs
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2022 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause
//! # RistrettoBulletProof
//!
//! Implementation of BulletProofs for the Ristretto group for Curve25519.
use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
use curve25519_dalek::{
constants::{RISTRETTO_BASEPOINT_COMPRESSED, RISTRETTO_BASEPOINT_POINT},
ristretto::{CompressedRistretto, RistrettoPoint, VartimeRistrettoPrecomputation},
};
use once_cell::sync::OnceCell;
use crate::{
generators::pedersen_gens::ExtensionDegree,
protocols::curve_point_protocol::CurvePointProtocol,
range_proof::RangeProof,
traits::{Compressable, Decompressable, FixedBytesRepr, FromUniformBytes, Precomputable},
PedersenGens,
};
/// A Bullet proof implentation using the Ristretto group.
pub type RistrettoRangeProof = RangeProof<RistrettoPoint>;
impl CurvePointProtocol for RistrettoPoint {}
impl FixedBytesRepr for CompressedRistretto {
fn as_fixed_bytes(&self) -> &[u8; 32] {
CompressedRistretto::as_bytes(self)
}
fn from_fixed_bytes(bytes: [u8; 32]) -> Self {
Self(bytes)
}
}
impl Decompressable for CompressedRistretto {
type Decompressed = RistrettoPoint;
fn decompress(&self) -> Option<Self::Decompressed> {
CompressedRistretto::decompress(self)
}
}
impl FromUniformBytes for RistrettoPoint {
fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
RistrettoPoint::from_uniform_bytes(bytes)
}
}
impl Compressable for RistrettoPoint {
type Compressed = CompressedRistretto;
fn compress(&self) -> Self::Compressed {
RistrettoPoint::compress(self)
}
}
impl Precomputable for RistrettoPoint {
type Precomputation = VartimeRistrettoPrecomputation;
}
/// Create extended Pedersen generators for the required extension degree using pre-calculated compressed constants
pub fn create_pedersen_gens_with_extension_degree(extension_degree: ExtensionDegree) -> PedersenGens<RistrettoPoint> {
let (g_base_vec, g_base_compressed_vec) = get_g_base(extension_degree);
PedersenGens {
h_base: RISTRETTO_BASEPOINT_POINT,
h_base_compressed: RISTRETTO_BASEPOINT_COMPRESSED,
g_base_vec: g_base_vec[..].to_owned(),
g_base_compressed_vec: g_base_compressed_vec[..].to_owned(),
extension_degree,
}
}
// Get masking points and compressed points based on extension degree
fn get_g_base(extension_degree: ExtensionDegree) -> (Vec<RistrettoPoint>, Vec<CompressedRistretto>) {
(
ristretto_masking_basepoints()[..extension_degree as usize].to_vec(),
ristretto_compressed_masking_basepoints()[..extension_degree as usize].to_vec(),
)
}
/// A static array of pre-generated points
fn ristretto_masking_basepoints() -> &'static [RistrettoPoint; ExtensionDegree::COUNT] {
static INSTANCE: OnceCell<[RistrettoPoint; ExtensionDegree::COUNT]> = OnceCell::new();
INSTANCE.get_or_init(|| {
let mut arr = [RistrettoPoint::default(); ExtensionDegree::COUNT];
for (i, point) in (ExtensionDegree::MINIMUM..).zip(arr.iter_mut()) {
let label = "RISTRETTO_MASKING_BASEPOINT_".to_owned() + &i.to_string();
*point = RistrettoPoint::hash_from_bytes_sha3_512(label.as_bytes());
}
arr
})
}
/// A static array of compressed pre-generated points
fn ristretto_compressed_masking_basepoints() -> &'static [CompressedRistretto; ExtensionDegree::COUNT] {
static INSTANCE: OnceCell<[CompressedRistretto; ExtensionDegree::COUNT]> = OnceCell::new();
INSTANCE.get_or_init(|| {
let mut arr = [CompressedRistretto::default(); ExtensionDegree::COUNT];
for (i, point) in ristretto_masking_basepoints().iter().enumerate() {
arr[i] = point.compress();
}
arr
})
}
#[cfg(test)]
mod tests {
use curve25519_dalek::scalar::Scalar;
use rand_chacha::ChaCha12Rng;
use rand_core::SeedableRng;
use super::*;
use crate::protocols::scalar_protocol::ScalarProtocol;
static EXTENSION_DEGREE: [ExtensionDegree; 6] = [
ExtensionDegree::DefaultPedersen,
ExtensionDegree::AddOneBasePoint,
ExtensionDegree::AddTwoBasePoints,
ExtensionDegree::AddThreeBasePoints,
ExtensionDegree::AddFourBasePoints,
ExtensionDegree::AddFiveBasePoints,
];
#[test]
fn test_constants() {
// Extended Pedersen generators with extension degree of zero to five
let masking_basepoints = ristretto_masking_basepoints();
for extension_degree in EXTENSION_DEGREE {
let pc_gens = create_pedersen_gens_with_extension_degree(extension_degree);
for (i, item) in masking_basepoints
.iter()
.enumerate()
.take(pc_gens.extension_degree as usize)
{
assert_eq!(pc_gens.g_base_vec[i].compress(), pc_gens.g_base_compressed_vec[i]);
assert_eq!(item.compress(), pc_gens.g_base_compressed_vec[i]);
}
assert_eq!(pc_gens.g_base_vec.len(), extension_degree as usize);
assert_eq!(pc_gens.g_base_compressed_vec.len(), extension_degree as usize);
}
}
#[test]
fn test_commitments() {
let mut rng = ChaCha12Rng::seed_from_u64(8675309); // for testing only!
let value = Scalar::random_not_zero(&mut rng);
let blindings = [
Scalar::random_not_zero(&mut rng),
Scalar::random_not_zero(&mut rng),
Scalar::random_not_zero(&mut rng),
Scalar::random_not_zero(&mut rng),
Scalar::random_not_zero(&mut rng),
Scalar::random_not_zero(&mut rng),
];
for extension_degree in EXTENSION_DEGREE {
let pc_gens = create_pedersen_gens_with_extension_degree(extension_degree);
for i in 0..ExtensionDegree::AddFiveBasePoints as usize {
// All commitments where enough extended generators are available to enable multi-exponentiation
// multiplication of the blinding factor vector will be ok
if i > 0 && i <= extension_degree as usize {
assert!(pc_gens.commit(&value, &blindings[..i]).is_ok());
} else {
assert!(pc_gens.commit(&value, &blindings[..i]).is_err());
}
}
}
}
}