Skip to content

wip: feat(txpool): initial sketch#7

Merged
mattsse merged 40 commits intomainfrom
matt/add-tx-pool
Oct 7, 2022
Merged

wip: feat(txpool): initial sketch#7
mattsse merged 40 commits intomainfrom
matt/add-tx-pool

Conversation

@mattsse
Copy link
Collaborator

@mattsse mattsse commented Sep 29, 2022

WIP...

interesting, looks like you can't create draft PRs in private repos.

Update:

  • queued pool
  • pending pool
    • base fee subpool to park transactions until feeCap>= baseFee
  • pool api
  • enforce size limits
  • ...

@mattsse mattsse changed the title feat(txpool): initial sketch wip: feat(txpool): initial sketch Sep 29, 2022
@rkrasiuk
Copy link
Contributor

rkrasiuk commented Oct 3, 2022

@mattsse the org has to be on paid plan to be able to make draft PRs in private repos

@mattsse
Copy link
Collaborator Author

mattsse commented Oct 6, 2022

@rakita opening this up for review, however there are still some things missing and things I want to change, especially when it comes to how transactions are stored.

this started out as a modification of the pool we wrote for anvil which works like a graph, where a transaction can depend on a previous transaction, and unlock the following transaction.

For this, there are a few more things to consider like dynamic fee, balance, which are not handled yet.

erigon's txpool is essentially a BTreeMap<(sender, nonce), Tx> and the Tx references the sub-pool where the transaction is currently stored. go's BTreeMap allows traversing the map in both directions starting at a given key, which is used to find all dependent transactions of a (sender, nonce) pair efficiently when the pool needs to update after a new block was mined.

This currently references the next transaction by storing its (sender, nonce) id.

So basically erigon can cheaply update account changes because there's a sender -> transactions mapping, whereas this is currently like tx -> next tx, which would make maintaining things like cumulative gas used more expensive.

trying to come up with a solution for this

EDIT: just found out you can do something like this with rust's BTreeMap via: map.range(..key).next_back().unwrap() so I'll try to refactor internals and store all transactions as (sender, nonce) => TX with a reference to the subpools

Also, this still needs a bunch of tests.

@mattsse mattsse requested a review from rakita October 6, 2022 13:58
Copy link
Collaborator

@rakita rakita left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was hard for me to wrap my head around this, there seems like there are things in need of cleanup or simplification. There are a lot of pools and new transaction types. SenderId is weird one, why not just use the account address? Parity really knows how to overcomplicate things :).

Maybe the best path is to merge this as it is, and continue working on it there, wdyt @mattsse?


