certora-cli-beta-mirror 8.1.0__py3-none-any.whl → 8.2.0__py3-none-any.whl

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.
@@ -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(EvmAppClass):
51
+ class SuiApp(MoveAppClass):
49
52
  attr_class = Attrs.SuiProverAttributes
@@ -2505,7 +2505,7 @@ class CertoraBuildGenerator:
2505
2505
  mut=InsertAfter())
2506
2506
  return function_finder_by_contract, function_finder_instrumentation
2507
2507
 
2508
- def add_internal_func_harnesses(self, contract_file: str, sdc: SDC, specCalls: List[str]) -> Optional[Tuple[Dict[str, str], Dict[str, Dict[int, Instrumentation]]]]:
2508
+ 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
2509
  # contract file -> byte offset -> to insert
2510
2510
  harness_function_instrumentation: Dict[str, Dict[int, Instrumentation]] = defaultdict(dict)
2511
2511
  # internal function name -> harness fuction name
@@ -2519,7 +2519,7 @@ class CertoraBuildGenerator:
2519
2519
 
2520
2520
  for c in sdc.contracts:
2521
2521
  for f in c.internal_funcs:
2522
- if f"{sdc.primary_contract}.{f.name}" not in specCalls:
2522
+ if f"{sdc.primary_contract}.{f.name}" not in spec_calls:
2523
2523
  continue
2524
2524
 
2525
2525
  if f.fromLib:
@@ -2669,12 +2669,12 @@ class CertoraBuildGenerator:
2669
2669
  def build(self, certora_verify_generator: CertoraVerifyGenerator) -> None:
2670
2670
  context = self.context
2671
2671
 
2672
- specCalls: List[str] = []
2672
+ spec_calls: List[str] = []
2673
2673
  if context.verify and not context.disallow_internal_function_calls:
2674
2674
  with tempfile.NamedTemporaryFile("r", dir=Util.get_build_dir()) as tmp_file:
2675
2675
  try:
2676
2676
  Ctx.run_local_spec_check(False, context, ["-listCalls", tmp_file.name], print_errors=False)
2677
- specCalls = tmp_file.read().split("\n")
2677
+ spec_calls = tmp_file.read().split("\n")
2678
2678
  except Exception as e:
2679
2679
  instrumentation_logger.warning(f"Failed to get calls from spec\n{e}")
2680
2680
 
@@ -2729,7 +2729,7 @@ class CertoraBuildGenerator:
2729
2729
  # We start by trying to instrument _all_ finders, both autofinders and source finders
2730
2730
  added_finders, all_finders_success, src_finders_gen_success, post_backup_dir = self.finders_compilation_round(
2731
2731
  build_arg_contract_file, i, ignore_patterns, path_for_compiler_collector_file, pre_backup_dir,
2732
- sdc_pre_finders, not context.disable_source_finders, specCalls)
2732
+ sdc_pre_finders, not context.disable_source_finders, spec_calls)
2733
2733
 
2734
2734
  # we could have a case where source finders failed but regular finders succeeded.
2735
2735
  # e.g. if we processed the AST wrong and skipped source finders generation
@@ -2741,7 +2741,7 @@ class CertoraBuildGenerator:
2741
2741
  # let's try just the function autofinders
2742
2742
  added_finders, function_autofinder_success, _, post_backup_dir = self.finders_compilation_round(
2743
2743
  build_arg_contract_file, i, ignore_patterns, path_for_compiler_collector_file, pre_backup_dir,
2744
- sdc_pre_finders, False, specCalls)
2744
+ sdc_pre_finders, False, spec_calls)
2745
2745
 
2746
2746
  if not function_autofinder_success:
2747
2747
  self.auto_finders_failed = True
@@ -3089,12 +3089,12 @@ class CertoraBuildGenerator:
3089
3089
  pre_backup_dir: Path,
3090
3090
  sdc_pre_finders: List[SDC],
3091
3091
  with_source_finders: bool,
3092
- specCalls: List[str]) -> Tuple[
3092
+ spec_calls: List[str]) -> Tuple[
3093
3093
  List[Tuple[Dict[str, InternalFunc], Dict[str, UnspecializedSourceFinder], Dict[str, str], SDC]], bool, bool, Path]:
3094
3094
  added_finders_to_sdc, finders_compilation_success, source_finders_gen_success = \
3095
3095
  self.instrument_auto_finders(
3096
3096
  build_arg_contract_file, i, sdc_pre_finders,
3097
- path_for_compiler_collector_file, with_source_finders, specCalls)
3097
+ path_for_compiler_collector_file, with_source_finders, spec_calls)
3098
3098
  # successful or not, we backup current .certora_sources for either debuggability, or for availability
3099
3099
  # of sources.
3100
3100
  post_backup_dir = self.get_fresh_backupdir(Util.POST_AUTOFINDER_BACKUP_DIR)
@@ -3167,7 +3167,7 @@ class CertoraBuildGenerator:
3167
3167
  sdc_pre_finders: List[SDC],
3168
3168
  path_for_compiler_collector_file: str,
3169
3169
  instrument_source_finders: bool,
3170
- specCalls: List[str]) -> Tuple[
3170
+ spec_calls: List[str]) -> Tuple[
3171
3171
  List[Tuple[Dict[str, InternalFunc], Dict[str, UnspecializedSourceFinder], Dict[str, str], SDC]], bool, bool]:
3172
3172
 
3173
3173
  # initialization
@@ -3188,7 +3188,7 @@ class CertoraBuildGenerator:
3188
3188
 
3189
3189
  added_internal_function_harnesses: Dict[str, str] = {}
3190
3190
  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, specCalls)
3191
+ added_internal_func_harness_tuple = self.add_internal_func_harnesses(build_arg_contract_file, sdc_pre_finder, spec_calls)
3192
3192
  if added_internal_func_harness_tuple:
3193
3193
  instr = CertoraBuildGenerator.merge_dicts_instrumentation(function_instr, added_internal_func_harness_tuple[1])
3194
3194
  added_internal_function_harnesses = added_internal_func_harness_tuple[0]
