Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max limit on big.Int input to circuit? #204

Closed
vck3000 opened this issue Dec 16, 2021 · 8 comments
Closed

Max limit on big.Int input to circuit? #204

vck3000 opened this issue Dec 16, 2021 · 8 comments

Comments

@vck3000
Copy link

vck3000 commented Dec 16, 2021

Hi there,

I'm doing some work with large inputs, and seem to have bumped into a limit on the input size.

I can't seem to pass in inputs larger than 32 bytes through the circuit witness and get it to show up correctly.

Minimal reproducible code:

type Circuit struct {
	Input frontend.Variable
}

func (c *Circuit) Define(curveID ecc.ID, api frontend.API) error {
	api.Println("After:")
	api.Println(c.Input)

	api.AssertIsEqual(c.Input, 0)

	return nil
}

func main() {
	var circuit Circuit
	r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &circuit)

	if err != nil {
		panic(err)
	}

	pk, _, _ := groth16.Setup(r1cs)

	largeInput := []byte{}
	// OK at 32
	// Not OK at 33
	for i := 0; i < 33; i++ {
		largeInput = append(largeInput, 1)
	}

	b := big.Int{}
	b.SetBytes(largeInput)

	var witness Circuit
	witness.Input.Assign(b)

	fmt.Println("Before:")
	fmt.Println(b.String())

	_, _ = groth16.Prove(r1cs, pk, &witness)
}

Output with 33 bytes:

Before:
116246175861776258935035969263623938864459278723152879976867221592257887011073
main.go:62 After:
main.go:63 6804961502579882823803940537337563421717456721072708258376200659378844532988

Output with 32 bytes:

Before:
454086624460063511464984254936031011189294057512315937409637584344757371137
main.go:62 After:
main.go:63 454086624460063511464984254936031011189294057512315937409637584344757371137

Any ideas on how I can get around this limit?

@ivokub
Copy link
Collaborator

ivokub commented Dec 16, 2021

Thanks @vck3000 for the feedback.

This is currently a limitation in gnark -- all arithmetic is done on the scalars of the underlying elliptic curve group. If a value is larger than the modulus of the scalars, then it will be reduced by the modulus.

We are quite aware of this and the solution would be to implement integer arithmetic on top of the scalar field. I can not right now give you specific timeline when it will happen. But it will probably happen in mid-/long-term future as we develop the standard gadget library.

@vck3000
Copy link
Author

vck3000 commented Dec 16, 2021

Cool, no worries. I will try to get around this by splitting my input into 32 byte chunks and passing them in.

@ZhAnGeek
Copy link

Hi how do you splitting your input? I got error

@ivokub
Copy link
Collaborator

ivokub commented Jun 27, 2022

Hi how do you splitting your input? I got error

@ZhAnGeek, can you provide example code and error?

@ZhAnGeek
Copy link

ZhAnGeek commented Jun 28, 2022

@ZhAnGeek, can you provide example code and error?

thanks, actually I and writing []frontend.Variable in a Circuit, and I found out that the length of this array should be fixed, and the amount of it is examined while frontend has compiled.

circuit.PK = make([]frontend.Variable, 5)
circuit.R = make([]frontend.Variable, 2)
circuit.S = make([]frontend.Variable, 2)
circuit.MSG = make([]frontend.Variable, 2)

_scs, err := frontend.Compile(ecc.BN254, scs.NewBuilder, &circuit, frontend.IgnoreUnconstrainedInputs())

can such array being not fixed long, for example I need the MSG to be expanded? thx.

@ivokub
Copy link
Collaborator

ivokub commented Jun 28, 2022

@ZhAnGeek, can you provide example code and error?

thanks, actually I and writing []frontend.Variable in a Circuit, and I found out that the length of this array should be fixed, and the amount of it is examined while frontend has compiled.

circuit.PK = make([]frontend.Variable, 5)
circuit.R = make([]frontend.Variable, 2)
circuit.S = make([]frontend.Variable, 2)
circuit.MSG = make([]frontend.Variable, 2)

_scs, err := frontend.Compile(ecc.BN254, scs.NewBuilder, &circuit, frontend.IgnoreUnconstrainedInputs())

can such array being not fixed long, for example I need the MSG to be expanded? thx.

The circuits are fixed after compiling, meaning that the all variables, coefficients, constants etc. are embedded in the circuit. It won't be possible to add variables (comparable to increasing the slices) in-circuit. Most notably, it won't be possible to write loops where the bounding condition is a variable (i.e. the number of iterations in a loop varies depending on the variable value).

Anyway, I think that your question is unrelated to the current issue. Maybe you can start a new discussion at https://github.com/ConsenSys/gnark/discussions and quote me? Please post your full working example including the circuit definition.

@vck3000
Copy link
Author

vck3000 commented Jun 30, 2022

Hi @ZhAnGeek,

I did something like the following:

type Circuit struct {
	Input0  frontend.Variable `gnark:",public"`
	Input1  frontend.Variable `gnark:",public"`
	Input2  frontend.Variable `gnark:",public"`
	Input3  frontend.Variable `gnark:",public"`
	Output0 frontend.Variable `gnark:",public"`
	Output1 frontend.Variable `gnark:",public"`
	Output2 frontend.Variable `gnark:",public"`
	Output3 frontend.Variable `gnark:",public"`
}

To test:

	t.Run("Medium sanitize across 32 byte boundary", func(t *testing.T) {
		testHelper.TestSingleCurve(t, &Circuit{}, &Circuit{
			Input0:  frontend.Value([]byte("abcdefghijklmnopqrstuvwxyzabc<s")),
			Input1:  frontend.Value([]byte("cript>asdf</script>defgh")),
			Input2:  frontend.Value([]byte{}),
			Input3:  frontend.Value([]byte{}),
			Output0: frontend.Value([]byte("abcdefghijklmnopqrstuvwxyzabcde")),
			Output1: frontend.Value([]byte("fgh")),
			Output2: frontend.Value([]byte{}),
			Output3: frontend.Value([]byte{}),
		})
	})

At the end of the day, the circuit is still compile-time deterministic.

@ivokub
Copy link
Collaborator

ivokub commented Jul 15, 2022

See non-native arithmetic gadget in std/math/nonnative for working in arbitrary fields (PR #325).

@ivokub ivokub closed this as completed Jul 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants