Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ WORKDIR /app
COPY __init__.py /opt/benchmarks/__init__.py
COPY tooling/__init__.py /opt/benchmarks/tooling/__init__.py
COPY tooling/command_runner.py /opt/benchmarks/tooling/command_runner.py
COPY tooling/spike_utils.py /opt/benchmarks/tooling/spike_utils.py

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Whitelist the helper in the Docker build context

All five provider Compose files build with benchmarks/ as their context, whose .dockerignore starts with ** and re-includes only tooling/__init__.py and tooling/command_runner.py. Because tooling/spike_utils.py is still excluded, this new COPY has no source in the transmitted context and every affected provider image build fails before its Oracle can run; add the helper to the .dockerignore allowlist.

Useful? React with 👍 / 👎.

COPY datasets/provider-feasibility-v1/cddlib/environment/input.json datasets/provider-feasibility-v1/cddlib/environment/pin.json datasets/provider-feasibility-v1/cddlib/environment/spike.py datasets/provider-feasibility-v1/cddlib/environment/submission_schema.json /app/
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONPATH=/opt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"task_id": "jacobian/cddlib",
"provider": "cddlib/pycddlib",
"contract": "jacobian.cddlib-hv-spike/v1",
"pin_sha256": "sha256:15b0b5b4d608bc2f354dd484c44aa3da7441d615ab9650d6f7611c7e97af7871"
"pin_sha256": "sha256:129610626988ff70540c9d7aef51efbda771ccee199eb44b629de50ad589104f"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"adapter_source_sha256": "sha256:8a6f0c90929f3cf9582208844d4d9ce10258bc5721dbe8581171dbc180eb05cd",
"adapter_source_sha256": "sha256:ddbf25b188f6fd5ca6aca2fb0ac6f64c514cb76cc00a4cb504fd660baf343d38",
"contract": "jacobian.cddlib-hv-spike/v1",
"provider": "cddlib/pycddlib",
"reproduction": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
from typing import Any

from benchmarks.tooling.command_runner import (
ToolCommandRequest,
ToolCommandResult,
ToolCommandStatus,
run_tool_command,
)
from benchmarks.tooling.spike_utils import (
canonical_json,
default_runner,
sha256_bytes,
Comment on lines +20 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bind the extracted helper to the provider pins

For cddlib, GUDHI, and Regina, adapter_source_sha256 still validates only spike.py, even though canonical serialization, hashing, and process-launch behavior now come from this separate module. If spike_utils.py changes while spike.py and its pin remain unchanged, the adapter accepts the frozen source digest and reports it despite executing different code; include the helper's digest in each applicable pin and validate it before execution, or keep the pinned behavior within the hashed adapter.

AGENTS.md reference: AGENTS.md:L66-L67

Useful? React with 👍 / 👎.

)

PIN_PATH = Path(__file__).with_name("pin.json")
Expand All @@ -41,28 +44,6 @@
_WORKER_ERROR_PREFIX = b"JACOBIAN_SPIKE_ERROR "


def _default_runner(
command: Sequence[str],
*,
input_bytes: bytes,
timeout_seconds: float,
environment: Mapping[str, str],
stdout_limit: int,
stderr_limit: int,
) -> ToolCommandResult:
request = ToolCommandRequest(
executable=command[0],
arguments=tuple(command[1:]),
environment=environment,
cwd=str(Path.cwd()),
timeout_seconds=timeout_seconds,
stdin_bytes=input_bytes,
stdout_limit_bytes=stdout_limit,
stderr_limit_bytes=stderr_limit,
)
return run_tool_command(request)


class CddlibSpikeError(RuntimeError):
"""A typed non-conclusion from the optional-provider spike."""

Expand All @@ -73,10 +54,6 @@ def __init__(self, status: str, code: str, detail: str) -> None:
self.detail = detail


def _sha256_bytes(payload: bytes) -> str:
return f"sha256:{hashlib.sha256(payload).hexdigest()}"


def _sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
Expand All @@ -85,13 +62,6 @@ def _sha256_file(path: Path) -> str:
return f"sha256:{digest.hexdigest()}"


def _canonical_json(payload: object) -> bytes:
return (
json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
+ "\n"
).encode("ascii")


