From 3690ba5182d4cc3e77e70d18d2072575fdf0ce97 Mon Sep 17 00:00:00 2001 From: Dusan Stanivukovic Date: Fri, 18 Oct 2024 15:13:09 +0200 Subject: [PATCH] Solution_id is integer (#3071) # Description Related to https://github.com/cowprotocol/services/issues/3064 This PR enables driver to send either string or integer for `solution_id`. This PR marks the start of transition period. Once the PR is merged, external solvers will be asked to: 1. Start sending `solution_id` as integer in `/solve` response. 2. Implement receiving either string or integer for `solution_id` on `/reveal` and on `/settle`. Once done, backend will have a [follow up](https://github.com/cowprotocol/services/issues/3072) where we will definitely switch to using integers in all three endpoints and https://github.com/cowprotocol/services/issues/3064 will be fixed. ## How to test Manually checked that both versions are properly serialized/deserialized. --- .../autopilot/src/infra/solvers/dto/solve.rs | 33 ++++++++++++++++++- crates/driver/openapi.yml | 4 +-- .../src/infra/api/routes/solve/dto/solved.rs | 1 - crates/driver/src/tests/setup/mod.rs | 3 +- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/crates/autopilot/src/infra/solvers/dto/solve.rs b/crates/autopilot/src/infra/solvers/dto/solve.rs index 04670462bd..693fec6d76 100644 --- a/crates/autopilot/src/infra/solvers/dto/solve.rs +++ b/crates/autopilot/src/infra/solvers/dto/solve.rs @@ -170,7 +170,7 @@ pub enum Side { pub struct Solution { /// Unique ID of the solution (per driver competition), used to identify /// it in subsequent requests (reveal, settle). - #[serde_as(as = "serde_with::DisplayFromStr")] + #[serde(deserialize_with = "deserialize_solution_id")] pub solution_id: u64, #[serde_as(as = "HexOrDecimalU256")] pub score: U256, @@ -182,6 +182,37 @@ pub struct Solution { pub gas: Option, } +fn deserialize_solution_id<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + struct SolutionIdVisitor; + + impl<'de> serde::de::Visitor<'de> for SolutionIdVisitor { + type Value = u64; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a string or integer representing a solution ID") + } + + fn visit_u64(self, value: u64) -> Result + where + E: serde::de::Error, + { + Ok(value) + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + value.parse::().map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_any(SolutionIdVisitor) +} + #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Response { diff --git a/crates/driver/openapi.yml b/crates/driver/openapi.yml index 27a2f7d665..91f8037113 100644 --- a/crates/driver/openapi.yml +++ b/crates/driver/openapi.yml @@ -382,8 +382,8 @@ components: The unique identifier of the solution. This id is used to identify the solution when executing it. - type: string - example: "1" + type: integer + example: 1 score: description: | The objective value of the solution. diff --git a/crates/driver/src/infra/api/routes/solve/dto/solved.rs b/crates/driver/src/infra/api/routes/solve/dto/solved.rs index 43692d7125..6b91523be0 100644 --- a/crates/driver/src/infra/api/routes/solve/dto/solved.rs +++ b/crates/driver/src/infra/api/routes/solve/dto/solved.rs @@ -70,7 +70,6 @@ type OrderId = [u8; order::UID_LEN]; pub struct Solution { /// Unique ID of the solution (per driver competition), used to identify it /// in subsequent requests (reveal, settle). - #[serde_as(as = "serde_with::DisplayFromStr")] solution_id: u64, #[serde_as(as = "serialize::U256")] score: eth::U256, diff --git a/crates/driver/src/tests/setup/mod.rs b/crates/driver/src/tests/setup/mod.rs index 9f1526c33b..8dba9197b0 100644 --- a/crates/driver/src/tests/setup/mod.rs +++ b/crates/driver/src/tests/setup/mod.rs @@ -1193,7 +1193,8 @@ impl<'a> SolveOk<'a> { solution .get("solutionId") .unwrap() - .as_str() + .as_u64() + .map(|id| id.to_string()) .unwrap() .to_owned() }