runtimeverification / runtimeverification/evm-semantics

Unexpected behaviour in proving `sum-to-n-foundry-spec.k`

Open
#2,617 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
KCL
Stars
591
Forks
156
Avg merge
2h 19m
Merged PRs (30d)
1

Description

The sum-to-n-foundry-spec.k file contains a circular proof of the usual sum of the first n integers. Currently, at the critical point, the branching that happens is unexpected to me and appears to require a lemma that I don't think should be required. I believe that Kore incorrectly returns a result that can then be interpreted as a split instead of a non-deterministic branch. The lemma in question is:

rule [rangeBool-not-zero-l]: notBool (X ==Int 0) => X ==Int 1 requires #rangeBool(X) [simplification]

The most important parts of the claim are the K cell and the word stack, and they are as expected:

<k>
  (JUMPI 1569 bool2Word(N:Int ==Int 0) ~> #pc [ JUMPI ] => .K)
  ~> #execute
  ...
</k>

<wordStack>
    (S => (S +Int ((N *Int (N +Int 1)) divInt 2)))
  : 0
  : (N => 0)
  : 334
  : 2123244496
  : .WordStack
</wordStack>

and the path condition is

{ true #Equals 0 <Int N:Int }
{ true #Equals 0 <=Int N:Int }
{ true #Equals 0 <=Int S:Int }
{ true #Equals N:Int <Int pow256 }
{ true #Equals S:Int <Int pow256 }
{ true #Equals ( 178 *Int N:Int ) <=Int GAS_AMT:Int }
{ true #Equals ( S:Int +Int ( ( ( N:Int *Int ( N:Int +Int 1 ) ) -Int ( ( N:Int *Int ( N:Int +Int 1 ) ) modInt 2 ) ) /Int 2 ) ) <Int pow256 } ) ) ) ) ) ) )

Now, the critical node in the proof is node 18, whose K cell and word stack are

<k>
  JUMPI 1569 bool2Word ( N:Int ==Int 1 )
  ~> #pc [ JUMPI ]
  ~> #execute
  ~> K_CELL_de090c3b:K
</k>

<wordStack>
  ( ( S:Int +Int N:Int ) : ( 0 : ( ( N:Int +Int -1 ) : ( 334 : ( 2123244496 : .WordStack ) ) ) ) )
</wordStack>

and whose path condition is the same as above. Without the lemma above, the execution branches into the following split:

┃ (branch)
┣━━┓ subst: .Subst
┃  ┃ constraint:
┃  ┃     ( ( S:Int +Int N:Int ) +Int ( ( ( ( N:Int +Int -1 ) *Int N:Int ) -Int ( ( ...
┃  ┃     ( S:Int +Int N:Int ) <Int pow256
┃  ┃     1 <Int N:Int
┃  ┃     N:Int <Int 115792089237316195423570985008687907853269984665640564039457584...
┃  ┃     ( 178 *Int ( N:Int +Int -1 ) ) <=Int ( GAS_AMT:Int +Int -178 )
┃  ┃     1 <=Int N:Int
┃  │
┃  └─ 19 (leaf, pending)
┃      k: JUMPI 1569 bool2Word ( N:Int ==Int 1 ) ~> #pc [ JUMPI ] ~> #execute ~> K_CELL_de ...
┃      pc: 1539
┃      callDepth: CALLDEPTH_CELL:Int
┃      statusCode: STATUSCODE_CELL:StatusCode
┃
┗━━┓ subst: .Subst
   ┃ constraint:
   ┃     notBool ( N:Int ==Int 0 )
   │
   └─ 20 (leaf, pending)
       k: JUMPI 1569 bool2Word ( N:Int ==Int 1 ) ~> #pc [ JUMPI ] ~> #execute ~> K_CELL_de ...
       pc: 1539
       callDepth: CALLDEPTH_CELL:Int
       statusCode: STATUSCODE_CELL:StatusCode

and since the second branch carries no additional information, the execution keeps branching infinitely. This appears to be a remainder branch of some kind, but the backend returns a non-empty rule predicate for every next state.

With the lemma above in place, Kore somehow uses it to make the split condition of node 20 become N ==Int 1. I have looked at all possible logs and I do not understand how.

As part of one of the latest PRs, I have added that lemma locally to that file so that it could pass, but I think that we should not have that lemma anywhere and that have a bug either in the backend reasoning or in the results returned by the backend or in how we interpret these results.

I am attaching the failing (without the lemma) and successful (with the lemma) bug reports for inspection by the backend team (@geo2a @goodlyrottenapple @jberthold).

succ.tar.gz
fail.tar.gz

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with tests/specs/examples/sum-to-n-foundry-spec.k and reproduce the failing report without the lemma, then compare it with succ.tar.gz. Read the referenced pyk/kcfg/explore.py predicate handling and inspect the attached backend logs to determine whether Kore returns an incorrect result or the result is interpreted incorrectly; done means the infinite branching is explained and the underlying bug is fixed.

Written by the indexing model from the issue text.

Assessment

Domain
backend, compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.