pub fn new(g1: E::G1, g2: E::G2, degree: usize) -> Self {
Self {
g1,
g2,
g2_tau: g2.mul(E::ScalarField::ZERO),
degree,
crs_g1: vec![],
crs_g2: vec![],
}
}
구조체를 초기화하는 역할을 합니다.
g1과 g2는 각각 그룹 과 에서의 기본 생성자입니다. 이 값들은 셋업 과정에서 그룹 원소들의 여러 지수 승을 구할 때 기본이 됩니다. degree는 다항식의 차수입니다.crs_g1과 crs_g2를 빈 값으로 초기화합니다.g2_tau는 아직 비밀 값이 없기 때문에 에 비밀 값 대신 0을 곱한 값을 설정합니다.pub fn setup(&mut self, secret: E::ScalarField) {
for i in 0..self.degree+1 {
self.crs_g1.push(self.g1.mul(secret.pow(&[i as u64])));
self.crs_g2.push(self.g2.mul(secret.pow(&[i as u64])));
}
self.g2_tau = self.g2.mul(secret);
}
이 함수는 실제로 KZG 셋업 과정을 수행합니다. 비밀 값(secret)을 기반으로 참조 문자열(CRS)을 생성합니다.
secret은 셋업에서 사용하는 비밀 값 sss입니다. 이 값은 셋업 과정에서 매우 중요하며 절대로 공개되지 않아야 합니다.crs_g1과 crs_g2 벡터에 비밀 값과 그 거듭제곱을 곱한 그룹 원소들이 채워집니다.for i in 0..self.degree+1: 다항식의 차수가 degree이기 때문에 000부터 degree까지의 거듭제곱을 다룹니다.self.crs_g1.push(self.g1.mul(secret.pow(&[i as u64]))): 이 부분은 를 계산해 crs_g1 벡터에 저장하는 과정입니다.
self.crs_g2.push(self.g2.mul(secret.pow(&[i as u64]))): 마찬가지로 를 계산해 crs_g2 벡터에 저장합니다.
이 과정에서 비밀 값의 거듭제곱을 각각 과 에서 계산하여 참조 문자열(CRS)을 만들게 됩니다.
self.g2_tau = self.g2.mul(secret);는 비밀 값 와 를 곱하여 값을 저장합니다. 이 값은 검증 단계에서 필요한 요소입니다.pub fn commit(&self, poly: &[E::ScalarField]) -> E::G1 {
let mut commitment = self.g1.mul(E::ScalarField::ZERO);
for i in 0..self.degree+1 {
commitment += self.crs_g1[i] * poly[i];
}
commitment
}
commit 함수poly)을 입력으로 받아, 이를 타원곡선 상의 한 점 로 변환합니다. 이 과정에서 만들어진 점은 다항식 커밋(commitment)으로 불리며, 이를 통해 나중에 다항식 평가값을 증명하고 검증할 수 있게 됩니다.E::G1은 타원 곡선 그룹 을 의미하며, commit 함수는 결국 상의 한 점을 반환합니다. 이 점이 다항식에 대한 커밋입니다.commitment = self.g1.mul(E::ScalarField::ZERO)for 루프: 계수를 기반으로 커밋 생성pub fn open(&self, poly: &[E::ScalarField], point: E::ScalarField) -> E::G1 {
// evaluate the polynomial at point|
let value = evaluate(poly, point);
// initialize denominator|
let denominator = [-point, E::ScalarField::ONE];
// initialize numerator|
let first = poly[0] - value;
let rest = &poly[1..];
let temp: Vec<E::ScalarField> = std::iter::once(first).chain(rest.iter().cloned()).collect();
let numerator: &[E::ScalarField] = &temp;
// get quotient by dividing numerator by denominator|
let quotient = div(numerator, &denominator).unwrap();
// calculate pi as proof (quotient multiplied by CRS)
let mut pi = self.g1.mul(E::ScalarField::ZERO);
for i in 0..quotient.len() {
pi += self.crs_g1[i] * quotient[i];
}
// return pi
pi
}
pub fn open(&self, poly: &[E::ScalarField], point: E::ScalarField) -> E::G1 {
이 함수는 두 가지 입력을 받습니다:
결과적으로, 이 함수는 에 대한 증명 값 를 반환합니다.
let value = evaluate(poly, point);
먼저, 다항식 P(x)를 입력된 점 에서 평가하여 값을 계산합니다. evaluate 함수는 다항식의 계수 배열과 점을 입력받아 을 반환합니다.
2.1 분모 설정
let denominator = [-point, E::ScalarField::ONE];
가 분모 역할을 합니다. 는 point로 주어졌으며, 분모는 타원곡선 그룹에서의 차수에 해당하는 두 요소 로 표현됩니다.
2.2 분자 설정
let first = poly[0] - value;
let rest = &poly[1..];
let temp: Vec<E::ScalarField> = std::iter::once(first).chain(rest.iter().cloned()).collect();
let numerator: &[E::ScalarField] = &temp;
분자는 입니다.
이를 위해 값을 다항식의 상수항에서 빼주고, 나머지 항은 그대로 복사합니다.
이 작업을 통해 의 계수를 만들어냅니다.
let quotient = div(numerator, &denominator).unwrap();
를 로 나누는 과정입니다.
이를 통해 몫 다항식이 생성됩니다.
몫 다항식은 KZG에서 중요한 역할을 하며, 이를 기반으로 증명(proof)을 만듭니다.
let mut pi = self.g1.mul(E::ScalarField::ZERO);
for i in 0..quotient.len() {
pi += self.crs_g1[i] * quotient[i];
}
여기서는 KZG 셋업에서 미리 생성된 CRS(공통 참조 문자열, crs_g1)를 사용해 증명 값 π를 계산합니다. 몫 다항식의 각 계수에 해당하는 와 곱해서 누적한 값을 통해 타원 곡선 상의 한 점 π가 만들어집니다.
pub fn verify( &self, point: E::ScalarField, value: E::ScalarField, commitment: E::G1, pi: E::G1 )
-> bool
{
let lhs = E::pairing(pi, self.g2_tau - self.g2.mul(point));
let rhs = E::pairing(commitment - self.g1.mul(value), self.g2);
lhs == rhs
}
point: E::ScalarField: 검증할 특정 점 aaa.value: E::ScalarField: 다항식이 이 점에서 평가된 값, 즉 f(a).commitment: E::G1: 다항식의 약속 값, 즉 다항식에 대한 KZG commitment.pi: E::G1: 검증자에게 제공된 증명 값.다음 두 개의 쌍선형 페어링의 결과가 같은지를 비교하여 증명을 검증합니다.
좌변 (lhs):
let lhs = E::pairing(pi, self.g2_tau - self.g2.mul(point));
pi는 증명 값이며, 는 KZG 셋업 과정에서 계산된 값입니다.self.g2.mul(point)는 약속의 그룹 요소에 대해 특정 점 a를 곱한 값입니다. 이 값은 그룹에서 다항식의 점을 나타냅니다.pi와 간의 페어링을 통해 계산됩니다. 이 페어링은 의 관계를 나타내며, 증명 값이 다항식의 평가값과 일치하는지를 확인하는 역할을 합니다.우변 (rhs):
let rhs = E::pairing(commitment - self.g1.mul(value), self.g2);
commitment는 다항식에 대한 KZG commitment이며, g1그룹의 요소입니다.self.g1.mul(value)는 평가된 값 y를 약속에 대해 곱한 것입니다. 이 값은 다항식의 평가 결과를 나타냅니다.lhs == rhs
[[KZG Polynomial Commitment]]