- Fix framework references (actix-web, not hyper) - Update all env var names (BAL_SERVER_*/BAL_PUSHER_* prefix) - Add validation.rs module documentation - Fix function signatures in xpub.rs and db.rs - Update API response formats (InfoResponse, StatsResponse) - Fix database schema (date_creation/date_update, push_err, tbl_stats) - Mark fixed vulnerabilities with current status - Add Docker support and actix tuning documentation - Remove outdated references (confy, bal-stats.rs.dontcompile) - Add regression test summary table
3.6 KiB
3.6 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 | (actix-web 4.9.0 + actix-governor, async)
| (src/bin/bal-server.rs) |
+-----------------+
| SQLite insert (db.rs, Arc<Mutex<Connection>>)
v
bal.db (WAL mode)
| (transactions with status=0, waiting locktime)
|
| ZMQ (hashblock)
v
+-----------------+
| bal-pusher | (tokio, ZMQ + RPC + reqwest)
| (src/bin/bal-pusher.rs)
+-----------------+
| bitcoincore-rpc
| sendrawtransaction
v
Bitcoin Network
Data Flow (Transaction Lifecycle)
- Submission: A client sends one or more raw hex transactions to the
pushtxsendpoint (newline-separated). - Validation: The
bal-serverparses each transaction usingbitcoin::Transactionviaconsensus::deserialize. 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. Batch inserts useUNION ALL SELECTfor efficiency. - Monitoring: The
bal-pusherlistens to the ZMQhashblocktopic with a 5-second receive timeout. When a new block is detected, it fetches blockchain info via RPC. - Evaluation: The pusher queries the database for transactions with
status=0and compares their locktime against the blockchain's best block height or median time (for timestamp-based locktimes aboveLOCKTIME_THRESHOLD). - Broadcast: If the locktime is satisfied, the pusher sends the transaction via
sendrawtransactionand updates the status to1(sent) or2(failed with error stored inpush_err). - Statistics: The pusher periodically calculates statistics and sends them to a remote
welistserver using an Ed25519-signed POST request. The server also exposes stats via theGET /:network/statsendpoint ifexpose_statsis enabled.
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 details stored inpush_err.
Error Handling Strategy
The codebase has been hardened with comprehensive error handling:
bal-server: Usesactix-web's built-in error handling. Allunwrap()/expect()calls have been replaced with safematch/if leterror propagation, returning appropriate HTTP status codes (400, 404, 500).bal-pusher: ZMQrecvusesset_rcvtimeo(5000)with a match/timeout handler. RPC connection failures log errors and retry with a sleep interval instead of panicking. The pusher logs warnings for consecutive ZMQ timeouts (~1 hour threshold).db.rs: Database operations useResulttypes. Theopen_dbfunction validates paths before opening. WAL mode is set with retry logic.
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. The actix-web Logger::default() middleware logs all HTTP requests/responses.