@@ -3887,21 +3887,19 @@ def build_from_scratch(context: CertoraContext,
3887
3887
  def build_from_cache_or_scratch(context: CertoraContext,
3888
3888
  certora_build_generator: CertoraBuildGenerator,
3889
3889
  certora_verify_generator: CertoraVerifyGenerator) \
3890
- -> Tuple[bool, bool, CachedFiles]:
3890
+ -> Tuple[bool, CachedFiles]:
3891
3891
  """
3892
3892
  Builds either from cache (fast path) or from scratch (slow path)
3893
- @returns 1st tuple element whether there was a cache hit or not
3894
- @returns 2nd tuple element whether the build cache is enabled and applicable
3895
- @returns 3rd tuple element the artifacts of the build to potentially be cached
3893
+ @returns 1st tuple element whether the cache should be saved
3894
+ @returns 2nd tuple element the artifacts of the build to potentially be cached
3896
3895
  """
3897
- cache_hit = False
3898
3896
  cached_files: Optional[CachedFiles] = None
3899
3897
 
3900
3898
  if not context.build_cache:
3901
3899
  cached_files = build_from_scratch(context, certora_build_generator,
3902
3900
  certora_verify_generator,
3903
3901
  False)
3904
- return cache_hit, False, cached_files
3902
+ return False, cached_files
3905
3903
 
3906
3904
  build_cache_applicable = CertoraBuildCacheManager.cache_is_applicable(context)
3907
3905
 
@@ -3912,34 +3910,60 @@ def build_from_cache_or_scratch(context: CertoraContext,
3912
3910
  cached_files = build_from_scratch(context, certora_build_generator,
3913
3911
  certora_verify_generator,
3914
3912
  False)
3915
- return cache_hit, False, cached_files
3913
+ return False, cached_files
3916
3914
 
3917
3915
  cached_files = CertoraBuildCacheManager.build_from_cache(context)
3918
- # if no match, will rebuild from scratch
3919
- if cached_files is not None:
3920
- # write to .certora_build.json
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
3916
+
3917
+ if not cached_files:
3918
+ # No match, rebuild
3938
3919
  cached_files = build_from_scratch(context, certora_build_generator,
3939
3920
  certora_verify_generator,
3940
3921
  True)
3922
+ return True, cached_files
3923
+
3924
+ # Cache hit!
3925
+
3926
+ # write to .certora_build.json
3927
+ # This must happen _before_ searching for new internal function calls - the typechecker needs this file.
3928
+ shutil.copyfile(cached_files.certora_build_file, Util.get_certora_build_file())
3929
+
3930
+ # Check whether there are any new internal function calls in the spec file - if there are then we need to build
3931
+ # from scratch in order to create the relevant harness function.
3932
+ if context.verify and not context.disallow_internal_function_calls:
3933
+ with tempfile.NamedTemporaryFile("r", dir=Util.get_build_dir()) as tmp_file:
3934
+ internal_calls = []
3935
+ try:
3936
+ Ctx.run_local_spec_check(True, context, ["-listCalls", tmp_file.name], print_errors=False)
3937
+ output = tmp_file.read().strip()
3938
+ if output:
3939
+ internal_calls = output.split("\n")
3940
+ except Exception as e:
3941
+ instrumentation_logger.warning(f"Failed to get calls from spec\n{e}")
3942
+
3943
+ if internal_calls:
3944
+ build_logger.info("Found new internal calls in the spec file, need to recompile anyway")
3945
+ # There are new internal calls in the spec, we need to rebuild in order to generate the
3946
+ # external harness functions for them.
3947
+ cached_files = build_from_scratch(context, certora_build_generator,
3948
+ certora_verify_generator,
3949
+ True)
3950
+ return True, cached_files
3951
+
3952
+ # write build_output_props file
3953
+ shutil.copyfile(cached_files.build_output_props_file, Util.get_built_output_props_file())
3954
+ # write build_cache indicator file
3955
+ with open(Util.get_build_cache_indicator_file(), "w+") as indicator_handle:
3956
+ json.dump({"build_cache_hit": True}, indicator_handle)
3957
+ # write in sources all the additional paths found
3958
+ for p in cached_files.path_with_additional_included_files.glob("*"):
3959
+ if p.is_dir():
3960
+ Util.safe_copy_folder(p,
3961
+ Util.get_certora_sources_dir() / p.name,
3962
+ shutil.ignore_patterns())
3963
+ else:
3964
+ shutil.copyfile(p, Util.get_certora_sources_dir() / p.name)
3941
3965
 
3942
- return cache_hit, True, cached_files
3966
+ return False, cached_files
3943
3967
 
3944
3968
 
3945
3969
  def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> None:
@@ -3969,9 +3993,9 @@ def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> No
3969
3993
  build_logger.warning(
3970
3994
  "Local checks of CVL specification files disabled. It is recommended to enable the checks.")
3971
3995
 
3972
- cache_hit, build_cache_enabled, cached_files = build_from_cache_or_scratch(context,
3973
- certora_build_generator,
3974
- certora_verify_generator)
3996
+ should_save_cache, cached_files = build_from_cache_or_scratch(context,
3997
+ certora_build_generator,
3998
+ certora_verify_generator)
3975
3999
 
3976
4000
  # avoid running the same test over and over again for each split run, context.split_rules is true only for
3977
4001
  # the first run and is set to [] for split runs
@@ -3990,7 +4014,7 @@ def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> No
3990
4014
  build_logger.debug("build_source_tree failed", exc_info=e)
3991
4015
 
3992
4016
  # save in build cache
3993
- if not cache_hit and build_cache_enabled and cached_files.may_store_in_build_cache:
4017
+ if should_save_cache and cached_files.may_store_in_build_cache:
3994
4018
  CertoraBuildCacheManager.save_build_cache(context, cached_files)
3995
4019
 
3996
4020
  certora_verify_generator.update_certora_verify_struct(True)