vsss_rs_std/verifier/
pedersen.rs

1/*
2    Copyright Michael Lodder. All Rights Reserved.
3    SPDX-License-Identifier: Apache-2.0
4*/
5
6use crate::*;
7use elliptic_curve::{
8    ff::PrimeField,
9    group::{Group, GroupEncoding, ScalarMul},
10};
11use serde::{Deserialize, Serialize};
12
13/// A Pedersen verifier is used to provide integrity checking of shamir shares
14/// `T` commitments are made to be used for verification.
15#[derive(Clone, Debug, Deserialize, Serialize)]
16pub struct PedersenVerifier<F: PrimeField, G: Group + GroupEncoding + ScalarMul<F>> {
17    /// The generator for the blinding factor
18    #[serde(
19        serialize_with = "serialize_group",
20        deserialize_with = "deserialize_group"
21    )]
22    pub generator: G,
23    /// The feldman verifier containing the share generator and commitments
24    #[serde(bound(serialize = "FeldmanVerifier<F, G>: Serialize"))]
25    #[serde(bound(deserialize = "FeldmanVerifier<F, G>: Deserialize<'de>"))]
26    pub feldman_verifier: FeldmanVerifier<F, G>,
27    /// The blinded commitments to the polynomial
28    #[serde(
29        serialize_with = "serialize_group_vec",
30        deserialize_with = "deserialize_group_vec"
31    )]
32    pub commitments: Vec<G>,
33}
34
35impl<F: PrimeField, G: Group + GroupEncoding + ScalarMul<F>> PedersenVerifier<F, G> {
36    /// Check whether the share is valid according this verifier set
37    pub fn verify(&self, share: &Share, blind_share: &Share) -> VsssResult<()> {
38        let secret = share.as_field_element::<F>()?;
39        let blinding = blind_share.as_field_element::<F>()?;
40
41        let x = F::from(share.identifier() as u64);
42        let mut i = F::ONE;
43
44        // FUTURE: execute this sum of products
45        // c_0 * c_1^i * c_2^{i^2} ... c_t^{i^t}
46        // as a constant time operation using <https://cr.yp.to/papers/pippenger.pdf>
47        // or Guide to Elliptic Curve Cryptography book,
48        // "Algorithm 3.48 Simultaneous multiple point multiplication"
49        // without precomputing the addition but still reduces doublings
50
51        // c_0
52        let mut rhs = self.commitments[0];
53        for v in &self.commitments[1..] {
54            i *= x;
55
56            // c_0 * c_1^i * c_2^{i^2} ... c_t^{i^t}
57            rhs += *v * i;
58        }
59
60        let g: G = (-self.feldman_verifier.generator) * secret;
61        let h: G = (-self.generator) * blinding;
62
63        let res: G = rhs + g + h;
64
65        if res.is_identity().into() {
66            Ok(())
67        } else {
68            Err(Error::InvalidShare)
69        }
70    }
71}