diff --git a/.github/workflows/desktop.yaml b/.github/workflows/desktop.yaml index 896d178bf..a04a841da 100644 --- a/.github/workflows/desktop.yaml +++ b/.github/workflows/desktop.yaml @@ -79,9 +79,14 @@ jobs: run: python -c "import torch; assert torch.__version__ == '2.6.0+cu124'" - name: Run protocol and runtime-boundary tests working-directory: . - run: | - python -m unittest discover -s desktop/tests -v - communityai-desktop --self-test + env: + # The desktop tests share synthetic publication documents with the root suite. + PYTHONPATH: ${{ github.workspace }}/tests + PYTEST_DISABLE_PLUGIN_AUTOLOAD: "1" + run: python -m pytest -q desktop/tests + - name: Run installed desktop self-test + working-directory: . + run: communityai-desktop --self-test - name: Verify normalized archive consumers working-directory: . run: python -m unittest discover -s tests -p test_runtime_archive_hardlinks.py -v diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index c79713d43..84d1af731 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -29,9 +29,19 @@ jobs: with: enable-cache: true cache-dependency-glob: "uv.lock" + - name: Install Linux Qt runtime libraries + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends --yes \ + libdbus-1-3 libegl1 libgl1 libglib2.0-0 libfontconfig1 libfreetype6 \ + libxkbcommon0 libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 \ + libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-shape0 libwayland-cursor0 xvfb xauth - name: Install dependencies run: | uv sync --extra dev --python ${{ matrix.python-version }} + # Desktop tests exercise the real Qt runtime, including subprocess diagnostics. + uv pip install --python .venv/bin/python -e ./desktop - name: Test Factory source contract env: PYTHONPATH: src:desktop/src diff --git a/desktop/pyproject.toml b/desktop/pyproject.toml index 3905b3378..5816469c8 100644 --- a/desktop/pyproject.toml +++ b/desktop/pyproject.toml @@ -17,6 +17,7 @@ dependencies = [ [project.optional-dependencies] dev = [ "pyinstaller>=6.11,<7", + "pytest==6.2.5", ] [project.scripts] diff --git a/desktop/runtime_packaging.py b/desktop/runtime_packaging.py index 1b79063a1..3992cf1c0 100644 --- a/desktop/runtime_packaging.py +++ b/desktop/runtime_packaging.py @@ -128,12 +128,18 @@ def normalize_runtime(node_root: Path, *, target_platform: str, torch_version: s source, source_identity = canonical[digest] if identity[:2] == source_identity[:2]: continue - if _identity(source) != source_identity or _identity(path) != identity: + # A same-length rewrite can preserve size and even mtime on a + # coarse filesystem. Recheck content before replacing a path. + if _identity(source) != source_identity or _identity(path) != identity or _sha256(source) != digest: raise RuntimeError("native library changed during normalization") temporary = path.with_name(f".{path.name}.hardlink-{uuid.uuid4().hex}") try: os.link(source, temporary, follow_symlinks=False) - if _identity(source) != source_identity or _identity(path) != identity: + if ( + _identity(source) != source_identity + or _identity(path) != identity + or _sha256(temporary) != digest + ): raise RuntimeError("native library changed during normalization") os.replace(temporary, path) finally: diff --git a/desktop/src/communityai_desktop/app.py b/desktop/src/communityai_desktop/app.py index fbd60b0b7..791308ee9 100644 --- a/desktop/src/communityai_desktop/app.py +++ b/desktop/src/communityai_desktop/app.py @@ -292,9 +292,8 @@ def connect() -> DesktopController: updater = None if qualification_automation is None and profile is None: - from PySide6.QtCore import QStandardPaths - from communityai_desktop.updater import UpdateManager, installed_root + from PySide6.QtCore import QStandardPaths root = installed_root() if root is not None: diff --git a/desktop/src/communityai_desktop/lifecycle.py b/desktop/src/communityai_desktop/lifecycle.py index bc5138081..c46c1ce9a 100644 --- a/desktop/src/communityai_desktop/lifecycle.py +++ b/desktop/src/communityai_desktop/lifecycle.py @@ -114,7 +114,9 @@ def __init__( self.node_url = normalize_loopback_url(node_url) self.credential_store = credential_store self.config_path = _absolute_path(config_path) - self.data_dir = Path(data_dir).expanduser().resolve() + # Keep the caller's path spelling. On Windows, resolve() expands an + # 8.3 alias and makes the fixed-profile sidecar reject the same directory. + self.data_dir = _absolute_path(data_dir) default_node_command = node_command is None self.node_command = tuple(node_command or _default_node_command()) if not self.node_command or any(not isinstance(part, str) or not part for part in self.node_command): diff --git a/desktop/src/communityai_desktop/model_health.py b/desktop/src/communityai_desktop/model_health.py index 6e0056fc5..3b9166947 100644 --- a/desktop/src/communityai_desktop/model_health.py +++ b/desktop/src/communityai_desktop/model_health.py @@ -1,5 +1,6 @@ """Live block coverage, observed peers, and this computer's artifact transfers.""" +from communityai_desktop.presentation import model_name from PySide6.QtCore import Qt from PySide6.QtWidgets import ( QFrame, @@ -15,8 +16,6 @@ QWidget, ) -from communityai_desktop.presentation import model_name - COLORS = { "covered": "#237851", "replicated": "#35b779", diff --git a/desktop/tests/test_build_desktop.py b/desktop/tests/test_build_desktop.py index 2d631f8a8..8681b6e27 100644 --- a/desktop/tests/test_build_desktop.py +++ b/desktop/tests/test_build_desktop.py @@ -1083,7 +1083,10 @@ class VolunteerBuildIsolationTests(unittest.TestCase): def setUp(self) -> None: self._temporary_directory = TemporaryDirectory() self.addCleanup(self._temporary_directory.cleanup) - self.tmp_path = Path(self._temporary_directory.name) + # macOS exposes its temporary directory through /var -> /private/var. + # Keep these safe fixtures on the canonical path; link-rejection tests + # below still pass their explicit linked paths to the production guard. + self.tmp_path = Path(self._temporary_directory.name).resolve() self.project = self.tmp_path / "repository" / "desktop" icon = self.project / "src" / "communityai_desktop" / "assets" / "communityai.ico" icon.parent.mkdir(parents=True) diff --git a/desktop/tests/test_cgroup_extension.py b/desktop/tests/test_cgroup_extension.py index aaf572bf8..c7409487b 100644 --- a/desktop/tests/test_cgroup_extension.py +++ b/desktop/tests/test_cgroup_extension.py @@ -9,8 +9,7 @@ from tempfile import TemporaryDirectory from unittest.mock import patch -from desktop import cgroup_extension as extension -from desktop import launch_node +from desktop import cgroup_extension as extension, launch_node class CgroupExtensionTests(unittest.TestCase): diff --git a/desktop/tests/test_gpu_sharing_controls.py b/desktop/tests/test_gpu_sharing_controls.py index f3e55078e..9ec3f008b 100644 --- a/desktop/tests/test_gpu_sharing_controls.py +++ b/desktop/tests/test_gpu_sharing_controls.py @@ -6,12 +6,11 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") +from communityai_desktop.resource_controls import GpuResourceControls from PySide6.QtCore import Qt from PySide6.QtTest import QTest from PySide6.QtWidgets import QAbstractSlider, QApplication -from communityai_desktop.resource_controls import GpuResourceControls - def state(): capacities = (8, 12, 16, 24, 32, 40, 48, 80) diff --git a/desktop/tests/test_host_memory_policy_settings.py b/desktop/tests/test_host_memory_policy_settings.py index 56b54fb2b..cf7383778 100644 --- a/desktop/tests/test_host_memory_policy_settings.py +++ b/desktop/tests/test_host_memory_policy_settings.py @@ -7,13 +7,12 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") import test_gpu_sharing_integration as gpu_fixture +from communityai_desktop.client import NodeClientError, _normalize_policy +from communityai_desktop.presentation import sharing_reason from PySide6.QtCore import QPoint, QRect, QTimer from PySide6.QtGui import QFontDatabase, QPalette from PySide6.QtWidgets import QApplication, QDialog, QDialogButtonBox, QLabel, QLineEdit, QPlainTextEdit, QScrollArea -from communityai_desktop.client import NodeClientError, _normalize_policy -from communityai_desktop.presentation import sharing_reason - def contrast(foreground, background): def luminance(color): diff --git a/desktop/tests/test_model_health.py b/desktop/tests/test_model_health.py index 2658e5ff0..aa38bbeae 100644 --- a/desktop/tests/test_model_health.py +++ b/desktop/tests/test_model_health.py @@ -4,13 +4,12 @@ os.environ["QT_QPA_PLATFORM"] = "offscreen" +from communityai_desktop.model_health import DownloadCard, DownloadsPanel, ModelHealthCard +from communityai_desktop.telemetry import download_view, route_view from PySide6.QtCore import Qt from PySide6.QtTest import QTest from PySide6.QtWidgets import QApplication -from communityai_desktop.model_health import DownloadCard, DownloadsPanel, ModelHealthCard -from communityai_desktop.telemetry import download_view, route_view - class ModelHealthTests(unittest.TestCase): @classmethod @@ -265,6 +264,7 @@ def test_typed_memory_rejection_keeps_managed_guidance_after_loading_state_is_cl from communityai_desktop.acceptance import _FakeNodeState from communityai_desktop.client import _normalize_contribution_status from communityai_desktop.controller import DesktopController + from drift.node.server import _contribution_status fixture = _FakeNodeState() diff --git a/desktop/tests/test_resource_controls.py b/desktop/tests/test_resource_controls.py index 67bce7062..8e33c56c3 100644 --- a/desktop/tests/test_resource_controls.py +++ b/desktop/tests/test_resource_controls.py @@ -8,12 +8,11 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") -from PySide6.QtWidgets import QApplication - from communityai_desktop.acceptance import fake_node from communityai_desktop.client import NodeClient, NodeClientError from communityai_desktop.controller import DesktopController from communityai_desktop.resource_controls import ResourceControls +from PySide6.QtWidgets import QApplication class ResourceControlsTests(unittest.TestCase): diff --git a/desktop/tests/test_resource_playthrough.py b/desktop/tests/test_resource_playthrough.py index 6c5783fe6..fe3799fce 100644 --- a/desktop/tests/test_resource_playthrough.py +++ b/desktop/tests/test_resource_playthrough.py @@ -7,12 +7,11 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") -from PySide6.QtCore import QTimer -from PySide6.QtWidgets import QApplication, QPushButton, QWidget - from communityai_desktop.app import main from communityai_desktop.resource_controls import ResourceControls from communityai_desktop.resource_playthrough import ResourcePlaythrough +from PySide6.QtCore import QTimer +from PySide6.QtWidgets import QApplication, QPushButton, QWidget class ResourcePlaythroughTests(unittest.TestCase): diff --git a/desktop/tests/test_resource_recovery_controls.py b/desktop/tests/test_resource_recovery_controls.py index abdc1d743..2aa0a2068 100644 --- a/desktop/tests/test_resource_recovery_controls.py +++ b/desktop/tests/test_resource_recovery_controls.py @@ -10,12 +10,11 @@ os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") -from PySide6.QtCore import QTimer - from communityai_desktop.acceptance import fake_node from communityai_desktop.client import NodeClient from communityai_desktop.controller import DesktopController from communityai_desktop.presentation import recovery_reason +from PySide6.QtCore import QTimer def test_recovery_keeps_off_and_pause_truth_while_gating_only_start(): diff --git a/desktop/tests/test_runtime_packaging.py b/desktop/tests/test_runtime_packaging.py index cf42327e1..30d37f58a 100644 --- a/desktop/tests/test_runtime_packaging.py +++ b/desktop/tests/test_runtime_packaging.py @@ -103,17 +103,25 @@ def test_changed_source_fails_before_link_replacement(self): first = self.write("_internal/a.so") second = self.write("_internal/b.so") real_hash = packaging._sha256 + original_stat = first.stat() + original_identity = packaging._identity(first) + # This rewrite keeps the original byte length and mtime, so metadata + # alone cannot detect a stale source digest before hardlink replacement. + self.assertEqual(len(b"poison-library"), len(b"native-library")) def hash_and_change(path): digest = real_hash(path) if path == first: - first.write_bytes(b"changed-longer") + first.write_bytes(b"poison-library") + os.utime(first, ns=(original_stat.st_atime_ns, original_stat.st_mtime_ns)) + self.assertEqual(packaging._identity(first), original_identity) return digest with patch.object(packaging, "_sha256", side_effect=hash_and_change): with self.assertRaisesRegex(RuntimeError, "changed during"): self.normalize() self.assertFalse(os.path.samefile(first, second)) + self.assertEqual(second.read_bytes(), b"native-library") def test_deb_staging_preserves_hardlinks_even_across_device_copy_fallback(self): first = self.write("a.so", b"a" * 1025) diff --git a/desktop/tests/test_simple_desktop.py b/desktop/tests/test_simple_desktop.py index 75162d1f9..870b0b23d 100644 --- a/desktop/tests/test_simple_desktop.py +++ b/desktop/tests/test_simple_desktop.py @@ -58,11 +58,10 @@ def test_stale_poll_error_does_not_cancel_a_successful_start(self): self._exercise_poll_race(True) def _exercise_poll_race(self, fail_poll): + from communityai_desktop.pyside_shell import run from PySide6.QtCore import QTimer from PySide6.QtWidgets import QLabel - from communityai_desktop.pyside_shell import run - with fake_node(all_workers_paused=True) as (url, token): state = DesktopController(NodeClient(url, token)).snapshot() state["hardware"] = { diff --git a/desktop/tests/test_startup.py b/desktop/tests/test_startup.py index 6eb04ebf1..f641f3775 100644 --- a/desktop/tests/test_startup.py +++ b/desktop/tests/test_startup.py @@ -402,7 +402,7 @@ def test_existing_instance_protocol_distinguishes_manual_and_login_launch(self): from communityai_desktop.pyside_shell import run application = QApplication.instance() or QApplication([]) - name = f"communityai-test-{uuid.uuid4().hex}" + name = f"cai-{uuid.uuid4().hex}" QLocalServer.removeServer(name) server = QLocalServer(application) server.setSocketOptions(QLocalServer.UserAccessOption) @@ -440,7 +440,7 @@ def test_primary_instance_releases_owned_endpoint_and_lock(self): from communityai_desktop.pyside_shell import run - name = f"communityai-owner-test-{uuid.uuid4().hex}" + name = f"cai-{uuid.uuid4().hex}" def unavailable(): raise RuntimeError("offline for UI smoke") diff --git a/desktop/tests/test_volunteer_node_launcher.py b/desktop/tests/test_volunteer_node_launcher.py index 3e11ff183..c27fc2dd7 100644 --- a/desktop/tests/test_volunteer_node_launcher.py +++ b/desktop/tests/test_volunteer_node_launcher.py @@ -1,6 +1,7 @@ from __future__ import annotations import builtins +import ctypes import importlib.util import io import json @@ -539,6 +540,49 @@ def bootstrap_runner(command, **kwargs): self.assertEqual(bootstrap_calls[0][1]["cwd"], str(self.profile.data_dir)) self.assertEqual(len(self.dispatches), 3) + @unittest.skipUnless(os.name == "nt", "Windows 8.3 path aliases") + def test_windows_short_profile_path_keeps_lifecycle_arguments_private(self): + length = ctypes.windll.kernel32.GetShortPathNameW(str(self.home), None, 0) + if not length: + self.skipTest("Windows did not provide a short path") + buffer = ctypes.create_unicode_buffer(length) + if not ctypes.windll.kernel32.GetShortPathNameW(str(self.home), buffer, length): + self.skipTest("Windows did not provide a short path") + short_home = Path(buffer.value) + if os.path.normcase(str(short_home)) == os.path.normcase(str(self.home)): + self.skipTest("8.3 aliases are disabled for this fixture") + + profile = VolunteerProfile(short_home / ".communityai" / "multigpu-volunteer") + profile.prepare() + from communityai_desktop.lifecycle import NodeLifecycleSupervisor + + supervisor = NodeLifecycleSupervisor( + profile.node_url, + types.SimpleNamespace(service=profile.credential_service, account=profile.credential_account), + config_path=profile.config_path, + data_dir=profile.data_dir, + node_command=(str(self.home / "volunteer-node"),), + pause_sharing_on_start=True, + local_inference_cpu_only=True, + allow_external_node=False, + ) + with patch.object(VolunteerProfile, "for_current_user", return_value=profile): + self.assertEqual(self._run(supervisor._command()[1:]), 0) + self.assertEqual(self.dispatches[-1][1], profile.data_dir) + + outside = self.home / "ordinary" / "escape.json" + with self.assertRaisesRegex(ValueError, "fixed profile root"): + launcher._node_arguments(["--data_dir", str(outside)], profile) + outside.parent.mkdir() + linked = profile.data_dir / "linked" + try: + linked.symlink_to(outside.parent, target_is_directory=True) + except OSError: + pass # External absolute path above still exercises the escape rejection. + else: + with self.assertRaisesRegex(ValueError, "symbolic links or junctions"): + launcher._node_arguments(["--data_dir", str(linked)], profile) + def test_worker_requires_inherited_current_parent_and_profile_before_dispatch(self): arguments = self._worker() for parent, root in ( diff --git a/scripts/benchmark_qwen_local_gpu.py b/scripts/benchmark_qwen_local_gpu.py index b1032865e..3ba644695 100644 --- a/scripts/benchmark_qwen_local_gpu.py +++ b/scripts/benchmark_qwen_local_gpu.py @@ -62,23 +62,33 @@ def main() -> int: torch.cuda.synchronize(device) seconds = time.monotonic() - began tokens = int(output.shape[-1] - prompt["input_ids"].shape[-1]) - results.append({"output_tokens": tokens, "seconds": round(seconds, 3), - "tokens_per_second_including_prefill": round(tokens / seconds, 3)}) - print(json.dumps({ - "scope": "offline single-GPU Transformers baseline, not vLLM or release qualification", - "model": "Qwen/Qwen3-1.7B", - "revision": REVISION, - "backend": "transformers", - "transformers_version": __import__("transformers").__version__, - "torch_version": torch.__version__, - "gpu": torch.cuda.get_device_name(device), - "gpu_count_used": 1, - "prompt_tokens": int(prompt["input_ids"].shape[-1]), - "load_seconds": round(loaded_seconds, 3), - "peak_cuda_bytes": torch.cuda.max_memory_allocated(device), - "runs": results, - "median_16_token_seconds": round(statistics.median(run["seconds"] for run in results[1:]), 3), - }, sort_keys=True)) + results.append( + { + "output_tokens": tokens, + "seconds": round(seconds, 3), + "tokens_per_second_including_prefill": round(tokens / seconds, 3), + } + ) + print( + json.dumps( + { + "scope": "offline single-GPU Transformers baseline, not vLLM or release qualification", + "model": "Qwen/Qwen3-1.7B", + "revision": REVISION, + "backend": "transformers", + "transformers_version": __import__("transformers").__version__, + "torch_version": torch.__version__, + "gpu": torch.cuda.get_device_name(device), + "gpu_count_used": 1, + "prompt_tokens": int(prompt["input_ids"].shape[-1]), + "load_seconds": round(loaded_seconds, 3), + "peak_cuda_bytes": torch.cuda.max_memory_allocated(device), + "runs": results, + "median_16_token_seconds": round(statistics.median(run["seconds"] for run in results[1:]), 3), + }, + sort_keys=True, + ) + ) return 0 diff --git a/scripts/check_abandoned_service_holds.py b/scripts/check_abandoned_service_holds.py index ec0d67e92..82ee33b2c 100644 --- a/scripts/check_abandoned_service_holds.py +++ b/scripts/check_abandoned_service_holds.py @@ -16,12 +16,23 @@ def quote(request_id): return module.SimulatedServiceQuote( - request_id=request_id, buyer_id="buyer", provider_id="provider", - funding_source="purchased", model_id="test/model", profile_id="test/profile", - service_class="text_inference", settlement_domain="local_simulation", - artifact_sha256="a" * 64, service_policy_sha256="b" * 64, - price_schedule_sha256="c" * 64, input_unit_price=1, output_unit_price=1, - max_input_units=5, max_output_units=5, fee_bps=0, spend_cap=10, + request_id=request_id, + buyer_id="buyer", + provider_id="provider", + funding_source="purchased", + model_id="test/model", + profile_id="test/profile", + service_class="text_inference", + settlement_domain="local_simulation", + artifact_sha256="a" * 64, + service_policy_sha256="b" * 64, + price_schedule_sha256="c" * 64, + input_unit_price=1, + output_unit_price=1, + max_input_units=5, + max_output_units=5, + fee_bps=0, + spend_cap=10, expires_at_unix=int(time.time()) + 60, ) @@ -51,8 +62,7 @@ def main(): def settle(): try: - return journal.settle_service("race", "provider", 5, 0, - "decision", "d" * 64, 2, 3) + return journal.settle_service("race", "provider", 5, 0, "decision", "d" * 64, 2, 3) except module.CommerceSimulationError: return False diff --git a/scripts/check_commerce_simulator.py b/scripts/check_commerce_simulator.py index e07b919ce..83c2202ab 100644 --- a/scripts/check_commerce_simulator.py +++ b/scripts/check_commerce_simulator.py @@ -22,14 +22,24 @@ def quote(request_id, buyer_id, cap, source="purchased", provider_id="provider_a"): return SimulatedServiceQuote( - request_id=request_id, buyer_id=buyer_id, provider_id=provider_id, funding_source=source, - model_id="test/model", profile_id="test/profile", - service_class="text_inference", settlement_domain="local_simulation", - artifact_sha256="a" * 64, service_policy_sha256="b" * 64, + request_id=request_id, + buyer_id=buyer_id, + provider_id=provider_id, + funding_source=source, + model_id="test/model", + profile_id="test/profile", + service_class="text_inference", + settlement_domain="local_simulation", + artifact_sha256="a" * 64, + service_policy_sha256="b" * 64, price_schedule_sha256="c" * 64, - input_unit_price=1, output_unit_price=1, - max_input_units=cap // 2, max_output_units=cap - cap // 2, - fee_bps=2000, spend_cap=cap, expires_at_unix=int(time.time()) + 60, + input_unit_price=1, + output_unit_price=1, + max_input_units=cap // 2, + max_output_units=cap - cap // 2, + fee_bps=2000, + spend_cap=cap, + expires_at_unix=int(time.time()) + 60, ) @@ -68,18 +78,26 @@ def check(): denied(lambda: ledger.reserve_service(replace(main_quote, profile_id="test/changed"))) assert ledger.buyer_wallet("alice")["service_held"] == 100 denied(lambda: ledger.reserve_service(quote("request_more", "alice", 2))) - denied(lambda: ledger.settle_service("request_main", "provider_a", 60, 13, - "decision_bad_fee", "a" * 64, 40, 20)) - denied(lambda: ledger.settle_service("request_main", "provider_other", 60, 10, - "decision_bad_provider", "a" * 64, 40, 20)) - denied(lambda: ledger.settle_service("request_main", "provider_a", 60, 10, - "decision_bad_units", "a" * 64, 51, 9)) - assert ledger.settle_service("request_main", "provider_a", 60, 10, - "decision_main", "a" * 64, 40, 20) - assert not ledger.settle_service("request_main", "provider_a", 60, 10, - "decision_main", "a" * 64, 40, 20) - denied(lambda: ledger.settle_service("request_main", "provider_a", 61, 10, - "decision_main", "a" * 64, 40, 20)) + denied( + lambda: ledger.settle_service( + "request_main", "provider_a", 60, 13, "decision_bad_fee", "a" * 64, 40, 20 + ) + ) + denied( + lambda: ledger.settle_service( + "request_main", "provider_other", 60, 10, "decision_bad_provider", "a" * 64, 40, 20 + ) + ) + denied( + lambda: ledger.settle_service( + "request_main", "provider_a", 60, 10, "decision_bad_units", "a" * 64, 51, 9 + ) + ) + assert ledger.settle_service("request_main", "provider_a", 60, 10, "decision_main", "a" * 64, 40, 20) + assert not ledger.settle_service("request_main", "provider_a", 60, 10, "decision_main", "a" * 64, 40, 20) + denied( + lambda: ledger.settle_service("request_main", "provider_a", 61, 10, "decision_main", "a" * 64, 40, 20) + ) assert ledger.buyer_wallet("alice")["purchased_available"] == 40 assert ledger.provider_wallet("provider_a")["pending"] == 50 assert ledger.release_earnings("release_main", "provider_a", 50, "risk_main") @@ -124,8 +142,7 @@ def race(request_id): assert reopened.create_order("order_second", "bob", "processor_second", 50) assert reopened.record_verified_processor_event("cap_second", "processor_second", "capture", 50) assert reopened.reserve_service(quote("request_second", "bob", 50, provider_id="provider_b")) - assert reopened.settle_service("request_second", "provider_b", 50, 0, - "decision_second", "b" * 64, 25, 25) + assert reopened.settle_service("request_second", "provider_b", 50, 0, "decision_second", "b" * 64, 25, 25) assert reopened.release_earnings("release_second", "provider_b", 50, "risk_second") assert reopened.request_payout("payout_failed", "provider_b", 20, "external_failed") assert reopened.mark_payout_unknown("payout_failed") diff --git a/scripts/check_credit_resale_simulator.py b/scripts/check_credit_resale_simulator.py index 02a5e3104..9bdd64748 100644 --- a/scripts/check_credit_resale_simulator.py +++ b/scripts/check_credit_resale_simulator.py @@ -23,14 +23,26 @@ def quote(request_id, buyer_id, cap, source, provider_id, resale_listing_id=None): return SimulatedServiceQuote( - request_id=request_id, buyer_id=buyer_id, provider_id=provider_id, funding_source=source, - model_id="test/model", profile_id="test/profile", service_class="text_inference", - settlement_domain="local_simulation", artifact_sha256="a" * 64, - service_policy_sha256="b" * 64, price_schedule_sha256="c" * 64, - input_unit_price=1, output_unit_price=1, max_input_units=cap // 2, - max_output_units=cap - cap // 2, fee_bps=0, spend_cap=cap, + request_id=request_id, + buyer_id=buyer_id, + provider_id=provider_id, + funding_source=source, + model_id="test/model", + profile_id="test/profile", + service_class="text_inference", + settlement_domain="local_simulation", + artifact_sha256="a" * 64, + service_policy_sha256="b" * 64, + price_schedule_sha256="c" * 64, + input_unit_price=1, + output_unit_price=1, + max_input_units=cap // 2, + max_output_units=cap - cap // 2, + fee_bps=0, + spend_cap=cap, expires_at_unix=int(time.time()) + 60, - version=2 if source == "resale" else 1, resale_listing_id=resale_listing_id, + version=2 if source == "resale" else 1, + resale_listing_id=resale_listing_id, ) @@ -121,9 +133,11 @@ def race_use(): assert ledger.buyer_wallet("buyer")["resale_access_available"] == 25 assert ledger.resale_lot_balance("buyer", "listing_1") == 20 assert ledger.resale_lot_balance("buyer", "listing_other") == 5 - denied(lambda: ledger.reserve_service( - quote("wrong_buyer", "buyer_void", 5, "resale", "service_provider", "listing_other") - )) + denied( + lambda: ledger.reserve_service( + quote("wrong_buyer", "buyer_void", 5, "resale", "service_provider", "listing_other") + ) + ) # Resale-origin access can be used but cannot itself be listed. denied(lambda: ledger.list_earned_credits("buyer_cannot_resell", "buyer", 20, 20, 0, expiry)) @@ -131,18 +145,18 @@ def race_use(): assert ledger.settle_service("buyer_use", "service_provider", 5, 0, "use_decision", "b" * 64, 2, 3) assert ledger.buyer_wallet("buyer")["resale_access_available"] == 20 assert ledger.resale_lot_balance("buyer", "listing_1") == 15 - denied(lambda: ledger.reserve_service( - quote("wrong_lot_use", "buyer", 20, "resale", "service_provider", "listing_1") - )) + denied( + lambda: ledger.reserve_service( + quote("wrong_lot_use", "buyer", 20, "resale", "service_provider", "listing_1") + ) + ) # A reversal while a buyer request is held must route its later refund # into loss recovery, never recreate spendable buyer credits. assert ledger.list_earned_credits("listing_held", "seller", 10, 10, 0, expiry) assert ledger.place_resale_order("listing_held", "buyer_held", "resale_ref_held") assert ledger.record_verified_resale_event("held_capture", "resale_ref_held", "capture", 10) - assert ledger.reserve_service(quote( - "held_use", "buyer_held", 10, "resale", "service_provider", "listing_held" - )) + assert ledger.reserve_service(quote("held_use", "buyer_held", 10, "resale", "service_provider", "listing_held")) assert ledger.record_verified_resale_event("held_reversal", "resale_ref_held", "reversal", 10) assert ledger.audit()["unfunded_reversal_loss"] == 10 assert ledger.refund_service("held_use", "no_output") @@ -201,18 +215,23 @@ def check_migration(path): "INSERT INTO reservations(request_id,buyer_id,source,cap,status) VALUES (?,?,?,?,?)", (sample.request_id, sample.buyer_id, sample.funding_source, sample.spend_cap, "held"), ) - connection.execute("INSERT INTO quotes VALUES (?,?,?)", - (sample.request_id, json.dumps(asdict(sample), sort_keys=True, - separators=(",", ":"), ensure_ascii=True), sample.digest)) + connection.execute( + "INSERT INTO quotes VALUES (?,?,?)", + ( + sample.request_id, + json.dumps(asdict(sample), sort_keys=True, separators=(",", ":"), ensure_ascii=True), + sample.digest, + ), + ) connection.execute("PRAGMA user_version=1") connection.close() with CommerceSimulator(path) as upgraded: assert upgraded._load_quote("legacy_request").digest == sample.digest assert upgraded._db.execute("PRAGMA user_version").fetchone()[0] == 2 assert upgraded._db.execute("PRAGMA foreign_key_check").fetchall() == [] - assert "'resale'" in upgraded._db.execute( - "SELECT sql FROM sqlite_master WHERE name='reservations'" - ).fetchone()[0] + assert ( + "'resale'" in upgraded._db.execute("SELECT sql FROM sqlite_master WHERE name='reservations'").fetchone()[0] + ) def check_held_settlement(path): diff --git a/scripts/check_glm53_w4a8_h100_launch.py b/scripts/check_glm53_w4a8_h100_launch.py index 5712757ae..ce829111a 100644 --- a/scripts/check_glm53_w4a8_h100_launch.py +++ b/scripts/check_glm53_w4a8_h100_launch.py @@ -62,13 +62,21 @@ def check(): assert candidate.environment["VLLM_NO_USAGE_STATS"] == "1" assert candidate.artifact_revision == PINNED_QUANTIZED_CANDIDATES[ARTIFACT_ID].revision assert candidate.recipe_revision == RECIPE_REVISION and candidate.required_vllm_version == "0.30.0" - assert not any((candidate.qualified, candidate.remote_code_reviewed, - candidate.quality_equivalence_proven, candidate.rights_approved)) + assert not any( + ( + candidate.qualified, + candidate.remote_code_reviewed, + candidate.quality_equivalence_proven, + candidate.rights_approved, + ) + ) refused(path, **(options | {"reported_devices": devices[:7]})) refused(path, **(options | {"reported_devices": devices[:-1] + (devices[0],)})) refused(path, **(options | {"reported_devices": devices[:-1] + ((7, "NVIDIA H200", 70_000_000_000),)})) - refused(path, **(options | {"reported_devices": devices[:-1] + ((7, "NVIDIA H100", MINIMUM_PER_RANK_BYTES - 1),)})) + refused( + path, **(options | {"reported_devices": devices[:-1] + ((7, "NVIDIA H100", MINIMUM_PER_RANK_BYTES - 1),)}) + ) refused(path, **(options | {"reported_devices": devices[:-1] + ((7, "NVIDIA H100", True),)})) refused(path, **(options | {"reported_devices": [*devices]})) refused(path, **(options | {"max_model_len": 2049})) diff --git a/scripts/check_managed_llama_cpp.py b/scripts/check_managed_llama_cpp.py index d38de6e4b..477de4e0e 100644 --- a/scripts/check_managed_llama_cpp.py +++ b/scripts/check_managed_llama_cpp.py @@ -19,29 +19,41 @@ sys.modules["drift"] = PACKAGE from drift.inference_provider import ( # noqa: E402 - Availability, EventKind, InferenceLimits, InferenceRequest, ProviderIdentity, ProviderProfile, + Availability, + EventKind, + InferenceLimits, + InferenceRequest, + ProviderIdentity, + ProviderProfile, ) from drift.managed_llama_cpp import ManagedLlamaCppAdapter, ManagedLlamaCppBinding # noqa: E402 from drift.managed_vllm_text import ManagedVllmTextClient # noqa: E402 def frame(model, *, text="", finish=None, usage=None): - return {"id": "cmpl-test-1", "object": "text_completion", "model": model, - "choices": [] if usage is not None else [{"index": 0, "text": text, "finish_reason": finish}], - **({"usage": usage} if usage is not None else {})} + return { + "id": "cmpl-test-1", + "object": "text_completion", + "model": model, + "choices": [] if usage is not None else [{"index": 0, "text": text, "finish_reason": finish}], + **({"usage": usage} if usage is not None else {}), + } async def main(): - profile = ProviderProfile("test/llama-qwen", "test/qwen-llama", Availability.AVAILABLE, - qualification_id="a" * 64) - binding = ManagedLlamaCppBinding( - profile, profile.model_id, "http://127.0.0.1:18247", "secret", (0,), "none", 256 - ) + profile = ProviderProfile("test/llama-qwen", "test/qwen-llama", Availability.AVAILABLE, qualification_id="a" * 64) + binding = ManagedLlamaCppBinding(profile, profile.model_id, "http://127.0.0.1:18247", "secret", (0,), "none", 256) assert binding.backend_id == "llama.cpp-b11173" for bad in ( - lambda: ManagedLlamaCppBinding(profile, profile.model_id, "http://other-host:18247", "secret", (0,), "none", 256), - lambda: ManagedLlamaCppBinding(profile, profile.model_id, "http://127.0.0.1:18247", "secret", (0, 0), "layer", 256), - lambda: ManagedLlamaCppBinding(profile, profile.model_id, "http://127.0.0.1:18247", "secret", (0, 1), "none", 256), + lambda: ManagedLlamaCppBinding( + profile, profile.model_id, "http://other-host:18247", "secret", (0,), "none", 256 + ), + lambda: ManagedLlamaCppBinding( + profile, profile.model_id, "http://127.0.0.1:18247", "secret", (0, 0), "layer", 256 + ), + lambda: ManagedLlamaCppBinding( + profile, profile.model_id, "http://127.0.0.1:18247", "secret", (0, 1), "none", 256 + ), ): try: bad() @@ -56,8 +68,11 @@ def transport(request): body = json.loads(request.content) seen.append((request.url.path, body, request.headers.get("Authorization"))) model = "wrong/model" if body["prompt"] == "bad" else body["model"] - frames = [frame(model, text="hello"), frame(model, finish="length"), - frame(model, usage={"prompt_tokens": 2, "completion_tokens": 1, "total_tokens": 3})] + frames = [ + frame(model, text="hello"), + frame(model, finish="length"), + frame(model, usage={"prompt_tokens": 2, "completion_tokens": 1, "total_tokens": 3}), + ] payload = b"".join(b"data: " + json.dumps(item).encode() + b"\n\n" for item in frames) payload += b"data: [DONE]\n\n" return httpx.Response(200, headers={"content-type": "text/event-stream"}, content=payload) @@ -69,9 +84,17 @@ def transport(request): def request(prompt): now = time.monotonic() - return InferenceRequest(identity, profile.profile_id, profile.model_id, - "a" * 32, "b" * 32, now, now + 5, prompt, - InferenceLimits(100, 4, 32, 4096)) + return InferenceRequest( + identity, + profile.profile_id, + profile.model_id, + "a" * 32, + "b" * 32, + now, + now + 5, + prompt, + InferenceLimits(100, 4, 32, 4096), + ) events = [event async for event in adapter.stream(request("good"))] assert [event.kind for event in events] == [EventKind.STARTED, EventKind.OUTPUT, EventKind.COMPLETED] diff --git a/scripts/check_managed_llama_cpp_api.py b/scripts/check_managed_llama_cpp_api.py index 95bc0ebaf..9aa668efb 100644 --- a/scripts/check_managed_llama_cpp_api.py +++ b/scripts/check_managed_llama_cpp_api.py @@ -29,8 +29,12 @@ def backend(request: httpx.Request) -> httpx.Response: frames = [ {"id": "llama-1", "model": model, "choices": [{"index": 0, "text": "hello", "finish_reason": None}]}, {"id": "llama-1", "model": model, "choices": [{"index": 0, "text": "", "finish_reason": "length"}]}, - {"id": "llama-1", "model": model, "choices": [], - "usage": {"prompt_tokens": 2, "completion_tokens": 1, "total_tokens": 3}}, + { + "id": "llama-1", + "model": model, + "choices": [], + "usage": {"prompt_tokens": 2, "completion_tokens": 1, "total_tokens": 3}, + }, ] payload = b"".join(b"data: " + json.dumps(frame).encode() + b"\n\n" for frame in frames) + b"data: [DONE]\n\n" return httpx.Response(200, headers={"content-type": "text/event-stream"}, content=payload) @@ -39,8 +43,10 @@ def backend(request: httpx.Request) -> httpx.Response: manager = ModelManager() adapter = ManagedLlamaCppAdapter(binding, client=backend_client) bridge = ManagedVllmTextClient(adapter, ProviderIdentity("test/provider", "test/instance"), digest) - manager.register(ModelDescriptor(model, manifest_digest=digest), - lambda: ModelRuntime(model=None, tokenizer=None, text_client=bridge)) + manager.register( + ModelDescriptor(model, manifest_digest=digest), + lambda: ModelRuntime(model=None, tokenizer=None, text_client=bridge), + ) app = create_app(model_manager=manager, api_keys=["api-key"], request_timeout=5.0) try: with TestClient(app) as client: @@ -59,6 +65,7 @@ def backend(request: httpx.Request) -> httpx.Response: print("PASS: llama.cpp fake stream through authenticated API; 256-token context enforced") finally: import asyncio + asyncio.run(backend_client.aclose()) diff --git a/scripts/check_managed_llama_cpp_process.py b/scripts/check_managed_llama_cpp_process.py index 1dd293de3..29ef04b4e 100644 --- a/scripts/check_managed_llama_cpp_process.py +++ b/scripts/check_managed_llama_cpp_process.py @@ -23,11 +23,17 @@ sys.modules["drift"] = PACKAGE from drift.inference_provider import ( # noqa: E402 - Availability, EventKind, InferenceLimits, InferenceRequest, ProviderIdentity, ProviderProfile, + Availability, + EventKind, + InferenceLimits, + InferenceRequest, + ProviderIdentity, + ProviderProfile, ) from drift.managed_llama_cpp import ManagedLlamaCppBinding # noqa: E402 from drift.managed_llama_cpp_process import ( # noqa: E402 - ManagedLlamaCppProcessError, ManagedLlamaCppProcessOwner, + ManagedLlamaCppProcessError, + ManagedLlamaCppProcessOwner, ) from drift.commerce_simulator import CommerceSimulator, SimulatedServiceQuote # noqa: E402 from drift.managed_vllm_text import ManagedVllmTextClient # noqa: E402 @@ -52,23 +58,38 @@ def request(profile: ProviderProfile, prompt: str) -> InferenceRequest: now = time.monotonic() return InferenceRequest( ProviderIdentity("test/local-provider", "test/local-instance"), - profile.profile_id, profile.model_id, "a" * 32, "b" * 32, - now, now + 20, prompt, InferenceLimits(252, 4, 100, 4096), + profile.profile_id, + profile.model_id, + "a" * 32, + "b" * 32, + now, + now + 20, + prompt, + InferenceLimits(252, 4, 100, 4096), ) async def main() -> None: profile = ProviderProfile( - "test/qwen-llama-owned", "test/qwen3-1.7b-llama-owned", - Availability.AVAILABLE, qualification_id="1" * 64, + "test/qwen-llama-owned", + "test/qwen3-1.7b-llama-owned", + Availability.AVAILABLE, + qualification_id="1" * 64, ) binding = ManagedLlamaCppBinding( - profile, profile.model_id, f"http://127.0.0.1:{free_port()}", - "local-owner-secret", (0,), "none", 256, + profile, + profile.model_id, + f"http://127.0.0.1:{free_port()}", + "local-owner-secret", + (0,), + "none", + 256, ) arguments = dict( - executable=SERVER, executable_sha256=SERVER_SHA, - model_file=MODEL, model_sha256=MODEL_SHA, + executable=SERVER, + executable_sha256=SERVER_SHA, + model_file=MODEL, + model_sha256=MODEL_SHA, ) owner = ManagedLlamaCppProcessOwner(binding, **arguments) bad_owner = ManagedLlamaCppProcessOwner(binding, **{**arguments, "model_sha256": "0" * 64}) @@ -107,18 +128,30 @@ async def main() -> None: def quote_for_request(_body, _chat, context): return SimulatedServiceQuote( - request_id=context.request_id, buyer_id=context.caller_id, - provider_id="provider", funding_source="purchased", - model_id=profile.model_id, profile_id=profile.profile_id, - service_class="text_inference", settlement_domain="local_simulation", - artifact_sha256=MODEL_SHA, service_policy_sha256="b" * 64, - price_schedule_sha256="c" * 64, input_unit_price=1, - output_unit_price=1, max_input_units=16, max_output_units=4, - fee_bps=1000, spend_cap=20, expires_at_unix=int(time.time()) + 60, + request_id=context.request_id, + buyer_id=context.caller_id, + provider_id="provider", + funding_source="purchased", + model_id=profile.model_id, + profile_id=profile.profile_id, + service_class="text_inference", + settlement_domain="local_simulation", + artifact_sha256=MODEL_SHA, + service_policy_sha256="b" * 64, + price_schedule_sha256="c" * 64, + input_unit_price=1, + output_unit_price=1, + max_input_units=16, + max_output_units=4, + fee_bps=1000, + spend_cap=20, + expires_at_unix=int(time.time()) + 60, ) bridge = ManagedVllmTextClient( - owner.new_adapter(), ProviderIdentity("provider", "instance"), digest, + owner.new_adapter(), + ProviderIdentity("provider", "instance"), + digest, ) paid = SimulatedPaidTextClient(bridge, journal, quote_for_request) manager = ModelManager() @@ -134,8 +167,13 @@ def quote_for_request(_body, _chat, context): with TestClient(app) as client: answer = client.post( "/v1/completions", - json={"model": profile.model_id, "prompt": "Reply with one short greeting.", - "max_tokens": 4, "temperature": 0, "stream": False}, + json={ + "model": profile.model_id, + "prompt": "Reply with one short greeting.", + "max_tokens": 4, + "temperature": 0, + "stream": False, + }, headers={"Authorization": "Bearer buyer-key"}, ) assert answer.status_code == 200, answer.text diff --git a/scripts/check_managed_vllm_process.py b/scripts/check_managed_vllm_process.py index c653fccc4..b02dc11a2 100644 --- a/scripts/check_managed_vllm_process.py +++ b/scripts/check_managed_vllm_process.py @@ -24,8 +24,7 @@ from drift.managed_vllm import ManagedVllmBinding # noqa: E402 from drift.managed_vllm_process import ManagedVllmProcessError, ManagedVllmProcessOwner # noqa: E402 - -FAKE_SERVE = r''' +FAKE_SERVE = r""" import argparse import json import subprocess @@ -90,7 +89,7 @@ def log_message(self, *_args): pass ThreadingHTTPServer((args.host, args.port), Server).serve_forever() -''' +""" def request(prompt: str) -> InferenceRequest: @@ -131,9 +130,7 @@ async def main() -> None: directory = Path(temporary) (directory / "serve").write_text(FAKE_SERVE, encoding="utf-8") profile = ProviderProfile("test/profile", "test/model", Availability.AVAILABLE, qualification_id="e" * 64) - binding = ManagedVllmBinding( - profile, "test/model", f"http://127.0.0.1:{unused_port()}", "secret", (0, 1), 2, 1 - ) + binding = ManagedVllmBinding(profile, "test/model", f"http://127.0.0.1:{unused_port()}", "secret", (0, 1), 2, 1) executable = Path(sys.executable) owner = ManagedVllmProcessOwner( binding, diff --git a/scripts/check_resale_expiry.py b/scripts/check_resale_expiry.py index 2b22c9a8a..5f6d64e60 100644 --- a/scripts/check_resale_expiry.py +++ b/scripts/check_resale_expiry.py @@ -5,7 +5,7 @@ from pathlib import Path from unittest.mock import patch -from check_credit_resale_simulator import CommerceSimulator, CommerceSimulationError, quote +from check_credit_resale_simulator import CommerceSimulationError, CommerceSimulator, quote def denied(action): @@ -41,10 +41,12 @@ def main(): assert ledger.expire_open_resale_listings(limit=1) == ("old_b",) assert ledger.expire_open_resale_listings(limit=1) == () assert ledger.buyer_wallet("seller")["earned_access_available"] == 20 - assert dict(ledger._db.execute( - "SELECT listing_id,status FROM resale_listings" - )) == {"old_a": "cancelled", "old_b": "cancelled", - "ordered": "ordered", "future": "open"} + assert dict(ledger._db.execute("SELECT listing_id,status FROM resale_listings")) == { + "old_a": "cancelled", + "old_b": "cancelled", + "ordered": "ordered", + "future": "open", + } ledger.audit() with CommerceSimulator(path) as reopened: @@ -54,9 +56,9 @@ def main(): reopened.record_verified_resale_event("ordered_rev", "ordered_ref", "reversal", 10) reopened.record_verified_resale_event("ordered_cap", "ordered_ref", "capture", 10) assert reopened.buyer_wallet("seller")["earned_access_available"] == 30 - assert reopened._db.execute( - "SELECT status FROM resale_listings WHERE listing_id='ordered'" - ).fetchone() == ("reversed",) + assert reopened._db.execute("SELECT status FROM resale_listings WHERE listing_id='ordered'").fetchone() == ( + "reversed", + ) reopened.audit() print("PASS: bounded expiry reclamation, replay, and ordered payment resolution") diff --git a/scripts/check_shadow_managed_api.py b/scripts/check_shadow_managed_api.py index 74d17bc09..bc8e5010c 100644 --- a/scripts/check_shadow_managed_api.py +++ b/scripts/check_shadow_managed_api.py @@ -21,7 +21,6 @@ from drift.shadow_credits import ShadowLedger from drift.shadow_metered_managed import ShadowMeteredManagedClient - MANIFEST = "sha256:" + "c" * 64 CALLS = [] @@ -34,12 +33,22 @@ def do_POST(self): body = b"data: [DONE]\n\n" else: frames = [ - {"id": "local-1", "model": payload["model"], "choices": [ - {"index": 0, "text": "ok", "finish_reason": None}]}, - {"id": "local-1", "model": payload["model"], "choices": [ - {"index": 0, "text": "", "finish_reason": "stop"}]}, - {"id": "local-1", "model": payload["model"], "choices": [], "usage": { - "prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2}}, + { + "id": "local-1", + "model": payload["model"], + "choices": [{"index": 0, "text": "ok", "finish_reason": None}], + }, + { + "id": "local-1", + "model": payload["model"], + "choices": [{"index": 0, "text": "", "finish_reason": "stop"}], + }, + { + "id": "local-1", + "model": payload["model"], + "choices": [], + "usage": {"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2}, + }, ] body = b"".join(b"data: " + json.dumps(frame).encode() + b"\n\n" for frame in frames) body += b"data: [DONE]\n\n" @@ -66,11 +75,17 @@ def main(): ledger_path = root / "shadow.db" with ShadowLedger(ledger_path) as ledger: ledger.grant_test_credits("fixture_grant", metadata["id"], 4096) - profile = ProviderProfile("test/metered", "test/model", Availability.AVAILABLE, - qualification_id="e" * 64) + profile = ProviderProfile( + "test/metered", "test/model", Availability.AVAILABLE, qualification_id="e" * 64 + ) binding = ManagedVllmBinding( - profile, "test/model", f"http://127.0.0.1:{server.server_port}", - "local-only", (0,), 1, 1, + profile, + "test/model", + f"http://127.0.0.1:{server.server_port}", + "local-only", + (0,), + 1, + 1, ) bridge = ManagedVllmTextClient( ManagedVllmAdapter(binding), ProviderIdentity("test/provider", "test/instance"), MANIFEST @@ -81,8 +96,7 @@ def main(): ModelDescriptor("test/model", manifest_digest=MANIFEST), lambda: ModelRuntime(model=None, tokenizer=None, text_client=metered), ) - app = create_app(model_manager=manager, api_key_identifier=key_store.identify, - request_timeout=5.0) + app = create_app(model_manager=manager, api_key_identifier=key_store.identify, request_timeout=5.0) with TestClient(app) as client: request = {"model": "test/model", "prompt": "hello", "max_tokens": 20} assert client.post("/v1/completions", json=request).status_code == 401 @@ -96,8 +110,9 @@ def main(): receipt = ledger.pending_receipts()[0] assert receipt.input_units == receipt.output_units == 1 assert receipt.proposed_charge == 2 and receipt.provider_id == metered.provider_id - unfunded = client.post("/v1/completions", json=request, - headers={"Authorization": "Bearer " + other_secret}) + unfunded = client.post( + "/v1/completions", json=request, headers={"Authorization": "Bearer " + other_secret} + ) assert unfunded.status_code == 400 and len(CALLS) == 1 streamed = client.post("/v1/completions", json={**request, "stream": True}, headers=headers) assert streamed.status_code == 200 and "data: [DONE]" in streamed.text @@ -105,12 +120,19 @@ def main(): no_balance = client.post("/v1/completions", json=request, headers=headers) assert no_balance.status_code == 400 and len(CALLS) == 2 ledger.grant_test_credits("failure_fixture", other_metadata["id"], 2048) - failed = client.post("/v1/completions", json={**request, "prompt": "fail"}, - headers={"Authorization": "Bearer " + other_secret}) + failed = client.post( + "/v1/completions", + json={**request, "prompt": "fail"}, + headers={"Authorization": "Bearer " + other_secret}, + ) assert failed.status_code == 503, failed.text assert len(CALLS) == 3 other_wallet = ledger.buyer_wallet(other_metadata["id"]) - assert (other_wallet["available"], other_wallet["held"], other_wallet["pending_receipts"]) == (2048, 0, 0) + assert (other_wallet["available"], other_wallet["held"], other_wallet["pending_receipts"]) == ( + 2048, + 0, + 0, + ) key_store.revoke(metadata["id"]) assert client.post("/v1/completions", json=request, headers=headers).status_code == 401 assert len(CALLS) == 3 diff --git a/scripts/check_simulated_paid_text.py b/scripts/check_simulated_paid_text.py index 0aa9bb25b..64d6638db 100644 --- a/scripts/check_simulated_paid_text.py +++ b/scripts/check_simulated_paid_text.py @@ -30,13 +30,24 @@ def quote_for_request(body, chat, context): assert chat is False and body["model"] == DIGEST return SimulatedServiceQuote( - request_id=context.request_id, buyer_id=context.caller_id, provider_id="provider", - funding_source="purchased", model_id=MODEL, profile_id=PROFILE.profile_id, - service_class="text_inference", settlement_domain="local_simulation", - artifact_sha256=DIGEST[7:], service_policy_sha256="b" * 64, - price_schedule_sha256="d" * 64, input_unit_price=1, output_unit_price=1, - max_input_units=20, max_output_units=4, fee_bps=1000, - spend_cap=24, expires_at_unix=int(time.time()) + 60, + request_id=context.request_id, + buyer_id=context.caller_id, + provider_id="provider", + funding_source="purchased", + model_id=MODEL, + profile_id=PROFILE.profile_id, + service_class="text_inference", + settlement_domain="local_simulation", + artifact_sha256=DIGEST[7:], + service_policy_sha256="b" * 64, + price_schedule_sha256="d" * 64, + input_unit_price=1, + output_unit_price=1, + max_input_units=20, + max_output_units=4, + fee_bps=1000, + spend_cap=24, + expires_at_unix=int(time.time()) + 60, ) @@ -46,8 +57,12 @@ def fake_response(request): frames = [ {"id": "fake-1", "model": model, "choices": [{"index": 0, "text": "hello", "finish_reason": None}]}, {"id": "fake-1", "model": model, "choices": [{"index": 0, "text": "", "finish_reason": "length"}]}, - {"id": "fake-1", "model": model, "choices": [], - "usage": {"prompt_tokens": 2, "completion_tokens": 1, "total_tokens": 3}}, + { + "id": "fake-1", + "model": model, + "choices": [], + "usage": {"prompt_tokens": 2, "completion_tokens": 1, "total_tokens": 3}, + }, ] body = b"".join(b"data: " + json.dumps(frame).encode() + b"\n\n" for frame in frames) return httpx.Response(200, headers={"content-type": "text/event-stream"}, content=body + b"data: [DONE]\n\n") @@ -56,7 +71,8 @@ def fake_response(request): def client_for(journal, backend_client): bridge = ManagedVllmTextClient( ManagedLlamaCppAdapter(BINDING, client=backend_client), - ProviderIdentity("provider", "instance"), DIGEST, + ProviderIdentity("provider", "instance"), + DIGEST, ) return SimulatedPaidTextClient(bridge, journal, quote_for_request) @@ -67,8 +83,9 @@ async def failed_and_cancelled(journal): paid = client_for(journal, backend) context = RequestContext.start(5, caller_id="buyer") try: - async for _ in paid.stream({"model": DIGEST, "prompt": "bad", "max_tokens": 4}, - chat=False, context=context): + async for _ in paid.stream( + {"model": DIGEST, "prompt": "bad", "max_tokens": 4}, chat=False, context=context + ): pass except ManagedProviderUnavailable: pass @@ -82,8 +99,7 @@ async def failed_and_cancelled(journal): try: paid = client_for(journal, backend) context = RequestContext.start(5, caller_id="buyer") - iterator = paid.stream({"model": DIGEST, "prompt": "cancel", "max_tokens": 4}, - chat=False, context=context) + iterator = paid.stream({"model": DIGEST, "prompt": "cancel", "max_tokens": 4}, chat=False, context=context) assert (await anext(iterator))["type"] == "heartbeat" assert journal.buyer_wallet("buyer")["service_held"] == 24 await iterator.aclose() @@ -102,8 +118,10 @@ def main(): try: manager = ModelManager() paid = client_for(journal, backend) - manager.register(ModelDescriptor(MODEL, manifest_digest=DIGEST), - lambda: ModelRuntime(model=None, tokenizer=None, text_client=paid)) + manager.register( + ModelDescriptor(MODEL, manifest_digest=DIGEST), + lambda: ModelRuntime(model=None, tokenizer=None, text_client=paid), + ) app = create_app( model_manager=manager, api_key_identifier=lambda key: "buyer" if key == "buyer-key" else None, diff --git a/scripts/check_vllm_context_binding.py b/scripts/check_vllm_context_binding.py index e3ce87771..d700bc76d 100644 --- a/scripts/check_vllm_context_binding.py +++ b/scripts/check_vllm_context_binding.py @@ -20,10 +20,17 @@ async def main(): - profile = ProviderProfile("test/small-vllm-profile", "test/small-vllm", Availability.AVAILABLE, - qualification_id="a" * 64) + profile = ProviderProfile( + "test/small-vllm-profile", "test/small-vllm", Availability.AVAILABLE, qualification_id="a" * 64 + ) binding = ManagedVllmBinding( - profile, profile.model_id, "http://127.0.0.1:18247", "key", (0,), 1, 1, + profile, + profile.model_id, + "http://127.0.0.1:18247", + "key", + (0,), + 1, + 1, max_model_len=256, ) with tempfile.TemporaryDirectory() as temporary: @@ -42,12 +49,15 @@ async def main(): else: raise AssertionError("probe context disagreed with route binding") bridge = ManagedVllmTextClient( - ManagedVllmAdapter(binding), ProviderIdentity("provider", "instance"), "sha256:" + "c" * 64, + ManagedVllmAdapter(binding), + ProviderIdentity("provider", "instance"), + "sha256:" + "c" * 64, ) try: async for _ in bridge.stream( {"model": "sha256:" + "c" * 64, "prompt": "hi", "max_tokens": 256}, - chat=False, context=RequestContext.start(5), + chat=False, + context=RequestContext.start(5), ): pass except ValueError: diff --git a/scripts/prepare_llama_b11173_local.py b/scripts/prepare_llama_b11173_local.py index b3e04b9f6..c7312f2bc 100644 --- a/scripts/prepare_llama_b11173_local.py +++ b/scripts/prepare_llama_b11173_local.py @@ -13,10 +13,8 @@ from pathlib import Path ASSETS = { - "llama-b11173-bin-win-cuda-12.4-x64.zip": - "322a376be0ebecdf965d3519a8cc9f5b318ea1f8766f5e2a955877f60339900c", - "cudart-llama-bin-win-cuda-12.4-x64.zip": - "8c79a9b226de4b3cacfd1f83d24f962d0773be79f1e7b75c6af4ded7e32ae1d6", + "llama-b11173-bin-win-cuda-12.4-x64.zip": "322a376be0ebecdf965d3519a8cc9f5b318ea1f8766f5e2a955877f60339900c", + "cudart-llama-bin-win-cuda-12.4-x64.zip": "8c79a9b226de4b3cacfd1f83d24f962d0773be79f1e7b75c6af4ded7e32ae1d6", } @@ -50,8 +48,14 @@ def main() -> int: for entry in archive.infolist(): name = entry.filename if ( - entry.is_dir() or not name or name in names or "/" in name or "\\" in name - or name in {".", ".."} or ":" in name or (entry.external_attr >> 16) & 0o170000 == 0o120000 + entry.is_dir() + or not name + or name in names + or "/" in name + or "\\" in name + or name in {".", ".."} + or ":" in name + or (entry.external_attr >> 16) & 0o170000 == 0o120000 ): parser.error(f"unsafe or duplicate archive member: {name}") names.add(name) diff --git a/scripts/probe_volunteer_linux_host.py b/scripts/probe_volunteer_linux_host.py index 5f96a0518..891580a2e 100644 --- a/scripts/probe_volunteer_linux_host.py +++ b/scripts/probe_volunteer_linux_host.py @@ -14,8 +14,7 @@ import sys from pathlib import Path -from probe_deepseek_h100_host import make_report as make_h100_report -from probe_deepseek_h100_host import parse_gpu_inventory, probe as probe_h100 +from probe_deepseek_h100_host import make_report as make_h100_report, parse_gpu_inventory, probe as probe_h100 _MAX_OUTPUT = 16_384 _UNIT = "communityai-multigpu-anchor.service" @@ -125,9 +124,8 @@ def glm_w4a8_h100_preflight(h100: dict[str, object]) -> dict[str, object]: "variant": "third-party-W4A8", "necessary_checks": { "eight_h100_80gb_class": checks.get("eight_h100_80gb_class") is True, - "each_gpu_free_at_least_recipe_eighth": len(free) == 8 and all( - amount >= _GLM_W4A8_PER_RANK_BYTES for amount in free - ), + "each_gpu_free_at_least_recipe_eighth": len(free) == 8 + and all(amount >= _GLM_W4A8_PER_RANK_BYTES for amount in free), "aggregate_gpu_free_at_least_recipe_minimum": sum(free) >= _GLM_W4A8_RECIPE_GPU_BYTES, "storage_free_at_least_pinned_weight_bytes": storage >= _GLM_W4A8_WEIGHT_BYTES, }, @@ -176,8 +174,7 @@ def run(command): missing = systemd_readiness(1000, mount, run=lambda _: None) assert missing["linger"] == "unavailable" and missing["anchor_unit_loaded"] is False sample = "\n".join(f"{i}, NVIDIA H100 80GB HBM3, 81559, 70000, 570.133.20" for i in range(8)) - h100 = make_h100_report(parse_gpu_inventory(sample), 250_000_000_000, - _GLM_W4A8_WEIGHT_BYTES, "ubuntu", "20.04") + h100 = make_h100_report(parse_gpu_inventory(sample), 250_000_000_000, _GLM_W4A8_WEIGHT_BYTES, "ubuntu", "20.04") glm = glm_w4a8_h100_preflight(h100) assert all(glm["necessary_checks"].values()) and glm["backend_qualified"] is False h100["gpus"][0]["free_bytes"] = _GLM_W4A8_PER_RANK_BYTES - 1 diff --git a/scripts/prototype_glm53_w4a8_h100_launch.py b/scripts/prototype_glm53_w4a8_h100_launch.py index a5b96076d..26b2235c8 100644 --- a/scripts/prototype_glm53_w4a8_h100_launch.py +++ b/scripts/prototype_glm53_w4a8_h100_launch.py @@ -8,18 +8,28 @@ def candidate(artifact: str, devices: tuple[int, ...], free_gpu_bytes: tuple[int if artifact != ARTIFACT: raise ValueError("wrong artifact") if ( - type(devices) is not tuple or len(devices) != 8 + type(devices) is not tuple + or len(devices) != 8 or any(type(device) is not int or device < 0 for device in devices) or len(set(devices)) != 8 - or type(free_gpu_bytes) is not tuple or len(free_gpu_bytes) != 8 + or type(free_gpu_bytes) is not tuple + or len(free_gpu_bytes) != 8 or any(type(amount) is not int or amount < (MINIMUM_GPU_BYTES + 7) // 8 for amount in free_gpu_bytes) or sum(free_gpu_bytes) < MINIMUM_GPU_BYTES ): raise ValueError("H100 W4A8 candidate requires eight distinct adequately free GPUs") return ( - "vllm", "serve", "/reviewed/snapshot", "--served-model-name", ARTIFACT, - "--tensor-parallel-size", "8", "--enable-expert-parallel", - "--kv-cache-dtype", "fp8_ds_mla", "--trust-remote-code", + "vllm", + "serve", + "/reviewed/snapshot", + "--served-model-name", + ARTIFACT, + "--tensor-parallel-size", + "8", + "--enable-expert-parallel", + "--kv-cache-dtype", + "fp8_ds_mla", + "--trust-remote-code", ) diff --git a/scripts/prototype_vllm_process_owner.py b/scripts/prototype_vllm_process_owner.py index 225820abf..ecd885f37 100644 --- a/scripts/prototype_vllm_process_owner.py +++ b/scripts/prototype_vllm_process_owner.py @@ -1,10 +1,10 @@ """Short process-tree containment experiment; no vLLM, model or GPU required.""" +import importlib.util import subprocess import sys import tempfile import time -import importlib.util from pathlib import Path SUPERVISOR = Path(__file__).resolve().parents[1] / "src" / "drift" / "node" / "edge_supervisor.py" diff --git a/scripts/smoke_llama_b11173_local.py b/scripts/smoke_llama_b11173_local.py index 5abb049ae..b73377303 100644 --- a/scripts/smoke_llama_b11173_local.py +++ b/scripts/smoke_llama_b11173_local.py @@ -33,7 +33,12 @@ from drift.node.edge_supervisor import _force_containment_exit, _new_containment # noqa: E402 from drift.inference_provider import ( # noqa: E402 - Availability, EventKind, InferenceLimits, InferenceRequest, ProviderIdentity, ProviderProfile, + Availability, + EventKind, + InferenceLimits, + InferenceRequest, + ProviderIdentity, + ProviderProfile, ) from drift.managed_llama_cpp import ManagedLlamaCppAdapter, ManagedLlamaCppBinding # noqa: E402 from drift.managed_vllm import ManagedGenerationOptions # noqa: E402 @@ -67,10 +72,17 @@ def free_port() -> int: def gpu_memory_mib() -> int: - output = subprocess.run( - ["nvidia-smi", "--query-gpu=memory.used", "--format=csv,noheader,nounits"], - capture_output=True, text=True, timeout=5, check=True, - ).stdout.strip().splitlines() + output = ( + subprocess.run( + ["nvidia-smi", "--query-gpu=memory.used", "--format=csv,noheader,nounits"], + capture_output=True, + text=True, + timeout=5, + check=True, + ) + .stdout.strip() + .splitlines() + ) if len(output) != 1 or not output[0].strip().isdecimal(): raise RuntimeError("single local GPU memory report is unavailable") return int(output[0].strip()) @@ -96,20 +108,49 @@ def main() -> int: key_file = Path(temporary) / "key.txt" key_file.write_text(key + "\n", encoding="ascii") command = [ - str(SERVER), "--model", str(MODEL), "--alias", ALIAS, - "--host", "127.0.0.1", "--port", str(port), - "--api-key-file", str(key_file), "--no-ui", "--no-slots", - "--device", "CUDA0", "--split-mode", "none", "--gpu-layers", "all", - "--fit", "off", "--ctx-size", "256", "--parallel", "1", - "--flash-attn", "off", "--ignore-eos", "--no-cache-prompt", - "--verbosity", "4", + str(SERVER), + "--model", + str(MODEL), + "--alias", + ALIAS, + "--host", + "127.0.0.1", + "--port", + str(port), + "--api-key-file", + str(key_file), + "--no-ui", + "--no-slots", + "--device", + "CUDA0", + "--split-mode", + "none", + "--gpu-layers", + "all", + "--fit", + "off", + "--ctx-size", + "256", + "--parallel", + "1", + "--flash-attn", + "off", + "--ignore-eos", + "--no-cache-prompt", + "--verbosity", + "4", ] environment = os.environ.copy() environment.update(HF_HUB_OFFLINE="1", TRANSFORMERS_OFFLINE="1") with LOG.open("w", encoding="utf-8") as log: process = subprocess.Popen( - command, cwd=str(ROOT / "run"), stdin=subprocess.DEVNULL, - stdout=log, stderr=subprocess.STDOUT, shell=False, env=environment, + command, + cwd=str(ROOT / "run"), + stdin=subprocess.DEVNULL, + stdout=log, + stderr=subprocess.STDOUT, + shell=False, + env=environment, **containment.popen_kwargs(), ) containment.attach(process) @@ -134,7 +175,8 @@ def main() -> int: models = client.get(base + "/v1/models", headers=headers).json() props = client.get(base + "/props", headers=headers).json() if ( - models.get("object") != "list" or len(models.get("data", [])) != 1 + models.get("object") != "list" + or len(models.get("data", [])) != 1 or models["data"][0].get("id") != ALIAS or props.get("model_path") != str(MODEL) or props.get("total_slots") != 1 @@ -144,9 +186,16 @@ def main() -> int: for limit in (4, 16, 16, 16): began = time.monotonic() response = client.post( - base + "/v1/completions", headers=headers, - json={"model": ALIAS, "prompt": PROMPT, "max_tokens": limit, - "temperature": 0, "stream": False}, timeout=20, + base + "/v1/completions", + headers=headers, + json={ + "model": ALIAS, + "prompt": PROMPT, + "max_tokens": limit, + "temperature": 0, + "stream": False, + }, + timeout=20, ) seconds = time.monotonic() - began response.raise_for_status() @@ -154,21 +203,37 @@ def main() -> int: usage = body.get("usage") choices = body.get("choices") if ( - type(usage) is not dict or type(choices) is not list or len(choices) != 1 - or type(choices[0]) is not dict or not choices[0].get("text") + type(usage) is not dict + or type(choices) is not list + or len(choices) != 1 + or type(choices[0]) is not dict + or not choices[0].get("text") or type(usage.get("prompt_tokens")) is not int or usage.get("completion_tokens") != limit ): raise RuntimeError("llama-server completion or usage mismatch") - runs.append({"output_tokens": limit, "seconds": round(seconds, 3), - "tokens_per_second_including_prefill": round(limit / seconds, 3)}) + runs.append( + { + "output_tokens": limit, + "seconds": round(seconds, 3), + "tokens_per_second_including_prefill": round(limit / seconds, 3), + } + ) stream_frames = [] stream_done = False with client.stream( - "POST", base + "/v1/completions", headers=headers, - json={"model": ALIAS, "prompt": PROMPT, "max_tokens": 4, - "temperature": 0, "stream": True, - "stream_options": {"include_usage": True}}, timeout=20, + "POST", + base + "/v1/completions", + headers=headers, + json={ + "model": ALIAS, + "prompt": PROMPT, + "max_tokens": 4, + "temperature": 0, + "stream": True, + "stream_options": {"include_usage": True}, + }, + timeout=20, ) as response: response.raise_for_status() for line in response.iter_lines(): @@ -189,27 +254,36 @@ def main() -> int: if not stream_done or not stream_frames: raise RuntimeError("llama.cpp SSE did not terminate") profile = ProviderProfile( - "test/qwen-llama-local", ALIAS, Availability.AVAILABLE, + "test/qwen-llama-local", + ALIAS, + Availability.AVAILABLE, qualification_id="1" * 64, ) binding = ManagedLlamaCppBinding(profile, ALIAS, base, key, (0,), "none", 256) now = time.monotonic() request = InferenceRequest( ProviderIdentity("test/local-provider", "test/local-instance"), - profile.profile_id, profile.model_id, secrets.token_hex(16), - secrets.token_hex(16), now, now + 20, PROMPT, + profile.profile_id, + profile.model_id, + secrets.token_hex(16), + secrets.token_hex(16), + now, + now + 20, + PROMPT, InferenceLimits(252, 4, 100, 4096), ) async def check_adapter(): adapter = ManagedLlamaCppAdapter(binding) - return [event async for event in adapter.stream( - request, options=ManagedGenerationOptions(temperature=0) - )] + return [ + event + async for event in adapter.stream(request, options=ManagedGenerationOptions(temperature=0)) + ] adapter_events = asyncio.run(check_adapter()) if ( - not adapter_events or adapter_events[-1].kind is not EventKind.COMPLETED + not adapter_events + or adapter_events[-1].kind is not EventKind.COMPLETED or adapter_events[-1].usage is None or adapter_events[-1].usage.output_units != 4 or not any(event.kind is EventKind.OUTPUT for event in adapter_events) @@ -218,7 +292,9 @@ async def check_adapter(): digest = "sha256:" + "c" * 64 manager = ModelManager() bridge = ManagedVllmTextClient( - ManagedLlamaCppAdapter(binding), request.identity, digest, + ManagedLlamaCppAdapter(binding), + request.identity, + digest, ) manager.register( ModelDescriptor(ALIAS, manifest_digest=digest), @@ -228,33 +304,36 @@ async def check_adapter(): with TestClient(app) as app_client: api_response = app_client.post( "/v1/completions", - json={"model": ALIAS, "prompt": PROMPT, "max_tokens": 4, - "temperature": 0, "stream": False}, + json={"model": ALIAS, "prompt": PROMPT, "max_tokens": 4, "temperature": 0, "stream": False}, headers={"Authorization": "Bearer local-api-key"}, ) if api_response.status_code != 200: raise RuntimeError("CommunityAI API to llama.cpp failed: " + api_response.text[:300]) api_body = api_response.json() - if ( - not api_body["choices"][0]["text"] - or api_body["usage"]["completion_tokens"] != 4 - ): + if not api_body["choices"][0]["text"] or api_body["usage"]["completion_tokens"] != 4: raise RuntimeError("CommunityAI API completion or usage mismatch") - result = {"model": "Qwen/Qwen3-1.7B", "backend": "llama.cpp b11173 CUDA", - "gpu_count_used": 1, "runs": runs, - "median_16_token_seconds": round(statistics.median(run["seconds"] for run in runs[1:]), 3), - "gpu_memory_delta_mib": loaded_gpu_memory - baseline_gpu_memory, - "sse_frames": len(stream_frames), - "communityai_adapter_completed": True, - "communityai_api_completed": True, - "props_build_info": props.get("build_info"), - "sse_models": sorted({str(frame.get("model")) for frame in stream_frames}), - "sse_final_usage": any(type(frame.get("usage")) is dict for frame in stream_frames), - "sse_finish_reasons": sorted({ - str(choice.get("finish_reason")) - for frame in stream_frames for choice in frame.get("choices", []) - if type(choice) is dict and choice.get("finish_reason") is not None - })} + result = { + "model": "Qwen/Qwen3-1.7B", + "backend": "llama.cpp b11173 CUDA", + "gpu_count_used": 1, + "runs": runs, + "median_16_token_seconds": round(statistics.median(run["seconds"] for run in runs[1:]), 3), + "gpu_memory_delta_mib": loaded_gpu_memory - baseline_gpu_memory, + "sse_frames": len(stream_frames), + "communityai_adapter_completed": True, + "communityai_api_completed": True, + "props_build_info": props.get("build_info"), + "sse_models": sorted({str(frame.get("model")) for frame in stream_frames}), + "sse_final_usage": any(type(frame.get("usage")) is dict for frame in stream_frames), + "sse_finish_reasons": sorted( + { + str(choice.get("finish_reason")) + for frame in stream_frames + for choice in frame.get("choices", []) + if type(choice) is dict and choice.get("finish_reason") is not None + } + ), + } except BaseException: if LOG.exists(): print(LOG.read_text(encoding="utf-8", errors="replace")[-2500:], file=sys.stderr) diff --git a/src/drift/commerce_simulator.py b/src/drift/commerce_simulator.py index a50313a77..9adbac0a8 100644 --- a/src/drift/commerce_simulator.py +++ b/src/drift/commerce_simulator.py @@ -50,8 +50,7 @@ def _digest(value: object) -> str: def _buyer_account(buyer_id: str, source: str, resale_listing_id: str | None = None) -> str: - _require(type(source) is str and source in {"purchased", "earned", "resale"}, - "invalid buyer funding provenance") + _require(type(source) is str and source in {"purchased", "earned", "resale"}, "invalid buyer funding provenance") if source == "resale": _id(resale_listing_id) return "buyer_resale:" + buyer_id + ":" + resale_listing_id @@ -85,7 +84,9 @@ class SimulatedServiceQuote: resale_listing_id: str | None = None def __post_init__(self) -> None: - _id(self.request_id); _id(self.buyer_id); _id(self.provider_id) + _id(self.request_id) + _id(self.buyer_id) + _id(self.provider_id) _require(self.buyer_id != self.provider_id, "self-provided service is ineligible") _buyer_account(self.buyer_id, self.funding_source, self.resale_listing_id) _id(self.service_class) @@ -94,20 +95,21 @@ def __post_init__(self) -> None: _require(type(value) is str and _MODEL_ID.fullmatch(value) is not None, "invalid quote profile") for value in (self.artifact_sha256, self.service_policy_sha256, self.price_schedule_sha256): _require(type(value) is str and _HASH.fullmatch(value) is not None, "invalid quote digest") - for value in (self.input_unit_price, self.output_unit_price, - self.max_input_units, self.max_output_units): + for value in (self.input_unit_price, self.output_unit_price, self.max_input_units, self.max_output_units): _amount(value) _amount(self.spend_cap, positive=True) _require( - 0 < self.input_unit_price * self.max_input_units - + self.output_unit_price * self.max_output_units <= self.spend_cap, + 0 + < self.input_unit_price * self.max_input_units + self.output_unit_price * self.max_output_units + <= self.spend_cap, "quote cap does not cover maximum priced work", ) _require(type(self.fee_bps) is int and 0 <= self.fee_bps <= 10_000, "invalid quoted fee") - _require(type(self.expires_at_unix) is int and 0 < self.expires_at_unix < 2**53, - "invalid quote expiry") - _require(type(self.version) is int and self.version == (2 if self.funding_source == "resale" else 1), - "unsupported quote version") + _require(type(self.expires_at_unix) is int and 0 < self.expires_at_unix < 2**53, "invalid quote expiry") + _require( + type(self.version) is int and self.version == (2 if self.funding_source == "resale" else 1), + "unsupported quote version", + ) @property def digest(self) -> str: @@ -209,14 +211,26 @@ def __init__(self, path: str | Path) -> None: try: self._db.execute("BEGIN IMMEDIATE") if version == 0: - _require(all( - self._db.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0] == 0 - for table in ( - "accounts", "events", "postings", "orders", "inbox", "reservations", - "quotes", "releases", "payouts", "resale_listings", "resale_inbox", - "resale_releases", - ) - ), "unversioned commerce journal") + _require( + all( + self._db.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0] == 0 + for table in ( + "accounts", + "events", + "postings", + "orders", + "inbox", + "reservations", + "quotes", + "releases", + "payouts", + "resale_listings", + "resale_inbox", + "resale_releases", + ) + ), + "unversioned commerce journal", + ) self._db.execute(f"PRAGMA user_version={SCHEMA_VERSION}") elif migrating: self._db.execute( @@ -231,8 +245,10 @@ def __init__(self, path: str | Path) -> None: self._db.execute("DROP TABLE reservations") self._db.execute("ALTER TABLE reservations_v2 RENAME TO reservations") self._db.execute("PRAGMA user_version=2") - _require(not self._db.execute("PRAGMA foreign_key_check").fetchone(), - "commerce journal migration foreign key mismatch") + _require( + not self._db.execute("PRAGMA foreign_key_check").fetchone(), + "commerce journal migration foreign key mismatch", + ) self._account("external_funding", "external") self._account("operator_loss", "loss") self._account("fees", "fees") @@ -273,8 +289,10 @@ def _load_quote(self, request_id: str) -> SimulatedServiceQuote: try: terms = json.loads(row[0]) _require(type(terms) is dict, "invalid stored quote terms") - _require(json.dumps(terms, sort_keys=True, separators=(",", ":"), ensure_ascii=True) == row[0], - "noncanonical quote") + _require( + json.dumps(terms, sort_keys=True, separators=(",", ":"), ensure_ascii=True) == row[0], + "noncanonical quote", + ) quote = SimulatedServiceQuote(**terms) except (TypeError, ValueError, json.JSONDecodeError) as exc: raise CommerceSimulationError("invalid stored quote") from exc @@ -282,8 +300,7 @@ def _load_quote(self, request_id: str) -> SimulatedServiceQuote: reservation = self._db.execute( "SELECT buyer_id,source,cap FROM reservations WHERE request_id=?", (request_id,) ).fetchone() - _require(reservation == (quote.buyer_id, quote.funding_source, quote.spend_cap), - "quote reservation mismatch") + _require(reservation == (quote.buyer_id, quote.funding_source, quote.spend_cap), "quote reservation mismatch") return quote def _post(self, event_id: str, kind: str, postings: list[tuple[str, int]], payload: object) -> bool: @@ -325,8 +342,12 @@ def _apply_order(self, processor_ref: str) -> None: buyer = _buyer_account(buyer_id, "purchased") if status == "pending" and captures: self._account(buyer, "buyer_purchased") - self._post("capture:" + order_id, "capture", [("external_funding", -amount), (buyer, amount)], - [order_id, processor_ref, amount]) + self._post( + "capture:" + order_id, + "capture", + [("external_funding", -amount), (buyer, amount)], + [order_id, processor_ref, amount], + ) self._db.execute( "UPDATE orders SET status='captured',capture_event_id=? WHERE order_id=?", (captures[0], order_id) ) @@ -334,7 +355,8 @@ def _apply_order(self, processor_ref: str) -> None: if status == "captured" and reversals: recovered = min(self._balance(buyer), amount) self._post( - "reversal:" + order_id, "reversal", + "reversal:" + order_id, + "reversal", [(buyer, -recovered), ("operator_loss", -(amount - recovered)), ("external_funding", amount)], [order_id, processor_ref, amount, recovered], ) @@ -343,17 +365,16 @@ def _apply_order(self, processor_ref: str) -> None: ) status = "reversed" if status in {"captured", "reversed"}: - self._db.execute( - "UPDATE inbox SET processed=1 WHERE processor_ref=? AND kind='capture'", (processor_ref,) - ) + self._db.execute("UPDATE inbox SET processed=1 WHERE processor_ref=? AND kind='capture'", (processor_ref,)) if status == "reversed": - self._db.execute( - "UPDATE inbox SET processed=1 WHERE processor_ref=? AND kind='reversal'", (processor_ref,) - ) + self._db.execute("UPDATE inbox SET processed=1 WHERE processor_ref=? AND kind='reversal'", (processor_ref,)) def create_order(self, order_id: str, buyer_id: str, processor_ref: str, amount: int) -> bool: """Create a simulated purchase intent; no access is credited yet.""" - _id(order_id); _id(buyer_id); _id(processor_ref); _amount(amount, positive=True) + _id(order_id) + _id(buyer_id) + _id(processor_ref) + _amount(amount, positive=True) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: @@ -373,8 +394,10 @@ def create_order(self, order_id: str, buyer_id: str, processor_ref: str, amount: resale_inbox_collision = self._db.execute( "SELECT 1 FROM resale_inbox WHERE processor_ref=?", (processor_ref,) ).fetchone() - _require(collision is None and resale_collision is None and resale_inbox_collision is None, - "processor reference already bound") + _require( + collision is None and resale_collision is None and resale_inbox_collision is None, + "processor reference already bound", + ) self._db.execute( "INSERT INTO orders VALUES (?,?,?,?,'pending',NULL,NULL)", (order_id, buyer_id, processor_ref, amount), @@ -393,7 +416,9 @@ def record_verified_processor_event(self, event_id: str, processor_ref: str, kin Reordered reversal-before-capture is held in the durable inbox. A new event ID for the same economic capture/reversal never posts twice. """ - _id(event_id); _id(processor_ref); _amount(amount, positive=True) + _id(event_id) + _id(processor_ref) + _amount(amount, positive=True) _require(type(kind) is str and kind in {"capture", "reversal"}, "invalid processor event kind") digest = _digest([processor_ref, kind, amount]) with self._lock: @@ -406,15 +431,24 @@ def record_verified_processor_event(self, event_id: str, processor_ref: str, kin _require(old == (processor_ref, kind, amount, digest), "conflicting processor event replay") inserted = False else: - _require(self._db.execute( - "SELECT 1 FROM resale_inbox WHERE event_id=?", (event_id,) - ).fetchone() is None, "processor event ID already used for resale") - _require(self._db.execute( - "SELECT 1 FROM resale_inbox WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already used for resale") - _require(self._db.execute( - "SELECT 1 FROM resale_listings WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already bound to resale") + _require( + self._db.execute("SELECT 1 FROM resale_inbox WHERE event_id=?", (event_id,)).fetchone() is None, + "processor event ID already used for resale", + ) + _require( + self._db.execute( + "SELECT 1 FROM resale_inbox WHERE processor_ref=?", (processor_ref,) + ).fetchone() + is None, + "processor reference already used for resale", + ) + _require( + self._db.execute( + "SELECT 1 FROM resale_listings WHERE processor_ref=?", (processor_ref,) + ).fetchone() + is None, + "processor reference already bound to resale", + ) self._db.execute( "INSERT INTO inbox VALUES (?,?,?,?,?,0)", (event_id, processor_ref, kind, amount, digest) ) @@ -430,8 +464,11 @@ def list_earned_credits( self, listing_id: str, seller_id: str, credits: int, price: int, fee: int, expires_at_unix: int ) -> bool: """Hold converted earned access for one simulated fixed-price resale.""" - _id(listing_id); _id(seller_id) - _amount(credits, positive=True); _amount(price, positive=True); _amount(fee) + _id(listing_id) + _id(seller_id) + _amount(credits, positive=True) + _amount(price, positive=True) + _amount(fee) _require(price == credits and fee < price, "simulated resale requires a one-to-one price") _require(type(expires_at_unix) is int and 0 < expires_at_unix < 2**53, "invalid resale expiry") with self._lock: @@ -442,8 +479,9 @@ def list_earned_credits( (listing_id,), ).fetchone() if old is not None: - _require(old == (seller_id, credits, price, fee, expires_at_unix), - "conflicting resale listing replay") + _require( + old == (seller_id, credits, price, fee, expires_at_unix), "conflicting resale listing replay" + ) self._db.execute("COMMIT") return False _require(self._balance("operator_loss") == 0, "unfunded loss blocks resale") @@ -451,9 +489,12 @@ def list_earned_credits( seller = _buyer_account(seller_id, "earned") hold = "resale_credit_hold:" + listing_id self._account(hold, "resale_credit_hold") - self._post("resale_list:" + listing_id, "resale_list", - [(seller, -credits), (hold, credits)], - [listing_id, seller_id, credits, price, fee, expires_at_unix]) + self._post( + "resale_list:" + listing_id, + "resale_list", + [(seller, -credits), (hold, credits)], + [listing_id, seller_id, credits, price, fee, expires_at_unix], + ) self._db.execute( "INSERT INTO resale_listings VALUES (?,?,?,?,?,?,'open',NULL,NULL,NULL,NULL)", (listing_id, seller_id, credits, price, fee, expires_at_unix), @@ -479,9 +520,12 @@ def cancel_resale_listing(self, listing_id: str) -> bool: self._db.execute("COMMIT") return False _require(status == "open", "ordered or completed resale cannot be cancelled") - self._post("resale_cancel:" + listing_id, "resale_cancel", - [("resale_credit_hold:" + listing_id, -credits), - (_buyer_account(seller_id, "earned"), credits)], [listing_id]) + self._post( + "resale_cancel:" + listing_id, + "resale_cancel", + [("resale_credit_hold:" + listing_id, -credits), (_buyer_account(seller_id, "earned"), credits)], + [listing_id], + ) self._db.execute("UPDATE resale_listings SET status='cancelled' WHERE listing_id=?", (listing_id,)) self._db.execute("COMMIT") return True @@ -510,33 +554,43 @@ def expire_open_resale_listings(self, *, limit: int = 100) -> tuple[str, ...]: def place_resale_order(self, listing_id: str, buyer_id: str, processor_ref: str) -> bool: """Bind one buyer and payment reference to an existing seller hold.""" - _id(listing_id); _id(buyer_id); _id(processor_ref) + _id(listing_id) + _id(buyer_id) + _id(processor_ref) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: row = self._db.execute( "SELECT seller_id,expires_at_unix,status,buyer_id,processor_ref FROM resale_listings " - "WHERE listing_id=?", (listing_id,) + "WHERE listing_id=?", + (listing_id,), ).fetchone() _require(row is not None, "unknown resale listing") seller_id, expiry, status, old_buyer, old_ref = row _require(buyer_id != seller_id, "self resale is ineligible") if status in {"ordered", "sold", "reversed"}: - _require((old_buyer, old_ref) == (buyer_id, processor_ref), - "conflicting resale order replay") + _require((old_buyer, old_ref) == (buyer_id, processor_ref), "conflicting resale order replay") inserted = False else: _require(status == "open" and expiry > time.time(), "resale listing unavailable") _require(self._balance("operator_loss") == 0, "unfunded loss blocks resale") - _require(self._db.execute( - "SELECT 1 FROM orders WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already bound") - _require(self._db.execute( - "SELECT 1 FROM inbox WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already used for purchase") - _require(self._db.execute( - "SELECT 1 FROM resale_listings WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already bound") + _require( + self._db.execute("SELECT 1 FROM orders WHERE processor_ref=?", (processor_ref,)).fetchone() + is None, + "processor reference already bound", + ) + _require( + self._db.execute("SELECT 1 FROM inbox WHERE processor_ref=?", (processor_ref,)).fetchone() + is None, + "processor reference already used for purchase", + ) + _require( + self._db.execute( + "SELECT 1 FROM resale_listings WHERE processor_ref=?", (processor_ref,) + ).fetchone() + is None, + "processor reference already bound", + ) self._db.execute( "UPDATE resale_listings SET status='ordered',buyer_id=?,processor_ref=? WHERE listing_id=?", (buyer_id, processor_ref, listing_id), @@ -552,7 +606,8 @@ def place_resale_order(self, listing_id: str, buyer_id: str, processor_ref: str) def _apply_resale(self, processor_ref: str) -> None: listing = self._db.execute( "SELECT listing_id,seller_id,credits,price,fee,buyer_id,status FROM resale_listings " - "WHERE processor_ref=?", (processor_ref,) + "WHERE processor_ref=?", + (processor_ref,), ).fetchone() if listing is None: return @@ -573,27 +628,39 @@ def _apply_resale(self, processor_ref: str) -> None: # net is zero and no access ever reaches the buyer. cash_hold = "resale_cash_hold:" + listing_id self._account(cash_hold, "resale_cash_hold") - self._post("resale_void_capture:" + listing_id, "resale_void_capture", - [("external_funding", -price), (cash_hold, price)], - [listing_id, processor_ref, captures[0], price]) - self._post("resale_void_reversal:" + listing_id, "resale_void_reversal", - [(cash_hold, -price), ("external_funding", price)], - [listing_id, processor_ref, reversals[0], price]) - self._post("resale_void:" + listing_id, "resale_void", - [(hold, -credits), (seller, credits)], - [listing_id, processor_ref, captures[0], reversals[0]]) + self._post( + "resale_void_capture:" + listing_id, + "resale_void_capture", + [("external_funding", -price), (cash_hold, price)], + [listing_id, processor_ref, captures[0], price], + ) + self._post( + "resale_void_reversal:" + listing_id, + "resale_void_reversal", + [(cash_hold, -price), ("external_funding", price)], + [listing_id, processor_ref, reversals[0], price], + ) + self._post( + "resale_void:" + listing_id, + "resale_void", + [(hold, -credits), (seller, credits)], + [listing_id, processor_ref, captures[0], reversals[0]], + ) self._db.execute( "UPDATE resale_listings SET status='reversed',capture_event_id=?,reversal_event_id=? " - "WHERE listing_id=?", (captures[0], reversals[0], listing_id), + "WHERE listing_id=?", + (captures[0], reversals[0], listing_id), ) status = "reversed" elif status == "ordered" and captures: self._account(buyer, "buyer_resale") self._account(payable, "resale_payable_hold") - self._post("resale_transfer:" + listing_id, "resale_transfer", - [(hold, -credits), (buyer, credits), - ("external_funding", -price), (payable, net), ("fees", fee)], - [listing_id, seller_id, buyer_id, processor_ref, credits, price, fee, captures[0]]) + self._post( + "resale_transfer:" + listing_id, + "resale_transfer", + [(hold, -credits), (buyer, credits), ("external_funding", -price), (payable, net), ("fees", fee)], + [listing_id, seller_id, buyer_id, processor_ref, credits, price, fee, captures[0]], + ) self._db.execute( "UPDATE resale_listings SET status='sold',capture_event_id=? WHERE listing_id=?", (captures[0], listing_id), @@ -602,19 +669,25 @@ def _apply_resale(self, processor_ref: str) -> None: if status == "sold" and reversals: recovered_credits = min(self._balance(buyer), credits) credit_loss = credits - recovered_credits - self._post("resale_credit_reversal:" + listing_id, "resale_credit_reversal", - [(buyer, -recovered_credits), ("operator_loss", -credit_loss), (seller, credits)], - [listing_id, recovered_credits, credit_loss, reversals[0]]) - released = self._db.execute( - "SELECT 1 FROM resale_releases WHERE listing_id=?", (listing_id,) - ).fetchone() is not None + self._post( + "resale_credit_reversal:" + listing_id, + "resale_credit_reversal", + [(buyer, -recovered_credits), ("operator_loss", -credit_loss), (seller, credits)], + [listing_id, recovered_credits, credit_loss, reversals[0]], + ) + released = ( + self._db.execute("SELECT 1 FROM resale_releases WHERE listing_id=?", (listing_id,)).fetchone() + is not None + ) source = "provider_eligible:" + seller_id if released else payable recovered_cash = min(self._balance(source), net) cash_loss = net - recovered_cash - self._post("resale_cash_reversal:" + listing_id, "resale_cash_reversal", - [(source, -recovered_cash), ("fees", -fee), - ("operator_loss", -cash_loss), ("external_funding", price)], - [listing_id, recovered_cash, cash_loss, reversals[0]]) + self._post( + "resale_cash_reversal:" + listing_id, + "resale_cash_reversal", + [(source, -recovered_cash), ("fees", -fee), ("operator_loss", -cash_loss), ("external_funding", price)], + [listing_id, recovered_cash, cash_loss, reversals[0]], + ) self._db.execute( "UPDATE resale_listings SET status='reversed',reversal_event_id=? WHERE listing_id=?", (reversals[0], listing_id), @@ -633,9 +706,10 @@ def _apply_resale(self, processor_ref: str) -> None: def record_verified_resale_event(self, event_id: str, processor_ref: str, kind: str, price: int) -> bool: """Ingest an authenticated simulated resale capture or reversal.""" - _id(event_id); _id(processor_ref); _amount(price, positive=True) - _require(type(kind) is str and kind in {"capture", "reversal"}, - "invalid resale processor event kind") + _id(event_id) + _id(processor_ref) + _amount(price, positive=True) + _require(type(kind) is str and kind in {"capture", "reversal"}, "invalid resale processor event kind") digest = _digest([processor_ref, kind, price]) with self._lock: self._db.execute("BEGIN IMMEDIATE") @@ -645,19 +719,23 @@ def record_verified_resale_event(self, event_id: str, processor_ref: str, kind: (event_id,), ).fetchone() if old is not None: - _require(old == (processor_ref, kind, price, digest), - "conflicting resale processor event replay") + _require(old == (processor_ref, kind, price, digest), "conflicting resale processor event replay") inserted = False else: - _require(self._db.execute( - "SELECT 1 FROM inbox WHERE event_id=?", (event_id,) - ).fetchone() is None, "processor event ID already used for purchase") - _require(self._db.execute( - "SELECT 1 FROM inbox WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already used for purchase") - _require(self._db.execute( - "SELECT 1 FROM orders WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "processor reference already bound to purchase") + _require( + self._db.execute("SELECT 1 FROM inbox WHERE event_id=?", (event_id,)).fetchone() is None, + "processor event ID already used for purchase", + ) + _require( + self._db.execute("SELECT 1 FROM inbox WHERE processor_ref=?", (processor_ref,)).fetchone() + is None, + "processor reference already used for purchase", + ) + _require( + self._db.execute("SELECT 1 FROM orders WHERE processor_ref=?", (processor_ref,)).fetchone() + is None, + "processor reference already bound to purchase", + ) self._db.execute( "INSERT INTO resale_inbox VALUES (?,?,?,?,?,0)", (event_id, processor_ref, kind, price, digest), @@ -672,7 +750,9 @@ def record_verified_resale_event(self, event_id: str, processor_ref: str, kind: def release_resale_proceeds(self, release_id: str, listing_id: str, risk_decision_id: str) -> bool: """Move a sold listing's held seller net into eligible payout balance.""" - _id(release_id); _id(listing_id); _id(risk_decision_id) + _id(release_id) + _id(listing_id) + _id(risk_decision_id) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: @@ -683,10 +763,14 @@ def release_resale_proceeds(self, release_id: str, listing_id: str, risk_decisio _require(old == (listing_id, risk_decision_id), "conflicting resale release replay") self._db.execute("COMMIT") return False - _require(self._db.execute( - "SELECT 1 FROM releases WHERE release_id=? OR risk_decision_id=?", - (release_id, risk_decision_id), - ).fetchone() is None, "release identity already used for ordinary earnings") + _require( + self._db.execute( + "SELECT 1 FROM releases WHERE release_id=? OR risk_decision_id=?", + (release_id, risk_decision_id), + ).fetchone() + is None, + "release identity already used for ordinary earnings", + ) listing = self._db.execute( "SELECT seller_id,price,fee,status FROM resale_listings WHERE listing_id=?", (listing_id,) ).fetchone() @@ -695,12 +779,15 @@ def release_resale_proceeds(self, release_id: str, listing_id: str, risk_decisio seller_id, price, fee, _ = listing eligible = "provider_eligible:" + seller_id self._account(eligible, "provider_eligible") - self._post("resale_release:" + listing_id, "resale_release", - [("resale_payable_hold:" + listing_id, -(price - fee)), - (eligible, price - fee)], - [release_id, listing_id, risk_decision_id]) - self._db.execute("INSERT INTO resale_releases VALUES (?,?,?)", - (release_id, listing_id, risk_decision_id)) + self._post( + "resale_release:" + listing_id, + "resale_release", + [("resale_payable_hold:" + listing_id, -(price - fee)), (eligible, price - fee)], + [release_id, listing_id, risk_decision_id], + ) + self._db.execute( + "INSERT INTO resale_releases VALUES (?,?,?)", (release_id, listing_id, risk_decision_id) + ) self._db.execute("COMMIT") return True except BaseException: @@ -710,9 +797,7 @@ def release_resale_proceeds(self, release_id: str, listing_id: str, risk_decisio def reserve_service(self, quote: SimulatedServiceQuote) -> bool: """Reserve a bound synthetic quote from one funding provenance.""" _require(type(quote) is SimulatedServiceQuote, "bound service quote required") - request_id, buyer_id, source, cap = ( - quote.request_id, quote.buyer_id, quote.funding_source, quote.spend_cap - ) + request_id, buyer_id, source, cap = (quote.request_id, quote.buyer_id, quote.funding_source, quote.spend_cap) buyer = _buyer_account(buyer_id, source, quote.resale_listing_id) with self._lock: self._db.execute("BEGIN IMMEDIATE") @@ -722,8 +807,10 @@ def reserve_service(self, quote: SimulatedServiceQuote) -> bool: ).fetchone() if old is not None: stored = self._load_quote(request_id) - _require(old == (buyer_id, source, cap) and stored.digest == quote.digest, - "conflicting service reservation replay") + _require( + old == (buyer_id, source, cap) and stored.digest == quote.digest, + "conflicting service reservation replay", + ) self._db.execute("COMMIT") return False _require(self._balance("operator_loss") == 0, "unfunded reversal loss blocks service admission") @@ -736,17 +823,23 @@ def reserve_service(self, quote: SimulatedServiceQuote) -> bool: _require(listing == (buyer_id, "sold"), "resale lot is not available for service") hold = "service_hold:" + request_id self._account(hold, "service_hold") - self._post("reserve:" + request_id, "reserve", [(buyer, -cap), (hold, cap)], - [request_id, buyer_id, source, cap, quote.digest]) + self._post( + "reserve:" + request_id, + "reserve", + [(buyer, -cap), (hold, cap)], + [request_id, buyer_id, source, cap, quote.digest], + ) self._db.execute( "INSERT INTO reservations(request_id,buyer_id,source,cap,status) VALUES (?,?,?,?,'held')", (request_id, buyer_id, source, cap), ) self._db.execute( "INSERT INTO quotes VALUES (?,?,?)", - (request_id, - json.dumps(quote.terms, sort_keys=True, separators=(",", ":"), ensure_ascii=True), - quote.digest), + ( + request_id, + json.dumps(quote.terms, sort_keys=True, separators=(",", ":"), ensure_ascii=True), + quote.digest, + ), ) self._db.execute("COMMIT") return True @@ -755,30 +848,57 @@ def reserve_service(self, quote: SimulatedServiceQuote) -> bool: raise def settle_service( - self, request_id: str, provider_id: str, charge: int, fee: int, - decision_id: str, receipt_digest: str, input_units: int, output_units: int, + self, + request_id: str, + provider_id: str, + charge: int, + fee: int, + decision_id: str, + receipt_digest: str, + input_units: int, + output_units: int, ) -> bool: """Apply a simulated independent work decision, not a self-reported claim.""" - _id(request_id); _id(provider_id); _id(decision_id) - _amount(charge, positive=True); _amount(fee); _amount(input_units); _amount(output_units) - _require(fee <= charge and type(receipt_digest) is str and _HASH.fullmatch(receipt_digest) is not None, - "invalid settlement decision") + _id(request_id) + _id(provider_id) + _id(decision_id) + _amount(charge, positive=True) + _amount(fee) + _amount(input_units) + _amount(output_units) + _require( + fee <= charge and type(receipt_digest) is str and _HASH.fullmatch(receipt_digest) is not None, + "invalid settlement decision", + ) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: row = self._db.execute( "SELECT buyer_id,source,cap,status,provider_id,charge,fee,decision_id,receipt_digest," "input_units,output_units " - "FROM reservations WHERE request_id=?", (request_id,) + "FROM reservations WHERE request_id=?", + (request_id,), ).fetchone() _require(row is not None, "unknown service reservation") - (buyer_id, source, cap, status, old_provider, old_charge, old_fee, - old_decision, old_receipt, old_input, old_output) = row + ( + buyer_id, + source, + cap, + status, + old_provider, + old_charge, + old_fee, + old_decision, + old_receipt, + old_input, + old_output, + ) = row if status == "settled": - _require((old_provider, old_charge, old_fee, old_decision, old_receipt, old_input, old_output) - == (provider_id, charge, fee, decision_id, receipt_digest, - input_units, output_units), - "conflicting settlement replay") + _require( + (old_provider, old_charge, old_fee, old_decision, old_receipt, old_input, old_output) + == (provider_id, charge, fee, decision_id, receipt_digest, input_units, output_units), + "conflicting settlement replay", + ) self._db.execute("COMMIT") return False _require(status == "held" and charge <= cap, "service is not held within cap") @@ -787,14 +907,15 @@ def settle_service( _require( input_units <= quote.max_input_units and output_units <= quote.max_output_units - and charge <= input_units * quote.input_unit_price - + output_units * quote.output_unit_price, + and charge <= input_units * quote.input_unit_price + output_units * quote.output_unit_price, "settlement exceeds quoted units or rates", ) _require(fee <= charge * quote.fee_bps // 10_000, "fee exceeds quoted limit") - _require(self._db.execute( - "SELECT 1 FROM reservations WHERE decision_id=?", (decision_id,) - ).fetchone() is None, "decision ID reused") + _require( + self._db.execute("SELECT 1 FROM reservations WHERE decision_id=?", (decision_id,)).fetchone() + is None, + "decision ID reused", + ) pending = "provider_pending:" + provider_id self._account(pending, "provider_pending") refund_account = _buyer_account(buyer_id, source, quote.resale_listing_id) @@ -807,18 +928,30 @@ def settle_service( if listing_status[0] == "reversed": refund_account = "operator_loss" self._post( - "settle:" + request_id, "settle", - [("service_hold:" + request_id, -cap), - (refund_account, cap - charge), - (pending, charge - fee), ("fees", fee)], - [request_id, provider_id, charge, fee, decision_id, receipt_digest, - input_units, output_units, quote.digest], + "settle:" + request_id, + "settle", + [ + ("service_hold:" + request_id, -cap), + (refund_account, cap - charge), + (pending, charge - fee), + ("fees", fee), + ], + [ + request_id, + provider_id, + charge, + fee, + decision_id, + receipt_digest, + input_units, + output_units, + quote.digest, + ], ) self._db.execute( "UPDATE reservations SET status='settled',provider_id=?,charge=?,fee=?," "decision_id=?,receipt_digest=?,input_units=?,output_units=? WHERE request_id=?", - (provider_id, charge, fee, decision_id, receipt_digest, - input_units, output_units, request_id), + (provider_id, charge, fee, decision_id, receipt_digest, input_units, output_units, request_id), ) self._db.execute("COMMIT") return True @@ -828,12 +961,14 @@ def settle_service( def refund_service(self, request_id: str, reason: str) -> bool: """Release an unserved request's entire synthetic hold.""" - _id(request_id); _id(reason) + _id(request_id) + _id(reason) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: row = self._db.execute( - "SELECT buyer_id,source,cap,status,refund_reason FROM reservations WHERE request_id=?", (request_id,) + "SELECT buyer_id,source,cap,status,refund_reason FROM reservations WHERE request_id=?", + (request_id,), ).fetchone() _require(row is not None, "unknown service reservation") buyer_id, source, cap, status, old_reason = row @@ -853,7 +988,8 @@ def refund_service(self, request_id: str, reason: str) -> bool: if listing_status[0] == "reversed": refund_account = "operator_loss" self._post( - "refund_service:" + request_id, "service_refund", + "refund_service:" + request_id, + "service_refund", [("service_hold:" + request_id, -cap), (refund_account, cap)], [request_id, reason], ) @@ -868,7 +1004,10 @@ def refund_service(self, request_id: str, reason: str) -> bool: def release_earnings(self, release_id: str, provider_id: str, amount: int, risk_decision_id: str) -> bool: """Move a simulated settled payable into eligible earnings.""" - _id(release_id); _id(provider_id); _id(risk_decision_id); _amount(amount, positive=True) + _id(release_id) + _id(provider_id) + _id(risk_decision_id) + _amount(amount, positive=True) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: @@ -879,20 +1018,26 @@ def release_earnings(self, release_id: str, provider_id: str, amount: int, risk_ _require(old == (provider_id, amount, risk_decision_id), "conflicting release replay") self._db.execute("COMMIT") return False - _require(self._db.execute( - "SELECT 1 FROM resale_releases WHERE release_id=? OR risk_decision_id=?", - (release_id, risk_decision_id), - ).fetchone() is None, "release identity already used for resale") + _require( + self._db.execute( + "SELECT 1 FROM resale_releases WHERE release_id=? OR risk_decision_id=?", + (release_id, risk_decision_id), + ).fetchone() + is None, + "release identity already used for resale", + ) _require(self._balance("operator_loss") == 0, "unfunded reversal loss blocks earning release") eligible = "provider_eligible:" + provider_id self._account(eligible, "provider_eligible") self._post( - "release:" + release_id, "earning_release", + "release:" + release_id, + "earning_release", [("provider_pending:" + provider_id, -amount), (eligible, amount)], [release_id, provider_id, amount, risk_decision_id], ) - self._db.execute("INSERT INTO releases VALUES (?,?,?,?)", - (release_id, provider_id, amount, risk_decision_id)) + self._db.execute( + "INSERT INTO releases VALUES (?,?,?,?)", (release_id, provider_id, amount, risk_decision_id) + ) self._db.execute("COMMIT") return True except BaseException: @@ -901,7 +1046,9 @@ def release_earnings(self, release_id: str, provider_id: str, amount: int, risk_ def convert_earnings(self, conversion_id: str, provider_id: str, amount: int) -> bool: """Use eligible earnings as a separate source of future access.""" - _id(conversion_id); _id(provider_id); _amount(amount, positive=True) + _id(conversion_id) + _id(provider_id) + _amount(amount, positive=True) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: @@ -913,7 +1060,8 @@ def convert_earnings(self, conversion_id: str, provider_id: str, amount: int) -> earned = _buyer_account(provider_id, "earned") self._account(earned, "buyer_earned") result = self._post( - "convert:" + conversion_id, "earning_conversion", + "convert:" + conversion_id, + "earning_conversion", [("provider_eligible:" + provider_id, -amount), (earned, amount)], [conversion_id, provider_id, amount], ) @@ -925,7 +1073,10 @@ def convert_earnings(self, conversion_id: str, provider_id: str, amount: int) -> def request_payout(self, payout_id: str, provider_id: str, amount: int, external_ref: str) -> bool: """Reserve eligible earnings; an unknown outcome must retain this hold.""" - _id(payout_id); _id(provider_id); _id(external_ref); _amount(amount, positive=True) + _id(payout_id) + _id(provider_id) + _id(external_ref) + _amount(amount, positive=True) with self._lock: self._db.execute("BEGIN IMMEDIATE") try: @@ -940,12 +1091,15 @@ def request_payout(self, payout_id: str, provider_id: str, amount: int, external hold = "payout_hold:" + payout_id self._account(hold, "payout_hold") self._post( - "payout_hold:" + payout_id, "payout_reserve", + "payout_hold:" + payout_id, + "payout_reserve", [("provider_eligible:" + provider_id, -amount), (hold, amount)], [payout_id, provider_id, amount, external_ref], ) - self._db.execute("INSERT INTO payouts VALUES (?,?,?,?,'reserved',NULL)", - (payout_id, provider_id, amount, external_ref)) + self._db.execute( + "INSERT INTO payouts VALUES (?,?,?,?,'reserved',NULL)", + (payout_id, provider_id, amount, external_ref), + ) self._db.execute("COMMIT") return True except BaseException: @@ -973,7 +1127,8 @@ def mark_payout_unknown(self, payout_id: str) -> bool: def resolve_payout(self, payout_id: str, outcome_event_id: str, *, paid: bool) -> bool: """Apply an externally verified final outcome, never a submission ACK.""" - _id(payout_id); _id(outcome_event_id) + _id(payout_id) + _id(outcome_event_id) _require(type(paid) is bool, "invalid payout outcome") with self._lock: self._db.execute("BEGIN IMMEDIATE") @@ -991,7 +1146,8 @@ def resolve_payout(self, payout_id: str, outcome_event_id: str, *, paid: bool) - _require(status in {"reserved", "unknown"}, "invalid payout state") destination = "external_funding" if paid else "provider_eligible:" + provider_id self._post( - "payout_result:" + payout_id, "payout_" + desired, + "payout_result:" + payout_id, + "payout_" + desired, [("payout_hold:" + payout_id, -amount), (destination, amount)], [payout_id, outcome_event_id, desired], ) @@ -1012,7 +1168,8 @@ def buyer_wallet(self, buyer_id: str) -> dict[str, int | str]: "SELECT COALESCE(SUM(cap),0) FROM reservations WHERE buyer_id=? AND status='held'", (buyer_id,) ).fetchone()[0] return { - "unit": "simulated_minor_unit", "buyer_id": buyer_id, + "unit": "simulated_minor_unit", + "buyer_id": buyer_id, "purchased_available": self._balance(_buyer_account(buyer_id, "purchased")), "earned_access_available": self._balance(_buyer_account(buyer_id, "earned")), "resale_access_available": self._db.execute( @@ -1025,7 +1182,8 @@ def buyer_wallet(self, buyer_id: str) -> dict[str, int | str]: def resale_lot_balance(self, buyer_id: str, listing_id: str) -> int: """Read one buyer's nontransferable resale-origin lot.""" - _id(buyer_id); _id(listing_id) + _id(buyer_id) + _id(listing_id) with self._lock: listing = self._db.execute( "SELECT buyer_id FROM resale_listings WHERE listing_id=?", (listing_id,) @@ -1038,10 +1196,12 @@ def provider_wallet(self, provider_id: str) -> dict[str, int | str]: with self._lock: held = self._db.execute( "SELECT COALESCE(SUM(amount),0) FROM payouts WHERE provider_id=? " - "AND status IN ('reserved','unknown')", (provider_id,) + "AND status IN ('reserved','unknown')", + (provider_id,), ).fetchone()[0] return { - "unit": "simulated_minor_unit", "provider_id": provider_id, + "unit": "simulated_minor_unit", + "provider_id": provider_id, "pending": self._balance("provider_pending:" + provider_id), "eligible": self._balance("provider_eligible:" + provider_id), "resale_payable_held": self._db.execute( @@ -1055,9 +1215,11 @@ def provider_wallet(self, provider_id: str) -> dict[str, int | str]: def unresolved_payouts(self) -> tuple[tuple[str, str], ...]: with self._lock: - return tuple(self._db.execute( - "SELECT payout_id,status FROM payouts WHERE status IN ('reserved','unknown') ORDER BY payout_id" - ).fetchall()) + return tuple( + self._db.execute( + "SELECT payout_id,status FROM payouts WHERE status IN ('reserved','unknown') ORDER BY payout_id" + ).fetchall() + ) def unresolved_service_holds(self, *, limit: int = 100) -> tuple[SimulatedServiceQuote, ...]: """Inspect durable holds after a crash; caller must verify work has stopped. @@ -1092,8 +1254,7 @@ def audit(self) -> dict[str, int]: posted = self._db.execute( "SELECT COALESCE(SUM(delta),0) FROM postings WHERE account_id=?", (account_id,) ).fetchone()[0] - _require(balance == posted and (kind in {"external", "loss"} or balance >= 0), - "account mismatch") + _require(balance == posted and (kind in {"external", "loss"} or balance >= 0), "account mismatch") for (event_id,) in self._db.execute("SELECT event_id FROM events"): total = self._db.execute( "SELECT COALESCE(SUM(delta),0) FROM postings WHERE event_id=?", (event_id,) @@ -1107,9 +1268,11 @@ def audit(self) -> dict[str, int]: "SELECT status FROM orders WHERE processor_ref=?", (processor_ref,) ).fetchone() if processed: - _require(order is not None and ( - order[0] == "reversed" or order[0] == "captured" and kind == "capture" - ), "processed processor event has no matching order state") + _require( + order is not None + and (order[0] == "reversed" or order[0] == "captured" and kind == "capture"), + "processed processor event has no matching order state", + ) for order_id, buyer_id, processor_ref, amount, status, capture_id, reversal_id in self._db.execute( "SELECT order_id,buyer_id,processor_ref,amount,status,capture_event_id,reversal_event_id FROM orders" ): @@ -1120,26 +1283,38 @@ def audit(self) -> dict[str, int]: captures = {row[0] for row in rows if row[1] == "capture"} reversals = {row[0] for row in rows if row[1] == "reversal"} if status == "pending": - _require(not captures and capture_id is None and reversal_id is None - and all(row[3] == 0 for row in rows), "pending order mismatch") + _require( + not captures + and capture_id is None + and reversal_id is None + and all(row[3] == 0 for row in rows), + "pending order mismatch", + ) elif status == "captured": - _require(capture_id in captures and not reversals and reversal_id is None - and all(row[3] == 1 for row in rows), "captured order mismatch") + _require( + capture_id in captures + and not reversals + and reversal_id is None + and all(row[3] == 1 for row in rows), + "captured order mismatch", + ) else: - _require(capture_id in captures and reversal_id in reversals - and all(row[3] == 1 for row in rows), "reversed order mismatch") + _require( + capture_id in captures and reversal_id in reversals and all(row[3] == 1 for row in rows), + "reversed order mismatch", + ) if status != "pending": event = self._db.execute( - "SELECT kind,payload_digest FROM events WHERE event_id=?", - ("capture:" + order_id,) + "SELECT kind,payload_digest FROM events WHERE event_id=?", ("capture:" + order_id,) ).fetchone() postings = self._db.execute( "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", - ("capture:" + order_id,) + ("capture:" + order_id,), ).fetchall() _require( event == ("capture", _digest([order_id, processor_ref, amount])) - and postings == [ + and postings + == [ ("external_funding", -amount), (_buyer_account(buyer_id, "purchased"), amount), ], @@ -1147,87 +1322,112 @@ def audit(self) -> dict[str, int]: ) if status == "reversed": event = self._db.execute( - "SELECT kind,payload_digest FROM events WHERE event_id=?", - ("reversal:" + order_id,) + "SELECT kind,payload_digest FROM events WHERE event_id=?", ("reversal:" + order_id,) ).fetchone() postings = self._db.execute( "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", - ("reversal:" + order_id,) + ("reversal:" + order_id,), ).fetchall() recovered = -postings[0][1] if len(postings) == 3 else -1 _require( 0 <= recovered <= amount and event == ("reversal", _digest([order_id, processor_ref, amount, recovered])) - and postings == [ + and postings + == [ (_buyer_account(buyer_id, "purchased"), -recovered), ("operator_loss", -(amount - recovered)), ("external_funding", amount), ], "reversal journal mismatch", ) - for request_id, cap, status in self._db.execute( - "SELECT request_id,cap,status FROM reservations" - ): + for request_id, cap, status in self._db.execute("SELECT request_id,cap,status FROM reservations"): quote = self._load_quote(request_id) _require(quote.spend_cap == cap, "service quote cap mismatch") - _require(self._balance("service_hold:" + request_id) == (cap if status == "held" else 0), - "service hold mismatch") + _require( + self._balance("service_hold:" + request_id) == (cap if status == "held" else 0), + "service hold mismatch", + ) row = self._db.execute( "SELECT provider_id,charge,fee,input_units,output_units,decision_id,receipt_digest,refund_reason " - "FROM reservations WHERE request_id=?", (request_id,) + "FROM reservations WHERE request_id=?", + (request_id,), ).fetchone() provider_id, charge, fee, input_units, output_units, decision_id, receipt_digest, reason = row if status == "settled": _require( provider_id == quote.provider_id - and all(value is not None for value in (charge, fee, input_units, output_units, - decision_id, receipt_digest)) + and all( + value is not None + for value in (charge, fee, input_units, output_units, decision_id, receipt_digest) + ) and input_units <= quote.max_input_units and output_units <= quote.max_output_units and charge <= quote.spend_cap - and charge <= input_units * quote.input_unit_price - + output_units * quote.output_unit_price + and charge <= input_units * quote.input_unit_price + output_units * quote.output_unit_price and fee <= charge * quote.fee_bps // 10_000 and reason is None, "settled quote mismatch", ) else: - _require(provider_id is None and all(value is None for value in - (charge, fee, input_units, output_units, decision_id, receipt_digest)) - and (reason is None if status == "held" else reason is not None), - "unsettled service mismatch") + _require( + provider_id is None + and all( + value is None + for value in (charge, fee, input_units, output_units, decision_id, receipt_digest) + ) + and (reason is None if status == "held" else reason is not None), + "unsettled service mismatch", + ) for event_id, processor_ref, kind, amount, digest, processed in self._db.execute( "SELECT event_id,processor_ref,kind,amount,payload_digest,processed FROM resale_inbox" ): - _require(digest == _digest([processor_ref, kind, amount]), - "resale processor inbox digest mismatch") - _require(self._db.execute( - "SELECT 1 FROM inbox WHERE event_id=? OR processor_ref=?", (event_id, processor_ref) - ).fetchone() is None, "resale processor reference reused for purchase") + _require(digest == _digest([processor_ref, kind, amount]), "resale processor inbox digest mismatch") + _require( + self._db.execute( + "SELECT 1 FROM inbox WHERE event_id=? OR processor_ref=?", (event_id, processor_ref) + ).fetchone() + is None, + "resale processor reference reused for purchase", + ) listing = self._db.execute( "SELECT status FROM resale_listings WHERE processor_ref=?", (processor_ref,) ).fetchone() if processed: - _require(listing is not None and ( - listing[0] == "reversed" or listing[0] == "sold" and kind == "capture" - ), "processed resale event has no matching listing state") - for (listing_id, seller_id, credits, price, fee, expiry, status, - buyer_id, processor_ref, capture_id, reversal_id) in self._db.execute( + _require( + listing is not None + and (listing[0] == "reversed" or listing[0] == "sold" and kind == "capture"), + "processed resale event has no matching listing state", + ) + for ( + listing_id, + seller_id, + credits, + price, + fee, + expiry, + status, + buyer_id, + processor_ref, + capture_id, + reversal_id, + ) in self._db.execute( "SELECT listing_id,seller_id,credits,price,fee,expires_at_unix,status,buyer_id," "processor_ref,capture_event_id,reversal_event_id FROM resale_listings" ): - _require(price == credits and 0 <= fee < price and expiry > 0, - "invalid resale listing terms") + _require(price == credits and 0 <= fee < price and expiry > 0, "invalid resale listing terms") hold = "resale_credit_hold:" + listing_id payable = "resale_payable_hold:" + listing_id - _require(self._balance(hold) == (credits if status in {"open", "ordered"} else 0), - "resale credit hold mismatch") + _require( + self._balance(hold) == (credits if status in {"open", "ordered"} else 0), + "resale credit hold mismatch", + ) release = self._db.execute( "SELECT release_id,risk_decision_id FROM resale_releases WHERE listing_id=?", (listing_id,) ).fetchone() - _require(self._balance(payable) == ( - price - fee if status == "sold" and release is None else 0 - ), "resale payable hold mismatch") + _require( + self._balance(payable) == (price - fee if status == "sold" and release is None else 0), + "resale payable hold mismatch", + ) listed = self._db.execute( "SELECT kind,payload_digest FROM events WHERE event_id=?", ("resale_list:" + listing_id,), @@ -1236,26 +1436,38 @@ def audit(self) -> dict[str, int]: "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", ("resale_list:" + listing_id,), ).fetchall() - _require(listed == ("resale_list", _digest([ - listing_id, seller_id, credits, price, fee, expiry - ])) and listed_postings == [ - (_buyer_account(seller_id, "earned"), -credits), (hold, credits) - ], "resale listing journal mismatch") + _require( + listed == ("resale_list", _digest([listing_id, seller_id, credits, price, fee, expiry])) + and listed_postings == [(_buyer_account(seller_id, "earned"), -credits), (hold, credits)], + "resale listing journal mismatch", + ) if status in {"open", "cancelled"}: - _require(buyer_id is None and processor_ref is None and capture_id is None - and reversal_id is None and release is None, - "unbound resale listing mismatch") + _require( + buyer_id is None + and processor_ref is None + and capture_id is None + and reversal_id is None + and release is None, + "unbound resale listing mismatch", + ) else: - _require(type(buyer_id) is str and buyer_id != seller_id - and type(processor_ref) is str, - "resale buyer binding mismatch") - _require(self._db.execute( - "SELECT 1 FROM orders WHERE processor_ref=?", (processor_ref,) - ).fetchone() is None, "resale processor reference reused for purchase") - rows = [] if processor_ref is None else self._db.execute( - "SELECT event_id,kind,amount,processed FROM resale_inbox WHERE processor_ref=?", - (processor_ref,), - ).fetchall() + _require( + type(buyer_id) is str and buyer_id != seller_id and type(processor_ref) is str, + "resale buyer binding mismatch", + ) + _require( + self._db.execute("SELECT 1 FROM orders WHERE processor_ref=?", (processor_ref,)).fetchone() + is None, + "resale processor reference reused for purchase", + ) + rows = ( + [] + if processor_ref is None + else self._db.execute( + "SELECT event_id,kind,amount,processed FROM resale_inbox WHERE processor_ref=?", + (processor_ref,), + ).fetchall() + ) _require(all(row[2] == price for row in rows), "resale processor amount mismatch") captures = {row[0] for row in rows if row[1] == "capture"} reversals = {row[0] for row in rows if row[1] == "reversal"} @@ -1272,16 +1484,16 @@ def audit(self) -> dict[str, int]: ("resale_void:" + listing_id,), ).fetchone() seller_account = _buyer_account(seller_id, "earned") - buyer_account = ( - _buyer_account(buyer_id, "resale", listing_id) if buyer_id is not None else None - ) + buyer_account = _buyer_account(buyer_id, "resale", listing_id) if buyer_id is not None else None expected_transfer = [ - (hold, -credits), (buyer_account, credits), - ("external_funding", -price), (payable, price - fee), ("fees", fee), + (hold, -credits), + (buyer_account, credits), + ("external_funding", -price), + (payable, price - fee), + ("fees", fee), ] if status == "open": - _require(not rows and transfer is None and void is None, - "open resale listing mismatch") + _require(not rows and transfer is None and void is None, "open resale listing mismatch") elif status == "cancelled": cancelled = self._db.execute( "SELECT kind,payload_digest FROM events WHERE event_id=?", @@ -1291,26 +1503,46 @@ def audit(self) -> dict[str, int]: "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", ("resale_cancel:" + listing_id,), ).fetchall() - _require(cancelled == ("resale_cancel", _digest([listing_id])) - and cancelled_postings == [(hold, -credits), (seller_account, credits)] - and transfer is None and void is None, "cancelled resale mismatch") + _require( + cancelled == ("resale_cancel", _digest([listing_id])) + and cancelled_postings == [(hold, -credits), (seller_account, credits)] + and transfer is None + and void is None, + "cancelled resale mismatch", + ) elif status == "ordered": - _require(not captures and capture_id is None and reversal_id is None - and transfer is None and void is None - and all(row[3] == 0 for row in rows), "ordered resale mismatch") + _require( + not captures + and capture_id is None + and reversal_id is None + and transfer is None + and void is None + and all(row[3] == 0 for row in rows), + "ordered resale mismatch", + ) elif status == "sold": - _require(capture_id in captures and not reversals and reversal_id is None - and transfer == ("resale_transfer", _digest([ - listing_id, seller_id, buyer_id, processor_ref, - credits, price, fee, capture_id - ])) and transfer_postings == expected_transfer - and void is None and all(row[3] == 1 for row in rows), - "sold resale mismatch") + _require( + capture_id in captures + and not reversals + and reversal_id is None + and transfer + == ( + "resale_transfer", + _digest( + [listing_id, seller_id, buyer_id, processor_ref, credits, price, fee, capture_id] + ), + ) + and transfer_postings == expected_transfer + and void is None + and all(row[3] == 1 for row in rows), + "sold resale mismatch", + ) else: - _require(capture_id in captures and reversal_id in reversals - and all(row[3] == 1 for row in rows), "reversed resale mismatch") - _require((void is not None) != (transfer is not None), - "reversed resale path mismatch") + _require( + capture_id in captures and reversal_id in reversals and all(row[3] == 1 for row in rows), + "reversed resale mismatch", + ) + _require((void is not None) != (transfer is not None), "reversed resale path mismatch") if void is not None: void_postings = self._db.execute( "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", @@ -1334,25 +1566,43 @@ def audit(self) -> dict[str, int]: "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", ("resale_void_reversal:" + listing_id,), ).fetchall() - _require(release is None and void == ("resale_void", _digest([ - listing_id, processor_ref, capture_id, reversal_id - ])) and void_postings == [(hold, -credits), (seller_account, credits)], - "void resale mismatch") - _require(cash_capture == ("resale_void_capture", _digest([ - listing_id, processor_ref, capture_id, price - ])) and cash_capture_postings == [ - ("external_funding", -price), (cash_hold, price) - ] and cash_reversal == ("resale_void_reversal", _digest([ - listing_id, processor_ref, reversal_id, price - ])) and cash_reversal_postings == [ - (cash_hold, -price), ("external_funding", price) - ], "void resale cash journal mismatch") + _require( + release is None + and void + == ("resale_void", _digest([listing_id, processor_ref, capture_id, reversal_id])) + and void_postings == [(hold, -credits), (seller_account, credits)], + "void resale mismatch", + ) + _require( + cash_capture + == ("resale_void_capture", _digest([listing_id, processor_ref, capture_id, price])) + and cash_capture_postings == [("external_funding", -price), (cash_hold, price)] + and cash_reversal + == ("resale_void_reversal", _digest([listing_id, processor_ref, reversal_id, price])) + and cash_reversal_postings == [(cash_hold, -price), ("external_funding", price)], + "void resale cash journal mismatch", + ) else: - _require(transfer == ("resale_transfer", _digest([ - listing_id, seller_id, buyer_id, processor_ref, - credits, price, fee, capture_id - ])) and transfer_postings == expected_transfer, - "reversed transfer mismatch") + _require( + transfer + == ( + "resale_transfer", + _digest( + [ + listing_id, + seller_id, + buyer_id, + processor_ref, + credits, + price, + fee, + capture_id, + ] + ), + ) + and transfer_postings == expected_transfer, + "reversed transfer mismatch", + ) credit_reversal = self._db.execute( "SELECT kind,payload_digest FROM events WHERE event_id=?", ("resale_credit_reversal:" + listing_id,), @@ -1363,12 +1613,21 @@ def audit(self) -> dict[str, int]: ).fetchall() recovered = -credit_postings[0][1] if len(credit_postings) == 3 else -1 credit_loss = credits - recovered - _require(0 <= recovered <= credits and credit_postings == [ - (buyer_account, -recovered), ("operator_loss", -credit_loss), - (seller_account, credits) - ] and credit_reversal == ("resale_credit_reversal", _digest([ - listing_id, recovered, credit_loss, reversal_id - ])), "resale credit reversal mismatch") + _require( + 0 <= recovered <= credits + and credit_postings + == [ + (buyer_account, -recovered), + ("operator_loss", -credit_loss), + (seller_account, credits), + ] + and credit_reversal + == ( + "resale_credit_reversal", + _digest([listing_id, recovered, credit_loss, reversal_id]), + ), + "resale credit reversal mismatch", + ) cash_reversal = self._db.execute( "SELECT kind,payload_digest FROM events WHERE event_id=?", ("resale_cash_reversal:" + listing_id,), @@ -1380,82 +1639,102 @@ def audit(self) -> dict[str, int]: cash_recovered = -cash_postings[0][1] if len(cash_postings) == 4 else -1 net = price - fee cash_loss = net - cash_recovered - recovery_source = ( - "provider_eligible:" + seller_id if release is not None else payable + recovery_source = "provider_eligible:" + seller_id if release is not None else payable + _require( + 0 <= cash_recovered <= net + and cash_postings + == [ + (recovery_source, -cash_recovered), + ("fees", -fee), + ("operator_loss", -cash_loss), + ("external_funding", price), + ] + and cash_reversal + == ( + "resale_cash_reversal", + _digest([listing_id, cash_recovered, cash_loss, reversal_id]), + ), + "resale cash reversal mismatch", ) - _require(0 <= cash_recovered <= net and cash_postings == [ - (recovery_source, -cash_recovered), ("fees", -fee), - ("operator_loss", -cash_loss), ("external_funding", price) - ] and cash_reversal == ("resale_cash_reversal", _digest([ - listing_id, cash_recovered, cash_loss, reversal_id - ])), "resale cash reversal mismatch") if release is not None: release_id, risk_decision_id = release - _require(status in {"sold", "reversed"} and transfer is not None, - "resale release without transfer") - _require(self._db.execute( - "SELECT kind,payload_digest FROM events WHERE event_id=?", - ("resale_release:" + listing_id,), - ).fetchone() == ("resale_release", _digest([ - release_id, listing_id, risk_decision_id - ])), "resale release journal mismatch") + _require( + status in {"sold", "reversed"} and transfer is not None, "resale release without transfer" + ) + _require( + self._db.execute( + "SELECT kind,payload_digest FROM events WHERE event_id=?", + ("resale_release:" + listing_id,), + ).fetchone() + == ("resale_release", _digest([release_id, listing_id, risk_decision_id])), + "resale release journal mismatch", + ) release_postings = self._db.execute( "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", ("resale_release:" + listing_id,), ).fetchall() - _require(release_postings == [ - (payable, -(price - fee)), ("provider_eligible:" + seller_id, price - fee) - ], "resale release postings mismatch") + _require( + release_postings + == [(payable, -(price - fee)), ("provider_eligible:" + seller_id, price - fee)], + "resale release postings mismatch", + ) for payout_id, provider_id, amount, external_ref, status, outcome_event_id in self._db.execute( "SELECT payout_id,provider_id,amount,external_ref,status,outcome_event_id FROM payouts" ): - _require(self._balance("payout_hold:" + payout_id) - == (amount if status in {"reserved", "unknown"} else 0), - "payout hold mismatch") + _require( + self._balance("payout_hold:" + payout_id) + == (amount if status in {"reserved", "unknown"} else 0), + "payout hold mismatch", + ) reserve = self._db.execute( - "SELECT kind,payload_digest FROM events WHERE event_id=?", - ("payout_hold:" + payout_id,) + "SELECT kind,payload_digest FROM events WHERE event_id=?", ("payout_hold:" + payout_id,) ).fetchone() reserve_postings = self._db.execute( "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", - ("payout_hold:" + payout_id,) + ("payout_hold:" + payout_id,), ).fetchall() _require( reserve == ("payout_reserve", _digest([payout_id, provider_id, amount, external_ref])) - and reserve_postings == [ + and reserve_postings + == [ ("provider_eligible:" + provider_id, -amount), ("payout_hold:" + payout_id, amount), ], "payout reserve journal mismatch", ) unknown_event = self._db.execute( - "SELECT kind,payload_digest FROM events WHERE event_id=?", - ("payout_unknown:" + payout_id,) + "SELECT kind,payload_digest FROM events WHERE event_id=?", ("payout_unknown:" + payout_id,) ).fetchone() result = self._db.execute( "SELECT kind,payload_digest FROM events WHERE event_id=?", ("payout_result:" + payout_id,) ).fetchone() if status == "reserved": - _require(unknown_event is None and result is None and outcome_event_id is None, - "reserved payout mismatch") + _require( + unknown_event is None and result is None and outcome_event_id is None, + "reserved payout mismatch", + ) elif status == "unknown": - _require(unknown_event == ("payout_unknown", _digest([payout_id])) - and result is None and outcome_event_id is None, - "unknown payout mismatch") + _require( + unknown_event == ("payout_unknown", _digest([payout_id])) + and result is None + and outcome_event_id is None, + "unknown payout mismatch", + ) else: - _require(unknown_event is None or unknown_event == - ("payout_unknown", _digest([payout_id])), "payout uncertainty journal mismatch") + _require( + unknown_event is None or unknown_event == ("payout_unknown", _digest([payout_id])), + "payout uncertainty journal mismatch", + ) result_postings = self._db.execute( "SELECT account_id,delta FROM postings WHERE event_id=? ORDER BY ordinal", - ("payout_result:" + payout_id,) + ("payout_result:" + payout_id,), ).fetchall() destination = "external_funding" if status == "paid" else "provider_eligible:" + provider_id - _require(result == ("payout_" + status, - _digest([payout_id, outcome_event_id, status])) - and result_postings == [ - ("payout_hold:" + payout_id, -amount), (destination, amount) - ], - "terminal payout mismatch") + _require( + result == ("payout_" + status, _digest([payout_id, outcome_event_id, status])) + and result_postings == [("payout_hold:" + payout_id, -amount), (destination, amount)], + "terminal payout mismatch", + ) _require(self._balance("operator_loss") <= 0, "invalid loss balance") result = { "events": self._db.execute("SELECT COUNT(*) FROM events").fetchone()[0], diff --git a/src/drift/managed_llama_cpp.py b/src/drift/managed_llama_cpp.py index 03d03793a..1183b0e47 100644 --- a/src/drift/managed_llama_cpp.py +++ b/src/drift/managed_llama_cpp.py @@ -50,11 +50,13 @@ def __post_init__(self) -> None: or endpoint.username is not None or endpoint.password is not None or endpoint.path not in {"", "/"} - or endpoint.query or endpoint.fragment + or endpoint.query + or endpoint.fragment ): raise ValueError("managed llama.cpp endpoint must be loopback HTTP") if ( - type(self.api_key) is not str or not self.api_key + type(self.api_key) is not str + or not self.api_key or any(ord(character) < 33 or ord(character) > 126 for character in self.api_key) ): raise ValueError("invalid managed llama.cpp API key") @@ -65,9 +67,8 @@ def __post_init__(self) -> None: or len(set(self.device_ids)) != len(self.device_ids) ): raise ValueError("invalid llama.cpp GPU selection") - if ( - self.split_mode not in {"none", "layer", "tensor"} - or (self.split_mode == "none") != (len(self.device_ids) == 1) + if self.split_mode not in {"none", "layer", "tensor"} or (self.split_mode == "none") != ( + len(self.device_ids) == 1 ): raise ValueError("invalid llama.cpp split mode or GPU count") if type(self.max_model_len) is not int or not 1 <= self.max_model_len <= 2048: diff --git a/src/drift/managed_llama_cpp_process.py b/src/drift/managed_llama_cpp_process.py index 149d7cc3b..3fac25105 100644 --- a/src/drift/managed_llama_cpp_process.py +++ b/src/drift/managed_llama_cpp_process.py @@ -66,8 +66,11 @@ def __init__( self.model_file = Path(model_file) for path, digest in ((self.executable, executable_sha256), (self.model_file, model_sha256)): if ( - not path.is_absolute() or not path.is_file() or type(digest) is not str - or len(digest) != 64 or any(c not in "0123456789abcdef" for c in digest) + not path.is_absolute() + or not path.is_file() + or type(digest) is not str + or len(digest) != 64 + or any(c not in "0123456789abcdef" for c in digest) ): raise ValueError("managed llama.cpp artifact requires an absolute file and SHA-256") self.executable_sha256 = executable_sha256 @@ -89,10 +92,7 @@ def running(self) -> bool: @property def ready(self) -> bool: - return ( - self._probe_accepted and self.running - and self._process.owns_tcp_listener(self._host, self._port) - ) + return self._probe_accepted and self.running and self._process.owns_tcp_listener(self._host, self._port) def start(self) -> None: if self.pid is not None: @@ -101,8 +101,11 @@ def start(self) -> None: _check_digest(self.executable, self.executable_sha256) _check_digest(self.model_file, self.model_sha256) version = subprocess.run( - [str(self.executable), "--version"], capture_output=True, text=True, - timeout=10, check=False, + [str(self.executable), "--version"], + capture_output=True, + text=True, + timeout=10, + check=False, ) if version.returncode or "build 11173, commit 84e76d8a2" not in version.stdout + version.stderr: # The hash is authoritative; version text also guards mismatched packaging. @@ -112,18 +115,39 @@ def start(self) -> None: key_file.write_text(self.binding.api_key + "\n", encoding="ascii") command = ( str(self.executable.resolve(strict=True)), - "--model", str(self.model_file.resolve(strict=True)), - "--alias", self.binding.served_model, - "--host", self._host, "--port", str(self._port), - "--api-key-file", str(key_file), "--no-ui", "--no-slots", - "--device", "CUDA0", "--split-mode", "none", "--gpu-layers", "all", - "--fit", "off", "--ctx-size", str(self.binding.max_model_len), - "--parallel", "1", "--flash-attn", "off", "--no-cache-prompt", + "--model", + str(self.model_file.resolve(strict=True)), + "--alias", + self.binding.served_model, + "--host", + self._host, + "--port", + str(self._port), + "--api-key-file", + str(key_file), + "--no-ui", + "--no-slots", + "--device", + "CUDA0", + "--split-mode", + "none", + "--gpu-layers", + "all", + "--fit", + "off", + "--ctx-size", + str(self.binding.max_model_len), + "--parallel", + "1", + "--flash-attn", + "off", + "--no-cache-prompt", ) environment = {key: value for key, value in os.environ.items() if not key.startswith("LLAMA_ARG_")} environment.update( CUDA_VISIBLE_DEVICES=str(self.binding.device_ids[0]), - HF_HUB_OFFLINE="1", TRANSFORMERS_OFFLINE="1", + HF_HUB_OFFLINE="1", + TRANSFORMERS_OFFLINE="1", ) try: self._process.start(command, environment, cwd=self.executable.parent) @@ -144,12 +168,16 @@ async def probe(self, *, seconds: float = 5.0) -> ManagedLlamaCppProbe: headers = {"Authorization": "Bearer " + self.binding.api_key} try: async with httpx.AsyncClient(trust_env=False, follow_redirects=False) as client: + async def fetch(path: str) -> dict: remaining = deadline - time.monotonic() if remaining <= 0: raise ManagedLlamaCppProcessError("llama.cpp probe deadline") async with client.stream( - "GET", self.binding.base_url + path, headers=headers, timeout=remaining, + "GET", + self.binding.base_url + path, + headers=headers, + timeout=remaining, ) as response: if response.status_code != 200: raise ManagedLlamaCppProcessError("llama.cpp probe rejected") @@ -172,12 +200,16 @@ async def fetch(path: str) -> dict: cards = models.get("data") settings = props.get("default_generation_settings") if ( - models.get("object") != "list" or type(cards) is not list or len(cards) != 1 - or type(cards[0]) is not dict or cards[0].get("id") != self.binding.served_model + models.get("object") != "list" + or type(cards) is not list + or len(cards) != 1 + or type(cards[0]) is not dict + or cards[0].get("id") != self.binding.served_model or props.get("build_info") != _BUILD_INFO or props.get("model_path") != str(self.model_file.resolve(strict=True)) or props.get("total_slots") != 1 - or type(settings) is not dict or settings.get("n_ctx") != self.binding.max_model_len + or type(settings) is not dict + or settings.get("n_ctx") != self.binding.max_model_len ): raise ManagedLlamaCppProcessError("llama.cpp route metadata mismatch") if not self.running or not self._process.owns_tcp_listener(self._host, self._port): @@ -189,14 +221,19 @@ async def fetch(path: str) -> dict: raise ManagedLlamaCppProcessError("llama.cpp probe unavailable") from exc self._probe_accepted = True return ManagedLlamaCppProbe( - self.binding.served_model, _BUILD_INFO, self.binding.max_model_len, time.monotonic(), + self.binding.served_model, + _BUILD_INFO, + self.binding.max_model_len, + time.monotonic(), ) def new_adapter(self) -> ManagedLlamaCppAdapter: if not self.ready: raise ManagedLlamaCppProcessError("llama.cpp process has not passed admission") return ManagedLlamaCppAdapter( - self.binding, on_quarantine=self.stop, before_dispatch=lambda: self.ready, + self.binding, + on_quarantine=self.stop, + before_dispatch=lambda: self.ready, ) def stop(self) -> None: diff --git a/src/drift/managed_vllm_glm53_w4a8_h100.py b/src/drift/managed_vllm_glm53_w4a8_h100.py index f8d95dfbd..7312de0d2 100644 --- a/src/drift/managed_vllm_glm53_w4a8_h100.py +++ b/src/drift/managed_vllm_glm53_w4a8_h100.py @@ -57,9 +57,13 @@ def build_glm53_w4a8_h100_launch_candidate( raise ValueError("invalid reported GPU") index, name, free = item if ( - type(index) is not int or not 0 <= index <= 255 - or type(name) is not str or "H100" not in name or len(name) > 128 - or type(free) is not int or not MINIMUM_PER_RANK_BYTES <= free <= 1 << 50 + type(index) is not int + or not 0 <= index <= 255 + or type(name) is not str + or "H100" not in name + or len(name) > 128 + or type(free) is not int + or not MINIMUM_PER_RANK_BYTES <= free <= 1 << 50 ): raise ValueError("H100 identity or free GPU memory preflight failed") indexes.append(index) @@ -76,7 +80,8 @@ def build_glm53_w4a8_h100_launch_candidate( or endpoint.username is not None or endpoint.password is not None or endpoint.path not in {"", "/"} - or endpoint.query or endpoint.fragment + or endpoint.query + or endpoint.fragment ): raise ValueError("managed endpoint must be explicit loopback HTTP") if type(api_key) is not str or not api_key or any(ord(ch) < 33 or ord(ch) > 126 for ch in api_key): @@ -87,15 +92,33 @@ def build_glm53_w4a8_h100_launch_candidate( if not path.is_absolute() or not path.is_dir(): raise ValueError("model directory must exist locally") argv = ( - "vllm", "serve", str(path.resolve(strict=True)), - "--served-model-name", ARTIFACT_ID, - "--host", endpoint.hostname, "--port", str(endpoint.port), - "--tensor-parallel-size", "8", "--pipeline-parallel-size", "1", - "--distributed-executor-backend", "mp", - "--enable-expert-parallel", "--kv-cache-dtype", "fp8_ds_mla", - "--gpu-memory-utilization", "0.90", "--max-model-len", str(max_model_len), - "--max-num-seqs", "1", "--trust-remote-code", - "--no-enable-log-requests", "--disable-uvicorn-access-log", + "vllm", + "serve", + str(path.resolve(strict=True)), + "--served-model-name", + ARTIFACT_ID, + "--host", + endpoint.hostname, + "--port", + str(endpoint.port), + "--tensor-parallel-size", + "8", + "--pipeline-parallel-size", + "1", + "--distributed-executor-backend", + "mp", + "--enable-expert-parallel", + "--kv-cache-dtype", + "fp8_ds_mla", + "--gpu-memory-utilization", + "0.90", + "--max-model-len", + str(max_model_len), + "--max-num-seqs", + "1", + "--trust-remote-code", + "--no-enable-log-requests", + "--disable-uvicorn-access-log", ) environment = { "CUDA_VISIBLE_DEVICES": ",".join(str(index) for index in indexes), diff --git a/src/drift/managed_vllm_process.py b/src/drift/managed_vllm_process.py index 884503a2d..6755fb3ed 100644 --- a/src/drift/managed_vllm_process.py +++ b/src/drift/managed_vllm_process.py @@ -77,12 +77,7 @@ def start(self, command: Sequence[str], environment: Mapping[str, str], *, cwd: or not Path(command[0]).is_file() or not isinstance(environment, Mapping) or any( - type(key) is not str - or not key - or "=" in key - or "\0" in key - or type(value) is not str - or "\0" in value + type(key) is not str or not key or "=" in key or "\0" in key or type(value) is not str or "\0" in value for key, value in environment.items() ) ): @@ -209,9 +204,7 @@ async def probe(self, *, seconds: float = 5.0): try: if not self._process.owns_tcp_listener(self._host, self._port): raise ManagedVllmProbeError("managed process does not own its loopback listener") - result = await probe_managed_vllm( - self.binding, expected_max_model_len=self.max_model_len, seconds=seconds - ) + result = await probe_managed_vllm(self.binding, expected_max_model_len=self.max_model_len, seconds=seconds) if not self.running or not self._process.owns_tcp_listener(self._host, self._port): raise ManagedVllmProbeError("managed backend listener exited during admission") except Exception: diff --git a/src/drift/shadow_credits.py b/src/drift/shadow_credits.py index 6d880191c..74dad910a 100644 --- a/src/drift/shadow_credits.py +++ b/src/drift/shadow_credits.py @@ -144,11 +144,18 @@ def _stored_receipt(row: tuple) -> WorkReceipt: except (TypeError, ValueError, json.JSONDecodeError) as exc: raise ShadowCreditError("invalid stored receipt") from exc _require( - (receipt.receipt_id, receipt.digest, receipt.request_id, receipt.provider_id, - receipt.stage_id, receipt.attempt_id, receipt.proposed_charge, receipt.input_units, - receipt.output_units) - == (receipt_id, digest, request_id, provider_id, stage_id, attempt_id, - charge, input_units, output_units), + ( + receipt.receipt_id, + receipt.digest, + receipt.request_id, + receipt.provider_id, + receipt.stage_id, + receipt.attempt_id, + receipt.proposed_charge, + receipt.input_units, + receipt.output_units, + ) + == (receipt_id, digest, request_id, provider_id, stage_id, attempt_id, charge, input_units, output_units), "receipt binding mismatch", ) return receipt @@ -504,7 +511,8 @@ def pending_receipts(self, *, limit: int = 100) -> tuple[WorkReceipt, ...]: rows = self._db.execute( "SELECT receipt_id, receipt_json, claim_digest, request_id, provider_id, " "stage_id, attempt_id, proposed_charge, input_units, output_units FROM receipts " - "WHERE status='pending' ORDER BY rowid LIMIT ?", (limit,) + "WHERE status='pending' ORDER BY rowid LIMIT ?", + (limit,), ).fetchall() return tuple(_stored_receipt(row) for row in rows) diff --git a/src/drift/shadow_metered_managed.py b/src/drift/shadow_metered_managed.py index d2a5595a3..48d9e18a5 100644 --- a/src/drift/shadow_metered_managed.py +++ b/src/drift/shadow_metered_managed.py @@ -95,8 +95,14 @@ async def stream(self, body: dict, *, chat: bool, context: RequestContext) -> As output_units=output_units, proposed_charge=input_units + output_units, evidence_sha256=_hash( - [context.request_id, context.attempt_id, self.bridge.identity.instance_id, - input_units, output_units, frame.get("finish_reason")] + [ + context.request_id, + context.attempt_id, + self.bridge.identity.instance_id, + input_units, + output_units, + frame.get("finish_reason"), + ] ), ) self.ledger.submit_receipt(receipt) diff --git a/src/drift/simulated_paid_text.py b/src/drift/simulated_paid_text.py index 80cf9005a..9cb6d9e25 100644 --- a/src/drift/simulated_paid_text.py +++ b/src/drift/simulated_paid_text.py @@ -91,8 +91,11 @@ async def stream(self, body: dict, *, chat: bool, context: RequestContext) -> As output_units = usage.get("completion_tokens") total_units = usage.get("total_tokens") if ( - type(input_units) is not int or type(output_units) is not int - or type(total_units) is not int or input_units < 0 or output_units < 0 + type(input_units) is not int + or type(output_units) is not int + or type(total_units) is not int + or input_units < 0 + or output_units < 0 or total_units != input_units + output_units ): raise ValueError("invalid simulated usage") @@ -100,13 +103,23 @@ async def stream(self, body: dict, *, chat: bool, context: RequestContext) -> As if charge <= 0: raise ValueError("zero priced simulated completion") fee = charge * quote.fee_bps // 10_000 - receipt = hashlib.sha256(json.dumps( - [quote.digest, usage, frame.get("finish_reason"), output_hash.hexdigest()], - sort_keys=True, separators=(",", ":"), ensure_ascii=True, - ).encode("ascii")).hexdigest() + receipt = hashlib.sha256( + json.dumps( + [quote.digest, usage, frame.get("finish_reason"), output_hash.hexdigest()], + sort_keys=True, + separators=(",", ":"), + ensure_ascii=True, + ).encode("ascii") + ).hexdigest() if not self.journal.settle_service( - quote.request_id, quote.provider_id, charge, fee, - "simdecision:" + quote.request_id, receipt, input_units, output_units, + quote.request_id, + quote.provider_id, + charge, + fee, + "simdecision:" + quote.request_id, + receipt, + input_units, + output_units, ): raise CommerceSimulationError("simulated settlement already applied") settled = True diff --git a/tests/test_gate16_catalog_drill.py b/tests/test_gate16_catalog_drill.py index 83a9a269b..06b1a57d2 100644 --- a/tests/test_gate16_catalog_drill.py +++ b/tests/test_gate16_catalog_drill.py @@ -46,6 +46,11 @@ def fetch(url, _maximum_bytes): cache.mkdir() (cache / "retained-sentinel").write_bytes(b"cache stays across withdrawal") local_config = next(item for item in document["models"] if item.get("execution") == "local") + remote_config = next(item for item in document["models"] if item.get("execution") == "distributed") + remote_manifest = Path(remote_config["manifest"]) + remote_cache = Path(remote_config["cache_dir"]) + remote_cache.mkdir(parents=True) + (remote_cache / "retained-weights").write_bytes(b"downloaded model") local_config.update(cache_dir=str(cache), local_device="cpu", request_timeout=17) document["contribution_policy"].update(sharing_enabled=False, max_vram="75%", max_processing_percent=50) path.write_text(json.dumps(document)) @@ -60,9 +65,12 @@ def fetch(url, _maximum_bytes): active[0] = SignedModelCatalog(1, withdrawal, ()).add_signature(key) assert installer.refresh().created withdrawn = NodeConfig.load(path) - # Older exact models remain manual choices by design. Withdrawal removes - # catalog approval and automatic routing, not operator-owned model history. - assert len(withdrawn.models) == 2 + # Withdrawal removes a retired catalog-managed entry from the config but + # leaves its stored manifest and cache intact for a signed forward restore. + assert len(withdrawn.models) == 1 + assert remote_manifest not in {model.manifest_path for model in withdrawn.models} + assert remote_manifest.is_file() + assert (remote_cache / "retained-weights").read_bytes() == b"downloaded model" withdrawn_local = next(model for model in withdrawn.models if model.execution == "local") assert withdrawn.auto_model_priority == (local.manifest_digest,) assert remote.manifest_digest not in {model.manifest_digest for model in load_configured_catalog(withdrawn).models} @@ -85,6 +93,7 @@ def fetch(url, _maximum_bytes): active[0] = SignedModelCatalog(1, restored, ()).add_signature(key) assert installer.refresh().created resumed = NodeConfig.load(path) + assert len(resumed.models) == 2 assert {model.manifest_digest for model in load_configured_catalog(resumed).models} == { local.manifest_digest, remote.manifest_digest, @@ -95,3 +104,5 @@ def fetch(url, _maximum_bytes): assert resumed_local.request_timeout == 17 assert resumed.contribution_policy == retained_policy assert (cache / "retained-sentinel").read_bytes() == b"cache stays across withdrawal" + assert remote_manifest.is_file() + assert (remote_cache / "retained-weights").read_bytes() == b"downloaded model" diff --git a/tests/test_linux_anchor_resources_native.py b/tests/test_linux_anchor_resources_native.py index f0cd687bf..e26221044 100644 --- a/tests/test_linux_anchor_resources_native.py +++ b/tests/test_linux_anchor_resources_native.py @@ -7,8 +7,7 @@ from test_linux_anchor_native import running # noqa: F401 from test_linux_anchor_state_native import journal # noqa: F401 -from drift.node import linux_anchor_resources as resources -from drift.node import linux_anchor_state as state +from drift.node import linux_anchor_resources as resources, linux_anchor_state as state from drift.node.resource_recovery import RecoverableStateError from drift.node.resource_reservations import ResourceReservationManager diff --git a/tests/test_linux_cgroup_recovery.py b/tests/test_linux_cgroup_recovery.py index f609c1da2..50713bae5 100644 --- a/tests/test_linux_cgroup_recovery.py +++ b/tests/test_linux_cgroup_recovery.py @@ -15,8 +15,7 @@ import pytest -from drift.node import linux_cgroup_recovery as cgroups -from drift.node import resource_recovery as recovery +from drift.node import linux_cgroup_recovery as cgroups, resource_recovery as recovery DIGEST = "sha256:" + "a" * 64 HOST = "sha256:" + "b" * 64 diff --git a/tests/test_paged_cache_admission.py b/tests/test_paged_cache_admission.py index be1cd43f3..731c5ff13 100644 --- a/tests/test_paged_cache_admission.py +++ b/tests/test_paged_cache_admission.py @@ -10,12 +10,11 @@ import contextlib import json import math +import unittest from pathlib import Path from types import SimpleNamespace -import unittest from unittest import mock - ROOT = Path(__file__).resolve().parents[1] @@ -52,18 +51,34 @@ def _load_methods(): nodes.append(node) elif isinstance(node, ast.ClassDef) and node.name in {"MemoryCache", "PagedKVPool"}: methods = {"allocate_paged_slots", "_wait_for_free_pages", "register_slot"} - nodes.append(ast.ClassDef( - name=node.name, bases=[], keywords=[], decorator_list=[], - body=[item for item in node.body if getattr(item, "name", None) in methods], - )) + nodes.append( + ast.ClassDef( + name=node.name, + bases=[], + keywords=[], + decorator_list=[], + body=[item for item in node.body if getattr(item, "name", None) in methods], + ) + ) handler_tree = ast.parse((ROOT / "src/drift/server/handler.py").read_text(encoding="utf-8")) - handler = next(node for node in handler_tree.body if isinstance(node, ast.ClassDef) - and node.name == "TransformerConnectionHandler") - nodes.append(ast.ClassDef( - name=handler.name, bases=[], keywords=[], decorator_list=[], - body=[item for item in handler.body - if getattr(item, "name", None) in {"rpc_inference", "_inference_batch_size"}], - )) + handler = next( + node + for node in handler_tree.body + if isinstance(node, ast.ClassDef) and node.name == "TransformerConnectionHandler" + ) + nodes.append( + ast.ClassDef( + name=handler.name, + bases=[], + keywords=[], + decorator_list=[], + body=[ + item + for item in handler.body + if getattr(item, "name", None) in {"rpc_inference", "_inference_batch_size"} + ], + ) + ) module = ast.fix_missing_locations(ast.Module(body=nodes, type_ignores=[])) exec(compile(module, "", "exec"), namespace) return namespace @@ -81,12 +96,23 @@ def _load_real_pool_and_paged_backend(torch): tree = ast.parse((ROOT / "src/drift/server" / filename).read_text(encoding="utf-8")) node = next(item for item in tree.body if isinstance(item, ast.ClassDef) and item.name == class_name) if methods is not None: - node = ast.ClassDef(name=node.name, bases=[], keywords=[], decorator_list=[], - body=[item for item in node.body if getattr(item, "name", None) in methods]) + node = ast.ClassDef( + name=node.name, + bases=[], + keywords=[], + decorator_list=[], + body=[item for item in node.body if getattr(item, "name", None) in methods], + ) nodes.append(node) namespace = dict(SOURCE, torch=torch, is_dummy=lambda tensor: tensor.numel() == 0) - exec(compile(ast.fix_missing_locations(ast.Module(body=nodes, type_ignores=[])), - "", "exec"), namespace) + exec( + compile( + ast.fix_missing_locations(ast.Module(body=nodes, type_ignores=[])), + "", + "exec", + ), + namespace, + ) return namespace @@ -102,8 +128,13 @@ def setUpClass(cls): def make_pool(self, *, pages=8, batch=2): pool = self.source["PagedKVPool"]( - num_pages=pages, page_size=1, num_kv_heads=1, k_head_dim=1, v_head_dim=1, - dtype=self.torch.float32, device=self.torch.device("cpu"), + num_pages=pages, + page_size=1, + num_kv_heads=1, + k_head_dim=1, + v_head_dim=1, + dtype=self.torch.float32, + device=self.torch.device("cpu"), ) pool.register_slot(0, batch) values = self.torch.arange(batch, dtype=self.torch.float32).reshape(batch, 1, 1) @@ -111,8 +142,11 @@ def make_pool(self, *, pages=8, batch=2): return pool def state(self, pool): - return ([list(row) for row in pool._block_tables[0]], list(pool._free_pages), - tuple(tensor.clone() for tensor in pool.gather(0, 1))) + return ( + [list(row) for row in pool._block_tables[0]], + list(pool._free_pages), + tuple(tensor.clone() for tensor in pool.gather(0, 1)), + ) def assert_state_equal(self, pool, before): table, free, kvs = before @@ -132,10 +166,19 @@ def test_original_oversized_beam_repro_rejects_without_leaking(self): def test_invalid_beam_rank_dtype_count_and_indices_are_atomic(self): torch = self.torch - for ids in (torch.tensor(0), torch.tensor([[0, 1]]), torch.tensor([0., 1.]), - torch.tensor([False, True]), torch.tensor([0, 1], dtype=torch.int32), - torch.tensor([], dtype=torch.int64), torch.tensor([0]), torch.tensor([0, 1, 1]), - torch.tensor([-1, 0]), torch.tensor([0, 2]), torch.tensor([0, 2**62])): + for ids in ( + torch.tensor(0), + torch.tensor([[0, 1]]), + torch.tensor([0.0, 1.0]), + torch.tensor([False, True]), + torch.tensor([0, 1], dtype=torch.int32), + torch.tensor([], dtype=torch.int64), + torch.tensor([0]), + torch.tensor([0, 1, 1]), + torch.tensor([-1, 0]), + torch.tensor([0, 2]), + torch.tensor([0, 2**62]), + ): with self.subTest(shape=tuple(ids.shape), dtype=str(ids.dtype), ids=ids.tolist()): pool = self.make_pool() before = self.state(pool) @@ -209,14 +252,19 @@ def backend_step(self, pool, hidden_batch, ids): backend._estimate_max_chunk_length = lambda *args: 1 backend._forward_chunked = lambda hidden, past, chunk: (hidden, past) return backend._paged_inference_step( - self.torch.zeros(hidden_batch, 1, 1), ids, + self.torch.zeros(hidden_batch, 1, 1), + ids, SimpleNamespace(cache_handles=(0,), prefix_length=1), ) def test_backend_rejects_batch_mismatch_and_invalid_dummy_before_cache_access(self): torch = self.torch - for batch, ids in ((1, torch.tensor([0, 1])), (1, torch.empty(0, dtype=torch.int64)), - (2, torch.empty((1, 0), dtype=torch.int64)), (2, torch.empty(0))): + for batch, ids in ( + (1, torch.tensor([0, 1])), + (1, torch.empty(0, dtype=torch.int64)), + (2, torch.empty((1, 0), dtype=torch.int64)), + (2, torch.empty(0)), + ): with self.subTest(batch=batch, shape=tuple(ids.shape), dtype=str(ids.dtype)): pool = self.make_pool() before = self.state(pool) @@ -226,8 +274,7 @@ def test_backend_rejects_batch_mismatch_and_invalid_dummy_before_cache_access(se self.assert_state_equal(pool, before) def test_backend_preserves_valid_dummy_permutation_and_duplicate_steps(self): - for ids in (self.torch.empty(0, dtype=self.torch.int64), self.torch.tensor([1, 0]), - self.torch.tensor([1, 1])): + for ids in (self.torch.empty(0, dtype=self.torch.int64), self.torch.tensor([1, 0]), self.torch.tensor([1, 1])): with self.subTest(ids=ids.tolist()): pool = self.make_pool() before = self.state(pool) @@ -333,8 +380,13 @@ def test_real_cpu_page_pool_roundtrip_when_torch_available(self): namespace = dict(SOURCE, torch=torch) exec(compile(module, "", "exec"), namespace) pool = namespace["PagedKVPool"]( - num_pages=12, page_size=2, num_kv_heads=1, k_head_dim=2, v_head_dim=2, - dtype=torch.float32, device=torch.device("cpu"), + num_pages=12, + page_size=2, + num_kv_heads=1, + k_head_dim=2, + v_head_dim=2, + dtype=torch.float32, + device=torch.device("cpu"), ) with self.assertRaises(ValueError): pool.register_slot(0, 10000) @@ -354,8 +406,19 @@ def test_real_cpu_page_pool_roundtrip_when_torch_available(self): self.assertEqual(pool.num_free_pages, 12) async def test_forged_rpc_shapes_reject_before_any_cache_allocation(self): - for shape in ((), (1,), (1, 2), (1, 2, 4, 1), (0, 1, 4), (-1, 1, 4), - (10000, 0, 4), (1, -1, 4), (1, 9, 4), (1, 1, 5), (3, 2, 4)): + for shape in ( + (), + (1,), + (1, 2), + (1, 2, 4, 1), + (0, 1, 4), + (-1, 1, 4), + (10000, 0, 4), + (1, -1, 4), + (1, 9, 4), + (1, 1, 5), + (3, 2, 4), + ): with self.subTest(shape=shape): events = await self.drive_request(shape, rejected=True) self.assertEqual(events, ["acquire", "release"]) @@ -387,10 +450,13 @@ def acquire(peer): handler._check_uids = lambda uid: (uid,) handler._log_request = lambda *args, **kwargs: None handler._check_manifest_digest = lambda metadata: None - handler.module_backends = {"model.0": SimpleNamespace( - config=SimpleNamespace(hidden_size=4), inference_pool=SimpleNamespace(max_batch_size=max_tokens), - memory_cache=SimpleNamespace(paged=True), - )} + handler.module_backends = { + "model.0": SimpleNamespace( + config=SimpleNamespace(hidden_size=4), + inference_pool=SimpleNamespace(max_batch_size=max_tokens), + memory_cache=SimpleNamespace(paged=True), + ) + } handler._get_active_adapter = lambda metadata: "" handler._iterate_inference_steps = lambda *args: None handler._prioritizer = handler.quant_type = None @@ -413,7 +479,8 @@ async def no_compute(**kwargs): async def requests(): yield SimpleNamespace( - uid="model.0", metadata=json.dumps({"max_length": 8}), + uid="model.0", + metadata=json.dumps({"max_length": 8}), tensors=[] if shape is None else [SimpleNamespace(size=shape)], ) diff --git a/tests/test_qualification_cost_guard.py b/tests/test_qualification_cost_guard.py index 0d39ab4dd..24991cc84 100644 --- a/tests/test_qualification_cost_guard.py +++ b/tests/test_qualification_cost_guard.py @@ -971,7 +971,15 @@ def test_provider_and_workload_must_match(): _authorization(workload=guard.FLY_DISCOVERY_SEED_WORKLOAD) -def test_cli_writes_bounded_plan_without_provider_calls(tmp_path, capsys): +def test_cli_writes_bounded_plan_without_provider_calls(tmp_path, capsys, monkeypatch): + class HistoricalDate(date): + @classmethod + def today(cls): + return cls(2026, 8, 26) + + # Exercise the historical CLI success fixture without changing the live + # GCP price-expiry guard, which has a separate stale-price regression test. + monkeypatch.setattr(guard, "date", HistoricalDate) ledger = tmp_path / "readiness.md" ledger.write_text( _ledger("| No new paid run recorded | — | — | USD 0 | USD 0 | — | READY |"), diff --git a/tests/test_text_generation.py b/tests/test_text_generation.py index 1d3ebbe22..79a80d62d 100644 --- a/tests/test_text_generation.py +++ b/tests/test_text_generation.py @@ -2,22 +2,23 @@ import asyncio import contextlib -import threading import queue +import threading from types import SimpleNamespace from unittest.mock import patch import torch +from test_qwen3_5_block import _tiny_config, _wrapped_blocks from torch import nn +from drift.api.server import _RequestCancelled from drift.models.qwen3_5.model import DistributedQwen3_5ForCausalLM from drift.server.text_generation import TextGenerationEngine -from drift.api.server import _RequestCancelled -from test_qwen3_5_block import _tiny_config, _wrapped_blocks def test_chunked_generation_preserves_remote_cache_and_full_prompt(): from transformers.models.qwen3_5 import Qwen3_5ForCausalLM + from drift.models.qwen3_5.cache import Qwen3_5HybridCache torch.set_num_threads(1)