Skip to content

Commit f81aca1

Browse files
committed
Merge remote-tracking branch 'upstream/master' into foundry-fixes
2 parents 5d27737 + 25b7b21 commit f81aca1

File tree

12 files changed

+328
-51
lines changed

12 files changed

+328
-51
lines changed

include/kframework/abi.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ where `F1 : F2 : F3 : F4` is the (two's complement) byte-array representation of
325325
rule #enc( #int256( DATA )) => #bufStrict(32, #getValue( #int256( DATA )))
326326
rule #enc( #int128( DATA )) => #bufStrict(32, #getValue( #int128( DATA )))
327327
328-
rule #enc( #bytes4( DATA )) => #bufStrict(32, #getValue( #bytes4( DATA )))
328+
rule #enc( #bytes4( DATA )) => #padRightToWidth(32, #bufStrict(4, #getValue(#bytes4( DATA ))))
329329
rule #enc(#bytes32( DATA )) => #bufStrict(32, #getValue(#bytes32( DATA )))
330330
331331
rule #enc( #bool( DATA )) => #bufStrict(32, #getValue( #bool( DATA )))

include/kframework/evm-types.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,10 @@ The local memory of execution is a byte-array (instead of a word-array).
435435
syntax ByteArray ::= #padToWidth ( Int , ByteArray ) [function, total]
436436
| #padRightToWidth ( Int , ByteArray ) [function, total]
437437
// ---------------------------------------------------------------------------
438-
rule #padToWidth(N, BS) => BS requires notBool (N >=Int 0)
439-
rule [padToWidthNonEmpty] : #padToWidth(N, BS) => padLeftBytes(BS, N, 0) requires N >=Int 0
440-
rule #padRightToWidth(N, BS) => BS requires notBool (N >=Int 0)
441-
rule #padRightToWidth(N, BS) => padRightBytes(BS, N, 0) requires N >=Int 0
438+
rule #padToWidth(N, BS) => BS requires notBool (N >=Int 0)
439+
rule [padToWidthNonEmpty]: #padToWidth(N, BS) => padLeftBytes(BS, N, 0) requires N >=Int 0
440+
rule #padRightToWidth(N, BS) => BS requires notBool (N >=Int 0)
441+
rule [padRightToWidthNonEmpty]: #padRightToWidth(N, BS) => padRightBytes(BS, N, 0) requires N >=Int 0
442442
```
443443

444444
```{.k .nobytes}

include/kframework/lemmas/lemmas.k

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,11 @@ module LEMMAS [symbolic]
136136

137137
// sizeByteArray
138138

139-
rule #sizeByteArray(BUF1 ++ BUF2) => #sizeByteArray(BUF1) +Int #sizeByteArray(BUF2) [simplification]
140-
rule #sizeByteArray(#buf(SIZE, _)) => SIZE [simplification]
141-
rule #sizeByteArray(_MEM [ START .. WIDTH ]) => WIDTH requires 0 <=Int START andBool 0 <=Int WIDTH [simplification]
142-
rule #sizeByteArray(#range(_, START, WIDTH)) => WIDTH requires 0 <=Int START andBool 0 <=Int WIDTH [simplification]
139+
rule #sizeByteArray(BUF1 ++ BUF2) => #sizeByteArray(BUF1) +Int #sizeByteArray(BUF2) [simplification]
140+
rule #sizeByteArray(#buf(SIZE, _)) => SIZE [simplification]
141+
rule #sizeByteArray(_MEM [ START .. WIDTH ]) => WIDTH requires 0 <=Int START andBool 0 <=Int WIDTH [simplification]
142+
rule #sizeByteArray(#range(_, START, WIDTH)) => WIDTH requires 0 <=Int START andBool 0 <=Int WIDTH [simplification]
143+
rule #sizeByteArray(#padRightToWidth(WIDTH, BUF)) => WIDTH requires #sizeByteArray(BUF) <=Int WIDTH [simplification]
143144

144145
// TODO: custom ==K unification doesn't work in Haskell yet
145146
// ++ unification
@@ -149,6 +150,12 @@ module LEMMAS [symbolic]
149150

150151
rule #asWord(WS) >>Int M => #asWord(WS [ 0 .. #sizeByteArray(WS) -Int (M /Int 8) ]) requires 0 <=Int M andBool M modInt 8 ==Int 0 [simplification]
151152

153+
rule #asWord(#padRightToWidth(32, BUF)) &Int notMaxUInt224 =>
154+
#asWord(#padRightToWidth(32, BUF))
155+
requires #sizeByteArray(BUF) <=Int 4 [simplification]
156+
157+
rule #padRightToWidth(_, BUF)[ 0 .. WIDTH ] => BUF requires #sizeByteArray(BUF) ==Int WIDTH [simplification]
158+
152159
endmodule
153160

154161
module LEMMAS-JAVA [symbolic, kast]

kevm-pyk/src/kevm_pyk/__main__.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,32 @@
1414
from pyk.kcfg import KCFG
1515
from pyk.ktool.kit import KIT
1616
from pyk.ktool.krun import KRunOutput, _krun
17+
from pyk.prelude.k import GENERATED_TOP_CELL
1718
from pyk.prelude.ml import is_top, mlTop
1819

1920
from .gst_to_kore import gst_to_kore
2021
from .kevm import KEVM, Foundry
2122
from .solc_to_k import Contract, contract_to_main_module, method_to_cfg, solc_compile
22-
from .utils import KCFG__replace_node, KPrint_make_unparsing, KProve_prove_claim, add_include_arg, sanitize_config
23+
from .utils import (
24+
KCFG__replace_node,
25+
KDefinition__expand_macros,
26+
KPrint_make_unparsing,
27+
KProve_prove_claim,
28+
add_include_arg,
29+
sanitize_config,
30+
)
2331

2432
T = TypeVar('T')
2533

2634
_LOGGER: Final = logging.getLogger(__name__)
2735
_LOG_FORMAT: Final = '%(levelname)s %(asctime)s %(name)s - %(message)s'
2836

2937

38+
def write_cfg(_cfg: KCFG, _cfgpath: Path) -> None:
39+
_cfgpath.write_text(_cfg.to_json())
40+
_LOGGER.info(f'Updated CFG file: {_cfgpath}')
41+
42+
3043
def _ignore_arg(args: Dict[str, Any], arg: str, cli_option: str) -> None:
3144
if arg in args:
3245
if args[arg] is not None:
@@ -327,25 +340,21 @@ def exec_foundry_prove(
327340
contract_name, method_name = test.split('.')
328341
contract = [c for c in contracts if c.name == contract_name][0]
329342
method = [m for m in contract.methods if m.name == method_name][0]
330-
empty_config = foundry.definition.empty_config(Foundry.Sorts.FOUNDRY_CELL)
343+
empty_config = foundry.definition.empty_config(GENERATED_TOP_CELL)
331344
cfg = method_to_cfg(empty_config, contract, method)
345+
init_term = cfg.get_unique_init().cterm.kast
346+
target_term = cfg.get_unique_target().cterm.kast
347+
_LOGGER.info(f'Expanding macros in initial state for test: {test}')
348+
init_term = KDefinition__expand_macros(foundry.definition, init_term)
349+
_LOGGER.info(f'Expanding macros in target state for test: {test}')
350+
target_term = KDefinition__expand_macros(foundry.definition, target_term)
332351
if simplify_init:
333352
_LOGGER.info(f'Simplifying initial state for test: {test}')
334-
edge = KCFG.Edge(cfg.get_unique_init(), cfg.get_unique_target(), mlTop(), -1)
335-
claim = edge.to_claim()
336-
init_simplified = foundry.prove_claim(
337-
claim, f'simplify-init-{cfg.get_unique_init().id}', args=['--depth', '0']
338-
)
339-
init_simplified = sanitize_config(foundry.definition, init_simplified)
340-
cfg = KCFG__replace_node(cfg, cfg.get_unique_init().id, CTerm(init_simplified))
353+
init_term = foundry.simplify(CTerm(init_term))
341354
_LOGGER.info(f'Simplifying target state for test: {test}')
342-
edge = KCFG.Edge(cfg.get_unique_target(), cfg.get_unique_init(), mlTop(), -1)
343-
claim = edge.to_claim()
344-
target_simplified = foundry.prove_claim(
345-
claim, f'simplify-target-{cfg.get_unique_target().id}', args=['--depth', '0']
346-
)
347-
target_simplified = sanitize_config(foundry.definition, target_simplified)
348-
cfg = KCFG__replace_node(cfg, cfg.get_unique_target().id, CTerm(target_simplified))
355+
target_term = foundry.simplify(CTerm(target_term))
356+
cfg = KCFG__replace_node(cfg, cfg.get_unique_init().id, CTerm(init_term))
357+
cfg = KCFG__replace_node(cfg, cfg.get_unique_target().id, CTerm(target_term))
349358
kcfgs[test] = (cfg, kcfg_file)
350359
with open(kcfg_file, 'w') as kf:
351360
kf.write(json.dumps(cfg.to_dict()))
@@ -357,11 +366,6 @@ def exec_foundry_prove(
357366

358367
lemma_rules = [KRule(KToken(lr, 'K'), att=KAtt({'simplification': ''})) for lr in lemmas]
359368

360-
def _write_cfg(_cfg: KCFG, _cfgpath: Path) -> None:
361-
with open(_cfgpath, 'w') as cfgfile:
362-
cfgfile.write(json.dumps(_cfg.to_dict()))
363-
_LOGGER.info(f'Updated CFG file: {_cfgpath}')
364-
365369
def prove_it(_id_and_cfg: Tuple[str, Tuple[KCFG, Path]]) -> bool:
366370
_cfg_id, (_cfg, _cfg_path) = _id_and_cfg
367371
if len(_cfg.frontier) == 0:
@@ -387,11 +391,12 @@ def prove_it(_id_and_cfg: Tuple[str, Tuple[KCFG, Path]]) -> bool:
387391
if minimize:
388392
result_state = minimize_term(result_state)
389393
_LOGGER.error(f'Proof failed: {_cfg_id}\n{foundry.pretty_print(result_state)}')
390-
_write_cfg(_cfg, _cfg_path)
394+
write_cfg(_cfg, _cfg_path)
391395
failure_nodes = _cfg.frontier + _cfg.stuck
392396
return len(failure_nodes) == 0
393397

394398
with ProcessPool(ncpus=workers) as process_pool:
399+
foundry.close_kore_rpc()
395400
results = process_pool.map(prove_it, kcfgs.items())
396401
process_pool.close()
397402

kevm-pyk/src/kevm_pyk/kevm.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ def concrete_rules() -> List[str]:
161161
'EVM-TYPES.bytesRange',
162162
'EVM-TYPES.mapWriteBytes.recursive',
163163
'EVM-TYPES.#padRightToWidth',
164+
'EVM-TYPES.padRightToWidthNonEmpty',
164165
'EVM-TYPES.#padToWidth',
165166
'EVM-TYPES.padToWidthNonEmpty',
166167
'EVM-TYPES.powmod.nonzero',
@@ -191,7 +192,7 @@ def add_invariant(cterm: CTerm) -> CTerm:
191192
constraints.append(mlEqualsTrue(KEVM.range_address(get_cell(config, 'ID_CELL'))))
192193
constraints.append(mlEqualsTrue(KEVM.range_address(get_cell(config, 'CALLER_CELL'))))
193194
constraints.append(mlEqualsTrue(KEVM.range_address(get_cell(config, 'ORIGIN_CELL'))))
194-
constraints.append(mlEqualsTrue(ltInt(KEVM.size_bytearray(get_cell(config, 'CALLDATA_CELL')), KEVM.pow256())))
195+
constraints.append(mlEqualsTrue(ltInt(KEVM.size_bytearray(get_cell(config, 'CALLDATA_CELL')), KEVM.pow128())))
195196

196197
return CTerm(mlAnd([config] + list(unique(constraints))))
197198

@@ -219,6 +220,10 @@ def jumpi_applied(pc: KInner, cond: KInner) -> KApply:
219220
def jump_applied(pc: KInner) -> KApply:
220221
return KApply('___EVM_InternalOp_UnStackOp_Int', [KEVM.jump(), pc])
221222

223+
@staticmethod
224+
def pow128() -> KApply:
225+
return KApply('pow128_WORD_Int', [])
226+
222227
@staticmethod
223228
def pow256() -> KApply:
224229
return KApply('pow256_WORD_Int', [])

kevm-pyk/src/kevm_pyk/solc_to_k.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,9 @@ def _range_predicate(term: KInner, type_label: str) -> Optional[KInner]:
545545
return KEVM.range_uint(256, term)
546546
if type_label == 'int256':
547547
return KEVM.range_sint(256, term)
548-
if type_label in {'bytes', 'string'}:
548+
if type_label == 'bytes':
549+
return KEVM.range_uint(128, KEVM.size_bytearray(term))
550+
if type_label == 'string':
549551
return TRUE
550552

551553
_LOGGER.warning(f'Unknown range predicate for type: {type_label}')

kevm-pyk/src/kevm_pyk/utils.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Collection, Iterable, List, Optional, Tuple
33

44
from pyk.cterm import CTerm
5-
from pyk.kast.inner import KApply, KInner, KVariable, Subst
5+
from pyk.kast.inner import KApply, KInner, KRewrite, KVariable, Subst
66
from pyk.kast.manip import (
77
abstract_term_safely,
88
bool_to_ml_pred,
@@ -23,6 +23,27 @@
2323
from pyk.prelude.ml import mlAnd
2424

2525

26+
def KDefinition__expand_macros(defn: KDefinition, term: KInner) -> KInner: # noqa: N802
27+
def _expand_macros(_term: KInner) -> KInner:
28+
if type(_term) is KApply:
29+
prod = defn.production_for_klabel(_term.label)
30+
if 'macro' in prod.att or 'alias' in prod.att or 'macro-rec' in prod.att or 'alias-rec' in prod.att:
31+
for r in defn.macro_rules:
32+
assert type(r.body) is KRewrite
33+
_new_term = r.body.apply_top(_term)
34+
if _new_term != _term:
35+
_term = _new_term
36+
break
37+
return _term
38+
39+
old_term = None
40+
while term != old_term:
41+
old_term = term
42+
term = bottom_up(_expand_macros, term)
43+
44+
return term
45+
46+
2647
def KCFG__replace_node(cfg: KCFG, node_id: str, new_cterm: CTerm) -> KCFG: # noqa: N802
2748

2849
# Remove old node, record data

tests/foundry/exclude

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ AssumeTest.test_assume_false
1414
AssumeTest.testFail_assume_false
1515
AssumeTest.testFail_assume_true
1616
BroadcastTest.testDeploy
17+
BytesTypeTest.test_bytes32_fail
18+
BytesTypeTest.test_bytes4_fail
19+
BytesTypeTest.testFail_bytes32
20+
BytesTypeTest.testFail_bytes4
1721
ContractBTest.testCannotSubtract43
1822
ContractBTest.testFailSubtract43
1923
ContractBTest.testNumberIs42

0 commit comments

Comments
 (0)