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

Spawn executor in transaction pool #25

Open
emhane opened this issue Jan 17, 2025 · 5 comments
Open

Spawn executor in transaction pool #25

emhane opened this issue Jan 17, 2025 · 5 comments
Assignees
Labels
A-execution Related to execution and EVM A-tx-pool Related to transaction pool D-interop-devnet Planned for interop-devnet

Comments

@emhane
Copy link
Member

emhane commented Jan 17, 2025

Describe the feature

Spawn executor inside of OpTransactionValidator::validate_one to execute the transactions on the current state. Discard transactions that fail execution.

/// Validates a single transaction.
///
/// See also [`TransactionValidator::validate_transaction`]
///
/// This behaves the same as [`EthTransactionValidator::validate_one`], but in addition, ensures
/// that the account has enough balance to cover the L1 gas cost.
pub fn validate_one(
&self,
origin: TransactionOrigin,
transaction: Tx,
) -> TransactionValidationOutcome<Tx> {
if transaction.is_eip4844() {
return TransactionValidationOutcome::Invalid(
transaction,
InvalidTransactionError::TxTypeNotSupported.into(),
)
}
let outcome = self.inner.validate_one(origin, transaction);
if !self.requires_l1_data_gas_fee() {
// no need to check L1 gas fee
return outcome
}
// ensure that the account has enough balance to cover the L1 gas cost
if let TransactionValidationOutcome::Valid {
balance,
state_nonce,
transaction: valid_tx,
propagate,
} = outcome
{
let mut l1_block_info = self.block_info.l1_block_info.read().clone();
let mut encoded = Vec::with_capacity(valid_tx.transaction().encoded_length());
let tx = valid_tx.transaction().clone_into_consensus();
tx.encode_2718(&mut encoded);
let cost_addition = match l1_block_info.l1_tx_data_fee(
self.chain_spec(),
self.block_timestamp(),
&encoded,
false,
) {
Ok(cost) => cost,
Err(err) => {
return TransactionValidationOutcome::Error(*valid_tx.hash(), Box::new(err))
}
};
let cost = valid_tx.transaction().cost().saturating_add(cost_addition);
// Checks for max cost
if cost > balance {
return TransactionValidationOutcome::Invalid(
valid_tx.into_transaction(),
InvalidTransactionError::InsufficientFunds(
GotExpected { got: balance, expected: cost }.into(),
)
.into(),
)
}
return TransactionValidationOutcome::Valid {
balance,
state_nonce,
transaction: valid_tx,
propagate,
}
}
outcome
}

Note: use trait bound OpTransactionValidator<Client: StateProviderFactory, ..>

check out how it's done in rpc for trace_filter (https://www.quicknode.com/docs/ethereum/trace_filter)

// replay all transactions of the block
self.spawn_tracing(move |this| {
// we need to get the state of the parent block because we're replaying this block
// on top of its parent block's state
let state_at = block.parent_hash();
let block_hash = block.hash();
let block_number = block_env.number.saturating_to::<u64>();
let base_fee = block_env.basefee.saturating_to::<u128>();
// now get the state
let state = this.state_at_block_id(state_at.into())?;
let mut db =
CacheDB::new(StateProviderDatabase::new(StateProviderTraitObjWrapper(&state)));
this.apply_pre_execution_changes(
&block,
&mut db,
&cfg_env_with_handler_cfg,
&block_env,
)?;
// prepare transactions, we do everything upfront to reduce time spent with open
// state
let max_transactions =
highest_index.map_or(block.body().transactions().len(), |highest| {
// we need + 1 because the index is 0-based
highest as usize + 1
});
let mut results = Vec::with_capacity(max_transactions);
let mut transactions = block
.transactions_with_sender()
.take(max_transactions)
.enumerate()
.map(|(idx, (signer, tx))| {
let tx_info = TransactionInfo {
hash: Some(*tx.tx_hash()),
index: Some(idx as u64),
block_hash: Some(block_hash),
block_number: Some(block_number),
base_fee: Some(base_fee),
};
let tx_env = this.evm_config().tx_env(tx, *signer);
(tx_info, tx_env)
})
.peekable();
while let Some((tx_info, tx)) = transactions.next() {
let env = EnvWithHandlerCfg::new_with_cfg_env(
cfg_env_with_handler_cfg.clone(),
block_env.clone(),
tx,
);
let mut inspector = inspector_setup();
let (res, _) =
this.inspect(StateCacheDbRefMutWrapper(&mut db), env, &mut inspector)?;
let ResultAndState { result, state } = res;
results.push(f(tx_info, inspector, result, &state, &db)?);
// need to apply the state changes of this transaction before executing the
// next transaction, but only if there's a next transaction
if transactions.peek().is_some() {
// commit the state changes to the DB
db.commit(state)
}
}
Ok(Some(results))
})
.await

Additional context

Following issue will also use maili API to determine validity of the executed transaction, ref op-rs/maili#98

@emhane emhane added the A-execution Related to execution and EVM label Jan 17, 2025
@emhane emhane added A-tx-pool Related to transaction pool D-interop-devnet Planned for interop-devnet labels Jan 17, 2025
@emhane
Copy link
Member Author

emhane commented Jan 17, 2025

use branch interop-devnet-X as base

@mattsse
Copy link

mattsse commented Jan 17, 2025

this is already performed on a validation task

@emhane
Copy link
Member Author

emhane commented Jan 21, 2025

links pls @mattsse ?

@emhane
Copy link
Member Author

emhane commented Jan 23, 2025

https://github.com/paradigmxyz/reth/blob/6dabd5244ebe206eddea1679996c3f9cc78ffb8b/crates/optimism/node/src/node.rs#L362-L366

this is just configures the number of validation tasks, I don't see anywhere to pass a hook to tx pool validation to perform an extra task? cc @Rjected

refcell added a commit that referenced this issue Jan 31, 2025
### Description

Closes #25

Spawns an executor in transaction validation.

---------

Co-authored-by: Emilia Hane <elsaemiliaevahane@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-execution Related to execution and EVM A-tx-pool Related to transaction pool D-interop-devnet Planned for interop-devnet
Projects
None yet
Development

No branches or pull requests

3 participants