diff --git a/internal/backend/circuits/crumb.go b/internal/backend/circuits/crumb.go new file mode 100644 index 0000000000..25c0f18f85 --- /dev/null +++ b/internal/backend/circuits/crumb.go @@ -0,0 +1,31 @@ +package circuits + +import ( + "github.com/consensys/gnark/frontend" + "golang.org/x/exp/rand" +) + +type isCrumbCircuit struct { + C []frontend.Variable +} + +func (circuit *isCrumbCircuit) Define(api frontend.API) error { + for _, x := range circuit.C { + api.AssertIsCrumb(x) + } + return nil +} + +func init() { + c := []frontend.Variable{0, 1, 2, 3} + good := []frontend.Circuit{ + &isCrumbCircuit{C: c}, + } + addNewEntry("isCrumb/case=good", &isCrumbCircuit{C: make([]frontend.Variable, len(c))}, good, nil, nil) + var bad []frontend.Circuit + for n := 0; n < 20; n++ { + x := rand.Intn(65531) + 4 //#nosec G404 weak rng OK for test + bad = append(bad, &isCrumbCircuit{C: []frontend.Variable{x}}) + } + addNewEntry("isCrumb/case=bad", &isCrumbCircuit{C: []frontend.Variable{nil}}, nil, bad, nil) +} diff --git a/test/api_assertions_test.go b/test/api_assertions_test.go deleted file mode 100644 index f53e2e2f25..0000000000 --- a/test/api_assertions_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package test - -import ( - "github.com/consensys/gnark/frontend" - "math/rand" - "testing" -) - -func TestIsCrumb(t *testing.T) { - c := []frontend.Variable{0, 1, 2, 3} - assert := NewAssert(t) - assert.SolvingSucceeded(&isCrumbCircuit{C: make([]frontend.Variable, len(c))}, &isCrumbCircuit{C: c}) - for n := 0; n < 20; n++ { - x := rand.Intn(65531) + 4 //#nosec G404 weak rng OK for test - assert.SolvingFailed(&isCrumbCircuit{C: []frontend.Variable{nil}}, &isCrumbCircuit{C: []frontend.Variable{x}}) - } -} - -type isCrumbCircuit struct { - C []frontend.Variable -} - -func (circuit *isCrumbCircuit) Define(api frontend.API) error { - for _, x := range circuit.C { - api.AssertIsCrumb(x) - } - return nil -} diff --git a/test/quick.go b/test/quick.go new file mode 100644 index 0000000000..457245404f --- /dev/null +++ b/test/quick.go @@ -0,0 +1,50 @@ +package test + +import ( + "crypto/rand" + "encoding/binary" + "errors" + "github.com/consensys/gnark/frontend" + "github.com/stretchr/testify/require" + "sync" + "testing" +) + +var snarkFunctionStore sync.Map + +type snarkFunctionTestCircuit struct { + funcId uint64 // this workaround is necessary because deepEquals fails on objects with function fields + DummyInput frontend.Variable // to keep the Plonk backend from crashing +} + +func (c *snarkFunctionTestCircuit) Define(api frontend.API) error { + + f, ok := snarkFunctionStore.Load(c.funcId) + if !ok { + return errors.New("function not found") + } + + F, ok := f.(func(frontend.API) error) + if !ok { + panic("unexpected entry type") + } + + return F(api) +} + +// Function returns a test function that can run a simple circuit consisting of function f +func Function(f func(frontend.API) error, opts ...TestingOption) func(*testing.T) { + return func(t *testing.T) { + var ( + c snarkFunctionTestCircuit + b [8]byte + ) + _, err := rand.Read(b[:]) + require.NoError(t, err) + c.funcId = binary.BigEndian.Uint64(b[:]) + snarkFunctionStore.Store(c.funcId, f) + + NewAssert(t).SolvingSucceeded(&c, &snarkFunctionTestCircuit{DummyInput: 0}, opts...) + snarkFunctionStore.Delete(c.funcId) + } +}