Skip to content

Commit

Permalink
Save solver competition from autopilot (#1741)
Browse files Browse the repository at this point in the history
Progress on #1672

Fixes #1614 (solver
competition part, since observations part is done).
  • Loading branch information
sunce86 authored Aug 8, 2023
1 parent ed86f6f commit b26eea8
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 17 deletions.
9 changes: 8 additions & 1 deletion crates/autopilot/src/database/competition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use {
settlement_scores::Score,
},
derivative::Derivative,
model::order::OrderUid,
model::{order::OrderUid, solver_competition::SolverCompetitionDB},
number_conversions::u256_to_big_decimal,
primitive_types::{H160, U256},
std::collections::{BTreeMap, HashSet},
Expand Down Expand Up @@ -52,6 +52,7 @@ pub struct Competition {
/// Uninternalized winner settlement call data
#[derivative(Debug(format_with = "shared::debug_bytes"))]
pub uninternalized_call_data: Vec<u8>,
pub competition_table: SolverCompetitionDB,
}

impl super::Postgres {
Expand All @@ -61,8 +62,14 @@ impl super::Postgres {
.with_label_values(&["save_competition"])
.start_timer();

let json = &serde_json::to_value(&competition.competition_table)?;

let mut ex = self.0.begin().await.context("begin")?;

database::solver_competition::save(&mut ex, competition.auction_id, json)
.await
.context("solver_competition::save")?;

for order_execution in &competition.order_executions {
let (solver_fee, surplus_fee) = match order_execution.executed_fee {
ExecutedFee::Solver(solver_fee) => (solver_fee, None),
Expand Down
59 changes: 52 additions & 7 deletions crates/autopilot/src/run_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ use {
auction::{Auction, AuctionId},
interaction::InteractionData,
order::{LimitOrderClass, OrderClass},
solver_competition::{
CompetitionAuction,
Order,
Score,
SolverCompetitionDB,
SolverSettlement,
},
},
primitive_types::{H160, H256},
rand::seq::SliceRandom,
Expand Down Expand Up @@ -93,7 +100,7 @@ impl RunLoop {
.collect();

// TODO: Keep going with other solutions until some deadline.
if let Some((index, solution)) = solutions.pop() {
if let Some((index, solution)) = solutions.last() {
// The winner has score 0 so all solutions are empty.
if solution.score == 0.into() {
return;
Expand All @@ -104,15 +111,14 @@ impl RunLoop {
let winner = solution.submission_address;
let winning_score = solution.score;
let reference_score = solutions
.last()
.iter()
.nth_back(1)
.map(|(_, response)| response.score)
.unwrap_or_default();
let mut participants = solutions
let participants = solutions
.iter()
.map(|(_, response)| response.submission_address)
.collect::<HashSet<_>>();
participants.insert(solution.submission_address); // add winner as participant

let mut prices = BTreeMap::new();
let block_deadline = competition_simulation_block
+ self.submission_deadline
Expand Down Expand Up @@ -169,6 +175,44 @@ impl RunLoop {
}
}
}
let competition_table = SolverCompetitionDB {
competition_simulation_block,
auction: CompetitionAuction {
orders: auction
.orders
.iter()
.map(|order| order.metadata.uid)
.collect(),
prices: auction.prices.clone(),
},
solutions: solutions
.iter()
.map(|(index, response)| SolverSettlement {
solver_address: response.submission_address,
score: Some(Score::Solver(response.score)),
ranking: Some(solutions.len() - index),
orders: response
.orders
.iter()
.map(|o| Order {
id: *o,
// TODO: revisit once colocation is enabled (remove not populated
// fields) Not all fields can be
// populated in the colocated world
..Default::default()
})
.collect(),
call_data: response.calldata.internalized.clone(),
uninternalized_call_data: Some(response.calldata.uninternalized.clone()),
// TODO: revisit once colocation is enabled (remove not populated fields)
// Not all fields can be populated in the colocated world
..Default::default()
})
.collect(),
// TODO: revisit once colocation is enabled (remove not populated fields)
// Not all fields can be populated in the colocated world
..Default::default()
};
let competition = Competition {
auction_id,
winner,
Expand All @@ -181,15 +225,16 @@ impl RunLoop {
competition_simulation_block,
call_data,
uninternalized_call_data,
competition_table,
};
tracing::info!(?competition, "saving competition");
if let Err(err) = self.save_competition(&competition).await {
tracing::error!(?err, "failed to save competition");
return;
}

tracing::info!(url = %self.drivers[index].url, "settling with solver");
match self.settle(id, &self.drivers[index], &solution).await {
tracing::info!(url = %self.drivers[*index].url, "settling with solver");
match self.settle(id, &self.drivers[*index], solution).await {
Ok(()) => (),
Err(err) => {
tracing::error!(?err, "solver {index} failed to settle");
Expand Down
15 changes: 6 additions & 9 deletions crates/e2e/tests/e2e/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ pub struct Cip20Data {
pub score: database::settlement_scores::Score,
pub trades: Vec<database::orders::OrderExecution>,
pub call_data: database::settlement_call_data::SettlementCallData,
// TODO add this when we eventually store the competition data
// pub competition: serde_json::Value,
pub competition: serde_json::Value,
}

/// Returns `Some(data)` if the all the expected CIP-20 data has been indexed
Expand Down Expand Up @@ -87,12 +86,10 @@ WHERE at.auction_id = $1
let call_data = database::settlement_call_data::fetch(&mut db, auction_id)
.await
.unwrap()?;

// TODO add this when we eventually store the competition data
// let competition = database::solver_competition::load_by_id(&mut db,
// auction_id) .await
// .unwrap()?
// .json;
let competition = database::solver_competition::load_by_id(&mut db, auction_id)
.await
.unwrap()?
.json;

Some(Cip20Data {
observation,
Expand All @@ -102,6 +99,6 @@ WHERE at.auction_id = $1
score,
trades,
call_data,
// competition,
competition,
})
}

0 comments on commit b26eea8

Please sign in to comment.