certora-cli 7.10.2__tar.gz → 7.14.3__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.
Files changed (67) hide show
  1. {certora_cli-7.10.2/certora_cli.egg-info → certora_cli-7.14.3}/PKG-INFO +2 -2
  2. certora_cli-7.14.3/README.md +1 -0
  3. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraBuild.py +8 -9
  4. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraCloudIO.py +10 -10
  5. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py +11 -8
  6. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraConfigIO.py +24 -20
  7. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraContext.py +107 -51
  8. certora_cli-7.10.2/certora_cli/EVMVerifier/certoraContextAttribute.py → certora_cli-7.14.3/certora_cli/EVMVerifier/certoraContextAttributes.py +670 -644
  9. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraContextValidator.py +28 -45
  10. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/equivCheck.py +1 -1
  11. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Mutate/mutateApp.py +195 -143
  12. certora_cli-7.10.2/certora_cli/Mutate/mutateAttribute.py → certora_cli-7.14.3/certora_cli/Mutate/mutateAttributes.py +32 -55
  13. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Mutate/mutateConstants.py +7 -3
  14. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Mutate/mutateValidate.py +18 -17
  15. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Shared/certoraAttrUtil.py +74 -25
  16. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Shared/certoraUtils.py +17 -58
  17. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Shared/certoraValidateFuncs.py +30 -22
  18. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/certoraRun.py +39 -22
  19. {certora_cli-7.10.2 → certora_cli-7.14.3/certora_cli.egg-info}/PKG-INFO +2 -2
  20. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli.egg-info/SOURCES.txt +2 -2
  21. certora_cli-7.14.3/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
  22. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_jars/Typechecker.jar +0 -0
  23. {certora_cli-7.10.2 → certora_cli-7.14.3}/setup.py +2 -2
  24. certora_cli-7.10.2/README.md +0 -1
  25. certora_cli-7.10.2/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
  26. {certora_cli-7.10.2 → certora_cli-7.14.3}/LICENSE +0 -0
  27. {certora_cli-7.10.2 → certora_cli-7.14.3}/MANIFEST.in +0 -0
  28. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_bins/__init__.py +0 -0
  29. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py +0 -0
  30. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py +0 -0
  31. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py +0 -0
  32. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSolBased.py +0 -0
  33. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py +0 -0
  34. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/CompilerCollectorYul.py +0 -0
  35. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/Compiler/__init__.py +0 -0
  36. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/__init__.py +0 -0
  37. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraBuildCacheManager.py +0 -0
  38. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraCompilerParameters.py +0 -0
  39. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraContextClass.py +0 -0
  40. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraContractFuncs.py +0 -0
  41. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraExtensionInfo.py +0 -0
  42. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraJobList.py +0 -0
  43. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraMiniSpecParser.py +0 -0
  44. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraNodeFilters.py +0 -0
  45. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraType.py +0 -0
  46. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EVMVerifier/certoraVerifyGenerator.py +0 -0
  47. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
  48. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
  49. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
  50. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
  51. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
  52. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/__init__.py +0 -0
  53. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
  54. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Mutate/__init__.py +0 -0
  55. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Mutate/mutateUtil.py +0 -0
  56. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Shared/ExpectedComparator.py +0 -0
  57. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Shared/__init__.py +0 -0
  58. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/Shared/certoraLogging.py +0 -0
  59. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/__init__.py +0 -0
  60. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/certoraEqCheck.py +0 -0
  61. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli/certoraMutate.py +0 -0
  62. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli.egg-info/dependency_links.txt +0 -0
  63. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli.egg-info/entry_points.txt +0 -0
  64. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli.egg-info/requires.txt +0 -0
  65. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_cli.egg-info/top_level.txt +0 -0
  66. {certora_cli-7.10.2 → certora_cli-7.14.3}/certora_jars/__init__.py +0 -0
  67. {certora_cli-7.10.2 → certora_cli-7.14.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: certora-cli
3
- Version: 7.10.2
3
+ Version: 7.14.3
4
4
  Summary: Runner for the Certora Prover
5
5
  Home-page: https://pypi.org/project/certora-cli
6
6
  Author: Certora
@@ -21,4 +21,4 @@ Requires-Dist: tabulate
21
21
  Requires-Dist: tqdm
22
22
  Requires-Dist: StrEnum
23
23
 
24
- Commit 849f06a. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
24
+ Commit 59b7da5. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -0,0 +1 @@
1
+ Commit 59b7da5. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -31,11 +31,12 @@ from EVMVerifier.certoraNodeFilters import NodeFilters as Nf
31
31
  import EVMVerifier.certoraType as CT
32
32
 
33
33
  from EVMVerifier.certoraContextClass import CertoraContext
34
- import EVMVerifier.certoraContextAttribute as Attr
34
+ import EVMVerifier.certoraContextAttributes as Attrs
35
35
  from Shared import certoraValidateFuncs as Vf
36
36
  from EVMVerifier import certoraContextValidator as Cv
37
- import EVMVerifier.certoraContext as Ctx
38
37
  from Shared import certoraUtils as Util
38
+ import EVMVerifier.certoraContext as Ctx
39
+
39
40
 
40
41
  BUILD_IS_LIBRARY = False
41
42
  AUTO_FINDER_PREFIX = "autoFinder_"
@@ -2804,7 +2805,8 @@ class CertoraBuildGenerator:
2804
2805
  errs.append(e)
2805
2806
  if len(errs) > 0:
2806
2807
  raise Util.CertoraUserInputError(
2807
- f"Some methods as specified via the `method` flag could not be found!{Util.NEW_LINE}{Util.NEW_LINE.join(str(e) for e in errs)}"
2808
+ "Some methods as specified via the `method` flag could not be found!"
2809
+ f"{Util.NEW_LINE}{Util.NEW_LINE.join(str(e) for e in errs)}"
2808
2810
  )
2809
2811
 
2810
2812
  # Build sources tree
@@ -3486,8 +3488,8 @@ class CertoraBuildGenerator:
3486
3488
  if context.yul_abi:
3487
3489
  sources.add(Path(context.yul_abi))
3488
3490
 
3489
- if hasattr(context,
3490
- Attr.ContextAttribute.PROVER_RESOURCE_FILES.get_conf_key()) and context.prover_resource_files:
3491
+ if hasattr(context, Attrs.EvmProverAttributes.PROVER_RESOURCE_FILES.get_conf_key()) \
3492
+ and context.prover_resource_files:
3491
3493
  for value in context.prover_resource_files:
3492
3494
  _, file_path = value.split(':')
3493
3495
  add_to_sources(Path(file_path))
@@ -3657,10 +3659,7 @@ def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> No
3657
3659
  build_logger.warning(
3658
3660
  "Local checks of CVL specification files disabled. It is recommended to enable the checks.")
3659
3661
  else:
3660
- typechecker_arguments = Ctx.get_typechecker_arguments(context)
3661
- spec_check_exit_code = Util.run_local_spec_check(False, typechecker_arguments)
3662
- if spec_check_exit_code != 0:
3663
- raise Util.CertoraUserInputError("CVL specification syntax check failed")
3662
+ Ctx.run_local_spec_check(False, context)
3664
3663
 
3665
3664
  certora_build_cache_manager = CertoraBuildCacheManager()
3666
3665
 
@@ -18,7 +18,7 @@ from EVMVerifier.certoraJobList import JobList
18
18
  from EVMVerifier.certoraExtensionInfo import ExtensionInfoWriter
19
19
  from EVMVerifier.certoraContextClass import CertoraContext
20
20
  from Shared import certoraUtils as Util
21
- import EVMVerifier.certoraContextAttribute as Attr
21
+ import EVMVerifier.certoraContextAttributes as Attrs
22
22
  import EVMVerifier.certoraContext as Ctx
23
23
  from Shared import certoraValidateFuncs as Vf
24
24
  from Mutate import mutateUtil as MutUtil
@@ -442,7 +442,7 @@ class CloudVerification:
442
442
  self.presigned_url = ""
443
443
  self.userId = -1
444
444
  self.msg = ""
445
- self.user_defined_cache = context.user_defined_cache
445
+ self.user_defined_cache = context.user_defined_cache if Attrs.is_evm_app() else None
446
446
  self.expected_filename = context.expected_file
447
447
 
448
448
  self.set_protocol_name_and_author(context)
@@ -577,7 +577,7 @@ class CloudVerification:
577
577
 
578
578
  jar_settings = Ctx.collect_jar_args(self.context)
579
579
 
580
- if self.context.is_solana:
580
+ if Attrs.is_solana_app():
581
581
  # We need to strip "../" path component from all file paths because
582
582
  # unzip will also do that.
583
583
  solana_jar_settings = []
@@ -597,7 +597,7 @@ class CloudVerification:
597
597
  elif arg == '-solanaSummaries':
598
598
  is_file = True
599
599
  auth_data["jarSettings"] = solana_jar_settings
600
- elif self.context.is_wasm:
600
+ elif Attrs.is_wasm_app():
601
601
  # We need to strip "../" path component from all file paths because
602
602
  # unzip will also do that.
603
603
  wasm_jar_settings = []
@@ -610,7 +610,7 @@ class CloudVerification:
610
610
  auth_data["jarSettings"] = jar_settings
611
611
 
612
612
  if self.context.coinbase_mode:
613
- auth_data["jarSettings"].append(Attr.ContextAttribute.COINBASE_MODE.value.jar_flag)
613
+ auth_data["jarSettings"].append(Attrs.EvmProverAttributes.COINBASE_MODE.jar_flag)
614
614
 
615
615
  if self.context.java_args is not None:
616
616
  auth_data["javaArgs"] = self.context.java_args.strip()
@@ -623,7 +623,7 @@ class CloudVerification:
623
623
 
624
624
  auth_data["useLatestFe"] = self.context.fe_version == str(Util.FeValue.LATEST)
625
625
 
626
- if self.context.cache is not None:
626
+ if Attrs.is_evm_app() and self.context.cache is not None:
627
627
  auth_data["toolSceneCacheKey"] = self.context.cache
628
628
 
629
629
  if self.context.msg is not None:
@@ -640,7 +640,7 @@ class CloudVerification:
640
640
  if self.protocol_author:
641
641
  auth_data["protocolAuthor"] = self.protocol_author
642
642
 
643
- if self.context.verify:
643
+ if Attrs.is_evm_app() and self.context.verify:
644
644
  auth_data["primaryContract"] = self.context.verify.split(':')[0]
645
645
  cloud_logger.debug(f'authdata = {auth_data}')
646
646
 
@@ -714,7 +714,7 @@ class CloudVerification:
714
714
  # We zip the tac file itself
715
715
  result = compress_files(self.ZipFilePath, self.context.files[0],
716
716
  short_output=Ctx.is_minimal_cli_output(self.context))
717
- elif self.context.is_bytecode:
717
+ elif Attrs.is_evm_app() and self.context.is_bytecode:
718
718
  # We zip the bytecode jsons and the spec
719
719
  paths = []
720
720
  for bytecode_json in self.context.bytecode_jsons:
@@ -722,7 +722,7 @@ class CloudVerification:
722
722
  paths.append(Path(self.context.bytecode_spec))
723
723
  result = compress_files(self.ZipFilePath, *paths,
724
724
  short_output=Ctx.is_minimal_cli_output(self.context))
725
- elif self.context.is_solana:
725
+ elif Attrs.is_solana_app():
726
726
  # We zip the ELF files and the two configuration files
727
727
  jar_args = Ctx.collect_jar_args(self.context)
728
728
  paths = []
@@ -739,7 +739,7 @@ class CloudVerification:
739
739
  elif arg == '-solanaSummaries':
740
740
  is_file = True
741
741
  result = compress_files(self.ZipFilePath, *paths, short_output=Ctx.is_minimal_cli_output(self.context))
742
- elif self.context.is_wasm:
742
+ elif Attrs.is_wasm_app():
743
743
  # We zip the wat file
744
744
  paths = []
745
745
  for file in self.context.files:
@@ -16,6 +16,9 @@ from EVMVerifier.certoraContextClass import CertoraContext
16
16
  metadata_logger = logging.getLogger("metadata")
17
17
 
18
18
 
19
+ def get_main_spec(context: CertoraContext) -> Optional[str]:
20
+ return getattr(context, 'spec_file', None) or getattr(context, 'bytecode_spec', None)
21
+
19
22
  # jsonify sets as lists
20
23
  class MetadataEncoder(json.JSONEncoder):
21
24
  def default(self, obj: Any) -> Any:
@@ -128,14 +131,14 @@ def build_conf_path_relative(relative_cwd: Path, context: CertoraContext) -> Opt
128
131
  return None
129
132
 
130
133
 
131
- def collect_run_metadata(wd: Path, raw_args: List[str], raw_input_conf_dict: Dict[str, Any], context: CertoraContext) \
134
+ def collect_run_metadata(wd: Path, raw_args: List[str], context: CertoraContext) \
132
135
  -> RunMetaData:
133
136
 
134
137
  # This is a temporary hotfix to fix a bug on windows. If git does not exist on client calls to to_relative()
135
138
  # cause exception and mess up paths
136
139
  if Utils.is_windows():
137
140
  return RunMetaData(raw_args=raw_args,
138
- conf=raw_input_conf_dict,
141
+ conf=context.conf_options,
139
142
  origin="",
140
143
  revision="",
141
144
  branch="",
@@ -163,13 +166,13 @@ def collect_run_metadata(wd: Path, raw_args: List[str], raw_input_conf_dict: Dic
163
166
  cwd_relative = improvise_cwd_relative(wd)
164
167
  conf_path = build_conf_path_relative(cwd_relative, context)
165
168
  return RunMetaData(raw_args=raw_args,
166
- conf=raw_input_conf_dict,
169
+ conf=context.conf_options,
167
170
  origin="",
168
171
  revision="",
169
172
  branch="",
170
173
  cwd_relative=cwd_relative,
171
174
  dirty=True,
172
- main_spec=context.main_spec,
175
+ main_spec=get_main_spec(context),
173
176
  conf_path=conf_path,
174
177
  group_id=context.group_id)
175
178
 
@@ -198,13 +201,13 @@ def collect_run_metadata(wd: Path, raw_args: List[str], raw_input_conf_dict: Dic
198
201
 
199
202
  conf_path = build_conf_path_relative(cwd_relative, context)
200
203
  data = RunMetaData(raw_args=raw_args,
201
- conf=raw_input_conf_dict,
204
+ conf=context.conf_options,
202
205
  origin=origin,
203
206
  revision=sha,
204
207
  branch=branch_name,
205
208
  cwd_relative=cwd_relative,
206
209
  dirty=dirty,
207
- main_spec=context.main_spec,
210
+ main_spec=get_main_spec(context),
208
211
  conf_path=conf_path,
209
212
  group_id=context.group_id)
210
213
 
@@ -216,12 +219,12 @@ def collect_run_metadata(wd: Path, raw_args: List[str], raw_input_conf_dict: Dic
216
219
  cwd_relative = improvise_cwd_relative(wd)
217
220
  conf_path = build_conf_path_relative(cwd_relative, context)
218
221
  return RunMetaData(raw_args=raw_args,
219
- conf=raw_input_conf_dict,
222
+ conf=context.conf_options,
220
223
  origin="",
221
224
  revision="",
222
225
  branch="",
223
226
  cwd_relative=cwd_relative,
224
227
  dirty=True,
225
- main_spec=context.main_spec,
228
+ main_spec=get_main_spec(context),
226
229
  conf_path=conf_path,
227
230
  group_id=context.group_id)
@@ -1,10 +1,10 @@
1
1
  import json5
2
2
  import logging
3
3
  from pathlib import Path
4
- from typing import Dict, Any, Optional
4
+ from typing import Dict, Any
5
5
 
6
6
  import EVMVerifier.certoraContext as Ctx
7
- import EVMVerifier.certoraContextAttribute as Attr
7
+ import EVMVerifier.certoraContextAttributes as Attrs
8
8
  from EVMVerifier.certoraContextClass import CertoraContext
9
9
  from Shared import certoraUtils as Util
10
10
 
@@ -31,11 +31,12 @@ def current_conf_to_file(context: CertoraContext) -> Dict[str, Any]:
31
31
  4. Parsing the .conf file is simpler, as we can ignore the null case
32
32
  """
33
33
  def input_arg_with_value(k: Any, v: Any) -> Any:
34
- return v is not None and v is not False and k in Attr.all_context_keys()
35
- context_to_save = {k: v for k, v in vars(context).items() if input_arg_with_value(k, v)}
36
- all_keys = Attr.all_context_keys()
34
+ all_conf_names = Attrs.get_attribute_class().all_conf_names()
35
+ return v is not None and v is not False and k in all_conf_names
37
36
 
38
- context_to_save = dict(sorted(context_to_save.items(), key=lambda x: all_keys.index(x[0])))
37
+ context_to_save = {k: v for k, v in vars(context).items() if input_arg_with_value(k, v)}
38
+ all_conf_names = Attrs.get_attribute_class().all_conf_names()
39
+ context_to_save = dict(sorted(context_to_save.items(), key=lambda x: all_conf_names.index(x[0])))
39
40
  context_to_save.pop('build_dir', None) # build dir should not be saved, each run should define its own build_dir
40
41
 
41
42
  out_file_path = Util.get_last_conf_file()
@@ -45,16 +46,14 @@ def current_conf_to_file(context: CertoraContext) -> Dict[str, Any]:
45
46
  return context_to_save
46
47
 
47
48
 
48
- def read_from_conf_file(context: CertoraContext, conf_file_path: Optional[Path] = None) -> None:
49
+ def read_from_conf_file(context: CertoraContext) -> None:
49
50
  """
50
- Reads data from the configuration file given in the command line and adds each key to the context namespace if the
51
- key is undefined there. For more details, see the invoked method read_from_conf.
52
- @param context: A namespace containing options from the command line, if any (context.files[0] should always be a
53
- .conf file when we call this method)
54
- :param conf_file_path: Path to the conf file
51
+ If the file in the command line is a conf file, read data from the configuration file and add each key to the
52
+ context namespace if the key was not set in the command line (command line shadows conf data).
53
+ @param context: A namespace containing options from the command line
55
54
  """
56
- if not conf_file_path:
57
- conf_file_path = Path(context.files[0])
55
+
56
+ conf_file_path = Path(context.files[0])
58
57
  assert conf_file_path.suffix == ".conf", f"conf file must be of type .conf, instead got {conf_file_path}"
59
58
 
60
59
  with conf_file_path.open() as conf_file:
@@ -66,21 +65,26 @@ def read_from_conf_file(context: CertoraContext, conf_file_path: Optional[Path]
66
65
  context.conf_file = str(conf_file_path)
67
66
 
68
67
 
69
- def check_conf_content(configuration: Dict[str, Any], context: CertoraContext) -> None:
68
+ def check_conf_content(conf: Dict[str, Any], context: CertoraContext) -> None:
70
69
  """
71
70
  validating content read from the conf file
72
71
  Note: a command line definition trumps the definition in the file.
73
72
  If in the .conf file solc is 4.25 and in the command line --solc solc6.10 was given, sol6.10 will be used
74
- @param configuration: A json object in the conf file format
73
+ @param conf: A json object in the conf file format
75
74
  @param context: A namespace containing options from the command line, if any
76
75
  """
77
- for option in configuration:
76
+ for option in conf:
78
77
  if hasattr(context, option):
79
78
  val = getattr(context, option)
80
79
  if val is None or val is False:
81
- setattr(context, option, configuration[option])
80
+ setattr(context, option, conf[option])
81
+ elif option != Attrs.EvmProverAttributes.FILES.get_conf_key() and val != conf[option]:
82
+ cli_val = ' '.join(val) if isinstance(val, list) else str(val)
83
+ conf_val = ' '.join(conf[option]) if isinstance(conf[option], list) else str(conf[option])
84
+ run_logger.warning(f"Note: attribute {option} value in CLI ({cli_val}) overrides value stored in conf"
85
+ f" file ({conf_val})")
82
86
  else:
83
87
  raise Util.CertoraUserInputError(f"{option} appears in the conf file but is not a known attribute. ")
84
- if 'files' not in configuration:
88
+ if 'files' not in conf:
85
89
  raise Util.CertoraUserInputError("Mandatory 'files' attribute is missing from the configuration")
86
- context.files = configuration['files'] # Override the current .conf file
90
+ context.files = conf['files'] # Override the current .conf file
@@ -6,7 +6,7 @@ import os
6
6
  import re
7
7
  import sys
8
8
  from pathlib import Path
9
- from typing import Dict, List, Optional, Tuple, Any
9
+ from typing import Dict, List, Optional, Any
10
10
  from rich.console import Console
11
11
 
12
12
 
@@ -17,7 +17,7 @@ from EVMVerifier.certoraContextClass import CertoraContext
17
17
  from Shared import certoraUtils as Util
18
18
  from EVMVerifier.certoraConfigIO import read_from_conf_file, current_conf_to_file
19
19
  import EVMVerifier.certoraContextValidator as Cv
20
- import EVMVerifier.certoraContextAttribute as Attr
20
+ import EVMVerifier.certoraContextAttributes as Attrs
21
21
  from Shared import certoraValidateFuncs as Vf
22
22
  from Shared import certoraAttrUtil as AttrUtil
23
23
 
@@ -37,31 +37,36 @@ def escape_string(string: str) -> str:
37
37
  return f"\"{string}\""
38
38
 
39
39
 
40
- def get_attr_value(context: CertoraContext, attr: Attr.ContextAttribute) -> Any:
40
+ def get_attr_value(context: CertoraContext, attr: AttrUtil.AttributeDefinition) -> Any:
41
41
  conf_key = attr.get_conf_key()
42
42
  return getattr(context, conf_key, None)
43
43
 
44
44
 
45
- def collect_args_with_jar_flags(context: CertoraContext) -> List[Attr.ContextAttribute]:
46
- return [arg for arg in Attr.ContextAttribute if get_attr_value(context, arg) and arg.value.jar_flag]
45
+ def collect_args_with_jar_flags(context: CertoraContext) -> List[AttrUtil.AttributeDefinition]:
46
+ attribute_list = Attrs.get_attribute_class().attribute_list()
47
+ return [attr for attr in attribute_list if get_attr_value(context, attr) and attr.jar_flag]
47
48
 
48
49
 
49
- def collect_args_build_cache_affecting(context: CertoraContext) -> List[Attr.ContextAttribute]:
50
- return [arg for arg in Attr.ContextAttribute if get_attr_value(context, arg) and arg.value.affects_build_cache_key]
50
+ def collect_args_build_cache_affecting(context: CertoraContext) -> List[AttrUtil.AttributeDefinition]:
51
+ attribute_list = Attrs.get_attribute_class().attribute_list()
52
+ return [attr for attr in attribute_list if get_attr_value(context, attr) and
53
+ attr.affects_build_cache_key]
51
54
 
52
55
 
53
- def collect_args_build_cache_disabling(context: CertoraContext) -> List[Attr.ContextAttribute]:
54
- return [arg for arg in Attr.ContextAttribute if get_attr_value(context, arg) and arg.value.disables_build_cache]
56
+ def collect_args_build_cache_disabling(context: CertoraContext) -> List[AttrUtil.AttributeDefinition]:
57
+ attribute_list = Attrs.get_attribute_class().attribute_list()
58
+ return [attr for attr in attribute_list if get_attr_value(context, attr) and
59
+ attr.disables_build_cache]
55
60
 
56
61
 
57
- def create_jar_flag_list(context: CertoraContext, args: List[Attr.ContextAttribute]) -> List[str]:
62
+ def create_jar_flag_list(context: CertoraContext, args: List[AttrUtil.AttributeDefinition]) -> List[str]:
58
63
  return_list = []
59
64
  for arg in args:
60
65
  attr = get_attr_value(context, arg)
61
- jar_flag = arg.value.jar_flag
66
+ jar_flag = arg.jar_flag
62
67
  assert jar_flag is not None
63
68
  return_list.append(jar_flag)
64
- if not arg.value.jar_no_value:
69
+ if not arg.jar_no_value:
65
70
  if isinstance(attr, list):
66
71
  return_list.append(','.join(attr))
67
72
  elif isinstance(attr, bool):
@@ -82,7 +87,7 @@ def collect_jar_args(context: CertoraContext) -> List[str]:
82
87
  """
83
88
  return_list = create_jar_flag_list(context, collect_args_with_jar_flags(context))
84
89
 
85
- prover_args_values = getattr(context, Attr.ContextAttribute.PROVER_ARGS.get_conf_key(), None)
90
+ prover_args_values = getattr(context, Attrs.EvmProverAttributes.PROVER_ARGS.get_conf_key(), None)
86
91
  if prover_args_values:
87
92
  for value in prover_args_values:
88
93
  return_list.extend(value.split())
@@ -93,7 +98,7 @@ def collect_jar_args(context: CertoraContext) -> List[str]:
93
98
  # will permit Solidity function calls in CVL quantifier bodies. We prioritize the type checker jar
94
99
  # argument "typechecker_args" in the conf files and if it contains the flag "-allowSolidityQuantifierCalls true"
95
100
  # we append the prover argument version to the list of prover jar arguments.
96
- type_checker_values = getattr(context, Attr.ContextAttribute.TYPECHECKER_ARGS.get_conf_key(), None)
101
+ type_checker_values = getattr(context, Attrs.EvmProverAttributes.TYPECHECKER_ARGS.get_conf_key(), None)
97
102
  if type_checker_values:
98
103
  for value in type_checker_values:
99
104
  values = value.split()
@@ -102,24 +107,22 @@ def collect_jar_args(context: CertoraContext) -> List[str]:
102
107
  return return_list
103
108
 
104
109
 
105
- def get_typechecker_arguments(context: CertoraContext, typechecker_args: Optional[List[str]] = None) -> str:
110
+ def get_typechecker_arguments(context: CertoraContext) -> List[str]:
106
111
  """
107
112
  Assembles a string of all the command-line options the typechecker cares about
108
113
  @param context: The context
109
- @param typechecker_args: A dict of additional options (as provided via "typechecker_args" in a conf file)
110
114
  @return: A string with all the options in the format the typechecker understands.
111
115
  """
112
- typecheck_cmd = ""
113
- if typechecker_args:
114
- typecheck_cmd = f"{typecheck_cmd} {' '.join(typechecker_args)}"
116
+ args = []
117
+ if context.typechecker_args:
118
+ args += context.typechecker_args
115
119
 
116
- relevant_args = filter(lambda arg: get_attr_value(context, arg),
117
- [Attr.ContextAttribute.RULE,
118
- Attr.ContextAttribute.EXCLUDE_RULE,
119
- Attr.ContextAttribute.FOUNDRY_TESTS_MODE])
120
- args_list = create_jar_flag_list(context, list(relevant_args))
120
+ relevant_attrs = filter(lambda arg: get_attr_value(context, arg),
121
+ [Attrs.EvmProverAttributes.RULE, Attrs.EvmProverAttributes.EXCLUDE_RULE,
122
+ Attrs.EvmProverAttributes.FOUNDRY_TESTS_MODE])
123
+ args += create_jar_flag_list(context, list(relevant_attrs))
121
124
 
122
- return f"{typecheck_cmd} {' '.join(args_list)}"
125
+ return args
123
126
 
124
127
 
125
128
  def get_local_run_cmd(context: CertoraContext) -> str:
@@ -129,9 +132,9 @@ def get_local_run_cmd(context: CertoraContext) -> str:
129
132
  @return: A command for running the prover locally
130
133
  """
131
134
  run_args = []
132
- if context.is_tac or context.is_solana or context.is_wasm:
135
+ if context.is_tac or Attrs.is_solana_app() or Attrs.is_wasm_app():
133
136
  run_args.append(context.files[0])
134
- if context.cache is not None:
137
+ if Attrs.is_evm_app() and context.cache is not None:
135
138
  run_args.extend(['-cache', context.cache])
136
139
 
137
140
  jar_args = collect_jar_args(context)
@@ -163,7 +166,7 @@ def get_local_run_cmd(context: CertoraContext) -> str:
163
166
  return cmd
164
167
 
165
168
 
166
- class ProverParser(AttrUtil.CertoraArgumentParser):
169
+ class ProverParser(AttrUtil.ContextAttributeParser):
167
170
  def __init__(self, *args: Any, **kwargs: Any) -> None:
168
171
  super().__init__(*args, **kwargs)
169
172
 
@@ -184,13 +187,12 @@ class ProverParser(AttrUtil.CertoraArgumentParser):
184
187
  console.print("3. list (L): gets multiple strings as a value, flags may also appear multiple times")
185
188
  console.print("4. map (M): collection of key, value pairs\n\n")
186
189
 
187
- Attr.ContextAttribute.print_attr_help()
190
+ Attrs.EvmProverAttributes.print_attr_help()
188
191
  console.print("\n\nYou can find detailed documentation of the supported flags here: "
189
192
  f"{Util.print_rich_link(CLI_DOCUMENTATION_URL)}\n\n")
190
193
 
191
194
  return ''
192
195
 
193
-
194
196
  def __get_argparser() -> argparse.ArgumentParser:
195
197
  def formatter(prog: Any) -> argparse.HelpFormatter:
196
198
  return argparse.HelpFormatter(prog, max_help_position=100, width=200)
@@ -200,19 +202,15 @@ def __get_argparser() -> argparse.ArgumentParser:
200
202
  epilog=" -*-*-* You can find detailed documentation of the supported options in "
201
203
  f"{CLI_DOCUMENTATION_URL} -*-*-*")
202
204
 
203
- args = list(Attr.ContextAttribute)
204
-
205
- for arg in args:
205
+ for arg in Attrs.get_attribute_class().attribute_list():
206
206
  flag = arg.get_flag()
207
- parser.add_argument(flag, help=arg.value.help_msg, **arg.value.argparse_args)
207
+ parser.add_argument(flag, help=arg.help_msg, **arg.argparse_args)
208
208
  return parser
209
209
 
210
210
 
211
- def get_args(args_list: Optional[List[str]] = None) -> Tuple[CertoraContext, Dict[str, Any]]:
211
+ def get_args(args_list: Optional[List[str]] = None) -> CertoraContext:
212
212
  """
213
213
  Compiles an argparse.Namespace from the given list of command line arguments.
214
- Additionally returns the prettified dictionary version of the input arguments as generated by current_conf_to_file
215
- and printed to the .conf file in .lastConfs.
216
214
 
217
215
  Why do we handle --version before argparse?
218
216
  Because on some platforms, mainly CI tests, we cannot fetch the installed distribution package version of
@@ -220,6 +218,8 @@ def get_args(args_list: Optional[List[str]] = None) -> Tuple[CertoraContext, Dic
220
218
  We do it pre-argparse, because we do not care bout the input validity of anything else if we have a --version flag
221
219
  """
222
220
 
221
+ if not Attrs.ATTRIBUTES_CLASS:
222
+ Attrs.set_attribute_class(Attrs.EvmProverAttributes) # for scripts that call get_args directly
223
223
  if args_list is None:
224
224
  args_list = sys.argv
225
225
 
@@ -249,20 +249,30 @@ def get_args(args_list: Optional[List[str]] = None) -> Tuple[CertoraContext, Dic
249
249
  if context.is_conf:
250
250
  read_from_conf_file(context)
251
251
 
252
- Cv.check_mode_of_operation(context) # Here boolean run characteristics are set
252
+ context.local = Util.is_local(context)
253
+ context.is_tac = context.files and context.files[0].endswith('.tac')
254
+ context.is_vyper = context.files and context.files[0].endswith('.vy')
255
+
256
+ if Attrs.is_evm_app():
257
+ Cv.check_mode_of_operation(context) # Here boolean run characteristics are set
253
258
 
254
259
  validator = Cv.CertoraContextValidator(context)
255
260
  validator.validate()
256
- current_build_directory = Util.get_build_dir()
257
- if context.build_dir is not None and current_build_directory != context.build_dir:
258
- Util.reset_certora_internal_dir(context.build_dir)
259
- os.rename(current_build_directory, context.build_dir)
261
+ if Attrs.is_evm_app():
262
+ current_build_directory = Util.get_build_dir()
263
+ if context.build_dir is not None and current_build_directory != context.build_dir:
264
+ Util.reset_certora_internal_dir(context.build_dir)
265
+ os.rename(current_build_directory, context.build_dir)
260
266
 
261
267
  # Store current options (including the ones read from .conf file)
262
- conf_options = current_conf_to_file(context)
268
+ context.conf_options = current_conf_to_file(context)
269
+
270
+ if context.java_args is not None:
271
+ context.java_args = ' '.join(context.java_args).replace('"', '').replace("'", '')
263
272
 
264
- validator.check_args_post_argparse()
265
- setup_cache(context) # Here context.cache, context.user_defined_cache are set
273
+ if Attrs.is_evm_app():
274
+ validator.check_args_post_argparse()
275
+ setup_cache(context) # Here context.cache, context.user_defined_cache are set
266
276
 
267
277
  # Setup defaults (defaults are not recorded in conf file)
268
278
  context.expected_file = context.expected_file or "expected.json"
@@ -273,7 +283,7 @@ def get_args(args_list: Optional[List[str]] = None) -> Tuple[CertoraContext, Dic
273
283
 
274
284
  if context.test == str(Util.TestValue.CHECK_ARGS):
275
285
  raise Util.TestResultsReady(context)
276
- return context, conf_options
286
+ return context
277
287
 
278
288
 
279
289
  def get_client_version() -> str:
@@ -340,7 +350,8 @@ def format_input(context: CertoraContext) -> None:
340
350
  :param context: Namespace containing all command line arguments, generated by get_args()
341
351
  """
342
352
  flatten_arg_lists(context)
343
- __dedup_link(context)
353
+ if Attrs.is_evm_app():
354
+ __dedup_link(context)
344
355
 
345
356
 
346
357
  def flatten_arg_lists(context: CertoraContext) -> None:
@@ -364,7 +375,8 @@ def flatten_arg_lists(context: CertoraContext) -> None:
364
375
 
365
376
  def __dedup_link(context: CertoraContext) -> None:
366
377
  try:
367
- context.link = list(set(context.link))
378
+ if hasattr(context, 'link'):
379
+ context.link = list(set(context.link))
368
380
  except TypeError:
369
381
  pass
370
382
 
@@ -433,8 +445,7 @@ def handle_flags_in_args(args: List[str]) -> None:
433
445
  Will all be converted to " -d"
434
446
 
435
447
  """
436
-
437
- all_flags = list(map(lambda member: member.get_flag(), Attr.ContextAttribute))
448
+ all_flags = list(map(lambda member: member.get_flag(), Attrs.get_attribute_class().attribute_list()))
438
449
 
439
450
  def surrounded(string: str, char: str) -> bool:
440
451
  if len(string) < 2:
@@ -450,7 +461,7 @@ def handle_flags_in_args(args: List[str]) -> None:
450
461
  arg = arg[1:-1]
451
462
  else:
452
463
  break
453
- if len(arg) > 0 and arg[0] == '-' and (args[index - 1] == Attr.ContextAttribute.JAVA_ARGS.get_flag()):
464
+ if len(arg) > 0 and arg[0] == '-' and (args[index - 1] == Attrs.EvmProverAttributes.JAVA_ARGS.get_flag()):
454
465
  arg = f" {arg}"
455
466
  if arg != args[index]:
456
467
  args[index] = arg
@@ -483,3 +494,48 @@ def __rename_key(context: CertoraContext, old_key: str, new_key: str) -> None:
483
494
  value = getattr(context, old_key)
484
495
  setattr(context, new_key, value)
485
496
  context.delete_key(old_key)
497
+
498
+
499
+ def run_typechecker(typechecker_name: str, with_typechecking: bool, args: List[str]) -> None:
500
+ """
501
+ Runs a spec typechecker or syntax checker
502
+ @param typechecker_name - the name of the jar that we should run for running typechecking
503
+ @param with_typechecking - True if we want full typechecking including build (Solidity outputs) file,
504
+ False if we run only the leaner syntax checking.
505
+ @param args: A list of strings of additional arguments to the typechecker jar.
506
+
507
+ """
508
+ # Find path to typechecker jar
509
+ path_to_typechecker = Util.find_jar(typechecker_name)
510
+
511
+ context_logger.debug(f"Path to typechecker is {path_to_typechecker}")
512
+ # if typechecker jar does not exist, we just skip this step
513
+ if not path_to_typechecker.is_file():
514
+ raise Util.CertoraUserInputError(f"Could not run type checker locally: file not found {path_to_typechecker}")
515
+
516
+ # args to typechecker
517
+ typecheck_cmd = f"java -jar {path_to_typechecker} " \
518
+ f'-buildDirectory "{Util.get_build_dir().resolve()}" ' \
519
+ f"{'-typeCheck ' if with_typechecking else ''}" \
520
+ f"{' '.join(args)}"
521
+
522
+ exit_code = Util.run_jar_cmd(typecheck_cmd, False, custom_error_message="Failed to compile spec files:",
523
+ logger_topic="type_check")
524
+ if exit_code != 0:
525
+ raise Util.CertoraUserInputError("CVL specification syntax and type check failed")
526
+
527
+
528
+ def run_local_spec_check(with_typechecking: bool, context: CertoraContext) -> None:
529
+ """
530
+ Runs the local type checker in one of two modes: (1) syntax only,
531
+ and (2) including full typechecking after building the contracts
532
+ """
533
+
534
+ if context.disable_local_typechecking or Util.is_ci_or_git_action():
535
+ return
536
+ args = get_typechecker_arguments(context)
537
+ if Util.is_java_installed():
538
+ run_typechecker("Typechecker.jar", with_typechecking, args)
539
+ else:
540
+ raise Util.CertoraUserInputError("Cannot run local checks because of missing a suitable java installtion. "
541
+ "To skip local checks run with the --disable_local_typechecking flag")