diff --git a/ipa/ipa_test.go b/ipa/ipa_test.go index 5d2629c..7b92b43 100644 --- a/ipa/ipa_test.go +++ b/ipa/ipa_test.go @@ -4,15 +4,20 @@ import ( "bytes" "crypto/sha256" "encoding/hex" - "os" + "fmt" "testing" - "github.com/crate-crypto/go-ipa/bandersnatch/fr" "github.com/crate-crypto/go-ipa/banderwagon" + "github.com/crate-crypto/go-ipa/bandersnatch/fr" "github.com/crate-crypto/go-ipa/common" "github.com/crate-crypto/go-ipa/test_helper" ) +const ( + transcriptLabelIPA = "ipa" + transcriptLabelTest = "test" +) + var ipaConf *IPAConfig func TestMain(m *testing.M) { @@ -21,40 +26,90 @@ func TestMain(m *testing.M) { if err != nil { panic(err) } - os.Exit(m.Run()) + m.Run() +} + +func hexEqual(t *testing.T, got []byte, wantHex, msg string) { + t.Helper() + gh := hex.EncodeToString(got) + if gh != wantHex { + t.Fatalf("%s: mismatch\n got: %s\n want: %s", msg, gh, wantHex) + } +} + +func scalarEqualHex(t *testing.T, got *fr.Element, wantHex, msg string) { + t.Helper() + gb := got.Bytes() + gh := hex.EncodeToString(gb[:]) + if gh != wantHex { + t.Fatalf("%s: mismatch\n got: %s\n want: %s", msg, gh, wantHex) + } +} + +func pointHex(p *banderwagon.Element) string { + b := p.Bytes() + return hex.EncodeToString(b[:]) +} + +func removeDuplicatePoints(points []banderwagon.Element) []banderwagon.Element { + seen := make(map[[32]byte]struct{}, len(points)) + out := make([]banderwagon.Element, 0, len(points)) + for _, p := range points { + b := p.Bytes() + var k [32]byte + copy(k[:], b[:]) + if _, ok := seen[k]; ok { + continue + } + seen[k] = struct{}{} + out = append(out, p) + } + return out +} + +func serializeDeserializeProof(t *testing.T, proof IPAProof) IPAProof { + t.Helper() + buf := new(bytes.Buffer) + if err := proof.Write(buf); err != nil { + t.Fatal("failed to write proof:", err) + } + var got IPAProof + if err := got.Read(buf); err != nil { + t.Fatal("failed to read proof:", err) + } + if !got.Equal(proof) { + t.Fatal("proof serialization does not match deserialization for IPA") + } + return got } func TestIPAProofCreateVerify(t *testing.T) { t.Parallel() - // Shared View var point fr.Element point.SetUint64(123456789) - // Prover view poly := test_helper.TestPoly256(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) - prover_comm := ipaConf.Commit(poly) - - prover_transcript := common.NewTranscript("ipa") + proverComm := ipaConf.Commit(poly) + proverTranscript := common.NewTranscript(transcriptLabelIPA) - proof, err := CreateIPAProof(prover_transcript, ipaConf, prover_comm, poly, point) + proof, err := CreateIPAProof(proverTranscript, ipaConf, proverComm, poly, point) if err != nil { t.Fatalf("could not create proof: %s", err) } - lagrange_coeffs := ipaConf.PrecomputedWeights.ComputeBarycentricCoefficients(point) - inner_product, err := InnerProd(poly, lagrange_coeffs) + lagrangeCoeffs := ipaConf.PrecomputedWeights.ComputeBarycentricCoefficients(point) + innerProduct, err := InnerProd(poly, lagrangeCoeffs) if err != nil { t.Fatalf("could not compute inner product: %s", err) } - test_serialize_deserialize_proof(t, proof) + serializeDeserializeProof(t, proof) - // Verifier view - verifier_comm := prover_comm // In reality, the verifier will rebuild this themselves - verifier_transcript := common.NewTranscript("ipa") + verifierComm := proverComm + verifierTranscript := common.NewTranscript(transcriptLabelIPA) - ok, err := CheckIPAProof(verifier_transcript, ipaConf, verifier_comm, proof, point, inner_product) + ok, err := CheckIPAProof(verifierTranscript, ipaConf, verifierComm, proof, point, innerProduct) if err != nil { t.Fatalf("could not check proof: %s", err) } @@ -66,12 +121,9 @@ func TestIPAProofCreateVerify(t *testing.T) { func TestIPAConsistencySimpleProof(t *testing.T) { t.Parallel() - // Shared View - var input_point fr.Element - input_point.SetUint64(2101) + var inputPoint fr.Element + inputPoint.SetUint64(2101) - // Prover view - // poly := test_helper.TestPoly256( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, @@ -83,90 +135,115 @@ func TestIPAConsistencySimpleProof(t *testing.T) { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ) - prover_comm := ipaConf.Commit(poly) - test_helper.PointEqualHex(t, prover_comm, "1b9dff8f5ebbac250d291dfe90e36283a227c64b113c37f1bfb9e7a743cdb128") + proverComm := ipaConf.Commit(poly) + test_helper.PointEqualHex(t, proverComm, "1b9dff8f5ebbac250d291dfe90e36283a227c64b113c37f1bfb9e7a743cdb128") - prover_transcript := common.NewTranscript("test") - proof, err := CreateIPAProof(prover_transcript, ipaConf, prover_comm, poly, input_point) + proverTranscript := common.NewTranscript(transcriptLabelTest) + proof, err := CreateIPAProof(proverTranscript, ipaConf, proverComm, poly, inputPoint) if err != nil { t.Fatalf("could not create proof: %s", err) } - lagrange_coeffs := ipaConf.PrecomputedWeights.ComputeBarycentricCoefficients(input_point) - output_point, err := InnerProd(poly, lagrange_coeffs) + lagrangeCoeffs := ipaConf.PrecomputedWeights.ComputeBarycentricCoefficients(inputPoint) + outputPoint, err := InnerProd(poly, lagrangeCoeffs) if err != nil { t.Fatalf("could not compute inner product: %s", err) } - test_helper.ScalarEqualHex(t, output_point, "4a353e70b03c89f161de002e8713beec0d740a5e20722fd5bd68b30540a33208") - - // Lets check the state of the transcript, by squeezing out a challenge - p_challenge := prover_transcript.ChallengeScalar([]byte("state")) - test_helper.ScalarEqualHex(t, p_challenge, "0a81881cbfd7d7197a54ebd67ed6a68b5867f3c783706675b34ece43e85e7306") + test_helper.ScalarEqualHex(t, outputPoint, "4a353e70b03c89f161de002e8713beec0d740a5e20722fd5bd68b30540a33208") - // Note, that we can be confident that any implementation which passes the above conditions - // will have a proof object that is consistent, as the transcript adds everything into the proof + pChallenge := proverTranscript.ChallengeScalar([]byte("state")) + test_helper.ScalarEqualHex(t, pChallenge, "0a81881cbfd7d7197a54ebd67ed6a68b5867f3c783706675b34ece43e85e7306") - // Verifier view - // - verifier_comm := prover_comm // In reality, the verifier will rebuild this themselves - verifier_transcript := common.NewTranscript("test") + verifierComm := proverComm + verifierTranscript := common.NewTranscript(transcriptLabelTest) - ok, err := CheckIPAProof(verifier_transcript, ipaConf, verifier_comm, proof, input_point, output_point) + ok, err := CheckIPAProof(verifierTranscript, ipaConf, verifierComm, proof, inputPoint, outputPoint) if err != nil { t.Fatalf("could not check proof: %s", err) } if !ok { t.Fatal("inner product proof failed") } - // - v_challenge := verifier_transcript.ChallengeScalar([]byte("state")) - if !v_challenge.Equal(&p_challenge) { + + vChallenge := verifierTranscript.ChallengeScalar([]byte("state")) + if !vChallenge.Equal(&pChallenge) { t.Fatal("prover and verifier state are not the same. The proof should not have passed!") } - // Check that the serialised proof matches the other implementations - expected := "273395a8febdaed38e94c3d874e99c911a47dd84616d54c55021d5c4131b507e46a4ec2c7e82b77ec2f533994c91ca7edaef212c666a1169b29c323eabb0cf690e0146638d0e2d543f81da4bd597bf3013e1663f340a8f87b845495598d0a3951590b6417f868edaeb3424ff174901d1185a53a3ee127fb7be0af42dda44bf992885bde279ef821a298087717ef3f2b78b2ede7f5d2ea1b60a4195de86a530eb247fd7e456012ae9a070c61635e55d1b7a340dfab8dae991d6273d099d9552815434cc1ba7bcdae341cf7928c6f25102370bdf4b26aad3af654d9dff4b3735661db3177342de5aad774a59d3e1b12754aee641d5f9cd1ecd2751471b308d2d8410add1c9fcc5a2b7371259f0538270832a98d18151f653efbc60895fab8be9650510449081626b5cd24671d1a3253487d44f589c2ff0da3557e307e520cf4e0054bbf8bdffaa24b7e4cce5092ccae5a08281ee24758374f4e65f126cacce64051905b5e2038060ad399c69ca6cb1d596d7c9cb5e161c7dcddc1a7ad62660dd4a5f69b31229b80e6b3df520714e4ea2b5896ebd48d14c7455e91c1ecf4acc5ffb36937c49413b7d1005dd6efbd526f5af5d61131ca3fcdae1218ce81c75e62b39100ec7f474b48a2bee6cef453fa1bc3db95c7c6575bc2d5927cbf7413181ac905766a4038a7b422a8ef2bf7b5059b5c546c19a33c1049482b9a9093f864913ca82290decf6e9a65bf3f66bc3ba4a8ed17b56d890a83bcbe74435a42499dec115" - + expectedHex := "273395a8febdaed38e94c3d874e99c911a47dd84616d54c55021d5c4131b507e46a4ec2c7e82b77ec2f533994c91ca7edaef212c666a1169b29c323eabb0cf690e0146638d0e2d543f81da4bd597bf3013e1663f340a8f87b845495598d0a3951590b6417f868edaeb3424ff174901d1185a53a3ee127fb7be0af42dda44bf992885bde279ef821a298087717ef3f2b78b2ede7f5d2ea1b60a4195de86a530eb247fd7e456012ae9a070c61635e55d1b7a340dfab8dae991d6273d099d9552815434cc1ba7bcdae341cf7928c6f25102370bdf4b26aad3af654d9dff4b3735661db3177342de5aad774a59d3e1b12754aee641d5f9cd1ecd2751471b308d2d8410add1c9fcc5a2b7371259f0538270832a98d18151f653efbc60895fab8be9650510449081626b5cd24671d1a3253487d44f589c2ff0da3557e307e520cf4e0054bbf8bdffaa24b7e4cce5092ccae5a08281ee24758374f4e65f126cacce64051905b5e2038060ad399c69ca6cb1d596d7c9cb5e161c7dcddc1a7ad62660dd4a5f69b31229b80e6b3df520714e4ea2b5896ebd48d14c7455e91c1ecf4acc5ffb36937c49413b7d1005dd6efbd526f5af5d61131ca3fcdae1218ce81c75e62b39100ec7f474b48a2bee6cef453fa1bc3db95c7c6575bc2d5927cbf7413181ac905766a4038a7b422a8ef2bf7b5059b5c546c19a33c1049482b9a9093f864913ca82290decf6e9a65bf3f66bc3ba4a8ed17b56d890a83bcbe74435a42499dec115" buf := new(bytes.Buffer) if err := proof.Write(buf); err != nil { - t.Fatal("could not serialise proof") - } + t.Fatal("could not serialise proof:", err) + } + hexEqual(t, buf.Bytes(), expectedHex, "serialized proof") + + t.Run("fails if claimed output is wrong", func(t *testing.T) { + vt := common.NewTranscript(transcriptLabelTest) + var one fr.Element + one.SetOne() + var bad fr.Element + bad.Add(&outputPoint, &one) // output + 1 + ok, err := CheckIPAProof(vt, ipaConf, verifierComm, proof, inputPoint, bad) + if err == nil && ok { + t.Fatal("verification should fail with incorrect claimed output") + } + }) + + t.Run("fails if commitment is tampered", func(t *testing.T) { + vt := common.NewTranscript(transcriptLabelTest) + var tampered banderwagon.Element + tampered.Add(&verifierComm, &banderwagon.Generator) // shift commitment + ok, err := CheckIPAProof(vt, ipaConf, tampered, proof, inputPoint, outputPoint) + if err == nil && ok { + t.Fatal("verification should fail with tampered commitment") + } + }) - bytes := buf.Bytes() - if expected != hex.EncodeToString(bytes) { - t.Fatal("expected serialised proof is different from the other implementations") - } + t.Run("fails if proof bytes are corrupted", func(t *testing.T) { + b := new(bytes.Buffer) + if err := proof.Write(b); err != nil { + t.Fatal(err) + } + raw := b.Bytes() + if len(raw) == 0 { + t.Fatal("empty proof bytes?") + } + raw[len(raw)-1] ^= 0x01 + + var corrupted IPAProof + if err := corrupted.Read(bytes.NewReader(raw)); err == nil { + vt := common.NewTranscript(transcriptLabelTest) + ok, err := CheckIPAProof(vt, ipaConf, verifierComm, corrupted, inputPoint, outputPoint) + if err == nil && ok { + t.Fatal("verification should fail with corrupted proof") + } + } + }) } func TestBasicInnerProduct(t *testing.T) { t.Parallel() - var a []fr.Element - for i := 0; i < 10; i++ { - var tmp fr.Element - tmp.SetUint64(uint64(i)) - a = append(a, tmp) - } - var b []fr.Element + a := make([]fr.Element, 10) + b := make([]fr.Element, 10) for i := 0; i < 10; i++ { - var tmp fr.Element - tmp.SetOne() - b = append(b, tmp) + a[i].SetUint64(uint64(i)) + b[i].SetOne() } got, err := InnerProd(a, b) if err != nil { t.Fatalf("could not compute inner product: %s", err) } - expected := fr.Zero() + expected := fr.Zero() for i := 0; i < 10; i++ { var tmp fr.Element tmp.SetUint64(uint64(i)) expected.Add(&expected, &tmp) } if !got.Equal(&expected) { - t.Fatal("the inner product should just be the sum of a since b is just 1") + t.Fatalf("inner product should equal sum(a) since b is all ones\n got: %x\n exp: %x", got.Bytes(), expected.Bytes()) } } @@ -175,35 +252,30 @@ func TestBasicCommit(t *testing.T) { gen := banderwagon.Generator - var generators []banderwagon.Element - for i := 0; i < 5; i++ { - generators = append(generators, gen) + generators := make([]banderwagon.Element, 5) + for i := range generators { + generators[i] = gen } - var a []fr.Element - for i := 0; i < 5; i++ { - var tmp fr.Element - _, err := tmp.SetRandom() - if err != nil { - t.Fatal("could not generate randomness") - } - a = append(a, tmp) + a := make([]fr.Element, 5) + for i := range a { + a[i].SetUint64(uint64(i + 1)) // 1..5 } + got, err := commit(generators, a) if err != nil { - t.Fatalf("could not compute inner product: %s", err) + t.Fatalf("commit failed: %v", err) } total := fr.Zero() - for i := 0; i < 5; i++ { + for i := range a { total.Add(&total, &a[i]) } - var expected banderwagon.Element expected.ScalarMul(&gen, &total) if !got.Equal(&expected) { - t.Fatal("commit function; incorrect results") + t.Fatalf("commit mismatch:\n got: %s\n exp: %s", pointHex(&got), pointHex(&expected)) } } @@ -212,114 +284,181 @@ func TestCRSGeneration(t *testing.T) { generator := banderwagon.Generator points := GenerateRandomPoints(256) - for _, point := range points { - if !point.IsOnCurve() { + for _, p := range points { + if !p.IsOnCurve() { t.Fatal("generated a point that was not on the curve") } - // Check point is in the correct subgroup by doing - // serialise deserialise roundtrip - - bytes := point.Bytes() - err := point.SetBytes(bytes[:]) - if err != nil { + bytes := p.Bytes() + if err := p.SetBytes(bytes[:]); err != nil { t.Fatal("point is not in the banderwagon subgroup") } - if point.Equal(&generator) { - t.Fatal("one of the generated points was the generator. The inner product point is being used as the generator.") + if p.Equal(&generator) { + t.Fatal("one of the generated points was the generator; inner product point should not be the generator") } } - // Check that the points are all unique points = removeDuplicatePoints(points) if len(points) != 256 { - t.Fatal("points contained duplicates") + t.Fatalf("points contained duplicates: got %d unique", len(points)) } - // Now check against the test vectors here: https://hackmd.io/1RcGSMQgT4uREaq1CCx_cg#Methodology - // TODO: This hackmd document needs to be updated - bytes := points[0].Bytes() - got := hex.EncodeToString(bytes[:]) - expected := "01587ad1336675eb912550ec2a28eb8923b824b490dd2ba82e48f14590a298a0" - if got != expected { - t.Fatal("the first point is not correct") + p0 := points[0].Bytes() + got := hex.EncodeToString(p0[:]) + want := "01587ad1336675eb912550ec2a28eb8923b824b490dd2ba82e48f14590a298a0" + if got != want { + t.Fatalf("the first point is not correct\n got: %s\n exp: %s", got, want) } - bytes = points[255].Bytes() - got = hex.EncodeToString(bytes[:]) - expected = "3de2be346b539395b0c0de56a5ccca54a317f1b5c80107b0802af9a62276a4d8" - if got != expected { - t.Fatal("the 256th (last) point is not correct") + + p255 := points[255].Bytes() + got = hex.EncodeToString(p255[:]) + want = "3de2be346b539395b0c0de56a5ccca54a317f1b5c80107b0802af9a62276a4d8" + if got != want { + t.Fatalf("the 256th (last) point is not correct\n got: %s\n exp: %s", got, want) } digest := sha256.New() - for _, point := range points { - bytes := point.Bytes() - digest.Write(bytes[:]) + for _, p := range points { + b := p.Bytes() + digest.Write(b[:]) } hash := digest.Sum(nil) got = hex.EncodeToString(hash[:]) - expected = "1fcaea10bf24f750200e06fa473c76ff0468007291fa548e2d99f09ba9256fdb" - if got != expected { - t.Fatal("unexpected point encountered") + want = "1fcaea10bf24f750200e06fa473c76ff0468007291fa548e2d99f09ba9256fdb" + if got != want { + t.Fatalf("unexpected point encountered\n got: %s\n exp: %s", got, want) } } func TestInsideDomainEvaluation(t *testing.T) { t.Parallel() - // Define some arbitrary polynomial in evaluation form. poly := test_helper.TestPoly256(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) polyComm := ipaConf.Commit(poly) - // For all the possible evaluation points *in the domain*, double check that - // proof generation and verification works correctly. for domainEvalPoint := 0; domainEvalPoint < domainSize; domainEvalPoint++ { - var frEvalPoint fr.Element - frEvalPoint.SetUint64(uint64(domainEvalPoint)) - - // Prover. - transcript := common.NewTranscript("ipa") - proof, err := CreateIPAProof(transcript, ipaConf, polyComm, poly, frEvalPoint) - if err != nil { - t.Fatalf("could not create proof: %s", err) - } + dep := domainEvalPoint + t.Run(fmt.Sprintf("domain-x=%d", dep), func(t *testing.T) { + var frEvalPoint fr.Element + frEvalPoint.SetUint64(uint64(dep)) + + tr := common.NewTranscript(transcriptLabelIPA) + proof, err := CreateIPAProof(tr, ipaConf, polyComm, poly, frEvalPoint) + if err != nil { + t.Fatalf("could not create proof: %s", err) + } + + tr = common.NewTranscript(transcriptLabelIPA) + ok, err := CheckIPAProof(tr, ipaConf, polyComm, proof, frEvalPoint, poly[dep]) + if err != nil { + t.Fatalf("could not check proof: %s", err) + } + if !ok { + t.Fatal("inner product proof failed") + } + }) + } +} - // Verifier. - transcript = common.NewTranscript("ipa") - // We check the proof against what we *know* to be correct regarding `poly` definition in evaluation form. - ok, err := CheckIPAProof(transcript, ipaConf, polyComm, proof, frEvalPoint, poly[domainEvalPoint]) - if err != nil { - t.Fatalf("could not check proof: %s", err) - } - if !ok { - t.Fatal("inner product proof failed") - } +func TestProofSerializeDeserialize(t *testing.T) { + t.Parallel() + + var point fr.Element + point.SetUint64(42) + poly := test_helper.TestPoly256(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) + comm := ipaConf.Commit(poly) + tr := common.NewTranscript(transcriptLabelIPA) + proof, err := CreateIPAProof(tr, ipaConf, comm, poly, point) + if err != nil { + t.Fatalf("could not create proof: %s", err) + } + got := serializeDeserializeProof(t, proof) + if !got.Equal(proof) { + t.Fatal("round-tripped proof not equal") } } -func test_serialize_deserialize_proof(t *testing.T, proof IPAProof) { - buf := new(bytes.Buffer) - if err := proof.Write(buf); err != nil { - t.Fatal("failed to write proof") +func TestInnerProdLinearityFirstArg(t *testing.T) { + t.Parallel() + const n = 16 + + randVec := func() []fr.Element { + v := make([]fr.Element, n) + for i := range v { + if _, err := v[i].SetRandom(); err != nil { + t.Fatal("randomness failed") + } + } + return v } - var got_proof IPAProof - if err := got_proof.Read(buf); err != nil { - t.Fatal("failed to read proof") + a := randVec() + a2 := randVec() + b := randVec() + + c := make([]fr.Element, n) + for i := 0; i < n; i++ { + c[i].Add(&a[i], &a2[i]) } - if !got_proof.Equal(proof) { - t.Fatal("proof serialization does not match deserialization for IPA") + ip1, err := InnerProd(a, b) + if err != nil { + t.Fatal(err) + } + ip2, err := InnerProd(a2, b) + if err != nil { + t.Fatal(err) + } + ip3, err := InnerProd(c, b) + if err != nil { + t.Fatal(err) + } + + sum := fr.Zero() + sum.Add(&sum, &ip1) + sum.Add(&sum, &ip2) + if !ip3.Equal(&sum) { + t.Fatalf("InnerProd not linear in first argument\n (a+a2, b) != (a,b)+(a2,b)\n got: %x\n exp: %x", ip3.Bytes(), sum.Bytes()) + } +} + +func BenchmarkCreateIPAProof(b *testing.B) { + var point fr.Element + point.SetUint64(123456789) + poly := test_helper.TestPoly256(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) + comm := ipaConf.Commit(poly) + + b.ReportAllocs() + for i := 0; i < b.N; i++ { + tr := common.NewTranscript(transcriptLabelIPA) + if _, err := CreateIPAProof(tr, ipaConf, comm, poly, point); err != nil { + b.Fatal(err) + } } } -func removeDuplicatePoints(intSlice []banderwagon.Element) []banderwagon.Element { - allKeys := make(map[banderwagon.Element]bool) - list := []banderwagon.Element{} - for _, item := range intSlice { - if _, value := allKeys[item]; !value { - allKeys[item] = true - list = append(list, item) +func BenchmarkCheckIPAProof(b *testing.B) { + var point fr.Element + point.SetUint64(123456789) + poly := test_helper.TestPoly256(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) + comm := ipaConf.Commit(poly) + tr := common.NewTranscript(transcriptLabelIPA) + proof, err := CreateIPAProof(tr, ipaConf, comm, poly, point) + if err != nil { + b.Fatal(err) + } + lc := ipaConf.PrecomputedWeights.ComputeBarycentricCoefficients(point) + ip, err := InnerProd(poly, lc) + if err != nil { + b.Fatal(err) + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + tr := common.NewTranscript(transcriptLabelIPA) + ok, err := CheckIPAProof(tr, ipaConf, comm, proof, point, ip) + if err != nil || !ok { + b.Fatal("verify failed") } } - return list }