diff --git a/ecc/bls12-377/fr/kzg/kzg.go b/ecc/bls12-377/fr/kzg/kzg.go index 13263864fa..97e5eca234 100644 --- a/ecc/bls12-377/fr/kzg/kzg.go +++ b/ecc/bls12-377/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bls12-377/fr/kzg/kzg_test.go b/ecc/bls12-377/fr/kzg/kzg_test.go index ba50e9707b..189878b7cb 100644 --- a/ecc/bls12-377/fr/kzg/kzg_test.go +++ b/ecc/bls12-377/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bls12-378/fr/kzg/kzg.go b/ecc/bls12-378/fr/kzg/kzg.go index 5877500814..5a3646fff6 100644 --- a/ecc/bls12-378/fr/kzg/kzg.go +++ b/ecc/bls12-378/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bls12-378/fr/kzg/kzg_test.go b/ecc/bls12-378/fr/kzg/kzg_test.go index 49ae70d163..a14db242a0 100644 --- a/ecc/bls12-378/fr/kzg/kzg_test.go +++ b/ecc/bls12-378/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bls12-381/fr/kzg/kzg.go b/ecc/bls12-381/fr/kzg/kzg.go index 63920a1e0f..24ebfe2dec 100644 --- a/ecc/bls12-381/fr/kzg/kzg.go +++ b/ecc/bls12-381/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bls12-381/fr/kzg/kzg_test.go b/ecc/bls12-381/fr/kzg/kzg_test.go index 1be5e6d0be..573c1c3111 100644 --- a/ecc/bls12-381/fr/kzg/kzg_test.go +++ b/ecc/bls12-381/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bls24-315/fr/kzg/kzg.go b/ecc/bls24-315/fr/kzg/kzg.go index 35a6a31f60..c43c3763b5 100644 --- a/ecc/bls24-315/fr/kzg/kzg.go +++ b/ecc/bls24-315/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bls24-315/fr/kzg/kzg_test.go b/ecc/bls24-315/fr/kzg/kzg_test.go index 5b0685930d..832b8466c0 100644 --- a/ecc/bls24-315/fr/kzg/kzg_test.go +++ b/ecc/bls24-315/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bls24-317/fr/kzg/kzg.go b/ecc/bls24-317/fr/kzg/kzg.go index dd32da7196..9059f3c961 100644 --- a/ecc/bls24-317/fr/kzg/kzg.go +++ b/ecc/bls24-317/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bls24-317/fr/kzg/kzg_test.go b/ecc/bls24-317/fr/kzg/kzg_test.go index eb6570bdc3..85fd1ae773 100644 --- a/ecc/bls24-317/fr/kzg/kzg_test.go +++ b/ecc/bls24-317/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bn254/fr/kzg/kzg.go b/ecc/bn254/fr/kzg/kzg.go index 970c6a03e1..53b40a5373 100644 --- a/ecc/bn254/fr/kzg/kzg.go +++ b/ecc/bn254/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bn254/fr/kzg/kzg_test.go b/ecc/bn254/fr/kzg/kzg_test.go index 44bd54aa59..468bc0d6d7 100644 --- a/ecc/bn254/fr/kzg/kzg_test.go +++ b/ecc/bn254/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bw6-633/fr/kzg/kzg.go b/ecc/bw6-633/fr/kzg/kzg.go index d6fe817bf3..1576325403 100644 --- a/ecc/bw6-633/fr/kzg/kzg.go +++ b/ecc/bw6-633/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bw6-633/fr/kzg/kzg_test.go b/ecc/bw6-633/fr/kzg/kzg_test.go index 093a99a715..0481c64e16 100644 --- a/ecc/bw6-633/fr/kzg/kzg_test.go +++ b/ecc/bw6-633/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bw6-756/fr/kzg/kzg.go b/ecc/bw6-756/fr/kzg/kzg.go index e33ac6fd24..95eaa5c0a0 100644 --- a/ecc/bw6-756/fr/kzg/kzg.go +++ b/ecc/bw6-756/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bw6-756/fr/kzg/kzg_test.go b/ecc/bw6-756/fr/kzg/kzg_test.go index 9dc3c8d2ea..dc8700ee98 100644 --- a/ecc/bw6-756/fr/kzg/kzg_test.go +++ b/ecc/bw6-756/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/ecc/bw6-761/fr/kzg/kzg.go b/ecc/bw6-761/fr/kzg/kzg.go index 24a74dd110..e1265fd772 100644 --- a/ecc/bw6-761/fr/kzg/kzg.go +++ b/ecc/bw6-761/fr/kzg/kzg.go @@ -223,7 +223,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -259,7 +260,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -316,8 +317,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -327,7 +329,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -360,10 +362,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -506,7 +509,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -523,6 +526,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/ecc/bw6-761/fr/kzg/kzg_test.go b/ecc/bw6-761/fr/kzg/kzg_test.go index 6aec4b93cc..b8b704fb99 100644 --- a/ecc/bw6-761/fr/kzg/kzg_test.go +++ b/ecc/bw6-761/fr/kzg/kzg_test.go @@ -200,6 +200,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -214,6 +221,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0]) diff --git a/internal/generator/kzg/template/kzg.go.tmpl b/internal/generator/kzg/template/kzg.go.tmpl index cb31d48c83..85f608d4ce 100644 --- a/internal/generator/kzg/template/kzg.go.tmpl +++ b/internal/generator/kzg/template/kzg.go.tmpl @@ -206,7 +206,8 @@ func Verify(commitment *Digest, proof *OpeningProof, point fr.Element, vk Verify // * point is the point at which the polynomials are opened. // * digests is the list of committed polynomials to open, need to derive the challenge using Fiat Shamir. // * polynomials is the list of polynomials to open, they are supposed to be of the same size. -func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey) (BatchOpeningProof, error) { +// * dataTranscript extra data that might be needed to derive the challenge used for folding +func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr.Element, hf hash.Hash, pk ProvingKey, dataTranscript ...[]byte) (BatchOpeningProof, error) { // check for invalid sizes nbDigests := len(digests) @@ -242,7 +243,7 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr wg.Wait() // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, res.ClaimedValues, hf, dataTranscript...) if err != nil { return BatchOpeningProof{}, err } @@ -299,8 +300,9 @@ func BatchOpenSinglePoint(polynomials [][]fr.Element, digests []Digest, point fr // // * digests list of digests on which batchOpeningProof is based // * batchOpeningProof opening proof of digests +// * transcript extra data needed to derive the challenge used for folding. // * returns the folded version of batchOpeningProof, Digest, the folded version of digests -func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash) (OpeningProof, Digest, error) { +func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, dataTranscript ...[]byte) (OpeningProof, Digest, error) { nbDigests := len(digests) @@ -310,7 +312,7 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. } // derive the challenge γ, binded to the point and the commitments - gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf) + gamma, err := deriveGamma(point, digests, batchOpeningProof.ClaimedValues, hf, dataTranscript...) if err != nil { return OpeningProof{}, Digest{}, ErrInvalidNbDigests } @@ -343,10 +345,11 @@ func FoldProof(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr. // // * digests list of digests on which opening proof is done // * batchOpeningProof proof of correct opening on the digests -func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey) error { +// * dataTranscript extra data that might be needed to derive the challenge used for the folding +func BatchVerifySinglePoint(digests []Digest, batchOpeningProof *BatchOpeningProof, point fr.Element, hf hash.Hash, vk VerifyingKey, dataTranscript ...[]byte) error { // fold the proof - foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf) + foldedProof, foldedDigest, err := FoldProof(digests, batchOpeningProof, point, hf, dataTranscript...) if err != nil { return err } @@ -489,7 +492,7 @@ func fold(di []Digest, fai []fr.Element, ci []fr.Element) (Digest, fr.Element, e } // deriveGamma derives a challenge using Fiat Shamir to fold proofs. -func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash) (fr.Element, error) { +func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, hf hash.Hash, dataTranscript ...[]byte) (fr.Element, error) { // derive the challenge gamma, binded to the point and the commitments fs := fiatshamir.NewTranscript(hf, "gamma") @@ -506,6 +509,13 @@ func deriveGamma(point fr.Element, digests []Digest, claimedValues []fr.Element, return fr.Element{}, err } } + + for i := 0; i < len(dataTranscript); i++ { + if err := fs.Bind("gamma", dataTranscript[i]); err != nil { + return fr.Element{}, err + } + } + gammaByte, err := fs.ComputeChallenge("gamma") if err != nil { return fr.Element{}, err diff --git a/internal/generator/kzg/template/kzg.test.go.tmpl b/internal/generator/kzg/template/kzg.test.go.tmpl index 40f38512fa..3cca01af93 100644 --- a/internal/generator/kzg/template/kzg.test.go.tmpl +++ b/internal/generator/kzg/template/kzg.test.go.tmpl @@ -182,6 +182,13 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + var salt fr.Element + salt.SetRandom() + proofExtendedTranscript, err := BatchOpenSinglePoint(f, digests, point, hf, testSrs.Pk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + // verify the claimed values for i := range f { expectedClaim := eval(f[i], point) @@ -196,6 +203,12 @@ func TestBatchVerifySinglePoint(t *testing.T) { t.Fatal(err) } + // verify correct proof with extended transcript + err = BatchVerifySinglePoint(digests, &proofExtendedTranscript, point, hf, testSrs.Vk, salt.Marshal()) + if err != nil { + t.Fatal(err) + } + { // verify wrong proof proof.ClaimedValues[0].Double(&proof.ClaimedValues[0])