github.com/consensys/gnark@v0.11.0/backend/solidity/solidity_test.go (about)

     1  package solidity_test
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"fmt"
     6  	"hash"
     7  	"testing"
     8  
     9  	"github.com/consensys/gnark-crypto/ecc"
    10  	"github.com/consensys/gnark/backend"
    11  	"github.com/consensys/gnark/backend/solidity"
    12  	"github.com/consensys/gnark/frontend"
    13  	"github.com/consensys/gnark/test"
    14  	"golang.org/x/crypto/sha3"
    15  )
    16  
    17  type noCommitCircuit struct {
    18  	A, B, Out frontend.Variable `gnark:",public"`
    19  }
    20  
    21  func (c *noCommitCircuit) Define(api frontend.API) error {
    22  	res := api.Mul(c.A, c.B)
    23  	api.AssertIsEqual(res, c.Out)
    24  	return nil
    25  }
    26  
    27  type commitCircuit struct {
    28  	A, B, Out frontend.Variable `gnark:",public"`
    29  }
    30  
    31  func (c *commitCircuit) Define(api frontend.API) error {
    32  	res := api.Mul(c.A, c.B)
    33  	api.AssertIsEqual(res, c.Out)
    34  	cmter, ok := api.(frontend.Committer)
    35  	if !ok {
    36  		return fmt.Errorf("api does not support commitment")
    37  	}
    38  	cmt1, err := cmter.Commit(res)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	api.AssertIsDifferent(cmt1, res)
    43  	return nil
    44  }
    45  
    46  type twoCommitCircuit struct {
    47  	A, B, Out frontend.Variable `gnark:",public"`
    48  }
    49  
    50  func (c *twoCommitCircuit) Define(api frontend.API) error {
    51  	res := api.Mul(c.A, c.B)
    52  	api.AssertIsEqual(res, c.Out)
    53  	cmter, ok := api.(frontend.Committer)
    54  	if !ok {
    55  		return fmt.Errorf("api does not support commitment")
    56  	}
    57  	cmt1, err := cmter.Commit(res)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	cmt2, err := cmter.Commit(cmt1)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	api.AssertIsDifferent(cmt1, cmt2)
    66  	return nil
    67  }
    68  
    69  func TestNoCommitment(t *testing.T) {
    70  	// should succeed both with G16 and PLONK:
    71  	assert := test.NewAssert(t)
    72  	circuit := &noCommitCircuit{}
    73  	assignment := &noCommitCircuit{A: 2, B: 3, Out: 6}
    74  	defaultOpts := []test.TestingOption{
    75  		test.WithCurves(ecc.BN254),
    76  		test.WithValidAssignment(assignment),
    77  	}
    78  	checkCircuit := func(assert *test.Assert, bid backend.ID) {
    79  		opts := append(defaultOpts,
    80  			test.WithBackends(bid),
    81  		)
    82  
    83  		assert.CheckCircuit(circuit, opts...)
    84  	}
    85  	assert.Run(func(assert *test.Assert) {
    86  		checkCircuit(assert, backend.GROTH16)
    87  	}, "Groth16")
    88  	assert.Run(func(assert *test.Assert) {
    89  		checkCircuit(assert, backend.PLONK)
    90  	}, "PLONK")
    91  }
    92  
    93  func TestSingleCommitment(t *testing.T) {
    94  	// should succeed both with G16 and PLONK:
    95  	// - But for G16 only if the hash-to-field is set to a supported one.
    96  	// - but for PLONK only if the hash-to-field is the default one. If not, then it should fail.
    97  	assert := test.NewAssert(t)
    98  	circuit := &commitCircuit{}
    99  	assignment := &commitCircuit{A: 2, B: 3, Out: 6}
   100  	defaultOpts := []test.TestingOption{
   101  		test.WithCurves(ecc.BN254),
   102  		test.WithValidAssignment(assignment),
   103  	}
   104  	checkCircuit := func(assert *test.Assert, bid backend.ID, newHash func() hash.Hash) {
   105  		opts := append(defaultOpts,
   106  			test.WithBackends(bid),
   107  			test.WithProverOpts(
   108  				backend.WithProverHashToFieldFunction(newHash()),
   109  			),
   110  			test.WithVerifierOpts(
   111  				backend.WithVerifierHashToFieldFunction(newHash()),
   112  			),
   113  			test.WithSolidityExportOptions(solidity.WithHashToFieldFunction(newHash())),
   114  		)
   115  
   116  		assert.CheckCircuit(circuit, opts...)
   117  	}
   118  	// G16 success with explicitly set options
   119  	assert.Run(func(assert *test.Assert) {
   120  		checkCircuit(assert, backend.GROTH16, sha256.New)
   121  	}, "groth16", "sha256")
   122  	assert.Run(func(assert *test.Assert) {
   123  		checkCircuit(assert, backend.GROTH16, sha3.NewLegacyKeccak256)
   124  	}, "groth16", "keccak256")
   125  	// G16 success with using TargetSolidityVerifier
   126  	assert.Run(func(assert *test.Assert) {
   127  		opts := append(defaultOpts,
   128  			test.WithBackends(backend.GROTH16),
   129  			test.WithProverOpts(
   130  				solidity.WithProverTargetSolidityVerifier(backend.GROTH16),
   131  			),
   132  			test.WithVerifierOpts(
   133  				solidity.WithVerifierTargetSolidityVerifier(backend.GROTH16),
   134  			),
   135  		)
   136  		assert.CheckCircuit(circuit, opts...)
   137  	}, "groth16", "targetSolidityVerifier")
   138  	// G16 success without any options because we set default options already in
   139  	// assert.CheckCircuit if they are not set.
   140  	assert.Run(func(assert *test.Assert) {
   141  		opts := append(defaultOpts,
   142  			test.WithBackends(backend.GROTH16),
   143  		)
   144  		assert.CheckCircuit(circuit, opts...)
   145  	}, "groth16", "no-options")
   146  
   147  	// PLONK success with default options
   148  	assert.Run(func(assert *test.Assert) {
   149  		opts := append(defaultOpts,
   150  			test.WithBackends(backend.PLONK),
   151  		)
   152  		assert.CheckCircuit(circuit, opts...)
   153  	}, "plonk", "default")
   154  	// PLONK success with using TargetSolidityVerifier
   155  	assert.Run(func(assert *test.Assert) {
   156  		opts := append(defaultOpts,
   157  			test.WithBackends(backend.PLONK),
   158  			test.WithProverOpts(
   159  				solidity.WithProverTargetSolidityVerifier(backend.PLONK),
   160  			),
   161  			test.WithVerifierOpts(
   162  				solidity.WithVerifierTargetSolidityVerifier(backend.PLONK),
   163  			),
   164  		)
   165  		assert.CheckCircuit(circuit, opts...)
   166  	}, "plonk", "targetSolidityVerifier")
   167  }
   168  
   169  func TestTwoCommitments(t *testing.T) {
   170  	// should succeed with PLONK only.
   171  	// - but for PLONK only if the hash-to-field is the default one. If not, then it should fail.
   172  	assert := test.NewAssert(t)
   173  	circuit := &twoCommitCircuit{}
   174  	assignment := &twoCommitCircuit{A: 2, B: 3, Out: 6}
   175  	assert.CheckCircuit(circuit, test.WithCurves(ecc.BN254), test.WithValidAssignment(assignment), test.WithBackends(backend.PLONK))
   176  }