Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
dee28ce
tmp
squadgazzz Dec 24, 2025
e6d60f7
Better logic
squadgazzz Dec 24, 2025
c12bb12
Protocol fees
squadgazzz Dec 24, 2025
decca80
Missing file
squadgazzz Dec 24, 2025
9a91a65
Migrate autopilot
squadgazzz Dec 25, 2025
39b5ca9
Simplified
squadgazzz Dec 25, 2025
e0d08c2
Refactor participant score
squadgazzz Dec 26, 2025
bccdc95
Adopt Unscored
squadgazzz Dec 26, 2025
4f08b1b
Merge branch 'refactor-participant-scores' into winner-selection-crate
squadgazzz Dec 26, 2025
4921a0f
Unscored types
squadgazzz Dec 26, 2025
86c7140
Extract to traits
squadgazzz Dec 26, 2025
768b631
Fix docs
squadgazzz Dec 26, 2025
fef8999
Nits
squadgazzz Dec 26, 2025
6140d10
Nit
squadgazzz Dec 26, 2025
ec59e5d
Merge branch 'refactor-participant-scores' into winner-selection-crate
squadgazzz Dec 29, 2025
906e461
Doc fixes
squadgazzz Dec 30, 2025
40772b3
Drop default state
squadgazzz Dec 30, 2025
dd8b019
Nits
squadgazzz Dec 30, 2025
94ac951
Merge branch 'refactor-participant-scores' into winner-selection-crate
squadgazzz Dec 30, 2025
bbfdfff
nit
squadgazzz Dec 30, 2025
886660b
Merge branch 'refactor-participant-scores' into winner-selection-crate
squadgazzz Dec 30, 2025
d9a5606
Merge branch 'main' into refactor-participant-scores
squadgazzz Dec 30, 2025
7c63b04
Fix
squadgazzz Dec 30, 2025
4e92619
Merge branch 'refactor-participant-scores' into winner-selection-crate
squadgazzz Dec 30, 2025
ce49ae1
Use iterator
squadgazzz Jan 2, 2026
8aa8ebf
Vec capacity
squadgazzz Jan 2, 2026
e79bb54
Merge branch 'refactor-participant-scores' into winner-selection-crate
squadgazzz Jan 2, 2026
4a0cbb7
Nits
squadgazzz Jan 2, 2026
f5d1a4b
Refactor
squadgazzz Jan 2, 2026
7475732
Merge branch 'main' into winner-selection-crate
squadgazzz Jan 2, 2026
62ee779
Extract U256Ext to numbers
squadgazzz Jan 5, 2026
cb9ed55
From traits
squadgazzz Jan 5, 2026
bf379f1
Nit
squadgazzz Jan 5, 2026
cda33f1
Naming
squadgazzz Jan 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ solver = { path = "crates/solver" }
solvers = { path = "crates/solvers" }
solvers-dto = { path = "crates/solvers-dto" }
testlib = { path = "crates/testlib" }
winner-selection = { path = "crates/winner-selection" }
time = "0.3.37"
tiny-keccak = "2.0.2"
tower = "0.4"
Expand Down
1 change: 1 addition & 0 deletions crates/autopilot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ tower-http = { workspace = true, features = ["trace"] }
tracing = { workspace = true }
url = { workspace = true }
web3 = { workspace = true }
winner-selection = { workspace = true }

[dev-dependencies]
mockall = { workspace = true }
Expand Down
86 changes: 29 additions & 57 deletions crates/autopilot/src/domain/competition/participant.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
pub use state::{RankType, Unscored};
use {
super::Score,
crate::{domain::competition::Solution, infra},
::winner_selection::state,
std::sync::Arc,
};

pub type Scored = state::Scored<Score>;
pub type Ranked = state::Ranked<Score>;

/// A solver's solution paired with the driver, progressing through the winner
/// selection process.
///
/// It uses the type-state pattern to enforce correct state
/// transitions at compile time. The state parameter tracks progression through
/// three phases:
///
/// 1. **Unscored**: Initial state when the solution is received from the driver
/// 2. **Scored**: After computing surplus and fees for the solution
/// 3. **Ranked**: After winner selection determines if this is a winner
#[derive(Clone)]
pub struct Participant<State = Ranked> {
solution: Solution,
driver: Arc<infra::Driver>,
state: State,
}

#[derive(Clone)]
pub struct Unscored;

#[derive(Clone)]
pub struct Scored {
pub(super) score: Score,
}

#[derive(Clone)]
pub struct Ranked {
pub(super) rank_type: RankType,
pub(super) score: Score,
}

#[derive(Clone)]
pub enum RankType {
Winner,
NonWinner,
FilteredOut,
}

impl<T> Participant<T> {
pub fn solution(&self) -> &Solution {
&self.solution
Expand All @@ -42,51 +36,29 @@ impl<T> Participant<T> {
}
}

impl Participant<Unscored> {
pub fn new(solution: Solution, driver: Arc<infra::Driver>) -> Self {
Self {
solution,
driver,
state: Unscored,
}
}
impl<State> state::HasState for Participant<State> {
type Next<NewState> = Participant<NewState>;
type State = State;

pub fn with_score(self, score: Score) -> Participant<Scored> {
fn with_state<NewState>(self, state: NewState) -> Self::Next<NewState> {
Participant {
solution: self.solution,
driver: self.driver,
state: Scored { score },
state,
}
}
}

impl Participant<Scored> {
pub fn score(&self) -> Score {
self.state.score
}

pub fn with_rank(self, rank_type: RankType) -> Participant<Ranked> {
Participant {
solution: self.solution,
driver: self.driver,
state: Ranked {
rank_type,
score: self.state.score,
},
}
fn state(&self) -> &Self::State {
&self.state
}
}

impl Participant<Ranked> {
pub fn score(&self) -> Score {
self.state.score
}

pub fn is_winner(&self) -> bool {
matches!(self.state.rank_type, RankType::Winner)
}

pub fn filtered_out(&self) -> bool {
matches!(self.state.rank_type, RankType::FilteredOut)
impl Participant<Unscored> {
pub fn new(solution: Solution, driver: Arc<infra::Driver>) -> Self {
Self {
solution,
driver,
state: Unscored,
}
}
}
Loading
Loading