fix: one transaction approval at a time, and honest copy for a nonce collision (closes #271)
All checks were successful
check / check (push) Successful in 40s

Populating the transaction in the background before the approval window
opens is what makes the displayed object the verified object. It also
fixes the nonce before the user has answered anything, so two
eth_sendTransaction calls populated concurrently took the same nonce
from a node that had seen neither of them broadcast, and the second
could never be sent: its approved nonce is spent, and the only way to
give it a fresh one is to populate it again after the user has read the
old one off the screen.

A second transaction approval is now refused while one is unanswered,
with EIP-1193 code -32002. The refusal happens before anything is
populated — no second nonce is allocated, no window opens — and the slot
is released when the requesting page has its answer. Signature approvals
are not gated; a signature consumes no nonce.

A collision that does happen is now reported for what it is. A broadcast
the node refused for the nonce, and an approval carrying a nonce this
worker has already broadcast (caught before the node is asked at all),
both report that the transaction did not reach the network and to send
it again, instead of the standing broadcast wording that warns it may
have sent. "already known" keeps that ambiguous wording deliberately: a
node that says it has the transaction has it.

Nothing about verification is weakened. The approval still carries the
transaction the screen displayed, and the artifact is still compared
against that object field for field.
This commit is contained in:
2026-08-14 04:12:12 +00:00
parent 9dcd875dd4
commit 73db8eee43
6 changed files with 545 additions and 64 deletions

17
TODO.md
View File

@@ -45,6 +45,23 @@ undefined identifiers, which is how
# Completed Steps
- 2026-08-14: One transaction approval at a time. Populating in the background
before the window opens is what makes the displayed object the verified
object, and it also fixes the nonce: two `eth_sendTransaction` calls populated
concurrently took the same nonce from a node that had seen neither broadcast,
and the second could then never be sent, because the only way to give it a
fresh nonce is to populate it again after the user has read the old one off
the screen. A second request is now refused with EIP-1193 `-32002` while one
is unanswered — before anything is populated, so no second nonce is allocated
and no second window opens — and the slot is freed when the page has its
answer. Signature approvals are not gated, consuming no nonce. A collision
that does happen is also reported accurately now: a broadcast the node refused
for the nonce, and an approval carrying a nonce this worker has already
broadcast (caught before the node is asked at all), both say the transaction
did not reach the network and to send it again, instead of warning that it may
have sent. `already known` deliberately keeps the ambiguous wording, because a
node that says it has the transaction has it
([#271](https://git.eeqj.de/sneak/AutistMask/issues/271)).
- 2026-08-12: EIP-1193 error codes now reach the page. `src/content/inpage.js`
rebuilt every failure as `new Error(error.message)`, so the code the
background produced and the content script relayed intact was dropped in the