certora-cli-alpha-master 20250520.21.30.33372__tar.gz → 20250521.12.50.829403__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 (87) hide show
  1. {certora_cli_alpha_master-20250520.21.30.33372/certora_cli_alpha_master.egg-info → certora_cli_alpha_master-20250521.12.50.829403}/PKG-INFO +2 -2
  2. certora_cli_alpha_master-20250521.12.50.829403/README.md +1 -0
  3. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Mutate/mutateApp.py +7 -2
  4. certora_cli_alpha_master-20250521.12.50.829403/certora_cli/Shared/proverCommon.py +300 -0
  5. certora_cli_alpha_master-20250521.12.50.829403/certora_cli/Shared/rustProverCommon.py +62 -0
  6. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/certoraEVMProver.py +2 -1
  7. certora_cli_alpha_master-20250521.12.50.829403/certora_cli/certoraRanger.py +39 -0
  8. certora_cli_alpha_master-20250521.12.50.829403/certora_cli/certoraRun.py +216 -0
  9. certora_cli_alpha_master-20250521.12.50.829403/certora_cli/certoraSolanaProver.py +98 -0
  10. certora_cli_alpha_master-20250521.12.50.829403/certora_cli/certoraSorobanProver.py +92 -0
  11. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403/certora_cli_alpha_master.egg-info}/PKG-INFO +2 -2
  12. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli_alpha_master.egg-info/SOURCES.txt +2 -0
  13. certora_cli_alpha_master-20250521.12.50.829403/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
  14. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_jars/Typechecker.jar +0 -0
  15. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/setup.py +2 -2
  16. certora_cli_alpha_master-20250520.21.30.33372/README.md +0 -1
  17. certora_cli_alpha_master-20250520.21.30.33372/certora_cli/certoraRanger.py +0 -71
  18. certora_cli_alpha_master-20250520.21.30.33372/certora_cli/certoraRun.py +0 -320
  19. certora_cli_alpha_master-20250520.21.30.33372/certora_cli/certoraSolanaProver.py +0 -193
  20. certora_cli_alpha_master-20250520.21.30.33372/certora_cli/certoraSorobanProver.py +0 -285
  21. certora_cli_alpha_master-20250520.21.30.33372/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
  22. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/LICENSE +0 -0
  23. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/MANIFEST.in +0 -0
  24. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_bins/__init__.py +0 -0
  25. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/CompilerCollector.py +0 -0
  26. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/CompilerCollectorFactory.py +0 -0
  27. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/CompilerCollectorSol.py +0 -0
  28. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/CompilerCollectorSolBased.py +0 -0
  29. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/CompilerCollectorVy.py +0 -0
  30. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/CompilerCollectorYul.py +0 -0
  31. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/Compiler/__init__.py +0 -0
  32. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/__init__.py +0 -0
  33. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraBuild.py +0 -0
  34. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraBuildCacheManager.py +0 -0
  35. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraBuildDataClasses.py +0 -0
  36. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraBuildRust.py +0 -0
  37. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraCloudIO.py +0 -0
  38. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraCollectConfigurationLayout.py +0 -0
  39. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraCollectRunMetadata.py +0 -0
  40. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraCompilerParameters.py +0 -0
  41. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraConfigIO.py +0 -0
  42. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraContext.py +0 -0
  43. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraContextAttributes.py +0 -0
  44. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraContextClass.py +0 -0
  45. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraContextValidator.py +0 -0
  46. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraContractFuncs.py +0 -0
  47. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraExtensionInfo.py +0 -0
  48. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraJobList.py +0 -0
  49. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraMiniSpecParser.py +0 -0
  50. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraNodeFilters.py +0 -0
  51. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraParseBuildScript.py +0 -0
  52. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraProjectScanner.py +0 -0
  53. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraSourceFinders.py +0 -0
  54. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraType.py +0 -0
  55. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/certoraVerifyGenerator.py +0 -0
  56. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/erc7201.py +0 -0
  57. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/splitRules.py +0 -0
  58. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/CertoraProver/storageExtension.py +0 -0
  59. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
  60. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
  61. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
  62. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
  63. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
  64. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/__init__.py +0 -0
  65. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
  66. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
  67. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Mutate/__init__.py +0 -0
  68. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Mutate/mutateAttributes.py +0 -0
  69. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Mutate/mutateConstants.py +0 -0
  70. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Mutate/mutateUtil.py +0 -0
  71. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Mutate/mutateValidate.py +0 -0
  72. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Shared/ExpectedComparator.py +0 -0
  73. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Shared/__init__.py +0 -0
  74. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Shared/certoraAttrUtil.py +0 -0
  75. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Shared/certoraLogging.py +0 -0
  76. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Shared/certoraUtils.py +0 -0
  77. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/Shared/certoraValidateFuncs.py +0 -0
  78. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/__init__.py +0 -0
  79. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/certoraEqCheck.py +0 -0
  80. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/certoraMutate.py +0 -0
  81. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli/rustMutator.py +0 -0
  82. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli_alpha_master.egg-info/dependency_links.txt +0 -0
  83. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli_alpha_master.egg-info/entry_points.txt +0 -0
  84. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli_alpha_master.egg-info/requires.txt +0 -0
  85. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_cli_alpha_master.egg-info/top_level.txt +0 -0
  86. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/certora_jars/__init__.py +0 -0
  87. {certora_cli_alpha_master-20250520.21.30.33372 → certora_cli_alpha_master-20250521.12.50.829403}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: certora-cli-alpha-master
3
- Version: 20250520.21.30.33372
3
+ Version: 20250521.12.50.829403
4
4
  Summary: Runner for the Certora Prover
5
5
  Home-page: https://pypi.org/project/certora-cli-alpha-master
6
6
  Author: Certora
@@ -37,4 +37,4 @@ Dynamic: requires-dist
37
37
  Dynamic: requires-python
38
38
  Dynamic: summary
39
39
 
40
- Commit 0b54154. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
40
+ Commit 0cdebd6. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -0,0 +1 @@
1
+ Commit 0cdebd6. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
@@ -44,7 +44,9 @@ from CertoraProver.certoraContextValidator import KEY_ENV_VAR
44
44
  from Mutate import mutateConstants as MConstants
45
45
  from Shared import certoraUtils as Util
46
46
  from Shared.certoraLogging import LoggingManager
47
- from certoraRun import run_certora, CertoraRunResult, CertoraFoundViolations
47
+ from certoraRun import run_certora
48
+ from Shared.proverCommon import CertoraRunResult, CertoraFoundViolations
49
+ from certoraSorobanProver import run_soroban_prover
48
50
  from Shared import certoraValidateFuncs as Vf
49
51
  from CertoraProver.Compiler.CompilerCollectorFactory import get_relevant_compiler
50
52
  from Mutate import mutateUtil as MutUtil
@@ -1416,7 +1418,10 @@ class MutateApp:
1416
1418
  certora_args.extend(["--disable_local_typechecking"])
1417
1419
  mutation_logger.debug(f"Running the Prover: {certora_args}")
1418
1420
  try:
1419
- certora_run_result = run_certora(certora_args)
1421
+ if self.is_soroban_run():
1422
+ certora_run_result = run_soroban_prover(certora_args)
1423
+ else:
1424
+ certora_run_result = run_certora(certora_args)
1420
1425
  except CertoraFoundViolations as e:
1421
1426
  assert e.results, "expect e.results not to be None"
1422
1427
  certora_run_result = e.results
