105 lines
2.9 KiB
Go
105 lines
2.9 KiB
Go
package ipa
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/crate-crypto/go-ipa/bandersnatch/fr"
|
|
"github.com/crate-crypto/go-ipa/banderwagon"
|
|
"github.com/crate-crypto/go-ipa/common"
|
|
)
|
|
|
|
// CheckIPAProof verifies an IPA proof for a committed polynomial in evaluation form.
|
|
// It verifies that `proof` is a valid proof for the polynomial at the evaluation
|
|
// point `evalPoint` with result `result`
|
|
func CheckIPAProof(transcript *common.Transcript, ic *IPAConfig, commitment banderwagon.Element, proof IPAProof, evalPoint fr.Element, result fr.Element) (bool, error) {
|
|
transcript.DomainSep(labelDomainSep)
|
|
|
|
if len(proof.L) != len(proof.R) {
|
|
return false, fmt.Errorf("vectors L and R should be the same size")
|
|
}
|
|
if len(proof.L) != int(ic.numRounds) {
|
|
return false, fmt.Errorf("the number of points for L and R should be equal to the number of rounds")
|
|
}
|
|
|
|
b := computeBVector(ic, evalPoint)
|
|
|
|
transcript.AppendPoint(&commitment, labelC)
|
|
transcript.AppendScalar(&evalPoint, labelInputPoint)
|
|
transcript.AppendScalar(&result, labelOutputPoint)
|
|
|
|
w := transcript.ChallengeScalar(labelW)
|
|
|
|
// Rescaling of q.
|
|
var q banderwagon.Element
|
|
q.ScalarMul(&ic.Q, &w)
|
|
|
|
var qy banderwagon.Element
|
|
qy.ScalarMul(&q, &result)
|
|
commitment.Add(&commitment, &qy)
|
|
|
|
challenges := generateChallenges(transcript, &proof)
|
|
challengesInv := fr.BatchInvert(challenges)
|
|
|
|
// Compute expected commitment
|
|
var err error
|
|
for i := 0; i < len(challenges); i++ {
|
|
x := challenges[i]
|
|
L := proof.L[i]
|
|
R := proof.R[i]
|
|
|
|
commitment, err = commit([]banderwagon.Element{commitment, L, R}, []fr.Element{fr.One(), x, challengesInv[i]})
|
|
if err != nil {
|
|
return false, fmt.Errorf("could not compute commitment+x*L+x^-1*R: %w", err)
|
|
}
|
|
}
|
|
|
|
g := ic.SRS
|
|
|
|
// We compute the folding-scalars for g and b.
|
|
foldingScalars := make([]fr.Element, len(g))
|
|
for i := 0; i < len(g); i++ {
|
|
scalar := fr.One()
|
|
|
|
for challengeIdx := 0; challengeIdx < len(challenges); challengeIdx++ {
|
|
if i&(1<<(7-challengeIdx)) > 0 {
|
|
scalar.Mul(&scalar, &challengesInv[challengeIdx])
|
|
}
|
|
}
|
|
foldingScalars[i] = scalar
|
|
}
|
|
g0, err := MultiScalar(g, foldingScalars)
|
|
if err != nil {
|
|
return false, fmt.Errorf("could not compute g0: %w", err)
|
|
}
|
|
b0, err := InnerProd(b, foldingScalars)
|
|
if err != nil {
|
|
return false, fmt.Errorf("could not compute b0: %w", err)
|
|
}
|
|
|
|
var got banderwagon.Element
|
|
// g0 * a + (a * b) * Q;
|
|
var part_1 banderwagon.Element
|
|
part_1.ScalarMul(&g0, &proof.A_scalar)
|
|
|
|
var part_2 banderwagon.Element
|
|
var part_2a fr.Element
|
|
|
|
part_2a.Mul(&b0, &proof.A_scalar)
|
|
part_2.ScalarMul(&q, &part_2a)
|
|
|
|
got.Add(&part_1, &part_2)
|
|
|
|
return got.Equal(&commitment), nil
|
|
}
|
|
|
|
func generateChallenges(transcript *common.Transcript, proof *IPAProof) []fr.Element {
|
|
|
|
challenges := make([]fr.Element, len(proof.L))
|
|
for i := 0; i < len(proof.L); i++ {
|
|
transcript.AppendPoint(&proof.L[i], labelL)
|
|
transcript.AppendPoint(&proof.R[i], labelR)
|
|
challenges[i] = transcript.ChallengeScalar(labelX)
|
|
}
|
|
return challenges
|
|
}
|