Skip to content

Commit

Permalink
perf: skip conflict checks for external transactins (#1627)
Browse files Browse the repository at this point in the history
  • Loading branch information
dinhani-cw authored Aug 12, 2024
1 parent 27b3b6d commit d4fca19
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/eth/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ impl Executor {

// persist state
let tx_execution = TransactionExecution::External(tx_execution);
self.miner.save_execution(tx_execution)?;
self.miner.save_execution(tx_execution, false)?;

// track metrics
#[cfg(feature = "metrics")]
Expand Down Expand Up @@ -497,7 +497,7 @@ impl Executor {
// save execution to temporary storage
// in case of failure, retry if conflict or abandon if unexpected error
let tx_execution = TransactionExecution::new_local(tx_input.clone(), evm_result.clone());
match self.miner.save_execution(tx_execution.clone()) {
match self.miner.save_execution(tx_execution.clone(), true) {
Ok(_) => {
return Ok(tx_execution);
}
Expand Down
4 changes: 2 additions & 2 deletions src/eth/miner/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl Miner {
}

/// Persists a transaction execution.
pub fn save_execution(&self, tx_execution: TransactionExecution) -> Result<(), StratusError> {
pub fn save_execution(&self, tx_execution: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError> {
// track
#[cfg(feature = "tracing")]
let _span = info_span!("miner::save_execution", tx_hash = %tx_execution.hash()).entered();
Expand All @@ -106,7 +106,7 @@ impl Miner {

// save execution to temporary storage
let tx_hash = tx_execution.hash();
self.storage.save_execution(tx_execution)?;
self.storage.save_execution(tx_execution, check_conflicts)?;

// if automine is enabled, automatically mines a block
let _ = self.notifier_pending_txs.send(tx_hash);
Expand Down
22 changes: 12 additions & 10 deletions src/eth/storage/inmemory/inmemory_temporary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,13 @@ impl TemporaryStorage for InMemoryTemporaryStorage {
Ok(())
}

fn save_execution(&self, tx: TransactionExecution) -> Result<(), StratusError> {
fn save_execution(&self, tx: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError> {
// check conflicts
let mut states = self.lock_write();
if let Some(conflicts) = check_conflicts(&states, tx.execution()) {
return Err(StratusError::TransactionConflict(conflicts.into()));
if check_conflicts {
if let Some(conflicts) = do_check_conflicts(&states, tx.execution()) {
return Err(StratusError::TransactionConflict(conflicts.into()));
}
}

// save account changes
Expand Down Expand Up @@ -226,12 +228,12 @@ impl TemporaryStorage for InMemoryTemporaryStorage {

fn read_account(&self, address: &Address) -> anyhow::Result<Option<Account>> {
let states = self.lock_read();
Ok(read_account(&states, address))
Ok(do_read_account(&states, address))
}

fn read_slot(&self, address: &Address, index: &SlotIndex) -> anyhow::Result<Option<Slot>> {
let states = self.lock_read();
Ok(read_slot(&states, address, index))
Ok(do_read_slot(&states, address, index))
}

// -------------------------------------------------------------------------
Expand All @@ -248,7 +250,7 @@ impl TemporaryStorage for InMemoryTemporaryStorage {
// -----------------------------------------------------------------------------
// Implementations without lock
// -----------------------------------------------------------------------------
fn read_account(states: &NonEmpty<InMemoryTemporaryStorageState>, address: &Address) -> Option<Account> {
fn do_read_account(states: &NonEmpty<InMemoryTemporaryStorageState>, address: &Address) -> Option<Account> {
// search all
for state in states.iter() {
let Some(account) = state.accounts.get(address) else { continue };
Expand All @@ -271,7 +273,7 @@ fn read_account(states: &NonEmpty<InMemoryTemporaryStorageState>, address: &Addr
None
}

fn read_slot(states: &NonEmpty<InMemoryTemporaryStorageState>, address: &Address, index: &SlotIndex) -> Option<Slot> {
fn do_read_slot(states: &NonEmpty<InMemoryTemporaryStorageState>, address: &Address, index: &SlotIndex) -> Option<Slot> {
// search all
for state in states.iter() {
let Some(account) = state.accounts.get(address) else { continue };
Expand All @@ -286,12 +288,12 @@ fn read_slot(states: &NonEmpty<InMemoryTemporaryStorageState>, address: &Address
None
}

fn check_conflicts(states: &NonEmpty<InMemoryTemporaryStorageState>, execution: &EvmExecution) -> Option<ExecutionConflicts> {
fn do_check_conflicts(states: &NonEmpty<InMemoryTemporaryStorageState>, execution: &EvmExecution) -> Option<ExecutionConflicts> {
let mut conflicts = ExecutionConflictsBuilder::default();

for (address, change) in &execution.changes {
// check account info conflicts
if let Some(account) = read_account(states, address) {
if let Some(account) = do_read_account(states, address) {
if let Some(expected) = change.nonce.take_original_ref() {
let original = &account.nonce;
if expected != original {
Expand All @@ -309,7 +311,7 @@ fn check_conflicts(states: &NonEmpty<InMemoryTemporaryStorageState>, execution:
// check slots conflicts
for (slot_index, slot_change) in &change.slots {
if let Some(expected) = slot_change.take_original_ref() {
let Some(original) = read_slot(states, address, slot_index) else {
let Some(original) = do_read_slot(states, address, slot_index) else {
continue;
};
if expected.value != original.value {
Expand Down
4 changes: 2 additions & 2 deletions src/eth/storage/stratus_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,12 +324,12 @@ impl StratusStorage {
// Blocks
// -------------------------------------------------------------------------

pub fn save_execution(&self, tx: TransactionExecution) -> Result<(), StratusError> {
pub fn save_execution(&self, tx: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError> {
#[cfg(feature = "tracing")]
let _span = tracing::info_span!("storage::save_execution", tx_hash = %tx.hash()).entered();
tracing::debug!(storage = %label::TEMP, tx_hash = %tx.hash(), "saving execution");

timed(|| self.temp.save_execution(tx))
timed(|| self.temp.save_execution(tx, check_conflicts))
.with(|m| {
metrics::inc_storage_save_execution(m.elapsed, label::TEMP, m.result.is_ok());
if let Err(ref e) = m.result {
Expand Down
2 changes: 1 addition & 1 deletion src/eth/storage/temporary_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub trait TemporaryStorage: Send + Sync + 'static {
fn set_pending_external_block(&self, block: ExternalBlock) -> anyhow::Result<()>;

/// Saves a re-executed transaction to the pending mined block.
fn save_execution(&self, tx: TransactionExecution) -> Result<(), StratusError>;
fn save_execution(&self, tx: TransactionExecution, check_conflicts: bool) -> Result<(), StratusError>;

/// Retrieves the pending transactions of the pending block.
fn pending_transactions(&self) -> anyhow::Result<Vec<TransactionExecution>>;
Expand Down

0 comments on commit d4fca19

Please sign in to comment.