use soroban_sdk::{contracttype, Env};
use super::crypto::{bn254_g1_add, bn254_g1_mul};
use super::error::ZKError;
use super::types::{G1Point, Scalar};
#[contracttype]
#[derive(Clone, Debug)]
pub struct PedersenParams {
pub g: G1Point,
pub h: G1Point,
}
#[contracttype]
#[derive(Clone, Debug)]
pub struct PedersenCommitment {
pub point: G1Point,
}
pub fn pedersen_commit(
env: &Env,
params: &PedersenParams,
value: &Scalar,
blinding: &Scalar,
) -> Result<PedersenCommitment, ZKError> {
let vg = bn254_g1_mul(env, ¶ms.g, value)?;
let rh = bn254_g1_mul(env, ¶ms.h, blinding)?;
let point = bn254_g1_add(env, &vg, &rh)?;
Ok(PedersenCommitment { point })
}
pub fn pedersen_verify(
env: &Env,
params: &PedersenParams,
commitment: &PedersenCommitment,
value: &Scalar,
blinding: &Scalar,
) -> Result<bool, ZKError> {
let expected = pedersen_commit(env, params, value, blinding)?;
Ok(commitment.point.bytes == expected.point.bytes)
}
#[cfg(test)]
mod tests {
use super::*;
use soroban_sdk::{BytesN, Env};
#[test]
fn test_pedersen_params_creation() {
let env = Env::default();
let params = PedersenParams {
g: G1Point {
bytes: BytesN::from_array(&env, &[0u8; 64]),
},
h: G1Point {
bytes: BytesN::from_array(&env, &[0u8; 64]),
},
};
assert_eq!(params.g.bytes.len(), 64);
assert_eq!(params.h.bytes.len(), 64);
}
#[test]
fn test_pedersen_commitment_type_creation() {
let env = Env::default();
let commitment = PedersenCommitment {
point: G1Point {
bytes: BytesN::from_array(&env, &[0u8; 64]),
},
};
assert_eq!(commitment.point.bytes.len(), 64);
}
#[test]
fn test_pedersen_same_commitment_equals() {
let env = Env::default();
let c1 = PedersenCommitment {
point: G1Point {
bytes: BytesN::from_array(&env, &[1u8; 64]),
},
};
let c2 = PedersenCommitment {
point: G1Point {
bytes: BytesN::from_array(&env, &[1u8; 64]),
},
};
assert_eq!(c1.point.bytes, c2.point.bytes);
}
#[test]
fn test_pedersen_different_commitments_differ() {
let env = Env::default();
let c1 = PedersenCommitment {
point: G1Point {
bytes: BytesN::from_array(&env, &[1u8; 64]),
},
};
let c2 = PedersenCommitment {
point: G1Point {
bytes: BytesN::from_array(&env, &[2u8; 64]),
},
};
assert_ne!(c1.point.bytes, c2.point.bytes);
}
}