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/Protocol/Mining

Candidate building

How the Lithos client builds each block you mine, where the revenue from its extra transactions goes, and what happens when part of it fails.

Advanced9 min readAssumes you know how Ergo blocks are assembled and what a mempool is. Read Mining on Lithos first.

Every block you mine starts as a block candidate: the transactions your Ergo node will commit to, turned into the job your mining software hashes. With Lithos, your own client decides what goes into that candidate before your node fills in the rest. This page explains how the client builds a candidate, where the revenue from its extra transactions goes, and how it falls back when something fails.

It stays general. The settings are listed in Block packages, and the ErgoDEX and LithosDex sources are configured in Batching and orders.

What goes into a candidate#

A Lithos candidate is built in layers, in the following order:

  1. The genesis transaction. It spends a collateral box and creates the holding box for the rollup this block opens. It is what makes the block a Lithos block, so it always comes first.
  2. The block package. Extra transactions from the client's transaction sources, such as Non-Interactive Share Proof (NISP) submissions and order executions. These are optional, and every source except storage rent ships on.
  3. The holding top-up. One final transaction that moves the revenue the package earned into the holding box.
  4. Your node's own selection. Your Ergo node fills the space left with fee-paying transactions from its mempool, as it would for any block.

With the package off, which is the default, a candidate is the genesis transaction followed by your node's selection.

Building the genesis transaction#

The genesis transaction has to exist before the node can hand out a job, so it is the one part of the candidate on the critical path. The client prepares for it in advance:

  • The collateral set is held in memory. The client keeps the live collateral boxes, up to 100, loaded ahead of time and refreshes them after every block. Nothing is fetched while a block waits.
  • A box is chosen per block. The box offering the finder the largest priority fee wins, and the oldest breaks a tie. A box that has been live for clearanceAge blocks, 7200 by default, is taken ahead of every bid, oldest first, so no box waits forever. Setting collateralStrategy to random draws uniformly instead. Boxes paying into a rollup chain this release does not build are never drawn, as Boxes your block never spends explains.
  • The coinbase goes to the lender. The client asks the node for a candidate paying the block reward to the chosen box's lender, which is what the collateral box paid for.

The genesis transaction is signed on its own thread, so nothing else the client is doing can delay it.

Building the block package#

When stratum.candidate.blockTransactions is on, the client asks each enabled transaction source for work as soon as a new block arrives. The sources, in the order they are asked, are:

SourceWhat it insertsShips
rollupsYour NISP submissions, rollup phase transforms, fraud proofs and payoutsOn
emissionsMaintenance of the collateral queueOn
rentCollection of boxes old enough to owe storage rentOff
lithosdexLithosDex order executions and the fee flushOn
ergodexErgoDEX order executionsOn

Every transaction a source offers is inserted without a fee. You are the one mining the block, so there is nobody to pay. Rollup and emission work is protocol work the client also sends to the mempool with a fee, so that it lands whoever finds the block. For rollup work, your own block gets the first chance, as How rollup work reaches the chain explains. Queue Activates get the same first block, and a Clear is always taken, as Queue work in your own blocks explains.

How the package is bounded#

A package is bounded twice. Each source is first held to its own limits on transactions, bytes and execution cost, so a busy source cannot use space a quieter one needs. The whole package is then held to blockShare of your node's current block limits, half by default, since the node still needs room for its own selection.

Sources are admitted in the order above until the package is full. The genesis transaction is counted first, so it is never the part that is dropped. A transaction that depends on an unconfirmed parent is admitted together with that parent or not at all, because a block carrying the child alone is invalid.

Waiting for sources#

Two deadlines apply after a new block, and they protect different things:

  • The job waits at most genesisWaitMs, 1.5 seconds by default. If the package is not ready by then, your mining software gets the genesis transaction alone, and the package follows as a new job when it is.
  • The sources get at most blockTxTimeout, 20 seconds by default. A source that has not answered two seconds before then is left out, and what the others built still goes in. A source that answers later is picked up by the next refresh.

Where the revenue goes#

Some sources earn ERG: executor fees from filled orders, and storage rent from collected boxes. That revenue goes to the pool, not to you alone. The holding top-up adds it to the holding box this block's genesis transaction created, and the rollup pays it out by score to every miner who submits to it, you included.

Two limits apply to the top-up:

  • Tokens cannot enter the holding box. Any tokens the package earns stay on outputs your wallet owns.
  • A top-up that does not fit is skipped. If the package budget has no room left for it, or it would cost more than it adds, the revenue stays on outputs your wallet owns and can be spent later.
Note
Why revenue is pooled

The holding box of a new rollup accepts extra value only inside the block that creates it, so only the miner who found the block can add to it. Pooling is what turns one miner's package revenue into a payout every Lithos miner shares, in the same way the block reward is shared.

Refreshing within a block#

