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 }