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

Enable generating KEVM claims from the basic blocks of Kontrol KCFGs #262

Merged
merged 23 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d019df6
kontrol/{foundry,__main__}: add option to generate a list of KEVM cla…
ehildenb Dec 21, 2023
3ce5699
kontrol/{foundry,__main__}: add option for where to generate KEVM cla…
ehildenb Dec 22, 2023
d925cf1
kontrol/foundry: avoid duplicate hyphens in module name
ehildenb Dec 22, 2023
74d41db
kontrol/foundry: better filtering of claims that wont work in KEVM
ehildenb Dec 23, 2023
e07c96c
kontrol/foundry: only include edge basic blocks, not ndbranches
ehildenb Dec 23, 2023
a2fed40
kontrol/foundry: correction to how we exclude foundry claims
ehildenb Dec 23, 2023
81af5b8
kontrol/foundry: do not duplicate source/target id in claim name
ehildenb Dec 24, 2023
a3389bd
kontrol/foundry: also filter out rules with call_foundry helper
ehildenb Dec 24, 2023
e450348
kontrol/foundry: filter out claims with terminal LHS too
ehildenb Dec 24, 2023
e49e606
kontrol/foundry: no commas in module names
ehildenb Dec 25, 2023
6885e71
kontrol/foundry: limit more foundry-specific klabels from being print…
ehildenb Dec 25, 2023
db6e9ed
kontrol/foundry: allow for empty claims by not generating the file
ehildenb Dec 25, 2023
9607e5b
Set Version: 0.1.105
Jan 9, 2024
632f09f
poetry.lock: update
ehildenb Jan 9, 2024
b26f976
Merge remote-tracking branch 'upstream/master' into kevm-claims
ehildenb Jan 11, 2024
b619030
Set Version: 0.1.109
Jan 11, 2024
20f106a
Merge branch 'master' into kevm-claims
ehildenb Jan 12, 2024
59d657d
Set Version: 0.1.112
Jan 12, 2024
920940e
Merge remote-tracking branch 'upstream/master' into kevm-claims
ehildenb Jan 15, 2024
05ee221
kontrol/foundry.py: simpler way to calculate new module name
ehildenb Jan 15, 2024
fedbf4a
kontrol/foundry: get list of productions to exclude from KEVM claims …
ehildenb Jan 15, 2024
0b59658
Set Version: 0.1.114
Jan 15, 2024
1b3569a
kontrol/foundry: grab klabel of productions, not sentence label
ehildenb Jan 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.113
0.1.114
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "kontrol"
version = "0.1.113"
version = "0.1.114"
description = "Foundry integration for KEVM"
authors = [
"Runtime Verification, Inc. <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion src/kontrol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
if TYPE_CHECKING:
from typing import Final

VERSION: Final = '0.1.113'
VERSION: Final = '0.1.114'
18 changes: 18 additions & 0 deletions src/kontrol/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from pyk.kbuild.utils import KVersion, k_version
from pyk.proof.reachability import APRProof
from pyk.proof.tui import APRProofViewer
from pyk.utils import ensure_dir_path

from . import VERSION
from .cli import KontrolCLIArgs
Expand Down Expand Up @@ -310,6 +311,8 @@ def exec_show(
nodes: Iterable[NodeIdLike] = (),
node_deltas: Iterable[tuple[NodeIdLike, NodeIdLike]] = (),
to_module: bool = False,
to_kevm_claims: bool = False,
kevm_claim_dir: Path | None = None,
minimize: bool = True,
sort_collections: bool = False,
omit_unstable_output: bool = False,
Expand All @@ -328,6 +331,8 @@ def exec_show(
nodes=nodes,
node_deltas=node_deltas,
to_module=to_module,
to_kevm_claims=to_kevm_claims,
kevm_claim_dir=kevm_claim_dir,
minimize=minimize,
omit_unstable_output=omit_unstable_output,
sort_collections=sort_collections,
Expand Down Expand Up @@ -762,6 +767,19 @@ def _parse_test_version_tuple(value: str) -> tuple[str, int | None]:
action='store_true',
help='Strip output that is likely to change without the contract logic changing',
)
show_args.add_argument(
'--to-kevm-claims',
dest='to_kevm_claims',
default=False,
action='store_true',
help='Generate a K module which can be run directly as KEVM claims for the given KCFG (best-effort).',
)
show_args.add_argument(
'--kevm-claim-dir',
dest='kevm_claim_dir',
type=ensure_dir_path,
help='Path to write KEVM claim files at.',
)

command_parser.add_parser(
'to-dot',
Expand Down
70 changes: 66 additions & 4 deletions src/kontrol/foundry.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import tomlkit
from kevm_pyk.kevm import KEVM, KEVMNodePrinter, KEVMSemantics
from kevm_pyk.utils import byte_offset_to_lines, legacy_explore, print_failure_info, print_model
from pyk.kast.inner import KApply, KSort, KToken
from pyk.kast.manip import minimize_term
from pyk.cterm import CTerm
from pyk.kast.inner import KApply, KSort, KToken, KVariable
from pyk.kast.manip import collect, extract_lhs, minimize_term
from pyk.kast.outer import KDefinition, KFlatModule, KImport, KRequire
from pyk.kcfg import KCFG
from pyk.prelude.bytes import bytesToken
from pyk.prelude.kbool import notBool
Expand All @@ -32,7 +34,6 @@
from collections.abc import Iterable
from typing import Any, Final

from pyk.cterm import CTerm
from pyk.kast.inner import KInner
from pyk.kcfg.kcfg import NodeIdLike
from pyk.kcfg.tui import KCFGElem
Expand Down Expand Up @@ -491,6 +492,8 @@ def foundry_show(
nodes: Iterable[NodeIdLike] = (),
node_deltas: Iterable[tuple[NodeIdLike, NodeIdLike]] = (),
to_module: bool = False,
to_kevm_claims: bool = False,
kevm_claim_dir: Path | None = None,
minimize: bool = True,
sort_collections: bool = False,
omit_unstable_output: bool = False,
Expand Down Expand Up @@ -550,7 +553,66 @@ def foundry_show(
res_lines += print_failure_info(proof, kcfg_explore, counterexample_info)
res_lines += Foundry.help_info()

return '\n'.join(res_lines)
if to_kevm_claims:
_foundry_labels = [
prod.klabel
for prod in foundry.kevm.definition.all_modules_dict['FOUNDRY-CHEAT-CODES'].productions
if prod.klabel is not None
]

def _remove_foundry_config(_cterm: CTerm) -> CTerm:
kevm_config_pattern = KApply(
'<generatedTop>',
[
KApply('<foundry>', [KVariable('KEVM_CELL'), KVariable('CHEATCODES_CELL')]),
KVariable('GENERATEDCOUNTER_CELL'),
],
)
kevm_config_match = kevm_config_pattern.match(_cterm.config)
if kevm_config_match is None:
_LOGGER.warning('Unable to match on <kevm> cell.')
return _cterm
return CTerm(kevm_config_match['KEVM_CELL'], _cterm.constraints)

def _contains_foundry_klabel(_kast: KInner) -> bool:
_contains = False

def _collect_klabel(_k: KInner) -> None:
nonlocal _contains
if type(_k) is KApply and _k.label.name in _foundry_labels:
_contains = True

collect(_collect_klabel, _kast)
return _contains

for node in proof.kcfg.nodes:
proof.kcfg.replace_node(node.id, _remove_foundry_config(node.cterm))

# Due to bug in KCFG.replace_node: https://github.com/runtimeverification/pyk/issues/686
proof.kcfg = KCFG.from_dict(proof.kcfg.to_dict())

claims = [edge.to_rule('BASIC-BLOCK', claim=True) for edge in proof.kcfg.edges()]
claims = [claim for claim in claims if not _contains_foundry_klabel(claim.body)]
claims = [
claim for claim in claims if not KEVMSemantics().is_terminal(CTerm.from_kast(extract_lhs(claim.body)))
]
if len(claims) == 0:
_LOGGER.warning(f'No claims retained for proof {proof.id}')

else:
module_name = re.sub(r'[%().:,]+', '-', proof.id.upper()) + '-SPEC'
module = KFlatModule(module_name, sentences=claims, imports=[KImport('VERIFICATION')])
defn = KDefinition(module_name, [module], requires=[KRequire('verification.k')])

defn_lines = foundry.kevm.pretty_print(defn, in_module='EVM').split('\n')

res_lines += defn_lines

if kevm_claim_dir is not None:
kevm_claims_file = kevm_claim_dir / (module_name.lower() + '.k')
kevm_claims_file.write_text('\n'.join(line.rstrip() for line in defn_lines))

return '\n'.join([line.rstrip() for line in res_lines])


def foundry_to_dot(foundry: Foundry, test: str, version: int | None = None) -> None:
Expand Down