diff --git a/fuel-core-interfaces/src/model.rs b/fuel-core-interfaces/src/model.rs index e76e3ebe19f..9fcc77aa7a3 100644 --- a/fuel-core-interfaces/src/model.rs +++ b/fuel-core-interfaces/src/model.rs @@ -1,7 +1,9 @@ mod block; mod block_height; mod coin; +mod txpool; pub use block::{FuelBlock, FuelBlockDb, FuelBlockHeader}; pub use block_height::BlockHeight; pub use coin::{Coin, CoinStatus}; +pub use txpool::{ArcTx, TxInfo}; diff --git a/fuel-txpool/src/containers/info.rs b/fuel-core-interfaces/src/model/txpool.rs similarity index 86% rename from fuel-txpool/src/containers/info.rs rename to fuel-core-interfaces/src/model/txpool.rs index 40ba8cba8e3..62bd170bce7 100644 --- a/fuel-txpool/src/containers/info.rs +++ b/fuel-core-interfaces/src/model/txpool.rs @@ -1,7 +1,10 @@ use std::ops::Deref; -use crate::types::ArcTx; use chrono::{DateTime, Utc}; +use fuel_tx::Transaction; +use std::sync::Arc; + +pub type ArcTx = Arc; #[derive(Debug, Clone)] pub struct TxInfo { diff --git a/fuel-core-interfaces/src/txpool.rs b/fuel-core-interfaces/src/txpool.rs index e1b04db809a..a1a145c8d68 100644 --- a/fuel-core-interfaces/src/txpool.rs +++ b/fuel-core-interfaces/src/txpool.rs @@ -8,6 +8,7 @@ use thiserror::Error; use crate::{ db::{Error as DbStateError, KvStoreError}, model::Coin, + model::TxInfo, }; use fuel_storage::Storage; use fuel_vm::prelude::Contract; @@ -50,10 +51,10 @@ pub trait TxPool: Send + Sync { -> Vec>>>; /// find all tx by their hash - async fn find(&self, hashes: &[TxId]) -> Vec>>; + async fn find(&self, hashes: &[TxId]) -> Vec>; /// find one tx by its hash - async fn find_one(&self, hash: &TxId) -> Option>; + async fn find_one(&self, hash: &TxId) -> Option; /// find all dependent tx and return them with requsted dependencies in one list sorted by Price. async fn find_dependent(&self, hashes: &[TxId]) -> Vec>; diff --git a/fuel-core/src/schema/tx.rs b/fuel-core/src/schema/tx.rs index 9574e51676b..2b1ffd0eac3 100644 --- a/fuel-core/src/schema/tx.rs +++ b/fuel-core/src/schema/tx.rs @@ -47,7 +47,7 @@ impl TxQuery { let found_tx = tx_pool.pool().find(&[key]).await; if let Some(Some(transaction)) = found_tx.get(0) { - Ok(Some(Transaction((transaction.deref()).clone()))) + Ok(Some(Transaction((transaction.tx().deref()).clone()))) } else { Ok(Storage::::get(db, &key)? .map(|tx| Transaction(tx.into_owned()))) diff --git a/fuel-core/src/schema/tx/types.rs b/fuel-core/src/schema/tx/types.rs index 5a13dd3faa2..94bd368a001 100644 --- a/fuel-core/src/schema/tx/types.rs +++ b/fuel-core/src/schema/tx/types.rs @@ -5,6 +5,7 @@ use crate::model::FuelBlockDb; use crate::schema::contract::Contract; use crate::schema::scalars::{AssetId, Bytes32, HexString, Salt, TransactionId, U64}; use crate::tx_pool::TransactionStatus as TxStatus; +use crate::tx_pool::TxPool; use crate::{database::Database, schema::block::Block}; use async_graphql::{Context, Enum, Object, Union}; use chrono::{DateTime, Utc}; @@ -12,6 +13,7 @@ use fuel_core_interfaces::db::KvStoreError; use fuel_storage::Storage; use fuel_types::bytes::SerializableVec; use fuel_vm::prelude::ProgramState as VmProgramState; +use std::sync::Arc; pub struct ProgramState { return_type: ReturnType, @@ -214,8 +216,18 @@ impl Transaction { async fn status(&self, ctx: &Context<'_>) -> async_graphql::Result> { let db = ctx.data_unchecked::(); - let status = db.get_tx_status(&self.0.id())?; - Ok(status.map(Into::into)) + + let txpool = ctx.data::>().unwrap().pool(); + + let transaction_in_pool = txpool.find_one(&self.0.id()).await; + + if transaction_in_pool.is_some() { + let time = transaction_in_pool.unwrap().submited_time(); + Ok(Some(TransactionStatus::Submitted(SubmittedStatus(time)))) + } else { + let status = db.get_tx_status(&self.0.id())?; + Ok(status.map(Into::into)) + } } async fn receipts(&self, ctx: &Context<'_>) -> async_graphql::Result>> { diff --git a/fuel-tests/tests/tx.rs b/fuel-tests/tests/tx.rs index 00f03cc357b..de9431f1e7e 100644 --- a/fuel-tests/tests/tx.rs +++ b/fuel-tests/tests/tx.rs @@ -159,6 +159,7 @@ async fn submit_utxo_verified_tx() { assert!(block_exists.is_some()); } + // Once https://github.com/FuelLabs/fuel-core/issues/50 is resolved this should rely on the Submitted Status rather than Success assert!(matches!( transaction_result, TransactionStatus::Success { .. } @@ -166,6 +167,17 @@ async fn submit_utxo_verified_tx() { } } +#[ignore] +#[tokio::test] +async fn transaction_status_submitted() { + // This test should ensure a transaction's status is Submitted while it is in the mempool + // This test should also ensure a transaction's time of submission is correct in the returned status + // Currently blocked until https://github.com/FuelLabs/fuel-core/issues/50 is resolved + // as execution must be seperate from submission for a tx to persist inside of the txpool + // Merge with the submit_utxo_verified_tx test once utxo_verification is the default + todo!(); +} + #[tokio::test] async fn receipts() { let transaction = fuel_tx::Transaction::default(); diff --git a/fuel-txpool/src/containers.rs b/fuel-txpool/src/containers.rs index a8b92fdca78..e9493b7969e 100644 --- a/fuel-txpool/src/containers.rs +++ b/fuel-txpool/src/containers.rs @@ -1,3 +1,2 @@ pub mod dependency; -pub mod info; pub mod price_sort; diff --git a/fuel-txpool/src/containers/dependency.rs b/fuel-txpool/src/containers/dependency.rs index 2c4337f1cf6..5245e0ab869 100644 --- a/fuel-txpool/src/containers/dependency.rs +++ b/fuel-txpool/src/containers/dependency.rs @@ -1,14 +1,12 @@ use crate::{types::*, Error}; use anyhow::anyhow; use fuel_core_interfaces::{ - model::{Coin, CoinStatus}, + model::{ArcTx, Coin, CoinStatus, TxInfo}, txpool::TxPoolDb, }; use fuel_tx::{Input, Output, UtxoId}; use std::collections::{HashMap, HashSet}; -use super::info::TxInfo; - /// Check and hold dependency between inputs and outputs. Be mindful /// about depth of connection #[derive(Debug, Clone)] diff --git a/fuel-txpool/src/containers/price_sort.rs b/fuel-txpool/src/containers/price_sort.rs index 26079d10b53..5646768e8fa 100644 --- a/fuel-txpool/src/containers/price_sort.rs +++ b/fuel-txpool/src/containers/price_sort.rs @@ -1,4 +1,5 @@ use crate::types::*; +use fuel_core_interfaces::model::ArcTx; use std::{cmp, collections::BTreeMap}; #[derive(Debug, Clone)] diff --git a/fuel-txpool/src/service.rs b/fuel-txpool/src/service.rs index e995bc7fada..2f5a3364e4b 100644 --- a/fuel-txpool/src/service.rs +++ b/fuel-txpool/src/service.rs @@ -3,9 +3,9 @@ use std::sync::Arc; use crate::Error; use crate::{subscribers::MultiSubscriber, types::*, Config, TxPool as TxPoolImpl}; -use fuel_core_interfaces::txpool::{Subscriber, TxPool, TxPoolDb}; - use async_trait::async_trait; +use fuel_core_interfaces::model::{ArcTx, TxInfo}; +use fuel_core_interfaces::txpool::{Subscriber, TxPool, TxPoolDb}; use std::collections::HashMap; use tokio::sync::RwLock; @@ -56,22 +56,17 @@ impl TxPool for TxPoolService { } /// find all tx by its hash - async fn find(&self, hashes: &[TxId]) -> Vec> { + async fn find(&self, hashes: &[TxId]) -> Vec> { let mut res = Vec::with_capacity(hashes.len()); let pool = self.txpool.read().await; for hash in hashes { - res.push(pool.txs().get(hash).map(|info| info.tx().clone())); + res.push(pool.txs().get(hash).cloned()); } res } - async fn find_one(&self, hash: &TxId) -> Option { - self.txpool - .read() - .await - .txs() - .get(hash) - .map(|info| info.tx().clone()) + async fn find_one(&self, hash: &TxId) -> Option { + self.txpool.read().await.txs().get(hash).cloned() } /// find all dependent tx and return them with requsted dependencies in one list sorted by Price. diff --git a/fuel-txpool/src/subscribers.rs b/fuel-txpool/src/subscribers.rs index f7d40e7fe57..f9c87ec1fa1 100644 --- a/fuel-txpool/src/subscribers.rs +++ b/fuel-txpool/src/subscribers.rs @@ -1,7 +1,8 @@ use std::sync::Arc; -use crate::{types::ArcTx, Error}; +use crate::Error; use async_trait::async_trait; +use fuel_core_interfaces::model::ArcTx; use fuel_core_interfaces::txpool::Subscriber; use parking_lot::RwLock; diff --git a/fuel-txpool/src/txpool.rs b/fuel-txpool/src/txpool.rs index 54b5e435452..9e92f7880ed 100644 --- a/fuel-txpool/src/txpool.rs +++ b/fuel-txpool/src/txpool.rs @@ -1,7 +1,7 @@ use crate::containers::dependency::Dependency; -use crate::containers::info::TxInfo; use crate::Error; use crate::{containers::price_sort::PriceSort, types::*, Config}; +use fuel_core_interfaces::model::{ArcTx, TxInfo}; use fuel_core_interfaces::txpool::TxPoolDb; use std::collections::HashMap; use std::sync::Arc; @@ -98,8 +98,8 @@ impl TxPool { /// remove transaction from pool needed on user demand. Low priority pub fn remove_by_tx_id(&mut self, tx_id: &TxId) -> Vec { - if let Some(tx) = self.by_hash.get(tx_id) { - self.by_gas_price.remove(tx); + if let Some(tx) = self.by_hash.remove(tx_id) { + self.by_gas_price.remove(tx.tx()); return self .by_dependency .recursively_remove_all_dependencies(&self.by_hash, tx.tx().clone()); diff --git a/fuel-txpool/src/types.rs b/fuel-txpool/src/types.rs index 58b99d3d35b..838356648ef 100644 --- a/fuel-txpool/src/types.rs +++ b/fuel-txpool/src/types.rs @@ -1,7 +1,5 @@ pub use fuel_tx::ContractId; pub use fuel_tx::{Transaction, TxId}; use fuel_types::Word; -use std::sync::Arc; -pub type ArcTx = Arc; pub type GasPrice = Word;