Submission confirmation is not tied to transaction identity — silent failures and possible duplicate actions
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- typescript
- Ambito
- blockchain, frontend
Direzione di ricerca
Start with src/submit/confirmationGate.ts, ActionSubmitController.ts, and ActionSubmitController.test.ts:156, then trace optimistic updates in bus/ingest.ts and retries in src/utils/cosmos/client.ts:281-303 and joinTable.ts:66. Run the existing submission tests first; done means confirmation and failure states are tied to transaction identity, optimistic movement cannot confirm a job, and uncertain retries do not create duplicate actions.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
From the external repository review (10 Sep 2026). Both halves verified against HEAD. Filed as one issue because they share a root cause and a fix: nothing in the submission path is tied to transaction identity.
a) Table progress is treated as confirmation
src/submit/confirmationGate.ts:41-49:
const countAdvanced = hasValue(current.actionCount) && current.actionCount > baseline.actionCount;
const indexAdvanced = nextActionIndex(current) > baseline.actionIndex;
const handAdvanced = hasValue(current.handNumber) && current.handNumber > baseline.handNumber;
return countAdvanced || indexAdvanced || handAdvanced;
All three are table-global counters. Any other player acting confirms our submission. The controller never compares job.hash to anything — it is assigned at ActionSubmitController.ts:199 and used only to call onSuccess.
The 8s timeout also marks the job confirmed, not unknown (:245-254 → confirmJob → status = "confirmed"). The timer starts at runJob entry, before broadcast, so it covers signing + broadcast + block time.
And a later rejection is then discarded (:207-210): isTerminal(job) is true for "confirmed", so a real chain rejection arriving afterwards is swallowed — no toast, no onError.
⚠️ Optimistic snapshots feed the same path. bus/ingest.ts:33 classifies optimistic as kind: "state", and those go straight onto the logical track that the controller reads. So a mempool projection of someone else's pending action can confirm our submission.
b) Uncertain failures cause fresh submissions
ActionSubmitController.ts:219-233 retries on transport errors. There is a guard — the reviewer under-stated this — but it is the same weak gate above, given only gateSettleMs: 250ms to observe a chain that commits in ~5s.
The retry re-signs from scratch: clearSigningCache() discards the memoized client, so the retry rebuilds the wallet and re-queries the account sequence.
The precise dangerous window: if the first tx is still pending, the re-query returns the same sequence and the identical bytes get deduped — harmless. If the first tx committed between the failure and the retry, the re-query returns sequence N+1 and produces a genuinely distinct, valid second action.
src/utils/cosmos/client.ts:281-303 (withMoneyMoverRetry, used by joinTable.ts:66) does the same with no confirmation gate at all, on a money-moving path.
Why this matters more than it looks
Combined with poker-vm#2609 — where the SDK returns a transaction hash for failed execution — there is currently no layer that can tell a user their action failed. The SDK reports failure as a hash; the UI confirms on unrelated table movement or an 8s timer; and any late rejection is discarded as moot.
Suggested plan
- Model the states honestly:
submitted,accepted,committed-success,committed-failure,unknown. A timer expiring producesunknown, neverconfirmed. That single change removes the silent-failure class. - Match by transaction identity. Correlate the committed receipt by hash rather than by counters.
performActionSyncalready returns a hash; the WS push should be reconcilable against it. - Keep optimistic state visually distinct from authoritative state and never let it satisfy a confirmation.
- On uncertain transport failure, query before resubmitting — and rebroadcast identical signed bytes rather than re-signing, so a duplicate is impossible rather than merely unlikely. Preserve the signed bytes and hash for that purpose.
- Serialize account-level submissions across the action path and
withMoneyMoverRetry, so two flows cannot race on the same sequence. - Tests exist for the current behaviour (
ActionSubmitController.test.ts:156codifies the 8s escape hatch as intended) — those need updating deliberately, not silently.
Original review findings 7 and 8.
- Lingua principale
- TypeScript
- Stelle
- 2
- Fork
- 5
- Merge medio
- 22h 35m
- PR unite (30g)
- 91
Preparare l'ambiente
Non abbiamo ancora controllato i file di configurazione di questo progetto. Parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di block52/ui
-
enhancement tech debt
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
feat(ui): player notes and tags — click a seat to note a player; tag icons (fish, shark, tight, loose…) show by their pillForse già presa @Dzeezbtc l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
-
chore(ui): move existing inline null/empty and typeof checks to the guardsForse già presa @bitcoinbrisbane l’ha presa 1 giorno fa. Apertarefactor tech debt UI
block52/ui#937 · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
architecture refactor tech debt
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
I maintainer di solito rispondono entro 1 giorno
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
kunchenguid/gh-axi#247 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
lidge-jun/opencodex#8101 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
effort:S P3 refactor
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
nightscout/nocturne#3243 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
JuliusBrussee/caveman#1449 ·
I maintainer di solito rispondono entro 1 giorno