mpc_stark/
commitment.rs

1//! Defines Pedersen commitments over the Stark curve used to commit to a value
2//! before opening it
3
4use rand::thread_rng;
5use sha3::{Digest, Sha3_256};
6
7use crate::{
8    algebra::{
9        scalar::{Scalar, ScalarResult},
10        stark_curve::{StarkPoint, StarkPointResult},
11    },
12    fabric::ResultValue,
13};
14
15/// A handle on the result of a Pedersen commitment, including the committed secret
16///
17/// Of the form `value * G + blinder * H`
18pub(crate) struct PedersenCommitment {
19    /// The committed value
20    pub(crate) value: Scalar,
21    /// The commitment blinder
22    pub(crate) blinder: Scalar,
23    /// The value of the commitment
24    pub(crate) commitment: StarkPoint,
25}
26
27impl PedersenCommitment {
28    /// Verify that the given commitment is valid
29    pub(crate) fn verify(&self) -> bool {
30        let generator = StarkPoint::generator();
31        let commitment = generator * self.value + generator * self.blinder;
32
33        commitment == self.commitment
34    }
35}
36
37/// A Pedersen commitment that has been allocated in an MPC computation graph
38pub(crate) struct PedersenCommitmentResult {
39    /// The committed value
40    pub(crate) value: ScalarResult,
41    /// The commitment blinder
42    pub(crate) blinder: Scalar,
43    /// The value of the commitment
44    pub(crate) commitment: StarkPointResult,
45}
46
47impl PedersenCommitmentResult {
48    /// Create a new Pedersen commitment to an underlying value
49    pub(crate) fn commit(value: ScalarResult) -> PedersenCommitmentResult {
50        // Concretely, we use the curve generator for both `G` and `H` as is done
51        // in dalek-cryptography: https://github.com/dalek-cryptography/bulletproofs/blob/main/src/generators.rs#L44-L53
52        let mut rng = thread_rng();
53        let blinder = Scalar::random(&mut rng);
54        let generator = StarkPoint::generator();
55        let commitment = generator * &value + generator * blinder;
56
57        PedersenCommitmentResult {
58            value,
59            blinder,
60            commitment,
61        }
62    }
63}
64
65/// A handle on the result of a salted Sha256 hash commitment, including the committed secret
66///
67/// Of the form `H(salt || value)`
68///
69/// We use hash commitments to commit to curve points before opening them. There is no straightforward
70/// way to adapt Pedersen commitments to curve points, and we do not need the homomorphic properties
71/// of a Pedersen commitment
72pub(crate) struct HashCommitment {
73    /// The committed value
74    pub(crate) value: StarkPoint,
75    /// The blinder used in the commitment
76    pub(crate) blinder: Scalar,
77    /// The value of the commitment
78    pub(crate) commitment: Scalar,
79}
80
81impl HashCommitment {
82    /// Verify that the given commitment is valid
83    pub(crate) fn verify(&self) -> bool {
84        // Create the bytes buffer
85        let mut bytes = self.value.to_bytes();
86        bytes.append(&mut self.blinder.to_bytes_be());
87
88        // Hash the bytes, squeeze an output, verify that it is equal to the commitment
89        let mut hasher = Sha3_256::new();
90        hasher.update(bytes);
91
92        let out_bytes = hasher.finalize();
93        let out = Scalar::from_be_bytes_mod_order(out_bytes.as_slice());
94
95        out == self.commitment
96    }
97}
98
99/// A hash commitment that has been allocated in an MPC computation graph
100pub(crate) struct HashCommitmentResult {
101    /// The committed value
102    pub(crate) value: StarkPointResult,
103    /// The blinder used in the commitment
104    pub(crate) blinder: Scalar,
105    /// The value of the commitment
106    pub(crate) commitment: ScalarResult,
107}
108
109impl HashCommitmentResult {
110    /// Create a new hash commitment to an underlying value
111    pub(crate) fn commit(value: StarkPointResult) -> HashCommitmentResult {
112        let mut rng = thread_rng();
113        let blinder = Scalar::random(&mut rng);
114        let comm = value.fabric.new_gate_op(vec![value.id], move |mut args| {
115            let value: StarkPoint = args.remove(0).into();
116
117            // Create the bytes buffer
118            let mut bytes = value.to_bytes();
119            bytes.append(&mut blinder.to_bytes_be());
120
121            // Hash the bytes, squeeze an output, verify that it is equal to the commitment
122            let mut hasher = Sha3_256::new();
123            hasher.update(bytes);
124
125            let out_bytes = hasher.finalize();
126            let out = Scalar::from_be_bytes_mod_order(out_bytes.as_slice());
127
128            ResultValue::Scalar(out)
129        });
130
131        HashCommitmentResult {
132            value,
133            blinder,
134            commitment: comm,
135        }
136    }
137}