Files
bal-server/docs/05_api_reference.md
svatantrya 69d877a360 docs: add comprehensive knowledge base and security audit
- 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
2026-07-16 14:11:18 -04:00

6.3 KiB

API Reference

Quick Reference


HTTP API (provided by bal-server)

GET /

  • Description: Returns a static identification string (e.g., "Will Executor Server").
  • Response: Plain text 200 OK.

GET /version

  • Description: Returns the Cargo package version (bal_server version).
  • Response: text/plain (e.g., 0.2.3).

GET /.pub_key.pem

  • Description: Returns the static Ed25519 public key PEM file for signature verification of remote stats.
  • Response: text/plain with the PEM file content.
  • File: public_key.pem in the project root.

GET /:network/info

  • Description: Returns JSON with the server's configuration for that specific network.
  • Supported Networks: bitcoin, testnet, testnet4, signet, regtest.
  • Response (200 OK):
    {
      "network": "regtest",
      "our_address": "bcrt...",
      "fee": 1000,
      "chain": "regtest",
      "version": "0.2.3"
    }
    
  • Error: 404 if the network is not configured.

GET /:network/stats

  • Description: Returns statistics for the given network. This endpoint is guarded by the expose_stats configuration flag.
  • Response (200 OK):
    {
      "report_date": 1712345678,
      "chain": "regtest",
      "total": 42,
      "waiting": 10,
      "sent": 30,
      "failed": 2,
      "waiting_profit": 10000,
      "sent_profit": 30000,
      "missed_profit": 5000,
      "unique_input": 15
    }
    
  • Error: 403 or 400 if stats are not enabled or the network is unknown.

POST /:network/pushtxs

  • Description: Accepts one or more raw hex Bitcoin transactions. The server deserializes the transaction, validates that the fee is paid to the correct our_address for that network, and stores the transaction in the database. It also stores all inputs and outputs.
  • Request Body:
    • Content-Type: application/json (or plain text, depending on the client).
    • The payload format is typically an array of raw hex strings or a single hex string.
    [
      "02000000000101...hex..."
    ]
    
  • Response (200 OK): A JSON array with the result for each transaction.
    [
      {
        "txid": "abc123...",
        "wtxid": "def456...",
        "status": 0,
        "locktime": 2100,
        "our_fees": 1000,
        "our_address": "bcrt1q..."
      }
    ]
    
  • Response (400 Bad Request): If the transaction is invalid, the fee is missing, or the locktime is not acceptable.
  • Response (500 Internal Server): Database error, Invalid hex, Invalid transaction (may contain a panic trace if an internal unwrap is hit).
  • Security Note: If a transaction is not valid or does not pay the required fees, it is not inserted into the database.

POST /searchtx

  • Description: Searches for a transaction by its txid. Returns the transaction details, status, raw hex, and fees.
  • Request Body:
    {
      "txid": "abc123..."
    }
    
  • Response (200 OK):
    {
      "txid": "abc123...",
      "status": 1,
      "tx": "020000000...",
      "our_address": "bcrt1q...",
      "our_fees": 1000,
      "locktime": 2100,
      "timestamp": 1712345678
    }
    
  • Response (404): If the transaction is not found in the database.
  • Response (400): If the request body is invalid.

ZMQ Messages (consumed by bal-pusher and bal-pusher-enhanced)

Topic: hashblock (Consumed by bal-pusher)

  • Format: A multipart ZMQ message. The first frame is the topic name (hashblock), the second frame is the 32-byte block hash.
  • Trigger: When a new Bitcoin block is found by the local node.
  • Action: The pusher fetches getblockchaininfo from the RPC, gets the updated mediantime, then queries and pushes pending transactions.
  • Endpoint: tcp://127.0.0.1:28332 (or network-specific ports).

Topic: rawblock (Consumed by bal-pusher-enhanced)

  • Format: A multipart ZMQ message. The first frame is the topic name (rawblock), the second frame is the raw serialized block data. The first 80 bytes of this second frame are the block header, in which bytes [68..72] are the timestamp (little-endian uint32_t).
  • Trigger: When a new Bitcoin block is found by the local node.
  • Action: The pusher extracts the block header, reads the timestamp from it, computes the rolling median of the last 11 block timestamps, then evaluates and pushes pending transactions.
  • Endpoint: tcp://127.0.0.1:28332 (or network-specific ports).
  • Note: This topic is much more bandwidth-intensive than hashblock because the entire block is sent over the wire.

Bitcoin Core RPC Usage (used by bal-pusher and bal-pusher-enhanced)

sendrawtransaction (Both pushers)

  • Method: sendrawtransaction (RPC 2)
  • Parameters: hexstring (the raw hex of the transaction to broadcast).
  • Description: Broadcasts the transaction to the Bitcoin network. If the transaction is invalid (e.g., bad-txns-inputs-missingorspent), the RPC will return an error with a negative code (e.g., -25).
  • Error Handling: The pusher catches these errors, logs them, and updates the database status to 2 (failed).

getblockchaininfo (Only bal-pusher)

  • Method: getblockchaininfo (RPC 1)
  • Parameters: None.
  • Description: Returns the current blockchain state, including the mediantime (the median timestamp of the last 11 blocks). This is used to evaluate the nLockTime of pending transactions.
  • Alternative: bal-pusher-enhanced does not use this method; it derives the block timestamp directly from the rawblock ZMQ message to avoid an RPC round-trip and a potential RPC dependency failure.

getblock (Only used by bal-pusher for median time)

  • Method: getblock (RPC 1)
  • Parameters: blockhash, verbosity (set to 1 for JSON with timestamp).
  • Description: Fetches the details of a block. It is used as an alternative to getblockchaininfo to get the block's time if getblockchaininfo fails or is insufficient.