diff --git a/src/livepeer_gateway/live_runner.py b/src/livepeer_gateway/live_runner.py index 2c53543..b965a3e 100644 --- a/src/livepeer_gateway/live_runner.py +++ b/src/livepeer_gateway/live_runner.py @@ -21,6 +21,7 @@ GetPaymentResponse, LivePaymentSession, _freeze_headers, + _payment_type_for_signer, get_signer_info, ) @@ -737,10 +738,19 @@ async def _get_runner_payment( signer_url: str, signer_headers: Optional[dict[str, str]], ) -> tuple[LivePaymentSession, GetPaymentResponse]: + # Scope/LV2V is a live-video job → always "lv2v". Every other runner (single-shot + # fal/tool caps) pays via the per-signer dual-path: legacy Daydream → "lv2v", + # modern signers → "byoc". The old hardcoded "live" was rejected by the Daydream + # signer ("invalid job type"), breaking LR payment on the default signer. + payment_type = ( + "lv2v" + if runner is not None and runner.app == "live-video-to-video/scope" + else _payment_type_for_signer(signer_url) + ) session = LivePaymentSession( signer_url=signer_url, signer_headers=signer_headers, - type="lv2v" if runner is not None and runner.app == "live-video-to-video/scope" else "live", + type=payment_type, payment_params=challenge.payment_params, manifest_id=challenge.manifest_id, orchestrator_url=challenge.orchestrator_url, diff --git a/src/livepeer_gateway/remote_signer.py b/src/livepeer_gateway/remote_signer.py index fc94463..a90575a 100644 --- a/src/livepeer_gateway/remote_signer.py +++ b/src/livepeer_gateway/remote_signer.py @@ -8,8 +8,9 @@ import ssl from dataclasses import dataclass from functools import lru_cache -from typing import Any, Optional +from typing import Any, Literal, Optional from urllib.error import HTTPError, URLError +from urllib.parse import urlparse from urllib.request import Request, urlopen import aiohttp @@ -19,6 +20,21 @@ from .errors import LivepeerGatewayError, PaymentError, SignerRefreshRequired _LOG = logging.getLogger(__name__) +_LEGACY_DAYDREAM_SIGNER_HOST = "signer.daydream.live" + + +def _payment_type_for_signer(signer_url: str) -> Literal["byoc", "lv2v"]: + """Select the payment payload shape for the target signer. + + Legacy Daydream signer (signer.daydream.live) accepts only type:"lv2v"; + modern signers (pymthouse DMZ, …) accept type:"byoc". Shared by the BYOC and + Live Runner payment paths so both speak the dialect their signer understands. + """ + hostname = (urlparse(signer_url).hostname or "").lower() + if hostname == _LEGACY_DAYDREAM_SIGNER_HOST: + return "lv2v" + return "byoc" + @dataclass(frozen=True) class GetPaymentResponse: payment: str