certora-cli 8.1.0__tar.gz → 8.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {certora_cli-8.1.0/certora_cli.egg-info → certora_cli-8.3.0}/PKG-INFO +2 -2
- certora_cli-8.3.0/README.md +1 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraApp.py +4 -1
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraBuild.py +143 -63
- certora_cli-8.3.0/certora_cli/CertoraProver/certoraBuildSui.py +112 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraConfigIO.py +2 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraContext.py +13 -10
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraContextAttributes.py +109 -21
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Mutate/mutateValidate.py +40 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/certoraUtils.py +30 -5
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/certoraValidateFuncs.py +22 -7
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraRun.py +0 -4
- {certora_cli-8.1.0 → certora_cli-8.3.0/certora_cli.egg-info}/PKG-INFO +2 -2
- certora_cli-8.1.0/certora_jars/Typechecker.jar → certora_cli-8.3.0/certora_jars/ASTExtraction.jar +0 -0
- certora_cli-8.3.0/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- certora_cli-8.1.0/certora_jars/ASTExtraction.jar → certora_cli-8.3.0/certora_jars/Typechecker.jar +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/setup.py +2 -2
- certora_cli-8.1.0/README.md +0 -1
- certora_cli-8.1.0/certora_cli/CertoraProver/certoraBuildSui.py +0 -68
- certora_cli-8.1.0/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora_cli-8.1.0 → certora_cli-8.3.0}/LICENSE +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/MANIFEST.in +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_bins/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/CompilerCollector.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorFactory.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorSol.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorSolBased.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorVy.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorYul.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/Compiler/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraBuildCacheManager.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraBuildDataClasses.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraBuildRust.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraCloudIO.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraCollectConfigurationLayout.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraCollectRunMetadata.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraCompilerParameters.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraContextClass.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraContextValidator.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraContractFuncs.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraExtensionInfo.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraJobList.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraMiniSpecParser.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraNodeFilters.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraParseBuildScript.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraProjectScanner.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraSourceFinders.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraType.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/certoraVerifyGenerator.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/erc7201.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/splitRules.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/CertoraProver/storageExtension.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Mutate/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Mutate/mutateApp.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Mutate/mutateAttributes.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Mutate/mutateConstants.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Mutate/mutateUtil.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/certoraAttrUtil.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/Shared/proverCommon.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraCVLFormatter.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraConcord.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraEVMProver.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraEqCheck.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraMutate.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraRanger.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraSolanaProver.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/certoraSorobanProver.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli/rustMutator.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli.egg-info/SOURCES.txt +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli.egg-info/dependency_links.txt +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli.egg-info/entry_points.txt +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli.egg-info/requires.txt +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_cli.egg-info/top_level.txt +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/certora_jars/__init__.py +0 -0
- {certora_cli-8.1.0 → certora_cli-8.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: certora-cli
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.3.0
|
|
4
4
|
Summary: Runner for the Certora Prover
|
|
5
5
|
Home-page: https://pypi.org/project/certora-cli
|
|
6
6
|
Author: Certora
|
|
@@ -39,4 +39,4 @@ Dynamic: requires-dist
|
|
|
39
39
|
Dynamic: requires-python
|
|
40
40
|
Dynamic: summary
|
|
41
41
|
|
|
42
|
-
Commit
|
|
42
|
+
Commit 3c8a0dd. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 3c8a0dd. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -33,6 +33,9 @@ class EvmApp(EvmAppClass):
|
|
|
33
33
|
class RustAppClass(CertoraApp):
|
|
34
34
|
pass
|
|
35
35
|
|
|
36
|
+
class MoveAppClass(CertoraApp):
|
|
37
|
+
pass
|
|
38
|
+
|
|
36
39
|
class SolanaApp(RustAppClass):
|
|
37
40
|
attr_class = Attrs.SolanaProverAttributes
|
|
38
41
|
|
|
@@ -45,5 +48,5 @@ class RangerApp(EvmAppClass):
|
|
|
45
48
|
class ConcordApp(EvmAppClass):
|
|
46
49
|
attr_class = Attrs.ConcordAttributes
|
|
47
50
|
|
|
48
|
-
class SuiApp(
|
|
51
|
+
class SuiApp(MoveAppClass):
|
|
49
52
|
attr_class = Attrs.SuiProverAttributes
|
|
@@ -203,11 +203,18 @@ class PresetImmutableReference(ImmutableReference):
|
|
|
203
203
|
# this function is Solidity specific.
|
|
204
204
|
# todo: create certoraBuildUtilsSol.py file, where such solidity specific functions will be.
|
|
205
205
|
def generate_finder_body(f: Func, internal_id: int, sym: int, compiler_collector: CompilerCollectorSol,
|
|
206
|
-
compressed: bool = False
|
|
206
|
+
compressed: bool = False,
|
|
207
|
+
should_generate_inlining: bool = True) -> Optional[Tuple[List[int], str]]:
|
|
207
208
|
if compressed:
|
|
208
209
|
return generate_compressed_finder(
|
|
209
210
|
f, internal_id, sym, compiler_collector
|
|
210
211
|
)
|
|
212
|
+
elif not should_generate_inlining:
|
|
213
|
+
# We should not generate inlining as reported in CERT-9399, only when compressed=False.
|
|
214
|
+
# used_symbols is being generated the exact same way as in generate_full_finder
|
|
215
|
+
used_symbols = [i for i in range(len(f.fullArgs))]
|
|
216
|
+
return used_symbols, ''
|
|
217
|
+
|
|
211
218
|
else:
|
|
212
219
|
return generate_full_finder(
|
|
213
220
|
f, internal_id, sym, compiler_collector
|
|
@@ -403,8 +410,9 @@ def get_modifier_param_type_name(ind: int, def_node: Dict[str, Any], f: Func) ->
|
|
|
403
410
|
|
|
404
411
|
def generate_modifier_finder(f: Func, internal_id: int, sym: int,
|
|
405
412
|
compiler_collector: CompilerCollectorSol, def_node: Dict[str, Any],
|
|
406
|
-
compress: bool) -> Optional[Tuple[str, str]]:
|
|
407
|
-
compressed = generate_finder_body(f, internal_id, sym, compiler_collector, compressed=compress
|
|
413
|
+
compress: bool, should_generate_inlining: bool) -> Optional[Tuple[str, str]]:
|
|
414
|
+
compressed = generate_finder_body(f, internal_id, sym, compiler_collector, compressed=compress,
|
|
415
|
+
should_generate_inlining=should_generate_inlining)
|
|
408
416
|
if compressed is None:
|
|
409
417
|
return None
|
|
410
418
|
modifier_name = f"logInternal{internal_id}"
|
|
@@ -427,9 +435,10 @@ def generate_modifier_finder(f: Func, internal_id: int, sym: int,
|
|
|
427
435
|
return f'{modifier_name}({",".join(arg_strings)})', modifier_body
|
|
428
436
|
|
|
429
437
|
|
|
430
|
-
def generate_inline_finder(f: Func, internal_id: int, sym: int,
|
|
431
|
-
|
|
432
|
-
finder = generate_finder_body(f, internal_id, sym, compiler_collector, compressed=should_compress
|
|
438
|
+
def generate_inline_finder(f: Func, internal_id: int, sym: int, compiler_collector: CompilerCollectorSol,
|
|
439
|
+
should_compress: bool, should_generate_inlining: bool) -> Optional[str]:
|
|
440
|
+
finder = generate_finder_body(f, internal_id, sym, compiler_collector, compressed=should_compress,
|
|
441
|
+
should_generate_inlining=should_generate_inlining)
|
|
433
442
|
if finder is None:
|
|
434
443
|
return None
|
|
435
444
|
return finder[1]
|
|
@@ -2448,6 +2457,19 @@ class CertoraBuildGenerator:
|
|
|
2448
2457
|
# (deprecate this option later)
|
|
2449
2458
|
should_compress = self.context.function_finder_mode == Vf.FunctionFinderMode.DEFAULT.name
|
|
2450
2459
|
|
|
2460
|
+
if self.context.solc_optimize and self.get_solc_via_ir_value(Path(contract_file)) and \
|
|
2461
|
+
any(param_name == "" for param_name in f.paramNames):
|
|
2462
|
+
# As reported in CERT-9399, we should not generate function finder for this edge case
|
|
2463
|
+
|
|
2464
|
+
instrumentation_logger.warning(f"Failed to generate auto finder for {f.name} @ {f.where()}.")
|
|
2465
|
+
instrumentation_logger.warning(
|
|
2466
|
+
"Cannot apply summaries for internal functions with unnamed argument when compiling "
|
|
2467
|
+
"using solc_optimize and solc_via_ir"
|
|
2468
|
+
)
|
|
2469
|
+
should_generate_inlining = False
|
|
2470
|
+
else:
|
|
2471
|
+
should_generate_inlining = True
|
|
2472
|
+
|
|
2451
2473
|
if len(mods) > 0:
|
|
2452
2474
|
# we need to add the instrumentation in a modifer because solidity modifiers will (potentially)
|
|
2453
2475
|
# appear before any instrumentation we add to the literal source body, which will tank the detection
|
|
@@ -2459,8 +2481,10 @@ class CertoraBuildGenerator:
|
|
|
2459
2481
|
# where in the source such modifiers will go. In order to insert a modifier, we have to have at
|
|
2460
2482
|
# least one modifier already present, and then insert before the first modifier's location in the
|
|
2461
2483
|
# source code
|
|
2462
|
-
mod_inst = generate_modifier_finder(
|
|
2463
|
-
|
|
2484
|
+
mod_inst = generate_modifier_finder(
|
|
2485
|
+
f, internal_id, function_symbol, sdc.compiler_collector, def_node,
|
|
2486
|
+
compress=should_compress, should_generate_inlining=should_generate_inlining
|
|
2487
|
+
)
|
|
2464
2488
|
if mod_inst is None:
|
|
2465
2489
|
instrumentation_logger.debug(f"Modifier generation for {f.name} @ {f.where()} failed")
|
|
2466
2490
|
return None
|
|
@@ -2494,8 +2518,8 @@ class CertoraBuildGenerator:
|
|
|
2494
2518
|
per_file_inst[first_mod_offset] = Instrumentation(expected=bytes(modifier_name[0:1], "utf-8"),
|
|
2495
2519
|
to_ins=modifier_invocation, mut=InsertBefore())
|
|
2496
2520
|
else:
|
|
2497
|
-
finder_res = generate_inline_finder(f, internal_id, function_symbol,
|
|
2498
|
-
|
|
2521
|
+
finder_res = generate_inline_finder(f, internal_id, function_symbol, sdc.compiler_collector,
|
|
2522
|
+
should_compress, should_generate_inlining)
|
|
2499
2523
|
if finder_res is None:
|
|
2500
2524
|
instrumentation_logger.debug(f"Generating auto finder for {f.name} @ {f.where()}"
|
|
2501
2525
|
f" failed, giving up generation")
|
|
@@ -2505,7 +2529,7 @@ class CertoraBuildGenerator:
|
|
|
2505
2529
|
mut=InsertAfter())
|
|
2506
2530
|
return function_finder_by_contract, function_finder_instrumentation
|
|
2507
2531
|
|
|
2508
|
-
def add_internal_func_harnesses(self, contract_file: str, sdc: SDC,
|
|
2532
|
+
def add_internal_func_harnesses(self, contract_file: str, sdc: SDC, spec_calls: List[str]) -> Optional[Tuple[Dict[str, str], Dict[str, Dict[int, Instrumentation]]]]:
|
|
2509
2533
|
# contract file -> byte offset -> to insert
|
|
2510
2534
|
harness_function_instrumentation: Dict[str, Dict[int, Instrumentation]] = defaultdict(dict)
|
|
2511
2535
|
# internal function name -> harness fuction name
|
|
@@ -2519,7 +2543,7 @@ class CertoraBuildGenerator:
|
|
|
2519
2543
|
|
|
2520
2544
|
for c in sdc.contracts:
|
|
2521
2545
|
for f in c.internal_funcs:
|
|
2522
|
-
if f"{sdc.primary_contract}.{f.name}" not in
|
|
2546
|
+
if f"{sdc.primary_contract}.{f.name}" not in spec_calls:
|
|
2523
2547
|
continue
|
|
2524
2548
|
|
|
2525
2549
|
if f.fromLib:
|
|
@@ -2669,14 +2693,14 @@ class CertoraBuildGenerator:
|
|
|
2669
2693
|
def build(self, certora_verify_generator: CertoraVerifyGenerator) -> None:
|
|
2670
2694
|
context = self.context
|
|
2671
2695
|
|
|
2672
|
-
|
|
2696
|
+
spec_calls: List[str] = []
|
|
2673
2697
|
if context.verify and not context.disallow_internal_function_calls:
|
|
2674
2698
|
with tempfile.NamedTemporaryFile("r", dir=Util.get_build_dir()) as tmp_file:
|
|
2675
2699
|
try:
|
|
2676
2700
|
Ctx.run_local_spec_check(False, context, ["-listCalls", tmp_file.name], print_errors=False)
|
|
2677
|
-
|
|
2701
|
+
spec_calls = tmp_file.read().split("\n")
|
|
2678
2702
|
except Exception as e:
|
|
2679
|
-
instrumentation_logger.
|
|
2703
|
+
instrumentation_logger.debug(f"Failed to get calls from spec\n{e}")
|
|
2680
2704
|
|
|
2681
2705
|
self.context.remappings = []
|
|
2682
2706
|
for i, build_arg_contract_file in enumerate(sorted(self.input_config.sorted_files)):
|
|
@@ -2729,7 +2753,7 @@ class CertoraBuildGenerator:
|
|
|
2729
2753
|
# We start by trying to instrument _all_ finders, both autofinders and source finders
|
|
2730
2754
|
added_finders, all_finders_success, src_finders_gen_success, post_backup_dir = self.finders_compilation_round(
|
|
2731
2755
|
build_arg_contract_file, i, ignore_patterns, path_for_compiler_collector_file, pre_backup_dir,
|
|
2732
|
-
sdc_pre_finders, not context.disable_source_finders,
|
|
2756
|
+
sdc_pre_finders, not context.disable_source_finders, spec_calls)
|
|
2733
2757
|
|
|
2734
2758
|
# we could have a case where source finders failed but regular finders succeeded.
|
|
2735
2759
|
# e.g. if we processed the AST wrong and skipped source finders generation
|
|
@@ -2741,7 +2765,7 @@ class CertoraBuildGenerator:
|
|
|
2741
2765
|
# let's try just the function autofinders
|
|
2742
2766
|
added_finders, function_autofinder_success, _, post_backup_dir = self.finders_compilation_round(
|
|
2743
2767
|
build_arg_contract_file, i, ignore_patterns, path_for_compiler_collector_file, pre_backup_dir,
|
|
2744
|
-
sdc_pre_finders, False,
|
|
2768
|
+
sdc_pre_finders, False, spec_calls)
|
|
2745
2769
|
|
|
2746
2770
|
if not function_autofinder_success:
|
|
2747
2771
|
self.auto_finders_failed = True
|
|
@@ -2825,7 +2849,7 @@ class CertoraBuildGenerator:
|
|
|
2825
2849
|
self.handle_erc7201_annotations()
|
|
2826
2850
|
self.handle_storage_extension_harnesses()
|
|
2827
2851
|
|
|
2828
|
-
def extract_slayout(self, original_file: str, ns_storage: Set[NameSpacedStorage], compiler_version: str) -> NewStorageInfo:
|
|
2852
|
+
def extract_slayout(self, original_file: str, ns_storage: Set[NameSpacedStorage], compiler_version: str, target_file: str) -> NewStorageInfo:
|
|
2829
2853
|
"""
|
|
2830
2854
|
Given a file containing a contract with namespaced storage, extract the storage information
|
|
2831
2855
|
corresponding to the namespaced types.
|
|
@@ -2869,8 +2893,8 @@ class CertoraBuildGenerator:
|
|
|
2869
2893
|
abs_path = Util.abs_posix_path(tmp_file.name)
|
|
2870
2894
|
self.context.file_to_contract[abs_path] = {harness_name}
|
|
2871
2895
|
|
|
2872
|
-
|
|
2873
|
-
|
|
2896
|
+
def attempt_compilation() -> NewStorageInfo:
|
|
2897
|
+
"""Helper function to compile and extract layout"""
|
|
2874
2898
|
compile_idx = storageExtension.get_next_file_index(self.file_to_sdc_name)
|
|
2875
2899
|
sdcs = self.collect_for_file(tmp_file.name, compile_idx, CompilerLangSol(), Path.cwd(), Util.abs_posix_path(tmp_file.name), None)
|
|
2876
2900
|
if not sdcs:
|
|
@@ -2879,12 +2903,38 @@ class CertoraBuildGenerator:
|
|
|
2879
2903
|
|
|
2880
2904
|
# Remap each slot according to the ERC-7201 namespace
|
|
2881
2905
|
remapped_fields = storageExtension.remapped_fields_from_layout(layout, var_to_slot)
|
|
2882
|
-
|
|
2883
2906
|
return (remapped_fields, layout.get('types', {}))
|
|
2884
2907
|
|
|
2908
|
+
# First attempt with original content
|
|
2909
|
+
try:
|
|
2910
|
+
return attempt_compilation()
|
|
2885
2911
|
except Exception as e:
|
|
2886
|
-
|
|
2887
|
-
|
|
2912
|
+
if not target_file:
|
|
2913
|
+
build_logger.error(f"Error extracting storage layout for {original_file}: {str(e)}")
|
|
2914
|
+
raise
|
|
2915
|
+
|
|
2916
|
+
# Retry with target file import
|
|
2917
|
+
build_logger.info("First attempt failed, retrying with import of target file")
|
|
2918
|
+
|
|
2919
|
+
# Read current content
|
|
2920
|
+
tmp_file.seek(0)
|
|
2921
|
+
current_content = tmp_file.read()
|
|
2922
|
+
|
|
2923
|
+
# Prepare modified content with target import at the beginning
|
|
2924
|
+
rel_target_path = os.path.relpath(target_file, Path.cwd())
|
|
2925
|
+
modified_content = f'import "{rel_target_path}";\n{current_content}'
|
|
2926
|
+
|
|
2927
|
+
# Write modified content
|
|
2928
|
+
tmp_file.seek(0)
|
|
2929
|
+
tmp_file.truncate()
|
|
2930
|
+
tmp_file.write(modified_content)
|
|
2931
|
+
tmp_file.flush()
|
|
2932
|
+
|
|
2933
|
+
try:
|
|
2934
|
+
return attempt_compilation()
|
|
2935
|
+
except Exception as retry_e:
|
|
2936
|
+
build_logger.error(f"Retry also failed for {original_file}: {str(retry_e)}")
|
|
2937
|
+
raise retry_e
|
|
2888
2938
|
finally:
|
|
2889
2939
|
# Delete the key from the context
|
|
2890
2940
|
self.context.file_to_contract.pop(abs_path, None)
|
|
@@ -2933,7 +2983,8 @@ class CertoraBuildGenerator:
|
|
|
2933
2983
|
|
|
2934
2984
|
# Now that we have all the storage layout information, extract it once
|
|
2935
2985
|
slayouts[key] = self.extract_slayout(imported_file, ns_storage,
|
|
2936
|
-
get_relevant_compiler(Path(target_file), self.context)
|
|
2986
|
+
get_relevant_compiler(Path(target_file), self.context),
|
|
2987
|
+
target_file)
|
|
2937
2988
|
|
|
2938
2989
|
if self.context.test == str(Util.TestValue.STORAGE_EXTENSION_LAYOUT):
|
|
2939
2990
|
raise Util.TestResultsReady(slayouts)
|
|
@@ -3089,12 +3140,12 @@ class CertoraBuildGenerator:
|
|
|
3089
3140
|
pre_backup_dir: Path,
|
|
3090
3141
|
sdc_pre_finders: List[SDC],
|
|
3091
3142
|
with_source_finders: bool,
|
|
3092
|
-
|
|
3143
|
+
spec_calls: List[str]) -> Tuple[
|
|
3093
3144
|
List[Tuple[Dict[str, InternalFunc], Dict[str, UnspecializedSourceFinder], Dict[str, str], SDC]], bool, bool, Path]:
|
|
3094
3145
|
added_finders_to_sdc, finders_compilation_success, source_finders_gen_success = \
|
|
3095
3146
|
self.instrument_auto_finders(
|
|
3096
3147
|
build_arg_contract_file, i, sdc_pre_finders,
|
|
3097
|
-
path_for_compiler_collector_file, with_source_finders,
|
|
3148
|
+
path_for_compiler_collector_file, with_source_finders, spec_calls)
|
|
3098
3149
|
# successful or not, we backup current .certora_sources for either debuggability, or for availability
|
|
3099
3150
|
# of sources.
|
|
3100
3151
|
post_backup_dir = self.get_fresh_backupdir(Util.POST_AUTOFINDER_BACKUP_DIR)
|
|
@@ -3167,7 +3218,7 @@ class CertoraBuildGenerator:
|
|
|
3167
3218
|
sdc_pre_finders: List[SDC],
|
|
3168
3219
|
path_for_compiler_collector_file: str,
|
|
3169
3220
|
instrument_source_finders: bool,
|
|
3170
|
-
|
|
3221
|
+
spec_calls: List[str]) -> Tuple[
|
|
3171
3222
|
List[Tuple[Dict[str, InternalFunc], Dict[str, UnspecializedSourceFinder], Dict[str, str], SDC]], bool, bool]:
|
|
3172
3223
|
|
|
3173
3224
|
# initialization
|
|
@@ -3188,7 +3239,7 @@ class CertoraBuildGenerator:
|
|
|
3188
3239
|
|
|
3189
3240
|
added_internal_function_harnesses: Dict[str, str] = {}
|
|
3190
3241
|
if not self.context.disallow_internal_function_calls:
|
|
3191
|
-
added_internal_func_harness_tuple = self.add_internal_func_harnesses(build_arg_contract_file, sdc_pre_finder,
|
|
3242
|
+
added_internal_func_harness_tuple = self.add_internal_func_harnesses(build_arg_contract_file, sdc_pre_finder, spec_calls)
|
|
3192
3243
|
if added_internal_func_harness_tuple:
|
|
3193
3244
|
instr = CertoraBuildGenerator.merge_dicts_instrumentation(function_instr, added_internal_func_harness_tuple[1])
|
|
3194
3245
|
added_internal_function_harnesses = added_internal_func_harness_tuple[0]
|
|
@@ -3793,6 +3844,14 @@ def build_source_tree(sources: Set[Path], context: CertoraContext, overwrite: bo
|
|
|
3793
3844
|
cwd_file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
3794
3845
|
cwd_file_path.touch()
|
|
3795
3846
|
|
|
3847
|
+
# copy context.forge_remappings to remappings.txt in the source tree, overwriting any existing remappings.txt
|
|
3848
|
+
forge_remappings = getattr(context, 'forge_remappings', None)
|
|
3849
|
+
if forge_remappings:
|
|
3850
|
+
remappings_file_path = Util.get_certora_sources_dir() / context.cwd_rel_in_sources / Util.REMAPPINGS_FILE
|
|
3851
|
+
with remappings_file_path.open("w") as remap_file:
|
|
3852
|
+
for remap in context.forge_remappings:
|
|
3853
|
+
remap_file.write(remap + "\n")
|
|
3854
|
+
|
|
3796
3855
|
# the empty file .project_directory is written in the source tree to denote the project directory
|
|
3797
3856
|
rust_proj_dir = getattr(context, 'rust_project_directory', None)
|
|
3798
3857
|
if rust_proj_dir:
|
|
@@ -3887,21 +3946,19 @@ def build_from_scratch(context: CertoraContext,
|
|
|
3887
3946
|
def build_from_cache_or_scratch(context: CertoraContext,
|
|
3888
3947
|
certora_build_generator: CertoraBuildGenerator,
|
|
3889
3948
|
certora_verify_generator: CertoraVerifyGenerator) \
|
|
3890
|
-
-> Tuple[bool,
|
|
3949
|
+
-> Tuple[bool, CachedFiles]:
|
|
3891
3950
|
"""
|
|
3892
3951
|
Builds either from cache (fast path) or from scratch (slow path)
|
|
3893
|
-
@returns 1st tuple element whether
|
|
3894
|
-
@returns 2nd tuple element
|
|
3895
|
-
@returns 3rd tuple element the artifacts of the build to potentially be cached
|
|
3952
|
+
@returns 1st tuple element whether the cache should be saved
|
|
3953
|
+
@returns 2nd tuple element the artifacts of the build to potentially be cached
|
|
3896
3954
|
"""
|
|
3897
|
-
cache_hit = False
|
|
3898
3955
|
cached_files: Optional[CachedFiles] = None
|
|
3899
3956
|
|
|
3900
3957
|
if not context.build_cache:
|
|
3901
3958
|
cached_files = build_from_scratch(context, certora_build_generator,
|
|
3902
3959
|
certora_verify_generator,
|
|
3903
3960
|
False)
|
|
3904
|
-
return
|
|
3961
|
+
return False, cached_files
|
|
3905
3962
|
|
|
3906
3963
|
build_cache_applicable = CertoraBuildCacheManager.cache_is_applicable(context)
|
|
3907
3964
|
|
|
@@ -3912,34 +3969,60 @@ def build_from_cache_or_scratch(context: CertoraContext,
|
|
|
3912
3969
|
cached_files = build_from_scratch(context, certora_build_generator,
|
|
3913
3970
|
certora_verify_generator,
|
|
3914
3971
|
False)
|
|
3915
|
-
return
|
|
3972
|
+
return False, cached_files
|
|
3916
3973
|
|
|
3917
3974
|
cached_files = CertoraBuildCacheManager.build_from_cache(context)
|
|
3918
|
-
|
|
3919
|
-
if
|
|
3920
|
-
#
|
|
3921
|
-
shutil.copyfile(cached_files.certora_build_file, Util.get_certora_build_file())
|
|
3922
|
-
# write build_output_props file
|
|
3923
|
-
shutil.copyfile(cached_files.build_output_props_file, Util.get_built_output_props_file())
|
|
3924
|
-
# write build_cache indicator file
|
|
3925
|
-
with open(Util.get_build_cache_indicator_file(), "w+") as indicator_handle:
|
|
3926
|
-
json.dump({"build_cache_hit": True}, indicator_handle)
|
|
3927
|
-
# write in sources all the additional paths found
|
|
3928
|
-
for p in cached_files.path_with_additional_included_files.glob("*"):
|
|
3929
|
-
if p.is_dir():
|
|
3930
|
-
Util.safe_copy_folder(p,
|
|
3931
|
-
Util.get_certora_sources_dir() / p.name,
|
|
3932
|
-
shutil.ignore_patterns())
|
|
3933
|
-
else:
|
|
3934
|
-
shutil.copyfile(p, Util.get_certora_sources_dir() / p.name)
|
|
3935
|
-
cache_hit = True
|
|
3936
|
-
else:
|
|
3937
|
-
# rebuild
|
|
3975
|
+
|
|
3976
|
+
if not cached_files:
|
|
3977
|
+
# No match, rebuild
|
|
3938
3978
|
cached_files = build_from_scratch(context, certora_build_generator,
|
|
3939
3979
|
certora_verify_generator,
|
|
3940
3980
|
True)
|
|
3981
|
+
return True, cached_files
|
|
3941
3982
|
|
|
3942
|
-
|
|
3983
|
+
# Cache hit!
|
|
3984
|
+
|
|
3985
|
+
# write to .certora_build.json
|
|
3986
|
+
# This must happen _before_ searching for new internal function calls - the typechecker needs this file.
|
|
3987
|
+
shutil.copyfile(cached_files.certora_build_file, Util.get_certora_build_file())
|
|
3988
|
+
|
|
3989
|
+
# Check whether there are any new internal function calls in the spec file - if there are then we need to build
|
|
3990
|
+
# from scratch in order to create the relevant harness function.
|
|
3991
|
+
if context.verify and not context.disallow_internal_function_calls:
|
|
3992
|
+
with tempfile.NamedTemporaryFile("r", dir=Util.get_build_dir()) as tmp_file:
|
|
3993
|
+
internal_calls = []
|
|
3994
|
+
try:
|
|
3995
|
+
Ctx.run_local_spec_check(True, context, ["-listCalls", tmp_file.name], print_errors=False)
|
|
3996
|
+
output = tmp_file.read().strip()
|
|
3997
|
+
if output:
|
|
3998
|
+
internal_calls = output.split("\n")
|
|
3999
|
+
except Exception as e:
|
|
4000
|
+
instrumentation_logger.debug(f"Failed to get calls from spec\n{e}")
|
|
4001
|
+
|
|
4002
|
+
if internal_calls:
|
|
4003
|
+
build_logger.info("Found new internal calls in the spec file, need to recompile anyway")
|
|
4004
|
+
# There are new internal calls in the spec, we need to rebuild in order to generate the
|
|
4005
|
+
# external harness functions for them.
|
|
4006
|
+
cached_files = build_from_scratch(context, certora_build_generator,
|
|
4007
|
+
certora_verify_generator,
|
|
4008
|
+
True)
|
|
4009
|
+
return True, cached_files
|
|
4010
|
+
|
|
4011
|
+
# write build_output_props file
|
|
4012
|
+
shutil.copyfile(cached_files.build_output_props_file, Util.get_built_output_props_file())
|
|
4013
|
+
# write build_cache indicator file
|
|
4014
|
+
with open(Util.get_build_cache_indicator_file(), "w+") as indicator_handle:
|
|
4015
|
+
json.dump({"build_cache_hit": True}, indicator_handle)
|
|
4016
|
+
# write in sources all the additional paths found
|
|
4017
|
+
for p in cached_files.path_with_additional_included_files.glob("*"):
|
|
4018
|
+
if p.is_dir():
|
|
4019
|
+
Util.safe_copy_folder(p,
|
|
4020
|
+
Util.get_certora_sources_dir() / p.name,
|
|
4021
|
+
shutil.ignore_patterns())
|
|
4022
|
+
else:
|
|
4023
|
+
shutil.copyfile(p, Util.get_certora_sources_dir() / p.name)
|
|
4024
|
+
|
|
4025
|
+
return False, cached_files
|
|
3943
4026
|
|
|
3944
4027
|
|
|
3945
4028
|
def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> None:
|
|
@@ -3965,13 +4048,10 @@ def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> No
|
|
|
3965
4048
|
if Cv.mode_has_spec_file(context) and not context.build_only and not ignore_spec_syntax_check:
|
|
3966
4049
|
if Ctx.should_run_local_speck_check(context):
|
|
3967
4050
|
Ctx.run_local_spec_check(False, context)
|
|
3968
|
-
else:
|
|
3969
|
-
build_logger.warning(
|
|
3970
|
-
"Local checks of CVL specification files disabled. It is recommended to enable the checks.")
|
|
3971
4051
|
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
4052
|
+
should_save_cache, cached_files = build_from_cache_or_scratch(context,
|
|
4053
|
+
certora_build_generator,
|
|
4054
|
+
certora_verify_generator)
|
|
3975
4055
|
|
|
3976
4056
|
# avoid running the same test over and over again for each split run, context.split_rules is true only for
|
|
3977
4057
|
# the first run and is set to [] for split runs
|
|
@@ -3990,7 +4070,7 @@ def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> No
|
|
|
3990
4070
|
build_logger.debug("build_source_tree failed", exc_info=e)
|
|
3991
4071
|
|
|
3992
4072
|
# save in build cache
|
|
3993
|
-
if
|
|
4073
|
+
if should_save_cache and cached_files.may_store_in_build_cache:
|
|
3994
4074
|
CertoraBuildCacheManager.save_build_cache(context, cached_files)
|
|
3995
4075
|
|
|
3996
4076
|
certora_verify_generator.update_certora_verify_struct(True)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# The Certora Prover
|
|
2
|
+
# Copyright (C) 2025 Certora Ltd.
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, version 3 of the License.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
scripts_dir_path = Path(__file__).parent.parent.resolve() # containing directory
|
|
23
|
+
sys.path.insert(0, str(scripts_dir_path))
|
|
24
|
+
|
|
25
|
+
import shutil
|
|
26
|
+
import time
|
|
27
|
+
import logging
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Set, Dict
|
|
30
|
+
|
|
31
|
+
from CertoraProver.certoraBuild import build_source_tree
|
|
32
|
+
from CertoraProver.certoraContextClass import CertoraContext
|
|
33
|
+
from Shared import certoraUtils as Util
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
log = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def build_sui_project(context: CertoraContext, timings: Dict) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Compile the Sui artefact and record elapsed time in *timings*.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
context: The CertoraContext object containing the configuration.
|
|
45
|
+
timings: A dictionary to store timing information.
|
|
46
|
+
"""
|
|
47
|
+
log.debug("Build Sui target")
|
|
48
|
+
start = time.perf_counter()
|
|
49
|
+
set_sui_build_directory(context)
|
|
50
|
+
timings["buildTime"] = round(time.perf_counter() - start, 4)
|
|
51
|
+
if context.test == str(Util.TestValue.AFTER_BUILD):
|
|
52
|
+
raise Util.TestResultsReady(context)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def set_sui_build_directory(context: CertoraContext) -> None:
|
|
56
|
+
sources: Set[Path] = set()
|
|
57
|
+
|
|
58
|
+
# If no move_path was specified, try to build the package
|
|
59
|
+
if not context.move_path:
|
|
60
|
+
move_toml_file = Util.find_file_in_parents("Move.toml")
|
|
61
|
+
if not move_toml_file:
|
|
62
|
+
raise Util.CertoraUserInputError("Could not find Move.toml, and no move_path was specified.")
|
|
63
|
+
sources.add(move_toml_file.absolute())
|
|
64
|
+
run_sui_build(context, move_toml_file.parent)
|
|
65
|
+
|
|
66
|
+
assert context.move_path, "expecting move_path to be set after build"
|
|
67
|
+
move_dir = Path(context.move_path)
|
|
68
|
+
assert move_dir.exists(), f"Output path '{move_dir}' does not exist"
|
|
69
|
+
assert move_dir.is_dir(), f"Output path '{move_dir}' is not a directory"
|
|
70
|
+
|
|
71
|
+
# Add all source files. We get these from the Sui build output, because it includes dependencies as well, and is
|
|
72
|
+
# available even if we didn't run the build ourselves.
|
|
73
|
+
sources.update(move_dir.rglob("*.move"))
|
|
74
|
+
|
|
75
|
+
# Add conf file if it exists
|
|
76
|
+
if getattr(context, 'conf_file', None) and Path(context.conf_file).exists():
|
|
77
|
+
sources.add(Path(context.conf_file).absolute())
|
|
78
|
+
|
|
79
|
+
# Copy the binary modules and source maps
|
|
80
|
+
shutil.copytree(move_dir,
|
|
81
|
+
Util.get_build_dir() / move_dir.name,
|
|
82
|
+
ignore=shutil.ignore_patterns('*.move'))
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# Create generators
|
|
86
|
+
build_source_tree(sources, context)
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
raise Util.CertoraUserInputError(f"Collecting build files failed with the exception: {e}")
|
|
90
|
+
|
|
91
|
+
def run_sui_build(context: CertoraContext, package_dir: Path) -> None:
|
|
92
|
+
assert not context.move_path, "run_sui_build: expecting move_path to be empty"
|
|
93
|
+
|
|
94
|
+
build_cmd = ["sui", "move", "build", "--test", "--path", str(package_dir)]
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
build_cmd_text = ' '.join(build_cmd)
|
|
98
|
+
log.info(f"Building by calling `{build_cmd_text}`")
|
|
99
|
+
result = subprocess.run(build_cmd, capture_output=False)
|
|
100
|
+
|
|
101
|
+
# Check if the script executed successfully
|
|
102
|
+
if result.returncode != 0:
|
|
103
|
+
raise Util.CertoraUserInputError(f"Error running `{build_cmd_text}`")
|
|
104
|
+
|
|
105
|
+
context.move_path = str(package_dir / "build")
|
|
106
|
+
|
|
107
|
+
except Util.TestResultsReady as e:
|
|
108
|
+
raise e
|
|
109
|
+
except Util.CertoraUserInputError as e:
|
|
110
|
+
raise e
|
|
111
|
+
except Exception as e:
|
|
112
|
+
raise Util.CertoraUserInputError(f"An unexpected error occurred: {e}")
|
|
@@ -111,6 +111,8 @@ def handle_override_base_config(context: CertoraContext) -> None:
|
|
|
111
111
|
if hasattr(context, attr):
|
|
112
112
|
value = getattr(context, attr, False)
|
|
113
113
|
if not value:
|
|
114
|
+
if attr in context.conf_file_attr and value is False:
|
|
115
|
+
continue # skip override if a boolean attribute was explicitly set to False in the conf file
|
|
114
116
|
setattr(context, attr, override_base_config_attrs.get(attr))
|
|
115
117
|
else:
|
|
116
118
|
raise Util.CertoraUserInputError(f"{attr} appears in the base conf file {context.override_base_config} but is not a known attribute.")
|
|
@@ -523,7 +523,15 @@ def __rename_key(context: CertoraContext, old_key: str, new_key: str) -> None:
|
|
|
523
523
|
|
|
524
524
|
|
|
525
525
|
def should_run_local_speck_check(context: CertoraContext) -> bool:
|
|
526
|
-
|
|
526
|
+
output = context.compilation_steps_only or not (context.disable_local_typechecking or Util.is_ci_or_git_action())
|
|
527
|
+
if not output:
|
|
528
|
+
if context.disable_local_typechecking:
|
|
529
|
+
context_logger.warning(
|
|
530
|
+
"Local checks of CVL specification files disabled. It is recommended to enable the checks."
|
|
531
|
+
)
|
|
532
|
+
else:
|
|
533
|
+
context_logger.info("Local checks of CVL specification files skipped in CI and will run remotely.")
|
|
534
|
+
return output
|
|
527
535
|
|
|
528
536
|
|
|
529
537
|
def run_typechecker(typechecker_name: str, with_typechecking: bool, args: List[str], print_errors: bool) -> None:
|
|
@@ -550,18 +558,13 @@ def run_typechecker(typechecker_name: str, with_typechecking: bool, args: List[s
|
|
|
550
558
|
context_logger.debug(f"typechecking cmd: {' '.join(cmd_str_list)}")
|
|
551
559
|
|
|
552
560
|
exit_code = Util.run_jar_cmd(cmd_str_list, False,
|
|
553
|
-
custom_error_message="Failed to run Certora Prover locally
|
|
554
|
-
"below for problems in the specifications
|
|
555
|
-
"prover_args defined in the .conf file.",
|
|
561
|
+
custom_error_message="Failed to run Certora Prover typechecker locally.\n"
|
|
562
|
+
"Please check the errors below for problems in the specifications"
|
|
563
|
+
" (.spec files) or the prover_args defined in the .conf file.",
|
|
556
564
|
logger_topic="type_check",
|
|
557
565
|
print_err=print_errors)
|
|
558
566
|
if exit_code != 0:
|
|
559
|
-
raise Util.CertoraUserInputError(
|
|
560
|
-
"CVL syntax or type check failed.\n Please fix the issue. "
|
|
561
|
-
"Using --disable_local_typechecking to skip this check is strongly discouraged, "
|
|
562
|
-
"as simple syntax errors will only be detected during the cloud run."
|
|
563
|
-
"with --disable_local_typechecking is not recommended is not recommended as "
|
|
564
|
-
"simple syntax failures will be visible only on the cloud run.")
|
|
567
|
+
raise Util.CertoraUserInputError("CVL syntax or type check failed, please fix the issue.")
|
|
565
568
|
|
|
566
569
|
|
|
567
570
|
def run_local_spec_check(with_typechecking: bool, context: CertoraContext, extra_args: List[str] = list(), print_errors: bool = True) -> None:
|