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

Return values in Prover.toml should not be supplied by the prover #624

Closed
2 tasks
kevaundray opened this issue Jan 10, 2023 · 13 comments
Closed
2 tasks

Return values in Prover.toml should not be supplied by the prover #624

kevaundray opened this issue Jan 10, 2023 · 13 comments
Labels
bug Something isn't working

Comments

@kevaundray
Copy link
Contributor

Description

Currently we allow return values to be supplied by the prover. This can only be done if the prover runs through the program and generates those values, which is unlikely.

Aim

If the prover wants to pass in values, they should just pass them into main as an argument and not via the return ="" field.

Expected behavior

When return ="" is prefilled in for the prover when creating proofs, we should issue an error.

Bug

(Describe the bug. Supplement error codes / terminal logs if applicable.)

To reproduce

(Describe the steps to reproduce the behavior.)

Environment

(Specify your setup and versions of dependencies.)

  • OS:

For nargo users

  • noir-lang/noir commit cloned:
  • Proving backend
    • default
      • Clang: (run clang --version)
    • wasm-base

For TypeScript users

  • Node.js: (run node --version)
  • @noir-lang/noir_wasm: (from yarn.lock)
  • @noir-lang/barretenberg: (from yarn.lock)
  • @noir-lang/aztec_backend: (from yarn.lock)

Additional context

(If applicable.)

@kevaundray kevaundray added the bug Something isn't working label Jan 10, 2023
@jfecher
Copy link
Contributor

jfecher commented Jan 10, 2023

This can only be done if the prover runs through the program and generates those values, which is unlikely.

Why is this unlikely? You cannot refer to a value returned from main before it is actually returned so I see no reason why we cannot generate these automatically. Can you give a problematic example?

@kevaundray
Copy link
Contributor Author

Because the semantics of return is that it is what is returned "after" you have executed the main function.

It seems like we agree though, I am saying that they can be generated automatically by the compiler, but it is unlikely that the prover/developer will put the values in manually by themselves.

ie the usecase of return =5 is less likely than the usecase return ="" and it gets populated automatically.

If the user wants to add the values manually then they can just provide the value as an input and make it public.

@TomAFrench
Copy link
Member

TomAFrench commented Jan 11, 2023

I think there's value in being able to fail early in the situation where you have additional context about what the return value of a circuit should be and want to enforce this at proving time. Otherwise the prover would have to immediately verify their proof using their expected return value which adds a bunch of overhead.

There will definitely exist buggy circuits which make it to production so the earlier these can be flagged up the better.

@kevaundray
Copy link
Contributor Author

I think there's value in being able to fail early in the situation where you have additional context about what the return value of a circuit should be and want to enforce this at proving time. Otherwise the prover would have to immediately verify their proof using their expected return value which adds a bunch of overhead.

There will definitely exist buggy circuits which make it to production so the earlier these can be flagged up the better.

They could provide the value as input in that case no? Though I think this argument also falls under the camp of "we need better testing infrastructure" for circuits

@TomAFrench
Copy link
Member

They could provide the value as input in that case no?

This assumes that they can change the circuit they're using from a "return as return value" to a "return as public input" model. If you're proving a circuit written by someone else then you may not be able to do this.

@TomAFrench
Copy link
Member

Note this doesn't have to happen inside the solving of the circuit. It would also be acceptable if the generated return value could be extracted from the witness and compared against the expected return value.

@kevaundray
Copy link
Contributor Author

Note this doesn't have to happen inside the solving of the circuit. It would also be acceptable if the generated return value could be extracted from the witness and compared against the expected return value.

This makes sense, though I still think it falls under the testing infrastructure umbrella and regular usage would probably not warrant this behaviour

@guipublic
Copy link
Contributor

I disagree, testing infrastructure umbrella falls into this case (providing the return value), but this case does not always falls into the infrastructure umbrella.

@guipublic
Copy link
Contributor

I also disagree with the goal of the issue:

If the prover wants to pass in values, they should just pass them into main as an argument and not via the return ="" field.

To do that prover needs to add inputs and manually constraint the result to the inputs, which with the setpub optimisation is now less efficient that using the return="value"
So we are going to have something which is less convenient and less performant.

@kevaundray
Copy link
Contributor Author

ally constraint the result to the inpu

  • If a part of your circuit logic requires you to constrain the return value to be equal some prover provided value, then you should pass it in as input and clearly specify what that input is, for example expected_nullifier

  • How is it less performant?

@guipublic
Copy link
Contributor

How is it less performant?

Because it requires some constraint: constrain result == my_expected_result
More public witness and more constraint(s), so it is less performant.

@kevaundray
Copy link
Contributor Author

How is it less performant?

Because it requires some constraint: constrain result == my_expected_result More public witness and more constraint(s), so it is less performant.

This was also the case before, you needed a constraint to constrain the result input to the return value. There are not more public inputs in this case, expected_results doesn't need to be public since the return value is public.

Though as noted, I do not see a usecase for this, except for testing infrastructure. Note that without Noir, the way to check that a public value is equal to something is via the verifier passing in the same value. You don't need to apply an explicit constraint in the circuit.

@TomAFrench
Copy link
Member

Closed by #731

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants