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

Potential Boogie limitation for simple assertions on contract and struct properties #457

Open
matteobilardi opened this issue Aug 15, 2019 · 1 comment
Labels

Comments

@matteobilardi
Copy link
Contributor

In both of these snippets, one would expect the assertion to be verified as the contract/struct property is set to zero upon initialisation and there are no declared methods that later modify such property.

contract Assert {
  var i: Int
}

Assert :: (any) {
  public init() {
    i = 0
  }

  public func failIfNotZero() {
    assert(self.i == 0)
  }
}

The Boogie translation for the previous code looks valid, however, the assertion cannot be verified by boogie. This is also the case for a similar struct:

struct Assert {
  var x: Int = 0

  public func failIfNotZero() {
    assert(self.x == 0)
  }
}

I initially speculated that the translation might be failing to keep track of initialisation, but that is certainly not the case for structs as the boogie translation explicitly requires that the struct instance on which a struct method is being called be among the ones which have been initialised so far. Thus, I fear that this might be either some boogie limitation or some unidentified conceptual issue with the current translation. In both cases, this issue needs further research.

@matteobilardi
Copy link
Contributor Author

Inability to keep track of initialisation in the Boogie translation

In a similar manner, the assertion in the following contract also fails.

contract Assert {
  var initialized: Bool = true
}

Assert :: (any) {
  public init() {}

  public func isInitialized() {
    assert(initialized)
  }
}

Currently, the Flint contract above gets translated for verification into the Boogie code below (once the Flint stdlib and all the checks on assets have been removed for clarity).

var initialized_Assert: bool;

procedure {:inline 10} init_Assert()
  modifies initialized_Assert;
{
    initialized_Assert := true;
}

procedure {:inline 10} isInitialized_Assert()
{
  assert (initialized_Assert);
}

However, such a translation fails to keep track of the fact that when the isInitialized method gets called on the singleton instance of the Assert contract, the init method must have already been called exactly once at some point in the past. The lack of this information causes the initialized contract property to assume any arbitrary value when isInitialized is called, thus, the assertion cannot be verified.

Even though I believe there should be a way to encode this information through the verifier language, with my current understanding of Boogie, I cannot think of a valid one: e.g. assigning an initial value to the initialized property in the global scope and immediately after declaration (initialized_Assert := false;) does not constitute valid Boogie code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants