Summary
tempo wallet sessions --orphaned only discovers ChannelOpened events within the last 100,000 blocks. Because Tempo session channels do not expire automatically, an active channel that is older than this window becomes undiscoverable if its local SQLite record is lost or unavailable.
This is a recovery and UX gap rather than an escrow contract bug: the funds remain recoverable on-chain when the channel ID is known, but the wallet cannot find that channel through its orphan recovery flow.
Current behavior
src/commands/sessions.ts calls findAllChannelsForPayer() for --orphaned and computes the scan range as:
const latest = (await publicClient.getBlockNumber()).valueOf() - logHeadMargin;
const earliest = latest > logScanDepth ? latest - logScanDepth : 0n;
findAllChannelsForPayer() then queries ChannelOpened logs only between earliest and latest. The current logScanDepth is 100_000.
Reproduction scenario
- Open a session channel and leave it active for more than the scan window.
- Remove or lose the local
channels database record.
- Run
tempo wallet sessions --orphaned or tempo wallet sessions close --orphaned.
- The channel is not returned because its
ChannelOpened event is outside the bounded log range.
The same result can be reproduced deterministically with a mocked RPC: place the ChannelOpened event before latest - 100_000 and verify that no getLogs request includes that block.
Question / possible direction
Is the 100,000-block bound an intentional RPC-cost safeguard, or should orphan recovery support an explicit wider scan? If the bound is intentional, a small follow-up could make the tradeoff visible and provide a recovery path, for example:
- an explicit
--from-block / --scan-depth option;
- a persisted scan cursor; or
- a clear warning that orphan discovery is limited to the configured block window.
I would keep the first change focused on recovery semantics and regression coverage. I would not change the default scan cost or any escrow behavior without maintainer guidance.
Would you prefer a narrow issue/PR around an explicit scan range, or should orphan recovery remain intentionally bounded?
Related protocol context: Tempo session channels have no automatic expiry and are closed cooperatively or through the request-close/grace-period/withdraw path.
Summary
tempo wallet sessions --orphanedonly discoversChannelOpenedevents within the last 100,000 blocks. Because Tempo session channels do not expire automatically, an active channel that is older than this window becomes undiscoverable if its local SQLite record is lost or unavailable.This is a recovery and UX gap rather than an escrow contract bug: the funds remain recoverable on-chain when the channel ID is known, but the wallet cannot find that channel through its orphan recovery flow.
Current behavior
src/commands/sessions.tscallsfindAllChannelsForPayer()for--orphanedand computes the scan range as:findAllChannelsForPayer()then queriesChannelOpenedlogs only betweenearliestandlatest. The currentlogScanDepthis100_000.Reproduction scenario
channelsdatabase record.tempo wallet sessions --orphanedortempo wallet sessions close --orphaned.ChannelOpenedevent is outside the bounded log range.The same result can be reproduced deterministically with a mocked RPC: place the
ChannelOpenedevent beforelatest - 100_000and verify that nogetLogsrequest includes that block.Question / possible direction
Is the 100,000-block bound an intentional RPC-cost safeguard, or should orphan recovery support an explicit wider scan? If the bound is intentional, a small follow-up could make the tradeoff visible and provide a recovery path, for example:
--from-block/--scan-depthoption;I would keep the first change focused on recovery semantics and regression coverage. I would not change the default scan cost or any escrow behavior without maintainer guidance.
Would you prefer a narrow issue/PR around an explicit scan range, or should orphan recovery remain intentionally bounded?
Related protocol context: Tempo session channels have no automatic expiry and are closed cooperatively or through the request-close/grace-period/withdraw path.