feat(docs): add docs for api package

This commit is contained in:
Renato Britto
2026-04-05 20:16:34 -03:00
parent 720342f880
commit 780c3122bd
4 changed files with 198 additions and 18 deletions
+3 -1
View File
@@ -12,4 +12,6 @@ dist/
.qwen
**/__pycache__/
target/
Cargo.lock
Cargo.lock
bitcoin.conf
.bitcoin-regtest
+80 -17
View File
@@ -31,6 +31,7 @@ Stealth ships a Rust workspace with:
- `stealth-engine` (analysis engine)
- `stealth-model` (domain model types and interfaces)
- `stealth-api` (http api)
- `stealth-bitcoincore` (Bitcoin Core RPC gateway adapter)
## Project Direction
@@ -162,36 +163,94 @@ Stealth currently runs **12 detectors** in `stealth-engine`.
```bash
git clone https://github.com/stealth-bitcoin/stealth.git
cd stealth
cargo build
```
### 2. Configure blockchain connection
### 2. Configure Bitcoin Core RPC (regtest)
Edit:
```
backend/script/config.ini
```
### 3. Development setup (regtest)
A regtest environment is provided for development and reproducible testing of heuristics.
Create a local `bitcoin.conf`:
```bash
cd backend/script
./setup.sh
cat > bitcoin.conf <<'EOF'
regtest=1
server=1
daemon=1
txindex=1
listen=0
[regtest]
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpcuser=localuser
rpcpassword=localpass
rpcport=18443
fallbackfee=0.0002
EOF
```
### 4. Generate sample transactions
### 3. Start Bitcoin Core
Regtest example:
```bash
python3 reproduce.py
mkdir -p "$PWD/.bitcoin-regtest"
bitcoind -datadir="$PWD/.bitcoin-regtest" -conf="$PWD/bitcoin.conf" -daemon
```
### 5. Start backend
Mainnet example:
```bash
cd backend/src/StealthBackend
./mvnw quarkus:dev
bitcoind -daemon
```
### 4. Start the API
```bash
STEALTH_RPC_URL=http://127.0.0.1:18443 \
STEALTH_RPC_USER=localuser \
STEALTH_RPC_PASS=localpass \
cargo run --bin stealth-api
```
`stealth-api` auto-detects common local RPC ports and can use credentials from `bitcoin.conf`, cookie file, or env vars.
### 5. Run a usable scan request
```bash
DATADIR="$PWD/.bitcoin-regtest"
CONF="$PWD/bitcoin.conf"
RPC="bitcoin-cli -datadir=$DATADIR -conf=$CONF -regtest -rpcport=18443"
API_PORT=20899
mkdir -p "$DATADIR"
if ! $RPC getblockchaininfo >/dev/null 2>&1; then
bitcoind -datadir="$DATADIR" -conf="$CONF" -daemon
fi
for _ in $(seq 1 100); do
if $RPC getblockchaininfo >/dev/null 2>&1; then
break
fi
sleep 0.2
done
STEALTH_RPC_URL=http://127.0.0.1:18443 \
STEALTH_RPC_USER=localuser \
STEALTH_RPC_PASS=localpass \
STEALTH_API_BIND=127.0.0.1:$API_PORT \
cargo run --bin stealth-api >/tmp/stealth-api.log 2>&1 &
API_PID=$!
trap 'kill $API_PID >/dev/null 2>&1 || true' EXIT
WALLET="scanwallet_$(date +%s)"
$RPC createwallet "$WALLET" >/dev/null
TARGET_ADDR="$($RPC -rpcwallet="$WALLET" getnewaddress)"
$RPC generatetoaddress 101 "$TARGET_ADDR" >/dev/null
DESC="$($RPC -rpcwallet="$WALLET" getaddressinfo "$TARGET_ADDR" | jq -r '.desc')"
curl -s "http://127.0.0.1:$API_PORT/api/wallet/scan" -H 'content-type: application/json' -d "{\"descriptor\":\"$DESC\"}" | jq
$RPC stop
```
### 6. Start frontend
@@ -232,6 +291,10 @@ stealth/
│ │ └── bitcoin-data/ # Regtest chain data (gitignored)
│ └── src/StealthBackend/ # Quarkus Java REST API (single /api/wallet/scan endpoint)
└── slides/ # Slidev pitch presentation
├── api/ # stealth-api (Axum HTTP layer)
│ ├── src/
│ └── tests/
└── target/ # Cargo build outputs
```
### Test Coverage
+107
View File
@@ -0,0 +1,107 @@
# Stealth API
`stealth-api` is the Rust HTTP transport layer for Stealth. It connects to a
running `bitcoind` via JSON-RPC, imports descriptors into temporary wallets,
builds a transaction graph, and runs privacy detectors from
`stealth-engine`.
## Running
```bash
# Stop any old API process, then start the current source build
pkill -f 'target/debug/stealth-api' 2>/dev/null || true
# Auto-detects local bitcoind RPC port (prefers 18443, then 8332/18332/38332)
# and uses credentials from bitcoin.conf or local cookie files.
cargo run --bin stealth-api
```
Set auth explicitly with username/password:
```bash
STEALTH_RPC_URL=http://127.0.0.1:8332 \
STEALTH_RPC_USER=user \
STEALTH_RPC_PASS=pass \
cargo run --bin stealth-api
```
Or use a cookie file:
```bash
STEALTH_RPC_URL=http://127.0.0.1:8332 \
STEALTH_RPC_COOKIE=~/.bitcoin/.cookie \
cargo run --bin stealth-api
```
Configure the listen address with `STEALTH_API_BIND` (default `127.0.0.1:20899`).
If you see `Connection refused (os error 111)`, either:
1. an old `stealth-api` process is still running, or
2. `bitcoind` RPC is not reachable on the detected/configured URL.
## API
### `POST /api/wallet/scan`
Accepts one mutually-exclusive source:
| Field | Type | Description |
|-------|------|-------------|
| `descriptor` | `string` | Single output descriptor |
| `descriptors` | `string[]` | Multiple descriptors |
| `utxos` | `UtxoInput[]` | Raw UTXO set |
**Descriptor scan flow:** creates a blank watch-only wallet, imports the
descriptor(s) with a full blockchain rescan, builds a `TxGraph`, runs all
17 detectors, then cleans up the temporary wallet.
**UTXO scan flow:** resolves each UTXO's address from the node, builds a
partial transaction graph, and runs applicable detectors.
#### Example (real descriptor from Bitcoin Core)
```bash
RPC="bitcoin-cli -regtest -rpcport=18443 -rpcuser=localuser -rpcpassword=localpass"
WALLET="scanwallet_$(date +%s)"
$RPC createwallet "$WALLET" >/dev/null
ADDR="$($RPC -rpcwallet="$WALLET" getnewaddress)"
DESC="$($RPC -rpcwallet="$WALLET" getaddressinfo "$ADDR" | jq -r '.desc')"
curl 'http://localhost:20899/api/wallet/scan' \
-H 'content-type: application/json' \
-d "{\"descriptor\":\"$DESC\"}" | jq
```
#### Responses
| Status | Meaning |
|--------|---------|
| `200` | Scan completed — body is a `Report` |
| `400` | Invalid input (bad descriptor shape, empty UTXOs, …) |
| `502` | bitcoind RPC unavailable/auth failed/connection failed |
## Environment variables
| Variable | Description |
|----------|-------------|
| `STEALTH_API_BIND` | Listen address (default `127.0.0.1:20899`) |
| `STEALTH_RPC_URL` | bitcoind RPC endpoint (overrides auto-detection) |
| `STEALTH_RPC_USER` | RPC username (otherwise read from `bitcoin.conf` when available) |
| `STEALTH_RPC_PASS` | RPC password (otherwise read from `bitcoin.conf` when available) |
| `STEALTH_RPC_COOKIE` | Path to `.cookie` file (otherwise API auto-detects common local cookie locations) |
## E2E test (regtest)
The API includes an end-to-end regtest integration test that:
1. creates wallets,
2. gets a real descriptor from `bitcoind`,
3. scans once with no history (`summary.clean = true`),
4. creates/mine transactions,
5. scans again and asserts findings (`summary.clean = false`).
Run it with:
```bash
cargo test -p stealth-api scan_descriptor_clean_then_findings_after_regtest_activity -- --nocapture
```
+8
View File
@@ -0,0 +1,8 @@
server=1
rpcuser=localuser
rpcpassword=localpass
[regtest]
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpcport=18443