mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Make the cross-group DLEq bit components pow 2, not the commitments as a whole
Few percent faster. Enables accumulating the current bit's point representation, whereas the blinding keys can't be accumulated. Also theoretically enables pre-computation of the bit points, removing hundreds of additions from the proof. When tested, this was less performant, possibly due to cache/heap allocation.
This commit is contained in:
@@ -110,16 +110,14 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
fn blinding_key<R: RngCore + CryptoRng, F: PrimeField>(
|
fn blinding_key<R: RngCore + CryptoRng, F: PrimeField>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
total: &mut F,
|
total: &mut F,
|
||||||
pow_2: &mut F,
|
|
||||||
last: bool
|
last: bool
|
||||||
) -> F {
|
) -> F {
|
||||||
let blinding_key = if last {
|
let blinding_key = if last {
|
||||||
-*total * pow_2.invert().unwrap()
|
-*total
|
||||||
} else {
|
} else {
|
||||||
F::random(&mut *rng)
|
F::random(&mut *rng)
|
||||||
};
|
};
|
||||||
*total += blinding_key * *pow_2;
|
*total += blinding_key;
|
||||||
*pow_2 = pow_2.double();
|
|
||||||
blinding_key
|
blinding_key
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,33 +153,10 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reconstruct_key<G: PrimeGroup>(
|
|
||||||
commitments: impl Iterator<Item = G>
|
|
||||||
) -> G where G::Scalar: PrimeFieldBits {
|
|
||||||
let mut pow_2 = G::Scalar::one();
|
|
||||||
#[cfg(feature = "multiexp")]
|
|
||||||
let res = multiexp::multiexp_vartime(
|
|
||||||
&commitments.map(|commitment| {
|
|
||||||
let res = (pow_2, commitment);
|
|
||||||
pow_2 = pow_2.double();
|
|
||||||
res
|
|
||||||
}).collect::<Vec<_>>()
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "multiexp"))]
|
|
||||||
let res = commitments.fold(G::identity(), |key, commitment| {
|
|
||||||
let res = key + (commitment * pow_2);
|
|
||||||
pow_2 = pow_2.double();
|
|
||||||
res
|
|
||||||
});
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reconstruct_keys(&self) -> (G0, G1) {
|
fn reconstruct_keys(&self) -> (G0, G1) {
|
||||||
(
|
(
|
||||||
Self::reconstruct_key(self.bits.iter().map(|bit| bit.commitments.0)),
|
self.bits.iter().map(|bit| bit.commitments.0).sum(),
|
||||||
Self::reconstruct_key(self.bits.iter().map(|bit| bit.commitments.1))
|
self.bits.iter().map(|bit| bit.commitments.1).sum()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +187,7 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut blinding_key_total = (G0::Scalar::zero(), G1::Scalar::zero());
|
let mut blinding_key_total = (G0::Scalar::zero(), G1::Scalar::zero());
|
||||||
let mut pow_2 = (G0::Scalar::one(), G1::Scalar::one());
|
let mut pow_2 = (generators.0.primary, generators.1.primary);
|
||||||
|
|
||||||
let raw_bits = f.0.to_le_bits();
|
let raw_bits = f.0.to_le_bits();
|
||||||
let capacity = usize::try_from(G0::Scalar::CAPACITY.min(G1::Scalar::CAPACITY)).unwrap();
|
let capacity = usize::try_from(G0::Scalar::CAPACITY.min(G1::Scalar::CAPACITY)).unwrap();
|
||||||
@@ -223,8 +198,8 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
|
|
||||||
let last = i == (capacity - 1);
|
let last = i == (capacity - 1);
|
||||||
let blinding_key = (
|
let blinding_key = (
|
||||||
Self::blinding_key(&mut *rng, &mut blinding_key_total.0, &mut pow_2.0, last),
|
Self::blinding_key(&mut *rng, &mut blinding_key_total.0, last),
|
||||||
Self::blinding_key(&mut *rng, &mut blinding_key_total.1, &mut pow_2.1, last)
|
Self::blinding_key(&mut *rng, &mut blinding_key_total.1, last)
|
||||||
);
|
);
|
||||||
if last {
|
if last {
|
||||||
debug_assert_eq!(blinding_key_total.0, G0::Scalar::zero());
|
debug_assert_eq!(blinding_key_total.0, G0::Scalar::zero());
|
||||||
@@ -235,8 +210,8 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
(generators.0.alt * blinding_key.0),
|
(generators.0.alt * blinding_key.0),
|
||||||
(generators.1.alt * blinding_key.1)
|
(generators.1.alt * blinding_key.1)
|
||||||
);
|
);
|
||||||
commitments.0 += generators.0.primary * G0::Scalar::from(bit.into());
|
commitments.0 += pow_2.0 * G0::Scalar::from(bit.into());
|
||||||
commitments.1 += generators.1.primary * G1::Scalar::from(bit.into());
|
commitments.1 += pow_2.1 * G1::Scalar::from(bit.into());
|
||||||
Self::transcript_bit(transcript, i, commitments);
|
Self::transcript_bit(transcript, i, commitments);
|
||||||
|
|
||||||
let nonces = (G0::Scalar::random(&mut *rng), G1::Scalar::random(&mut *rng));
|
let nonces = (G0::Scalar::random(&mut *rng), G1::Scalar::random(&mut *rng));
|
||||||
@@ -249,8 +224,8 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
let mut to_sign = commitments;
|
let mut to_sign = commitments;
|
||||||
let bit = Choice::from(bit);
|
let bit = Choice::from(bit);
|
||||||
let inv_bit = (!bit).unwrap_u8();
|
let inv_bit = (!bit).unwrap_u8();
|
||||||
to_sign.0 -= generators.0.primary * G0::Scalar::from(inv_bit.into());
|
to_sign.0 -= pow_2.0 * G0::Scalar::from(inv_bit.into());
|
||||||
to_sign.1 -= generators.1.primary * G1::Scalar::from(inv_bit.into());
|
to_sign.1 -= pow_2.1 * G1::Scalar::from(inv_bit.into());
|
||||||
let e_1 = Self::R_nonces(transcript.clone(), generators, (s_0.0, s_0.1), to_sign, e_0);
|
let e_1 = Self::R_nonces(transcript.clone(), generators, (s_0.0, s_0.1), to_sign, e_0);
|
||||||
let mut s_1 = (nonces.0 + (e_1.0 * blinding_key.0), nonces.1 + (e_1.1 * blinding_key.1));
|
let mut s_1 = (nonces.0 + (e_1.0 * blinding_key.0), nonces.1 + (e_1.1 * blinding_key.1));
|
||||||
|
|
||||||
@@ -263,6 +238,9 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
if last {
|
if last {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pow_2.0 = pow_2.0.double();
|
||||||
|
pow_2.1 = pow_2.1.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
let proof = DLEqProof { bits, poks };
|
let proof = DLEqProof { bits, poks };
|
||||||
@@ -326,6 +304,7 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
Err(DLEqError::InvalidProofOfKnowledge)?;
|
Err(DLEqError::InvalidProofOfKnowledge)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut pow_2 = (generators.0.primary, generators.1.primary);
|
||||||
for (i, bit) in self.bits.iter().enumerate() {
|
for (i, bit) in self.bits.iter().enumerate() {
|
||||||
Self::transcript_bit(transcript, i, bit.commitments);
|
Self::transcript_bit(transcript, i, bit.commitments);
|
||||||
|
|
||||||
@@ -335,8 +314,8 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
generators,
|
generators,
|
||||||
bit.s[0],
|
bit.s[0],
|
||||||
(
|
(
|
||||||
bit.commitments.0 - generators.0.primary,
|
bit.commitments.0 - pow_2.0,
|
||||||
bit.commitments.1 - generators.1.primary
|
bit.commitments.1 - pow_2.1
|
||||||
),
|
),
|
||||||
Self::R_nonces(
|
Self::R_nonces(
|
||||||
transcript.clone(),
|
transcript.clone(),
|
||||||
@@ -348,6 +327,9 @@ impl<G0: PrimeGroup, G1: PrimeGroup> DLEqProof<G0, G1>
|
|||||||
) {
|
) {
|
||||||
return Err(DLEqError::InvalidProof);
|
return Err(DLEqError::InvalidProof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pow_2.0 = pow_2.0.double();
|
||||||
|
pow_2.1 = pow_2.1.double();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(keys)
|
Ok(keys)
|
||||||
|
|||||||
Reference in New Issue
Block a user