mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-13 22:49:25 +00:00
Add documentation to the eVRF-based DKG
This commit is contained in:
@@ -39,8 +39,8 @@ dleq = { path = "../dleq", version = "^0.4.1", default-features = false }
|
|||||||
# eVRF DKG dependencies
|
# eVRF DKG dependencies
|
||||||
subtle = { version = "2", default-features = false, features = ["std"], optional = true }
|
subtle = { version = "2", default-features = false, features = ["std"], optional = true }
|
||||||
generic-array = { version = "1", default-features = false, features = ["alloc"], optional = true }
|
generic-array = { version = "1", default-features = false, features = ["alloc"], optional = true }
|
||||||
rand_chacha = { version = "0.3", default-features = false, features = ["std"], optional = true }
|
|
||||||
blake2 = { version = "0.10", default-features = false, features = ["std"], optional = true }
|
blake2 = { version = "0.10", default-features = false, features = ["std"], optional = true }
|
||||||
|
rand_chacha = { version = "0.3", default-features = false, features = ["std"], optional = true }
|
||||||
generalized-bulletproofs = { path = "../evrf/generalized-bulletproofs", default-features = false, optional = true }
|
generalized-bulletproofs = { path = "../evrf/generalized-bulletproofs", default-features = false, optional = true }
|
||||||
ec-divisors = { path = "../evrf/divisors", default-features = false, optional = true }
|
ec-divisors = { path = "../evrf/divisors", default-features = false, optional = true }
|
||||||
generalized-bulletproofs-circuit-abstraction = { path = "./circuit-abstraction", optional = true }
|
generalized-bulletproofs-circuit-abstraction = { path = "./circuit-abstraction", optional = true }
|
||||||
@@ -53,10 +53,6 @@ generalized-bulletproofs = { path = "./generalized-bulletproofs", features = ["t
|
|||||||
ec-divisors = { path = "./divisors", features = ["pasta"] }
|
ec-divisors = { path = "./divisors", features = ["pasta"] }
|
||||||
pasta_curves = "0.5"
|
pasta_curves = "0.5"
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
generalized-bulletproofs-circuit-abstraction = { path = "./circuit-abstraction" }
|
|
||||||
generalized-bulletproofs-ec-gadgets = { path = "./ec-gadgets" }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = [
|
std = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -79,6 +75,19 @@ std = [
|
|||||||
"dleq/serialize"
|
"dleq/serialize"
|
||||||
]
|
]
|
||||||
borsh = ["dep:borsh"]
|
borsh = ["dep:borsh"]
|
||||||
evrf = ["std", "dep:subtle", "dep:generic-array", "dep:rand_chacha", "dep:blake2", "dep:ec-divisors", "dep:generalized-bulletproofs", "dep:evrf"]
|
evrf = [
|
||||||
|
"std",
|
||||||
|
|
||||||
|
"dep:subtle",
|
||||||
|
"dep:generic-array",
|
||||||
|
|
||||||
|
"dep:blake2",
|
||||||
|
"dep:rand_chacha",
|
||||||
|
|
||||||
|
"dep:generalized-bulletproofs",
|
||||||
|
"dep:ec-divisors",
|
||||||
|
"dep:generalized-bulletproofs-circuit-abstraction",
|
||||||
|
"dep:generalized-bulletproofs-ec-gadgets",
|
||||||
|
]
|
||||||
tests = ["rand_core/getrandom"]
|
tests = ["rand_core/getrandom"]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
@@ -1,3 +1,57 @@
|
|||||||
|
/*
|
||||||
|
We implement a DKG using an eVRF, as detailed in the eVRF paper. For the eVRF itself, we do not
|
||||||
|
use a Paillier-based construction, nor the detailed construction premised on a Bulletproof.
|
||||||
|
|
||||||
|
For reference, the detailed construction premised on a Bulletproof involves two curves, notated
|
||||||
|
here as `C` and `E`, where the scalar field of `C` is the field of `E`. Accordingly, Bulletproofs
|
||||||
|
over `C` can efficiently perform group operations of points of curve `E`. Each participant has a
|
||||||
|
private point (`P_i`) on curve `E` committed to over curve `C`. The eVRF selects a pair of
|
||||||
|
scalars `a, b`, where the participant proves in-Bulletproof the points `A_i, B_i` are
|
||||||
|
`a * P_i, b * P_i`. The eVRF proceeds to commit to `A_i.x + B_i.x` in a Pedersen Commitment.
|
||||||
|
|
||||||
|
Our eVRF uses
|
||||||
|
[Generalized Bulletproofs](https://repo.getmonero.org/monero-project/ccs-proposals/uploads/a9baa50c38c6312efc0fea5c6a188bb9/gbp.pdf).
|
||||||
|
This allows us much larger witnesses without growing the reference string, and enables us to
|
||||||
|
efficiently sample challenges off in-circuit variables (via placing the variables in a vector
|
||||||
|
commitment, then challenging from a transcript of the commitments). We proceed to use
|
||||||
|
[elliptic curve divisors](https://repo.getmonero.org/-/project/54/uploads/eb1bf5b4d4855a3480c38abf895bd8e8/Veridise_Divisor_Proofs.pdf)
|
||||||
|
(which require the ability to sample a challenge off in-circuit variables) to prove discrete
|
||||||
|
logarithms efficiently.
|
||||||
|
|
||||||
|
This is done via having a private scalar (`p_i`) on curve `E`, not a private point, and
|
||||||
|
publishing the public key for it (`P_i = p_i * G`, where `G` is a generator of `E`). The eVRF
|
||||||
|
samples two points with unknown discrete logarithms `A, B`, and the circuit proves a Pedersen
|
||||||
|
Commitment commits to `(p_i * A).x + (p_i * B).x`.
|
||||||
|
|
||||||
|
With the eVRF established, we now detail our other novel aspect. The eVRF paper expects secret
|
||||||
|
shares to be sent to the other parties yet does not detail a precise way to do so. If we
|
||||||
|
encrypted the secret shares with some stream cipher, each recipient would have to attest validity
|
||||||
|
or accuse the sender of impropriety. We want an encryption scheme where anyone can verify the
|
||||||
|
secret shares were encrypted properly, without additional info, efficiently.
|
||||||
|
|
||||||
|
Please note from the published commitments, it's possible to calculcate a commitment to the
|
||||||
|
secret share each party should receive (`V_i`).
|
||||||
|
|
||||||
|
We have the sender sample two scalars per recipient, denoted `x_i, y_i` (where `i` is the
|
||||||
|
recipient index). They perform the eVRF to prove a Pedersen Commitment commits to
|
||||||
|
`z_i = (x_i * P_i).x + (y_i * P_i).x`. They then publish the encrypted share `s_i + z_i` and
|
||||||
|
`X_i = x_i * G, Y_i = y_i * G`.
|
||||||
|
|
||||||
|
The recipient is able to decrypt the share via calculating
|
||||||
|
`s_i - ((p_i * X_i).x + (p_i * Y_i).x)`.
|
||||||
|
|
||||||
|
To verify the secret share, we have the `F` terms of the Pedersen Commitments revealed (where
|
||||||
|
`F, H` are generators of `C`, `F` is used for binding and `H` for blinding). This already needs
|
||||||
|
to be done for the eVRF outputs used within the DKG, in order to obtain thecommitments to the
|
||||||
|
coefficients. When we have the commitment `Z_i = ((p_i * A).x + (p_i * B).x) * F`, we simply
|
||||||
|
check `s_i * F = Z_i + V_i`.
|
||||||
|
|
||||||
|
In order to open the Pedersen Commitments to their `F` terms, we transcript the commitments and
|
||||||
|
the claimed openings, then assign random weights to each pair of `(commitment, opening). The
|
||||||
|
prover proves knowledge of the discrete logarithm of the sum weighted commitments, minus the sum
|
||||||
|
sum weighted openings, over `H`.
|
||||||
|
*/
|
||||||
|
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ use generalized_bulletproofs_ec_gadgets::*;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following circuit has two roles.
|
||||||
|
|
||||||
|
1) Generating every coefficient used in the DKG, per the eVRF paper, using the fixed eVRF key.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
/// A curve to perform the eVRF with.
|
/// A curve to perform the eVRF with.
|
||||||
pub trait EvrfCurve: Ciphersuite {
|
pub trait EvrfCurve: Ciphersuite {
|
||||||
type EmbeddedCurve: Ciphersuite;
|
type EmbeddedCurve: Ciphersuite;
|
||||||
@@ -35,13 +42,13 @@ pub trait EvrfCurve: Ciphersuite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The result of proving for an eVRF.
|
/// The result of proving for an eVRF.
|
||||||
pub struct EvrfProveResult<C: Ciphersuite> {
|
pub(crate) struct EvrfProveResult<C: Ciphersuite> {
|
||||||
pub scalars: Vec<Zeroizing<C::F>>,
|
pub(crate) encrypted_scalars: Vec<C::F>,
|
||||||
pub proof: Vec<u8>,
|
pub(crate) proof: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct to prove/verify eVRFs with.
|
/// A struct to prove/verify eVRFs with.
|
||||||
pub struct Evrf;
|
pub(crate) struct Evrf;
|
||||||
impl Evrf {
|
impl Evrf {
|
||||||
fn transcript_to_points<C: Ciphersuite>(seed: [u8; 32], quantity: usize) -> Vec<C::G> {
|
fn transcript_to_points<C: Ciphersuite>(seed: [u8; 32], quantity: usize) -> Vec<C::G> {
|
||||||
// We need to do two Diffie-Hellman's per point in order to achieve an unbiased result
|
// We need to do two Diffie-Hellman's per point in order to achieve an unbiased result
|
||||||
@@ -182,7 +189,7 @@ impl Evrf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Prove a point on an elliptic curve had its discrete logarithm generated via an eVRF.
|
/// Prove a point on an elliptic curve had its discrete logarithm generated via an eVRF.
|
||||||
pub fn prove<C: EvrfCurve>(
|
pub(crate) fn prove<C: EvrfCurve>(
|
||||||
rng: &mut (impl RngCore + CryptoRng),
|
rng: &mut (impl RngCore + CryptoRng),
|
||||||
generators: &Generators<C>,
|
generators: &Generators<C>,
|
||||||
evrf_private_key: Zeroizing<<<C as EvrfCurve>::EmbeddedCurve as Ciphersuite>::F>,
|
evrf_private_key: Zeroizing<<<C as EvrfCurve>::EmbeddedCurve as Ciphersuite>::F>,
|
||||||
@@ -459,7 +466,7 @@ impl Evrf {
|
|||||||
|
|
||||||
// TODO: Dedicated error
|
// TODO: Dedicated error
|
||||||
/// Verify an eVRF proof, returning the commitments output.
|
/// Verify an eVRF proof, returning the commitments output.
|
||||||
pub fn verify<C: EvrfCurve>(
|
pub(crate) fn verify<C: EvrfCurve>(
|
||||||
rng: &mut (impl RngCore + CryptoRng),
|
rng: &mut (impl RngCore + CryptoRng),
|
||||||
generators: &Generators<C>,
|
generators: &Generators<C>,
|
||||||
verifier: &mut BatchVerifier<C>,
|
verifier: &mut BatchVerifier<C>,
|
||||||
|
|||||||
Reference in New Issue
Block a user