Skip to content

chore: fund spark regtest from the shared wallet - #1308

Merged
ovitrif merged 3 commits into
masterfrom
feat/spark-regtest-fund-mnemonic
Nov 12, 2026
Merged

ovitrif merged 3 commits into
masterfrom
feat/spark-regtest-fund-mnemonic

Conversation

@ovitrif

@ovitrif ovitrif commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Twin: synonymdev/bitkit-android#1891

This PR adds scripts/spark-regtest-fund.py, which funds Spark regtest addresses from the shared Spark regtest wallet that Lightspark funded for our tests, so local runs and CI can fund them without faucet credentials.

Description

  • spark-regtest-fund.py spends from the wallet behind the SPARK_REGTEST_MNEMONIC repository secret: one P2WPKH address at BIP84 m/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).
  • It matches the Android script in synonymdev/bitkit-android#1891: each send spends one random confirmed coin that covers it, and retries with another coin on a broadcast error. The API's address index lags the mempool, and several jobs and agents spend from the same wallet, so a largest-first pick would make concurrent senders collide on one coin.
  • On iOS it funds only Spark's deposit address on a Debug build launched without SPARK_CHAIN_SERVICE_URL: Savings watches Bitkit's staging regtest, a different chain, so the docstring points Savings funding at the staging ./lsp deposit.
  • It runs with uv run (inline embit dependency), and --balance prints the wallet's confirmed and unconfirmed sats.

Out of Scope

  • .github/workflows: no job funds from Spark regtest yet; a job that needs funds passes SPARK_REGTEST_MNEMONIC from secrets and calls this script.

Design

N/A — no UI changes.

Preview

N/A

QA Notes

Setup

SPARK_REGTEST_MNEMONIC set to the shared wallet's recovery phrase (stored as a repository secret), and uv installed.

Journeys

N/A — no user-visible behaviour change.

Manual Tests

  • 1. SPARK_REGTEST_MNEMONIC="…" uv run scripts/spark-regtest-fund.py --balance → prints the wallet address bcrt1qef4prw6ezd0mr8s52a2hytmetjn9r3a0q7vcws and its balance
  • 2. SPARK_REGTEST_MNEMONIC="…" uv run scripts/spark-regtest-fund.py <bcrt1… address> 20000 → prints a txid that https://regtest-mempool.us-west-2.sparkinfra.net/api/tx/<txid>/status knows

Automated Checks

N/A

Evidence

  • 1: printed the wallet with 10,628,518 sats confirmed.
  • 2: verified with the identical script in synonymdev/bitkit-android#1891, where two sends started at the same moment both broadcast (b61c1bbf…6acc, be889c4d…0888), each on its own coin.
  • Without SPARK_REGTEST_MNEMONIC the script exits with a message naming the variable.
  • git diff --check clean; no app code changed, so no build or device run.

Gaps

None.

Models used

  • Planning/scoping: claude-opus-5-5 (reasoning: Not exposed)
  • Implementation: claude-opus-5-5 (reasoning: Not exposed)
  • Review: Not performed

The session metadata available here names the model but not a reasoning setting.

@ovitrif ovitrif self-assigned this Nov 12, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-12T15:37:18.289906Z 2cd439e PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@ovitrif
ovitrif requested review from a team, ben-kaufman and pwltr and removed request for a team November 12, 2026 15:36
@greptile-apps

greptile-apps Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Low impact] The PR adds a manual funding path for Spark regtest development and CI work.

Fix the multi-input retry before merging so concurrent funding does not fail despite enough usable funds.

Findings

  1. P1 Retries drop usable coins ▶

Summary

Adds scripts/spark-regtest-fund.py to fund regtest addresses from the shared wallet.

  • Developers can send Spark regtest funds from the shared wallet.
  • The script shows the shared wallet's confirmed and unconfirmed balance.

Reviews (1) · Last reviewed commit: "chore: fund spark regtest from the share..." · Reviewed by Greptile

Comment thread scripts/spark-regtest-fund.py Resolved

@pwltr pwltr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2cd439e. The new funding script signs from the shared regtest wallet and broadcasts through Lightspark's mempool API; its code matches the Android twin, and 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

@ovitrif

ovitrif commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator Author

Low — A failed multi-input send drops every picked coin from the retry.

@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 talosmachina left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No findings. Adds scripts/spark-regtest-fund.py, the same funder as synonymdev/bitkit-android#1891: spends from the shared regtest wallet behind SPARK_REGTEST_MNEMONIC, one random confirmed coin per send, retried with another coin on a broadcast error. Reviewed 2cd439e, full tier, static; I did not run it, since it spends from a shared wallet.

What I checked, and 4 candidates I ruled out

Read in full: the script; diffed it against the Android one (only the docstring differs)

Ruled out

  • P2WPKH signing: scriptCode is the key's P2PKH script per BIP143, witness is DER sig + SIGHASH_ALL + compressed pubkey.
  • Fee underpaid: vsize rounds up and counts a change output even when sub-dust change is dropped into the fee.
  • Retry picking the same coin: failed outpoints go into skip, applied before both pick strategies.
  • Secret exposure: the mnemonic comes from the environment and is never printed.

CI: green apart from Run Tests, still running at review time; the PR touches no Swift.

Merge confidence: 4/5, a dev script with no test, not run here.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One LOW inline on the docstring; approving. The script doesn't ship: it isn't in the Xcode project or any build phase. No credential is committed or printed: the mnemonic comes only from SPARK_REGTEST_MNEMONIC, and errors print only the HTTP status and body. Keys are regtest-derived (m/84h/1h), so a wrong endpoint can't reach real funds. Signing, vsize rounding and dust change match the Android twin synonymdev/bitkit-android#1891, which merged. The LOW can be fixed here or in a follow-up, your choice.

Device gate: no device check needed: dev tooling only.

Comment thread scripts/spark-regtest-fund.py Resolved
@ovitrif
ovitrif requested review from jvsena42 and pwltr November 12, 2026 16:36

@ben-kaufman ben-kaufman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new material findings at beaf8856. The latest changes only correct the funding instructions, and executable code is unchanged. The rare multi-input retry limitation remains accepted for this developer regtest tool. Live funding, concurrent sends and the uv run entry point remain unverified by this review.

Reviewer model: gpt-6.1-sol
Reasoning effort: xhigh

@ovitrif

ovitrif commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator Author

Merged: approved by @ben-kaufman on the current head, checks green, the review threads answered.

@ovitrif
ovitrif merged commit a517238 into master Nov 12, 2026
21 checks passed
@ovitrif
ovitrif deleted the feat/spark-regtest-fund-mnemonic branch November 12, 2026 22:27
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.

5 participants