perf(escrow,milestones): O(n log n) largest-remainder dust distribution - #61
Merged
Merged
Conversation
Replace the O(n²) repeated-linear-scan dust loop in compute_split with a single heapsort by (remainder desc, address asc, index asc) followed by a linear pass awarding one unit to each of the first `dust` entries. The two approaches are equivalent: each award only consumes the chosen entry, so repeated largest-remainder selection is identical to taking the top-dust sorted entries. Heapsort is in-place, non-recursive, and allocation-free, so it is safe under #![no_std]. Adds test_large_split_distributes_dust_by_largest_remainder to both contracts: 60 recipients with 40 dust units and 47 tied remainders, verified against a reference copy of the old O(n²) scan. Closes MergeFi#55.
|
@aristotle224 is attempting to deploy a commit to the chonilius' projects Team on Vercel. A member of the Team first needs to authorize it. |
4 tasks
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.
Description
Closes #55 — makes
compute_split's dust-distribution step O(n log n) instead of O(n²).Before
The dust loop (
contracts/escrow/src/lib.rs:295-317, byte-identical incontracts/milestones/src/lib.rs:279-301) did a full linear scan over allnrecipients per dust unit to find the largest remaining remainder. With up ton-1dust units worst case, that's ~n²/2comparisons on every split.After
Build an
(index, remainder, address)record per recipient, heapsort once by (remainder desc, address asc, index asc), then award one unit to each of the firstdustentries in a linear pass.dustof a single sort".dust ≤ n-1always, so the firstdustsorted entries always exist.#.Motivation
Compounds with #8 (unbounded recipients): the quadratic cost scaled with both recipient count and dust. This flattens the curve so recipient-count growth (the #8 axis) no longer carries a per-dust O(n) penalty.
Tests
test_large_split_distributes_dust_by_largest_remainder(escrow + milestones): 60 recipients, 40 dust units, 47 tied remainders exercising the address tie-break; every share matched against a reference copy of the old O(n²) approach, total payout = total distributable.test_adversarial_ordering_resistanceand both*_rounding_dust_by_largest_remaindertests.cargo test --workspace,cargo clippy --workspace --all-targets, andcargo fmt --checkall clean.