Skip to content
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

Colocation Notify - failed simulation #2013

Merged
merged 11 commits into from
Nov 1, 2023
1 change: 1 addition & 0 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions crates/driver/src/domain/competition/solution/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,9 @@ pub enum Error {
#[error(transparent)]
Execution(#[from] trade::ExecutionError),
#[error(
"invalid internalization: solution attempts to internalize tokens which are not trusted"
"non bufferable tokens used: solution attempts to internalize tokens which are not trusted"
)]
UntrustedInternalization(BTreeSet<TokenAddress>),
NonBufferableTokensUsed(BTreeSet<TokenAddress>),
#[error("invalid internalization: uninternalized solution fails to simulate")]
FailingInternalization,
#[error("insufficient solver account Ether balance, required {0:?}")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl Settlement {
.map(|asset| asset.token)
.collect::<BTreeSet<_>>();
if !untrusted_tokens.is_empty() {
return Err(Error::UntrustedInternalization(untrusted_tokens));
return Err(Error::NonBufferableTokensUsed(untrusted_tokens));
}

// Encode the solution into a settlement.
Expand Down
43 changes: 21 additions & 22 deletions crates/driver/src/infra/notify/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ use {
mod notification;

pub use notification::{Kind, Notification, ScoreKind, Settlement};

use crate::domain::{competition::score, eth, mempools::Error};
use {
super::simulator,
crate::domain::{competition::score, eth, mempools::Error},
};

pub fn solver_timeout(solver: &Solver, auction_id: Option<auction::Id>) {
solver.notify(auction_id, None, notification::Kind::Timeout);
Expand Down Expand Up @@ -59,29 +61,26 @@ pub fn encoding_failed(
solution_id: solution::Id,
err: &solution::Error,
) {
match err {
solution::Error::UntrustedInternalization(tokens) => {
solver.notify(
auction_id,
Some(solution_id),
notification::Kind::NonBufferableTokensUsed(tokens.clone()),
);
let notification = match err {
solution::Error::NonBufferableTokensUsed(tokens) => {
notification::Kind::NonBufferableTokensUsed(tokens.clone())
}
solution::Error::SolverAccountInsufficientBalance(required) => {
solver.notify(
auction_id,
Some(solution_id),
notification::Kind::SolverAccountInsufficientBalance(*required),
);
notification::Kind::SolverAccountInsufficientBalance(*required)
}
solution::Error::Blockchain(_) => (),
solution::Error::Boundary(_) => (),
solution::Error::Simulation(_) => (), // todo,
solution::Error::AssetFlow(_) => (),
solution::Error::Execution(_) => (),
solution::Error::FailingInternalization => (),
solution::Error::DifferentSolvers => (),
}
solution::Error::Blockchain(_) => return,
solution::Error::Boundary(_) => return,
solution::Error::Simulation(simulator::Error::WithTx(error)) => {
notification::Kind::SimulationFailed(error.tx.clone())
}
solution::Error::Simulation(simulator::Error::Basic(_)) => return,
solution::Error::AssetFlow(_) => return,
solution::Error::Execution(_) => return,
solution::Error::FailingInternalization => return,
solution::Error::DifferentSolvers => return,
};

solver.notify(auction_id, Some(solution_id), notification);
}

pub fn executed(
Expand Down
12 changes: 7 additions & 5 deletions crates/driver/src/infra/notify/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ use {
std::collections::BTreeSet,
};

type RequiredEther = Ether;
type TokensUsed = BTreeSet<TokenAddress>;
type TransactionHash = eth::TxId;
type Transaction = eth::Tx;

/// A notification sent to solvers in case of important events in the driver.
#[derive(Debug)]
pub struct Notification {
Expand All @@ -14,9 +19,6 @@ pub struct Notification {
pub kind: Kind,
}

pub type RequiredEther = Ether;
pub type TokensUsed = BTreeSet<TokenAddress>;

#[derive(Debug)]
pub enum Kind {
/// Solver engine timed out.
Expand All @@ -25,6 +27,8 @@ pub enum Kind {
EmptySolution,
/// Solution received from solver engine don't have unique id.
DuplicatedSolutionId,
/// Failed simulation during competition.
SimulationFailed(Transaction),
/// No valid score could be computed for the solution.
ScoringFailed(ScoreKind),
/// Solution aimed to internalize tokens that are not considered safe to
Expand Down Expand Up @@ -60,8 +64,6 @@ pub enum ScoreKind {
ObjectiveValueNonPositive,
}

type TransactionHash = eth::TxId;

#[derive(Debug)]
pub enum Settlement {
/// Winning solver settled successfully transaction onchain.
Expand Down
8 changes: 4 additions & 4 deletions crates/driver/src/infra/simulator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,17 +142,17 @@ pub enum SimulatorError {
#[derive(Debug, thiserror::Error)]
#[error("err: {err:?}, tx: {tx:?}")]
pub struct WithTxError {
err: SimulatorError,
tx: eth::Tx,
pub err: SimulatorError,
pub tx: eth::Tx,
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("basic: {0:?}")]
#[error(transparent)]
Basic(#[from] SimulatorError),
/// If a transaction reverted, forward that transaction together with the
/// error.
#[error("with tx: {0:?}")]
#[error(transparent)]
WithTx(#[from] WithTxError),
}

Expand Down
22 changes: 22 additions & 0 deletions crates/driver/src/infra/solver/dto/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use {
serde::Serialize,
serde_with::serde_as,
std::collections::BTreeSet,
web3::types::AccessList,
};

impl Notification {
Expand All @@ -24,6 +25,13 @@ impl Notification {
kind: match kind {
notify::Kind::Timeout => Kind::Timeout,
notify::Kind::EmptySolution => Kind::EmptySolution,
notify::Kind::SimulationFailed(tx) => Kind::SimulationFailed(Tx {
from: tx.from.into(),
to: tx.to.into(),
input: tx.input.into(),
value: tx.value.into(),
access_list: tx.access_list.into(),
}),
notify::Kind::ScoringFailed(notify::ScoreKind::ZeroScore) => {
Kind::ScoringFailed(ScoreKind::ZeroScore)
}
Expand Down Expand Up @@ -82,6 +90,7 @@ pub enum Kind {
Timeout,
EmptySolution,
DuplicatedSolutionId,
SimulationFailed(Tx),
ScoringFailed(ScoreKind),
NonBufferableTokensUsed {
tokens: BTreeSet<eth::H160>,
Expand All @@ -93,6 +102,19 @@ pub enum Kind {
Settled(Settlement),
}

#[serde_as]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Tx {
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
pub from: eth::H160,
pub to: eth::H160,
#[serde_as(as = "serialize::Hex")]
pub input: Vec<u8>,
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
#[serde_as(as = "serialize::U256")]
pub value: eth::U256,
pub access_list: AccessList,
}

#[serde_as]
#[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")]
Expand Down
2 changes: 2 additions & 0 deletions crates/shared/src/http_solver/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ pub struct SimulatedTransaction {
/// on
pub tx_index: u64,
/// Is transaction simulated with internalized interactions or without
/// TODO: remove field once the colocation is enabled.
pub internalization: InternalizationStrategy,
/// Which storage the settlement tries to access. Contains `None` if some
/// error happened while estimating the access list.
Expand Down Expand Up @@ -536,6 +537,7 @@ pub enum InternalizationStrategy {
EncodeAllInteractions,
#[serde(rename = "Enabled")]
SkipInternalizableInteraction,
Unknown,
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions crates/solvers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal", "tim
toml = "0.7"
tower = "0.4"
tower-http = { version = "0.4", features = ["trace"] }
web3 = "0.19"

# TODO Once solvers are ported and E2E tests set up, slowly migrate code and
# remove/re-evaluate these dependencies.
Expand Down
22 changes: 22 additions & 0 deletions crates/solvers/src/api/routes/notify/dto/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use {
serde::Deserialize,
serde_with::{serde_as, DisplayFromStr},
std::collections::BTreeSet,
web3::types::AccessList,
};

impl Notification {
Expand All @@ -21,6 +22,13 @@ impl Notification {
kind: match &self.kind {
Kind::Timeout => notification::Kind::Timeout,
Kind::EmptySolution => notification::Kind::EmptySolution,
Kind::SimulationFailed(tx) => notification::Kind::SimulationFailed(eth::Tx {
from: tx.from.into(),
to: tx.to.into(),
input: tx.input.clone().into(),
value: tx.value.into(),
access_list: tx.access_list.clone(),
}),
Kind::ScoringFailed(ScoreKind::ObjectiveValueNonPositive) => {
notification::Kind::ScoringFailed(
notification::ScoreKind::ObjectiveValueNonPositive,
Expand Down Expand Up @@ -89,6 +97,7 @@ pub enum Kind {
Timeout,
EmptySolution,
DuplicatedSolutionId,
SimulationFailed(Tx),
ScoringFailed(ScoreKind),
NonBufferableTokensUsed {
tokens: BTreeSet<H160>,
Expand All @@ -100,6 +109,19 @@ pub enum Kind {
Settled(Settlement),
}

#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Tx {
from: H160,
to: H160,
#[serde_as(as = "serialize::Hex")]
input: Vec<u8>,
#[serde_as(as = "serialize::U256")]
value: U256,
access_list: AccessList,
}

#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
Expand Down
21 changes: 21 additions & 0 deletions crates/solvers/src/boundary/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,19 @@ use {
BatchAuctionModel,
ConcentratedPoolParameters,
ConstantProductPoolParameters,
InternalizationStrategy,
MetadataModel,
OrderModel,
Score,
SettledBatchAuctionModel,
SimulatedTransaction,
SolverRejectionReason,
SolverRunError,
StablePoolParameters,
SubmissionResult,
TokenAmount,
TokenInfoModel,
TransactionWithError,
WeightedPoolTokenData,
WeightedProductPoolParameters,
},
Expand Down Expand Up @@ -572,6 +575,8 @@ fn to_domain_solution(
})
}

const UNKNOWN_BLOCK_NUMBER: u64 = 0;

fn to_boundary_auction_result(notification: &notification::Notification) -> (i64, AuctionResult) {
let auction_id = match notification.auction_id {
auction::Id::Solve(id) => id,
Expand All @@ -583,6 +588,22 @@ fn to_boundary_auction_result(notification: &notification::Notification) -> (i64
AuctionResult::Rejected(SolverRejectionReason::RunError(SolverRunError::Timeout))
}
Kind::EmptySolution => AuctionResult::Rejected(SolverRejectionReason::NoUserOrders),
Kind::SimulationFailed(tx) => AuctionResult::Rejected(
SolverRejectionReason::SimulationFailure(TransactionWithError {
error: "".to_string(),
transaction: SimulatedTransaction {
from: tx.from.into(),
to: tx.to.into(),
data: tx.input.clone().into(),
internalization: InternalizationStrategy::Unknown,
block_number: UNKNOWN_BLOCK_NUMBER, // todo #2018
tx_index: Default::default(),
sunce86 marked this conversation as resolved.
Show resolved Hide resolved
access_list: Default::default(),
max_fee_per_gas: Default::default(),
max_priority_fee_per_gas: Default::default(),
},
}),
),
Kind::ScoringFailed(ScoreKind::ObjectiveValueNonPositive) => {
AuctionResult::Rejected(SolverRejectionReason::ObjectiveValueNonPositive)
}
Expand Down
34 changes: 34 additions & 0 deletions crates/solvers/src/domain/eth/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use {crate::util::bytes::Bytes, web3::types::AccessList};

mod chain;

pub use {
Expand Down Expand Up @@ -37,9 +39,41 @@ pub struct Asset {
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Ether(pub U256);

impl From<U256> for Ether {
fn from(value: U256) -> Self {
Self(value)
}
}

/// Gas amount.
#[derive(Clone, Copy, Debug, Default)]
pub struct Gas(pub U256);

/// A 256-bit rational type.
pub type Rational = num::rational::Ratio<U256>;

/// An address. Can be an EOA or a smart contract address.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Address(pub H160);

impl From<H160> for Address {
fn from(value: H160) -> Self {
Self(value)
}
}

impl From<Address> for H160 {
fn from(value: Address) -> Self {
value.0
}
}

/// An onchain transaction.
#[derive(Debug, Clone)]
pub struct Tx {
pub from: Address,
pub to: Address,
pub value: Ether,
pub input: Bytes<Vec<u8>>,
pub access_list: AccessList,
}
Loading
Loading