chore: add eip4844 nonce gap error (#4414)

This commit is contained in:
Matthias Seitz
2023-08-30 16:13:27 -07:00
committed by GitHub
parent 3088104a6d
commit e33e3c9154
3 changed files with 28 additions and 7 deletions

View File

@ -520,6 +520,9 @@ impl From<InvalidPoolTransactionError> for RpcPoolError {
InvalidPoolTransactionError::InvalidEip4844Blob(err) => {
RpcPoolError::InvalidEip4844Blob(err)
}
InvalidPoolTransactionError::Eip4844NonceGap => {
RpcPoolError::Invalid(RpcInvalidTransactionError::NonceTooHigh)
}
}
}
}

View File

@ -144,6 +144,14 @@ pub enum InvalidPoolTransactionError {
/// Thrown if validating the blob sidecar for the transaction failed.
#[error(transparent)]
InvalidEip4844Blob(BlobTransactionValidationError),
/// EIP-4844 transactions are only accepted if they're gapless, meaning the previous nonce of
/// the transaction (`tx.nonce -1`) must either be in the pool or match the on chain nonce of
/// the sender.
///
/// This error is thrown on validation if a valid blob transaction arrives with a nonce that
/// would introduce gap in the nonce sequence.
#[error("Nonce too high.")]
Eip4844NonceGap,
/// Any other error that occurred while inserting/validating that is transaction specific
#[error("{0:?}")]
Other(Box<dyn PoolTransactionError>),
@ -210,6 +218,11 @@ impl InvalidPoolTransactionError {
// This is only reachable when the blob is invalid
true
}
InvalidPoolTransactionError::Eip4844NonceGap => {
// it is possible that the pool sees `nonce n` before `nonce n-1` and this is only
// thrown for valid(good) blob transactions
false
}
}
}
}

View File

@ -1085,7 +1085,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
false
}
/// Inserts a new transaction into the pool.
/// Inserts a new _valid_ transaction into the pool.
///
/// If the transaction already exists, it will be replaced if not underpriced.
/// Returns info to which sub-pool the transaction should be moved.
@ -1104,13 +1104,16 @@ impl<T: PoolTransaction> AllTransactions<T> {
assert!(on_chain_nonce <= transaction.nonce(), "Invalid transaction");
let transaction = Arc::new(self.ensure_valid(transaction)?);
let tx_id = *transaction.id();
let inserted_tx_id = *transaction.id();
let mut state = TxState::default();
let mut cumulative_cost = U256::ZERO;
let mut updates = Vec::new();
let ancestor =
TransactionId::ancestor(transaction.transaction.nonce(), on_chain_nonce, tx_id.sender);
let ancestor = TransactionId::ancestor(
transaction.transaction.nonce(),
on_chain_nonce,
inserted_tx_id.sender,
);
// If there's no ancestor tx then this is the next transaction.
if ancestor.is_none() {
@ -1133,6 +1136,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
state.insert(TxState::NOT_TOO_MUCH_GAS);
}
// placeholder for the replaced transaction, if any
let mut replaced_tx = None;
let pool_tx = PoolInternalTransaction {
@ -1175,6 +1179,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
// The next transaction of this sender
let on_chain_id = TransactionId::new(transaction.sender_id(), on_chain_nonce);
{
// get all transactions of the sender's account
let mut descendants = self.descendant_txs_mut(&on_chain_id).peekable();
// Tracks the next nonce we expect if the transactions are gapless
@ -1189,7 +1194,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
// SAFETY: the transaction was added above so the _inclusive_ descendants iterator
// returns at least 1 tx.
let (id, tx) = descendants.peek().expect("Includes >= 1; qed.");
if id.nonce < tx_id.nonce {
if id.nonce < inserted_tx_id.nonce {
!tx.state.is_pending()
} else {
true
@ -1232,7 +1237,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
// update the pool based on the state
tx.subpool = tx.state.into();
if tx_id.eq(id) {
if inserted_tx_id.eq(id) {
// if it is the new transaction, track the state
state = tx.state;
} else {
@ -1254,7 +1259,7 @@ impl<T: PoolTransaction> AllTransactions<T> {
// If this wasn't a replacement transaction we need to update the counter.
if replaced_tx.is_none() {
self.tx_inc(tx_id.sender);
self.tx_inc(inserted_tx_id.sender);
}
Ok(InsertOk { transaction, move_to: state.into(), state, replaced_tx, updates })