EPMB/unsigned: fixed multi-page winner computation#8987
Conversation
In `FullSupportsOfMiner`, we initially considered `MaxWinnersPerPage` as the overall maximum total winners across pages. However, it should be calculated as `Pages * MaxWinnersPerPage`. This bug was identified in [#staking-miner-1074](paritytech/polkadot-staking-miner#1074) while testing the staking miner in a setup with aggressive trimming to evaluate backer bounding. Consequently, the computed solution had a low overall total of winners and was rejected with a `WrongWinnerCount` error. A test has been added to replicate this scenario.
|
/cmd prdoc --audience runtime_dev --bump patch |
…time_dev --bump patch'
prdoc/pr_8987.prdoc
Outdated
| ## The issue | ||
|
|
||
| In `FullSupportsOfMiner`, we initially considered `MaxWinnersPerPage` as the overall maximum number of winners across pages. However, it should be calculated as `Pages * MaxWinnersPerPage` to prevent the computed solution from having a low overall total of winners, which could result in a `WrongWinnerCount` error. | ||
|
|
||
| This bug was identified in | ||
| [#staking-miner-1074](https://github.com/paritytech/polkadot-staking-miner/issues/1074) while testing the staking miner in a setup with aggressive trimming to evaluate backer bounding. | ||
|
|
||
| ## How to test | ||
|
|
||
| A test has been added to replicate this scenario: | ||
|
|
||
| Test configuration: | ||
| - `Pages=2` | ||
| - `MaxWinnersPerPage=2` | ||
| - `desired_targets=3` (3 or 4 doesn't matter here, the key point is that is strictly > `MaxWinnersPerPage`) | ||
| - `MaxBackersPerWinner=1` | ||
|
|
||
| Before the fix in this PR: | ||
| - `FullSupportsOfMiner` could only hold 2 winners in total (bounded by `MaxWinnersPerPage`) | ||
| - But the mining algorithm needed to hold 3 winners across multiple pages | ||
| - This would cause a `WrongWinnerCount` error during verification | ||
|
|
||
| With the fix: | ||
| - `FullSupportsOfMiner` can now hold `Pages * MaxWinnersPerPage = 2 * 2 = 4` winners | ||
| - The test passes with 3 winners across 2 pages (proving it can hold more than `MaxWinnersPerPage=2`) | ||
| - No `WrongWinnerCount` errors occur |
There was a problem hiding this comment.
| ## The issue | |
| In `FullSupportsOfMiner`, we initially considered `MaxWinnersPerPage` as the overall maximum number of winners across pages. However, it should be calculated as `Pages * MaxWinnersPerPage` to prevent the computed solution from having a low overall total of winners, which could result in a `WrongWinnerCount` error. | |
| This bug was identified in | |
| [#staking-miner-1074](https://github.com/paritytech/polkadot-staking-miner/issues/1074) while testing the staking miner in a setup with aggressive trimming to evaluate backer bounding. | |
| ## How to test | |
| A test has been added to replicate this scenario: | |
| Test configuration: | |
| - `Pages=2` | |
| - `MaxWinnersPerPage=2` | |
| - `desired_targets=3` (3 or 4 doesn't matter here, the key point is that is strictly > `MaxWinnersPerPage`) | |
| - `MaxBackersPerWinner=1` | |
| Before the fix in this PR: | |
| - `FullSupportsOfMiner` could only hold 2 winners in total (bounded by `MaxWinnersPerPage`) | |
| - But the mining algorithm needed to hold 3 winners across multiple pages | |
| - This would cause a `WrongWinnerCount` error during verification | |
| With the fix: | |
| - `FullSupportsOfMiner` can now hold `Pages * MaxWinnersPerPage = 2 * 2 = 4` winners | |
| - The test passes with 3 winners across 2 pages (proving it can hold more than `MaxWinnersPerPage=2`) | |
| - No `WrongWinnerCount` errors occur | |
| Change the calculation of `MaxWinnersPerPage` in `FullSupportsOfMiner` to `Pages * MaxWinnersPerPage` (instead of the overall maximum number of winners across pages) to prevent the computed solution from having a low overall total of winners, which could result in a `WrongWinnerCount` error. |
| >; | ||
|
|
||
| /// Helper type that computes the maximum total winners across all pages. | ||
| pub struct MaxWinnersTotal<T: MinerConfig>(core::marker::PhantomData<T>); |
There was a problem hiding this comment.
Elsewhere in the code, we have a similar naming dilemma:
MaxBackersPerWinner: page-local boundMaxBackersPerWinnerFinal: bound across all pages
I am happy with either naming schemes (or even a new one) but I do suggest them to be consistent.
There was a problem hiding this comment.
very fair point, let me use Final here as well
| <T as MinerConfig>::AccountId, | ||
| <T as MinerConfig>::MaxWinnersPerPage, | ||
| MaxWinnersTotal<T>, | ||
| <T as MinerConfig>::MaxBackersPerWinnerFinal, |
There was a problem hiding this comment.
You can actually see the naming convention I mentioned here, noting the Final postfix.
There was a problem hiding this comment.
renamed to use Final for consistency, ty
kianenigma
left a comment
There was a problem hiding this comment.
This is a very useful finding! would have been hard to catch later in prod.
The unfortunate note is that we will 99% use configurations in prod that will not trigger any trimming, but in the case of the 1%, it is hard to catch :)
I have a todo in the code about this, which you can now maybe remove and convert to an issue for us as well:
// TODO: we should have a fuzzer for miner that ensures no matter the parameters, it generates a
// valid solution. Esp. for the trimming.
What we did here was a small step towards this! But we can later it push it to the extreme: No matter what is in the snapshot, and what configurations are set in MinerConfig, it MUST produce something that is valid, or fail to produce a solution.
| // The solution should still be valid despite aggressive trimming | ||
| assert!(solution.solution_pages.len() > 0); | ||
|
|
||
| let winner_count = solution |
There was a problem hiding this comment.
It is not a great name, but I found winner_count_single_page_target_snapshot.
There was a problem hiding this comment.
not completely sold but also I don't mind to change the name either, I was hoping that the comments were enough to explain what we are doing in the test
There was a problem hiding this comment.
yeah it is fine either way. Just noted that we have a helper fn that does the same.
Kept the TODO for the time being, and added #9038 |
## The issue In `FullSupportsOfMiner`, we initially considered `MaxWinnersPerPage` as the overall maximum number of winners across pages. However, it should be calculated as `Pages * MaxWinnersPerPage` to prevent the computed solution from having a low overall total of winners, which could result in a `WrongWinnerCount` error. This bug was identified in [#staking-miner-1074](paritytech/polkadot-staking-miner#1074) while testing the staking miner in a setup with aggressive trimming to evaluate backer bounding. ## How to test A test has been added to replicate this scenario: Test configuration: - `Pages=2` - `MaxWinnersPerPage=2` - `desired_targets=3` (3 or 4 doesn't matter here, the key point is that is strictly > `MaxWinnersPerPage`) - `MaxBackersPerWinner=1` Before the fix in this PR: - `FullSupportsOfMiner` could only hold 2 winners in total (bounded by `MaxWinnersPerPage`) - But the mining algorithm needed to hold 3 winners across multiple pages - This would cause a `WrongWinnerCount` error during verification With the fix: - `FullSupportsOfMiner` can now hold `Pages * MaxWinnersPerPage = 2 * 2 = 4` winners - The test passes with 3 winners across 2 pages (proving it can hold more than `MaxWinnersPerPage=2`) - No `WrongWinnerCount` errors occur --------- Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* master: (91 commits) Add extra information to the harmless error logs during validate_transaction (#9047) `sp-tracing`: Remove `test-utils` feature (#9063) add try-state check for staking roles -- staker cannot be nominator a… (#9034) net/discovery: File persistence for `AddrCache` (#8839) dispute-coordinator: handle race with offchain disabling (#9050) Align parameters for `EventEmitter::emit_sent_event` (#9057) Fetch parent block `api_version` (#9059) [XCM Precompile] Rename functions and improve docs in the Solidity interface (#9023) Cleanup and improvements for `ControlledValidatorIndices` (#8896) reenable 0001-parachains-pvf (#9046) Add optional auto-rebag within on-idle (#8684) Fix flaxy 0003-block-building-warp-sync test - one more approach (#8974) [Staking] [AHM] Fixes insufficient slashing of nominators (and some other small issues). (#8937) chore: Bump bounded-collections dep (#9004) XCMP and DMP improvements (#8860) EPMB/unsigned: fixed multi-page winner computation (#8987) Always send full parent header, not only hash, part of collation response (#8939) revive: Precompiles should return dummy code when queried (#9001) Fix confusing log messages in network protocol behaviour (#8819) Fix pallet_migrations benchmark when FailedMigrationHandler emits events (#8694) ...
## The issue In `FullSupportsOfMiner`, we initially considered `MaxWinnersPerPage` as the overall maximum number of winners across pages. However, it should be calculated as `Pages * MaxWinnersPerPage` to prevent the computed solution from having a low overall total of winners, which could result in a `WrongWinnerCount` error. This bug was identified in [#staking-miner-1074](paritytech/polkadot-staking-miner#1074) while testing the staking miner in a setup with aggressive trimming to evaluate backer bounding. ## How to test A test has been added to replicate this scenario: Test configuration: - `Pages=2` - `MaxWinnersPerPage=2` - `desired_targets=3` (3 or 4 doesn't matter here, the key point is that is strictly > `MaxWinnersPerPage`) - `MaxBackersPerWinner=1` Before the fix in this PR: - `FullSupportsOfMiner` could only hold 2 winners in total (bounded by `MaxWinnersPerPage`) - But the mining algorithm needed to hold 3 winners across multiple pages - This would cause a `WrongWinnerCount` error during verification With the fix: - `FullSupportsOfMiner` can now hold `Pages * MaxWinnersPerPage = 2 * 2 = 4` winners - The test passes with 3 winners across 2 pages (proving it can hold more than `MaxWinnersPerPage=2`) - No `WrongWinnerCount` errors occur --------- Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The issue
In
FullSupportsOfMiner, we initially consideredMaxWinnersPerPageas the overall maximum number of winners across pages. However, it should be calculated asPages * MaxWinnersPerPageto prevent the computed solution from having a low overall total of winners, which could result in aWrongWinnerCounterror.This bug was identified in
#staking-miner-1074 while testing the staking miner in a setup with aggressive trimming to evaluate backer bounding.
How to test
A test has been added to replicate this scenario:
Test configuration:
Pages=2MaxWinnersPerPage=2desired_targets=3(3 or 4 doesn't matter here, the key point is that is strictly >MaxWinnersPerPage)MaxBackersPerWinner=1Before the fix in this PR:
FullSupportsOfMinercould only hold 2 winners in total (bounded byMaxWinnersPerPage)WrongWinnerCounterror during verificationWith the fix:
FullSupportsOfMinercan now holdPages * MaxWinnersPerPage = 2 * 2 = 4winnersMaxWinnersPerPage=2)WrongWinnerCounterrors occur