style(txpool): turn InsertResult into std::result::Result (#73)

* refactor(txpool): consider below proto fee cap an error

* style(txpool): turn InsertResult into std::result::Result

* chore: rustfmt

* docs: add missing docs
This commit is contained in:
Matthias Seitz
2022-10-14 21:03:00 +02:00
committed by GitHub
parent 533c3ebe98
commit 2317bcb702

View File

@ -163,7 +163,7 @@ impl<T: TransactionOrdering> TxPool<T> {
let hash = *tx.hash(); let hash = *tx.hash();
match self.all_transactions.insert_tx(tx, on_chain_balance, on_chain_nonce) { match self.all_transactions.insert_tx(tx, on_chain_balance, on_chain_nonce) {
InsertResult::Inserted { transaction, move_to, replaced_tx, updates, .. } => { Ok(InsertOk { transaction, move_to, replaced_tx, updates, .. }) => {
self.add_new_transaction(transaction.clone(), replaced_tx, move_to); self.add_new_transaction(transaction.clone(), replaced_tx, move_to);
let UpdateOutcome { promoted, discarded, removed } = self.process_updates(updates); let UpdateOutcome { promoted, discarded, removed } = self.process_updates(updates);
@ -181,10 +181,10 @@ impl<T: TransactionOrdering> TxPool<T> {
Ok(res) Ok(res)
} }
InsertResult::Underpriced { existing, .. } => { Err(InsertErr::Underpriced { existing, .. }) => {
Err(PoolError::ReplacementUnderpriced(existing)) Err(PoolError::ReplacementUnderpriced(existing))
} }
InsertResult::ProtocolFeeCapTooLow { transaction, fee_cap } => { Err(InsertErr::ProtocolFeeCapTooLow { transaction, fee_cap }) => {
Err(PoolError::ProtocolFeeCapTooLow(*transaction.hash(), fee_cap)) Err(PoolError::ProtocolFeeCapTooLow(*transaction.hash(), fee_cap))
} }
} }
@ -482,7 +482,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
// Check dynamic fee // Check dynamic fee
if let Some(fee_cap) = transaction.max_fee_per_gas() { if let Some(fee_cap) = transaction.max_fee_per_gas() {
if fee_cap < self.minimal_protocol_basefee { if fee_cap < self.minimal_protocol_basefee {
return InsertResult::ProtocolFeeCapTooLow { transaction, fee_cap } return Err(InsertErr::ProtocolFeeCapTooLow { transaction, fee_cap })
} }
if fee_cap >= self.pending_basefee { if fee_cap >= self.pending_basefee {
state.insert(TxState::ENOUGH_FEE_CAP_BLOCK); state.insert(TxState::ENOUGH_FEE_CAP_BLOCK);
@ -517,10 +517,10 @@ impl<T: PoolTransaction> AllTransactions<T> {
// Transaction already exists // Transaction already exists
// Ensure the new transaction is not underpriced // Ensure the new transaction is not underpriced
if transaction.is_underpriced(entry.get().transaction.as_ref()) { if transaction.is_underpriced(entry.get().transaction.as_ref()) {
return InsertResult::Underpriced { return Err(InsertErr::Underpriced {
transaction: pool_tx.transaction, transaction: pool_tx.transaction,
existing: *entry.get().transaction.hash(), existing: *entry.get().transaction.hash(),
} })
} }
let new_hash = *pool_tx.transaction.hash(); let new_hash = *pool_tx.transaction.hash();
let new_transaction = pool_tx.transaction.clone(); let new_transaction = pool_tx.transaction.clone();
@ -587,7 +587,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
self.tx_inc(tx_id.sender); self.tx_inc(tx_id.sender);
} }
InsertResult::Inserted { transaction, move_to: state.into(), state, replaced_tx, updates } Ok(InsertOk { transaction, move_to: state.into(), state, replaced_tx, updates })
} }
/// Rechecks the transaction of the given sender and returns a set of updates. /// Rechecks the transaction of the given sender and returns a set of updates.
@ -642,18 +642,12 @@ pub(crate) struct PoolUpdate {
pub(crate) destination: Destination, pub(crate) destination: Destination,
} }
/// The outcome of [TxPool::insert_tx] /// Result type for inserting a transaction
pub(crate) type InsertResult<T> = Result<InsertOk<T>, InsertErr<T>>;
/// Err variant of `InsertResult`
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum InsertResult<T: PoolTransaction> { pub(crate) enum InsertErr<T: PoolTransaction> {
/// Transaction was successfully inserted into the pool
Inserted {
transaction: Arc<ValidPoolTransaction<T>>,
move_to: SubPool,
state: TxState,
replaced_tx: Option<(Arc<ValidPoolTransaction<T>>, SubPool)>,
/// Additional updates to transactions affected by this change.
updates: Vec<PoolUpdate>,
},
/// Attempted to replace existing transaction, but was underpriced /// Attempted to replace existing transaction, but was underpriced
Underpriced { transaction: Arc<ValidPoolTransaction<T>>, existing: TxHash }, Underpriced { transaction: Arc<ValidPoolTransaction<T>>, existing: TxHash },
/// The transactions feeCap is lower than the chain's minimum fee requirement. /// The transactions feeCap is lower than the chain's minimum fee requirement.
@ -662,17 +656,19 @@ pub(crate) enum InsertResult<T: PoolTransaction> {
ProtocolFeeCapTooLow { transaction: Arc<ValidPoolTransaction<T>>, fee_cap: U256 }, ProtocolFeeCapTooLow { transaction: Arc<ValidPoolTransaction<T>>, fee_cap: U256 },
} }
// === impl InsertResult === /// Transaction was successfully inserted into the pool
#[derive(Debug)]
// Some test helpers pub(crate) struct InsertOk<T: PoolTransaction> {
#[allow(missing_docs)] /// Ref to the inserted transaction.
#[cfg(test)] transaction: Arc<ValidPoolTransaction<T>>,
impl<T: PoolTransaction> InsertResult<T> { /// Where to move the transaction to.
/// Returns true if the result is underpriced variant move_to: SubPool,
/// Current state of the inserted tx.
pub(crate) fn is_underpriced(&self) -> bool { state: TxState,
matches!(self, InsertResult::Underpriced { .. }) /// The transaction that was replaced by this.
} replaced_tx: Option<(Arc<ValidPoolTransaction<T>>, SubPool)>,
/// Additional updates to transactions affected by this change.
updates: Vec<PoolUpdate>,
} }
/// The internal transaction typed used by `AllTransactions` which also additional info used for /// The internal transaction typed used by `AllTransactions` which also additional info used for
@ -782,19 +778,14 @@ mod tests {
let mut pool = AllTransactions::default(); let mut pool = AllTransactions::default();
let tx = MockTransaction::eip1559().inc_price().inc_limit(); let tx = MockTransaction::eip1559().inc_price().inc_limit();
let valid_tx = f.validated(tx.clone()); let valid_tx = f.validated(tx.clone());
let res = pool.insert_tx(valid_tx.clone(), on_chain_balance, on_chain_nonce); let InsertOk { updates, replaced_tx, move_to, state, .. } =
match res { pool.insert_tx(valid_tx.clone(), on_chain_balance, on_chain_nonce).unwrap();
InsertResult::Inserted { updates, replaced_tx, move_to, state, .. } => { assert!(updates.is_empty());
assert!(updates.is_empty()); assert!(replaced_tx.is_none());
assert!(replaced_tx.is_none()); assert!(state.contains(TxState::NO_NONCE_GAPS));
assert!(state.contains(TxState::NO_NONCE_GAPS)); assert!(!state.contains(TxState::ENOUGH_BALANCE));
assert!(!state.contains(TxState::ENOUGH_BALANCE)); assert_eq!(move_to, SubPool::Queued);
assert_eq!(move_to, SubPool::Queued);
}
_ => {
panic!("not underpriced")
}
};
assert_eq!(pool.len(), 1); assert_eq!(pool.len(), 1);
assert!(pool.contains(valid_tx.hash())); assert!(pool.contains(valid_tx.hash()));
let expected_state = TxState::ENOUGH_FEE_CAP_BLOCK | TxState::NO_NONCE_GAPS; let expected_state = TxState::ENOUGH_FEE_CAP_BLOCK | TxState::NO_NONCE_GAPS;
@ -803,23 +794,19 @@ mod tests {
// insert the same tx again // insert the same tx again
let res = pool.insert_tx(valid_tx, on_chain_balance, on_chain_nonce); let res = pool.insert_tx(valid_tx, on_chain_balance, on_chain_nonce);
assert!(res.is_underpriced()); assert!(res.is_err());
assert_eq!(pool.len(), 1); assert_eq!(pool.len(), 1);
let valid_tx = f.validated(tx.next()); let valid_tx = f.validated(tx.next());
let res = pool.insert_tx(valid_tx.clone(), on_chain_balance, on_chain_nonce); let InsertOk { updates, replaced_tx, move_to, state, .. } =
match res { pool.insert_tx(valid_tx.clone(), on_chain_balance, on_chain_nonce).unwrap();
InsertResult::Inserted { updates, replaced_tx, move_to, state, .. } => {
assert!(updates.is_empty()); assert!(updates.is_empty());
assert!(replaced_tx.is_none()); assert!(replaced_tx.is_none());
assert!(state.contains(TxState::NO_NONCE_GAPS)); assert!(state.contains(TxState::NO_NONCE_GAPS));
assert!(!state.contains(TxState::ENOUGH_BALANCE)); assert!(!state.contains(TxState::ENOUGH_BALANCE));
assert_eq!(move_to, SubPool::Queued); assert_eq!(move_to, SubPool::Queued);
}
_ => {
panic!("not underpriced")
}
};
assert!(pool.contains(valid_tx.hash())); assert!(pool.contains(valid_tx.hash()));
assert_eq!(pool.len(), 2); assert_eq!(pool.len(), 2);
let inserted = pool.get(valid_tx.id()).unwrap(); let inserted = pool.get(valid_tx.id()).unwrap();
@ -836,17 +823,12 @@ mod tests {
let first = f.validated(tx.clone()); let first = f.validated(tx.clone());
let _res = pool.insert_tx(first.clone(), on_chain_balance, on_chain_nonce); let _res = pool.insert_tx(first.clone(), on_chain_balance, on_chain_nonce);
let replacement = f.validated(tx.rng_hash().inc_price()); let replacement = f.validated(tx.rng_hash().inc_price());
let res = pool.insert_tx(replacement.clone(), on_chain_balance, on_chain_nonce); let InsertOk { updates, replaced_tx, .. } =
match res { pool.insert_tx(replacement.clone(), on_chain_balance, on_chain_nonce).unwrap();
InsertResult::Inserted { updates, replaced_tx, .. } => { assert!(updates.is_empty());
assert!(updates.is_empty()); let replaced = replaced_tx.unwrap();
let replaced = replaced_tx.unwrap(); assert_eq!(replaced.0.hash(), first.hash());
assert_eq!(replaced.0.hash(), first.hash());
}
_ => {
panic!("is inserted")
}
};
assert!(!pool.contains(first.hash())); assert!(!pool.contains(first.hash()));
assert!(pool.contains(replacement.hash())); assert!(pool.contains(replacement.hash()));
assert_eq!(pool.len(), 1); assert_eq!(pool.len(), 1);
@ -868,20 +850,14 @@ mod tests {
assert!(!first_in_pool.state.contains(TxState::NO_NONCE_GAPS)); assert!(!first_in_pool.state.contains(TxState::NO_NONCE_GAPS));
let prev = f.validated(tx.prev()); let prev = f.validated(tx.prev());
let res = pool.insert_tx(prev, on_chain_balance, on_chain_nonce); let InsertOk { updates, replaced_tx, state, move_to, .. } =
pool.insert_tx(prev, on_chain_balance, on_chain_nonce).unwrap();
match res { // no updates since still in queued pool
InsertResult::Inserted { updates, replaced_tx, state, move_to, .. } => { assert!(updates.is_empty());
// no updates since still in queued pool assert!(replaced_tx.is_none());
assert!(updates.is_empty()); assert!(state.contains(TxState::NO_NONCE_GAPS));
assert!(replaced_tx.is_none()); assert_eq!(move_to, SubPool::Queued);
assert!(state.contains(TxState::NO_NONCE_GAPS));
assert_eq!(move_to, SubPool::Queued);
}
_ => {
panic!("is inserted")
}
};
let first_in_pool = pool.get(first.id()).unwrap(); let first_in_pool = pool.get(first.id()).unwrap();
// has non nonce gap // has non nonce gap
@ -897,7 +873,7 @@ mod tests {
let mut pool = AllTransactions::default(); let mut pool = AllTransactions::default();
let tx = MockTransaction::eip1559().inc_nonce().set_gas_price(100u64.into()).inc_limit(); let tx = MockTransaction::eip1559().inc_nonce().set_gas_price(100u64.into()).inc_limit();
let first = f.validated(tx.clone()); let first = f.validated(tx.clone());
let _res = pool.insert_tx(first.clone(), on_chain_balance, on_chain_nonce); let _res = pool.insert_tx(first.clone(), on_chain_balance, on_chain_nonce).unwrap();
let first_in_pool = pool.get(first.id()).unwrap(); let first_in_pool = pool.get(first.id()).unwrap();
// has nonce gap // has nonce gap
@ -905,20 +881,14 @@ mod tests {
assert_eq!(SubPool::Queued, first_in_pool.subpool); assert_eq!(SubPool::Queued, first_in_pool.subpool);
let prev = f.validated(tx.prev()); let prev = f.validated(tx.prev());
let res = pool.insert_tx(prev, on_chain_balance, on_chain_nonce); let InsertOk { updates, replaced_tx, state, move_to, .. } =
pool.insert_tx(prev, on_chain_balance, on_chain_nonce).unwrap();
match res { // updated previous tx
InsertResult::Inserted { updates, replaced_tx, state, move_to, .. } => { assert_eq!(updates.len(), 1);
// updated previous tx assert!(replaced_tx.is_none());
assert_eq!(updates.len(), 1); assert!(state.contains(TxState::NO_NONCE_GAPS));
assert!(replaced_tx.is_none()); assert_eq!(move_to, SubPool::Pending);
assert!(state.contains(TxState::NO_NONCE_GAPS));
assert_eq!(move_to, SubPool::Pending);
}
_ => {
panic!("is inserted")
}
};
let first_in_pool = pool.get(first.id()).unwrap(); let first_in_pool = pool.get(first.id()).unwrap();
// has non nonce gap // has non nonce gap