github.com/consensys/gnark-crypto@v0.14.0/internal/generator/pedersen/template/pedersen.test.go.tmpl (about)

     1  import (
     2  	"fmt"
     3  	"testing"
     4  
     5  	"github.com/consensys/gnark-crypto/ecc"
     6  	curve "github.com/consensys/gnark-crypto/ecc/{{.Name}}"
     7  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr"
     8  	"github.com/consensys/gnark-crypto/utils/testutils"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func interfaceSliceToFrSlice(t *testing.T, values ...interface{}) []fr.Element {
    13  	res := make([]fr.Element, len(values))
    14  	for i, v := range values {
    15  		_, err := res[i].SetInterface(v)
    16  		assert.NoError(t, err)
    17  	}
    18  	return res
    19  }
    20  
    21  func randomFrSlice(t *testing.T, size int) []interface{} {
    22  	res := make([]interface{}, size)
    23  	var err error
    24  	for i := range res {
    25  		var v fr.Element
    26  		res[i], err = v.SetRandom()
    27  		assert.NoError(t, err)
    28  	}
    29  	return res
    30  }
    31  
    32  func randomOnG1() (curve.G1Affine, error) { // TODO: Add to G1.go?
    33  	if gBytes, err := randomFrSizedBytes(); err != nil {
    34  		return curve.G1Affine{}, err
    35  	} else {
    36  		return curve.HashToG1(gBytes, []byte("random on g1"))
    37  	}
    38  }
    39  
    40  func randomG1Slice(t *testing.T, size int) []curve.G1Affine {
    41  	res := make([]curve.G1Affine, size)
    42  	for i := range res {
    43  		var err error
    44  		res[i], err = randomOnG1()
    45  		assert.NoError(t, err)
    46  	}
    47  	return res
    48  }
    49  
    50  func testCommit(t *testing.T, values ...interface{}) {
    51  
    52  	basis := randomG1Slice(t, len(values))
    53  
    54  	var (
    55  		pk              []ProvingKey
    56  		vk              VerifyingKey
    57  		err             error
    58  		commitment, pok curve.G1Affine
    59  	)
    60  	valuesFr := interfaceSliceToFrSlice(t, values...)
    61  
    62  	pk, vk, err = Setup([][]curve.G1Affine{basis})
    63  	assert.NoError(t, err)
    64  	commitment, err = pk[0].Commit(valuesFr)
    65  	assert.NoError(t, err)
    66  	pok, err = pk[0].ProveKnowledge(valuesFr)
    67  	assert.NoError(t, err)
    68  	assert.NoError(t, vk.Verify(commitment, pok))
    69  
    70  	pok.Neg(&pok)
    71  	assert.NotNil(t, vk.Verify(commitment, pok))
    72  }
    73  
    74  func TestFoldProofs(t *testing.T) {
    75  
    76  	values := [][]fr.Element{
    77  		interfaceSliceToFrSlice(t, randomFrSlice(t, 5)...),
    78  		interfaceSliceToFrSlice(t, randomFrSlice(t, 5)...),
    79  		interfaceSliceToFrSlice(t, randomFrSlice(t, 5)...),
    80  	}
    81  
    82  	bases := make([][]curve.G1Affine, len(values))
    83  	for i := range bases {
    84  		bases[i] = randomG1Slice(t, len(values[i]))
    85  	}
    86  
    87  	pk, vk, err := Setup(bases)
    88  	assert.NoError(t, err)
    89  
    90  	commitments := make([]curve.G1Affine, len(values))
    91  	for i := range values {
    92  		commitments[i], err = pk[i].Commit(values[i])
    93  		assert.NoError(t, err)
    94  	}
    95  
    96  	hashes, err := fr.Hash([]byte("test"), []byte("pedersen"), 1)
    97  	assert.NoError(t, err)
    98  
    99  	t.Run("folding with zeros", func(t *testing.T) {
   100  		pokFolded, err := BatchProve(pk[:2], [][]fr.Element{
   101  			values[0],
   102  			make([]fr.Element, len(values[1])),
   103  		}, hashes[0])
   104  		assert.NoError(t, err)
   105  		var pok curve.G1Affine
   106  		pok, err = pk[0].ProveKnowledge(values[0])
   107  		assert.NoError(t, err)
   108  		assert.Equal(t, pok, pokFolded)
   109  	})
   110  
   111  	t.Run("run empty", func(t *testing.T) {
   112  		var foldedCommitment curve.G1Affine
   113  		pok, err := BatchProve([]ProvingKey{}, [][]fr.Element{}, hashes[0])
   114  		assert.NoError(t, err)
   115  
   116  		_, err = foldedCommitment.Fold([]curve.G1Affine{}, hashes[0], ecc.MultiExpConfig{NbTasks: 1})
   117  		assert.NoError(t, err)
   118  		assert.NoError(t, vk.Verify(foldedCommitment, pok))
   119  	})
   120  
   121  	run := func(values [][]fr.Element) func(t *testing.T) {
   122  		return func(t *testing.T) {
   123  
   124  			var foldedCommitment curve.G1Affine
   125  			pok, err := BatchProve(pk[:len(values)], values, hashes[0])
   126  			assert.NoError(t, err)
   127  
   128  			_, err = foldedCommitment.Fold(commitments[:len(values)], hashes[0], ecc.MultiExpConfig{NbTasks: 1})
   129  			assert.NoError(t, err)
   130  			assert.NoError(t, vk.Verify(foldedCommitment, pok))
   131  
   132  			pok.Neg(&pok)
   133  			assert.NotNil(t, vk.Verify(foldedCommitment, pok))
   134  		}
   135  	}
   136  
   137  	for i := range values {
   138  		t.Run(fmt.Sprintf("folding %d", i+1), run(values[:i+1]))
   139  	}
   140  }
   141  
   142  func TestCommitToOne(t *testing.T) {
   143  	testCommit(t, 1)
   144  }
   145  
   146  func TestCommitSingle(t *testing.T) {
   147  	testCommit(t, randomFrSlice(t, 1)...)
   148  }
   149  
   150  func TestCommitFiveElements(t *testing.T) {
   151  	testCommit(t, randomFrSlice(t, 5)...)
   152  }
   153  
   154  func TestMarshal(t *testing.T) {
   155  	var pk ProvingKey
   156  	pk.BasisExpSigma = randomG1Slice(t, 5)
   157  	pk.Basis = randomG1Slice(t, 5)
   158  
   159  	var (
   160  		vk  VerifyingKey
   161  		err error
   162  	)
   163  	vk.G, err = curve.RandomOnG2()
   164  	assert.NoError(t, err)
   165  	vk.GSigma, err = curve.RandomOnG2()
   166  	assert.NoError(t, err)
   167  
   168  	t.Run("ProvingKey -> Bytes -> ProvingKey must remain identical.", testutils.SerializationRoundTrip(&pk))
   169  	t.Run("ProvingKey -> Bytes (raw) -> ProvingKey must remain identical.", testutils.SerializationRoundTripRaw(&pk))
   170  	t.Run("VerifyingKey -> Bytes -> VerifyingKey must remain identical.", testutils.SerializationRoundTrip(&vk))
   171  	t.Run("VerifyingKey -> Bytes (raw) -> ProvingKey must remain identical.", testutils.SerializationRoundTripRaw(&vk))
   172  }
   173  
   174  
   175  func TestSemiFoldProofs(t *testing.T) {
   176  	const (
   177  		commitmentLength = 5
   178  		nbCommitments    = 5
   179  	)
   180  	g, err := curve.RandomOnG2()
   181  	assert.NoError(t, err)
   182  
   183  	basis := randomG1Slice(t, commitmentLength*nbCommitments)
   184  
   185  	vk, pk := make([]VerifyingKey, nbCommitments), make([]ProvingKey, nbCommitments)
   186  	for i := range pk {
   187  		var pk0 []ProvingKey
   188  		pk0, vk[i], err = Setup([][]curve.G1Affine{basis[i*commitmentLength : (i+1)*commitmentLength]}, WithG2Point(g))
   189  		assert.NoError(t, err)
   190  		pk[i] = pk0[0]
   191  	}
   192  
   193  	values := make([][]fr.Element, nbCommitments)
   194  	for i := range values {
   195  		values[i] = make([]fr.Element, commitmentLength)
   196  		for j := range values[i] {
   197  			_, err = values[i][j].SetRandom()
   198  			assert.NoError(t, err)
   199  		}
   200  	}
   201  
   202  	commitments := make([]curve.G1Affine, nbCommitments)
   203  	proofs := make([]curve.G1Affine, nbCommitments)
   204  	for i := range commitments {
   205  		commitments[i], err = pk[i].Commit(values[i])
   206  		assert.NoError(t, err)
   207  		proofs[i], err = pk[i].ProveKnowledge(values[i])
   208  		assert.NoError(t, err)
   209  	}
   210  
   211  	var challenge fr.Element
   212  	_, err = challenge.SetRandom()
   213  	assert.NoError(t, err)
   214  
   215  	assert.NoError(t, BatchVerifyMultiVk(vk, commitments, proofs, challenge))
   216  
   217  	// send folded proof
   218  	proof, err := new(curve.G1Affine).Fold(proofs, challenge, ecc.MultiExpConfig{NbTasks: 1})
   219  	assert.NoError(t, err)
   220  	assert.NoError(t, BatchVerifyMultiVk(vk, commitments, []curve.G1Affine{*proof}, challenge))
   221  }