-
Notifications
You must be signed in to change notification settings - Fork 152
[POC] Winner selection crate #4010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: refactor-participant-scores
Are you sure you want to change the base?
Conversation
1c8a399 to
decca80
Compare
# Conflicts: # crates/autopilot/src/domain/competition/participant.rs # crates/autopilot/src/domain/competition/winner_selection.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR extracts winner selection logic into a new standalone winner-selection crate to prepare for Pod network integration. The crate contains minimal data structures and algorithms needed to run winner selection, allowing both autopilot and drivers to use the same logic for determining winning solutions.
Key changes:
- New
winner-selectioncrate with minimal solution/order data structures optimized for serialization - Generalized ranking traits using state markers (Unscored, Scored, Ranked)
- Autopilot refactored to use the new crate with conversion functions between domain types
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/winner-selection/Cargo.toml | Defines new crate with dependencies for winner selection |
| crates/winner-selection/src/lib.rs | Module organization and re-exports for the new crate |
| crates/winner-selection/src/primitives.rs | Core primitive types (OrderUid, Side, FeePolicy, Quote) |
| crates/winner-selection/src/util.rs | Mathematical utility functions for U256 operations |
| crates/winner-selection/src/state.rs | Generic state markers and traits for scoring/ranking |
| crates/winner-selection/src/solution.rs | Minimal solution and order data structures |
| crates/winner-selection/src/auction.rs | Auction context with fee policies and native prices |
| crates/winner-selection/src/arbitrator.rs | Core winner selection algorithm implementation |
| crates/autopilot/src/domain/competition/winner_selection.rs | Refactored to wrap and delegate to new winner-selection crate |
| crates/autopilot/src/domain/competition/participant.rs | Uses generalized state traits from winner-selection |
| crates/autopilot/src/domain/settlement/trade/mod.rs | Removes score computation now handled by winner-selection |
| crates/autopilot/src/domain/settlement/trade/math.rs | Removes score computation logic |
| crates/autopilot/src/domain/settlement/mod.rs | Adds test helpers to verify winner-selection integration |
| crates/autopilot/src/shadow.rs | Updates to use new Arbitrator constructor |
| crates/autopilot/src/run_loop.rs | Updates to use new Arbitrator constructor |
| crates/autopilot/src/infra/persistence/mod.rs | Imports RankedItem trait from winner-selection |
| crates/autopilot/Cargo.toml | Adds winner-selection dependency |
| Cargo.toml | Adds winner-selection workspace member |
| Cargo.lock | Registers new winner-selection crate |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let multiplied = self.checked_mul(Self::from(factor * CONVERSION_FACTOR))? | ||
| / Self::from(CONVERSION_FACTOR); |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conversion factor calculation may lose precision due to floating-point limitations. The value factor * CONVERSION_FACTOR is computed as a floating-point multiplication before being cast to U256. If factor is very small or very large, this could result in precision loss or overflow in floating-point arithmetic before the conversion. Consider checking for edge cases or documenting the valid range of factor values.
| let multiplied = self.checked_mul(Self::from(factor * CONVERSION_FACTOR))? | |
| / Self::from(CONVERSION_FACTOR); | |
| const U256_CONVERSION_FACTOR: U256 = U256::from(1_000_000_000_000_000_000u128); | |
| // Scale the factor in floating point space, but guard against | |
| // non-finite and out-of-range values before converting to U256. | |
| let scaled = factor * CONVERSION_FACTOR; | |
| if !scaled.is_finite() || scaled < 0.0 || scaled > u128::MAX as f64 { | |
| return None; | |
| } | |
| // Round to the nearest integer to preserve as much precision as possible | |
| // when converting from f64 to an integer type. | |
| let scaled_int = scaled.round() as u128; | |
| let multiplied = self.checked_mul(Self::from(scaled_int))? / U256_CONVERSION_FACTOR; |
Description
One of the prerequisites for integrating the Pod network[more details] is to extract the winner selection logic into a separate crate since the following flow is expected in the future: autopilot sends an auction to all the drivers to solve -> drivers send their solutions to the pod network -> once competition deadline is reached, each driver fetches all submitted solutions from the pod network -> each driver decides whether its solutions are among winning ones. Both driver and autopilot should use the same logic, so a separate crate is introduced in this PR.
Changes
The PR is huge since it mostly moves the code. In any case, I made it as a POC before trying to split it into smaller parts, since this turned out to be non-trivial. I am open to any ideas on how to do this, if ever needed.
How to test
Existing tests