-
Notifications
You must be signed in to change notification settings - Fork 106
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
Refactor mempool tests #2771
Refactor mempool tests #2771
Conversation
In #2770 I created a test that had to split the tx list in three parts (the first, the rest except the last, the last, and a reference to the second-to-last). I tried to come up with a non "C-like" way that did not uses indices everywhere, but it relied on some |
An attempt to improve readability a bit by not returning a tuple with a value that can be obtained from a single return type.
Use a more functional style to try to make it a bit clearer.
Allow a finer control over the block range to extract the transactions from.
It was previously not clear that only the first genesis transaction was being used. The remaining transactions in the genesis block were discarded and then readded later.
Remove a redundant internal `ready_and` call.
Remove unnecessary deserializations and heap allocations.
Make the separation between the transactions expected to be in the mempool and those expected to be rejected clearer.
Allow getting the last transaction more easily.
052c49d
to
43fac9b
Compare
Interesting problem! Regarding keeping the return type as let mut transactions = unmined_transactions_in_blocks(height, network);
let first_transaction = transactions.next().unwrap();
let last_transaction = transactions.next_back().unwrap();
// Then use the "middle" transactions in `transactions` Another option for when the iterator is not a let mut transactions = unmined_transactions_in_blocks(height, network);
let first_transactions = transactions.next().unwrap();
let mut transactions: Vec<_> = transactions.collect();
let last_transaction = transactions.pop().unwrap(); I updated the PR to return a |
That's great, the best of both worlds 😁 |
I don't mind what you do here - whatever works best for writing tests. But I want to encourage you to merge this refactor soon, so it doesn't block other work, or cause rework. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes are good to me.
|
||
// Insert them all to the storage | ||
for unmined_transaction in unmined_transactions.clone() { | ||
storage.insert(unmined_transaction)?; | ||
} | ||
|
||
// Separate transactions into the ones expected to be in the mempool and those expected to be | ||
// rejected. | ||
let rejected_transaction_count = total_transactions - MEMPOOL_SIZE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// Separate transactions into the ones expected to be in the mempool and those expected to be | ||
// rejected. | ||
let rejected_transaction_count = total_transactions - MEMPOOL_SIZE; | ||
let expected_to_be_rejected = &unmined_transactions[..rejected_transaction_count]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break when we implement ZIP-401
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case it might make sense to change the assertions to be:
- Does the storage contain exactly
MEMPOOL_SIZE
transactions? - Are all transactions in the mempool storage from the
unmined_transactions
list? - Are all transaction IDs in the mempool from the
unmined_transactions
list (maybe minus the "accepted" transactions)? - (Maybe) Are they all unique?
Playing with an idea here:
let mut remaining_transactions: HashMap<UnminedTxId> = unmined_transactions
.into_iter()
.map(|transaction| transaction.id)
.collect();
let stored_transactions = storage.transactions();
assert_eq!(stored_transactions.len(), MEMPOOL_SIZE));
for transaction in stored_transactions {
assert!(remaining_transactions.remove(&transaction.id));
}
let rejected_transactions = storage.rejected_transactions().into_iter().collect();
assert_eq!(remaining_transactions, rejected_transactions);
Motivation
I was working on tests for #2682, and I saw an opportunity to tweak
unmined_transactions_in_blocks
a bit, but ended up getting carried away and refactored some other parts as well. I'm not sure if these are good ideas, so any feedback is welcome.Solution
The biggest change is that
unmined_transactions_in_blocks
receives a range of block heights instead of a maximum height, and returns an iterator instead of a tuple with aVec
and the transaction count. The code that use this function were also tweaked a bit in an attempt to make clearer how the unmined transactions were being used and to remove some redundancy.Review
Reviewer Checklist