Repository navigation
chore: fund spark regtest from the shared wallet - #1891
Conversation
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 089abaf239
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
[Medium impact] The changes affect one developer and CI funding utility for Spark regtest. Fix the multi-input retry path before merging so concurrent sends do not fail despite enough available funds. Findings
SummaryReplaces Lightspark's authenticated faucet with local spending from the shared regtest wallet.
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Read shared wallet mnemonic] --> B[Derive wallet address and key]
B --> C[Fetch confirmed coins]
C --> D[Pick coins and sign payment]
D --> E[Broadcast payment]
E -->|Success| F[Print transaction ID]
E -->|HTTP error| G[Skip every selected coin]
G -->|Attempts remain| D
Reviews (1) · Last reviewed commit: "chore: fund spark regtest from the share..." · Reviewed by Greptile |
pwltr
left a comment
There was a problem hiding this comment.
Reviewed 089abaf. The funding script now signs from the shared regtest wallet and broadcasts through Lightspark's mempool API; the fee estimate, segwit signing and change handling check out.
Low — A failed multi-input send drops every picked coin from the retry. When no single coin covers the send, pick() combines several, and on a broadcast error scripts/spark-regtest-fund.py:108 skips all of them, though another sender may have spent only one. The retry can then exit with "Insufficient confirmed funds" while the wallet still has enough. Skipping only the coins that turned out spent, or re-reading the UTXO list before retrying, would avoid it.
Review details
General review
Model: Claude Opus 5.5
Reasoning effort: high
Regtest APKDownload bitkit-dev-debug universal APK (expires in 30 days). |
@pwltr Thanks. I'm keeping it as is: multi-input sends only happen when no single coin covers the amount, and the wallet holds 40 coins of 200k sats, so a normal test-wallet funding always spends one coin. In the rare multi-input case a lost race exits cleanly with nothing sent, and a rerun after the next block (about a minute) reads a fresh UTXO list. |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. scripts/spark-regtest-fund.py now spends from the shared regtest wallet behind SPARK_REGTEST_MNEMONIC (BIP84 m/84'/1'/0'/0/0, signed locally, broadcast to the regtest mempool API) instead of calling the authenticated faucet. Reviewed 089abaf, full tier, static; I did not run it, since it spends from a shared wallet.
What I checked, and 5 candidates I ruled out
Read in full: the script at the head, and the removed faucet version
Callers: nothing else in the repo references the script or FAUCET_USERNAME/FAUCET_PASSWORD, so no workflow breaks with the faucet path gone
Twin: identical to synonymdev/bitkit-ios#1308 apart from the docstring
Ruled out
- P2WPKH signing: BIP143 scriptCode is the P2PKH script of the key, which is what
sighash_segwitgets; witness is DER sig +SIGHASH_ALL+ compressed pubkey. - Fee underpaid:
vsizerounds every component up (11 + 68 per input + destination + a change output), and a dropped sub-dust change goes to the fee. - Retry reusing a spent coin: the failed attempt's outpoints go into
skip, which both the single-coin and the largest-first paths filter on. - Secret exposure: the mnemonic is only read from the environment; errors print the API path and response, never the key.
- Unconfirmed coins: only confirmed coins are picked, so a send never chains on another job's unconfirmed change.
CI: green.
Merge confidence: 4/5, a dev script with no test, not run here.
|
Merged: approved by @pwltr, checks green, the review threads answered. |
Twin: synonymdev/bitkit-ios#1308
This PR switches
scripts/spark-regtest-fund.pyfrom Lightspark's API faucet to the shared Spark regtest wallet that Lightspark funded for our tests, so local runs and CI can fund Spark regtest addresses without faucet credentials.Description
spark-regtest-fund.pynow spends from the wallet behind theSPARK_REGTEST_MNEMONICrepository secret: one P2WPKH address at BIP84m/84'/1'/0'/0/0, used for receive and change. It signs locally and broadcasts through Lightspark's regtest mempool API (regtest-mempool.us-west-2.sparkinfra.net), soFAUCET_USERNAME/FAUCET_PASSWORDare no longer needed.uv run(inlineembitdependency), and--balanceprints the wallet's confirmed and unconfirmed sats.Out of Scope
.github/workflows: no job funds from Spark regtest yet; a job that needs funds passesSPARK_REGTEST_MNEMONICfrom secrets and calls this script.Design
N/A — no UI changes.
Preview
N/A
QA Notes
Setup
SPARK_REGTEST_MNEMONICset to the shared wallet's recovery phrase (stored as a repository secret), anduvinstalled.Journeys
N/A — no user-visible behaviour change.
Manual Tests
SPARK_REGTEST_MNEMONIC="…" uv run scripts/spark-regtest-fund.py --balance→ prints the wallet addressbcrt1qef4prw6ezd0mr8s52a2hytmetjn9r3a0q7vcwsand its balanceSPARK_REGTEST_MNEMONIC="…" uv run scripts/spark-regtest-fund.py <bcrt1… address> 20000→ prints a txid thathttps://regtest-mempool.us-west-2.sparkinfra.net/api/tx/<txid>/statusknowsAutomated Checks
N/A
Evidence
b61c1bbf…6acc,be889c4d…0888) and reached the mempool, each on its own coin.SPARK_REGTEST_MNEMONICthe script exits with a message naming the variable.git diff --checkclean; no app code changed, so no build or device run.Gaps
None.
Models used
claude-opus-5-5(reasoning:Not exposed)claude-opus-5-5(reasoning:Not exposed)The session metadata available here names the model but not a reasoning setting.