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

CVC5 unable to reason about "power" function #49

Open
rod-chapman opened this issue Nov 29, 2024 · 5 comments
Open

CVC5 unable to reason about "power" function #49

rod-chapman opened this issue Nov 29, 2024 · 5 comments
Assignees

Comments

@rod-chapman
Copy link

Dear AdaCore,
I'm experimenting with verification of some cryptographic code (in this case the LibMLKEM library). We have found that CVC5 1.2.0 is very poor at reasoning about the "power" theory for integers, and we have to fall back on AltErgo to discharge those VCs.

BUT... we find that CVC5 has a built-in "int.pow2" operator, which it is able to reason with. If I remove the "power" theory from the SMT file, and change all instances of (power 2 i) to (int.pow2 i) then CVC5 proves my VCs almost instantly. Perhaps gnatprove could be changed to use "int.pow2" where possible when --prover=cvc5 is selected?

This is using GNATProve 14.1.0 on macOS.

I can send example SMT files if you'd like to see an example.

@HuStmpHrrr
Copy link

Just to add a bit more information: z3 also support exponential natively. I can see that the definition and the properties of power are generated to regulate the model of power to make sure the model meets what we expect. I do not think that's necessary anymore with modern z3 and cvc5.

@kanigsson
Copy link
Contributor

Hello Rod and Jason,

thanks for this investigation. I will bring this up with the Why3 team who is maintaining the prover drivers.

Johannes

@kanigsson kanigsson self-assigned this Dec 1, 2024
@clairedross
Copy link
Contributor

Hello,
Just to complement Johannes' answer, I wanted to add that even if some construct is supported in the underlying SMT solver, it does not mean that it is necessarily beneficial overall to use it. It generally depends how heavy the support is. More precisely, there are VCs where the construct occurs which would benefit from more precision, and others which do not need it, it is always like that. If the precise support is so heavy that it degrades the second kind of VCs too much, it can happen that it enabling this support is detrimental overall.
Best,

@rod-chapman
Copy link
Author

Here's an example.

power.smt2 is a VC generated by SPARK Pro (line 1499 of mlkem.adb in the LibMLKEM repo). CVC5 1.2.0 is completely defeated by this.

pow2.smt2 is the same file, but replacing "(power 2 " by "(int.pow2 " in 4 places. CVC5 says "unsat" in about 0.04 seconds on my laptop.

It would be interesting to try this change on your entire test suite and see what happens...
power.smt2.gz
pow2.smt2.gz

@HuStmpHrrr
Copy link

Hi Claire,

I agree with everything you said. I think the best thing to do is to have options to choose different generated VCs, and let the application layers to worry about which version is the best for them. The current generated power is most definitely unhelpful for CVC5 (probably less so for Z3), because it is defined through a sequence of assertions. A better alternative is to define recursive functions (define-fun-rec), if a custom power function is needed. In any case, I think CVC5 in general is benefited from using builtin Int.pow and Int.pow2.

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

4 participants