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

Research: explicit SMT assertions for non-linear arithmetic #247

Open
karmacoma-eth opened this issue Jan 10, 2024 · 0 comments
Open

Research: explicit SMT assertions for non-linear arithmetic #247

karmacoma-eth opened this issue Jan 10, 2024 · 0 comments
Labels
enhancement New feature or request help wanted Extra attention is needed research question

Comments

@karmacoma-eth
Copy link
Collaborator

karmacoma-eth commented Jan 10, 2024

Problem

Non-linear arithmetic on bitvectors is very expensive for SMT solvers. Simple queries take a very long time to complete, for instance:

from z3 import *

x = BitVec('x', 256)
y = BitVec('y', 256)

# takes 7s to return [y = 0, x = 1]
solve(Not(ULT(UDiv(x, y), x)))

# takes 1m30s to return unsat (no solution)
solve(ULT(x, y), UDiv(x, y) > 0)

As a result, the equivalent tests in halmos also take a long time:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

contract DivisionIsHard {
    /// @notice we expect a counterexample [y = 0, x = 1]
    function check_divRoundsDown(uint256 x, uint256 y) external {
        assert(x / y < x);
    }

    /// @notice we expect unsat (no counterexample)
    function check_divRoundsToZero(uint256 x, uint256 y) external {
        require(x < y);
        assert(x / y == 0);
    }
}

(run with halmos --solver-timeout-assertion 0 --statistics)

Let's break down how halmos processes check_divRoundsDown:

  • halmos starts with an uninterpreted function (evm_bvudiv) to avoid the cost of bitvector division
  • halmos finds a path that could trigger the assertion violation, asks the solver for a model
  • the solver returns an invalid model since it contains evm_bvudiv (i.e. it doesn't know that we're asking about the actual division operation)
  • halmos refines the query (aka replaces the UF evm_bvudiv with the real bvudiv operator) and asks the solver again
  • the solver returns a valid counterexample (x = 0, y = 1), but takes a while to do so

Proposed solution

This test is simple enough that it can be solved without refinement, i.e. no need to do any actual bitvector division.

We could explicitly tell the solver some properties of evm_bvudiv that are sufficient to return a counterexample:

    def mk_div(self, ex: Exec, x: Any, y: Any) -> Any:
        term = f_div(x, y)
        ex.path.append(ULE(term, x))  # (x / y) <= x

        # y == 0 implies (x / y) == 0
        ex.path.append(Implies(y == con(0), term == con(0)))

        # y == 1 implies (x / y) == x
        ex.path.append(Implies(y == con(1), term == x))

        # y > 1 implies (x / y) < x
        ex.path.append(Implies(ULT(con(1), y), ULT(term, x)))

        # y > x implies (x / y) == 0
        ex.path.append(Implies(ULT(x, y), term == con(0)))

        return term

In this case, the key assertion is y == 1 implies (x / y) == x. With this, the test returns a valid result immediately and does not require refining the query.

Work to do

  • find interesting axioms to add (for div, mul, mod, sdiv, ...)
  • study the power of the added axioms (are we able to solve more tests?)
  • study the performance trade-off (are we solving real problems faster? is adding many assertions making the query too big?)
  • study the performance trade-off for a couple of solvers: the effect could be different on z3 vs boolector, cvc5, etc.
  • is it possible to do better than eagerly adding assertions for all operations?

Related

Hozzová, Petra, et al. "Overapproximation of Non-Linear Integer Arithmetic for Smart Contract Verification." Proceedings of 24th International Conference on Logic. Vol. 94. 2023.

@karmacoma-eth karmacoma-eth changed the title Research: explore performance benefits of adding explicit non-linear arithmetic axioms Research: explicit SMT assertions for non-linear arithmetic Jan 10, 2024
@daejunpark daejunpark added the help wanted Extra attention is needed label Mar 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed research question
Projects
None yet
Development

No branches or pull requests

2 participants