Run your own pool: this is the operator page. If you just want to point an ASIC and mine, use the join page instead.
Current version: v5.0.9 The version the network runs. Install only v5.0.9, using the steps below. The syscoind file on the downloads page has SHA256 436dba8c3bd7983887cc3d14945143ff13ea8db95ffaa1e1c28de8a7337f2422 Check your download against it (step 3). The files on that page are the exact binaries running on the network's own nodes.
AuxPoW chain ID is 29 since block 88,000 (it was 16 before; the change took effect on 2026-10-18). Blocks below 88,000 used chain ID 16. Blocks from 88,000 up must carry chain ID 29, and software from before the fork rejects them. Since this change, SHIT and SYS can share one merge-mining tree under Bitcoin as the real parent.
Do not mix up the two chain IDs: the AuxPoW chain ID is 29. The NEVM chain ID is 20026. They are different numbers used for different things.
If you just want to mine ShitcoinBtc with your pool, run this on a fresh
Ubuntu 22.04/24.04 box (2 GB RAM, 1 vCPU, 25 GB SSD minimum) and skip to
section 8, then complete the REQUIRED checks in section 8A before you point real hash at it:
curl -sSL https://shitcoinbtc.xyz/pool-setup.sh | sudo bash -s -- --payout shit1qYOURPAYOUTADDRESS
That installs the node, the NEVM helper, restores the fast-sync snapshot, creates a dedicated pool wallet on the node (step 7 of the script, so its acceptance test has a wallet to call), and starts our merged-mining stratum proxy. Point any stock stratum miner (cpuminer, cgminer, ...) at 127.0.0.1:3333 on this box and you are mining. The proxy listens on localhost by default: if your miners run on other machines, set LISTEN_HOST in proxy.conf to this box's LAN address and read the stratum security notes below first, never expose raw stratum to the internet. Your pool software needs no merged-mining support -- the proxy builds every block's AuxPoW for you (see "How the proxy works" below). Block rewards pay to the --payout address you gave.
No shit1... address yet? Get one before you run the command: from any ShitcoinBtc wallet you already use, or from the web wallet. The script cannot invent one for you, and it exits without --payout. (Once a node is running you can also make one there: createwallet then getnewaddress, section 7, but the fast path needs the address up front.)
Prefer to do it by hand, or integrating with existing pool software? Continue
below.
ShitcoinBtc is merge-mined: every block must carry a valid AuxPoW. Normally
your pool software would have to build that itself. The proxy removes that
burden:
your payout address, mempool transactions, and the NEVM commitment.
like mining any normal sha256d coin -- no special software, no config
changes beyond the pool URL.
share meets the network target it assembles the AuxPoW block and submits it
to your node.
What mining through the proxy earns: the proxy builds a synthetic parent block locally. That parent is not a real Bitcoin block and is never broadcast to the Bitcoin network, so mining through the proxy earns SHIT only. If your pool software can build AuxPoW itself, use the daemon's native getauxblock path against your own Bitcoin node instead: the parent there is a real Bitcoin block, so the same work earns BTC + SHIT.
The proxy is a single Python file, no exotic dependencies. Everything for a manual install is on the downloads page, you need all three of these files:
https://shitcoinbtc.xyz/downloads/shitcoin-stratum-proxy.pyhttps://shitcoinbtc.xyz/downloads/proxy.conf.examplehttps://shitcoinbtc.xyz/downloads/shitcoin-stratum-proxy.service.exampleIt never touches your wallet keys -- it only needs the node's RPC (localhost) and your payout *address*.
Stratum proxy and the fork: read this if you set up before block 88,000: the current proxy stamps AuxPoW chain ID 29 on new blocks and carries the spool / retry / alarm submission protection in section 8A. A proxy copy from before the fork stamps chain ID 16, and blocks built with it are rejected at the current height; a copy without the 2026-10-26 submission protection can lose a found block silently. Get the current file from the link above and check it before you run it:
sha256sum shitcoin-stratum-proxy.py
# must print: b561c6ef146178def8d729c29860a8c9a31c038175e045674f951b53c0d7a39e
If your hash is different, your copy is old or altered. Download it again from the link above. pool-setup.sh checks this hash for you and stops if it does not match.
Stratum security notes (read before you open ports):
unencrypted -- anyone on the path can rewrite them and steal payouts. Put
stunnel/VPN in front of your stratum port, or keep miners on a private
network. Never expose the raw stratum port to the internet.
checksum/signature. A trojaned build can skim shares or redirect coinbase
outputs.
claiming to be us sends you files, it is a scam -- get everything from the
links in this guide only.
Measured on our live node (fully synced, height ~50,700):
| Minimum | Recommended | |
| RAM | 2 GB | 4 GB |
| CPU | 1 vCPU | 2 vCPU |
| Disk | 25 GB SSD | 40 GB SSD |
| OS | Ubuntu 22.04 / 24.04 x86_64 | same |
Why these numbers: a synced node uses about 500 MB RAM total (syscoind ~360 MB, sysgeth ~50 MB) and under 1 GB disk (chain data ~85 MB at 50k blocks, it grows slowly). But the initial sync is the peak That is where a small box chokes. One of our pool operators stalled permanently at block 48,000 on an undersized machine because the helper program ran out of memory mid-sync. Give it 2 GB and you avoid that entirely.
Open TCP port 8369 in your firewall (P2P). Keep RPC (8370) on localhost only.
Manual path: install the system packages first. The fast-path script does this for you; by hand you must do it yourself, before anything below, or the binaries will not start and the proxy will die on import zmq. This is the same package list the script installs:
sudo apt-get update
sudo apt-get install -y wget unzip python3 python3-zmq openssl curl ca-certificates libzmq5 libevent-2.1-7 libsqlite3-0 libgmp10 libssl3
Syncing from zero takes hours and is where small machines die. Skip most of it with the snapshot, but unpack it as the shitcoin user, into the node's real datadir /home/shitcoin/.syscoin, not into your own login user's home. The node runs as user shitcoin (steps 5–6); a snapshot unpacked into the .syscoin folder in your own home directory is never seen by it, and the node then full-syncs for hours while you believe you restored it. So first create the user and datadir (the first two commands of step 5), then:
cd /tmp
# grab the latest snapshot (the -latest file is always the newest build;
# there is no directory listing page, so use the exact filename below)
wget https://shitcoinbtc.xyz/snapshots/shitcoin-chain-snapshot-latest.tar.gz
wget https://shitcoinbtc.xyz/snapshots/shitcoin-chain-snapshot-latest.tar.gz.sha256
sha256sum -c shitcoin-chain-snapshot-latest.tar.gz.sha256 # must say OK
# unpack AS user shitcoin INTO /home/shitcoin/.syscoin (handles both the
# dated-folder layout of older snapshots and the flat layout of newer ones):
sudo -u shitcoin bash -c 'cd /home/shitcoin/.syscoin && if tar tzf /tmp/shitcoin-chain-snapshot-latest.tar.gz | head -1 | grep -q "^shitcoin-chain-snapshot-"; then tar xzf /tmp/shitcoin-chain-snapshot-latest.tar.gz --strip-components=1; else tar xzf /tmp/shitcoin-chain-snapshot-latest.tar.gz; fi'
sudo chown -R shitcoin:shitcoin /home/shitcoin/.syscoin
How current is the snapshot, honestly: the snapshot served today was built on 2026-10-18 at height 88,386. The chain tip was about 110,000 when this guide was last updated (2026-10-26), so the snapshot puts you roughly 22,000 blocks behind It saves most of the sync, it does not drop you "near the tip", and syncing the remainder still takes real time. Plan for that; do not debug a healthy catch-up sync as a failure. One honesty note on the check above: the snapshot's .sha256 file is served from the same site as the snapshot itself, so a passing check proves the download arrived intact, it is not an independent signature from a second source. If the snapshots page has no file yet, do the full sync in step 6 and be patient.
Install the current version, v5.0.9. The downloads page ships syscoind and syscoin-cli as single files: there is no tarball. Do not install the old v1.0.0 package: it is from before the fork and cannot follow the chain from block 88,000 up.
cd /tmp
wget https://shitcoinbtc.xyz/downloads/syscoind
wget https://shitcoinbtc.xyz/downloads/syscoin-cli
wget https://shitcoinbtc.xyz/downloads/SHA256SUMS.txt
# SHA256SUMS.txt also lists sysgeth (step 4 installs it) — check the two files downloaded here:
grep -E ' (syscoind|syscoin-cli)$' SHA256SUMS.txt | sha256sum -c - # both must say OK
sha256sum syscoind # must print: 436dba8c3bd7983887cc3d14945143ff13ea8db95ffaa1e1c28de8a7337f2422
sudo install -m 755 syscoind /usr/local/bin/
sudo install -m 755 syscoin-cli /usr/local/bin/
syscoind --version # should print v5.0.9
sysgeth builds the NEVM block templates your pool needs for mining. With v5.0.9 the daemon manages sysgeth itself: at startup syscoind stops any running sysgeth, then launches the sysgeth it finds beside syscoind (in /usr/local/bin, next to the syscoind binary). Do not run sysgeth as a separate systemd service with this build. Just put the binary in place:
cd /tmp
wget https://github.com/ShitcoinBTC/sysgeth/releases/download/v1.0.0/sysgeth-linux-x86_64.zip
unzip -o sysgeth-linux-x86_64.zip
md5sum sysgeth # must print: 95601fd2e3f0829521bd8206df1f7b4b
sudo install -m 755 sysgeth /usr/local/bin/sysgeth
Note on the version number: sysgeth is a separate program from the node and has its own release numbers. This build is the one running on our live nodes today, the MD5 check above proves your copy is that build.
The daemon passes --syscoin and --nevmpub to sysgeth itself, driven by syscoin.conf (step 5): zmqpubnevm=tcp://127.0.0.1:9377 sets the --nevmpub address, and the gethcommandline lines pass the rest. Without zmqpubnevm, NEVM blocks fail with nevm-data-not-found and getblocktemplate / getauxblock fail with nevm-data-not-found. The NEVM chain ID is 20026: a different number from the AuxPoW chain ID 29.
Required: --syscoin.statebootstrap.disable must be one of the gethcommandline lines in syscoin.conf. Without it, the spawned sysgeth downloads the Syscoin mainnet state bootstrap (about 1 GB) and never becomes ready.
Do not create a sysgeth service. If an older (5.0.7-era) install left one behind, stop and disable it so it does not compete with the daemon-managed sysgeth:
sudo systemctl disable --now sysgeth 2>/dev/null || true
Do not install the old /usr/local/bin/sysgeth wrapper script that some early setups used: the real sysgeth binary itself must sit beside syscoind in /usr/local/bin.
If you followed step 2, the shitcoin user and /home/shitcoin/.syscoin already exist: useradd will say the user exists; that is fine, continue.
sudo useradd -m -s /bin/bash shitcoin
sudo mkdir -p /home/shitcoin/.syscoin
RPCPASS=$(openssl rand -hex 24)
sudo tee /home/shitcoin/.syscoin/syscoin.conf > /dev/null <<EOF
server=1
daemon=1
txindex=1
port=8369
rpcport=8370
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpcuser=shitcoinrpc
rpcpassword=$RPCPASS
zmqpubnevm=tcp://127.0.0.1:9377
gethcommandline=--syscoin.statebootstrap.disable
gethcommandline=--nodiscover
gethcommandline=--maxpeers=0
gethcommandline=--http
gethcommandline=--http.addr=127.0.0.1
gethcommandline=--http.port=8545
gethcommandline=--http.api=eth,net,web3
maxconnections=40
dbcache=512
addnode=77.42.74.252
addnode=170.101.111.196
addnode=216.106.186.238
EOF
sudo chown -R shitcoin:shitcoin /home/shitcoin/.syscoin
sudo chmod 600 /home/shitcoin/.syscoin/syscoin.conf
echo "RPC password: $RPCPASS (save this)"
The three addnode lines are our seed nodes (Helsinki, Frankfurt, Seattle).
About blocknotify: tip-change refresh wiring is REQUIRED on every pool path (section 8A), but the exact line depends on your path, so it is not in the base config above. The stratum proxy refreshes itself with its built-in 5-second tip poll and takes no blocknotify line: do not add one pointing at it. Yiimp + adapter and your-own-software setups add exactly one blocknotify= line, given verbatim in sections 8 and 8A. syscoind accepts only one blocknotify command: if two consumers need a poke, chain them with ; in that single line, as section 8A shows, a second blocknotify= line silently replaces the first.
sudo tee /etc/systemd/system/syscoind.service > /dev/null <<'EOF'
[Unit]
Description=ShitcoinBtc node
After=network.target
[Service]
User=shitcoin
ExecStart=/usr/local/bin/syscoind -datadir=/home/shitcoin/.syscoin -conf=/home/shitcoin/.syscoin/syscoin.conf
Restart=always
RestartSec=30
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now syscoind
# block height (compare to the network height on https://shitcoinbtc.xyz)
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getblockcount
# sysgeth must be running — the daemon launches it itself (step 4)
ps aux | grep '[s]ysgeth'
# peer count (should climb to 8+ within minutes)
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getconnectioncount
# no errors in the log
sudo -u shitcoin tail -20 /home/shitcoin/.syscoin/debug.log
Final acceptance test: setup is NOT done until this passes. Syncing is not the finish line: a node can be fully synced with 8+ peers and still be unable to build a single block. Once the node is synced, ask it for merge-mining work. There are two equal forms of this test: either one passing is acceptance:
Form 1: getauxblock (needs a wallet). Parameterless getauxblock is a wallet RPC. The exact rule: it works when exactly one wallet is loaded on the daemon, or when you name the wallet with -rpcwallet=<wallet> on the CLI call. Create a dedicated wallet for this (the fast-path script already created one named pool for you):
# one-time: create the dedicated acceptance/pool wallet
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin createwallet pool
# the acceptance test itself, naming that wallet explicitly:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin -rpcwallet=pool getauxblock
Form 2: createauxblock <payout> (wallet-free, equal acceptance path). This form needs no wallet at all:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin createauxblock shit1qYOURPAYOUTADDRESS
Either form's answer must be a block template (JSON) containing "chainid": 29. That, and only that, proves your node can build blocks on the current chain. Failure branches, in the order you will actually hit them:
getauxblock refuses until it completes. Check sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin mnsync status, wait until it reports synced, then run the test again.nevm-data-not-found, the NEVM block is missing or wrong in syscoin.conf Go back to step 5, check the zmqpubnevm and gethcommandline lines, and restart syscoind.-19 on form 1), you have zero or 2+ wallets loaded and named none: create the dedicated wallet above, or re-run with -rpcwallet=<wallet> Or simply use wallet-free form 2. The same wallet rule binds any pool software that calls parameterless getauxblock directly (see Option C, Route B).Stuck at this test? The contact at the bottom of this page is where a stuck newcomer should ask, include your height, peer count, mnsync status output, and the exact error the test returned.
With the snapshot you still have the catch-up sync described in step 2. Full sync from zero takes several hours, leave it alone while it works.
Option A: stratum proxy (recommended, no merged-mining support needed).
If you ran pool-setup.sh, this is already done The script downloads the proxy, checks its SHA256 (section "How the proxy works"), and places every file at exactly the paths below. Skip to the PAYOUT_ADDRESS note and section 8A.
Manual install: every step, in order. The service file expects the proxy at /opt/shitcoin-stratum-proxy/shitcoin-stratum-proxy.py and its config at /etc/shitcoin-stratum-proxy/proxy.conf; use exactly those paths or the service will not start:
# 1. download all three files (URLs in "How the proxy works" above)
cd /tmp
wget https://shitcoinbtc.xyz/downloads/shitcoin-stratum-proxy.py
wget https://shitcoinbtc.xyz/downloads/proxy.conf.example
wget https://shitcoinbtc.xyz/downloads/shitcoin-stratum-proxy.service.example
sha256sum shitcoin-stratum-proxy.py # must print b561c6ef146178def8d729c29860a8c9a31c038175e045674f951b53c0d7a39e
# 2. create the directories the layout needs
sudo install -d -m 0755 /opt/shitcoin-stratum-proxy
sudo install -d -m 0755 /etc/shitcoin-stratum-proxy
sudo install -d -o shitcoin -g shitcoin -m 0755 /var/log/shitcoin-stratum-proxy
sudo install -d -o shitcoin -g shitcoin -m 0700 /var/lib/shitcoin-stratum-proxy/spool
# 3. place the files at the exact paths the service uses
sudo install -m 0755 shitcoin-stratum-proxy.py /opt/shitcoin-stratum-proxy/shitcoin-stratum-proxy.py
sudo cp proxy.conf.example /etc/shitcoin-stratum-proxy/proxy.conf
sudo cp shitcoin-stratum-proxy.service.example /etc/systemd/system/shitcoin-stratum-proxy.service
# 4. set your payout address (the one required edit)
sudo nano /etc/shitcoin-stratum-proxy/proxy.conf # set PAYOUT_ADDRESS=shit1qYOUR...
sudo chown shitcoin:shitcoin /etc/shitcoin-stratum-proxy/proxy.conf
sudo chmod 600 /etc/shitcoin-stratum-proxy/proxy.conf
# 5. start it
sudo systemctl daemon-reload
sudo systemctl enable --now shitcoin-stratum-proxy
journalctl -u shitcoin-stratum-proxy -f # watch shares/blocks
The shipped proxy.conf.example already carries the correct submission-protection values: SPOOL_DIR=/var/lib/shitcoin-stratum-proxy/spool, SUBMIT_RETRIES=3, SUBMIT_BACKOFF_SECS=2, SPOOL_REPLAY_SECS=60, ALARM_CMD= (empty = no hook; the log/stderr/ALARM.txt alarm is always on): leave them as they are and complete section 8A's checks. The spool directory must stay owned by the service user (shitcoin) with mode 0700: anyone who can write it can forge or delete found-block entries and alarms. The proxy takes its payout from PAYOUT_ADDRESS in proxy.conf it has no --payout command-line flag; --payout belongs to pool-setup.sh, which writes PAYOUT_ADDRESS for you.
Then point any stock stratum miner at 127.0.0.1:3333 (or, if miners are remote, set LISTEN_HOST in proxy.conf to your box's address and firewall the port to your miners only, see the stratum security notes). That is the whole integration.
Option B: your own pool software via node RPC. This is the hardest path. Read all of it before you start: every warning below is a way an outside pool has already hashed happily while producing nothing, or lost a block it found.
WARNING: do NOT use getblocktemplate. On this daemon, getblocktemplate returns no AuxPoW data at all No chain ID, no aux target, nothing to commit into a Bitcoin coinbase. A pool built on getblocktemplate will hash forever and can never produce a valid SHIT block, and nothing will error to tell you so. You must drive the AuxPoW RPCs below instead.
A real Bitcoin parent chain is required. ShitcoinBtc is merge-mined only: every SHIT block must carry valid AuxPoW anchored in a real Bitcoin block header whose coinbase commits to the SHIT template. That means your own synced Bitcoin Core node to build parents against (the stratum proxy in Option A skips this only because it builds a synthetic parent and earns SHIT only). Standalone SHIT block templates are rejected by consensus.
The integration contract:
createauxblock <your payout address> wallet-free, the recommended form, or parameterless getauxblock, which is a wallet RPC and works only with exactly one wallet loaded on the daemon, or with -rpcwallet=<wallet file> naming one on every call. Zero or 2+ wallets with no -rpcwallet fails with -19."chainid": 29. If it does not, stop, you are on the wrong daemon/build (see the section 7 acceptance test).target vs _target: the daemon returns the submit target only as _target. Use _target verbatim: byte for byte exactly as sent, never reversed, never byte-swapped. A field named target does not exist in the daemon's reply; it exists only when the yiimp adapter (Option C) adds it, and the adapter adds it by copying _target verbatim. Software that reads a missing target compares against empty/zero data and never submits: silently.submitauxblock <hash> <auxpow>, with the hash from the template the AuxPoW was built for. Acceptance is the reply result: true exactly. result: false, or any error reply, is a failure, never a success.coinbasescript carries the AuxPoW tag anchor (tip minus 5, rounded down to a multiple of 10), and that anchor is consensus-checked (bad-auxpow-tag / bad-auxpow-ref). The script therefore rotates roughly every 10 blocks. Re-fetch createauxblock at least every 10 blocks and build every parent coinbase from the current template's script, a script cached across a rotation boundary produces consensus-rejected blocks whose submissions present as unexplained result: false failures. This rule applies on every path where your own software builds the parent coinbase (Option B, and yiimp's stratum on Option C): the adapter forwards every template call fresh and caches nothing, so the cache to audit is in your pool software, not in the shim.-8 "block hash unknown": locally; the network never sees it. Wire the daemon's blocknotify to your software's refresh, in syscoin.conf, exactly like this, and restart the daemon:
blocknotify=/path/to/your-refresh-command %s
%s is replaced by the new block hash. Your refresh must drop the cached aux template and fetch a fresh one. Test it: after the next block lands, your software must be working from the new tip, not the old one.If your software cannot do merged mining at all, use Option A instead, that is what the proxy is for.
Option C: yiimp, using the yiimp adapter package.
If your pool runs yiimp, do not point vanilla yiimp straight at the node. Vanilla yiimp and the v5.0.9 daemon nearly agree on AuxPoW, but three mismatches silently stop a yiimp pool from ever producing a SHIT block: yiimp reads a target field as its submit trigger, while the daemon returns that value only as _target, so yiimp ends up comparing against nothing; yiimp calls parameterless getauxblock, a wallet RPC that fails with -19 whenever the daemon does not have exactly one wallet loaded; and the daemon clears its aux-template cache on every tip change (about every 30 seconds), so a submission for a template from a previous tip fails with -8 "block hash unknown". The adapter package fixes all three. Download it here: https://shitcoinbtc.xyz/downloads/shit-yiimp-adapter-bundle.zip Unpack it and follow its README. Patched yiimp on Route B below is the exception to the first sentence: it does point straight at the daemon, after the patches below. Your node must already pass the acceptance test in section 7 before either route below will work, use the createauxblock <your payout address> form of that test if your daemon runs wallet-free, because plain getauxblock needs exactly one wallet loaded.
Verify the bundle before you unpack it. Download SHA256SUMS.txt from the downloads page separately and check the zip against it: sha256sum shit-yiimp-adapter-bundle.zip must match the shit-yiimp-adapter-bundle.zip entry in https://shitcoinbtc.xyz/downloads/SHA256SUMS.txt. The expected hash for the current bundle is 970d0bc324e09cceb8a49383d76015a68ce7e27971a23bb8bf28f4322d34e2e0 (the RT-2 republication of 2026-10-27, freeze v2; see the kit CHANGELOG for the bundle history: R2/R3 build fc6e4b4e before it, f8bdee77 before that). Inside that bundle, the adapter itself is shit-yiimp-adapter.py sha256 6680e7ad430adea7d0fb9387e7ba2e57a850edfb4a040e1b1c07113e2a339fef (inside bundle 970d0bc324e09cceb8a49383d76015a68ce7e27971a23bb8bf28f4322d34e2e0): kit hash, this citation pair, and the served file must all agree at deploy time. Do not trust the SHA256SUMS file inside the zip by itself: a sums file shipped inside the thing it claims to verify proves nothing about the zip you downloaded; the check that counts is against the sums file served separately on the downloads page.
Pick one of the two routes in the package:
Route A: the shim (recommended, no yiimp rebuild). The package's shit-yiimp-adapter.py is the shim: a small adapter that sits between yiimp and the daemon. It is not the stratum proxy in Option A, that proxy is a different program, for pool software that cannot do merged mining. Copy adapter.conf.example to adapter.conf and set payout_address to your pool's SHIT payout address: the shim will not start without it, because every template it asks the daemon for pays that address. Then change only the SHIT coin's RPC connection in yiimp: point it at the shim (default 127.0.0.1:19332) instead of the daemon (default 127.0.0.1:8370). The shim adds target to every aux-template reply, copied from _target exactly as the daemon sent it, byte for byte, do not reverse it. It also translates yiimp's getauxblock calls into wallet-free forms: a call with no arguments becomes createauxblock with your payout address, and a call carrying a block hash and AuxPoW becomes submitauxblock. Everything else is forwarded to the daemon, including the daemon's own errors (for example nevm-data-not-found), except two kinds of calls the shim handles itself without contacting the daemon: dangerous, wallet and stop methods (such as stop, spend methods, and anything starting with wallet), which it blocks locally with -32601, and getauxblock calls in any other shape, which it rejects locally with -32602.
Route A submission protection: set these in adapter.conf (these are the adapter's real key names; do not invent others). First create its spool directory, before the adapter's first start, owned by the user the adapter service runs as, mode 0700 The spool and its alarm marker are the only durable evidence of a found block:
sudo install -d -m 0700 -o shitcoin /var/lib/shit-yiimp-adapter/spool
sudo install -d -m 0755 /var/log/shit-yiimp-adapter
# in adapter.conf, [adapter] section:
spool_dir = /var/lib/shit-yiimp-adapter/spool
submit_retry_attempts = 3
submit_retry_delay_seconds = 1
submit_retry_refresh = true
spool_replay_interval_seconds = 300
# alarm_file defaults to <spool_dir>/ALARM_SUBMISSION_FAILED when unset
# Optional (freeze v2.3, R3): a second, independent submit daemon.
# When the primary daemon does not reach confirmed acceptance, the
# same (hash, auxpow) pair is submitted here too -- first confirmed
# acceptance wins. Leave unset for single-daemon behaviour.
#secondary_daemon_url = http://127.0.0.1:18370/
Second submit daemon (freeze v2.3, R3). With secondary_daemon_url set, a found block is not hostage to one daemon: a wedged, peerless or NEVM-locked primary can no longer eat it alone. The one exception is a primary error reply carrying a validation verdict (for example -26 bad-prevblk): that pair is invalid on any daemon, so it is not sprayed at the secondary. The stratum proxy has the same option as SUBMIT_FALLBACK_RPC_URL in proxy.conf (empty by default; same deterministic-rejection exception for BIP22 reject reasons).
Warning: submit_retry_refresh is a boolean — true or false, never a number. Writing a number there instead of true reads as false and silently disables the refresh between retries (that exact mistake was published in an earlier draft of this guide; do not repeat it). With the values above, a found block is spooled to disk before submission, retried a bounded number of times, replayed on startup and every 300 seconds, and alarmed on final failure, see section 8A.
For Route A, blocknotify is REQUIRED. Add the adapter package's syscoin.conf.snippet line to syscoin.conf and restart the daemon. The snippet's recommended line, verbatim (create the log directory first, as above, the line logs its output and its failures instead of swallowing them):
blocknotify=curl -sS --max-time 5 "http://127.0.0.1:19332/notify?hash=%s" >>/var/log/shit-yiimp-adapter/blocknotify.log 2>&1 || echo "adapter blocknotify FAILED for block %s (curl exit $?)" >>/var/log/shit-yiimp-adapter/blocknotify.log
(The snippet's Option B touches a signal file instead and requires notify_file = /tmp/shit-yiimp-adapter.tip in adapter.conf. Use one form, not both.)
Critical: the adapter poke above refreshes only the adapter It records the tip change in the adapter. It does not refresh yiimp: yiimp will keep serving stale work until its own refresh notices the new tip. Yiimp ALSO needs its own blocknotify / work-refresh wiring (yiimp's own blocknotify helper, per your yiimp install). Because syscoind takes only one blocknotify command, chain both in the single line: adapter poke and yiimp's own notify, with ; between them, exactly as the combined example at the bottom of the snippet shows. Replacing yiimp's own line with only the adapter poke leaves yiimp stale; wiring only yiimp's line leaves the adapter uninformed. A setup missing either half is not finished, see section 8A.
Route B: patch yiimp and rebuild. The package's yiimp-patch/ folder carries the same fixes as changes to yiimp's stratum source, for a checkout of tpruvot/yiimp, branch next And for forks whose stratum/coind_template.cpp still contains the stock coind_getauxblock. 0001-stratum-auxblock-underscore-target.patch teaches yiimp to read _target (stored exactly as sent, never reversed). Patch 0001 alone does not remove the wallet requirement: the parameterless getauxblock call still runs, so the daemon must have exactly one wallet loaded, or be started with -rpcwallet=<wallet file>, for that call to work. The optional 0002-stratum-createauxblock-variant.patch, applied on top of the first, makes only the template fetch wallet-free: when the SHIT coin's master_wallet payout address in yiimp (coins.master_wallet) is valid, the fetch becomes createauxblock with that address, and on any failure it falls back to the stock getauxblock call. Verify the effective payout address in the stratum log and with createauxblock by hand before relying on it, because yiimp can replace master_wallet at start-up. Submission does not change: it stays the stock getauxblock(hash, auxpow) call. Apply them in your yiimp checkout with patch -p1 from the stratum directory, in the order the patch folder's own README sets out (git apply works identically), then rebuild stratum with make (also make -C ../blocknotify if needed). Route A needs no rebuild and closes the same three gaps, so use Route B only if you would rather carry the fix in yiimp itself.
For Route B, wire blocknotify straight to yiimp: do not use the adapter snippet, because no shim is running to poke. Use yiimp's own blocknotify helper, as the patch folder's README sets out: blocknotify=/var/stratum/blocknotify 127.0.0.1:<STRATUM_TCP_PORT> <SHIT_COIN_ID> %s in the SHIT daemon's syscoin.conf, then restart the daemon. The two placeholders, plainly: <STRATUM_TCP_PORT> is the TCP port your yiimp stratum itself listens on for the SHIT coin (the port miners connect to, for example 3333 if that is the port you configured for SHIT in yiimp); <SHIT_COIN_ID> is the numeric id of the SHIT row in yiimp's coins database table (look it up in yiimp's admin / the coins table, it is yiimp's internal ID for this coin, not a ShitcoinBtc number). A worked example with example values filled in: blocknotify=/var/stratum/blocknotify 127.0.0.1:3333 42 %s. The main package README describes the same wiring as the chained form without the adapter poke.
Whichever route you picked, verify it the way yiimp will use it. On Route A, ask for work through the shim:
curl -s http://127.0.0.1:19332/ -H 'Content-Type: application/json' \
-d '{"jsonrpc":"1.0","id":1,"method":"getauxblock","params":[]}'
The reply must contain all three of these: a "target" field, "chainid": 29, and the original "_target" field, and "target" must be identical to "_target", character for character. That result: getauxblock through the shim returning "chainid": 29 with target present. Is the proof that templates are flowing and yiimp has a real target to trigger submissions on. On Route B, make the same check against the daemon the way your patched yiimp does, and confirm the template still carries "chainid": 29 and that stratum is holding a non-empty target for SHIT, identical to the daemon's _target.
Why this section exists. On 2026-10-26 the chain stalled for about 90 minutes after a pool found the next block twice and neither find ever reached the network. The daemon clears its aux-template cache on every tip change. A submission made against the previous tip's template fails locally with -8 "block hash unknown" It never enters the network, so nobody else can see that anything went wrong. The software in that path had no retry, no spool, and no alarm, so the found blocks were lost silently and permanently. The settings below are therefore required, not optional, on every pool setup. A setup that skips any of them is not finished, even if the section 7 acceptance test passes.
The one rule about found blocks: read this before the settings. A found block is bound to the work it was found on: a proxy block to its prevhash, an AuxPoW solution to its template's hash, coinbase and prevhash. It can only ever be submitted, and re-submitted, as the identical payload: the same block hex, the same (hash, auxpow) pair. No software can move a found solution onto a fresh template, and none of ours tries. So "retry with refresh" does not mean rebuilding the solution on new work. It means: between attempts, the software re-checks the tip / template state (a cheap getblockcount probe on the proxy; a createauxblock liveness check on the adapter) to learn whether the original template is still live and whether the tip has moved, while only ever re-sending the same payload. If the tip has moved to or past your block's height, that block can never land: the height now belongs to whatever block the chain took instead. The spool and the alarm exist so that loss is loud, on disk, and impossible to miss Not so it can be undone. What you do in that case is step 4 below.
1. Tip-change refresh: REQUIRED, on every path.
blocknotify line for the proxy: it has no notify endpoint, and a blocknotify= line in syscoin.conf pointing at it would do nothing. Verify the loop is alive instead: after the next block arrives, the proxy log must show new tip <height> (was <old height>): rebuilding job. If that line never appears after a tip change, your setup is not finished, do not mine on it.blocknotify line to syscoin.conf, exactly as given in Option C, and restart the daemon. And wire yiimp's own blocknotify / work-refresh as well, chained with ; in the same single line: the adapter poke alone does not refresh yiimp, and yiimp alone does not inform the adapter. Both halves are required.blocknotify straight to yiimp's own blocknotify helper, exactly as described in Option C.blocknotify to a command that makes your software drop its cached aux template and fetch a fresh one on every tip change, in syscoin.conf:
blocknotify=/path/to/your-refresh-command %s
%s is replaced by the new block hash. Test it: after the next block, your software must be working from the new tip, not the old one.2. Spool found blocks to disk: REQUIRED. A found block is written to disk before its first submission, and the spool entry is removed only after the daemon confirms acceptance. A proxy or adapter that is off, hung, or restarted at the wrong moment cannot lose it that way. Use exactly these key names, they are the keys the shipped programs actually read; any other name is ignored silently:
# stratum proxy — in proxy.conf (pool-setup.sh and proxy.conf.example
# already write exactly this; check yours matches)
SPOOL_DIR=/var/lib/shitcoin-stratum-proxy/spool
SUBMIT_RETRIES=3
SUBMIT_BACKOFF_SECS=2
SPOOL_REPLAY_SECS=60
ALARM_CMD=
On the proxy: SUBMIT_RETRIES is the number of retries after the first attempt, always of the same payload; the spool is replayed on startup and every SPOOL_REPLAY_SECS (60 seconds). ALARM_CMD is an optional hook (see step 3): leave it empty if you have no hook; the alarm itself is not optional. Create the spool directory owned by the service user, mode 0700 (step 2 of the manual Option A install does this): sudo install -d -o shitcoin -g shitcoin -m 0700 /var/lib/shitcoin-stratum-proxy/spool. Never point the spool at /tmp A reboot must not erase a found block, and anyone who can write the spool directory can forge or delete found-block entries and alarms.
# yiimp adapter — in adapter.conf, [adapter] section (the bundle's
# adapter.conf.example already carries exactly this)
spool_dir = /var/lib/shit-yiimp-adapter/spool
submit_retry_attempts = 3
submit_retry_delay_seconds = 1
submit_retry_refresh = true
spool_replay_interval_seconds = 300
# alarm_file defaults to <spool_dir>/ALARM_SUBMISSION_FAILED when unset
On the adapter: the spool is replayed on startup and every spool_replay_interval_seconds (300 seconds), and every replay first checks each entry against the chain, so a block that landed despite a lost reply resolves itself instead of re-alarming forever. Create its directory the same way: sudo install -d -m 0700 -o <adapter-service-user> /var/lib/shit-yiimp-adapter/spool. And repeat the warning from Option C because it already bit once: submit_retry_refresh is a boolean (true/false). A numeric value reads as false and disables the refresh.
3. Submission-failure alarm: REQUIRED. Every finally-failed submission must make noise a human will notice, it must never exist only as a quiet log line nobody reads. Both programs alarm by default; your job is to confirm the alarm surface exists and test it once (for example by pointing a test copy at a stopped daemon) before you trust the setup:
*** ALARM *** SUBMISSION FAILED height=... line in the log and on stderr, an ALARM.txt file in the spool directory, and spool_pending=<N> in the proxy's 5-minute stats: log line so a stuck spool shows up in normal monitoring. ALARM_CMD in proxy.conf optionally runs a command of yours (mail/webhook script, the alarm text arrives on its stdin). The hook fires at most once per spooled block, then only again on escalation intervals of at least an hour, so a permanently dead block cannot page you every minute; a buried entry is eventually dead-lettered to a .dead file: kept as evidence, no longer submitted or alarmed. ALARM.txt is a pending list: one line per failed block; a block's line is removed when that block is later confirmed, and the file is rotated to ALARM.txt.resolved only when the last pending line clears (freeze v2.2; before v2.2 each new failure overwrote the file and hid earlier failures).ALARM_SUBMISSION_FAILED error log event, a *** ALARM *** line on stderr, an optional alarm_cmd hook in adapter.conf (alarm text on stdin; freeze v2.2), and an on-disk marker file (ALARM_SUBMISSION_FAILED in the spool directory by default) that lists all pending failed hashes. Watch also for stale_template_submit_-8, submit_result_not_true (the daemon replied without a true result: a failure, spool kept) and submit_retry_aborted_template_dead (retry stopped early because the refresh proved the template dead). Point any file monitor at the marker file.3B. NEVM wedge watchdog: REQUIRED on the installer path (kit item A3-K1, freeze v2.2). The v5.0.9 daemon can wedge its NEVM template fetch: one ZMQ timeout can poison the shared template socket, after which every template fetch fails, block production stops, and nothing self-heals, a daemon restart is the only exit until a patched daemon ships. The signature is the daemon log (debug.log) repeating Could not fetch NEVM block nevm-header-not-sent. The kit ships nevm-wedge-watchdog.py (downloads page, with a .service.example): it tails the daemon log and, after 3 consecutive signature lines, raises the alarm (journal/stderr, an ALARM_NEVM_WEDGE.txt marker, optional hook). pool-setup.sh installs and enables it automatically. The watchdog detects and alarms only, it does not fix the wedge: on its alarm, run systemctl restart syscoind and confirm getauxblock returns a template with "chainid": 29 again.
4. When a found block still cannot land: the operator procedure. Retrying is bounded (proxy: SUBMIT_RETRIES; adapter: submit_retry_attempts) and always re-sends the identical payload, aborting early once the tip is known to have moved past the block's height. If it still fails:
/var/lib/shitcoin-stratum-proxy/spool/ALARM.txt and count the spool entries. Adapter: read the ALARM_SUBMISSION_FAILED marker in its spool directory, it names every pending failed hash.syscoin-cli -datadir=/home/shitcoin/.syscoin getblockhash <height> And compare it with your found block's hash (on the adapter you can also ask getblock <your hash>). If the hash at that height is yours, your block did land (a lost reply, not a lost block); the spool entry will resolve on the next replay, do not resubmit by hand. If a different hash sits at that height, your block lost that height permanently..dead file and the alarm record on disk as the evidence, fix the cause (usually the refresh wiring in step 1) before you mine on, and go back to mining the current tip. Do not keep re-submitting the dead payload, and do not try to attach the solution to a new template, that is cryptographically impossible, not a setting you missed.One defect to know about in proxy builds before this fix: an older proxy counted a daemon-rejected submitblock as a found block and told the miner the share succeeded. A rejection is a failure, never a success: in the current proxy a rejection logs submitblock attempt ... REJECTED: ..., increments submit_failures in the stats line, and the miner is told the submission failed. Ambiguous results (inconclusive / duplicate) are only counted as accepted after the proxy confirms the block's hash with getblockhash at that height. If your proxy log shows anything else next to a submission, treat the block as not submitted and follow step 4. Only run the current proxy build (SHA256 in "How the proxy works").
Section 8A keeps a found block from being lost silently. This section is the rest of the conformance pack: the checks that prove your pool is peered, relaying, refreshing, and reporting the way this chain needs. None of them is optional. A setup that passes section 7 and section 8A but skips this section is still not finished.
Conformance at a glance: every row must pass:
| # | Check | Satisfies |
|---|---|---|
| 1 | Your daemon holds direct connections to all three seed nodes | R14(a) |
| 2 | BIP152 compact blocks are negotiated at protocol 70015 or higher, and a locally accepted block is seen by the network within seconds | R14(b) |
| 3 | yiimp pools: a monitor alarms on REJECTED lines for SHIT, the wallet rule is proven, and blocknotify is wired in both halves | R14(c) |
| 4 | You know the mempool playbook below and can run it without looking anything up | R14(d) |
| 5 | Your software treats an aux template as valid only for its tip, and "block hash unknown" as a refresh event, not a pool failure | R14(e) |
| 6 | A late block that still clears is written up as a network incident, never logged as a normal success | R14(f) |
| 7 | Template refresh is push-triggered (blocknotify or ZMQ), with no poll interval anywhere in the path above 5 seconds | R7 |
| 8 | coinbasescript is never cached across blocks and is re-fetched at least every 10 blocks | R11 |
| 9 | Every pool-critical file you run hash-matches the published sums | R14(g) |
Your pool daemon must hold direct connections to our three nodes, not just reach the network through whatever peers it happens to find. A block announced only through a slow, indirect path can sit in another node's request queue; a direct pool-to-seed connection collapses that to one hop, and if a block is still late after this check passes, relay is exonerated with evidence and the problem is provably on the submission side.
Step 5 of this guide already writes these lines for a new install. Verify all three are present in /home/shitcoin/.syscoin/syscoin.conf This is a conformance requirement for a producing pool, not just a bootstrap help:
addnode=77.42.74.252
addnode=170.101.111.196
addnode=216.106.186.238
Rules that go with them:
addnode, in the config file, so the connections are re-made after every restart. The addnode RPC command with onetry is not a substitute, it tries once and forgets.-connect= (or connect=) to these addresses instead. connect restricts your daemon to only those peers and cuts it off from the rest of the network. addnode adds direct peers on top of normal peer discovery, which is what you want.Verify after a restart (give it a few minutes to connect):
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getaddednodeinfo
The answer lists each addnode peer with a "connected" field: all three must say true. Cross-check with the live peer list:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getpeerinfo | grep '"addr"'
Each of the three seed IPs must appear there (with port :8369) as an outbound peer, alongside your normal peers. If one seed stays "connected": false, check your firewall allows outbound TCP 8369 and that the line has no typo, then restart syscoind once, do not mine on a daemon that is peered to none of them.
This daemon relays blocks with BIP152 compact blocks: a peer in high-bandwidth mode is sent the compact block immediately, without waiting to be asked, which is the fastest relay this software has. That mode is only available on connections negotiated at protocol version 70015 or higher, and a node grants high-bandwidth mode to at most 3 peers, chosen by how fast they have delivered blocks before. This is a verification, not a setting: there is no config line that forces it. You check it, you do not configure it:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getnetworkinfo
"protocolversion" must be 70015 or higher (the current daemon reports well above this). Below 70015 you are running an old or wrong daemon, go back to step 3.
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getpeerinfo | python3 -c '
import json,sys
for p in json.load(sys.stdin):
print(p.get("addr"), "version", p.get("version"),
"hb_to", p.get("bip152_hb_to"), "hb_from", p.get("bip152_hb_from"))'
Every connected peer should show "version" at 70015 or higher. After blocks have flowed (wait for the next few blocks if you just restarted), at least one of the three seed connections from 8B.1 should show hb_to or hb_from as true. A brand-new connection can legitimately show false in both directions until the daemon picks its high-bandwidth peers, recheck after about 10 minutes before treating it as a problem, and do not restart-loop trying to force it. If your build's getpeerinfo does not carry the bip152_hb_* fields, check the daemon log instead: grep -E 'cmpctblock|sendcmpct' /home/shitcoin/.syscoin/debug.log | tail should show compact-block traffic with your peers.getblockcount), and the public height on https://shitcoinbtc.xyz must follow within about a minute. Your tip moving while the public height does not move within 90 seconds is a visibility incident: keep the block's hash, the time your daemon accepted it, and your debug.log, and report it the same day through the contact at the bottom of this page. Expected gain from this whole check is seconds, not minutes, its job is to close the relay question with evidence, so a late block is never again blamed on relay by guesswork.These three items are yiimp-only, and they are on top of everything in Option C and section 8A, not instead of any of it.
(i) Alarm on REJECTED lines for the SHIT aux coin: REQUIRED. When the daemon refuses a SHIT submission (for example the -8 "block hash unknown" of section 8A), yiimp's stratum does not raise an error anywhere a human looks. It writes one line to the stratum log (debug.log in your yiimp stratum install):
SHIT <height> REJECTED
The matching success line is *** ACCEPTED SHIT <height> (+1). Point a log monitor at the rejection pattern for the SHIT coin and treat every hit as a submission-failure alarm, with the same seriousness as the adapter's ALARM_SUBMISSION_FAILED marker in section 8A:
grep -E 'SHIT [0-9]+ REJECTED' /path/to/yiimp/stratum/debug.log
On a healthy pool that count is zero. Any line it finds: follow section 8A step 4 against the chain for that height before you mine on. A pool that only watches for ACCEPTED lines will sit happily through exactly the silent loss this kit exists to prevent.
(ii) The wallet must be loaded, and a null reply is a failure, never a success. Parameterless getauxblock is a wallet RPC (Option C, Route B without patch 0002, calls it directly). With no wallet loaded it does not reliably error: it can return null, and pool code that treats a null or empty reply as a successful template fetch will report health while it has no work and no target at all. Prove the rule instead of assuming it:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin listwallets
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin -rpcwallet=pool getauxblock
listwallets must show the one dedicated pool wallet (create it as in section 7 if it does not), and the getauxblock answer must be a JSON object containing "chainid": 29, a hash, and _target. If the answer is null, an error -19, or anything without chainid 29: stop That is a failed fetch, whatever your pool software logged. The clean way out of the whole trap is the wallet-free path: Route A's adapter, or patch 0002's createauxblock form, and section 7's acceptance test in its createauxblock form proves it.
(iii) blocknotify wiring: both halves, one line. Restated as a conformance check because a half-wired version passes casual inspection: the daemon takes exactly one blocknotify= line; on Route A that one line must poke both the adapter and yiimp's own refresh, chained with ; exactly as Option C shows (the adapter poke alone does not refresh yiimp, and yiimp's line alone does not inform the adapter); on Route B the one line goes straight to yiimp's own helper, blocknotify=/var/stratum/blocknotify 127.0.0.1:<STRATUM_TCP_PORT> <SHIT_COIN_ID> %s, with the two placeholders filled from your install as Option C explains. After the next block lands, prove it worked: a template fetched after the tip change carries a different hash from one fetched before it, both at "chainid": 29, and yiimp's own log shows fresh work within a second or two of the tip, not at its next poll.
Twice in Namecoin's history, the chain this AuxPoW design comes from, pools stopped producing for days, not because of consensus, relay, or difficulty, but because a mempool condition made template creation itself error or time out, and pools waited instead of acting. In both cases the pools that recovered first did so pool-side, in minutes, by clearing or de-prioritising mempool transactions, before any daemon fix existed. Do not wait out this failure shape. Work this playbook.
Trigger: start the playbook when any of these is true:
createauxblock / getauxblock errors or times out twice in a row while getblockcount still answers and the chain is moving on the public height, orFirst rule out the two look-alikes this guide already covers: the NEVM wedge signature (section 8A step 3B, repeated Could not fetch NEVM block nevm-header-not-sent in debug.log, fix is a daemon restart) and masternode sync after a restart (section 7, wait for mnsync status to report synced). If neither matches, continue:
time sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin createauxblock shit1qYOURPAYOUTADDRESS
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getmempoolinfo
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getrawmempool | head -20
grep -E 'ERROR|template' /home/shitcoin/.syscoin/debug.log | tail -30
Note the exact error and the time. If a specific transaction is named in the error or the log, write its txid down, it is the suspect for step 2.
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin prioritisetransaction <SUSPECT_TXID> 0 -100000000
(The middle 0 is a required placeholder in this daemon's RPC; the last number is a fee delta of −1 coin in satoshis, a strong de-prioritisation.) Then re-run the createauxblock command from step 1. If templates build again, you are done: keep the txid, the error, and the time in your notes, and report it the same day through the contact at the bottom of this page, a toxic transaction that hit your mempool will hit other pools too. If a transaction only needs to be mined sooner so a dependent transaction becomes buildable, the same command with a positive delta does the opposite job.
sudo systemctl stop syscoind
sudo rm /home/shitcoin/.syscoin/mempool.dat
sudo systemctl start syscoind
# after masternode sync completes (section 7), prove templates build:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin createauxblock shit1qYOURPAYOUTADDRESS
The answer must be a template with "chainid": 29. Deleting mempool.dat while the daemon is stopped is the whole mechanism: a plain restart is not a clear, because the daemon saves the mempool to that file and reloads it. Note that a clear also discards any prioritisations you set in step 2, re-apply one if its transaction reappears and breaks templates again.State these exactly, for every pool path, because most stale-template losses come from software quietly assuming one of them is false:
coinbasescript and aux hash from a fresh template fetch for that rebuild too (see 8B.8), never from the previous parent job's leftovers.-8) is a refresh event, not a pool failure. It means the work was built on a template whose tip has gone. If nothing was solved on it, the correct response is mechanical and unalarmed: drop the template, fetch a fresh one, resume mining. Do not retry the same submission, do not restart the daemon over it, and do not record it as a daemon fault, record it as stale work, and if it happens constantly, your refresh wiring (8B.7) is the thing to fix.A late AuxPoW block that still clears means no competing block existed during the delay. Report it as a network incident, not a success.
Read that as an operating rule, not a slogan. If one of your blocks reaches the network minutes late and still becomes the chain tip, the reward landing does not make the event a success: it means the whole network produced nothing in the meantime, which is the only reason the late block was not orphaned. On a busier chain, or against a competing pool that was producing normally, that same delay loses the block and the reward outright.
So, for any block of yours whose solve-to-network time runs to minutes, and for any chain gap of roughly 10 minutes or more that your block ends:
.dead file if there is one, the alarm records, and the relevant proxy / adapter / stratum and debug.log lines. Do not delete them once the block lands, a landed block is when the paperwork starts, not when it becomes unnecessary.The mandate: template refresh is triggered by the tip change itself: blocknotify or a ZMQ tip notification: on every pool path. Polling is only the backstop, and no poll interval anywhere in your template path may be set above 5 seconds.
Why this shape: the reference discipline comes from RSK's merge-mining guide, poll the aux work every 2 seconds and push a new stratum job (mining.notify) to miners every time new work arrives, decoupled from the parent chain's cadence. Our chain's tip moves about every 30 seconds, and unlike RSK's setup our kit's primary trigger is the push, not the poll, so the adapted rule for this chain is: push does the real work (a refresh within a second or two of the tip change), and the poll backstop is capped at 5 seconds. Five seconds is one-sixth of a 30-second tip: a completely missed push still costs at most 5 seconds of stale work, the backstop gets about six chances per block to catch a missed push, and the load is trivial, the backstop polls the height (getblockcount, one cheap call), not a full template rebuild. Stock yiimp's roughly 20–21 second database poll, by contrast, can waste most of a whole tip when it is the only refresh mechanism, which is why it is non-conforming on its own: it may exist, but only underneath wired blocknotify.
Per path:
blocknotify line: the proxy has no notify endpoint and takes none. Its built-in tip poll is 5 seconds, inside the cap, and it rebuilds and re-issues the job the moment the tip changes. Verify it is alive as section 8A step 1 says: after the next block, the proxy log shows new tip <height> (was <old height>): rebuilding job.blocknotify is the trigger, wired exactly as Option C and 8B.3(iii) require. The adapter's own backstop is tip_poll_seconds in adapter.conf The shipped default is 5; do not raise it:
# in adapter.conf, [adapter] section:
tip_poll_seconds = 5
blocknotify is the trigger (8B.3(iii)). Yiimp's internal ~21 second poll remains only as an incidental backstop behind it, with blocknotify wired, fresh aux work appears in the stratum log within a second or two of the tip, and that observed timing, not the poll, is what you verify.blocknotify= line (section 8, Option B) pointing at your refresh command, or a ZMQ subscription your software implements against the daemon's block notification:
# in syscoin.conf, only if YOUR software subscribes to it:
zmqpubhashblock=tcp://127.0.0.1:28332
Set exactly one of the two as your trigger (both is fine if your software genuinely consumes both; a zmqpubhashblock= line that nothing subscribes to is not wiring, it is decoration, the shipped proxy and adapter do not listen on it, so never add it "for" them). Do not confuse this with zmqpubnevm=tcp://127.0.0.1:9377 from step 5: that channel carries NEVM template data between syscoind and sysgeth, it is not a tip notification, and it stays exactly as step 5 sets it. Cap any poll you also run at 5 seconds, polling getblockcount and fetching a fresh template only when the height has actually changed, never poll createauxblock itself as the backstop; a template fetch pulls NEVM data with it and is not a cheap probe.The refresh is only finished when the miners get the job. A refresh that updates your pool software's template but leaves miners working the old job until they happen to ask again is half-wired. On every path, the observable pass condition is the same: within a few seconds of a tip change your miners are working a job built on the new tip (proxy: the new tip … rebuilding job log line and a fresh job to connected miners; yiimp: a new auxblock line and fresh work in the stratum log), without any miner reconnecting or waiting for a job timer.
coinbasescript rotation rule: never cache it [R11]The rule: coinbasescript is part of the template, not a constant. Never cache it across blocks. Take it fresh from the newest template on every refresh, and re-fetch createauxblock at least every 10 blocks even on a path where nothing else forces a fetch.
What it is: every createauxblock / getauxblock template carries a coinbasescript field: the AuxPoW tag your software commits into the Bitcoin parent coinbase. That tag anchors to the block at (tip height − 5), rounded down to a multiple of 10, and consensus checks it when the block connects (bad-auxpow-tag / bad-auxpow-ref rejections). Do the arithmetic once and the trap is obvious: the anchor moves every time the tip crosses the next multiple-of-10 boundary, so the script rotates roughly every 10 blocks: about every 5 minutes While changing at no other time. A pool that fetches the script once, at startup or first template, and builds parent coinbases from the cached copy thereafter produces consensus-rejected blocks from the first rotation onward, even with a fresh template hash, a fresh target, and perfect refresh wiring. Pool-side it does not look like a script problem: the submission just returns false, or surfaces as the SHIT <height> REJECTED line of 8B.3(i), for reasons nothing in the pool log explains.
How each path complies:
coinbasescript used for a parent job must be the one from the same template fetch that supplied that job's aux hash Never a script stored at startup, never one carried over from the previous job, never one keyed only to the payout address. If your code fetches templates less often than the tip changes (it should not, see 8B.7), the hard floor is: re-fetch createauxblock at least every 10 blocks and rebuild the parent coinbase from the new script.Verify it, do not assume it. Two fetches, at least 11 blocks apart, must return different scripts:
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin createauxblock shit1qYOURPAYOUTADDRESS | grep coinbasescript
# note the height, wait until the chain is at least 11 blocks higher, run it again
sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin createauxblock shit1qYOURPAYOUTADDRESS | grep coinbasescript
The two coinbasescript values must differ. If they are identical, the daemon is not the suspect, something on your side is serving you a cached template; find it before you mine. The mirror-image symptom in production: submissions that fail in bursts starting near heights ending in 0, after stretches of clean accepts, are this rule being broken until proven otherwise.
Restated in one place, because the checks are otherwise spread across this guide: never run a pool-critical binary or script whose hash you have not checked against the sums published separately on the downloads page. The daemon hash is in step 3, the stratum proxy hash in "How the proxy works", and the yiimp adapter bundle hash in Option C, check each one at install, and check again at every upgrade, against SHA256SUMS.txt fetched from the downloads page itself, never against a sums file that arrived inside the same download it is supposed to verify. A pool-critical fix you cannot verify against the published release is not a fix you can claim to be running, and if a hash ever does not match, stop, download again from this guide's links only, and do not mine on the mismatched file.
Proxy says "payout address" error on start.
PAYOUT_ADDRESS must be a valid shit1... address. Get one from any ShitcoinBtc
wallet (node wallet, web wallet, or browser extension).
Proxy finds shares but no blocks.
Check submission health FIRST: before you decide this is just luck. Shares climbing only proves miners are connected and hashing. It proves nothing about whether found blocks are being submitted, and "shares but no blocks" is exactly what a pool looks like while every submission is being rejected (that failure froze the chain for about 90 minutes on 2026-10-26 while the pool believed it was healthy). Work this checklist, in order:
/var/lib/shitcoin-stratum-proxy/spool/ALARM.txt exist? Read it. (Adapter/yiimp: read the ALARM_SUBMISSION_FAILED marker in the adapter spool directory instead.) An alarm file present means a found block already failed to submit.ls /var/lib/shitcoin-stratum-proxy/spool/ any .json entries are found blocks still waiting for confirmed acceptance; .dead files are blocks that were buried and can never land (see section 8A step 4). The proxy's 5-minute stats: log line reports the same number as spool_pending=<N>, alongside submit_failures=<N> Both must be 0 on a healthy pool.SUBMISSION FAILED, submitblock attempt followed by REJECTED or FAILED, and *** ALARM *** (journalctl -u shitcoin-stratum-proxy | grep -E 'SUBMISSION FAILED|REJECTED|ALARM'). On the adapter, grep for stale_template_submit_-8, ALARM_SUBMISSION_FAILED, submit_result_not_true and submit_retry_aborted_template_dead. In the daemon's debug.log, a stale submission shows as -8 "block hash unknown".getblockhash <height> (section 8A step 4) tells you whose block the chain actually took.Only when the alarm files are absent, spool_pending=0, submit_failures=0 and none of those log strings appear is "no blocks yet" the normal explanation: blocks arrive at the network difficulty (CPU-mineable, but still probabilistic), so a small pool can hash a long time between finds. If shares stay at zero instead, your miners are not connecting (check the port/firewall and LISTEN_HOST).
Proxy exits with "nevm template" errors.
sysgeth must be running: the proxy fetches NEVM templates from it over ZMQ (tcp://127.0.0.1:9377). The daemon launches sysgeth itself (step 4): check that the sysgeth binary sits beside syscoind in /usr/local/bin, that syscoin.conf carries the zmqpubnevm and gethcommandline lines from step 5, and that syscoind is running. Do not start a separate sysgeth service.
Blocks fail with nevm-data-not-found.
The daemon passes --nevmpub from zmqpubnevm in syscoin.conf. Check that syscoin.conf contains zmqpubnevm=tcp://127.0.0.1:9377 and all the gethcommandline lines from step 5 (including gethcommandline=--syscoin.statebootstrap.disable), restart syscoind (it manages sysgeth), and check the running command line with ps aux | grep '[s]ysgeth' — --nevmpub tcp://127.0.0.1:9377 must be there.
Node or proxy rejects blocks, or the node will not follow the chain past 88,000.
You are running software from before the fork. The node must be v5.0.9 (step 3) and the proxy must be the current file (SHA256 b561c6ef146178def8d729c29860a8c9a31c038175e045674f951b53c0d7a39e, see "How the proxy works"). Anything older stamps or expects AuxPoW chain ID 16; the chain has used chain ID 29 since block 88,000.
Stuck at the same height after a restart, or never getting past ~48,000.
Do not keep wiping the data folders, that just replays the failure. Check these first:
ps aux | grep '[s]ysgeth' # helper alive?
grep -E "ERROR|nevm-" /home/shitcoin/.syscoin/debug.log | tail -30 # exact reject reason
tail -60 /home/shitcoin/.syscoin/sysgeth.log # helper-side errors
dmesg | grep -i oom | tail -10 # killed for memory?
free -h # how much RAM?
dmesg shows the OOM killer took sysgeth, your box needs more RAM (see specs above).ps shows no sysgeth, the daemon did not launch it: check that the sysgeth binary sits beside syscoind in /usr/local/bin, that syscoin.conf carries the zmqpubnevm and gethcommandline lines from step 5, and check the syscoind service: sudo systemctl status syscoind. There is no separate sysgeth service with this build (step 4).nevm-response-not-found, the helper timed out: again, usually a slow/small machine./home/shitcoin/.syscoin (blocks, chainstate: the daemon-managed sysgeth keeps its data in /home/shitcoin/.syscoin/geth, so it is wiped with it), restore the snapshot from step 2, and let it sync without restarting anything halfway.A found block never appeared on the chain, or submissions fail with -8 "block hash unknown".
Work section 8A step 4, in order: do not improvise a resubmission scheme:
/var/lib/shitcoin-stratum-proxy/spool/ALARM.txt (proxy) or the ALARM_SUBMISSION_FAILED marker in the adapter spool directory (yiimp). If a submission failed with no alarm, the alarm setup is broken, fix that before mining again..json entry in the spool directory (waiting / being replayed), or already dead-lettered to a .dead file (buried: kept as evidence, never submitted again)? Check the proxy's stats: line for spool_pending= and submit_failures=.sudo -u shitcoin syscoin-cli -datadir=/home/shitcoin/.syscoin getblockhash <height>. If it returns your block's hash, the block landed: a lost reply, not a lost block; the spool entry resolves itself on replay, do not resubmit by hand. If it returns a different hash, the tip moved past your height and the block can never land.syscoind fails to start.
tail -30 /home/shitcoin/.syscoin/debug.log The reason is always in the last lines. Common: port 8369 already in use, or bad permissions on the datadir (chown -R shitcoin:shitcoin).
Restored a snapshot but the node rolls back or stalls.
The daemon-managed sysgeth keeps its data in /home/shitcoin/.syscoin/geth. If you
restored a snapshot and the node rolls back or stalls, stop syscoind, delete
/home/shitcoin/.syscoin/geth (the helper data only: not the whole /home/shitcoin/.syscoin), and restart.
A stale helper database makes syscoind roll the chain back to match it on startup.
Upgrading later.
Stop the service, replace the binaries in /usr/local/bin, start the service. Never delete the datadir on upgrade. The current version is v5.0.9: upgrade to that, from the downloads page only.
Questions: the founder is reachable on Telegram as @JodieWanamaker. Include your node's height, peer count, and the last 30 lines of debug.log That is everything needed to diagnose it.