byoc: support offchain mode without an Eth keystore#3906
Open
rickstaa wants to merge 1 commit into
Open
Conversation
In -network offchain mode the broadcaster's Sign() returns empty bytes (core/broadcaster.go:14) and the orchestrator's VerifySig() short-circuits to true (core/orchestrator.go:66) — both already offchain-aware. BYOC should inherit that behaviour but didn't because: - byoc/job_gateway.go's getJobSender always prefixed the encoded signature with "0x", producing the literal string "0x" for empty sigs. - byoc/job_orchestrator.go's verifyTokenCreds only stripped the prefix when len > 130, so "0x" passed through to hex.DecodeString and failed with "invalid byte: U+0078 'x'", aborting before VerifySig's offchain bypass could run. Fix: - encodeJobSig() returns "" for empty sigs, "0x" + hex otherwise. - verifyTokenCreds() unconditionally trims a "0x" prefix; an empty sig now decodes to empty bytes and VerifySig short-circuits to true offchain. Also fixes a missing format verb in the existing "Unable to hex-decode signature" log line. Tests cover both helpers plus the verifyTokenCreds round-trip with empty and "0x"-prefixed sigs. After this change a BYOC stack can run with just -network offchain on both gateway and orchestrator — no -ethPassword, no auto-generated keystore, no -ethUrl. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 tasks
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3906 +/- ##
===================================================
+ Coverage 32.87450% 32.92286% +0.04836%
===================================================
Files 171 171
Lines 42063 42065 +2
===================================================
+ Hits 13828 13849 +21
+ Misses 27194 27173 -21
- Partials 1041 1043 +2
... and 4 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
This was referenced Apr 29, 2026
rickstaa
added a commit
to livepeer/livepeer-python-gateway
that referenced
this pull request
May 8, 2026
The TODO referenced switching examples to bare `-network offchain` once livepeer/go-livepeer#3906 lands. Current setup (on-chain Arbitrum + pricePerUnit 0) works correctly today; the only cost is some 429 noise from the public Arbitrum RPC. Tracked in the SDK epic (#8); no need to keep the comment in every compose. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #3905. BYOC currently requires
-ethPassword=...on both gateway and orchestrator even in-network offchainmode — a throwaway keystore exists only to satisfy a vestigial signing requirement. After this PR, BYOC inherits transcoding's existing offchain story: no keystore, no-ethUrl, just-network offchain.Root cause (recap from #3905)
Both halves of the signing flow are already offchain-aware:
core/broadcaster.go:14—Sign()returns[]byte{}, nilwhennode.Eth == nil.core/orchestrator.go:66—VerifySig()returnstruewhennode.Eth == nil.BYOC's wrapper code prevented that bypass from being reached:
byoc/job_gateway.go—getJobSenderalways prefixed"0x", producing the literal string"0x"for empty sigs.byoc/job_orchestrator.go—verifyTokenCredsonly stripped"0x"whenlen(Sig) > 130, so the literal"0x"passed through tohex.DecodeStringand failed.Changes
byoc/job_gateway.go— extractedencodeJobSig()that returns""for empty sigs and"0x" + hexotherwise.byoc/job_orchestrator.go—verifyTokenCredsunconditionally trims a"0x"prefix viastrings.TrimPrefix. Empty sig now decodes to empty bytes,VerifySigshort-circuits totrueoffchain. Also fixed a missing format verb in the existingUnable to hex-decode signaturelog line.TestEncodeJobSig(helper),TestVerifyTokenCreds_OffchainEmptySig(round-trip),TestVerifyTokenCreds_StripsHexPrefix(regression for short prefixed sigs).Test plan
go test ./byoc/...passes (existing + new tests)go build ./byoc/...clean-network offchainon both nodes, no-ethPassword, no-ethUrl. Capability registers,/process/request/<suffix>round-trips through gateway → orchestrator → worker container. (Will validate in livepeer-python-gateway hello-world example once this lands.)Context
Surfaced while building a Pipeline SDK hello-world test against unmodified go-livepeer. The example currently uses
-ethPassword=secret-passwordas a workaround — once this lands, the compose drops the keystore flag entirely.🤖 Generated with Claude Code