darkfi_sdk/crypto/
pedersen.rs

1/* This file is part of DarkFi (https://dark.fi)
2 *
3 * Copyright (C) 2020-2025 Dyne.org foundation
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19use halo2_gadgets::ecc::chip::FixedPoint;
20use pasta_curves::{arithmetic::CurveExt, pallas};
21
22use super::{
23    blind::ScalarBlind,
24    constants::{
25        fixed_bases::{
26            VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES,
27        },
28        NullifierK,
29    },
30    util::fp_mod_fv,
31};
32
33/// Pedersen commitment for a full-width base field element.
34#[allow(non_snake_case)]
35pub fn pedersen_commitment_base(value: pallas::Base, blind: ScalarBlind) -> pallas::Point {
36    let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
37    let V = NullifierK.generator();
38    let R = hasher(&VALUE_COMMITMENT_R_BYTES);
39
40    V * fp_mod_fv(value) + R * blind.inner()
41}
42
43/// Pedersen commitment for a 64-bit value, in the base field.
44#[allow(non_snake_case)]
45pub fn pedersen_commitment_u64(value: u64, blind: ScalarBlind) -> pallas::Point {
46    let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION);
47    let V = hasher(&VALUE_COMMITMENT_V_BYTES);
48    let R = hasher(&VALUE_COMMITMENT_R_BYTES);
49
50    V * fp_mod_fv(pallas::Base::from(value)) + R * blind.inner()
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn pedersen_commitment() {
59        let a_value = pallas::Base::from(10);
60        let a_blind = ScalarBlind::from(11);
61        let b_value = pallas::Base::from(20);
62        let b_blind = ScalarBlind::from(21);
63
64        assert_eq!(
65            pedersen_commitment_base(a_value, a_blind) + pedersen_commitment_base(b_value, b_blind),
66            pedersen_commitment_base(a_value + b_value, &a_blind + &b_blind)
67        );
68
69        let a_value = 10;
70        let b_value = 20;
71
72        assert_eq!(
73            pedersen_commitment_u64(a_value, a_blind) + pedersen_commitment_u64(b_value, b_blind),
74            pedersen_commitment_u64(a_value + b_value, &a_blind + &b_blind)
75        );
76    }
77}