certora-cli 8.8.1__tar.gz → 8.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {certora_cli-8.8.1/certora_cli.egg-info → certora_cli-8.13.0}/PKG-INFO +2 -2
- certora_cli-8.13.0/README.md +1 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraBuild.py +83 -28
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraBuildCacheManager.py +16 -1
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraBuildRust.py +3 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraBuildSui.py +42 -12
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraCloudIO.py +9 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraContext.py +39 -8
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraContextAttributes.py +132 -7
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraContextValidator.py +25 -1
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraParseBuildScript.py +3 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/splitRules.py +31 -17
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/certoraUtils.py +4 -2
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/certoraValidateFuncs.py +18 -1
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraSolanaProver.py +22 -1
- {certora_cli-8.8.1 → certora_cli-8.13.0/certora_cli.egg-info}/PKG-INFO +2 -2
- certora_cli-8.8.1/certora_jars/Typechecker.jar → certora_cli-8.13.0/certora_jars/ASTExtraction.jar +0 -0
- certora_cli-8.13.0/certora_jars/CERTORA-CLI-VERSION-METADATA.json +1 -0
- certora_cli-8.8.1/certora_jars/ASTExtraction.jar → certora_cli-8.13.0/certora_jars/Typechecker.jar +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/setup.py +2 -2
- certora_cli-8.8.1/README.md +0 -1
- certora_cli-8.8.1/certora_jars/CERTORA-CLI-VERSION-METADATA.json +0 -1
- {certora_cli-8.8.1 → certora_cli-8.13.0}/LICENSE +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/MANIFEST.in +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_bins/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/CompilerCollector.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorFactory.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorSol.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorSolBased.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorVy.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/CompilerCollectorYul.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/Compiler/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/castingInstrumenter.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraApp.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraBuildDataClasses.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraCollectConfigurationLayout.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraCollectRunMetadata.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraCompilerParameters.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraConfigIO.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraContextClass.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraContractFuncs.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraExtensionInfo.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraJobList.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraMiniSpecParser.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraNodeFilters.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraOffsetConverter.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraProjectScanner.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraSourceFinders.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraType.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraVerifyGenerator.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/erc7201.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/storageExtension.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/uncheckedOverflowInstrumenter.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/Eq_default.conf +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/Eq_mc_no_out_template.spec +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/Eq_mc_template.spec +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/Eq_sanity.conf +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/Eq_template.spec +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/equivCheck.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/EquivalenceCheck/sanity.spec +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Mutate/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Mutate/mutateApp.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Mutate/mutateAttributes.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Mutate/mutateConstants.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Mutate/mutateUtil.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Mutate/mutateValidate.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/ExpectedComparator.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/certoraAttrUtil.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/certoraLogging.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/Shared/proverCommon.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraCVLFormatter.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraConcord.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraEVMProver.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraEqCheck.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraMutate.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraRanger.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraRun.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraSorobanProver.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/certoraSuiProver.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/rustMutator.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli.egg-info/SOURCES.txt +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli.egg-info/dependency_links.txt +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli.egg-info/entry_points.txt +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli.egg-info/requires.txt +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli.egg-info/top_level.txt +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/certora_jars/__init__.py +0 -0
- {certora_cli-8.8.1 → certora_cli-8.13.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: certora-cli
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.13.0
|
|
4
4
|
Summary: Runner for the Certora Prover
|
|
5
5
|
Home-page: https://pypi.org/project/certora-cli
|
|
6
6
|
Author: Certora
|
|
@@ -38,4 +38,4 @@ Dynamic: requires-dist
|
|
|
38
38
|
Dynamic: requires-python
|
|
39
39
|
Dynamic: summary
|
|
40
40
|
|
|
41
|
-
Commit
|
|
41
|
+
Commit 3ce73ef. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Commit 3ce73ef. Build and Run scripts for executing the Certora Prover on Solidity smart contracts.
|
|
@@ -890,7 +890,7 @@ class CertoraBuildGenerator:
|
|
|
890
890
|
# same name but used separately could exist right?
|
|
891
891
|
# Add to the current contract all public/external functions, and internal/private ones if
|
|
892
892
|
# this is the declaring contract.
|
|
893
|
-
if func_visibility in ("public", "external") or (c_name == contract_name):
|
|
893
|
+
if func_visibility in ("public", "external") or (c_name == contract_name and c_file == contract_file):
|
|
894
894
|
funcs.append(func)
|
|
895
895
|
ast_logger.debug(f"Function {func.source_code_signature()} added")
|
|
896
896
|
|
|
@@ -1114,11 +1114,12 @@ class CertoraBuildGenerator:
|
|
|
1114
1114
|
assert "baseName" in bc and "referencedDeclaration" in bc["baseName"]
|
|
1115
1115
|
next_bc_ref = bc["baseName"]["referencedDeclaration"]
|
|
1116
1116
|
next_bc = self.get_contract_file_of(build_arg_contract_file, next_bc_ref)
|
|
1117
|
-
|
|
1117
|
+
next_bc_name = self.asts[build_arg_contract_file][next_bc][next_bc_ref]["name"]
|
|
1118
|
+
if (next_bc, next_bc_name) not in [(e[0], e[1]) for e in base_contracts_lst]:
|
|
1118
1119
|
base_contracts_lst.append(
|
|
1119
|
-
(next_bc,
|
|
1120
|
+
(next_bc, next_bc_name,
|
|
1120
1121
|
self.is_library_def_node(next_bc, next_bc_ref, build_arg_contract_file)))
|
|
1121
|
-
base_contracts_queue.insert(0, (next_bc,
|
|
1122
|
+
base_contracts_queue.insert(0, (next_bc, next_bc_ref))
|
|
1122
1123
|
|
|
1123
1124
|
if base_contracts_queue:
|
|
1124
1125
|
retrieve_base_contracts_list_rec(base_contracts_queue, base_contracts_lst)
|
|
@@ -1447,7 +1448,9 @@ class CertoraBuildGenerator:
|
|
|
1447
1448
|
if not self.context.strict_solc_optimizer and self.get_solc_via_ir_value(contract_file_path):
|
|
1448
1449
|
# The default optimizer steps (taken from libsolidity/interface/OptimiserSettings.h) but with the
|
|
1449
1450
|
# full inliner step removed
|
|
1450
|
-
|
|
1451
|
+
solc0_8_34_to_0_8_34 = ("dfDvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLvifMCTUca[r]LSsTFOtfDnca[r]"
|
|
1452
|
+
"IulcscCTUtvifMx[scCTUt]TOntnfDIulvifMjmul[jul]VcTOculjmul")
|
|
1453
|
+
solc0_8_26_to_0_8_33 = ("dhfoDgvulfnTUtnIfxa[r]EscLMVcul[j]Trpeulxa[r]cLCTUca[r]LSsTFOtfDnca[r]" +
|
|
1451
1454
|
"IulcscCTUtx[scCTUt]TOntnfDIuljmul[jul]VcTOculjmul")
|
|
1452
1455
|
solc0_8_13_to_0_8_25 = "dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul[j]T" + \
|
|
1453
1456
|
"peulxa[rul]xa[r]cLgvifCTUca[r]LSsTFOtfDnca[r]Iulc]jmul[jul]VcTOculjmul"
|
|
@@ -1496,8 +1499,10 @@ class CertoraBuildGenerator:
|
|
|
1496
1499
|
yul_optimizer_steps = solc0_8_12
|
|
1497
1500
|
elif minor == 8 and 13 <= patch <= 25:
|
|
1498
1501
|
yul_optimizer_steps = solc0_8_13_to_0_8_25
|
|
1499
|
-
elif minor == 8 and 26 <= patch <=
|
|
1500
|
-
yul_optimizer_steps =
|
|
1502
|
+
elif minor == 8 and 26 <= patch <= 33:
|
|
1503
|
+
yul_optimizer_steps = solc0_8_26_to_0_8_33
|
|
1504
|
+
elif minor == 8 and 34 <= patch <= 34:
|
|
1505
|
+
yul_optimizer_steps = solc0_8_34_to_0_8_34
|
|
1501
1506
|
assert yul_optimizer_steps is not None, \
|
|
1502
1507
|
'Yul Optimizer steps missing for requested Solidity version. Please contact Certora team.'
|
|
1503
1508
|
|
|
@@ -1591,10 +1596,12 @@ class CertoraBuildGenerator:
|
|
|
1591
1596
|
"evm.bytecode.functionDebugData"]
|
|
1592
1597
|
ast_selection = ["id", "ast"]
|
|
1593
1598
|
elif compiler_collector_lang == CompilerLangVy():
|
|
1594
|
-
main_contract_for_output_selection = "*"
|
|
1595
1599
|
sources_dict = {}
|
|
1596
|
-
|
|
1597
|
-
|
|
1600
|
+
vyper_custom_std_json_in = None
|
|
1601
|
+
|
|
1602
|
+
if self.context.vyper_custom_std_json_in_map:
|
|
1603
|
+
main_contract_for_output_selection = contract_file_as_provided
|
|
1604
|
+
if contract_file_as_provided in self.context.vyper_custom_std_json_in_map:
|
|
1598
1605
|
"""
|
|
1599
1606
|
If we're given a custom standard_json, we'll take from it the sources and
|
|
1600
1607
|
the search paths.
|
|
@@ -1606,18 +1613,36 @@ class CertoraBuildGenerator:
|
|
|
1606
1613
|
if we get more projects.
|
|
1607
1614
|
"""
|
|
1608
1615
|
vyper_custom_std_json_in = self.context.vyper_custom_std_json_in_map[contract_file_as_provided]
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1616
|
+
elif self.context.resolve_vyper_imports and compiler_collector.compiler_version >= (0, 4, 0):
|
|
1617
|
+
main_contract_for_output_selection = contract_file_as_provided
|
|
1618
|
+
"""
|
|
1619
|
+
If resolve_vyper_imports is enabled, we ask the vyper compiler to generate a standard_json for us.
|
|
1620
|
+
"""
|
|
1621
|
+
compiler_ver_to_run = get_relevant_compiler(Path(contract_file_as_provided), self.context)
|
|
1622
|
+
vyper_options = f"-f solc_json {contract_file_as_provided} --disable-sys-path"
|
|
1623
|
+
for path in ((self.context.vyper_system_path or []) + (self.context.vyper_import_path or [])):
|
|
1624
|
+
vyper_options += f" -p {path}"
|
|
1625
|
+
Util.run_compiler_cmd(f"{compiler_ver_to_run} {vyper_options}",
|
|
1626
|
+
f"{contract_file_posix_abs.name}.std_json_generated.json",
|
|
1627
|
+
wd=compile_wd)
|
|
1628
|
+
vyper_custom_std_json_in = compiler_collector_lang.compilation_output_path(
|
|
1629
|
+
f"{contract_file_posix_abs.name}.std_json_generated.stdout.json")
|
|
1630
|
+
|
|
1631
|
+
if vyper_custom_std_json_in:
|
|
1632
|
+
with open(vyper_custom_std_json_in) as custom:
|
|
1633
|
+
custom_json = json.load(custom)
|
|
1634
|
+
sources_dict = custom_json.get("sources", None)
|
|
1635
|
+
search_paths_arr = custom_json.get("settings", {}).get("search_paths", None)
|
|
1636
|
+
additional_asts = [x for x, _ in sources_dict.items() if x.endswith(".vy")]
|
|
1637
|
+
|
|
1638
|
+
if not sources_dict:
|
|
1639
|
+
with open(contract_file_posix_abs) as f:
|
|
1615
1640
|
contents = f.read()
|
|
1616
1641
|
sources_dict = {str(contract_file_posix_abs): {"content": contents}}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1642
|
+
output_selection = ["abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers"]
|
|
1643
|
+
if compiler_collector.compiler_version >= (0, 4, 4):
|
|
1644
|
+
output_selection += ["metadata", "evm.deployedBytecode.symbolMap"]
|
|
1645
|
+
ast_selection = ["ast"]
|
|
1621
1646
|
else:
|
|
1622
1647
|
# "non-compilable" language so no need to deal with it
|
|
1623
1648
|
fatal_error(compiler_logger, "Expected only Solidity and Vyper as "
|
|
@@ -2483,8 +2508,8 @@ class CertoraBuildGenerator:
|
|
|
2483
2508
|
return f"{contract}_{address}"
|
|
2484
2509
|
|
|
2485
2510
|
@staticmethod
|
|
2486
|
-
def get_primary_contract_from_sdc(contracts: List[ContractInSDC], primary: str) -> List[ContractInSDC]:
|
|
2487
|
-
return [x for x in contracts if x.name == primary]
|
|
2511
|
+
def get_primary_contract_from_sdc(contracts: List[ContractInSDC], primary: str, primary_file: str) -> List[ContractInSDC]:
|
|
2512
|
+
return [x for x in contracts if x.name == primary and Util.abs_norm_path(x.original_file) == Util.abs_norm_path(primary_file)]
|
|
2488
2513
|
|
|
2489
2514
|
@staticmethod
|
|
2490
2515
|
def generate_library_import(file_absolute_path: str, library_name: str) -> str:
|
|
@@ -2945,7 +2970,7 @@ class CertoraBuildGenerator:
|
|
|
2945
2970
|
sdc.original_srclist,
|
|
2946
2971
|
sdc.report_srclist,
|
|
2947
2972
|
f"{sdc.sdc_name}_{library_contract.name}",
|
|
2948
|
-
self.get_primary_contract_from_sdc(sdc.contracts, library_contract.name),
|
|
2973
|
+
self.get_primary_contract_from_sdc(sdc.contracts, library_contract.name, library_contract.original_file),
|
|
2949
2974
|
[],
|
|
2950
2975
|
{},
|
|
2951
2976
|
{},
|
|
@@ -2956,7 +2981,7 @@ class CertoraBuildGenerator:
|
|
|
2956
2981
|
self.SDCs[self.get_sdc_key(sdc_lib.primary_contract, sdc_lib.primary_contract_address)] = sdc_lib
|
|
2957
2982
|
|
|
2958
2983
|
# Filter out irrelevant contracts, now that we extracted the libraries, leave just the primary
|
|
2959
|
-
sdc.contracts = self.get_primary_contract_from_sdc(sdc.contracts, sdc.primary_contract)
|
|
2984
|
+
sdc.contracts = self.get_primary_contract_from_sdc(sdc.contracts, sdc.primary_contract, sdc.sdc_origin_file)
|
|
2960
2985
|
assert len(
|
|
2961
2986
|
sdc.contracts) == 1, f"Found multiple primary contracts ({sdc.contracts}) in SDC {sdc.sdc_name}"
|
|
2962
2987
|
|
|
@@ -2977,8 +3002,13 @@ class CertoraBuildGenerator:
|
|
|
2977
3002
|
corresponding to the namespaced types.
|
|
2978
3003
|
|
|
2979
3004
|
Args:
|
|
2980
|
-
original_file: Path to the Solidity file containing namespaced storage declarations
|
|
3005
|
+
original_file: Path to the Solidity file containing namespaced storage declarations.
|
|
3006
|
+
This may be a (transitivly) imported file rather than a user-specified target.
|
|
2981
3007
|
ns_storage: Set of tuples (type_name, namespace) for each namespaced storage
|
|
3008
|
+
compiler_version: The compiler version to use, already resolved from target_file
|
|
3009
|
+
target_file: The user-specified file (from conf file) that imported original_file.
|
|
3010
|
+
Used to resolve compilation settings (solc_optimize_map, solc_via_ir_map, etc.)
|
|
3011
|
+
for the temporary harness file, since original_file may not have entries in those maps.
|
|
2982
3012
|
|
|
2983
3013
|
Returns:
|
|
2984
3014
|
NewStorageInfo: A tuple (fields, types) where:
|
|
@@ -2997,8 +3027,24 @@ class CertoraBuildGenerator:
|
|
|
2997
3027
|
# directly can cause issues.
|
|
2998
3028
|
tmp_file.write(f"import \"{original_file}\";\n\n")
|
|
2999
3029
|
rel_path = os.path.relpath(tmp_file.name, Path.cwd())
|
|
3000
|
-
|
|
3001
|
-
|
|
3030
|
+
tmp_abs_path = Util.abs_posix_path(tmp_file.name)
|
|
3031
|
+
# Add the temp file to all map attributes so that map lookups
|
|
3032
|
+
# (solc_optimize_map, solc_via_ir_map, etc.) succeed during compilation.
|
|
3033
|
+
# We resolve values from target_file (a user-specified file in context.file_paths)
|
|
3034
|
+
# rather than original_file (which may be a transitive dependency not in any map).
|
|
3035
|
+
# We store both relative and absolute path keys because different lookup sites
|
|
3036
|
+
# normalize paths differently: get_relevant_compiler uses relative paths,
|
|
3037
|
+
# while _handle_via_ir/_handle_optimize use absolute paths.
|
|
3038
|
+
for map_attr in self.context.app.attr_class.all_map_attrs():
|
|
3039
|
+
map_attr_value = getattr(self.context, map_attr, None)
|
|
3040
|
+
if not map_attr_value:
|
|
3041
|
+
continue
|
|
3042
|
+
attr_name = map_attr[:-len(Util.MAP_SUFFIX)]
|
|
3043
|
+
target_value = Ctx.get_map_attribute_value(
|
|
3044
|
+
self.context, Path(target_file), attr_name
|
|
3045
|
+
)
|
|
3046
|
+
if target_value is not None:
|
|
3047
|
+
map_attr_value.update({rel_path: target_value, tmp_abs_path: target_value}, last=False)
|
|
3002
3048
|
# Write the harness contract with dummy fields for each namespaced storage
|
|
3003
3049
|
var_to_slot = storageExtension.write_harness_contract(tmp_file, harness_name, ns_storage)
|
|
3004
3050
|
tmp_file.flush()
|
|
@@ -4121,8 +4167,13 @@ def build_from_scratch(context: CertoraContext,
|
|
|
4121
4167
|
indent=4,
|
|
4122
4168
|
sort_keys=True)
|
|
4123
4169
|
|
|
4170
|
+
# check if asts file exists (only when --dump_asts is used)
|
|
4171
|
+
asts_file = Util.get_asts_file()
|
|
4172
|
+
asts_file_if_exists = asts_file if asts_file.exists() else None
|
|
4173
|
+
|
|
4124
4174
|
return CachedFiles(certora_build_file, all_contract_files, build_output_props_file, may_store_in_build_cache,
|
|
4125
|
-
path_with_additional_included_files=absolute_sources_dir
|
|
4175
|
+
path_with_additional_included_files=absolute_sources_dir,
|
|
4176
|
+
asts_file=asts_file_if_exists)
|
|
4126
4177
|
|
|
4127
4178
|
|
|
4128
4179
|
def build_from_cache_or_scratch(context: CertoraContext,
|
|
@@ -4204,6 +4255,10 @@ def build_from_cache_or_scratch(context: CertoraContext,
|
|
|
4204
4255
|
else:
|
|
4205
4256
|
shutil.copyfile(p, Util.get_certora_sources_dir() / p.name)
|
|
4206
4257
|
|
|
4258
|
+
# restore asts file from cache if present
|
|
4259
|
+
if cached_files.asts_file is not None and cached_files.asts_file.exists():
|
|
4260
|
+
shutil.copyfile(cached_files.asts_file, Util.get_asts_file())
|
|
4261
|
+
|
|
4207
4262
|
return False, cached_files
|
|
4208
4263
|
|
|
4209
4264
|
|
{certora_cli-8.8.1 → certora_cli-8.13.0}/certora_cli/CertoraProver/certoraBuildCacheManager.py
RENAMED
|
@@ -41,6 +41,9 @@ class CachedFiles:
|
|
|
41
41
|
# to keep .post_autofinders
|
|
42
42
|
path_with_additional_included_files: Path
|
|
43
43
|
|
|
44
|
+
# optional asts file (only present when --dump_asts is used)
|
|
45
|
+
asts_file: Optional[Path] = None
|
|
46
|
+
|
|
44
47
|
def all_exist(self, main_cache_entry_dir: Path, sub_cache_key: str) -> bool:
|
|
45
48
|
exist = self.certora_build_file.exists() and \
|
|
46
49
|
self.certora_build_file == main_cache_entry_dir / f"{sub_cache_key}.{CachedFiles.certora_build_suffix}"
|
|
@@ -55,6 +58,7 @@ class CachedFiles:
|
|
|
55
58
|
file_list_suffix = "file_list.json"
|
|
56
59
|
build_output_props_suffix = "build_output_props.json"
|
|
57
60
|
additional_included_files = "additional_included_files"
|
|
61
|
+
asts_suffix = "asts.json"
|
|
58
62
|
|
|
59
63
|
|
|
60
64
|
class CertoraBuildCacheManager:
|
|
@@ -124,8 +128,14 @@ class CertoraBuildCacheManager:
|
|
|
124
128
|
return None
|
|
125
129
|
|
|
126
130
|
additional_included_files = main_cache_entry_dir / f"{sub_cache_key}.{CachedFiles.additional_included_files}"
|
|
131
|
+
|
|
132
|
+
# check if asts file exists in cache
|
|
133
|
+
asts_file_in_cache = main_cache_entry_dir / f"{sub_cache_key}.{CachedFiles.asts_suffix}"
|
|
134
|
+
asts_file = asts_file_in_cache if asts_file_in_cache.exists() else None
|
|
135
|
+
|
|
127
136
|
return CachedFiles(certora_build_file, all_contract_files, build_output_props_file,
|
|
128
|
-
may_store_in_build_cache=True, path_with_additional_included_files=additional_included_files
|
|
137
|
+
may_store_in_build_cache=True, path_with_additional_included_files=additional_included_files,
|
|
138
|
+
asts_file=asts_file)
|
|
129
139
|
|
|
130
140
|
@staticmethod
|
|
131
141
|
def save_build_cache(context: CertoraContext, cached_files: CachedFiles) -> None:
|
|
@@ -170,6 +180,11 @@ class CertoraBuildCacheManager:
|
|
|
170
180
|
# save additional props file
|
|
171
181
|
shutil.copyfile(cached_files.build_output_props_file,
|
|
172
182
|
main_cache_entry_dir / f"{sub_cache_key}.{CachedFiles.build_output_props_suffix}")
|
|
183
|
+
# save asts file if present
|
|
184
|
+
if cached_files.asts_file is not None and cached_files.asts_file.exists():
|
|
185
|
+
shutil.copyfile(cached_files.asts_file,
|
|
186
|
+
main_cache_entry_dir / f"{sub_cache_key}.{CachedFiles.asts_suffix}")
|
|
187
|
+
|
|
173
188
|
# save .post_autofinders from additional included files
|
|
174
189
|
trg_path_with_additional_included_files = \
|
|
175
190
|
main_cache_entry_dir / f"{sub_cache_key}.{CachedFiles.additional_included_files}"
|
|
@@ -83,6 +83,9 @@ def build_rust_app(context: CertoraContext) -> None:
|
|
|
83
83
|
build_command.extend(["--tools-version", context.cargo_tools_version])
|
|
84
84
|
context.rust_project_directory = Util.find_nearest_cargo_toml()
|
|
85
85
|
|
|
86
|
+
if getattr(context, 'solana_sbf_arch', None) is not None:
|
|
87
|
+
build_command.extend(["--arch", context.solana_sbf_arch])
|
|
88
|
+
|
|
86
89
|
if context.cargo_features is not None:
|
|
87
90
|
build_command.append(feature_flag)
|
|
88
91
|
build_command.append(' '.join(context.cargo_features))
|
|
@@ -55,13 +55,42 @@ def build_sui_project(context: CertoraContext, timings: Dict) -> None:
|
|
|
55
55
|
def set_sui_build_directory(context: CertoraContext) -> None:
|
|
56
56
|
sources: Set[Path] = set()
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
move_toml_file: Path | None = None
|
|
59
|
+
|
|
60
|
+
if context.move_path:
|
|
61
|
+
# If move_path is specified, we assume the user has already built the spec package separately. This is a legacy
|
|
62
|
+
# option that should not be used by new projects; they should use `spec_package_path` and/or `build_script`
|
|
63
|
+
# instead.
|
|
64
|
+
assert not context.build_script, "cannot have move_path and build_script together"
|
|
65
|
+
assert not context.spec_package_path, "cannot have move_path and spec_package_path together"
|
|
66
|
+
context.sui_package_summary_path = None
|
|
67
|
+
else:
|
|
68
|
+
if context.spec_package_path:
|
|
69
|
+
# Verify that there is a Move.toml at the specified spec_package_path
|
|
70
|
+
spec_package_dir = Path(context.spec_package_path)
|
|
71
|
+
move_toml_file = spec_package_dir / "Move.toml"
|
|
72
|
+
if not move_toml_file.exists():
|
|
73
|
+
raise Util.CertoraUserInputError(f"Could not find Move.toml at specified spec_package_path '{context.spec_package_path}'")
|
|
74
|
+
else:
|
|
75
|
+
# If spec_package_path is not specified, try to find the package that the current directory is in.
|
|
76
|
+
move_toml_file = Util.find_file_in_parents("Move.toml")
|
|
77
|
+
if not move_toml_file:
|
|
78
|
+
raise Util.CertoraUserInputError("Could not find Move.toml, and no spec_package_path was specified.")
|
|
79
|
+
spec_package_dir = move_toml_file.parent
|
|
80
|
+
context.spec_package_path = str(spec_package_dir)
|
|
81
|
+
|
|
63
82
|
sources.add(move_toml_file.absolute())
|
|
64
|
-
|
|
83
|
+
context.move_path = str(spec_package_dir / "build")
|
|
84
|
+
context.sui_package_summary_path = spec_package_dir / "package_summaries"
|
|
85
|
+
|
|
86
|
+
if context.build_script:
|
|
87
|
+
# Run the user-provided build script
|
|
88
|
+
script_path = Path(context.build_script).resolve()
|
|
89
|
+
sources.add(script_path)
|
|
90
|
+
run_sui_build([str(script_path), str(spec_package_dir)])
|
|
91
|
+
else:
|
|
92
|
+
# Build the package using `sui move summary`, which will also produce the package summaries.
|
|
93
|
+
run_sui_build(["sui", "move", "summary", "--test", "--path", str(move_toml_file.parent)])
|
|
65
94
|
|
|
66
95
|
assert context.move_path, "expecting move_path to be set after build"
|
|
67
96
|
move_dir = Path(context.move_path)
|
|
@@ -81,6 +110,12 @@ def set_sui_build_directory(context: CertoraContext) -> None:
|
|
|
81
110
|
Util.get_build_dir() / move_dir.name,
|
|
82
111
|
ignore=shutil.ignore_patterns('*.move'))
|
|
83
112
|
|
|
113
|
+
# Copy package summary directory if it exists. Projects built manually with "sui move build" may not have this.
|
|
114
|
+
if context.sui_package_summary_path and context.sui_package_summary_path.exists():
|
|
115
|
+
assert context.sui_package_summary_path.is_dir(), f"Package summary path '{context.sui_package_summary_path}' is not a directory"
|
|
116
|
+
shutil.copytree(context.sui_package_summary_path,
|
|
117
|
+
Util.get_build_dir() / context.sui_package_summary_path.name)
|
|
118
|
+
|
|
84
119
|
try:
|
|
85
120
|
# Create generators
|
|
86
121
|
build_source_tree(sources, context)
|
|
@@ -88,11 +123,8 @@ def set_sui_build_directory(context: CertoraContext) -> None:
|
|
|
88
123
|
except Exception as e:
|
|
89
124
|
raise Util.CertoraUserInputError(f"Collecting build files failed with the exception: {e}")
|
|
90
125
|
|
|
91
|
-
def run_sui_build(context: CertoraContext, package_dir: Path) -> None:
|
|
92
|
-
assert not context.move_path, "run_sui_build: expecting move_path to be empty"
|
|
93
|
-
|
|
94
|
-
build_cmd = ["sui", "move", "build", "--test", "--path", str(package_dir)]
|
|
95
126
|
|
|
127
|
+
def run_sui_build(build_cmd: list[str]) -> None:
|
|
96
128
|
try:
|
|
97
129
|
build_cmd_text = ' '.join(build_cmd)
|
|
98
130
|
log.info(f"Building by calling `{build_cmd_text}`")
|
|
@@ -102,8 +134,6 @@ def run_sui_build(context: CertoraContext, package_dir: Path) -> None:
|
|
|
102
134
|
if result.returncode != 0:
|
|
103
135
|
raise Util.CertoraUserInputError(f"Error running `{build_cmd_text}`")
|
|
104
136
|
|
|
105
|
-
context.move_path = str(package_dir / "build")
|
|
106
|
-
|
|
107
137
|
except Util.TestResultsReady as e:
|
|
108
138
|
raise e
|
|
109
139
|
except Util.CertoraUserInputError as e:
|
|
@@ -611,10 +611,16 @@ class CloudVerification:
|
|
|
611
611
|
rust_jar_settings.append('-solanaInlining')
|
|
612
612
|
rust_jar_settings.append(paths_in_source_dir(self.context.solana_inlining))
|
|
613
613
|
|
|
614
|
+
if self.context.assert_on_panic is not None:
|
|
615
|
+
rust_jar_settings.extend(['-solanaAssertOnPanic', str(self.context.assert_on_panic).lower()])
|
|
616
|
+
|
|
614
617
|
auth_data["jarSettings"] = rust_jar_settings + jar_settings
|
|
615
618
|
|
|
616
619
|
elif Attrs.is_sui_app():
|
|
617
620
|
sui_jar_settings = ['-movePath', Path(self.context.move_path).name]
|
|
621
|
+
if self.context.sui_package_summary_path and self.context.sui_package_summary_path.exists():
|
|
622
|
+
sui_jar_settings.append('-suiPackageSummaryPath')
|
|
623
|
+
sui_jar_settings.append(self.context.sui_package_summary_path.name)
|
|
618
624
|
auth_data["jarSettings"] = sui_jar_settings + jar_settings
|
|
619
625
|
|
|
620
626
|
elif Attrs.is_concord_app():
|
|
@@ -766,6 +772,9 @@ class CloudVerification:
|
|
|
766
772
|
Util.get_configuration_layout_data_file(),
|
|
767
773
|
Util.get_build_dir() / Path(self.context.move_path).name]
|
|
768
774
|
|
|
775
|
+
if self.context.sui_package_summary_path and self.context.sui_package_summary_path.exists():
|
|
776
|
+
files_list.append(Util.get_build_dir() / self.context.sui_package_summary_path.name)
|
|
777
|
+
|
|
769
778
|
if Util.get_certora_sources_dir().exists():
|
|
770
779
|
files_list.append(Util.get_certora_sources_dir())
|
|
771
780
|
|
|
@@ -63,6 +63,9 @@ def is_evm_app_class(context: CertoraContext) -> bool:
|
|
|
63
63
|
def is_rust_app_class(context: CertoraContext) -> bool:
|
|
64
64
|
return issubclass(context.app, App.RustAppClass)
|
|
65
65
|
|
|
66
|
+
def is_move_app_class(context: CertoraContext) -> bool:
|
|
67
|
+
return issubclass(context.app, App.MoveAppClass)
|
|
68
|
+
|
|
66
69
|
def get_attr_value(context: CertoraContext, attr: AttrUtil.AttributeDefinition) -> Any:
|
|
67
70
|
conf_key = attr.get_conf_key()
|
|
68
71
|
return getattr(context, conf_key, None)
|
|
@@ -133,6 +136,9 @@ def get_local_run_cmd(context: CertoraContext) -> List[str]:
|
|
|
133
136
|
# For local runs, we want path to be relative to cwd instead of zip root.
|
|
134
137
|
move_rel_path = os.path.relpath(Path(context.move_path), os.getcwd())
|
|
135
138
|
run_args.extend(['-movePath', move_rel_path])
|
|
139
|
+
if context.sui_package_summary_path and context.sui_package_summary_path.exists():
|
|
140
|
+
spec_package_summary_rel_path = os.path.relpath(context.sui_package_summary_path, os.getcwd())
|
|
141
|
+
run_args.extend(['-suiPackageSummaryPath', spec_package_summary_rel_path])
|
|
136
142
|
elif is_rust_app_class(context):
|
|
137
143
|
# For local runs, we want path to be relative to cwd instead of zip root.
|
|
138
144
|
rust_rel_path = os.path.relpath(Path(context.files[0]), os.getcwd())
|
|
@@ -284,6 +290,9 @@ def get_args(args_list: List[str], app: Type[App.CertoraApp]) -> CertoraContext:
|
|
|
284
290
|
Util.reset_certora_internal_dir(context.build_dir)
|
|
285
291
|
os.rename(current_build_directory, context.build_dir)
|
|
286
292
|
|
|
293
|
+
if is_evm_app_class(context):
|
|
294
|
+
handle_vyper_system_path(context)
|
|
295
|
+
|
|
287
296
|
# Store current options (including the ones read from .conf file)
|
|
288
297
|
context.conf_options = current_conf_to_file(context)
|
|
289
298
|
|
|
@@ -297,6 +306,8 @@ def get_args(args_list: List[str], app: Type[App.CertoraApp]) -> CertoraContext:
|
|
|
297
306
|
validator.handle_concord_attrs()
|
|
298
307
|
if is_rust_app_class(context):
|
|
299
308
|
validator.check_rust_args_post_argparse()
|
|
309
|
+
if is_move_app_class(context):
|
|
310
|
+
validator.check_move_args_post_argparse()
|
|
300
311
|
|
|
301
312
|
attrs_to_relative(context)
|
|
302
313
|
# Setup defaults (defaults are not recorded in conf file)
|
|
@@ -594,14 +605,14 @@ def run_local_spec_check(with_typechecking: bool, context: CertoraContext, extra
|
|
|
594
605
|
raise Util.CertoraUserInputError("Cannot run local checks because of missing a suitable java installation. "
|
|
595
606
|
"To skip local checks run with the --disable_local_typechecking flag")
|
|
596
607
|
|
|
597
|
-
def
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
return input_path
|
|
608
|
+
def to_relative(input_path: Union[str, Path]) -> Union[str, Path]:
|
|
609
|
+
path = Path(input_path) if isinstance(input_path, str) else input_path
|
|
610
|
+
if path.is_absolute():
|
|
611
|
+
relative_path = os.path.relpath(path, Path.cwd()) # Path.relative_to only works for subdirectories
|
|
612
|
+
return str(relative_path) if isinstance(input_path, str) else relative_path
|
|
613
|
+
return input_path
|
|
604
614
|
|
|
615
|
+
def attrs_to_relative(context: CertoraContext) -> None:
|
|
605
616
|
def str_attr_to_relative(attr_name: str) -> None:
|
|
606
617
|
attr_value = getattr(context, attr_name, None)
|
|
607
618
|
if attr_value:
|
|
@@ -647,7 +658,6 @@ def attrs_to_relative(context: CertoraContext) -> None:
|
|
|
647
658
|
if Path(spec_file).is_absolute():
|
|
648
659
|
context.verify = ':'.join([contract, str(to_relative(spec_file))])
|
|
649
660
|
|
|
650
|
-
cwd = Path.cwd()
|
|
651
661
|
str_attr_to_relative('packages_path')
|
|
652
662
|
str_attr_to_relative('bytecode_spec')
|
|
653
663
|
str_attr_to_relative('yul_abi')
|
|
@@ -683,3 +693,24 @@ def get_map_attribute_value(context: CertoraContext, path: Path, attr_name: str)
|
|
|
683
693
|
if glob.globmatch(str(path), pattern, flags=glob.GLOBSTAR):
|
|
684
694
|
return entry_value
|
|
685
695
|
raise RuntimeError(f"cannot match {attr_name} to {path} from {attr_name}_map")
|
|
696
|
+
|
|
697
|
+
def handle_vyper_system_path(context: CertoraContext) -> None:
|
|
698
|
+
"""
|
|
699
|
+
Just like the Vyper compiler, we add the sys.path to the search path for imports, which allows us to resolve imports
|
|
700
|
+
using a package manager.
|
|
701
|
+
|
|
702
|
+
Note that we do this here, rather than allowing the Vyper compiler to do it, because we want to persist these paths
|
|
703
|
+
in the generated run.conf file, to make it easy to reproduce in a different environment.
|
|
704
|
+
"""
|
|
705
|
+
if context.resolve_vyper_imports:
|
|
706
|
+
if not context.vyper_system_path:
|
|
707
|
+
# Pass the directories from sys.path in reversed order (Vyper treats later paths as higher precedence)
|
|
708
|
+
context.vyper_system_path = [
|
|
709
|
+
to_relative(p) for p in reversed(sys.path) if Path(p).is_dir()
|
|
710
|
+
]
|
|
711
|
+
else:
|
|
712
|
+
# Filter out any directories that do not exist, to make the generated run.conf file more portable to
|
|
713
|
+
# different environments.
|
|
714
|
+
context.vyper_system_path = [
|
|
715
|
+
p for p in context.vyper_system_path if Path(p).is_dir()
|
|
716
|
+
]
|