From bd205300a36670a4413d71f065c89740d525db71 Mon Sep 17 00:00:00 2001 From: Dusan Stanivukovic Date: Fri, 10 Nov 2023 15:08:47 +0100 Subject: [PATCH] Colocation - Notify asset flow (#2053) # Description Noticed that some of the solvers are not populating `inputs` and `outputs` fields in `interactions` data, leading to solutions from these solvers being discarded in colocated driver. This PR adds a new notification type to inform solvers about their bad expectation, but is also useful for debugging in case a solver does not populate these fields (since the missmatches will be full amounts of tokens in that case). Missmatches take the range `[-U256, U256]` so `String` seemed like the easiest way to serialize it. --- crates/driver/src/infra/notify/mod.rs | 2 +- crates/driver/src/infra/notify/notification.rs | 7 ++++++- .../src/infra/solver/dto/notification.rs | 11 ++++++++++- crates/shared/src/http_solver/model.rs | 5 +++++ .../src/api/routes/notify/dto/notification.rs | 18 +++++++++++++++++- crates/solvers/src/api/routes/notify/mod.rs | 2 +- crates/solvers/src/api/routes/solve/mod.rs | 2 +- crates/solvers/src/boundary/legacy.rs | 6 ++++++ crates/solvers/src/domain/notification.rs | 4 +++- 9 files changed, 50 insertions(+), 7 deletions(-) diff --git a/crates/driver/src/infra/notify/mod.rs b/crates/driver/src/infra/notify/mod.rs index 77b6c18ac4..82c8169bd3 100644 --- a/crates/driver/src/infra/notify/mod.rs +++ b/crates/driver/src/infra/notify/mod.rs @@ -77,7 +77,7 @@ pub fn encoding_failed( notification::Kind::SimulationFailed(error.tx.clone()) } solution::Error::Simulation(simulator::Error::Basic(_)) => return, - solution::Error::AssetFlow(_) => return, + solution::Error::AssetFlow(missmatch) => notification::Kind::AssetFlow(missmatch.clone()), solution::Error::Execution(_) => return, solution::Error::FailingInternalization => return, solution::Error::DifferentSolvers => return, diff --git a/crates/driver/src/infra/notify/notification.rs b/crates/driver/src/infra/notify/notification.rs index d804ef4443..220237088a 100644 --- a/crates/driver/src/infra/notify/notification.rs +++ b/crates/driver/src/infra/notify/notification.rs @@ -3,13 +3,14 @@ use { competition::{auction, score::Quality, solution, Score}, eth::{self, Ether, GasCost, TokenAddress}, }, - std::collections::BTreeSet, + std::collections::{BTreeSet, HashMap}, }; type RequiredEther = Ether; type TokensUsed = BTreeSet; type TransactionHash = eth::TxId; type Transaction = eth::Tx; +type Missmatches = HashMap; /// A notification sent to solvers in case of important events in the driver. #[derive(Debug)] @@ -36,6 +37,10 @@ pub enum Kind { NonBufferableTokensUsed(TokensUsed), /// Solver don't have enough balance to submit the solution onchain. SolverAccountInsufficientBalance(RequiredEther), + /// For some of the tokens used in the solution, the amount leaving the + /// settlement contract is higher than amount entering the settlement + /// contract. + AssetFlow(Missmatches), /// Result of winning solver trying to settle the transaction onchain. Settled(Settlement), } diff --git a/crates/driver/src/infra/solver/dto/notification.rs b/crates/driver/src/infra/solver/dto/notification.rs index c45ecf92cc..3bcb77e2b4 100644 --- a/crates/driver/src/infra/solver/dto/notification.rs +++ b/crates/driver/src/infra/solver/dto/notification.rs @@ -9,7 +9,7 @@ use { }, serde::Serialize, serde_with::serde_as, - std::collections::BTreeSet, + std::collections::{BTreeSet, HashMap}, web3::types::AccessList, }; @@ -62,6 +62,12 @@ impl Notification { required: required.0, } } + notify::Kind::AssetFlow(amounts) => Kind::AssetFlow { + amounts: amounts + .into_iter() + .map(|(token, amount)| (token.0 .0, amount.to_string())) + .collect(), + }, notify::Kind::DuplicatedSolutionId => Kind::DuplicatedSolutionId, notify::Kind::Settled(kind) => Kind::Settled(match kind { notify::Settlement::Success(hash) => Settlement::Success { @@ -103,6 +109,9 @@ pub enum Kind { #[serde_as(as = "serialize::U256")] required: eth::U256, }, + AssetFlow { + amounts: HashMap, + }, Settled(Settlement), } diff --git a/crates/shared/src/http_solver/model.rs b/crates/shared/src/http_solver/model.rs index fb4aa2b322..e8b8aa4292 100644 --- a/crates/shared/src/http_solver/model.rs +++ b/crates/shared/src/http_solver/model.rs @@ -486,6 +486,11 @@ pub enum SolverRejectionReason { /// Solver balance too low to cover the execution costs. SolverAccountInsufficientBalance(U256), + /// For some of the tokens used in the solution, the amount leaving the + /// settlement contract is higher than amount entering the settlement + /// contract. + AssetFlow(HashMap), + /// Solution received from solver engine don't have unique id. DuplicatedSolutionId(u64), } diff --git a/crates/solvers/src/api/routes/notify/dto/notification.rs b/crates/solvers/src/api/routes/notify/dto/notification.rs index ede2b5f228..8381be51cc 100644 --- a/crates/solvers/src/api/routes/notify/dto/notification.rs +++ b/crates/solvers/src/api/routes/notify/dto/notification.rs @@ -3,10 +3,11 @@ use { domain::{auction, eth, notification}, util::serialize, }, + bigdecimal::Num, ethereum_types::{H160, H256, U256}, serde::Deserialize, serde_with::{serde_as, DisplayFromStr}, - std::collections::BTreeSet, + std::collections::{BTreeSet, HashMap}, web3::types::AccessList, }; @@ -67,6 +68,18 @@ impl Notification { Kind::SolverAccountInsufficientBalance { required } => { notification::Kind::SolverAccountInsufficientBalance(eth::Ether(*required)) } + Kind::AssetFlow { amounts } => notification::Kind::AssetFlow( + amounts + .clone() + .into_iter() + .map(|(token, amount)| { + ( + token.into(), + num::BigInt::from_str_radix(&amount, 10).unwrap_or_default(), + ) + }) + .collect(), + ), Kind::DuplicatedSolutionId => notification::Kind::DuplicatedSolutionId, Kind::Settled(kind) => notification::Kind::Settled(match kind { Settlement::Success { transaction } => { @@ -109,6 +122,9 @@ pub enum Kind { #[serde_as(as = "serialize::U256")] required: U256, }, + AssetFlow { + amounts: HashMap, + }, Settled(Settlement), } diff --git a/crates/solvers/src/api/routes/notify/mod.rs b/crates/solvers/src/api/routes/notify/mod.rs index 49f94356a9..f2e47b52a9 100644 --- a/crates/solvers/src/api/routes/notify/mod.rs +++ b/crates/solvers/src/api/routes/notify/mod.rs @@ -10,7 +10,7 @@ pub async fn notify( let notification = notification.to_domain(); let auction_id = notification.auction_id; - tracing::info!(id = %auction_id, "auction"); + tracing::trace!(?auction_id, ?notification); state.notify(notification); axum::http::StatusCode::OK diff --git a/crates/solvers/src/api/routes/solve/mod.rs b/crates/solvers/src/api/routes/solve/mod.rs index 53b6a25060..786800e9c6 100644 --- a/crates/solvers/src/api/routes/solve/mod.rs +++ b/crates/solvers/src/api/routes/solve/mod.rs @@ -31,7 +31,7 @@ pub async fn solve( .instrument(tracing::info_span!("auction", id = %auction_id)) .await; - tracing::trace!(?solutions); + tracing::trace!(?auction_id, ?solutions); let solutions = dto::Solutions::from_domain(&solutions); ( diff --git a/crates/solvers/src/boundary/legacy.rs b/crates/solvers/src/boundary/legacy.rs index 1863a0931b..3f245346e7 100644 --- a/crates/solvers/src/boundary/legacy.rs +++ b/crates/solvers/src/boundary/legacy.rs @@ -643,6 +643,12 @@ fn to_boundary_auction_result(notification: ¬ification::Notification) -> (i64 Kind::SolverAccountInsufficientBalance(required) => AuctionResult::Rejected( SolverRejectionReason::SolverAccountInsufficientBalance(required.0), ), + Kind::AssetFlow(amounts) => AuctionResult::Rejected(SolverRejectionReason::AssetFlow( + amounts + .iter() + .map(|(token, amount)| (token.0, amount.to_string())) + .collect(), + )), Kind::DuplicatedSolutionId => { AuctionResult::Rejected(SolverRejectionReason::DuplicatedSolutionId( notification diff --git a/crates/solvers/src/domain/notification.rs b/crates/solvers/src/domain/notification.rs index 5d2c75da8e..f115bac5c6 100644 --- a/crates/solvers/src/domain/notification.rs +++ b/crates/solvers/src/domain/notification.rs @@ -4,13 +4,14 @@ use { eth::{self, Ether, TokenAddress}, solution::{self, SuccessProbability}, }, - std::collections::BTreeSet, + std::collections::{BTreeSet, HashMap}, }; type RequiredEther = Ether; type TokensUsed = BTreeSet; type TransactionHash = eth::H256; type Transaction = eth::Tx; +type Missmatches = HashMap; /// The notification about important events happened in driver, that solvers /// need to know about. @@ -31,6 +32,7 @@ pub enum Kind { ScoringFailed(ScoreKind), NonBufferableTokensUsed(TokensUsed), SolverAccountInsufficientBalance(RequiredEther), + AssetFlow(Missmatches), Settled(Settlement), }