Skip to content

DAH-2585: unlock coldkey before the fund spinner hides its password prompt - #99

Open
arhangel66 wants to merge 2 commits into
mainfrom
DAH-2585-fund-unlock-coldkey-before-spinner
Open

DAH-2585: unlock coldkey before the fund spinner hides its password prompt#99
arhangel66 wants to merge 2 commits into
mainfrom
DAH-2585-fund-unlock-coldkey-before-spinner

Conversation

@arhangel66

@arhangel66 arhangel66 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Problem

lium fund reads as hung on Checking wallet registration.... On 2026-08-04 a customer gave up after minutes and sent 5 TAO to the company coldkey manually — money that stays unaccounted until registration completes.

It was never hung; it was waiting for a password that does not look like a question.

Both funding paths wrap CheckWalletRegistrationAction in ui.load("Checking wallet registration", ...). For a wallet that is not registered yet, that action calls Lium.add_wallet(), which signs with bt_wallet.coldkey — and reading .coldkey makes bittensor_wallet print Enter your password: straight to the terminal, on the same line, with no newline.

Measured under a pty against a real encrypted wallet (bittensor_wallet 4.0.1), sitting on the prompt for 4 s without answering:

  • spinner frames emitted after the prompt appeared: 0
  • line-erase (\r\x1b[2K) sequences after the prompt appeared: 0
  • a plain Python background thread ticked 1 time in 3 s instead of ~30 — the Rust password reader holds the GIL, so Rich's refresh thread stalls
  • ESC[?25l (hide cursor) had been sent, ESC[?25h had not — the cursor is hidden at the prompt

So the prompt is not repainted away. The spinner freezes mid-frame and the prompt lands glued to the tail of that dead line, cursor hidden, nothing echoing:

⠹ Checking wallet registration...Enter your password:

A stopped spinner with text stuck to it reads as a crashed command, not as a question — which is exactly how it was reported.

Fix

Unlock the coldkey in lium fund before the first spinner opens, in both the TAO and the --alpha path (new UnlockColdkeyAction). The prompt then gets its own clean line with a visible cursor, before any Status is running. unlock_coldkey() caches the decrypted keypair on the wallet, so the later signing does not ask again — measured password prompts stay at 1.

In the alpha path Lium() now constructs before the unlock, so a missing API key aborts without asking for a password first. The TAO path already had that order.

Trade-off

The password is now requested on every lium fund run, before the amount prompt and the confirm — including for already-registered wallets that previously only got asked after confirming. Accepted: the run ends in a coldkey signature anyway, and a wrong password now fails before any network call instead of after.

Two known limits, unchanged by this PR: the Rust prompt reads the controlling tty (a piped password is not consumed), and a wrong password has no retry — the command has to be re-run.

Tests

Three regression tests in test/test_fund_cli.py: the unlock precedes every ui.load spinner on both paths, and a coldkey that fails to decrypt aborts before registration or transfer. All three fail if the unlock is removed (verified by mutating UnlockColdkeyAction into a no-op).

pytest test/test_fund_cli.py -q   # 52 passed
pytest test/ -q                   # 328 passed, 11 failed — same 11 fail on origin/main

Pre-deploy verification

Staging, encrypted coldkey, unregistered wallet: the password prompt appears on its own line before the spinner, and registration completes.

Post-deploy verification

+1 d: a fresh coldkey funds end-to-end — the pay-tao listener logs Transfer matched company wallet, with no CRITICAL: No Stripe customer ID.

@arhangel66
arhangel66 requested a review from taiberium August 7, 2026 07:35
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