/// The interface used to interact with the blockchain and access storage.
#[async_trait::async_trait]
pub trait PoolClient: Send + Sync + TransactionValidator {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is TransactionValidator needed here?

fn ensure_block_number(&self, block_id: &BlockID) -> PoolResult<U64> {
self.convert_block_id(block_id)
.and_then(|number| number.ok_or(PoolError::BlockNumberNotFound(*block_id)))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: we probably need account_info(address) to get the account nonce and balance.

type Error: Into<PoolError>;

/// Returns the block number for the given block identifier.
fn convert_block_id(&self, block_id: &BlockID) -> PoolResult<Option<U64>>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if i understand why would we need get block number and mapping of hash->height. TxPool should only care about base_fee and transactions that are removed/added, and that is broadcasted to txpool on block inclusion.

///
/// This assigns a _unique_ `SenderId` for a new `Address`.
#[derive(Debug)]
pub struct SenderIdentifiers {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I searched code and this seems not used

/// This is the identifier of an internal `address` mapping that is valid in the context of this
/// program.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct SenderId(u64);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like there is some internal mapping that uses SenderId, and it is used inside TransactionId as a field.
GraphPool has it as sender_info but it seems like it is not used, maybe it is just a leftover, that still needs impl to be used.

//! In essence the transaction pool is made of two separate sub-pools:
//!
//! _Pending Pool_: Contains all transactions that are valid on the current state and satisfy
//! (3. a)(1): _No_ nonce gaps _Queued Pool_: Contains all transactions that are currently
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! (3. a)(1): _No_ nonce gaps _Queued Pool_: Contains all transactions that are currently
//! (3. a)(1): _No_ nonce gaps
//! _Queued Pool_: Contains all transactions that are currently

///
/// This pool maintains a dependency graph of transactions and provides the currently ready
/// transactions.
pub struct GraphPool<T: TransactionOrdering> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main pool that is inside PoolInner that contains all data/Transaction


/// A reference to a transaction in the _pending_ pool
#[derive(Debug)]
pub(crate) struct PoolTransactionRef<T: TransactionOrdering> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of transaction types, maybe we can consolidate them into one that is easier to follow. It is just an idea, unsure if it is good.

///
/// This will be an empty list if there are no nonce gaps across multiple transactions of the
/// same sender in the pool. If there are gaps, this will include the missing transactions.
pub(crate) missing_dependencies: HashSet<TransactionId>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TransactionId contains of SenderId (that is internal u64) and nonce, we probably need account address to verify dependencies

/// Returns the EIP-1559 Priority fee the caller is paying to the block author.
///
/// This will return `None` for non-EIP1559 transactions
fn max_priority_fee_per_gas(&self) -> Option<&U256>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is something called effective gas price that for new transactions is base_fee+max_priority_fee_per_gas and for legact transaction this is gas_price, this was used to sort transactions inside pool.

@mattsse
Copy link
Collaborator Author

mattsse commented Oct 7, 2022

It was hard for me to wrap my head around this, there seems like there are things in need of cleanup or simplification.

Definitely. Need to refactor some internals to handle things like base fee and balance. I'm currently in the process of integrating some designs that erigon took. which will eventually replace the GraphPool.

There are a lot of pools and new transaction types. SenderId is weird one, why not just use the account address?

idea was that this would reduce an Address to a simple u64, but since of the maps used are BTreeMap, perhaps this doesn't even matter much.

Parity really knows how to overcomplicate things :).

Maybe the best path is to merge this as it is, and continue working on it there, wdyt @mattsse?

sgtm! I'll merge this as is, and follow up with additional PRs.

@mattsse mattsse merged commit 791ee28 into main Oct 7, 2022
@mattsse mattsse deleted the matt/add-tx-pool branch October 7, 2022 20:00
clabby added a commit to clabby/reth that referenced this pull request Aug 13, 2023
Resolution checkpoint

Resolution checkpoint paradigmxyz#2

Resolution checkpoint paradigmxyz#3

x

Resolution checkpoint paradigmxyz#4

Resolution checkpoint paradigmxyz#5

Resolution checkpoint paradigmxyz#6

Resolution checkpoint paradigmxyz#7

Resolution checkpoint paradigmxyz#8

Resolve checkpoint paradigmxyz#9 (transaction primitive)

Resolve checkpoint paradigmxyz#10 (rpc api transactions)

Resolve checkpoint paradigmxyz#11 (building w/o feature flag)

Start review

Compiling with and without `optimism` feature flag

Remove `DepositTx` from txpool mock tests, they never go into the txpool

fmt

code lint

fix signature tests

Co-authored-by: nicolas <48695862+merklefruit@users.noreply.github.com>

Use free CI runners (revert before upstream)

Co-authored-by: refcell <abigger87@gmail.com>

Signature test fixes

Co-authored-by refcell <abigger87@gmail.com>

Fix Receipt proptest

Co-authored-by BB <brian.t.bland@gmail.com>

lint

Fix variable-length compact for txtype/transaction

Co-authored-by: Brian Bland <brian.t.bland@gmail.com>

Fix basefee tests

Remove unnecessary rpc deps

Co-authored-by: Brian Bland <brian.t.bland@gmail.com>
Co-authored-by: refcell <abigger87@gmail.com>
Co-authored-by: nicolas <48695862+merklefruit@users.noreply.github.com>
Co-authored-by: Roberto <bayardo@alum.mit.edu>
clabby added a commit to clabby/reth that referenced this pull request Aug 13, 2023
Resolution checkpoint

Resolution checkpoint paradigmxyz#2

Resolution checkpoint paradigmxyz#3

x

Resolution checkpoint paradigmxyz#4

Resolution checkpoint paradigmxyz#5

Resolution checkpoint paradigmxyz#6

Resolution checkpoint paradigmxyz#7

Resolution checkpoint paradigmxyz#8

Resolve checkpoint paradigmxyz#9 (transaction primitive)

Resolve checkpoint paradigmxyz#10 (rpc api transactions)

Resolve checkpoint paradigmxyz#11 (building w/o feature flag)

Start review

Compiling with and without `optimism` feature flag

Remove `DepositTx` from txpool mock tests, they never go into the txpool

fmt

code lint

fix signature tests

Co-authored-by: nicolas <48695862+merklefruit@users.noreply.github.com>

Use free CI runners (revert before upstream)

Co-authored-by: refcell <abigger87@gmail.com>

Signature test fixes

Co-authored-by refcell <abigger87@gmail.com>

Fix Receipt proptest

Co-authored-by BB <brian.t.bland@gmail.com>

lint

Fix variable-length compact for txtype/transaction

Co-authored-by: Brian Bland <brian.t.bland@gmail.com>

Fix basefee tests

Remove unnecessary rpc deps

Co-authored-by: Brian Bland <brian.t.bland@gmail.com>
Co-authored-by: refcell <abigger87@gmail.com>
Co-authored-by: nicolas <48695862+merklefruit@users.noreply.github.com>
Co-authored-by: Roberto <bayardo@alum.mit.edu>
anonymousGiga added a commit to anonymousGiga/reth that referenced this pull request Feb 20, 2024
* add feature 'enable_tps_gas_record'

* format and rebase code

---------

Co-authored-by: anonymousGiga <cryptonymGong@gmail.com>
yutianwu pushed a commit to yutianwu/reth that referenced this pull request Jun 5, 2024
AshinGau added a commit to AshinGau/reth that referenced this pull request Sep 12, 2024
…mxyz#7)

Concurrent verification of transaction finality state
AshinGau added a commit to AshinGau/reth that referenced this pull request Oct 13, 2024
…mxyz#7)

Concurrent verification of transaction finality state
jenpaff pushed a commit that referenced this pull request Oct 6, 2025
* upstreamed to alloy

* upstreamed to alloy
joshieDo added a commit that referenced this pull request Feb 4, 2026
…length

- Issue #5: Add flush_current_changeset_offset() before reading sidecar
  in truncate_changesets() to ensure in-memory offset is written
- Issue #7: Use ChangesetOffsetReader::with_len() instead of new() to
  respect committed length from header, ignoring uncommitted records
- Add regression tests for both issues
- Update changeset-healing-review.md to reflect 17 tests
- Remove unused variables in tests
AnilChinchawale added a commit to AnilChinchawale/reth that referenced this pull request Mar 2, 2026
…aradigmxyz#7 slow re-download

- Issue paradigmxyz#6 downgraded P0→P3: bad FCU feeder was the cause (all 3 hashes same)
- Fixed reth-fcu-feeder.py to use genesis as finalizedBlockHash
- Pipeline completes ALL 13 stages with single FCU (1M+ blocks!)
- Added Issue paradigmxyz#7: reverse headers downloader extremely slow after restart
- Updated status and strategy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants