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

[wip - don't merge] initial bundle sponsorship code #83

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions crates/rbuilder/src/building/order_commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ pub struct TransactionOk {
pub receipt: Receipt,
}

#[derive(Error, Debug, Eq, PartialEq)]
#[derive(Clone, Error, Debug, Eq, PartialEq)]
pub enum TransactionErr {
#[error("Invalid transaction: {0:?}")]
InvalidTransaction(InvalidTransaction),
Expand Down Expand Up @@ -203,7 +203,7 @@ pub struct BundleOk {
pub original_order_ids: Vec<OrderId>,
}

#[derive(Error, Debug, Eq, PartialEq)]
#[derive(Clone, Error, Debug, Eq, PartialEq)]
pub enum BundleErr {
#[error("Invalid transaction, hash: {0:?}, err: {1}")]
InvalidTransaction(B256, TransactionErr),
Expand Down Expand Up @@ -264,7 +264,7 @@ pub struct OrderOk {
pub used_state_trace: Option<UsedStateTrace>,
}

#[derive(Error, Debug, Eq, PartialEq)]
#[derive(Clone, Error, Debug, Eq, PartialEq)]
pub enum OrderErr {
#[error("Transaction error: {0}")]
Transaction(#[from] TransactionErr),
Expand Down
4 changes: 2 additions & 2 deletions crates/rbuilder/src/building/payout_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn create_payout_tx(
signer.sign_tx(tx)
}

#[derive(Debug, thiserror::Error, Eq, PartialEq)]
#[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)]
pub enum PayoutTxErr {
#[error("Reth error: {0}")]
Reth(#[from] ProviderError),
Expand Down Expand Up @@ -92,7 +92,7 @@ pub fn insert_test_payout_tx(
}
}

#[derive(Debug, thiserror::Error, Eq, PartialEq)]
#[derive(Clone, Debug, thiserror::Error, Eq, PartialEq)]
pub enum EstimatePayoutGasErr {
#[error("Reth error: {0}")]
Reth(#[from] ProviderError),
Expand Down
61 changes: 60 additions & 1 deletion crates/rbuilder/src/building/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use super::{
OrderErr, PartialBlockFork,
};
use crate::{
building::{BlockBuildingContext, BlockState, CriticalCommitOrderError},
building::{
BlockBuildingContext, BlockState, BundleErr, CriticalCommitOrderError, InvalidTransaction,
TransactionErr,
},
primitives::{Order, OrderId, SimValue, SimulatedOrder},
utils::{NonceCache, NonceCacheRef},
};
Expand Down Expand Up @@ -404,9 +407,37 @@ pub fn simulate_order(
let mut tracer = AccumulatorSimulationTracer::new();
let mut fork = PartialBlockFork::new(state).with_tracer(&mut tracer);
let rollback_point = fork.rollback_point();
let order_copy = order.clone();
let sim_res = simulate_order_using_fork(parent_orders, order, ctx, &mut fork);
fork.rollback(rollback_point);
let sim_res = sim_res?;
if let OrderSimResult::Failed(err) = &sim_res {
let err_copy = err.clone();
tracing::trace!("Order simulation failed: {}", err);
match err {
OrderErr::Bundle(BundleErr::InvalidTransaction(_, transaction_err))
| OrderErr::Transaction(transaction_err) => { // TODO: add share bundle case
if let TransactionErr::InvalidTransaction(invalid_transaction) = transaction_err {
if let InvalidTransaction::LackOfFundForMaxFee { fee, balance } =
invalid_transaction
{
let balance_needed = **fee - **balance;

tracing::trace!("Order failed due to lack of funds for max fee. Attempting to sponsor. Fee: {}, Balance: {}, Sponsor fee: {}", fee, balance, balance_needed);

let nonce = state.nonce(ctx.builder_signer.as_ref().unwrap().address)?;

let signer = get_tx_signer(order_copy, err_copy);

// TODO: actually sponsor the tx
// I had thought about doing so with create_payout_tx - not sure what the right way to do it is
// We also need an update to OrderSimResult to include sponsorship payment info ("e.g. this tx needs to be sponsored for x amount of ETH")
}
}
}
_ => {}
}
}
Ok(OrderSimResultWithGas {
result: sim_res,
gas_used: tracer.used_gas,
Expand Down Expand Up @@ -467,3 +498,31 @@ pub fn simulate_order_using_fork<Tracer: SimulationTracer>(
Err(err) => Ok(OrderSimResult::Failed(err)),
}
}

fn get_tx_signer(order: Order, order_err: OrderErr) -> Option<Address> {
match order_err {
OrderErr::Bundle(bundle_err) => {
if let BundleErr::InvalidTransaction(tx_hash, _) = bundle_err {
Some(order.get_tx_signer_by_hash(tx_hash).unwrap())
} else {
tracing::trace!("error get_tx_signer: expected invalid transaction and found something that wasn't an invalid transaction");
None
}
}
OrderErr::Transaction(_) => match order.clone() {
Order::Tx(tx) => Some(tx.tx_with_blobs.signer()),
_ => {
tracing::trace!(
"error get_tx_signer: expected tx and found something that wasn't a tx"
);
None
}
},
OrderErr::NegativeProfit(_) => {
tracing::trace!(
"error get_tx_signer: expected tx and found something that wasn't a tx"
);
None
}
}
}
29 changes: 29 additions & 0 deletions crates/rbuilder/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ pub struct Bundle {
}

impl Bundle {
/// Returns the signer of the tx with the given hash.
/// This is used to figure out who to sponsor the tx.
pub fn get_tx_signer_by_hash(&self, hash: B256) -> Option<Address> {
self.txs
.iter()
.find(|tx| tx.hash() == hash)
.map(|tx| tx.signer())
}

pub fn can_execute_with_block_base_fee(&self, block_base_fee: u128) -> bool {
can_execute_with_block_base_fee(self.list_txs(), block_base_fee)
}
Expand Down Expand Up @@ -591,6 +600,26 @@ pub enum OrderReplacementKey {
}

impl Order {
/// Returns the signer of the tx with the given hash.
/// This is used to figure out who to sponsor the tx.
pub fn get_tx_signer_by_hash(&self, hash: B256) -> Option<Address> {
match self {
Order::Bundle(bundle) => bundle.get_tx_signer_by_hash(hash),
Order::Tx(tx) => {
if tx.tx_with_blobs.hash() == hash {
Some(tx.tx_with_blobs.signer())
} else {
None
}
}
Order::ShareBundle(bundle) => bundle
.flatten_txs()
.into_iter()
.find(|(tx, _)| tx.hash() == hash)
.map(|(tx, _)| tx.signer()),
}
}

/// Partial execution is valid as long as some tx is left.
pub fn can_execute_with_block_base_fee(&self, block_base_fee: u128) -> bool {
match self {
Expand Down
Loading