Skip to content
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

Fix Transaction Status API #263

Merged
merged 26 commits into from
Apr 27, 2022
Merged

Fix Transaction Status API #263

merged 26 commits into from
Apr 27, 2022

Conversation

ControlCplusControlV
Copy link
Contributor

Closes #154

This updates the transaction status api to use the mempool as a shortcut to determine transaction status, as if a transaction is in the mempool it's status is submitted. There is a small TODO where the time used for the submitted status is the current time of when the status if fetched rather than the actual time it was submitted.

The dependent_transactions api was shelved as I understand it isn't that important, and I thought that if it is implemented it may make more sense to do with once utxo_validation is turned on.


let tx_pooldb = Box::new(db.clone()) as Box<dyn TxPoolDb>;

let txpool = TxPoolService::new(tx_pooldb, Arc::new(Config::default()));
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this creating an brand new instance of a txpool on each status request? We should be fetching the shared txpool out of the ctx like we do with the db. The db backs the txpool, but a lot of the data in the txpool is managed in memory, so creating an ephemeral txpool like this will not share any data with the txpool used in other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wasn't sure if this was the best way to access the txpool, I went with this approach as I wanted to avoid side effects (hence the clone), but I see why this could be extremely expensive and how the shared data could end up being helpful, so I will move this to fetch from the context

Copy link
Member

@Voxelot Voxelot Apr 14, 2022

Choose a reason for hiding this comment

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

The clone is of the db, which is just cloning a pointer and virtually has no cost. The issue is that creating a new txpool instance wouldn't know about the transaction submitted by the user, as it's a different instance with it's own hashmaps in memory. So the transaction the user is looking for would never exist in the temp pool you're making here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, will keep that in mind when deciding between whether to clone or pull in an object from the context.

What is the best way to fetch the TxPool from a context - let txpool = ctx.data::<Arc<dyn TxPool>>().unwrap(); however this results in many tests breaking with Custom { kind: Other, error: Curl("Send failed since rewinding of the data stream failed"): Send failed since rewinding of the data stream failed }, what would be the correct way to fetch the TxPool or TxPoolService from the current context?

Copy link
Member

Choose a reason for hiding this comment

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

It's injected into the context here: https://github.com/FuelLabs/fuel-core/blob/master/fuel-core/src/service/graph_api.rs#L37

So based on the type use there it would be the concrete Arc<TxPool> instead of dyn TxPool.

@Voxelot
Copy link
Member

Voxelot commented Apr 14, 2022

tests?

@ControlCplusControlV
Copy link
Contributor Author

Oh I thought the transaction status api unit tests would cover this, however I will in one to specifically test this new behavior and make sure it is behaving properly

@ControlCplusControlV ControlCplusControlV marked this pull request as draft April 15, 2022 03:20
@ControlCplusControlV
Copy link
Contributor Author

I've been running into some conversion issues. I noticed the submit_utxo_verified_tx test was actually able to catch a bug (with the api returning submitted too much), and the get_transaction_by_id test as well, so I was looking to base my new test off one of them. However, submit_tx on FuelClient currently deletes a transaction immediately after adding it to the txpool, and while to test the Submitted status I need a transaction that is currently inside the txpool. Then when testing with initializing just a txpool from TxPoolService where it is possible to insert a tx without deleting it, the Transaction objects I am using are of fuel_tx::Transaction and cannot be converted to the type where their status is checkable through the status api (fuel_core::schema::tx::types::Transaction )

So my question boils down to how would this behavior be tested? As the only way to get a transaction from FuelClient which is of the type I could check its status using the api would mean its not in the txpool (so it couldn't be submitted, as we are deleting transactions from the txpool atomically), and using a fresh TxPoolService doesn't seem to make the transaction accessible in the correct type to check its status via the api.

@ControlCplusControlV
Copy link
Contributor Author

So the Submitted Status isn't currently testable with the new fix without significant modification to they way the txpool currently works. There is still some coverage testing Success and Failed, but there are no current calls which would result in a Submitted status because submit_tx deletes and executes a transaction from the txpool as soon as its added. The TxPool isn't directly accessible either otherwise I would do a quick test to insert a tx and check status.

I have been able to test it though by removing the block execution and deletion of the tx from txpool by commenting out parts of submit_tx. I would prefer to make tests for this to be made a new issue for when tx's will persist in the mempool as it will be a much more natural test, and as of now I haven't found a way to test this update without changes other parts of the Client.

@ControlCplusControlV ControlCplusControlV marked this pull request as ready for review April 18, 2022 22:41

let txpool = ctx.data::<Arc<TxPool>>().unwrap().pool();

let transaction_in_pool = txpool.find(&[self.0.id()]).await;
Copy link
Contributor

Choose a reason for hiding this comment

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

You can just extend TxPool to support find_one function it should be easy to add as you just need to see how find is made, this should simplify a bit logic here.
Other than that this seems okay.

@Voxelot
Copy link
Member

Voxelot commented Apr 19, 2022

You could include the test that passed when you modified the txpool and add the #[ignored] annotation with a todo linking to #50, so that when that task is implemented the test can be re-enabled.

@ControlCplusControlV
Copy link
Contributor Author

I've added an empty test with a todo!() macro and explanation of what the test should do for testing the Submitted status and a link to the issue which is blocking it, then ignored the test the todo!()

@ControlCplusControlV
Copy link
Contributor Author

So to explain this (hopefully) final commit

  • Moves to new find_one method
  • Extends TxPool trait in fuel_core_interface/src/txpool.rs to use the new TxInfo struct rather than just Arc<Tx> as mentioned to me by @rakita . This required TxInfo being moved to avoid a circular dependency between fuel-core-interfaces and fuel-txpool, which now resides in fuel-core-interfaces as its a type so I thought it was most fitting there.
  • Fixes time so that the Submitted Status returned has the accurate time of when the transaction was submitted
  • Added a mock test with annotations to an issue and a note to add in an automatic unit test for when execution is decoupled from submit_tx, so that Submitted can be tested in the future when it's a reachable status

I have re-done manual testing as well to ensure Submitted still works properly after this change (modifying submit_tx in submit_utxo_verified tx test to leave transactions in the txpool, and then checking their status)

use fuel_tx::Transaction;
use std::sync::Arc;

pub type ArcTx = Arc<Transaction>;

#[derive(Debug, Clone)]
pub struct TxInfo {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I would just move this file to fuel-core-interfaces/src/model/info.rs and maybe even rename it to txpool.rs it feels like modules specific to txpool, that is why a little bit a specific naming of file.
other than that lgtm :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I wasn't sure what name so I chose info but I agreetxpool is better to make it more clear in what it does and easier to find. It is now moved it to fuel-core-interfaces/src/model/txpool.rs

Comment on lines +224 to +225
if transaction_in_pool.is_some() {
let time = transaction_in_pool.unwrap().submited_time();
Copy link
Member

Choose a reason for hiding this comment

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

[nit] use if-let syntax to avoid .is_some followed by unwrap.

@ControlCplusControlV ControlCplusControlV merged commit 0b78de5 into master Apr 27, 2022
@ControlCplusControlV ControlCplusControlV deleted the controlc/152_pt2 branch April 27, 2022 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[txpool] Implement removal of txs that are included into chain
3 participants