LithosDocs
ProtocolPayoutsTokenStatsDocs
Start mining
Documentation home
Protocol
  • Lithos Protocol
  • LFSM
    • Rollups
    • NISPs
    • Emissions
    • Mining on Lithos
    • Candidate building
    • Ergo Voting
  • LithosDex
    • Trading with orders
    • Providing liquidity
Run Lithos
  • Startup guide
    • Setting up an Ergo testnet node
  • Configuration
    • Node connection and security
    • Stratum and difficulty
    • Block packages
    • Batching and orders
    • Collateral and emission
    • Wallet and consolidation
    • Statistics and web panels
    • Synchronization and storage
    • Tasks and dispatchers
    • Failure modes
    • Reporting issues
Client API
  • Overview
    • getLithos client information
    • getList UTXO ids for blocks
    • getUTXO ids by block height
    • getBlock info by UTXO id
    • postBlock info for multiple UTXO ids
    • getGet a block's miner set
    • getList all pool blocks
    • getGet Lithos payouts
    • getStatistics overview
    • getMining and payment totals
    • getMining statistics by hour or day
    • getEstimate Lithos hashrate
    • getNetwork difficulty by epoch
    • getThis client's own hashrate
    • getThis client's hashrate over time
    • getThis client's payouts and claims
    • getCollateral inventory
    • getLocal mining activity
    • getCollateral market snapshot
    • getList queue boxes
    • getList the active set
    • getPermit price history
    • getYour locked block rewards
    • postClaim unlocked block rewards
    • postQuote joining the queue
    • postJoin the collateral queue
    • getLithosDex pool state
    • getLithosDex fee vault state
    • getList your outstanding orders
    • postQuote a swap order
    • postPlace a swap order
    • postQuote a deposit order
    • postPlace a deposit order
    • postQuote a redeem order
    • postPlace a redeem order
    • postCancel an order
    • postQuote a swap
    • postQuote a swap by desired output
    • postExecute a swap
    • postQuote a liquidity deposit
    • postDeposit liquidity
    • postQuote a liquidity redemption
    • postRedeem liquidity
    • getList liquidity provisions
    • postClaim settled fees for a provision
    • postQuote a provision resize
    • postResize a provision
    • postCheck a pending fee flush
    • postFlush pending fees to the vault
    • getPool-wide fee history
    • getPool price history
    • getRecent pool activity
    • getFee history for one provision
    • getWallet balances and lending status
    • getGet Stratum information
    • getGet candidate settings
    • getGet difficulty commitment
    • postCommit a difficulty
    • getGet best NISP at height
Lithos

A decentralized mining pool protocol on Ergo. Miners build their own blocks; contracts pay them for proven work.

Live on Ergo mainnet
Protocol
  • How Lithos works
  • Mining on Lithos
  • NISPs
  • Emissions
  • LFSM contracts
Run Lithos
  • Startup guide
  • Configuration
  • LithosDex
  • Client API
  • Failure modes
Network
  • Live stats
  • Public stats API
  • Ergo Platform↗
  • SOAT Miner↗
Community
  • Telegram↗
  • X / Twitter↗
  • GitHub↗
Lithos
© 2026 Lithos Protocol. Open source under the MIT licence.λίθος — stone
Docs/Run Lithos/Configuration

Tasks and dispatchers

Committing your difficulty, background tasks, thread pools, and the switch that disables protocol work.

Expert7 min readAssumes you know what an Akka dispatcher is and why thread pool isolation matters. Most miners never change anything on this page.

Three blocks are left. state holds two switches: one that commits your difficulty on chain and one that turns protocol work off. lithos-tasks configures the three background timers, and lithos-contexts defines the thread pools everything runs on.

The dispatcher pools in particular encode a design decision rather than a preference, and the page says which ones you must not merge.

Protocol switches#

SettingDefaultRangeWhat it does
state.autoCommitfalsetrue or falseRegister this miner and commit stratum.diff on chain, then keep the commitment equal to it
state.disableTransformsfalsetrue or falseDisable every transaction and interaction with LFSM rollups

disableTransforms is a blunt instrument. With it on the client follows the chain but submits nothing: no NISPs, no phase transforms, no fraud proofs, no payouts, and no commitments. You mine and are not paid. This can be useful for testing.

Committing your difficulty#

A miner is paid from a rollup only after two things are on chain: a registration in the Miner Dictionary, the on-chain registry of Lithos miners, and a difficulty commitment, the score your NISPs are judged against. Your first difficulty commitment also registers you.

You commit from the Commitment tab under Mining, Difficulty in the web interface, or with POST /mining/commitment. autoCommit is the alternative: the client commits stratum.diff for you. It ships off, so a new client never writes a difficulty you are still testing. While it is on, the Commitment tab and POST /mining/commitment refuse to commit, so only one of them ever changes your difficulty. While you are not registered, the client mines normally but cannot submit NISPs, and the log says so at startup.

With autoCommit on, the dictionary task checks every minute, starting about a minute after startup:

  1. If you are not registered, the client registers you with stratum.diff as your first commitment. Registration waits until the Miner Dictionary has synced.
  2. If you are registered and your newest commitment differs from stratum.diff, the client replaces it as soon as the contracts allow.
  3. After sending either transaction, the client waits for it to confirm and for its own sync to reach that block, then checks again.
  4. Once the confirmed commitment equals stratum.diff, the loop stops until the next restart.

The contracts decide how fast a difficulty commitment moves, however it is sent. The following counts blocks from the moment it is sent:

EventBlocks after sendingTestnetMainnet
The commitment binds, and NISPs are judged against it125about 1 hour 35 minutesabout 4 hours 10 minutes
The commitment may be replaced by a new one845about 10 hours 30 minutesabout 28 hours

A registration or change has 5 blocks to be included. If it misses them it becomes invalid, and the client sends a new one on a later check.

While the loop is waiting, it logs the reason once, as Auto-commit waiting on ..., and again only when the reason changes. autoCommit does nothing while disableTransforms is true or the dictionary task is disabled.

Tip
Choose your difficulty before you commit

A difficulty commitment holds for 845 blocks before it can be replaced. Measure your super share rate first with stratum.forceConfigDiff = true, as in Stratum and difficulty.

Background tasks#

Three tasks run on timers. Each takes the same three keys, and all three are required for each task:

KeyRangeWhat it does
enabledtrue or falseWhether the task runs
startup1 to 604800000 msDelay before its first run
interval1 to 604800000 msGap between runs

The three tasks and what they ship as:

TaskEnabledStartupIntervalWhat it does
lithos-tasks.stratum-servertrue30 seconds30 secondsRuns the stratum server that your mining software connects to
lithos-tasks.rollup-sync-tasktrue10 seconds500 millisDrives rollup phase work against current state
lithos-tasks.dictionary-sync-tasktrue60 seconds60 secondsRegisters and commits when state.autoCommit is on, and warns before your registration expires

Durations take any form the config library parses, such as 500 millis, 30 seconds or 5 minutes. The dictionary task runs at most once a minute, so a shorter interval there is raised to one minute.

A missing task block stops the client rather than defaulting, because a task silently not running is worse than a refusal to start. The one exception is a lookup that only picks a log message, which reads an absent block as disabled.

Warning
The dictionary task is what warns you about expiry

A registration lasts 919,800 blocks and then stops being honoured. This task reads your own entry and warns from 720 blocks before expiry onward, naming the height after which removal is safe. Disabling it removes that warning, and removing a live registration at the wrong moment slashes your own honest submissions.

Dispatchers#

lithos-contexts defines every thread pool the client uses. Startup checks that each named block exists and leaves the contents to Akka, so a missing block is caught and a bad pool size is not.

The client requires all twenty-three of these blocks:

DispatcherPoolServes
wallet-io-dispatcher1 thread, queue 4Candidate requests, which change the node's cached work
wallet-maintenance-dispatcher2 threads, queue 8Inventory scans and reward sweeps
critical-wallet-dispatcher1 thread, queue 4Wallet work that must not queue behind optional work
critical-tx-dispatcher2 threads, queue 4Transactions that must not be delayed
engine-candidate-dispatcher2 threads, queue 4Engine work for candidate assembly
engine-io-dispatcher1 thread, queue 4General engine node I/O
mempool-io-dispatcher1 thread, queue 4Mempool reads
candidate-io-dispatcher1 thread, queue 4Candidate node I/O
mining-control-io-dispatcher2 threads, queue 4One chain observation and one solved-block submission, concurrently
genesis-dispatcher1 thread, queue 4Collateral genesis signing
batching-io-dispatcher2 threads, queue 4ErgoDEX order discovery, broadcasts and builds
lithosdex-batching-io-dispatcher2 threads, queue 4The same for LithosDex
snapshot-io-dispatcher4 threads, queue 4Snapshot save, restore and dictionary reconstruction
stratum-dispatcherfork-join, 4 to 16The stratum server
polling-dispatcher32 threadsNode polling
sync-dispatcherfork-join, 2 to 10Synchronization
tx-dispatcherfork-join, 2 to 10General transaction work
dex-dispatcher16 threadsThe local LithosDex HTTP endpoints
database-dispatcher2 threadsLocal database work
stats-dispatcher1 threadThe statistics collector behind the web panels
stats-read-dispatcher1 thread, queue 1LithosDex statistics reads from the node
stats-store-dispatcher1 thread, queue 1Writing LithosDex statistics to disk
mining-stats-dispatcher1 thread, queue 1Mining statistics: node reads and their history on disk

A top-level stats-mailbox block also bounds the statistics collector's mailbox at 256 messages, so a slow statistics read drops observations rather than growing memory. See Statistics and web panels.

Why they are separate#

The separation is the point, and three of these exist because merging them cost blocks.

A found block must never queue behind node I/O. mining-control-io-dispatcher has two threads so that one chain observation and one solved-block submission can run at once, and neither waits for candidate HTTP, wallet work or transaction preparation. An early version ran a rollup batch inside the same mailbox that answers block assembly, and every block in flight silently lost its inserted transactions with nothing in the log connecting the two.

Candidate requests are serialised on purpose. wallet-io-dispatcher has exactly one thread because asking the node for a candidate replaces the node's cached work. Two concurrent requests would each mutate a cache the other depends on. Optional transaction workers cannot occupy that thread.

Genesis signing has its own worker so that background collateral refresh and ordinary transaction work cannot occupy it while cached inputs are ready for a new block.

Snapshot work blocks in LevelDB, sometimes for a long time. Four threads cover the one save, one restore and two dictionary reconstructions the actor may own, and the bounded queue contains work left behind by an unexpected restart when a backend call cannot be interrupted.

Danger
Do not merge these pools

The thread counts are small enough to look wasteful and are not. Every one-thread pool here is a serialisation guarantee, and every separate pool is an isolation guarantee for work that must not wait behind something slower. Raising a count is usually safe; merging two blocks is not.

Next steps#

  • Configuration overview: how a missing block is reported at startup.
  • Synchronization and storage: what snapshot-io-dispatcher is doing.
  • Statistics and web panels: what the four statistics dispatchers serve.
Edit this page on GitHubsynced from e0ca86a
← PreviousSynchronization and storageNext →Failure modes
On this page
  • Protocol switches
  • Committing your difficulty
  • Background tasks
  • Dispatchers
  • Why they are separate
  • Next steps