github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-377/fr/sumcheck/sumcheck_test.go (about)

     1  // Copyright 2020 Consensys Software Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Code generated by consensys/gnark-crypto DO NOT EDIT
    16  
    17  package sumcheck
    18  
    19  import (
    20  	"fmt"
    21  	"github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
    22  	"github.com/consensys/gnark-crypto/ecc/bls12-377/fr/polynomial"
    23  	"github.com/consensys/gnark-crypto/ecc/bls12-377/fr/test_vector_utils"
    24  	fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir"
    25  	"github.com/stretchr/testify/assert"
    26  	"hash"
    27  	"math/bits"
    28  	"strings"
    29  	"testing"
    30  )
    31  
    32  type singleMultilinClaim struct {
    33  	g polynomial.MultiLin
    34  }
    35  
    36  func (c singleMultilinClaim) ProveFinalEval(r []fr.Element) interface{} {
    37  	return nil // verifier can compute the final eval itself
    38  }
    39  
    40  func (c singleMultilinClaim) VarsNum() int {
    41  	return bits.TrailingZeros(uint(len(c.g)))
    42  }
    43  
    44  func (c singleMultilinClaim) ClaimsNum() int {
    45  	return 1
    46  }
    47  
    48  func sumForX1One(g polynomial.MultiLin) polynomial.Polynomial {
    49  	sum := g[len(g)/2]
    50  	for i := len(g)/2 + 1; i < len(g); i++ {
    51  		sum.Add(&sum, &g[i])
    52  	}
    53  	return []fr.Element{sum}
    54  }
    55  
    56  func (c singleMultilinClaim) Combine(fr.Element) polynomial.Polynomial {
    57  	return sumForX1One(c.g)
    58  }
    59  
    60  func (c *singleMultilinClaim) Next(r fr.Element) polynomial.Polynomial {
    61  	c.g.Fold(r)
    62  	return sumForX1One(c.g)
    63  }
    64  
    65  type singleMultilinLazyClaim struct {
    66  	g          polynomial.MultiLin
    67  	claimedSum fr.Element
    68  }
    69  
    70  func (c singleMultilinLazyClaim) VerifyFinalEval(r []fr.Element, combinationCoeff fr.Element, purportedValue fr.Element, proof interface{}) error {
    71  	val := c.g.Evaluate(r, nil)
    72  	if val.Equal(&purportedValue) {
    73  		return nil
    74  	}
    75  	return fmt.Errorf("mismatch")
    76  }
    77  
    78  func (c singleMultilinLazyClaim) CombinedSum(combinationCoeffs fr.Element) fr.Element {
    79  	return c.claimedSum
    80  }
    81  
    82  func (c singleMultilinLazyClaim) Degree(i int) int {
    83  	return 1
    84  }
    85  
    86  func (c singleMultilinLazyClaim) ClaimsNum() int {
    87  	return 1
    88  }
    89  
    90  func (c singleMultilinLazyClaim) VarsNum() int {
    91  	return bits.TrailingZeros(uint(len(c.g)))
    92  }
    93  
    94  func testSumcheckSingleClaimMultilin(polyInt []uint64, hashGenerator func() hash.Hash) error {
    95  	poly := make(polynomial.MultiLin, len(polyInt))
    96  	for i, n := range polyInt {
    97  		poly[i].SetUint64(n)
    98  	}
    99  
   100  	claim := singleMultilinClaim{g: poly.Clone()}
   101  
   102  	proof, err := Prove(&claim, fiatshamir.WithHash(hashGenerator()))
   103  	if err != nil {
   104  		return err
   105  	}
   106  
   107  	var sb strings.Builder
   108  	for _, p := range proof.PartialSumPolys {
   109  
   110  		sb.WriteString("\t{")
   111  		for i := 0; i < len(p); i++ {
   112  			sb.WriteString(p[i].String())
   113  			if i+1 < len(p) {
   114  				sb.WriteString(", ")
   115  			}
   116  		}
   117  		sb.WriteString("}\n")
   118  	}
   119  
   120  	lazyClaim := singleMultilinLazyClaim{g: poly, claimedSum: poly.Sum()}
   121  	if err = Verify(lazyClaim, proof, fiatshamir.WithHash(hashGenerator())); err != nil {
   122  		return err
   123  	}
   124  
   125  	proof.PartialSumPolys[0][0].Add(&proof.PartialSumPolys[0][0], test_vector_utils.ToElement(1))
   126  	lazyClaim = singleMultilinLazyClaim{g: poly, claimedSum: poly.Sum()}
   127  	if Verify(lazyClaim, proof, fiatshamir.WithHash(hashGenerator())) == nil {
   128  		return fmt.Errorf("bad proof accepted")
   129  	}
   130  	return nil
   131  }
   132  
   133  func TestSumcheckDeterministicHashSingleClaimMultilin(t *testing.T) {
   134  	//printMsws(36)
   135  
   136  	polys := [][]uint64{
   137  		{1, 2, 3, 4},             // 1 + 2X₁ + X₂
   138  		{1, 2, 3, 4, 5, 6, 7, 8}, // 1 + 4X₁ + 2X₂ + X₃
   139  		{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, // 1 + 8X₁ + 4X₂ + 2X₃ + X₄
   140  	}
   141  
   142  	const MaxStep = 4
   143  	const MaxStart = 4
   144  	hashGens := make([]func() hash.Hash, 0, MaxStart*MaxStep)
   145  
   146  	for step := 0; step < MaxStep; step++ {
   147  		for startState := 0; startState < MaxStart; startState++ {
   148  			if step == 0 && startState == 1 { // unlucky case where a bad proof would be accepted
   149  				continue
   150  			}
   151  			hashGens = append(hashGens, test_vector_utils.NewMessageCounterGenerator(startState, step))
   152  		}
   153  	}
   154  
   155  	for _, poly := range polys {
   156  		for _, hashGen := range hashGens {
   157  			assert.NoError(t, testSumcheckSingleClaimMultilin(poly, hashGen),
   158  				"failed with poly %v and hashGen %v", poly, hashGen())
   159  		}
   160  	}
   161  }