fix(solana): keep video settlement blockhash fresh via proactive re-sign#22
Merged
VickyXAI merged 2 commits intoJul 8, 2026
Merged
Conversation
Slow / flaky-status video models (1080p bytedance/seedance-2.0) bounce the upstream status completed<->in_progress for minutes. The gateway settles only on a 'completed' poll, so a signature made earlier goes stale (Solana blockhash lifetime ~60-90s) before the settling poll lands — yielding a perpetual transaction_simulation_failed that the on-402 re-sign can't outrun (each re-signed blockhash re-expires during the next ~40s in_progress gap). Fix: during the async media poll loop, proactively re-sign the ORIGINAL challenge (same amount/pay_to, freshly-fetched blockhash) every MEDIA_RESIGN_FRESH_SECONDS (25s) so the settlement signature is always fresh whenever upstream flips to completed. Only the completed poll settles; in-progress polls ignore the header, so this never double-charges. Best-effort: a failed re-sign keeps the prior signature. Gated on max_resigns>0 (video only; image unaffected). Verified live on Solana mainnet: bytedance/seedance-2.0 at 1080p — the exact customer request that failed 2/2 before — now settles on the first completed poll with ZERO settlement-402s (tx 64fDCvbE…, $1.674918).
ea1d494 to
aabb9d5
Compare
…ign comment - Add sync+async tests asserting max_resigns==0 (image path) never proactively re-signs even with a 0s freshness window — every poll reuses the single submit-time signature, proving the video-only fix leaves the image flow untouched. - Reword the proactive re-sign comment (sync + async): 'async media path' -> 'poll-based media path' to avoid confusion with the asyncio client.
VickyXAI
pushed a commit
that referenced
this pull request
Jul 8, 2026
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.
Problem
Customer hit
transaction_simulation_failed(402) callingbytedance/seedance-2.0at 1080p through the sidecar. Reproduced 2/2 with the released SDK (1.5.0).Root cause (traced): the gateway settles the x402 payment only on a poll where the upstream status is
completed. Slow / flaky-status video models (1080p Seedance Pro) bounce the upstream statuscompleted <-> in_progressfor minutes. The payment transaction is built + signed client-side with a Solanarecent_blockhash(lifetime ~60-90s). By the time a settlingcompletedpoll lands, the signature is stale →transaction_simulation_failed. The existing on-402 re-sign can't outrun it: each re-signed blockhash re-expires during the next ~40sin_progressgap, andMEDIA_POLL_MAX_RESIGNSexhausts.(Durable nonce would be the protocol-level cure, but the blockhash is set inside the third-party
x402[svm]client — that's a client+facilitator+library change, out of scope here.)Fix
During the async media poll loop, proactively re-sign the ORIGINAL challenge (identical amount/pay_to, freshly-fetched blockhash) every
MEDIA_RESIGN_FRESH_SECONDS(25s), so the settlement signature is always fresh whenever upstream flips tocompleted.max_resigns > 0→ video only; image path untouched.completedpoll settles;in_progresspolls ignore the header → never double-charges.SolanaLLMClientandAsyncSolanaLLMClient.Validation
Live on Solana mainnet, the exact customer request (
bytedance/seedance-2.0, 1080p, 5s, 16:9):completedpoll, 0 settlement-402s, real mp4 delivered, on-chain tx64fDCvbE…, $1.674918 settled once.Regression: 114 passed (solana/image/cache/video), black clean.