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
16 changes: 10 additions & 6 deletions packages/syft-job/src/syft_job/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,17 @@ def _digest(
skip: frozenset[str] = frozenset(),
) -> str:
digest = hashlib.sha256()
# Sort on the posix string: WindowsPath sorts case-insensitively.
files = sorted(
path
for path in submission_dir.rglob("*")
if path.is_file()
and not _is_skipped(relative := path.relative_to(submission_dir))
and (entries is None or relative.parts[0] in entries)
and relative.as_posix() not in skip
(
path
for path in submission_dir.rglob("*")
if path.is_file()
and not _is_skipped(relative := path.relative_to(submission_dir))
and (entries is None or relative.parts[0] in entries)
and relative.as_posix() not in skip
),
key=lambda path: path.relative_to(submission_dir).as_posix(),
)
for path in files:
digest.update(path.relative_to(submission_dir).as_posix().encode())
Expand Down
29 changes: 29 additions & 0 deletions packages/syft-job/tests/test_submission_hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""The submission hash must not depend on how the OS sorts paths.

WindowsPath sorts case-insensitively and PosixPath case-sensitively, so a DS on
Windows and a DO on Linux would feed files in a different order.
"""

import hashlib
from pathlib import Path

from syft_job.submission import code_hash


def test_code_hash_orders_files_by_posix_path(tmp_path: Path):
files = {
"run.sh": b"python code/a.py\n",
"code/B.py": b"b\n",
"code/a.py": b"a\n",
}
for name, content in files.items():
(tmp_path / name).parent.mkdir(parents=True, exist_ok=True)
(tmp_path / name).write_bytes(content)

expected = hashlib.sha256()
for name in sorted(files): # "code/B.py" < "code/a.py" < "run.sh"
expected.update(name.encode())
expected.update(b"\0")
expected.update(hashlib.sha256(files[name]).digest())

assert code_hash(tmp_path) == expected.hexdigest()
Loading