# Kachie DATUM gateway [简体中文说明](KACHIE.zh-CN.md) This is Kachie's adaptation of the iohzrd gateway at commit `7491a5099dd5d887a027c812f71de63e0d5986a3`. The MIT license is retained. Your node chooses the transactions. Kachie supplies the complete coinbase split, verifies shares and shares rewards with the Traditional pool. DATUM has a 0% fee; 0.5 percentage points of Traditional's 1.5% fee fund the DATUM bonus. ## Build from source Linux verified; native macOS build/mining validation is pending. FreeBSD is unsupported: the gateway builds there, but refuses to start Kachie mining because its durable proof spool needs an atomic no-replace rename (Linux or macOS only). On Ubuntu, install the build dependencies described in README.md and Python 3. On macOS, install Apple's Xcode Command Line Tools (`xcode-select --install`) and Homebrew. Install the dependencies with: ```sh brew install cmake pkgconf curl jansson libsodium libmicrohttpd argp-standalone epoll-shim python ``` In the extracted source directory, build as your normal user: ```sh cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_API=OFF -DKACHIE_BUILD_TESTS=ON cmake --build build -j2 ctest --test-dir build --output-on-failure ``` ## Setup language and local dashboard The setup helper accepts flags; it does not run an interactive wizard. Use `--language en` for English help, errors and completion messages, or `--language zh-CN` (or `--lang zh-CN`) for Simplified Chinese: ```sh python3 kachie-setup.py --language en --help ``` The default `--language auto` uses the first nonempty terminal locale in `LC_ALL`, `LC_MESSAGES`, then `LANG`. Chinese locales select Simplified Chinese; other, missing or malformed locales select English. `C` and `POSIX` explicitly select English. Language selection does not change configuration keys, addresses, identity files or mining behavior. Gateway runtime logs remain in English. The local dashboard is disabled by default. To enable it, build with the API included (replace the API-disabled configure command above): ```sh cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_API=ON -DKACHIE_BUILD_TESTS=ON cmake --build build -j2 ctest --test-dir build --output-on-failure ``` For a new configuration, opt in with `--dashboard-port 7152`: ```sh python3 kachie-setup.py --language en --address YOUR_XBT_ADDRESS --rpc-cookie "/absolute/path/to/.cookie" --listen YOUR_LAN_IP --dashboard-port 7152 ``` After you start the gateway, open on the same computer. The dashboard detects the browser language and provides an English/简体中文 selector. Its language is independent of the setup helper's terminal language. The helper fixes the dashboard listener at `127.0.0.1`, keeps `api.modify_conf=false` and does not enable an admin password or change CSRF protection. Use a free port from 1 through 65535; `0` keeps the dashboard disabled. For an existing configuration, do not rerun setup to replace it. With a gateway built using `ENABLE_API=ON`, manually set `api.listen_port` to `7152` in `private/gateway.json`, keeping `api.listen_addr` as `127.0.0.1` and `api.modify_conf` as `false`. Keep the existing gateway identity and other settings. Apply the change during a restart you plan yourself; setup does not restart the gateway. If you already manage an admin password, these instructions leave it unchanged. Do not expose the dashboard or node RPC to the public Internet. ## Connect your node and miners Run the Bitcoin (XBT) Knots node with RPC enabled and fully synchronized. The setup helper connects to node RPC on `127.0.0.1:8332`; use `--rpc-url` if your local node uses another port. Run setup as the same user as your node: ```sh python3 kachie-setup.py --address YOUR_XBT_ADDRESS --rpc-cookie "/absolute/path/to/.cookie" --listen YOUR_LAN_IP ./run-kachie.sh ``` For a macOS node using the standard data directory, the cookie argument is `--rpc-cookie "$HOME/Library/Application Support/Bitcoin/.cookie"`. Use your actual data directory if customized, and quote paths containing spaces. The helper records this path without reading the cookie; the gateway reads it when connecting to your node. Homebrew provides `python3`; the launcher uses Bash syntax compatible with macOS's bundled Bash 3.2. Point miners at `stratum+tcp://YOUR_LAN_IP:23334`, username `address.worker`, password `x`. Worker names support letters, numbers, `_` and `-` (up to 100 characters). Use a dedicated XBT payout wallet. The gateway never needs its private key. Use a lower-case mainnet `bc1...` v0/v1 address or a mainnet `1...`/`3...` address. Setup verifies its network, checksum, witness version and program length before creating private state. The setup script creates a private gateway identity and refuses to overwrite an existing configuration. Keep `private/gateway.identity` stable across restarts. Before an upgrade, move, or restore, stop the gateway and back up `private/gateway.identity`, `private/gateway.json`, `private/abw-spool/`, and `private/candidates/` as one atomic set. Restore that complete set before starting the gateway; never mix files from different backups or installations. The shared binary retains `private/candidates/` for its trusted house-gateway role; Prime never sends completed XOR blocks over an external KPA1 connection, so that connection leaves the compatibility archive empty. The signing identity is part of protected-work recovery. Replacing or losing it causes Prime to reject historical signed payout authorizations, while the spool identity check fails closed rather than replaying them under a new identity. Any independently implemented KPA1 gateway must retain the same HELLO signing identity for historical recovery. Stock CONVOY, iohzrd and FlyTheElephant do not implement KPA1/KAP5 and cannot use Kachie's protected work unchanged. On macOS, keep private state on a local APFS volume that supports exclusive rename and `F_FULLFSYNC`, which the gateway uses for durable proof/body storage and, in its trusted house role, completed-block archives. Bind the miner listener to your LAN. Keep node RPC and the gateway API private. After a pool disconnect the gateway reconnects after 0.5-1, 1-2, 2.5-5, 5-10 and then 10-20 seconds, measured from the disconnect; a pool on the same host (`127.0.0.1`, `::1` or `localhost`) retries after about 0.5, 1, 2 and then 5 seconds. The steps restart once a session has stayed up for 30 seconds. With `pooled_mining_only`, miners are disconnected only after the pool connection has been down for 15 seconds; a connected session that is briefly without work keeps its miners. ## Miner admission and capacity The packaged defaults allow 1,024 total miner connections while preventing one source from taking every slot. An IPv4 address is one source; IPv4-mapped IPv6 is folded into that same IPv4 source, and native IPv6 is grouped by `/64` so rotating interface addresses cannot evade the limit. The defaults are 512 connections per source, 4,096 new connections per minute, a 2,048-connection burst, and 256 slots reserved for new sources. Large trusted NATs can be listed as comma-separated IPv4 `/32` or IPv6 `/64` entries in `stratum.source_limit_exempt`. Keep that list limited to addresses you control. PROXY protocol remains disabled by default. If miners arrive through a trusted L4 proxy, set `stratum.trust_proxy` to the number of trusted hops (1 through 8) and list every proxy peer in `stratum.proxy_trusted_sources` as IPv4 `/32` or IPv6 `/64`. PROXY headers from any other peer are rejected. Trust is checked hop by hop: a further PROXY header counts only when the previous header named a listed proxy; otherwise the gateway keeps the last trusted source. An older config that enables `trust_proxy` must add this allowlist before upgrading. Idle clients are removed after 15 seconds without subscribing, 300 seconds without a first accepted share, or 900 seconds after their last accepted share. All three timeouts must remain positive. Existing configurations that explicitly used `0` to disable a timeout must choose a finite value before upgrading. `max_clients_per_source` must be below `max_clients` and leave the configured reserved slots available. If a smaller installation sets `max_clients` to 256 or less, it must also lower `reserved_clients` from its 256 default. The packaged configuration defaults to 1,024 connections. Kachie's private house deployment uses the supported 16,384-connection ceiling. At the default variable-difficulty target of two accepted shares per minute, those settings are about 34 and 546 proofs per second respectively. Raising either value also raises memory, disk and accounting throughput requirements; the gateway rejects configurations whose bounded worker arrays, queues and proof indexes exceed its memory budget. Every protected proof starts a private KAP5 disk-spool commit before the gateway can report success to the miner. On the normal path it is durable before the proof is sent upstream. Coinbase, transaction body and message objects are content-addressed and deduplicated. If a sync call makes no progress for 250 ms, the existing ingress thread adopts an immutable full-body copy and forwards the exact body before the proof while the storage call continues; no per-proof thread is created and miner success remains durability-gated. The unresolved proof/index cap is derived from configured clients, target shares per minute and the 16-minute retention horizon, with a 65,536 minimum and 4,194,304 hard ceiling. The 16,384-client house configuration reserves 524,288 identities. The spool permits 8 GiB while keeping 1 GiB of filesystem space in reserve. No unresolved proof is evicted. If capacity, free space, integrity or durability fails, the gateway stops new work and does not report the affected share as accepted without known durable ownership. Before publishing a job, the gateway also reserves one maximum-size reference proof for every configured Stratum worker thread (at most 64). The exact bound is 66,888 logical bytes per proof; filesystem block rounding, three files per proof, all 256 shard directories and one atomic temporary file are included, with an 8 MiB minimum physical reserve. Startup fails if the configured hard caps cannot cover that admitted set. If byte or inode headroom later reaches this watermark, the gateway stops publishing jobs and accepting connections, revokes existing miner sockets, and waits for every already-admitted submit to finish its durable KAP5 write. Its Prime connection and durable replay remain online. Override the limits only with `KACHIE_DATUM_ABW_SPOOL_MAX_PROOFS`, `KACHIE_DATUM_ABW_SPOOL_MAX_BYTES`, and `KACHIE_DATUM_ABW_SPOOL_FREE_RESERVE`; lowering them below the startup reserve is rejected. Disk I/O failure, filesystem-capacity query failure, and inode exhaustion use the same miner-drain path. Durable restart/refill replay is proof-first and does not expand or proactively send KAT1. Prime uses its durable registered body, or uniformly requests the exact missing body with authenticated `0x15` before classification. That request opens a 20-second exact-transfer idle timer and a hard five-minute limit anchored to the proof send; only monotonic bytes from that direct encrypted frame or authenticated in-order bulk acknowledgements rebase the idle timer. Completion starts fresh, independent 30-second credit and ownership timers. The five-second body-progress limit applies only to the exceptional undurable RAM emergency path. Any timeout reconnects and retains KAP5; unrelated traffic cannot extend these bounds. Prime's outcome-blind disclosure epoch remains fixed at two seconds and does not delay a terminal once the exact body is ready. The gateway forwards at most 256 protected proofs without their exact terminal pair. Prime's two-second external disclosure epoch makes this a 128-proof/s live window. Further KAP5 records remain in a deterministic disk-backed backlog; fresh protected intake and job publication pause until paged proof-first replay drains below the low-water mark. This easily covers the packaged 1,024-client default. The 16,384-client house deployment relies on the backlog gate during a burst and on its trusted source's immediate terminal path; compact replay, durable capture and terminal turnover are tested above 600 proofs per second. KAP5 retains typed terminal facts across restart. The loader accepts legacy KAP4 records for migration, but the gateway writes only KAP5 records now. ## XOR protected mining Upgrade the gateway when connecting to Kachie's protected pool: this version requires the Kachie DATUM v3 extension and has no unprotected or solo fallback. It waits for an assignment, a Prime-signed complete payout split, and Prime's durable acknowledgement of the exact transaction body before issuing work. Your node still chooses the transactions; every ASIC uses the full coinbase. The fee, reward window, and direct coinbase payouts are unchanged. The gateway writes that exact transaction body once as a content-addressed `KAT1` object before registration and pins it through acknowledgement, job publication and local template retirement. Unresolved `KAP5` proofs add their own references, so late proofs keep the body after the live job retires. Normal shares carry only the compact body hash instead of copying the full body. If a new body plus the configured ingress reserve will not fit, publication stops before any miner can receive the job; proof churn and terminal cleanup cannot evict a live pin. Prime sends only a commitment and never returns an assignment key as gateway feedback. That prevents direct inspection of whether an unsurrendered ordinary share also wins a block. Terminal decisions and public chain outcomes still form the adaptive oracle described below. An accepted v2 block necessarily publishes its retired generation key in the extended header. These are mining-assignment keys, not wallet private keys. Prime verifies the exact signed payout and registered block body, and reports acceptance only after durable accounting. An empty reward window uses Prime's explicitly signed finder rule. See [protocol and recovery details](KACHIE-XOR.md). The active assignment changes when the parent changes, after a winning block, or when its bounded negative-result exposure is consumed. This limit applies to both Traditional and external DATUM work because the public chain can reveal a negative result even when the gateway itself is trusted. A same-parent rotation publishes a new small protected-job wrapper without disconnecting ASICs; late proofs from the retired wrapper remain deliverable. Routine GBT refreshes reuse one pretrimmed, immutable transaction body. A protected body is never recycled for the same parent: the gateway uses another slot in its 32-body ring or stops publication. A later, different parent may supersede an old ring slot, at which point that old live job fails closed. Proofs already admitted to KAP5 remain self-contained; an ASIC submission which arrives only after its old body has left this bounded ring cannot be reconstructed. Within that retained-body horizon, the generation hash index and 65,536-wrapper cap stop new publication before overwriting an admitted wrapper. Old work remains bound to its random assignment ID and key hash after a routing slot is reused. The gateway's resume token and unresolved `KAP5` proofs survive process restart in the private spool and can recover a lost terminal receipt. When the local node reports a possible new tip, or submitted work is already known to use an old parent, the gateway removes ordinary local-credit eligibility but still durably forwards the proof. Prime independently checks the signed generation and registered body. For an external DATUM identity it returns the ordinary exact share decision plus the exact `A7` generation/body-ownership release. It never sends that external identity a candidate label, an assignment key as gateway feedback, completed-block `0x98`, or candidate-specific `A5`. If native-node submission is ambiguous, Prime sends no terminal and fences same-parent work until exact resolution or parent departure. KAP5 remains authoritative across reconnect. A candidate-labeled `A4`/`A5` transcript is never used for external DATUM; `A4` remains a legacy migration command which this gateway refuses while mandatory protection is active. A routine tip pause keeps miner sockets open so bytes already in TCP or the parser are preserved before the clean replacement job is sent on the same connection. Start the gateway with `run-kachie.sh`; it configures the private proof spool and recovery state. A proof is removed only after both Prime's durable terminal share receipt and the exact `A7` generation/raw-hash ownership release; either may arrive first. The tested `0x98`/`A5` completed-block relay remains available only for the authenticated pool-operated Traditional house gateway. Prime owns and starts submitting that block before asking the house gateway for redundant local node relay. External DATUM does not receive that transcript. Storage exhaustion stops fresh protected work and never silently drops an unresolved proof. The miner-facing receipt wait is asynchronous and lasts 150 seconds. It covers the ordinary 30-second terminal epoch, reconnect jitter, the 30-second TCP connect bound, a successor terminal epoch, and handshake/scheduling margin. An exact missing-body recovery may legitimately outlive this local wait because it has a 20-second idle and five-minute absolute bound. If resolution is still unavailable, or all 256 local waiter slots are occupied, the gateway returns `upstream-pending`, cancels only local vardiff/statistics credit, and keeps KAP5 replay active. It does not count this as a rejected share. Stratum v1 has no standard pending result, so an ASIC UI may still display it as rejected even if Prime credits the proof later. Very fast miners have their share difficulty capped to preserve sixteen hidden target bits, and consequently submit shares more often. If even the pool's minimum difficulty cannot preserve those bits, the gateway warns and the pool refuses unsafe work on every non-regtest chain. The XOR assignment design makes selective recognition costly, but observable results under one fixed mask and public chain outcomes still form an adaptive oracle. Prime counts unique negative exposure by verified work, retires the generation at one 256th of expected network work, and charges an under-floor probe the entire remaining budget before replying. Even so, an optimized sampler can trade roughly 288 physical accepted proofs for one selectively credited proof under the reviewed model. This is an economic limit, not proof that withholding is impossible. It cannot prevent all-share or random-share dropping. After the first accepted block is public, a malicious gateway which already retained a second same-parent winner can identify and broadcast that sibling, causing a same-height race or orphan; its signed coinbase cannot redirect another miner's reward. XOR also cannot prevent downtime, denial of service, stale-chain rejection, compromised hosts, or simultaneous disk/network/process failure before either side owns a new proof. Pool: `stratum.kachiepool.com:28915` Public key: `4b7e6aad450d54b6607a431040281c968eed18c3638617cab5969a8fc3c45507a37e2034baf3b83f59c9725dbf3eeb78ab08edc198e4e5a924f4ee6d7e3fa167` The Kachie build's compiled defaults, `--example-conf` output, bundled example, and `kachie-setup.py` all pin this host, port, and public key. An existing configuration that explicitly names another pool is left unchanged. The gateway never fetches a pool key automatically: whenever `datum.pool_host` is set, `datum.pool_pubkey` must be exactly 128 hexadecimal digits. `--validate-config` refuses an empty or malformed key, and a `mining.pool_address` that is not a valid Bitcoin address, before any proof spool is created.