Skip to content

fix(broadcast): survive the Credible RPC alignment window - #124

Draft
lean-apple wants to merge 4 commits into
mainfrom
fix/credible-rpc-alignment-window
Draft

fix(broadcast): survive the Credible RPC alignment window#124
lean-apple wants to merge 4 commits into
mainfrom
fix/credible-rpc-alignment-window

Conversation

@lean-apple

@lean-apple lean-apple commented Aug 10, 2026

Copy link
Copy Markdown
Member

Summary

Credible RPC can briefly return assertions are unavailable while its assertion state catches up with the chain. This PR makes PCL wait through that window without risking a duplicate transaction.

What changed

  • PCL fills and signs the transaction once, then reuses the exact same bytes for every retry.
  • Before retrying, it checks whether the transaction hash is already known. If it is, PCL stops resubmitting and waits for the receipt.
  • Transport failures after submission are treated as uncertain and reconciled using the signed transaction hash.
  • Gas-estimation failures are retried before anything is signed, while assertion rejections remain terminal.
  • Errors distinguish between transactions that were never submitted and transactions that may already be in flight.
  • Receipt polling respects the configured transaction timeout, including slow RPC calls and long polling intervals.

Verification

Mocked RPC tests cover failures before and after forwarding, transport failures, safe resubmission, deduplication, nonce handling, assertion rejection, receipt confirmation, and timeout boundaries.

Resolves ENG-4467

A Credible RPC endpoint refuses to judge a transaction while its assertion
state trails the chain head, and that refusal is raised both before the
transaction is forwarded and after, so the error alone cannot say whether
anything was submitted. Retrying it blindly risked a second transaction on
the same nonce, so activation failed instead.

Sign one envelope and resubmit those exact bytes: identical hash and nonce
mean a node can only deduplicate the retry. Each attempt first asks the
endpoint whether it already holds the hash, which is the only reliable
answer to what the refusal leaves open. Gas estimation is gated the same
way and is retried before anything is signed.

When the window outlasts the retries the two outcomes stay distinct:
`onchain.assertions_unavailable` guarantees nothing was submitted, while
`onchain.tx_submission_unconfirmed` carries the signed hash to reconcile.
@linear-code

linear-code Bot commented Aug 13, 2026

Copy link
Copy Markdown

ENG-4467

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant