Skip to content

Commit 7320812

Browse files
committed
Add Thunder to the regtest stack
Wires the aarch64-darwin (and x86_64) L2-S9-Thunder prebuilt into the existing bitcoind+electrs+enforcer stack: setup.sh: downloads L2-S9-Thunder-latest-*.zip alongside the other three; extracts thunder + thunder-cli into .regtest/bin/. start.sh: waits for the enforcer's gRPC (50051) to actually be listening before launching Thunder (18444 GBT comes up first — Thunder needs 50051 to verify the mainchain ValidatorService at boot). Launches Thunder with --mainchain-grpc-url http://127.0.0.1:50051 and --rpc-addr 127.0.0.1:6009 — the same port payout/lib/thunder.js defaults to. stop.sh/status.sh: aware of the extra process. thunder-init.sh: NEW. Idempotently generates a Thunder wallet mnemonic, sets the seed, prints a wallet address + the `s9_<base58>_<hex6>` deposit-format wrapper the mainchain wallet needs to target Thunder-owned funds. End-to-end verified on aarch64-darwin: - Stack of four processes comes up clean - Thunder connects to the enforcer, both ValidatorService and WalletService verify - Thunder RPC on :6009 responds to `balance` with {"total_sats":0,"available_sats":0} - After thunder-init, a canonical CreateDepositTransaction to the Thunder-owned deposit address updates the enforcer's Ctip (Ctip value went from 100_000_000 to 150_000_000 sats across two 50M-sat deposits) - The TwoWayPeg event stream on the enforcer shows both deposits with their exact OP_RETURN payload bytes Not verified end-to-end: Thunder producing a sidechain block to credit the wallet balance. Thunder's `mine` RPC blocks pending BMM coordination with the mainchain — that's a Thunder-side concern outside the scope of the pool. The enforcer-side Ctip update is the authoritative consensus signal that the deposit was accepted; from the pool's perspective, once the deposit is in the Ctip, Thunder's own state transition is a follow-up. VERIFY.md section 10 is expanded with the thunder-init flow and a concrete canonical-deposit check anyone can reproduce.
1 parent 3653199 commit 7320812

7 files changed

Lines changed: 130 additions & 23 deletions

File tree

VERIFY.md

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -298,29 +298,60 @@ PAYOUT_DB_PATH=./shares.db node /Users/rob/projects/simplepool/payout/audit.js
298298
## 10 · BIP300 regtest stack (infra) — `b0da16f` + `6037a25`
299299

300300
```
301-
scripts/regtest/setup.sh # ~50 MB of prebuilt binaries
301+
scripts/regtest/setup.sh # ~90 MB of prebuilt binaries incl. Thunder
302302
scripts/regtest/start.sh
303303
scripts/regtest/status.sh
304304
```
305305

306-
- [ ] `status.sh` shows all three processes `up`.
306+
- [ ] `status.sh` shows all **four** processes `up`: `bitcoind`,
307+
`electrs`, `bip300301_enforcer`, `thunder`.
308+
- [ ] Thunder log ends with
309+
`Verified existence of cusf.mainchain.v1.ValidatorService` and
310+
`starting RPC server at 127.0.0.1:6009`.
307311
- [ ] `curl -sS -u user:password -H 'content-type: application/json' \
308312
--data '{"jsonrpc":"1.0","id":1,"method":"getblockcount","params":[]}' \
309313
http://127.0.0.1:18443/` returns a number.
314+
- [ ] `curl -sS -H 'content-type: application/json' \
315+
--data '{"jsonrpc":"2.0","id":1,"method":"balance","params":[]}' \
316+
http://127.0.0.1:6009/` returns
317+
`{"result":{"total_sats":0,"available_sats":0}}` — Thunder RPC
318+
is reachable (matches what the payout worker expects).
310319

311-
Activate Thunder:
320+
Activate the sidechain, then set up Thunder's wallet:
312321

313322
```
314323
scripts/regtest/activate-thunder.sh
324+
scripts/regtest/thunder-init.sh
315325
```
316326

317-
- [ ] First run prints `sidechain 9 is now ACTIVE` with proposalHeight
318-
and activationHeight (regtest activates after 6 votes).
319-
- [ ] Second run prints `sidechain 9 already active. nothing to do.`
320-
(idempotent).
321-
- [ ] `grpcurl -plaintext 127.0.0.1:50051
322-
cusf.mainchain.v1.ValidatorService/GetSidechains` shows sidechain
323-
9 in the active list.
327+
- [ ] `activate-thunder.sh` first run prints `sidechain 9 is now
328+
ACTIVE`; second run is a no-op.
329+
- [ ] `thunder-init.sh` prints a fresh mnemonic + wallet address +
330+
formatted deposit string (`s9_<base58>_<hex6>`); second run
331+
short-circuits with `already initialised`.
332+
333+
Issue a canonical deposit to the Thunder-owned address it printed,
334+
then observe the enforcer's TwoWayPeg event stream:
335+
336+
```
337+
DEP='<paste the deposit format from thunder-init.sh>'
338+
grpcurl -plaintext -d "{\"sidechain_id\":9,\"address\":\"$DEP\",\"value_sats\":100000000,\"fee_sats\":1000}" \
339+
127.0.0.1:50051 cusf.mainchain.v1.WalletService/CreateDepositTransaction
340+
grpcurl -plaintext -d '{"blocks":1}' \
341+
127.0.0.1:50051 cusf.mainchain.v1.WalletService/GenerateBlocks
342+
grpcurl -plaintext -d '{"sidechain_number":9}' \
343+
127.0.0.1:50051 cusf.mainchain.v1.ValidatorService/GetCtip
344+
```
345+
346+
- [ ] Ctip returns non-empty with `value: "100000000"` (or the running
347+
total if earlier deposits happened).
348+
349+
Note: Thunder's own balance staying at 0 after a canonical deposit is
350+
expected until Thunder produces a sidechain block via BMM. BMM is a
351+
Thunder-side concern (thunder-cli's `mine` command blocks on
352+
mainchain coordination) — outside the scope of the pool. The
353+
enforcer-side Ctip update is the authoritative signal that the
354+
deposit was consensus-accepted.
324355

325356
---
326357

scripts/regtest/README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,26 @@ LayerTwo-Labs enforcer.
3333
- **electrs**: Electrum server the enforcer's wallet uses for sync.
3434
- **bip300301_enforcer**: validates BIP300 deposits, serves the
3535
`getblocktemplate` simplepool talks to.
36-
37-
Thunder itself is intentionally NOT in this stack. There's no
38-
aarch64-darwin prebuilt for it, and the enforcer is the authoritative
39-
deposit validator — observing a Deposit event tagged with sidechain 9
40-
proves the coinbase shape is correct.
36+
- **thunder** (L2-S9): the actual sidechain node, connected to the
37+
enforcer via gRPC on 50051, RPC on 6009 (matches what
38+
`payout/lib/thunder.js` expects out of the box).
4139

4240
## Quickstart
4341

4442
```
4543
scripts/regtest/setup.sh # download prebuilts + write configs
46-
scripts/regtest/start.sh # bring up bitcoind, electrs, enforcer
44+
scripts/regtest/start.sh # bring up bitcoind, electrs, enforcer, thunder
4745
scripts/regtest/status.sh # ps-style summary
4846
scripts/regtest/activate-thunder.sh # propose + ack sidechain #9 until active
47+
scripts/regtest/thunder-init.sh # generate Thunder wallet mnemonic + address
4948
scripts/regtest/validate.sh # activate, mine 150, probe GBT, print runbook
5049
scripts/regtest/inspect-coinbase.sh # after mining: parse tip's coinbase
5150
scripts/regtest/stop.sh
5251
```
5352

54-
`activate-thunder.sh` requires `grpcurl` (`brew install grpcurl`).
55-
It's idempotent — re-running once Thunder is active is a no-op.
53+
`activate-thunder.sh` and `thunder-init.sh` are both idempotent —
54+
re-running once the state is set up is a no-op.
55+
Requires `grpcurl` (`brew install grpcurl`).
5656

5757
Everything lives under `.regtest/` (gitignored): binaries in
5858
`.regtest/bin/`, chain state in `.regtest/data/`, logs in

scripts/regtest/setup.sh

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ REGTEST="$ROOT/.regtest"
2121
BIN="$REGTEST/bin"
2222
DATA="$REGTEST/data"
2323
LOGS="$REGTEST/logs"
24-
mkdir -p "$BIN" "$DATA/bitcoind" "$DATA/electrs" "$DATA/enforcer" "$LOGS"
24+
mkdir -p "$BIN" "$DATA/bitcoind" "$DATA/electrs" "$DATA/enforcer" "$DATA/thunder" "$LOGS"
2525

2626
# ---- arch detection ----
2727
UNAME_M="$(uname -m)"
@@ -57,8 +57,10 @@ extract_to_bin() {
5757
# -j strips directories. Some zips have only one file (electrs).
5858
unzip -qq -j -o "$zip" "$match" -d "$BIN"
5959
# Find the most-recently-extracted file and rename to $final if needed.
60+
# Exclude already-canonical filenames so each extraction is idempotent
61+
# regardless of what got extracted before it.
6062
local actual
61-
actual="$(ls -t "$BIN" | grep -v -E '\.zip$|^bitcoind$|^bitcoin-cli$|^electrs$|^bip300301_enforcer$' | head -1 || true)"
63+
actual="$(ls -t "$BIN" | grep -v -E '\.zip$|^(bitcoind|bitcoin-cli|electrs|bip300301_enforcer|thunder|thunder-cli)$' | head -1 || true)"
6264
if [[ -n "$actual" && "$actual" != "$final" ]]; then
6365
mv "$BIN/$actual" "$BIN/$final"
6466
fi
@@ -72,11 +74,13 @@ case "$ARCH" in
7274
BITCOIN_ZIP_URL="https://releases.drivechain.info/L1-bitcoin-patched-v30.2-aarch64-apple-darwin.zip"
7375
ENFORCER_ZIP_URL="https://releases.drivechain.info/bip300301-enforcer-latest-aarch64-apple-darwin.zip"
7476
ELECTRS_ZIP_URL="https://releases.drivechain.info/electrs-latest-aarch64-apple-darwin.zip"
77+
THUNDER_ZIP_URL="https://releases.drivechain.info/L2-S9-Thunder-latest-aarch64-apple-darwin.zip"
7578
;;
7679
x86_64-apple-darwin)
7780
BITCOIN_ZIP_URL="https://releases.drivechain.info/L1-bitcoin-patched-latest-x86_64-apple-darwin.zip"
7881
ENFORCER_ZIP_URL="https://releases.drivechain.info/bip300301-enforcer-latest-x86_64-apple-darwin.zip"
7982
ELECTRS_ZIP_URL="https://releases.drivechain.info/electrs-latest-x86_64-apple-darwin.zip"
83+
THUNDER_ZIP_URL="https://releases.drivechain.info/L2-S9-Thunder-latest-x86_64-apple-darwin.zip"
8084
;;
8185
*)
8286
echo "no prebuilt binaries for $ARCH — build from source" >&2
@@ -87,12 +91,15 @@ esac
8791
fetch_zip "$BITCOIN_ZIP_URL" "$BIN/bitcoind.zip"
8892
fetch_zip "$ENFORCER_ZIP_URL" "$BIN/enforcer.zip"
8993
fetch_zip "$ELECTRS_ZIP_URL" "$BIN/electrs.zip"
94+
fetch_zip "$THUNDER_ZIP_URL" "$BIN/thunder.zip"
9095

9196
echo "==> extracting binaries"
9297
extract_to_bin "$BIN/bitcoind.zip" '*/bitcoind' bitcoind
9398
extract_to_bin "$BIN/bitcoind.zip" '*/bitcoin-cli' bitcoin-cli
9499
extract_to_bin "$BIN/enforcer.zip" '*bip300301-enforcer*' bip300301_enforcer
95100
extract_to_bin "$BIN/electrs.zip" '*electrs*' electrs
101+
extract_to_bin "$BIN/thunder.zip" 'thunder-latest-*' thunder
102+
extract_to_bin "$BIN/thunder.zip" 'thunder-cli-latest-*' thunder-cli
96103

97104
echo "==> binaries ready in $BIN"
98105
ls -la "$BIN" | tail -n +2

scripts/regtest/start.sh

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ LOGS="$REGTEST/logs"
1414
RUN="$REGTEST/run"
1515
mkdir -p "$RUN"
1616

17-
for b in bitcoind bitcoin-cli bip300301_enforcer electrs; do
17+
for b in bitcoind bitcoin-cli bip300301_enforcer electrs thunder thunder-cli; do
1818
if [[ ! -x "$BIN/$b" ]]; then
1919
echo "missing $BIN/$b — run scripts/regtest/setup.sh first" >&2
2020
exit 1
@@ -105,6 +105,22 @@ start_if_dead bip300301_enforcer \
105105
--serve-grpc-addr=127.0.0.1:50051
106106

