Break fee inputs into chunks in collectRewards (#2185) - #2462
Open
Ergologica wants to merge 3 commits into
Open
Conversation
This was referenced Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2185.
Problem
CandidateGenerator.collectRewardscollects every fee box of a block into one fee transaction:With enough fee-paying transactions in a block, that transaction can grow past the block limits and be invalid, which invalidates the candidate.
Fix
Fee boxes are grouped into chunks of at most
MaxFeeBoxesPerTransaction(100), one fee-collecting transaction per chunk. Each chunk gets its own miner box and its own token set truncated atMaxAssetsPerBox, as before.Chunking
collectRewardsalone would have had no effect where it counts:collectFeesended in.headOption, and the assembly loop incollectTxscarried the fee transaction as a singleOption[CostedTransaction], so every chunk after the first would have been dropped silently.collectFeesnow returnsSeq[ErgoTransaction]and the loop threadsSeq[CostedTransaction]. Each chunk is validated on its own withstatefulValidity; one failing chunk aborts the step exactly as one failing fee transaction did before, and the cost/size check sees all of them together.Behaviour is unchanged for any block with 100 fee boxes or fewer, which is every block on mainnet today.
Tests
fee boxes are collected in chunks of at most MaxFeeBoxesPerTransaction- with more fee boxes than one chunk holds, the transaction count isceil(n / 100), every fee box is spent exactly once across the chunks, and the miner's total is unchanged.collect reward from both emission box and feesasserted exactly 2 transactions, which stops holding once the generator produces more than 100 fee boxes. It now checks the invariants that survive a split: the emission transaction, per-chunk input bounds, and the total paid to the miner.sbt "testOnly org.ergoplatform.mining.CandidateGeneratorPropSpec"- 9/9 green.On the chunk size
100 is a deliberate conservative constant rather than a computed limit. The alternative is to size chunks from the block cost and size parameters in the upcoming context, which would put block-limit arithmetic inside reward collection. Happy to change the number, or to derive it, if you would rather have that.