forked from bitcoinafterlife/bal-server
- Add docs/INDEX.md with navigable index and quick reference guides - Add 9 knowledge base files covering project overview, Bitcoin domain, architecture, modules, API reference, database schema, deployment/security - Update AGENTS.md with knowledge base reference and update policy - Add tests/sql_injection_tests.rs with regression tests for SQL injection - Fix SQL injection vulnerabilities in bal-pusher.rs: * Replace string-formatted UPDATE IN with loop + parameterized queries * Replace string-formatted UPDATE push_err with parameterized query * Add chain name validation in calculate_stats to prevent env var tampering - Update .gitignore to exclude bal-pusher.env and bal-pusher.sh
3.1 KiB
3.1 KiB
Architecture and Data Flow
Quick Reference
- What this file contains: high-level architecture, data flow, state machine, and error handling strategy.
- See also: 01_project_overview.md, 04_modules_detail.md, 05_api_reference.md, 06_database_schema.md
High-Level Architecture
User
|
| HTTP POST (raw hex transactions)
v
+-----------------+
| bal-server | (hyper + tokio, async)
| (src/bin/bal-server.rs) |
+-----------------+
| SQLite insert (db.rs)
v
bal.db
| (transactions with status=0, waiting locktime)
|
| ZMQ (hashblock / rawblock)
v
+-----------------+
+-----------------+
| bal-pusher | (async, ZMQ + RPC + reqwest)
| (src/bin/bal-pusher.rs)
+-----------------+
+-----------------+
| bal-pusher-enhanced | (sync, ZMQ + raw header parsing)
| (src/bin/bal-pusher-enhanced.rs)
+-----------------+
| bitcoincore-rpc
| sendrawtransaction
v
Bitcoin Network
Data Flow (Transaction Lifecycle)
- Submission: A client sends one or more raw hex transactions to the
pushtxsendpoint. - Validation: The
bal-serverparses each transaction usingbitcoin::Transaction. It checks for the fee output, extracts inputs/outputs, and validates the locktime. - Storage: Valid transactions are stored in
tbl_txwithstatus = 0(waiting). The inputs and outputs are stored intbl_inpandtbl_out. - Monitoring: The
bal-pusherlistens to the ZMQhashblocktopic. When a new block is detected, it fetches themediantimeviagetblockchaininfo(or via the block's median time in the enhanced version). - Evaluation: The pusher queries the database for transactions with
status=0and compares their locktime to the current blockchain median time. - Broadcast: If the locktime is satisfied, the pusher sends the transaction via
sendrawtransactionand updates the status to1(sent) or2(failed if the RPC returns an error). - Statistics: The pusher periodically sends statistics to a remote server (
welist) using a signed POST request. The server also collects stats on its own.
State Machine
[Submitted] -> status=0 (waiting)
|
| locktime satisfied
v
[Push attempt] -> status=1 (sent) or status=2 (failed)
The status field in tbl_tx is an integer:
0: Waiting for locktime.1: Successfully sent to the network.2: Failed (e.g., RPC error-25 bad-txns-inputs-missingorspent).
Error Handling Strategy
The codebase is currently inconsistent with error handling. The bal-server uses unwrap() on many critical paths (e.g., sqlite::open, Regex::new, body parsing), which causes panics in the async runtime. The bal-pusher also panics on RPC connection failures (panic!("impossible to get client {}", e)) which crashes the entire ZMQ loop.
Logging and Monitoring
The project uses env_logger and log. By default, RUST_LOG=info is set. The bal-pusher sends signed statistics to a remote server. The server exposes a stats endpoint (/<network>/stats) if expose_stats is enabled.