107107
wait_for bip300301_enforcer "nc -z 127.0.0.1 18444" 30
108+
# Thunder connects to the enforcer's gRPC — make sure that's actually
109+
# up before launching it (18444 GBT can come up first).
110+
wait_for enforcer-grpc "nc -z 127.0.0.1 50051" 15
111+
112+
echo "==> starting thunder (sidechain #9)"
113+
start_if_dead thunder \
114+
"$BIN/thunder" \
115+
--headless \
116+
--datadir "$DATA/thunder" \
117+
--network regtest \
118+
--mainchain-grpc-url http://127.0.0.1:50051 \
119+
--net-addr 127.0.0.1:4009 \
120+
--rpc-addr 127.0.0.1:6009 \
121+
--log-level INFO
122+
123+
wait_for thunder "nc -z 127.0.0.1 6009" 30
108124

109125
echo ""
110126
echo "stack up. endpoints:"
@@ -113,5 +129,7 @@ echo " electrs: 127.0.0.1:60401"
113129
echo " enforcer GBT: 127.0.0.1:18444 (point simplepool at this)"
114130
echo " enforcer JSONRPC: 127.0.0.1:8123"
115131
echo " enforcer gRPC: 127.0.0.1:50051"
132+
echo " thunder RPC: 127.0.0.1:6009 (point payout worker at this)"
133+
echo " thunder P2P: 127.0.0.1:4009"
116134
echo ""
117135
echo "next: scripts/regtest/validate.sh"

scripts/regtest/status.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
44
RUN="$ROOT/.regtest/run"
55
LOGS="$ROOT/.regtest/logs"
66

7-
for name in bitcoind electrs bip300301_enforcer; do
7+
for name in bitcoind electrs bip300301_enforcer thunder; do
88
pidfile="$RUN/$name.pid"
99
if [[ -f "$pidfile" ]]; then
1010
pid="$(cat "$pidfile")"

scripts/regtest/stop.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -u
44
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
55
RUN="$ROOT/.regtest/run"
66

7-
for name in bip300301_enforcer electrs bitcoind; do
7+
for name in thunder bip300301_enforcer electrs bitcoind; do
88
pidfile="$RUN/$name.pid"
99
[[ -f "$pidfile" ]] || continue
1010
pid="$(cat "$pidfile")"

scripts/regtest/thunder-init.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env bash
2+
# Initialise the Thunder wallet: generate a mnemonic, set the seed, and
3+
# print a deposit address the mainchain wallet can target.
4+
#
5+
# Idempotent — re-running once the seed is set is a no-op that prints
6+
# the existing deposit address.
7+
#
8+
# Requires: thunder + thunder-cli in .regtest/bin (via setup.sh), Thunder
9+
# process running (via start.sh).
10+
11+
set -euo pipefail
12+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
13+
BIN="$ROOT/.regtest/bin"
14+
TCLI="$BIN/thunder-cli"
15+
16+
if [[ ! -x "$TCLI" ]]; then
17+
echo "missing $TCLI — run scripts/regtest/setup.sh" >&2
18+
exit 1
19+
fi
20+
21+
# Probe: does Thunder's wallet already have a seed? get-new-address
22+
# succeeds silently when yes; errors "no seed" to stderr when no.
23+
if ADDR="$($TCLI get-new-address 2>/dev/null)" && [[ -n "$ADDR" ]]; then
24+
echo "==> Thunder wallet already initialised"
25+
DEP="$($TCLI format-deposit-address "$ADDR" 2>/dev/null)"
26+
echo " new address: $ADDR"
27+
echo " deposit format: $DEP"
28+
exit 0
29+
fi
30+
31+
echo "==> generating fresh Thunder wallet mnemonic"
32+
MNEMONIC="$($TCLI generate-mnemonic)"
33+
echo " mnemonic: $MNEMONIC"
34+
35+
echo "==> setting seed"
36+
$TCLI set-seed-from-mnemonic "$MNEMONIC" >/dev/null
37+
38+
ADDR="$($TCLI get-new-address)"
39+
DEP="$($TCLI format-deposit-address "$ADDR")"
40+
41+
echo ""
42+
echo "Thunder wallet ready."
43+
echo " new address: $ADDR"
44+
echo " deposit format: $DEP"
45+
echo ""
46+
echo "To send a deposit into this wallet from the mainchain:"
47+
echo " grpcurl -plaintext -d '{\"sidechain_id\":9, \"address\":\"$DEP\","
48+
echo " \"value_sats\":100000000, \"fee_sats\":1000}' \\"
49+
echo " 127.0.0.1:50051 cusf.mainchain.v1.WalletService/CreateDepositTransaction"
50+
echo " grpcurl -plaintext -d '{\"blocks\":1}' \\"
51+
echo " 127.0.0.1:50051 cusf.mainchain.v1.WalletService/GenerateBlocks"

0 commit comments

Comments
 (0)