1. Zexe中的pedersen commitment
Zexe中基于的是pairing based曲线。
Zexe中的pedersen commitment 为Pedersen CRH,当做
C
o
m
(
a
1
∗
m
1
,
a
1
∗
r
1
)
=
a
1
∗
C
o
m
(
m
1
,
r
1
)
Com(a_1*m_1,a_1*r_1)=a_1* Com(m_1,r_1)
Com(a1∗m1,a1∗r1)=a1∗Com(m1,r1)时,
得特别注意WINDOW_SIZE的设置(最大可设置为与 randomness_generator
一样,为域内最大位数:MODULUS_BITS
)。(因为>=8的数值,因为input[u8]数组的bit位长度为8*N(N为整数)。)【PedersenCommitment::commit
是逐bit进行commit求和。】
考虑到缓存情况等原因,应结合实际情况设置WINDOW_SIZE和NUM_WINDOWS。
Parameters.generators
的组成为:
( G 1 2 G 1 4 G 1 . . . 2 W I N D O W _ S I Z E − 1 G 1 G 2 2 G 2 4 G 2 . . . 2 W I N D O W _ S I Z E − 1 G 2 . . . . . . . . . . . . . . . G N U M _ W I N D O W S 2 G N U M _ W I N D O W S 4 G N U M _ W I N D O W S . . . 2 W I N D O W _ S I Z E − 1 G N U M _ W I N D O W S ) \begin{pmatrix} G_1&2G_1 & 4G_1 & ... &2^{WINDOW\_SIZE-1}G_1 \\ G_2&2G_2 & 4G_2 & ... &2^{WINDOW\_SIZE-1}G_2 \\ ... & ... & ... & ... & ...\\ G_{NUM\_WINDOWS}& 2G_{NUM\_WINDOWS} & 4G_{NUM\_WINDOWS} & ... &2^{WINDOW\_SIZE-1}G_{NUM\_WINDOWS} \end{pmatrix} ⎝⎜⎜⎛G1G2...GNUM_WINDOWS2G12G2...2GNUM_WINDOWS4G14G2...4GNUM_WINDOWS............2WINDOW_SIZE−1G12WINDOW_SIZE−1G2...2WINDOW_SIZE−1GNUM_WINDOWS⎠⎟⎟⎞
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
let time = start_timer!(|| format!(
"PedersenCOMM::Setup: {} {}-bit windows; {{0,1}}^{{{}}} -> G",
W::NUM_WINDOWS,
W::WINDOW_SIZE,
W::NUM_WINDOWS * W::WINDOW_SIZE
));
let num_powers = <G::ScalarField as PrimeField>::Params::MODULUS_BITS as usize;
let randomness_generator = PedersenCRH::<_, W>::generator_powers(num_powers, rng);
let generators = PedersenCRH::<_, W>::create_generators(rng);
end_timer!(time);
Ok(Self::Parameters {
randomness_generator,
generators,
})
}
impl<G: Group, W: PedersenWindow> PedersenCRH<G, W> {
pub fn create_generators<R: Rng>(rng: &mut R) -> Vec<Vec<G>> {
let mut generators_powers = Vec::new();
for _ in 0..W::NUM_WINDOWS {
generators_powers.push(Self::generator_powers(W::WINDOW_SIZE, rng));
}
generators_powers
}
pub fn generator_powers<R: Rng>(num_powers: usize, rng: &mut R) -> Vec<G> {
let mut cur_gen_powers = Vec::with_capacity(num_powers);
let mut base = G::rand(rng);
for _ in 0..num_powers {
cur_gen_powers.push(base);
base.double_in_place();
}
cur_gen_powers
}
}
以下代码可证明Com(m_1,r_1) + Com(m_2,r_2)=Com(m_1+m_2, r_1+r_2)
#[test]
fn commitment_combination_test() {
#[derive(Clone, PartialEq, Eq, Hash)]
pub(super) struct Window;
impl PedersenWindow for Window {
const WINDOW_SIZE: usize = 8; // Should be no less than 8 , for `bytes_to_bits` in `commit`->`evalute` func will be always be 8*N (N as an integer bigger than 0)
const NUM_WINDOWS: usize = 8;
}
let input_1 = [51u8, 5];
let rng = &mut thread_rng();
let randomness = PedersenRandomness(Fr::rand(rng));
let parameters = PedersenCommitment::<JubJub, Window>::setup(rng).unwrap();
let primitive_result =
PedersenCommitment::<JubJub, Window>::commit(¶meters, &input_1, &randomness).unwrap();
println!("primitive_result:{:?}, primitive_result + &JubJub::zero(): {:?}", primitive_result, primitive_result + &JubJub::zero());
assert_eq!(primitive_result, primitive_result + &JubJub::zero());
assert_eq!(parameters.generators[0][1], parameters.generators[0][0] * &Fr::from(2 as u64));
//assert_eq!(primitive_result, parameters.generators[0][0] * &Fr::from(2 as u64));
let input_2 = [5u8, 11];
let randomness_2 = PedersenRandomness(Fr::rand(rng));
let primitive_result_2 =
PedersenCommitment::<JubJub, Window>::commit(¶meters, &input_2, &randomness_2).unwrap();
let a_1 = 4u8;
let a_2 = 2u8;
//let randomness_3 = PedersenRandomness(randomness.0 + &randomness_2.0);
let randomness_3 = PedersenRandomness(randomness.0 * &Fr::from(a_1 as u64) + &(randomness_2.0 * &Fr::from(a_2 as u64)));
//let input_3 = [214u8, 42]; //a_1*i1+a_2*i2=1*5+2*7=19
let input_3: Vec<u8>= input_1.iter().zip(input_2.iter()).map(|(i1,i2)| a_1*i1+a_2*i2).collect();
let primitive_result_3 =
PedersenCommitment::<JubJub, Window>::commit(¶meters, &input_3, &randomness_3).unwrap();
println!("primitive_result:{:?}, a1:{:?}, primitive_result_2:{:?}, a_2:{:?}", primitive_result, a_1, primitive_result_2, a_2);
//assert_eq!(primitive_result * &Fr::from(a_1 as u64) + &(primitive_result_2 * &Fr::from(a_2 as u64)), primitive_result_3);
let primitive_expected = (primitive_result * &Fr::from(a_1 as u64) + &(primitive_result_2 * &Fr::from(a_2 as u64))).into_affine();
let primitive_direct = primitive_result_3.into_affine();
assert_eq!(primitive_direct.x, primitive_expected.x);
assert_eq!(primitive_direct.y, primitive_expected.y);
}
2. Qesa中的pedersen commitment
Qesa中基于的是curve25519。
任意取值均可通过
C
o
m
(
a
1
∗
m
1
,
a
1
∗
r
1
)
+
C
o
m
(
a
2
∗
m
2
,
a
2
∗
r
2
)
=
C
o
m
(
a
1
∗
m
1
+
a
2
∗
m
2
,
a
1
∗
r
1
+
a
2
∗
r
2
)
Com(a_1*m_1, a_1*r_1) + Com(a_2*m_2, a_2*r_2)=Com(a_1*m_1+ a_2*m_2, a_1*r_1+ a_2*r_2)
Com(a1∗m1,a1∗r1)+Com(a2∗m2,a2∗r2)=Com(a1∗m1+a2∗m2,a1∗r1+a2∗r2)
#[test]
fn test_commitment_combination() {
let n = 1;
let mut rng = rand::thread_rng();
let G: Vec<RistrettoPoint> = (0..n).map(|_| RistrettoPoint::random(&mut rng)).collect();
let G0: RistrettoPoint = RistrettoPoint::random(&mut rng);
let w_1 = Scalar::random(&mut rng);
let w_2 = Scalar::random(&mut rng);
let r_1 = Scalar::random(&mut rng);
let r_2 = Scalar::random(&mut rng);
let c_1 = pedersen_commit(&G0, &G.clone(), &vec![w_1.clone()], &r_1);
let c_2 = pedersen_commit(&G0, &G.clone(), &vec![w_2.clone()], &r_2);
let a_1 = &Scalar::random(&mut rng);
let a_2 = &Scalar::random(&mut rng);
let w_combined = &w_1 * a_1 + &w_2 * a_2;
let r_combined = &r_1 * a_1 + &r_2 * a_2;
let c_combined = pedersen_commit(&G0, &G.clone(), &vec![w_combined.clone()], &r_combined);
assert_eq!(a_1 * &c_1 + a_2*&c_2, c_combined);
}