@@ -0,0 +1,300 @@
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
+ """
17
+ Shared helpers for certoraRun entry points (Solana & Soroban & EVM).
18
+
19
+ Placing the context_build environment preparation logic and verification helpers in one module
20
+ reduces duplication from the dedicated entry scripts.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import sys
26
+ import logging
27
+ import functools
28
+ from pathlib import Path
29
+ from dataclasses import dataclass
30
+ from rich.console import Console
31
+ from typing import List, Tuple, Type, Optional, Dict, NoReturn, Callable
32
+
33
+ scripts_dir_path = Path(__file__).parent.parent.resolve() # containing directory
34
+ sys.path.insert(0, str(scripts_dir_path))
35
+
36
+ from CertoraProver.certoraCloudIO import validate_version_and_branch
37
+ from Shared.certoraLogging import LoggingManager
38
+ from Shared import certoraUtils as Util
39
+ from Shared.certoraAttrUtil import Attributes
40
+ import CertoraProver.certoraContext as Ctx
41
+ from CertoraProver.certoraContextClass import CertoraContext
42
+ import CertoraProver.certoraContextAttributes as Attrs
43
+ from CertoraProver.certoraCollectRunMetadata import collect_run_metadata
44
+ from CertoraProver.certoraCollectConfigurationLayout import collect_configuration_layout
45
+ from CertoraProver import certoraContextValidator as Cv
46
+ from CertoraProver.certoraCloudIO import CloudVerification
47
+
48
+ log = logging.getLogger(__name__)
49
+
50
+
51
+ VIOLATIONS_EXIT_CODE = 100
52
+
53
+ @dataclass
54
+ class CertoraRunResult:
55
+ link: Optional[str] # Path to emv_dir if running locally, or the link to the job status page
56
+ is_local_link: bool
57
+ src_dir: Path
58
+ rule_report_link: Optional[str]
59
+
60
+ class CertoraFoundViolations(Exception):
61
+ def __init__(self, message: str, results: Optional[CertoraRunResult] = None) -> None:
62
+ super().__init__(message)
63
+ self.results = results
64
+
65
+ # --------------------------------------------------------------------------- #
66
+ # Setup Environment
67
+ # --------------------------------------------------------------------------- #
68
+ def build_context(args: List[str], attributes: Type[Attributes]) -> Tuple[CertoraContext, LoggingManager]:
69
+ """
70
+ Build the context for the Certora Prover.
71
+ This function is responsible for setting up the context and logging manager
72
+ for the Certora Prover. It handles the following tasks:
73
+ 1. Setting up the logging manager
74
+ 2. Parsing the command line arguments
75
+ 3. Setting up the context
76
+
77
+ Args:
78
+ args: The command line arguments to parse.
79
+ attributes: The attributes class to use for the context. (e.g., SolanaProverAttributes or SorobanProverAttributes)
80
+ Returns:
81
+ A tuple containing the CertoraContext object and the LoggingManager object.
82
+ """
83
+ Attrs.set_attribute_class(attributes)
84
+ non_str_els = [x for x in args if not isinstance(x, str)]
85
+ if non_str_els:
86
+ print(f"args for run_certora that are not strings: {non_str_els}")
87
+ exit(1)
88
+
89
+ # If we are not in debug mode, we do not want to print the traceback in case of exceptions.
90
+ if '--debug' not in args: # We check manually, because we want no traceback in argument parsing exceptions
91
+ sys.tracebacklimit = 0
92
+
93
+ # creating the default internal dir, files may be copied to user defined build directory after
94
+ # parsing the input
95
+
96
+ if not ('--help' in args or '--version' in args):
97
+ Util.reset_certora_internal_dir()
98
+ Util.safe_create_dir(Util.get_build_dir())
99
+ logging_manager = LoggingManager()
100
+
101
+ Ctx.handle_flags_in_args(args)
102
+ context = Ctx.get_args(args) # Parse arguments
103
+
104
+ assert logging_manager, "logging manager was not set"
105
+ logging_manager.set_log_level_and_format(is_quiet=Ctx.is_minimal_cli_output(context),
106
+ debug=context.debug,
107
+ debug_topics=context.debug_topics,
108
+ show_debug_topics=context.show_debug_topics)
109
+
110
+ return context, logging_manager
111
+
112
+
113
+ def collect_and_dump_metadata(context: CertoraContext) -> None:
114
+ """
115
+ Collect and validate run metadata.
116
+
117
+ Args:
118
+ context: The Certora context containing verification settings
119
+
120
+ Raises:
121
+ Util.TestResultsReady: If this is a metadata test run
122
+ """
123
+ metadata = collect_run_metadata(wd=Path.cwd(), raw_args=sys.argv, context=context)
124
+
125
+ if context.test == str(Util.TestValue.CHECK_METADATA):
126
+ raise Util.TestResultsReady(metadata)
127
+
128
+ metadata.dump()
129
+
130
+
131
+ def collect_and_dump_config_layout(context: CertoraContext) -> None:
132
+ """
133
+ Collect and dump the configuration layout.
134
+
135
+ Args:
136
+ context: The Certora context containing verification settings
137
+
138
+ Raises:
139
+ Util.TestResultsReady: If this is a configuration layout test run
140
+ """
141
+ configuration_layout = collect_configuration_layout()
142
+
143
+ if context.test == str(Util.TestValue.CHECK_CONFIG_LAYOUT):
144
+ raise Util.TestResultsReady(configuration_layout)
145
+
146
+ configuration_layout.dump()
147
+
148
+
149
+ def ensure_version_compatibility(context: CertoraContext) -> None:
150
+ if not (context.local or context.build_only or context.compilation_steps_only):
151
+ """
152
+ Before running the local type checker, we see if the current package version is compatible with
153
+ the latest. We check it before running the local type checker, because local type checking
154
+ errors could be simply a result of syntax introduced in the newest version.
155
+ The line below will raise an exception if the local version is incompatible.
156
+ """
157
+ validate_version_and_branch(context)
158
+
159
+ # --------------------------------------------------------------------------- #
160
+ # Verification helpers
161
+ # --------------------------------------------------------------------------- #
162
+
163
+ def run_local(context: CertoraContext, timings: Dict, additional_commands: Optional[List[str]] = None, compare_with_expected_file: bool = False) -> int:
164
+ """
165
+ Run the verifier locally and return its exit code (0 = success).
166
+ Args:
167
+ context: The CertoraContext object containing the configuration.
168
+ timings: A dictionary to store timing information.
169
+ additional_commands: A list of additional commands to pass to the verifier.
170
+ Returns:
171
+ An integer representing the exit code of the verifier run.
172
+ """
173
+ cmd: List[str] = Ctx.get_local_run_cmd(context)
174
+
175
+ if additional_commands:
176
+ cmd.extend(additional_commands)
177
+
178
+ print("Verifier run command:\n %s", " ".join(cmd))
179
+ rc = Util.run_jar_cmd(
180
+ cmd,
181
+ override_exit_code=compare_with_expected_file,
182
+ logger_topic="verification",
183
+ print_output=True,
184
+ )
185
+
186
+ if rc == 0:
187
+ Util.print_completion_message("Finished running verifier:")
188
+ print("\t%s", " ".join(cmd))
189
+ timings.setdefault("buildTime", 0.0) # ensure key exists
190
+ return 0
191
+
192
+ return 1
193
+
194
+
195
+ def run_remote(
196
+ context: CertoraContext,
197
+ args: List[str],
198
+ timings: Dict,
199
+ ) -> Tuple[int, Optional[CertoraRunResult]]:
200
+ """
201
+ Run verification in Certora Cloud.
202
+
203
+ Args:
204
+ context: The CertoraContext object containing the configuration.
205
+ args: The command line arguments to pass to the cloud verification.
206
+ timings: A dictionary to store timing information.
207
+ Returns:
208
+ A tuple containing the exit code (0 = success) and an optional CertoraRunResult object.
209
+ """
210
+ if context.compilation_steps_only:
211
+ return 0, CertoraRunResult(None, False, Util.get_certora_sources_dir(), None)
212
+
213
+ context.key = Cv.validate_certora_key()
214
+ cloud = CloudVerification(context, timings)
215
+
216
+ pretty_args = [f"'{a}'" if " " in a else a for a in args]
217
+
218
+ ok = cloud.cli_verify_and_report(" ".join(pretty_args), context.wait_for_results)
219
+
220
+ exit_code = 0 if ok else VIOLATIONS_EXIT_CODE
221
+ result: Optional[CertoraRunResult] = None
222
+ if cloud.statusUrl:
223
+ result = CertoraRunResult(
224
+ cloud.statusUrl,
225
+ False,
226
+ Util.get_certora_sources_dir(),
227
+ cloud.reportUrl,
228
+ )
229
+ return exit_code, result
230
+
231
+
232
+ def handle_exit(exit_code: int, return_value: Optional[CertoraRunResult]) -> Optional[CertoraRunResult]:
233
+ """
234
+ Handle the exit code of the verification run.
235
+ Args:
236
+ exit_code: The exit code of the verification run.
237
+ return_value: The CertoraRunResult object containing the results of the verification run.
238
+ Raises:
239
+ CertoraFoundViolations: If violations were found during the verification run.
240
+ Util.CertoraUserInputError: If there was an error with the user input.
241
+ Returns:
242
+ The CertoraRunResult object containing the results of the verification run.
243
+ """
244
+ if exit_code == VIOLATIONS_EXIT_CODE:
245
+ raise CertoraFoundViolations("violations were found", return_value)
246
+ if exit_code != 0:
247
+ raise Util.CertoraUserInputError(f"run_certora failed (code {exit_code})")
248
+ return return_value
249
+
250
+
251
+ # --------------------------------------------------------------------------- #
252
+ # Entry point decorator
253
+ # --------------------------------------------------------------------------- #
254
+
255
+ console = Console()
256
+
257
+ def catch_exits(fn: Callable[..., None]) -> Callable[..., NoReturn]:
258
+ """
259
+ Wrap any entry-point in a standard try/except + sys.exit logic.
260
+ The wrapped function should do its work and then return normally;
261
+ this decorator will exit(0) on success or exit(1/other) on failure.
262
+ """
263
+ @functools.wraps(fn)
264
+ def wrapper(*args, **kwargs) -> NoReturn: # type: ignore
265
+ try:
266
+ fn(*args, **kwargs)
267
+ sys.exit(0)
268
+
269
+ except KeyboardInterrupt:
270
+ console.print("[bold red]\nInterrupted by user")
271
+ sys.exit(1)
272
+
273
+ except Util.TestResultsReady:
274
+ print("reached checkpoint")
275
+ sys.exit(0)
276
+
277
+ except CertoraFoundViolations as e:
278
+ link = getattr(e.results, "rule_report_link", None)
279
+ if link:
280
+ print(f"report url: {link}")
281
+ console.print("[bold red]\nViolations were found\n")
282
+ sys.exit(1)
283
+
284
+ except Util.CertoraUserInputError as e:
285
+ if e.orig:
286
+ print(f"\n{str(e.orig).strip()}")
287
+ if e.more_info:
288
+ print(f"\n{e.more_info.strip()}")
289
+ console.print(f"[bold red]\n{e}\n")
290
+ sys.exit(1)
291
+
292
+ except Util.ExitException as e:
293
+ console.print(f"[bold red]{e}")
294
+ sys.exit(e.exit_code)
295
+
296
+ except Exception as e:
297
+ console.print(f"[bold red]{e}")
298
+ sys.exit(1)
299
+
300
+ return wrapper
@@ -0,0 +1,62 @@
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
+ """
17
+ Shared helpers for Rust-based targets (Solana & Soroban).
18
+
19
+ Placing the build logic in one module removes
20
+ duplication from the dedicated entry scripts.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import sys
26
+ from pathlib import Path
27
+
28
+ scripts_dir_path = Path(__file__).parent.parent.resolve() # containing directory
29
+ sys.path.insert(0, str(scripts_dir_path))
30
+
31
+ import time
32
+ import logging
33
+ from typing import Dict
34
+
35
+ from Shared import certoraUtils as Util
36
+
37
+ from CertoraProver.certoraContextClass import CertoraContext
38
+
39
+ from CertoraProver.certoraBuildRust import set_rust_build_directory
40
+
41
+
42
+ log = logging.getLogger(__name__)
43
+
44
+
45
+ # --------------------------------------------------------------------------- #
46
+ # Build
47
+ # --------------------------------------------------------------------------- #
48
+
49
+ def build_rust_project(context: CertoraContext, timings: Dict) -> None:
50
+ """
51
+ Compile the Rust artefact and record elapsed time in *timings*.
52
+
53
+ Args:
54
+ context: The CertoraContext object containing the configuration.
55
+ timings: A dictionary to store timing information.
56
+ """
57
+ log.debug("Build Rust target")
58
+ start = time.perf_counter()
59
+ set_rust_build_directory(context)
60
+ timings["buildTime"] = round(time.perf_counter() - start, 4)
61
+ if context.test == str(Util.TestValue.AFTER_BUILD):
62
+ raise Util.TestResultsReady(context)
@@ -22,7 +22,8 @@ scripts_dir_path = Path(__file__).parent.resolve() # containing directory
22
22
  sys.path.insert(0, str(scripts_dir_path))
23
23
 
24
24
  import CertoraProver.certoraContextAttributes as Attrs
25
- from certoraRun import run_certora, CertoraRunResult
25
+ from Shared.proverCommon import CertoraRunResult
26
+ from certoraRun import run_certora
26
27
  from typing import List, Optional
27
28
 
28
29
 
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python3
2
+ # The Certora Prover
3
+ # Copyright (C) 2025 Certora Ltd.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, version 3 of the License.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ scripts_dir_path = Path(__file__).parent.resolve() # containing directory
22
+ sys.path.insert(0, str(scripts_dir_path))
23
+
24
+ import CertoraProver.certoraContextAttributes as Attrs
25
+ from certoraRun import run_certora
26
+ from Shared.proverCommon import CertoraRunResult, catch_exits
27
+
28
+ from typing import List, Optional
29
+
30
+
31
+ def run_ranger(args: List[str]) -> Optional[CertoraRunResult]:
32
+ return run_certora(args, Attrs.RangerAttributes, prover_cmd=sys.argv[0])
33
+
34
+ @catch_exits
35
+ def entry_point() -> None:
36
+ run_ranger(sys.argv[1:])
37
+
38
+ if __name__ == '__main__':
39
+ entry_point()
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env python3
2
+ # The Certora Prover
3
+ # Copyright (C) 2025 Certora Ltd.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, version 3 of the License.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ import sys
18
+ import time
19
+ import logging
20
+ from typing import List, Optional, Type
21
+ from pathlib import Path
22
+
23
+ scripts_dir_path = Path(__file__).parent.resolve() # containing directory
24
+ sys.path.insert(0, str(scripts_dir_path))
25
+ from Shared import certoraUtils as Util
26
+
27
+ from CertoraProver.certoraCloudIO import CloudVerification, validate_version_and_branch
28
+
29
+ from CertoraProver.certoraBuild import build
30
+ from CertoraProver.certoraBuildRust import set_rust_build_directory
31
+ import CertoraProver.certoraContext as Ctx
32
+
33
+ from CertoraProver import certoraContextValidator as Cv
34
+ import CertoraProver.certoraContextAttributes as Attrs
35
+ from Shared import certoraAttrUtil as AttrUtil
36
+ from Shared.proverCommon import (
37
+ build_context,
38
+ collect_and_dump_metadata,
39
+ collect_and_dump_config_layout,
40
+ ensure_version_compatibility,
41
+ run_local,
42
+ run_remote,
43
+ CertoraRunResult,
44
+ handle_exit,
45
+ catch_exits
46
+ )
47
+ import CertoraProver.splitRules as splitRules
48
+
49
+ BUILD_SCRIPT_PATH = Path("CertoraProver/certoraBuild.py")
50
+
51
+ # logger for issues regarding the general run flow.
52
+ # Also serves as the default logger for errors originating from unexpected places.
53
+ run_logger = logging.getLogger("run")
54
+
55
+ def run_certora(args: List[str], attrs_class: Optional[Type[AttrUtil.Attributes]] = None,
56
+ prover_cmd: Optional[str] = None) -> Optional[CertoraRunResult]:
57
+ """
58
+ The main function that is responsible for the general flow of the script.
59
+ The general flow is:
60
+ 1. Parse program arguments
61
+ 2. Run the necessary steps (type checking/ build/ cloud verification/ local verification)
62
+
63
+ """
64
+ if not attrs_class:
65
+ attrs_class = Attrs.detect_application_class(args)
66
+
67
+ context, logging_manager = build_context(args, attrs_class)
68
+
69
+ if prover_cmd:
70
+ context.prover_cmd = prover_cmd
71
+
72
+ timings = {}
73
+ exit_code = 0 # The exit code of the script. 0 means success, any other number is an error.
74
+ return_value = None
75
+
76
+ # Collect and validate metadata
77
+ collect_and_dump_metadata(context)
78
+ # Collect and dump configuration layout
79
+ collect_and_dump_config_layout(context)
80
+
81
+ if Attrs.is_evm_app() and context.split_rules:
82
+ context.build_only = True
83
+ build(context)
84
+ context.build_only = False
85
+ rule_handler = splitRules.SplitRulesHandler(context)
86
+ exit_code = rule_handler.generate_runs()
87
+ CloudVerification(context).print_group_id_url()
88
+ if exit_code == 0:
89
+ print("Split rules succeeded")
90
+ else:
91
+ raise Util.ExitException("Split rules failed", exit_code)
92
+
93
+ if Attrs.is_rust_app():
94
+ set_rust_build_directory(context)
95
+
96
+ if context.local:
97
+ check_cmd = Ctx.get_local_run_cmd(context)
98
+ check_cmd_string = " ".join(check_cmd)
99
+ print(f"Verifier run command:\n {check_cmd_string}", flush=True)
100
+
101
+ compare_with_tool_output = False
102
+ run_result = Util.run_jar_cmd(check_cmd, compare_with_tool_output, logger_topic="verification",
103
+ print_output=True)
104
+ # For solana and wasm, we don't check types so build time is zero.
105
+ timings["buildTime"] = 0.0
106
+ if run_result != 0:
107
+ exit_code = 1
108
+ else:
109
+ Util.print_completion_message("Finished running verifier:")
110
+ print(f"\t{check_cmd_string}")
111
+ else:
112
+ validate_version_and_branch(context)
113
+ context.key = Cv.validate_certora_key()
114
+ cloud_verifier = CloudVerification(context, timings)
115
+ # Wrap strings with space with ' so it can be copied and pasted to shell
116
+ pretty_args = [f"'{arg}'" if ' ' in arg else arg for arg in args]
117
+ cl_args = ' '.join(pretty_args)
118
+ logging_manager.remove_debug_logger()
119
+ result = cloud_verifier.cli_verify_and_report(cl_args, context.wait_for_results)
120
+ if cloud_verifier.statusUrl:
121
+ return_value = CertoraRunResult(cloud_verifier.statusUrl, False,
122
+ Util.get_certora_sources_dir(), cloud_verifier.reportUrl)
123
+ if not result:
124
+ exit_code = 1
125
+ else:
126
+
127
+ # Version validation
128
+ ensure_version_compatibility(context)
129
+
130
+ # When a TAC file is provided, no build arguments will be processed
131
+ if not context.is_tac:
132
+ run_logger.debug(f"There is no TAC file. Going to script {BUILD_SCRIPT_PATH} to main_with_args()")
133
+ build_start = time.perf_counter()
134
+
135
+ # If we are not in CI, we also check the spec for Syntax errors.
136
+ build(context)
137
+ build_end = time.perf_counter()
138
+
139
+ timings["buildTime"] = round(build_end - build_start, 4)
140
+ if context.test == str(Util.TestValue.AFTER_BUILD):
141
+ raise Util.TestResultsReady(context)
142
+
143
+ if context.build_only:
144
+ return return_value
145
+
146
+ # either we skipped building (TAC MODE) or build succeeded
147
+ if context.local:
148
+ compare_with_expected_file = Path(context.expected_file).exists()
149
+
150
+ run_result = run_local(context, timings, compare_with_expected_file=compare_with_expected_file)
151
+ emv_dir = latest_emv_dir()
152
+ return_value = CertoraRunResult(str(emv_dir) if emv_dir else None, True,
153
+ Util.get_certora_sources_dir(), None)
154
+ if run_result != 0:
155
+ exit_code = run_result
156
+ elif compare_with_expected_file:
157
+ print("Comparing tool output to the expected output:")
158
+ output_path = context.tool_output or (
159
+ 'tmpOutput.json' if emv_dir is None else
160
+ str(emv_dir / 'Reports/output.json')
161
+ )
162
+ result = Util.check_results_from_file(output_path, context.expected_file)
163
+ if not result:
164
+ exit_code = 1
165
+ else: # Remote run
166
+ # Syntax checking and typechecking
167
+ if Cv.mode_has_spec_file(context):
168
+ if context.disable_local_typechecking:
169
+ run_logger.warning(
170
+ "Local checks of CVL specification files disabled. It is recommended to enable "
171
+ "the checks.")
172
+ else:
173
+ typechecking_start = time.perf_counter()
174
+ Ctx.run_local_spec_check(True, context)
175
+ typechecking_end = time.perf_counter()
176
+ timings['typecheckingTime'] = round(typechecking_end - typechecking_start, 4)
177
+
178
+ # Remove debug logger and run remote verification
179
+ logging_manager.remove_debug_logger()
180
+ exit_code, return_value = run_remote(context, args, timings)
181
+
182
+ # Handle exit codes and return
183
+ return handle_exit(exit_code, return_value)
184
+
185
+
186
+ def latest_emv_dir() -> Optional[Path]:
187
+ """
188
+ Returns the latest emv-... directory.
189
+ This is known to be highly unreliable _unless_ we know that in the current work dir only one jar
190
+ is invoked every time, and that we do not pass arguments to the jar that change the output directory.
191
+ The current use case is for the local-and-sync'd dev-mode for mutation testing.
192
+ """
193
+ cwd = Path.cwd()
194
+ candidates = list(cwd.glob(r"emv-[0-9]*-certora-*"))
195
+ max = None
196
+ max_no = -1
197
+ for candidate in candidates:
198
+ if candidate.is_dir():
199
+ index = int(str(candidate.stem).split("-")[1])
200
+ if index > max_no:
201
+ max = candidate
202
+ max_no = index
203
+ return max
204
+
205
+
206
+ @catch_exits
207
+ def entry_point() -> None:
208
+ """
209
+ This function is the entry point of the certora_cli customer-facing package, as well as this script.
210
+ It is important this function gets no arguments!
211
+ """
212
+ run_certora(sys.argv[1:], prover_cmd=sys.argv[0])
213
+
214
+
215
+ if __name__ == '__main__':
216
+ entry_point()