github.com/consensys/gnark-crypto@v0.14.0/internal/generator/sumcheck/test_vectors/main.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir"
     7  	"github.com/consensys/gnark-crypto/internal/generator/test_vector_utils/small_rational"
     8  	"github.com/consensys/gnark-crypto/internal/generator/test_vector_utils/small_rational/polynomial"
     9  	"github.com/consensys/gnark-crypto/internal/generator/test_vector_utils/small_rational/sumcheck"
    10  	"github.com/consensys/gnark-crypto/internal/generator/test_vector_utils/small_rational/test_vector_utils"
    11  	"hash"
    12  	"math/bits"
    13  	"os"
    14  	"path/filepath"
    15  )
    16  
    17  func runMultilin(testCaseInfo *TestCaseInfo) error {
    18  
    19  	var poly polynomial.MultiLin
    20  	if v, err := test_vector_utils.SliceToElementSlice(testCaseInfo.Values); err == nil {
    21  		poly = v
    22  	} else {
    23  		return err
    24  	}
    25  
    26  	var hsh hash.Hash
    27  	var err error
    28  	if hsh, err = test_vector_utils.HashFromDescription(testCaseInfo.Hash); err != nil {
    29  		return err
    30  	}
    31  
    32  	proof, err := sumcheck.Prove(
    33  		&singleMultilinClaim{poly}, fiatshamir.WithHash(hsh))
    34  	if err != nil {
    35  		return err
    36  	}
    37  	testCaseInfo.Proof = toPrintableProof(proof)
    38  
    39  	// Verification
    40  	if v, _err := test_vector_utils.SliceToElementSlice(testCaseInfo.Values); _err == nil {
    41  		poly = v
    42  	} else {
    43  		return _err
    44  	}
    45  	var claimedSum small_rational.SmallRational
    46  	if _, err = claimedSum.SetInterface(testCaseInfo.ClaimedSum); err != nil {
    47  		return err
    48  	}
    49  
    50  	if err = sumcheck.Verify(singleMultilinLazyClaim{g: poly, claimedSum: claimedSum}, proof, fiatshamir.WithHash(hsh)); err != nil {
    51  		return fmt.Errorf("proof rejected: %v", err)
    52  	}
    53  
    54  	proof.PartialSumPolys[0][0].Add(&proof.PartialSumPolys[0][0], test_vector_utils.ToElement(1))
    55  	if err = sumcheck.Verify(singleMultilinLazyClaim{g: poly, claimedSum: claimedSum}, proof, fiatshamir.WithHash(hsh)); err == nil {
    56  		return fmt.Errorf("bad proof accepted")
    57  	}
    58  	return nil
    59  }
    60  
    61  func run(testCaseInfo *TestCaseInfo) error {
    62  	switch testCaseInfo.Type {
    63  	case "multilin":
    64  		return runMultilin(testCaseInfo)
    65  	default:
    66  		return fmt.Errorf("type \"%s\" unrecognized", testCaseInfo.Type)
    67  	}
    68  }
    69  
    70  func runAll(relPath string) error {
    71  	var filename string
    72  	var err error
    73  	if filename, err = filepath.Abs(relPath); err != nil {
    74  		return err
    75  	}
    76  
    77  	var bytes []byte
    78  
    79  	if bytes, err = os.ReadFile(filename); err != nil {
    80  		return err
    81  	}
    82  
    83  	var testCasesInfo TestCasesInfo
    84  	if err = json.Unmarshal(bytes, &testCasesInfo); err != nil {
    85  		return err
    86  	}
    87  
    88  	failed := false
    89  	for name, testCase := range testCasesInfo {
    90  		if err = run(testCase); err != nil {
    91  			fmt.Println(name, ":", err)
    92  			failed = true
    93  		}
    94  	}
    95  
    96  	if failed {
    97  		return fmt.Errorf("test case failed")
    98  	}
    99  
   100  	if bytes, err = json.MarshalIndent(testCasesInfo, "", "\t"); err != nil {
   101  		return err
   102  	}
   103  
   104  	return os.WriteFile(filename, bytes, 0)
   105  }
   106  
   107  func main() {
   108  	if err := runAll("sumcheck/test_vectors/vectors.json"); err != nil {
   109  		fmt.Println(err)
   110  		os.Exit(-1)
   111  	}
   112  }
   113  
   114  type TestCasesInfo map[string]*TestCaseInfo
   115  
   116  type TestCaseInfo struct {
   117  	Type        string                            `json:"type"`
   118  	Hash        test_vector_utils.HashDescription `json:"hash"`
   119  	Values      []interface{}                     `json:"values"`
   120  	Description string                            `json:"description"`
   121  	Proof       PrintableProof                    `json:"proof"`
   122  	ClaimedSum  interface{}                       `json:"claimedSum"`
   123  }
   124  
   125  type PrintableProof struct {
   126  	PartialSumPolys [][]interface{} `json:"partialSumPolys"`
   127  	FinalEvalProof  interface{}     `json:"finalEvalProof"`
   128  }
   129  
   130  func toPrintableProof(proof sumcheck.Proof) (printable PrintableProof) {
   131  	if proof.FinalEvalProof != nil {
   132  		panic("null expected")
   133  	}
   134  	printable.FinalEvalProof = struct{}{}
   135  	printable.PartialSumPolys = test_vector_utils.ElementSliceSliceToInterfaceSliceSlice(proof.PartialSumPolys)
   136  	return
   137  }
   138  
   139  type singleMultilinClaim struct {
   140  	g polynomial.MultiLin
   141  }
   142  
   143  func (c singleMultilinClaim) ProveFinalEval([]small_rational.SmallRational) interface{} {
   144  	return nil // verifier can compute the final eval itself
   145  }
   146  
   147  func (c singleMultilinClaim) VarsNum() int {
   148  	return bits.TrailingZeros(uint(len(c.g)))
   149  }
   150  
   151  func (c singleMultilinClaim) ClaimsNum() int {
   152  	return 1
   153  }
   154  
   155  func sumForX1One(g polynomial.MultiLin) polynomial.Polynomial {
   156  	sum := g[len(g)/2]
   157  	for i := len(g)/2 + 1; i < len(g); i++ {
   158  		sum.Add(&sum, &g[i])
   159  	}
   160  	return []small_rational.SmallRational{sum}
   161  }
   162  
   163  func (c singleMultilinClaim) Combine(small_rational.SmallRational) polynomial.Polynomial {
   164  	return sumForX1One(c.g)
   165  }
   166  
   167  func (c *singleMultilinClaim) Next(r small_rational.SmallRational) polynomial.Polynomial {
   168  	c.g.Fold(r)
   169  	return sumForX1One(c.g)
   170  }
   171  
   172  type singleMultilinLazyClaim struct {
   173  	g          polynomial.MultiLin
   174  	claimedSum small_rational.SmallRational
   175  }
   176  
   177  func (c singleMultilinLazyClaim) VerifyFinalEval(r []small_rational.SmallRational, _ small_rational.SmallRational, purportedValue small_rational.SmallRational, _ interface{}) error {
   178  	val := c.g.Evaluate(r, nil)
   179  	if val.Equal(&purportedValue) {
   180  		return nil
   181  	}
   182  	return fmt.Errorf("mismatch")
   183  }
   184  
   185  func (c singleMultilinLazyClaim) CombinedSum(small_rational.SmallRational) small_rational.SmallRational {
   186  	return c.claimedSum
   187  }
   188  
   189  func (c singleMultilinLazyClaim) Degree(int) int {
   190  	return 1
   191  }
   192  
   193  func (c singleMultilinLazyClaim) ClaimsNum() int {
   194  	return 1
   195  }
   196  
   197  func (c singleMultilinLazyClaim) VarsNum() int {
   198  	return bits.TrailingZeros(uint(len(c.g)))
   199  }