Transactions keep arriving after a block starts, and some pay more than what the package already holds. Every mempoolRefreshMs, 20 seconds by default, the client rebuilds the package against the current mempool.

A rebuilt package does not always replace the job. Changing jobs costs your mining software a moment of work, so the client switches only when the rebuilt package earns at least minCandidateChangeRevenue more than the one it is serving, 0.001 ERG by default.

Rollup and emission transactions earn no ERG, so the client also switches when the rebuilt package adds at least minNewProtocolTxs of them, 1 by default. Setting refreshForProtocolTxs to false turns that rule off.

How rollup work reaches the chain#

Your client sends its rollup transactions to the mempool with a fee, so they land whoever finds the block. These are your NISP submissions, rollup phase transforms, fraud proofs and payouts. With blockTransactions on, your own block gets the first chance to carry each one without a fee, in the following order:

  1. A new rollup transaction waits for the next package rebuild, up to mempoolRefreshMs, so your package can take it first.
  2. While your block carries the transaction, the client holds the fee-paying copy back.
  3. If you find the block, the transaction lands without a fee, and the client sends nothing.
  4. If someone else finds the block, the client checks the chain within a minute. If the work is still undone, the client sends the fee-paying copy and stops offering the transaction to your blocks.

NISP submissions and fraud proofs must land before a fixed window closes. Any with 10 blocks or fewer left, about 20 minutes at Ergo's 2-minute block time, are sent with a fee at once, whatever your block carries.

Emission transactions are not held back. The client sends them to the mempool on its own timers. The settings that change when rollup work waits are in Rollup work.

When part of a candidate fails#

The client never stops mining over a failed candidate. It falls back one step at a time, and each step is logged at warning or error level with the reason:

What failedWhat the client does
A source errors or does not answer in timeBuilds the package without that source
The node leaves one inserted transaction out of the candidateMines the rest of the package and logs which transaction was left out
The node refuses the candidate with the package in itMines the genesis transaction alone until the next block
Collecting the package takes longer than blockTxTimeoutMines the genesis transaction alone until the next block
The genesis transaction cannot be builtTries a different collateral box, up to two more times
The node refuses the genesis transactionTries a different collateral box, up to three times per block
No genesis transaction is ready within genesisWaitMsServes a solo job until one is ready
No genesis transaction can be built at allServes a solo job for the rest of the block
Warning
Solo blocks are not Lithos blocks

A solo block pays its reward to your node's own mining address, and no rollup opens. Super shares found on a solo job do not count towards a NISP. Occasional solo jobs are normal while a new block's genesis is being built. A client that mines solo for long stretches has a collateral or node problem, and the log names it.

Seeing what your client built#

The Block package tab on the Mining page shows the job your stratum is serving right now: its genesis transaction, the transactions the package inserted, the holding top-up, and the sources that contributed. Refresh reads the newest job without waiting for the page's timer. Below the block, three cards show the following:

  • Collateral box: the box the genesis transaction spends, its priority fee above the principal floor, and the part of that fee paid to you.
  • Extra transactions: whether blockTransactions is on, and for each source whether it is asked, its limits, and whether it made it into this job.
  • Job refresh: when a rebuilt package replaces the job mid-block.

A source marked not asked, no slots or batcher off is enabled but contributes nothing, and hovering the status names the setting that stops it. To see the same detail in the log, turn on stratum.candidate.logTimings and stratum.candidate.logBudgets.

The following log lines show what happened to individual transactions. A stub is the client's record of one rollup transaction waiting to be sent, named as its type and the first 8 characters of its rollup's id:

Log lineWhat it means
Holding N rollup stub(s) back from the funded path…Your block carries these rollup transactions, so their fee-paying copies wait
Releasing N rollup stub(s) to the funded path…The block passed without them, so their fee-paying copies go out now
Node left N of M requested transaction(s) out of candidate…Your node left these transactions out of your block. A Not included transaction line in the node's log gives the reason, and no such line means one of the transaction's inputs was missing or already spent
Node left N transaction(s) out of block H, and the top-up spending their outputs with them…Your node refused an inserted transaction, which also invalidates the top-up collecting its revenue. The client mines the genesis transaction alone for a moment, then rebuilds the package without that transaction, up to twice per block
Dropping optional candidate transactions…The inserted transactions could not be used, after any rebuilds. The rest of this block is mined with the genesis transaction alone

Next steps#

  • Block packages: every setting on this page.
  • Batching and orders: the sources that fill other people's orders.
  • Mining on Lithos: how the rollup that shares this revenue pays you.
Edit this page on GitHubsynced from e0ca86a
← PreviousMining on LithosNext →Ergo Voting
On this page
  • What goes into a candidate
  • Building the genesis transaction
  • Building the block package
  • How the package is bounded
  • Waiting for sources
  • Where the revenue goes
  • Refreshing within a block
  • How rollup work reaches the chain
  • When part of a candidate fails
  • Seeing what your client built
  • Next steps