certora-cli 7.20.3__tar.gz → 7.22.2__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-7.20.3/certora_cli.egg-info → certora_cli-7.22.2}/PKG-INFO +4 -2
- certora_cli-7.22.2/README.md +1 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraBuild.py +113 -98
- certora_cli-7.22.2/certora_cli/EVMVerifier/certoraBuildRust.py +78 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraCloudIO.py +82 -55
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py +1 -1
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraConfigIO.py +10 -4
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraContext.py +11 -68
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraContextAttributes.py +107 -64
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraContextValidator.py +18 -21
- certora_cli-7.22.2/certora_cli/EVMVerifier/certoraParseBuildScript.py +58 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraType.py +1 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Mutate/mutateApp.py +181 -42
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Mutate/mutateAttributes.py +10 -2
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Mutate/mutateConstants.py +1 -2
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Mutate/mutateUtil.py +1 -1
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Mutate/mutateValidate.py +4 -2
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Shared/certoraAttrUtil.py +3 -2
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Shared/certoraUtils.py +51 -20
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Shared/certoraValidateFuncs.py +34 -10
- certora_cli-7.22.2/certora_cli/certoraEVMProver.py +21 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/certoraMutate.py +17 -14
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/certoraRun.py +4 -5
- certora_cli-7.22.2/certora_cli/certoraSolanaProver.py +152 -0
- certora_cli-7.22.2/certora_cli/certoraSorobanProver.py +21 -0
- certora_cli-7.22.2/certora_cli/rustMutator.py +401 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2/certora_cli.egg-info}/PKG-INFO +4 -2
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli.egg-info/SOURCES.txt +6 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli.egg-info/entry_points.txt +3 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli.egg-info/requires.txt +2 -0
- certora_cli-7.22.2/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_jars/Typechecker.jar +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/setup.py +7 -4
- certora_cli-7.20.3/README.md +0 -1
- certora_cli-7.20.3/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora_cli-7.20.3 → certora_cli-7.22.2}/LICENSE +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/MANIFEST.in +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_bins/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/CompilerCollector.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorFactory.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSol.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorSolBased.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorVy.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/CompilerCollectorYul.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/Compiler/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraBuildCacheManager.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraBuildDataClasses.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraCompilerParameters.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraContextClass.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraContractFuncs.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraExtensionInfo.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraJobList.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraMiniSpecParser.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraNodeFilters.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraSourceFinders.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraVerifyGenerator.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Mutate/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Shared/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/certoraEqCheck.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli.egg-info/dependency_links.txt +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli.egg-info/top_level.txt +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/certora_jars/__init__.py +0 -0
- {certora_cli-7.20.3 → certora_cli-7.22.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: certora-cli
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.22.2
|
|
4
4
|
Summary: Runner for the Certora Prover
|
|
5
5
|
Home-page: https://pypi.org/project/certora-cli
|
|
6
6
|
Author: Certora
|
|
@@ -21,5 +21,7 @@ Requires-Dist: tabulate
|
|
|
21
21
|
Requires-Dist: tqdm
|
|
22
22
|
Requires-Dist: StrEnum
|
|
23
23
|
Requires-Dist: tomli
|
|
24
|
+
Requires-Dist: universalmutator
|
|
25
|
+
Requires-Dist: jinja2
|
|
24
26
|
|
|
25
|
-
Commit
|
|
27
|
+
Commit 31a4e5d. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 31a4e5d. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -515,11 +515,11 @@ class CertoraBuildGenerator:
|
|
|
515
515
|
ret = Path(self.function_finder_file_remappings[file])
|
|
516
516
|
else:
|
|
517
517
|
ret = Path(file)
|
|
518
|
-
abs_sources_dir = Util.get_certora_sources_dir().
|
|
518
|
+
abs_sources_dir = Util.get_certora_sources_dir().absolute()
|
|
519
519
|
if abs_sources_dir in ret.parents:
|
|
520
520
|
# Normalize the file-name to never include the extra `.certora_internal/.../.certora_sources` part
|
|
521
521
|
# of the path.
|
|
522
|
-
ret = ret.relative_to(abs_sources_dir)
|
|
522
|
+
ret = Util.abs_norm_path(ret.relative_to(abs_sources_dir))
|
|
523
523
|
|
|
524
524
|
# things look nicer if they are rooted in .certora_sources
|
|
525
525
|
# note that we only have those fully populated after starting to work on internal function finders
|
|
@@ -1104,12 +1104,12 @@ class CertoraBuildGenerator:
|
|
|
1104
1104
|
function name, inputs, outputs, stateMutability) for each contract
|
|
1105
1105
|
"""
|
|
1106
1106
|
func_signatures = []
|
|
1107
|
-
file_abs_path = Path(self.to_autofinder_file(str(contract_file))).
|
|
1107
|
+
file_abs_path = Path(self.to_autofinder_file(str(contract_file))).absolute()
|
|
1108
1108
|
if file_abs_path.suffix == VY:
|
|
1109
1109
|
smart_contract_lang: CompilerLang = CompilerLangVy()
|
|
1110
|
-
sdc_name = self.file_to_sdc_name[Path(contract_file).
|
|
1110
|
+
sdc_name = self.file_to_sdc_name[Path(contract_file).absolute()]
|
|
1111
1111
|
standard_json_data = self.get_standard_json_data(sdc_name, smart_contract_lang)
|
|
1112
|
-
abi = standard_json_data[CONTRACTS][str(Path(contract_file).
|
|
1112
|
+
abi = standard_json_data[CONTRACTS][str(Path(contract_file).absolute())][contract_name]['abi']
|
|
1113
1113
|
ast_logger.debug(f"abi is: \n{abi}")
|
|
1114
1114
|
for f in filter(lambda x: self.is_imported_abi_entry(x), abi):
|
|
1115
1115
|
func_signature = self.get_full_func_signature(f)
|
|
@@ -1347,6 +1347,11 @@ class CertoraBuildGenerator:
|
|
|
1347
1347
|
settings_dict["optimizer"] = {"enabled": True}
|
|
1348
1348
|
if int(self.context.solc_optimize) > 0:
|
|
1349
1349
|
settings_dict["optimizer"]['runs'] = int(self.context.solc_optimize)
|
|
1350
|
+
|
|
1351
|
+
# if optimizer is true, we should also define settings_dict["optimizer"]["details"]
|
|
1352
|
+
# for both optimize map and optimize
|
|
1353
|
+
optimizer = settings_dict.get("optimizer")
|
|
1354
|
+
if optimizer and isinstance(optimizer, dict) and optimizer.get('enabled'):
|
|
1350
1355
|
# if we are not disabling finder friendly optimizer specifically, enable it whenever viaIR is also enabled
|
|
1351
1356
|
if not self.context.strict_solc_optimizer and (
|
|
1352
1357
|
self.context.solc_via_ir or self.context.solc_experimental_via_ir):
|
|
@@ -1572,7 +1577,17 @@ class CertoraBuildGenerator:
|
|
|
1572
1577
|
while queue:
|
|
1573
1578
|
pop = queue.pop(0)
|
|
1574
1579
|
if isinstance(pop, dict) and node_id_attrb in pop:
|
|
1575
|
-
|
|
1580
|
+
idAttr = pop[node_id_attrb]
|
|
1581
|
+
if isinstance(idAttr, int):
|
|
1582
|
+
container[int(idAttr)] = pop
|
|
1583
|
+
elif isinstance(idAttr, list) and len(idAttr) == 1 and isinstance(idAttr[0], int):
|
|
1584
|
+
# In the bug reported in https://certora.atlassian.net/browse/CERT-7643 the id field is a list
|
|
1585
|
+
# instead of a single integer - we except that the first element of the list is the actual id
|
|
1586
|
+
# and unpack it.
|
|
1587
|
+
container[int(idAttr[0])] = pop
|
|
1588
|
+
else:
|
|
1589
|
+
raise Exception(f"Unexpected type of attribute `{node_id_attrb}`, was {idAttr}, expected an integer or an int-typed list of length 1")
|
|
1590
|
+
|
|
1576
1591
|
for key, value in pop.items():
|
|
1577
1592
|
if (node_type_attrb in pop and
|
|
1578
1593
|
pop[node_type_attrb] == "InlineAssembly" and key == "externalReferences"):
|
|
@@ -1692,7 +1707,7 @@ class CertoraBuildGenerator:
|
|
|
1692
1707
|
is_vyper = smart_contract_lang == CompilerLangVy()
|
|
1693
1708
|
sdc_name = f"{Path(build_arg_contract_file).name}_{file_index}"
|
|
1694
1709
|
compilation_path = self.get_compilation_path(sdc_name)
|
|
1695
|
-
self.file_to_sdc_name[
|
|
1710
|
+
self.file_to_sdc_name[Util.abs_norm_path(build_arg_contract_file)] = sdc_name
|
|
1696
1711
|
# update remappings and collect_cmd:
|
|
1697
1712
|
if not is_vyper:
|
|
1698
1713
|
Util.safe_create_dir(compilation_path)
|
|
@@ -1714,7 +1729,7 @@ class CertoraBuildGenerator:
|
|
|
1714
1729
|
is equivalent to `main_path = self.context.solc_allow_path`, and that's the best we can do in that
|
|
1715
1730
|
case anyway.
|
|
1716
1731
|
"""
|
|
1717
|
-
main_path = (compile_wd / self.context.solc_allow_path).
|
|
1732
|
+
main_path = (compile_wd / self.context.solc_allow_path).absolute()
|
|
1718
1733
|
else:
|
|
1719
1734
|
main_path = self.context.solc_allow_path
|
|
1720
1735
|
self.context.solc_cmd_allow_paths = [f'"{main_path}"', '.']
|
|
@@ -1813,7 +1828,8 @@ class CertoraBuildGenerator:
|
|
|
1813
1828
|
contract_file = str(contract_file_obj)
|
|
1814
1829
|
build_logger.debug(f"Processing dependencies from file {contract_file}")
|
|
1815
1830
|
# make sure path name is in posix format.
|
|
1816
|
-
contract_file_abs =
|
|
1831
|
+
contract_file_abs = str(Util.abs_norm_path(contract_file))
|
|
1832
|
+
|
|
1817
1833
|
# using os.path.relpath because Path.relative_to cannot go up the directory tree (no ..)
|
|
1818
1834
|
contract_file_rel = os.path.relpath(Path(contract_file_abs), Path.cwd())
|
|
1819
1835
|
|
|
@@ -1849,7 +1865,7 @@ class CertoraBuildGenerator:
|
|
|
1849
1865
|
base_contracts = sorted(self.retrieve_base_contracts_list(build_arg_contract_file, contract_file,
|
|
1850
1866
|
contract_name), key=lambda x: x[0])
|
|
1851
1867
|
for c_file, _, _ in base_contracts:
|
|
1852
|
-
norm_c_file =
|
|
1868
|
+
norm_c_file = Util.abs_norm_path(c_file)
|
|
1853
1869
|
resolved_to_orig[str(norm_c_file)] = c_file
|
|
1854
1870
|
if norm_c_file not in seen_link_refs:
|
|
1855
1871
|
build_logger.debug(f"Adding a base contract link ref {norm_c_file} to worklist")
|
|
@@ -1860,7 +1876,7 @@ class CertoraBuildGenerator:
|
|
|
1860
1876
|
contract_object = data[CONTRACTS][contract_file][contract_name]
|
|
1861
1877
|
lib_link_refs = sorted(contract_object["evm"]["deployedBytecode"]["linkReferences"])
|
|
1862
1878
|
for lib_link_ref in lib_link_refs: # linkReference is a library reference
|
|
1863
|
-
norm_link_ref = Path(lib_link_ref).
|
|
1879
|
+
norm_link_ref = Path(lib_link_ref).absolute()
|
|
1864
1880
|
resolved_to_orig[str(norm_link_ref)] = lib_link_ref
|
|
1865
1881
|
if norm_link_ref not in seen_link_refs:
|
|
1866
1882
|
build_logger.debug(f"Adding library link ref {norm_link_ref} to worklist")
|
|
@@ -1879,8 +1895,7 @@ class CertoraBuildGenerator:
|
|
|
1879
1895
|
contract_refs = [c_file for c_file in
|
|
1880
1896
|
data[CONTRACTS].keys() if
|
|
1881
1897
|
ref in data[CONTRACTS][c_file].keys()]
|
|
1882
|
-
contract_files_resolved = sorted([
|
|
1883
|
-
contract_refs])
|
|
1898
|
+
contract_files_resolved = sorted([Util.abs_norm_path(x) for x in contract_refs])
|
|
1884
1899
|
|
|
1885
1900
|
# There may be two non unique paths but actually referring to the same absolute path.
|
|
1886
1901
|
# Normalizing as absolute
|
|
@@ -2302,7 +2317,7 @@ class CertoraBuildGenerator:
|
|
|
2302
2317
|
f" {c.name} that doesn't have a location")
|
|
2303
2318
|
return None
|
|
2304
2319
|
|
|
2305
|
-
instrumentation_path = Util.
|
|
2320
|
+
instrumentation_path = str(Util.abs_norm_path(loc[0]))
|
|
2306
2321
|
if instrumentation_path not in function_finder_instrumentation:
|
|
2307
2322
|
instrumentation_logger.debug(f"New instrumentation for location {loc[0]}, " +
|
|
2308
2323
|
f"instrumentation path {instrumentation_path}")
|
|
@@ -2615,7 +2630,7 @@ class CertoraBuildGenerator:
|
|
|
2615
2630
|
sources_from_pre_finder_SDCs |= sdc.all_contract_files
|
|
2616
2631
|
sources = self.collect_sources(context, certora_verify_generator, sources_from_pre_finder_SDCs)
|
|
2617
2632
|
try:
|
|
2618
|
-
self.cwd_rel_in_sources =
|
|
2633
|
+
self.cwd_rel_in_sources = build_source_tree(sources, context)
|
|
2619
2634
|
except Exception as e:
|
|
2620
2635
|
build_logger.debug(f"build_source_tree failed. Sources: {sources}", exc_info=e)
|
|
2621
2636
|
raise
|
|
@@ -2782,85 +2797,6 @@ class CertoraBuildGenerator:
|
|
|
2782
2797
|
common_path = Path(os.path.commonpath(list(sources.union({cwd}))))
|
|
2783
2798
|
return cwd.relative_to(common_path), common_path
|
|
2784
2799
|
|
|
2785
|
-
@staticmethod
|
|
2786
|
-
def build_source_tree(sources: Set[Path], context: CertoraContext, overwrite: bool = False) -> Path:
|
|
2787
|
-
"""
|
|
2788
|
-
Copies files to .certora_sources
|
|
2789
|
-
@returns the cwd relative in sources
|
|
2790
|
-
"""
|
|
2791
|
-
sources = sources_to_abs(sources)
|
|
2792
|
-
cwd_rel_in_sources, common_path = CertoraBuildGenerator.get_cwd_rel_in_sources(sources)
|
|
2793
|
-
|
|
2794
|
-
for source_path in sources:
|
|
2795
|
-
is_dir = source_path.is_dir()
|
|
2796
|
-
# copy file to the path of the file from the common root under the sources directory
|
|
2797
|
-
|
|
2798
|
-
# make sure directory exists
|
|
2799
|
-
target_path = Util.get_certora_sources_dir() / source_path.relative_to(common_path)
|
|
2800
|
-
target_directory = target_path if is_dir else target_path.parent
|
|
2801
|
-
try:
|
|
2802
|
-
target_directory.mkdir(parents=True, exist_ok=True)
|
|
2803
|
-
except OSError as e:
|
|
2804
|
-
build_logger.debug(f"Failed to create directory {target_directory}", exc_info=e)
|
|
2805
|
-
raise
|
|
2806
|
-
|
|
2807
|
-
# copy files. if we got a directory, nothing to do
|
|
2808
|
-
if is_dir:
|
|
2809
|
-
build_logger.debug(f"Skipping directory {source_path}")
|
|
2810
|
-
continue
|
|
2811
|
-
|
|
2812
|
-
try:
|
|
2813
|
-
if overwrite:
|
|
2814
|
-
# expecting target path to exist.
|
|
2815
|
-
if target_path.exists():
|
|
2816
|
-
build_logger.debug(f"Overwriting {target_path} by copying from {source_path}")
|
|
2817
|
-
else:
|
|
2818
|
-
build_logger.warning(f"Supposed to overwrite {target_path} by copying from {source_path}" +
|
|
2819
|
-
" but it does not exist... this may indicate bad things happen")
|
|
2820
|
-
if overwrite or not target_path.exists():
|
|
2821
|
-
build_logger.debug(f"Copying {source_path} to {target_path}")
|
|
2822
|
-
shutil.copyfile(source_path, target_path)
|
|
2823
|
-
except OSError as e:
|
|
2824
|
-
build_logger.debug(f"Couldn't copy {source_path} to {target_path}", exc_info=e)
|
|
2825
|
-
raise
|
|
2826
|
-
|
|
2827
|
-
# the empty file .cwd is written in the source tree to denote the current working directory
|
|
2828
|
-
if cwd_rel_in_sources != '.':
|
|
2829
|
-
file_path = Util.get_certora_sources_dir() / cwd_rel_in_sources / Util.CWD_FILE
|
|
2830
|
-
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
2831
|
-
file_path.touch()
|
|
2832
|
-
|
|
2833
|
-
"""
|
|
2834
|
-
Once the resource files are copied to the source tree, the paths in the value of the 'prover_resource_files'
|
|
2835
|
-
attribute are replaced with the relative path of the resource file from the source tree root.
|
|
2836
|
-
This way The server can easily find the resource files in the source tree. The path from the source tree is the
|
|
2837
|
-
relative path of cwd from source tree root (most cases '.') concatenated with the relative path of the resource
|
|
2838
|
-
file from cwd
|
|
2839
|
-
"""
|
|
2840
|
-
if context.prover_resource_files:
|
|
2841
|
-
new_value = []
|
|
2842
|
-
len_orig = len(context.prover_resource_files)
|
|
2843
|
-
for value in context.prover_resource_files:
|
|
2844
|
-
label, file_path = value.split(':')
|
|
2845
|
-
rel_path = Path(os.path.relpath(file_path, '.'))
|
|
2846
|
-
new_value.append(':'.join([label, os.path.normpath(rel_path)]))
|
|
2847
|
-
if len_orig != len(new_value):
|
|
2848
|
-
raise RuntimeError(f"fail to process prover_resource_files {len_orig} out of {len(new_value)}")
|
|
2849
|
-
context.prover_resource_files = new_value
|
|
2850
|
-
|
|
2851
|
-
# Copy the repro conf file to the sources as the overall way to reproduce this run easily.
|
|
2852
|
-
# The file is being copied in here and not added through collect_sources, because we want
|
|
2853
|
-
# to avoid building the whole tree up to the common path for this file. We simply want to copy
|
|
2854
|
-
# the repro file from .certora_internal to .certora_sources so it will be uploaded as a run
|
|
2855
|
-
# resource.
|
|
2856
|
-
try:
|
|
2857
|
-
shutil.copy(Util.get_last_conf_file(), Util.get_certora_sources_dir() / Util.LAST_CONF_FILE)
|
|
2858
|
-
except OSError as e:
|
|
2859
|
-
build_logger.debug("Couldn't copy repro conf to certora sources.", exc_info=e)
|
|
2860
|
-
raise
|
|
2861
|
-
|
|
2862
|
-
return cwd_rel_in_sources
|
|
2863
|
-
|
|
2864
2800
|
@staticmethod
|
|
2865
2801
|
def normalize_path(path: str) -> str:
|
|
2866
2802
|
"""
|
|
@@ -2879,7 +2815,7 @@ class CertoraBuildGenerator:
|
|
|
2879
2815
|
p = Path(path)
|
|
2880
2816
|
if p.is_absolute():
|
|
2881
2817
|
return path
|
|
2882
|
-
return str(Path.cwd() / p.
|
|
2818
|
+
return str(Path.cwd() / p.absolute())
|
|
2883
2819
|
|
|
2884
2820
|
@staticmethod
|
|
2885
2821
|
def merge_dicts_instrumentation(dict1: Dict[str, Dict[int, Instrumentation]],
|
|
@@ -3052,7 +2988,7 @@ class CertoraBuildGenerator:
|
|
|
3052
2988
|
"""
|
|
3053
2989
|
rel_to_cwd_path = Path(os.path.relpath(path, '.'))
|
|
3054
2990
|
new_path = Util.get_certora_sources_dir() / self.cwd_rel_in_sources / rel_to_cwd_path
|
|
3055
|
-
return str(new_path.
|
|
2991
|
+
return str(new_path.absolute())
|
|
3056
2992
|
|
|
3057
2993
|
def handle_links(self) -> None:
|
|
3058
2994
|
# Link processing
|
|
@@ -3457,6 +3393,85 @@ def sources_to_abs(sources: Set[Path]) -> Set[Path]:
|
|
|
3457
3393
|
return result
|
|
3458
3394
|
|
|
3459
3395
|
|
|
3396
|
+
def build_source_tree(sources: Set[Path], context: CertoraContext, overwrite: bool = False) -> Path:
|
|
3397
|
+
"""
|
|
3398
|
+
Copies files to .certora_sources
|
|
3399
|
+
@returns the cwd relative in sources
|
|
3400
|
+
"""
|
|
3401
|
+
sources = sources_to_abs(sources)
|
|
3402
|
+
cwd_rel_in_sources, common_path = CertoraBuildGenerator.get_cwd_rel_in_sources(sources)
|
|
3403
|
+
|
|
3404
|
+
for source_path in sources:
|
|
3405
|
+
is_dir = source_path.is_dir()
|
|
3406
|
+
# copy file to the path of the file from the common root under the sources directory
|
|
3407
|
+
|
|
3408
|
+
# make sure directory exists
|
|
3409
|
+
target_path = Util.get_certora_sources_dir() / source_path.relative_to(common_path)
|
|
3410
|
+
target_directory = target_path if is_dir else target_path.parent
|
|
3411
|
+
try:
|
|
3412
|
+
target_directory.mkdir(parents=True, exist_ok=True)
|
|
3413
|
+
except OSError as e:
|
|
3414
|
+
build_logger.debug(f"Failed to create directory {target_directory}", exc_info=e)
|
|
3415
|
+
raise
|
|
3416
|
+
|
|
3417
|
+
# copy files. if we got a directory, nothing to do
|
|
3418
|
+
if is_dir:
|
|
3419
|
+
build_logger.debug(f"Skipping directory {source_path}")
|
|
3420
|
+
continue
|
|
3421
|
+
|
|
3422
|
+
try:
|
|
3423
|
+
if overwrite:
|
|
3424
|
+
# expecting target path to exist.
|
|
3425
|
+
if target_path.exists():
|
|
3426
|
+
build_logger.debug(f"Overwriting {target_path} by copying from {source_path}")
|
|
3427
|
+
else:
|
|
3428
|
+
build_logger.warning(f"Supposed to overwrite {target_path} by copying from {source_path}" +
|
|
3429
|
+
" but it does not exist... this may indicate bad things happen")
|
|
3430
|
+
if overwrite or not target_path.exists():
|
|
3431
|
+
build_logger.debug(f"Copying {source_path} to {target_path}")
|
|
3432
|
+
shutil.copyfile(source_path, target_path)
|
|
3433
|
+
except OSError as e:
|
|
3434
|
+
build_logger.debug(f"Couldn't copy {source_path} to {target_path}", exc_info=e)
|
|
3435
|
+
raise
|
|
3436
|
+
|
|
3437
|
+
# the empty file .cwd is written in the source tree to denote the current working directory
|
|
3438
|
+
if cwd_rel_in_sources != '.':
|
|
3439
|
+
file_path = Util.get_certora_sources_dir() / cwd_rel_in_sources / Util.CWD_FILE
|
|
3440
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
3441
|
+
file_path.touch()
|
|
3442
|
+
|
|
3443
|
+
"""
|
|
3444
|
+
Once the resource files are copied to the source tree, the paths in the value of the 'prover_resource_files'
|
|
3445
|
+
attribute are replaced with the relative path of the resource file from the source tree root.
|
|
3446
|
+
This way The server can easily find the resource files in the source tree. The path from the source tree is the
|
|
3447
|
+
relative path of cwd from source tree root (most cases '.') concatenated with the relative path of the resource
|
|
3448
|
+
file from cwd
|
|
3449
|
+
"""
|
|
3450
|
+
if context.prover_resource_files:
|
|
3451
|
+
new_value = []
|
|
3452
|
+
len_orig = len(context.prover_resource_files)
|
|
3453
|
+
for value in context.prover_resource_files:
|
|
3454
|
+
label, file_path = value.split(':')
|
|
3455
|
+
rel_path = Path(os.path.relpath(file_path, '.'))
|
|
3456
|
+
new_value.append(':'.join([label, os.path.normpath(rel_path)]))
|
|
3457
|
+
if len_orig != len(new_value):
|
|
3458
|
+
raise RuntimeError(f"fail to process prover_resource_files {len_orig} out of {len(new_value)}")
|
|
3459
|
+
context.prover_resource_files = new_value
|
|
3460
|
+
|
|
3461
|
+
# Copy the repro conf file to the sources as the overall way to reproduce this run easily.
|
|
3462
|
+
# The file is being copied in here and not added through collect_sources, because we want
|
|
3463
|
+
# to avoid building the whole tree up to the common path for this file. We simply want to copy
|
|
3464
|
+
# the repro file from .certora_internal to .certora_sources so it will be uploaded as a run
|
|
3465
|
+
# resource.
|
|
3466
|
+
try:
|
|
3467
|
+
shutil.copy(Util.get_last_conf_file(), Util.get_certora_sources_dir() / Util.LAST_CONF_FILE)
|
|
3468
|
+
except OSError as e:
|
|
3469
|
+
build_logger.debug("Couldn't copy repro conf to certora sources.", exc_info=e)
|
|
3470
|
+
raise
|
|
3471
|
+
|
|
3472
|
+
return cwd_rel_in_sources
|
|
3473
|
+
|
|
3474
|
+
|
|
3460
3475
|
def build_from_scratch(certora_build_generator: CertoraBuildGenerator,
|
|
3461
3476
|
certora_verify_generator: CertoraVerifyGenerator,
|
|
3462
3477
|
build_cache_enabled: bool) -> CachedFiles:
|
|
@@ -3481,7 +3496,7 @@ def build_from_scratch(certora_build_generator: CertoraBuildGenerator,
|
|
|
3481
3496
|
saw_paths_not_in_sources = False
|
|
3482
3497
|
paths_not_in_sources = set()
|
|
3483
3498
|
may_store_in_build_cache = True
|
|
3484
|
-
absolute_sources_dir = Util.get_certora_sources_dir().
|
|
3499
|
+
absolute_sources_dir = Util.get_certora_sources_dir().absolute()
|
|
3485
3500
|
for sdc in certora_build_generator.SDCs.values():
|
|
3486
3501
|
# the contract files in SDCs are relative to .certora_sources. Which isn't good for us here.
|
|
3487
3502
|
# Need to be relative to original paths
|
|
@@ -3620,7 +3635,7 @@ def build(context: CertoraContext, ignore_spec_syntax_check: bool = False) -> No
|
|
|
3620
3635
|
cached_files.all_contract_files)
|
|
3621
3636
|
try:
|
|
3622
3637
|
# Copies files, not updating state
|
|
3623
|
-
|
|
3638
|
+
build_source_tree(sources, context)
|
|
3624
3639
|
except Exception as e:
|
|
3625
3640
|
build_logger.debug("build_source_tree failed", exc_info=e)
|
|
3626
3641
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import glob
|
|
2
|
+
import shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Set
|
|
5
|
+
|
|
6
|
+
from EVMVerifier.certoraBuild import build_source_tree
|
|
7
|
+
from EVMVerifier.certoraContextClass import CertoraContext
|
|
8
|
+
from EVMVerifier.certoraParseBuildScript import run_script_and_parse_json
|
|
9
|
+
from Shared import certoraUtils as Util
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def build_rust_app(context: CertoraContext) -> None:
|
|
13
|
+
if context.build_script:
|
|
14
|
+
run_script_and_parse_json(context)
|
|
15
|
+
if not context.rust_executables:
|
|
16
|
+
raise Util.CertoraUserInputError("failed to get target executable")
|
|
17
|
+
|
|
18
|
+
sources: Set[Path] = set()
|
|
19
|
+
root_directory = Path(context.rust_project_directory)
|
|
20
|
+
collect_files_from_rust_sources(context, sources, root_directory)
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
# Create generators
|
|
24
|
+
build_source_tree(sources, context)
|
|
25
|
+
|
|
26
|
+
copy_files_to_build_dir(context)
|
|
27
|
+
|
|
28
|
+
except Exception as e:
|
|
29
|
+
raise Util.CertoraUserInputError(f"Collecting build files failed with the exception: {e}")
|
|
30
|
+
else:
|
|
31
|
+
if not context.files:
|
|
32
|
+
raise Util.CertoraUserInputError("'files' or 'build_script' must be set for Rust projects")
|
|
33
|
+
if len(context.files) > 1:
|
|
34
|
+
raise Util.CertoraUserInputError("Rust projects must specify exactly one executable in 'files'.")
|
|
35
|
+
context.rust_executables = context.files[0]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def collect_files_from_rust_sources(context: CertoraContext, sources: Set[Path], root_directory: Path) -> None:
|
|
39
|
+
patterns = ["*.rs", "*.so", "*.wasm", "Cargo.toml", "Cargo.lock", "justfile"]
|
|
40
|
+
exclude_dirs = [".certora_internal"]
|
|
41
|
+
|
|
42
|
+
if not root_directory.is_dir():
|
|
43
|
+
raise ValueError(f"The given directory {root_directory} is not valid.")
|
|
44
|
+
|
|
45
|
+
for source in context.rust_sources:
|
|
46
|
+
for file in glob.glob(f'{root_directory.joinpath(source)}', recursive=True):
|
|
47
|
+
file_path = Path(file)
|
|
48
|
+
if any(excluded in file_path.parts for excluded in exclude_dirs):
|
|
49
|
+
continue
|
|
50
|
+
if file_path.is_file() and any(file_path.match(pattern) for pattern in patterns):
|
|
51
|
+
sources.add(file_path)
|
|
52
|
+
|
|
53
|
+
if Path(context.build_script).exists():
|
|
54
|
+
sources.add(Path(context.build_script).resolve())
|
|
55
|
+
if context.conf_file and Path(context.conf_file).exists():
|
|
56
|
+
sources.add(Path(context.conf_file).absolute())
|
|
57
|
+
|
|
58
|
+
additional_files = (getattr(context, 'solana_inlining', None) or []) + \
|
|
59
|
+
(getattr(context, 'solana_summaries', None) or [])
|
|
60
|
+
for file in additional_files:
|
|
61
|
+
sources.add(Path(file))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def copy_files_to_build_dir(context: CertoraContext) -> None:
|
|
65
|
+
rust_executable = Path(context.rust_project_directory) / context.rust_executables
|
|
66
|
+
shutil.copyfile(rust_executable, Util.get_build_dir() / rust_executable.name)
|
|
67
|
+
|
|
68
|
+
additional_files = (getattr(context, 'solana_inlining', None) or []) + \
|
|
69
|
+
(getattr(context, 'solana_summaries', None) or [])
|
|
70
|
+
|
|
71
|
+
for file in additional_files:
|
|
72
|
+
file_path = Path(file).resolve()
|
|
73
|
+
shutil.copy(file_path, Util.get_build_dir() / file_path.name)
|
|
74
|
+
|
|
75
|
+
if rust_logs := getattr(context, 'rust_logs_stdout', None):
|
|
76
|
+
shutil.copy(Path(rust_logs), Util.get_build_dir() / Path(rust_logs).name)
|
|
77
|
+
if rust_logs := getattr(context, 'rust_logs_stderr', None):
|
|
78
|
+
shutil.copy(Path(rust_logs), Util.get_build_dir() / Path(rust_logs).name)
|
|
@@ -190,25 +190,6 @@ def parse_json(response: Response) -> Dict[str, Any]:
|
|
|
190
190
|
return json_response
|
|
191
191
|
|
|
192
192
|
|
|
193
|
-
def compress_files_wasm(zip_file_path: Path, context: CertoraContext) -> bool:
|
|
194
|
-
with zipfile.ZipFile(zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zip_obj:
|
|
195
|
-
cargo_directory = context.cargo_dir
|
|
196
|
-
for path in cargo_directory.rglob('*.rs'):
|
|
197
|
-
if cargo_directory / 'target' in path.parents or cargo_directory / '.certora_internal' in path.parents:
|
|
198
|
-
continue
|
|
199
|
-
zip_obj.write(path, Util.CERTORA_SOURCES / path.relative_to(cargo_directory))
|
|
200
|
-
for path in [cargo_directory / 'Cargo.toml', cargo_directory / 'Cargo.lock']:
|
|
201
|
-
if path.exists():
|
|
202
|
-
zip_obj.write(path, path.relative_to(cargo_directory))
|
|
203
|
-
if context.wasm_file.exists():
|
|
204
|
-
zip_obj.write(context.wasm_file, context.wasm_file.relative_to(context.wasm_file.parent))
|
|
205
|
-
|
|
206
|
-
if zip_file_path.stat().st_size > MAX_FILE_SIZE:
|
|
207
|
-
cloud_logger.error(f"{GENERAL_ERR_PREFIX} Max 25MB file size exceeded.")
|
|
208
|
-
return False
|
|
209
|
-
return True
|
|
210
|
-
|
|
211
|
-
|
|
212
193
|
def compress_files(zip_file_path: Path, *resource_paths: Path, short_output: bool = False) -> bool:
|
|
213
194
|
with zipfile.ZipFile(zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zip_obj:
|
|
214
195
|
|
|
@@ -600,8 +581,12 @@ class CloudVerification:
|
|
|
600
581
|
# We need to strip "../" path component from all file paths because
|
|
601
582
|
# unzip will also do that.
|
|
602
583
|
solana_jar_settings = []
|
|
603
|
-
|
|
604
|
-
solana_jar_settings.append(
|
|
584
|
+
if hasattr(self.context, 'build_script') and self.context.build_script:
|
|
585
|
+
solana_jar_settings.append(Path(self.context.rust_executables).name)
|
|
586
|
+
|
|
587
|
+
else:
|
|
588
|
+
for file in self.context.files:
|
|
589
|
+
solana_jar_settings.append(file.split('../')[-1])
|
|
605
590
|
|
|
606
591
|
is_file = False
|
|
607
592
|
for arg in jar_settings:
|
|
@@ -616,18 +601,19 @@ class CloudVerification:
|
|
|
616
601
|
elif arg == '-solanaSummaries':
|
|
617
602
|
is_file = True
|
|
618
603
|
auth_data["jarSettings"] = solana_jar_settings
|
|
619
|
-
elif Attrs.
|
|
604
|
+
elif Attrs.is_soroban_app():
|
|
620
605
|
# We need to strip "../" path component from all file paths because
|
|
621
606
|
# unzip will also do that.
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
607
|
+
soroban_jar_settings = []
|
|
608
|
+
# not needed - should be in files
|
|
609
|
+
if hasattr(self.context, 'build_script') and self.context.build_script:
|
|
610
|
+
soroban_jar_settings.append(Path(self.context.rust_executables).name)
|
|
625
611
|
else:
|
|
626
612
|
for file in self.context.files:
|
|
627
|
-
|
|
613
|
+
soroban_jar_settings.append(file.split('../')[-1])
|
|
628
614
|
for arg in jar_settings:
|
|
629
|
-
|
|
630
|
-
auth_data["jarSettings"] =
|
|
615
|
+
soroban_jar_settings.append(arg)
|
|
616
|
+
auth_data["jarSettings"] = soroban_jar_settings
|
|
631
617
|
else:
|
|
632
618
|
auth_data["jarSettings"] = jar_settings
|
|
633
619
|
|
|
@@ -738,40 +724,81 @@ class CloudVerification:
|
|
|
738
724
|
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
739
725
|
elif Attrs.is_evm_app() and self.context.is_bytecode:
|
|
740
726
|
# We zip the bytecode jsons and the spec
|
|
741
|
-
paths = [
|
|
727
|
+
paths = [Util.get_certora_build_file(), Util.get_certora_verify_file(),
|
|
728
|
+
Util.get_certora_metadata_file()]
|
|
729
|
+
if Util.get_certora_sources_dir().exists():
|
|
730
|
+
paths.append(Util.get_certora_sources_dir())
|
|
731
|
+
|
|
742
732
|
for bytecode_json in self.context.bytecode_jsons:
|
|
743
733
|
paths.append(Path(bytecode_json))
|
|
744
734
|
paths.append(Path(self.context.bytecode_spec))
|
|
745
735
|
result = compress_files(self.ZipFilePath, *paths,
|
|
746
736
|
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
747
|
-
elif Attrs.
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
737
|
+
elif Attrs.is_rust_app():
|
|
738
|
+
files_list = [Util.get_certora_metadata_file()]
|
|
739
|
+
|
|
740
|
+
if hasattr(self.context, 'build_script') and self.context.build_script:
|
|
741
|
+
result = compress_files(self.logZipFilePath, Util.get_debug_log_file(),
|
|
742
|
+
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
743
|
+
|
|
744
|
+
if not result:
|
|
745
|
+
return False
|
|
746
|
+
files_list.append(self.logZipFilePath)
|
|
747
|
+
if Util.get_certora_sources_dir().exists():
|
|
748
|
+
files_list.append(Util.get_certora_sources_dir())
|
|
749
|
+
|
|
750
|
+
files_list.append(Util.get_build_dir() / Path(self.context.rust_executables).name)
|
|
751
|
+
|
|
752
|
+
# Create a .RustExecution file to classify zipInput as a rust source code
|
|
753
|
+
rust_execution_file = Util.get_build_dir() / ".RustExecution"
|
|
754
|
+
rust_execution_file.touch(exist_ok=True)
|
|
755
|
+
files_list.append(rust_execution_file)
|
|
756
|
+
|
|
757
|
+
additional_files = (getattr(self.context, 'solana_inlining', None) or []) + \
|
|
758
|
+
(getattr(self.context, 'solana_summaries', None) or [])
|
|
759
|
+
for file in additional_files:
|
|
760
|
+
files_list.append(Util.get_build_dir() / Path(file).name)
|
|
761
|
+
|
|
762
|
+
if attr_file := getattr(self.context, 'rust_logs_stdout', None):
|
|
763
|
+
files_list.append(Util.get_build_dir() / Path(attr_file).name)
|
|
764
|
+
if attr_file := getattr(self.context, 'rust_logs_stderr', None):
|
|
765
|
+
files_list.append(Util.get_build_dir() / Path(attr_file).name)
|
|
766
|
+
|
|
767
|
+
result = compress_files(self.ZipFilePath, *files_list,
|
|
768
|
+
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
769
|
+
|
|
770
|
+
elif Attrs.is_solana_app():
|
|
771
|
+
# We zip the ELF files and the two configuration files
|
|
772
|
+
jar_args = Ctx.collect_jar_args(self.context)
|
|
758
773
|
|
|
759
|
-
if arg == '-solanaInlining':
|
|
760
|
-
is_file = True
|
|
761
|
-
elif arg == '-solanaSummaries':
|
|
762
|
-
is_file = True
|
|
763
|
-
result = compress_files(self.ZipFilePath, *paths,
|
|
764
|
-
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
765
|
-
elif Attrs.is_wasm_app():
|
|
766
|
-
# We zip the wat file
|
|
767
|
-
paths = []
|
|
768
|
-
if hasattr(self.context, 'wasm_file') and self.context.wasm_file:
|
|
769
|
-
result = compress_files_wasm(self.ZipFilePath, self.context)
|
|
770
|
-
else:
|
|
771
774
|
for file in self.context.files:
|
|
772
|
-
|
|
773
|
-
|
|
775
|
+
files_list.append(Path(file))
|
|
776
|
+
is_file = False
|
|
777
|
+
for arg in jar_args:
|
|
778
|
+
if is_file:
|
|
779
|
+
files_list.append(Path(arg))
|
|
780
|
+
is_file = False
|
|
781
|
+
|
|
782
|
+
if arg == '-solanaInlining':
|
|
783
|
+
is_file = True
|
|
784
|
+
elif arg == '-solanaSummaries':
|
|
785
|
+
is_file = True
|
|
786
|
+
result = compress_files(self.ZipFilePath, *files_list,
|
|
774
787
|
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
788
|
+
|
|
789
|
+
elif Attrs.is_soroban_app():
|
|
790
|
+
# We zip the wat file
|
|
791
|
+
for file in self.context.files:
|
|
792
|
+
files_list.append(Path(file))
|
|
793
|
+
result = compress_files(self.ZipFilePath, *files_list,
|
|
794
|
+
short_output=Ctx.is_minimal_cli_output(self.context))
|
|
795
|
+
else:
|
|
796
|
+
raise Util.CertoraUserInputError(
|
|
797
|
+
'When running rust application, context should either have attribute "rust_executables" '
|
|
798
|
+
'provided by build_script execution, '
|
|
799
|
+
'or either is_solana_app(), is_soroban_app() should be set to True'
|
|
800
|
+
)
|
|
801
|
+
|
|
775
802
|
else:
|
|
776
803
|
# Zip the log file first separately and again with the rest of the files, so it will not be decompressed
|
|
777
804
|
# on each run in order to save space
|
|
@@ -847,7 +874,7 @@ class CloudVerification:
|
|
|
847
874
|
self.vscode_extension_info_writer.add_field("verification_report_url", self.reportUrl)
|
|
848
875
|
self.vscode_extension_info_writer.write_file()
|
|
849
876
|
|
|
850
|
-
if wait_for_results == str(Vf.WaitForResultOptions.NONE):
|
|
877
|
+
if not wait_for_results or wait_for_results == str(Vf.WaitForResultOptions.NONE):
|
|
851
878
|
job_list.save_data()
|
|
852
879
|
job_list.save_recent_jobs_to_path()
|
|
853
880
|
self.print_output_links()
|
{certora_cli-7.20.3 → certora_cli-7.22.2}/certora_cli/EVMVerifier/certoraCollectRunMetadata.py
RENAMED
|
@@ -149,7 +149,7 @@ def collect_run_metadata(wd: Path, raw_args: List[str], context: CertoraContext)
|
|
|
149
149
|
group_id=None)
|
|
150
150
|
|
|
151
151
|
# collect information about current git snapshot
|
|
152
|
-
cwd_abs = wd.
|
|
152
|
+
cwd_abs = wd.absolute()
|
|
153
153
|
|
|
154
154
|
is_git_executable = False
|
|
155
155
|
git_present_out = None
|