Skip to content

Fetch the parent tx when watching a delayed transaction - #878

Merged
pm47 merged 2 commits into
masterfrom
fetch-parent-delayed
Sep 21, 2026
Merged

pm47 merged 2 commits into
masterfrom
fetch-parent-delayed

Conversation

@pm47

@pm47 pm47 commented Sep 16, 2026

Copy link
Copy Markdown
Member

When publishing a tx that has a relative delay, we watch the output it spends until the delay elapses, which requires the script of that output to compute an electrum script hash. We derived that script from the witness, which only works for p2wpkh and p2wsh: for taproot inputs we hashed the control block into a p2wsh script and watched a script hash that doesn't exist anywhere. We now fetch the parent tx and read the script directly, which is also the only option for a taproot key path spend, where the witness is a signature that doesn't reveal the output key.

This was never triggered because the broken watch never had to work: we always set another watch on that same tx (e.g. ClosingTxConfirmed on the commit tx) whose script is correct, and we trigger watch-confirmed by txid whenever we process the history of any script hash. The correct watch was thus doing the work of the broken one, both in production and in ElectrumWatcherIntegrationTest.

As a side-effect, we no longer throw on a tx that spends a non-segwit input, whose witness is empty.

@pm47
pm47 requested a review from sstone September 16, 2026 16:09
@pm47
pm47 added this pull request to stack #881 September 17, 2026 14:38
@pm47
pm47 removed this pull request from stack #881 September 18, 2026 09:26
pm47 and others added 2 commits September 18, 2026 13:55
When publishing a tx that has a relative delay, we watch the output it
spends until the delay elapses, which requires the script of that output
to compute an electrum script hash. We derived that script from the
witness, which only works for p2wpkh and p2wsh: for taproot inputs we
hashed the control block into a p2wsh script and watched a script hash
that doesn't exist anywhere. We now fetch the parent tx and read the
script directly, which is also the only option for a taproot key path
spend, where the witness is a signature that doesn't reveal the output
key.

This was never triggered because the broken watch never had to work: we
always set another watch on that same tx (e.g. `ClosingTxConfirmed` on
the commit tx) whose script is correct, and we trigger watch-confirmed
by txid whenever we process the history of *any* script hash. The
correct watch was thus doing the work of the broken one, both in
production and in `ElectrumWatcherIntegrationTest`.

As a side-effect, we no longer throw on a tx that spends a non-segwit
input, whose witness is empty.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…880)

When publishing a delayed transaction, we now fetch its parent to get the
script of the output it spends. If that fetch fails we put the transaction
back into the publish queue, but that queue was only drained on reconnection:
`getTx` returns null after two 10s timeouts or on any electrum error, without
losing the connection, so on a long-lived connection the transaction was
dropped and no `ParentTxConfirmed` watch was ever registered.

We now also drain the publish queue whenever we receive a new block, which
bounds the retry delay to one block instead of one reconnection.

The publish handler is extracted into `processPublish`, which lets the queue
be drained by calling it directly instead of re-sending to our own mailbox:
that self-send could deadlock the watcher if the queue exceeded the mailbox
buffer. The queue is cleared before being replayed, since `processPublish`
puts failed transactions back into it.
@pm47
pm47 force-pushed the fetch-parent-delayed branch from 9235a47 to 1c1e603 Compare September 18, 2026 11:55
@pm47
pm47 merged commit dbe5685 into master Sep 21, 2026
2 checks passed
@pm47
pm47 deleted the fetch-parent-delayed branch September 21, 2026 12:47
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.

2 participants