def _load_pin(path: Path) -> dict[str, Any]:
try:
payload = json.loads(path.read_text(encoding="utf-8"))
Expand Down Expand Up @@ -272,7 +242,7 @@ def _inspect_archive(

for member_name, payload in contents.items():
expected = source_pin["identity_members"][member_name]
if _sha256_bytes(payload) != expected["sha256"]:
if sha256_bytes(payload) != expected["sha256"]:
raise CddlibSpikeError(
"REJECTED",
"SOURCE_METADATA_MISMATCH",
Expand Down Expand Up @@ -782,7 +752,7 @@ def _parse_provider_output(output: bytes, pin: Mapping[str, Any]) -> dict[str, A
"PROVIDER_OUTPUT_MALFORMED",
"The pycddlib output is not canonical ASCII JSON.",
) from exc
if not isinstance(payload, dict) or _canonical_json(payload) != output:
if not isinstance(payload, dict) or canonical_json(payload) != output:
raise CddlibSpikeError(
"ERROR",
"PROVIDER_OUTPUT_MALFORMED",
Expand Down Expand Up @@ -817,7 +787,7 @@ def _parse_provider_output(output: bytes, pin: Mapping[str, Any]) -> dict[str, A
reproduction = pin["reproduction"]
if (
mathematical != _expected_mathematical(pin)
or _sha256_bytes(_canonical_json(mathematical))
or sha256_bytes(canonical_json(mathematical))
!= reproduction["expected_mathematical_output_sha256"]
):
raise CddlibSpikeError(
Expand All @@ -834,7 +804,7 @@ def run_spike(
cddlib_source_archive: Path,
pycddlib_source_archive: Path,
timeout_seconds: float = 10,
runner: ProcessRunner = _default_runner,
runner: ProcessRunner = default_runner,
pin_path: Path = PIN_PATH,
adapter_source: Path = ADAPTER_SOURCE,
) -> dict[str, Any]:
Expand Down Expand Up @@ -904,7 +874,7 @@ def run_spike(
},
"reproduction": {
"scope": pin["reproduction"]["scope"],
"provider_output_sha256": _sha256_bytes(output),
"provider_output_sha256": sha256_bytes(output),
"exact_arithmetic": provider_output["exact_arithmetic"],
"cases": provider_output["cases"],
},
Expand Down Expand Up @@ -964,7 +934,7 @@ def _worker(pin_path: Path) -> int:
installed_version = importlib.metadata.version("pycddlib")
if installed_version != pin["versions"]["pycddlib"]:
sys.stdout.buffer.write(
_canonical_json(
canonical_json(
{
"contract": pin["contract"],
"provider": pin["provider"],
Expand Down Expand Up @@ -1072,7 +1042,7 @@ def _worker(pin_path: Path) -> int:
"distribution_record_sha256": _sha256_file(record_path),
},
}
sys.stdout.buffer.write(_canonical_json(payload))
sys.stdout.buffer.write(canonical_json(payload))
return 0


Expand All @@ -1094,7 +1064,7 @@ def main(argv: Sequence[str] | None = None) -> int:
"code": exc.code,
"detail": exc.detail,
}
sys.stderr.buffer.write(_WORKER_ERROR_PREFIX + _canonical_json(payload))
sys.stderr.buffer.write(_WORKER_ERROR_PREFIX + canonical_json(payload))
return 64
if (
args.python_executable is None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"provider": {"const": "cddlib/pycddlib"},
"contract": {"const": "jacobian.cddlib-hv-spike/v1"},
"status": {"enum": ["COMPLETED", "TIMEOUT", "CANCELLED", "ERROR", "REJECTED"]},
"pin_sha256": {"const": "sha256:15b0b5b4d608bc2f354dd484c44aa3da7441d615ab9650d6f7611c7e97af7871"}
"pin_sha256": {"const": "sha256:129610626988ff70540c9d7aef51efbda771ccee199eb44b629de50ad589104f"}
}
},
"claimed_assurance": {"enum": ["UNVERIFIED","COMPUTED"]},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
TASK_ID = "jacobian/cddlib"
PROVIDER = "cddlib/pycddlib"
CONTRACT = "jacobian.cddlib-hv-spike/v1"
PIN = "sha256:15b0b5b4d608bc2f354dd484c44aa3da7441d615ab9650d6f7611c7e97af7871"
PIN = "sha256:129610626988ff70540c9d7aef51efbda771ccee199eb44b629de50ad589104f"

report = json.loads(REPORT.read_text())
status = report.get("status", "ERROR")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"task_id": "jacobian/cddlib",
"provider": "cddlib/pycddlib",
"contract": "jacobian.cddlib-hv-spike/v1",
"pin_sha256": "sha256:15b0b5b4d608bc2f354dd484c44aa3da7441d615ab9650d6f7611c7e97af7871",
"pin_sha256": "sha256:129610626988ff70540c9d7aef51efbda771ccee199eb44b629de50ad589104f",
"report_conclusion": "SPIKE_PASSED_PRODUCTION_DEFERRED",
"report_assurance": "OBSERVED_EXACT_PROVIDER_BEHAVIOR_WITH_SOUNDNESS_REPLAY",
"reproduction": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"task_id": "jacobian/cddlib",
"provider": "cddlib/pycddlib",
"contract": "jacobian.cddlib-hv-spike/v1",
"pin_sha256": "sha256:15b0b5b4d608bc2f354dd484c44aa3da7441d615ab9650d6f7611c7e97af7871"
"pin_sha256": "sha256:129610626988ff70540c9d7aef51efbda771ccee199eb44b629de50ad589104f"
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"const": "jacobian.cddlib-hv-spike/v1"
},
"pin_sha256": {
"const": "sha256:15b0b5b4d608bc2f354dd484c44aa3da7441d615ab9650d6f7611c7e97af7871"
"const": "sha256:129610626988ff70540c9d7aef51efbda771ccee199eb44b629de50ad589104f"
},
"provider": {
"const": "cddlib/pycddlib"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ WORKDIR /app
COPY __init__.py /opt/benchmarks/__init__.py
COPY tooling/__init__.py /opt/benchmarks/tooling/__init__.py
COPY tooling/command_runner.py /opt/benchmarks/tooling/command_runner.py
COPY tooling/spike_utils.py /opt/benchmarks/tooling/spike_utils.py
COPY datasets/provider-feasibility-v1/cgal/environment/cgal_delaunay_spike.cpp datasets/provider-feasibility-v1/cgal/environment/input.json datasets/provider-feasibility-v1/cgal/environment/cgal_delaunay_pin.json datasets/provider-feasibility-v1/cgal/environment/spike.py datasets/provider-feasibility-v1/cgal/environment/submission_schema.json /app/
RUN g++ -std=c++17 -O2 -I/opt/provider/CGAL-6.2/include /app/cgal_delaunay_spike.cpp -lgmp -lmpfr -o /opt/provider/cgal-spike
ENV PYTHONDONTWRITEBYTECODE=1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
from typing import Any

from benchmarks.tooling.command_runner import (
ToolCommandRequest,
ToolCommandResult,
ToolCommandStatus,
run_tool_command,
)
from benchmarks.tooling.spike_utils import (
default_runner,
sha256_bytes,
)

PIN_PATH = Path(__file__).with_name("cgal_delaunay_pin.json")
Expand All @@ -30,28 +32,6 @@
ProcessRunner = Callable[..., ToolCommandResult]


def _default_runner(
command: Sequence[str],
*,
input_bytes: bytes,
timeout_seconds: float,
environment: Mapping[str, str],
stdout_limit: int,
stderr_limit: int,
) -> ToolCommandResult:
request = ToolCommandRequest(
executable=command[0],
arguments=tuple(command[1:]),
environment=environment,
cwd=str(Path.cwd()),
timeout_seconds=timeout_seconds,
stdin_bytes=input_bytes,
stdout_limit_bytes=stdout_limit,
stderr_limit_bytes=stderr_limit,
)
return run_tool_command(request)


class CgalSpikeError(RuntimeError):
def __init__(self, status: str, code: str, detail: str) -> None:
super().__init__(detail)
Expand All @@ -60,10 +40,6 @@ def __init__(self, status: str, code: str, detail: str) -> None:
self.detail = detail


def _sha256_bytes(payload: bytes) -> str:
return f"sha256:{hashlib.sha256(payload).hexdigest()}"


def _sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
Expand Down Expand Up @@ -279,7 +255,7 @@ def run_spike(
executable: Path,
source_archive: Path,
timeout_seconds: float = 5,
runner: ProcessRunner = _default_runner,
runner: ProcessRunner = default_runner,
pin_path: Path = PIN_PATH,
adapter_source: Path = ADAPTER_SOURCE,
) -> dict[str, Any]:
Expand Down Expand Up @@ -325,14 +301,14 @@ def run_spike(
) from exc
if (
decoded != case["expected_output"]
or _sha256_bytes(output) != case["expected_output_sha256"]
or sha256_bytes(output) != case["expected_output_sha256"]
):
raise CgalSpikeError(
"REJECTED",
"REPRODUCTION_MISMATCH",
f"The CGAL {name} reproduction differs from the frozen result.",
)
observed[name] = _sha256_bytes(output)
observed[name] = sha256_bytes(output)
compiler_support = _compiler_support(
toolchain["compiler"],
pin["supported_gnu_compiler_minimum"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ WORKDIR /app
COPY __init__.py /opt/benchmarks/__init__.py
COPY tooling/__init__.py /opt/benchmarks/tooling/__init__.py
COPY tooling/command_runner.py /opt/benchmarks/tooling/command_runner.py
COPY tooling/spike_utils.py /opt/benchmarks/tooling/spike_utils.py
COPY datasets/provider-feasibility-v1/gudhi/environment/input.json datasets/provider-feasibility-v1/gudhi/environment/pin.json datasets/provider-feasibility-v1/gudhi/environment/spike.py datasets/provider-feasibility-v1/gudhi/environment/submission_schema.json /app/
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONPATH=/opt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"task_id": "jacobian/gudhi",
"provider": "gudhi",
"contract": "jacobian.gudhi-persistence-spike/v1",
"pin_sha256": "sha256:329e57f50ad88ddbf2f6a3fe7cbbb0b5121be7c92a01d3a0b57db9241b1e6813"
"pin_sha256": "sha256:3decd51546ff618689114fb57eff03e1abc50133207e50fcba5c473583c02f4f"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"adapter_source_sha256": "sha256:a6a8f83a0e6ebf6d4783506171e4f8f2be1c185a0a9032a7ff7ba3d2c4855131",
"adapter_source_sha256": "sha256:2406f703ceafb0bff19cda9210358f75670f9ae2a08f7688f7cf168a8975eb4a",
"contract": "jacobian.gudhi-persistence-spike/v1",
"documentation_url": "https://gudhi.inria.fr/python/3.13.0/simplex_tree_ref.html",
"licensing_url": "https://gudhi.inria.fr/licensing/",
Expand Down
Loading
Loading