Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit e5fed33

Browse files
authored
Refactor tx-pool maintenance and other high-level api (#4629)
* Reduction. * Reformation. * add locked timer stuff * fix issues and introduce full pool * arrange together * fix benches * fix new_light * Add revalidation test case * review fixes * review fixes * use just ready future * address review
1 parent 219fad6 commit e5fed33

File tree

12 files changed

+423
-827
lines changed

12 files changed

+423
-827
lines changed

bin/node-template/src/service.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ macro_rules! new_full_start {
4343
.with_transaction_pool(|config, client, _fetcher| {
4444
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
4545
let pool = sc_transaction_pool::BasicPool::new(config, pool_api);
46-
let maintainer = sc_transaction_pool::FullBasicPoolMaintainer::new(pool.pool().clone(), client);
47-
let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer);
48-
Ok(maintainable_pool)
46+
Ok(pool)
4947
})?
5048
.with_import_queue(|_config, client, mut select_chain, transaction_pool| {
5149
let select_chain = select_chain.take()
@@ -207,11 +205,12 @@ pub fn new_light<C: Send + Default + 'static>(config: Configuration<C, GenesisCo
207205
.with_transaction_pool(|config, client, fetcher| {
208206
let fetcher = fetcher
209207
.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
208+
210209
let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
211-
let pool = sc_transaction_pool::BasicPool::new(config, pool_api);
212-
let maintainer = sc_transaction_pool::LightBasicPoolMaintainer::with_defaults(pool.pool().clone(), client, fetcher);
213-
let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer);
214-
Ok(maintainable_pool)
210+
let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
211+
config, pool_api, sc_transaction_pool::RevalidationType::Light,
212+
);
213+
Ok(pool)
215214
})?
216215
.with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| {
217216
let fetch_checker = fetcher

bin/node/cli/src/service.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ macro_rules! new_full_start {
6464
.with_transaction_pool(|config, client, _fetcher| {
6565
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
6666
let pool = sc_transaction_pool::BasicPool::new(config, pool_api);
67-
let maintainer = sc_transaction_pool::FullBasicPoolMaintainer::new(pool.pool().clone(), client);
68-
let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer);
69-
Ok(maintainable_pool)
67+
Ok(pool)
7068
})?
7169
.with_import_queue(|_config, client, mut select_chain, _transaction_pool| {
7270
let select_chain = select_chain.take()
@@ -272,15 +270,9 @@ type ConcreteClient =
272270
#[allow(dead_code)]
273271
type ConcreteBackend = Backend<ConcreteBlock>;
274272
#[allow(dead_code)]
275-
type ConcreteTransactionPool = sp_transaction_pool::MaintainableTransactionPool<
276-
sc_transaction_pool::BasicPool<
277-
sc_transaction_pool::FullChainApi<ConcreteClient, ConcreteBlock>,
278-
ConcreteBlock
279-
>,
280-
sc_transaction_pool::FullBasicPoolMaintainer<
281-
ConcreteClient,
282-
sc_transaction_pool::FullChainApi<ConcreteClient, Block>
283-
>
273+
type ConcreteTransactionPool = sc_transaction_pool::BasicPool<
274+
sc_transaction_pool::FullChainApi<ConcreteClient, ConcreteBlock>,
275+
ConcreteBlock
284276
>;
285277

286278
/// A specialized configuration object for setting up the node..
@@ -322,10 +314,10 @@ pub fn new_light<C: Send + Default + 'static>(config: NodeConfiguration<C>)
322314
let fetcher = fetcher
323315
.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
324316
let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
325-
let pool = sc_transaction_pool::BasicPool::new(config, pool_api);
326-
let maintainer = sc_transaction_pool::LightBasicPoolMaintainer::with_defaults(pool.pool().clone(), client, fetcher);
327-
let maintainable_pool = sp_transaction_pool::MaintainableTransactionPool::new(pool, maintainer);
328-
Ok(maintainable_pool)
317+
let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
318+
config, pool_api, sc_transaction_pool::RevalidationType::Light,
319+
);
320+
Ok(pool)
329321
})?
330322
.with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| {
331323
let fetch_checker = fetcher

client/service/src/builder.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use std::{
4949
};
5050
use sysinfo::{get_current_pid, ProcessExt, System, SystemExt};
5151
use sc_telemetry::{telemetry, SUBSTRATE_INFO};
52-
use sp_transaction_pool::{TransactionPool, TransactionPoolMaintainer};
52+
use sp_transaction_pool::MaintainedTransactionPool;
5353
use sp_blockchain;
5454
use grafana_data_source::{self, record_metrics};
5555

@@ -740,9 +740,7 @@ ServiceBuilder<
740740
TSc: Clone,
741741
TImpQu: 'static + ImportQueue<TBl>,
742742
TNetP: NetworkSpecialization<TBl>,
743-
TExPool: 'static
744-
+ TransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash>
745-
+ TransactionPoolMaintainer<Block=TBl, Hash = <TBl as BlockT>::Hash>,
743+
TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> + 'static,
746744
TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata> + Clone,
747745
{
748746

client/service/src/lib.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub use self::builder::{
6161
};
6262
pub use config::{Configuration, Roles, PruningMode};
6363
pub use sc_chain_spec::{ChainSpec, Properties, RuntimeGenesis, Extension as ChainSpecExtension};
64-
pub use sp_transaction_pool::{TransactionPool, TransactionPoolMaintainer, InPoolTransaction, error::IntoPoolError};
64+
pub use sp_transaction_pool::{TransactionPool, InPoolTransaction, error::IntoPoolError};
6565
pub use sc_transaction_pool::txpool::Options as TransactionPoolOptions;
6666
pub use sc_client::FinalityNotifications;
6767
pub use sc_rpc::Metadata as RpcMetadata;
@@ -148,8 +148,7 @@ pub trait AbstractService: 'static + Future<Output = Result<(), Error>> +
148148
/// Chain selection algorithm.
149149
type SelectChain: sp_consensus::SelectChain<Self::Block>;
150150
/// Transaction pool.
151-
type TransactionPool: TransactionPool<Block = Self::Block>
152-
+ TransactionPoolMaintainer<Block = Self::Block>;
151+
type TransactionPool: TransactionPool<Block = Self::Block>;
153152
/// Network specialization.
154153
type NetworkSpecialization: NetworkSpecialization<Self::Block>;
155154

@@ -213,8 +212,7 @@ where
213212
TExec: 'static + sc_client::CallExecutor<TBl> + Send + Sync + Clone,
214213
TRtApi: 'static + Send + Sync,
215214
TSc: sp_consensus::SelectChain<TBl> + 'static + Clone + Send + Unpin,
216-
TExPool: 'static + TransactionPool<Block = TBl>
217-
+ TransactionPoolMaintainer<Block = TBl>,
215+
TExPool: 'static + TransactionPool<Block = TBl>,
218216
TOc: 'static + Send + Sync,
219217
TNetSpec: NetworkSpecialization<TBl>,
220218
{

client/transaction-pool/graph/benches/basics.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
use criterion::{criterion_group, criterion_main, Criterion};
1818

19-
use futures::executor::block_on;
19+
use futures::{future::{ready, Ready}, executor::block_on};
2020
use sc_transaction_graph::*;
2121
use sp_runtime::transaction_validity::{ValidTransaction, InvalidTransaction};
2222
use codec::Encode;
@@ -49,7 +49,8 @@ impl ChainApi for TestApi {
4949
type Block = Block;
5050
type Hash = H256;
5151
type Error = sp_transaction_pool::error::Error;
52-
type ValidationFuture = futures::future::Ready<sp_transaction_pool::error::Result<TransactionValidity>>;
52+
type ValidationFuture = Ready<sp_transaction_pool::error::Result<TransactionValidity>>;
53+
type BodyFuture = Ready<sp_transaction_pool::error::Result<Option<Vec<Extrinsic>>>>;
5354

5455
fn validate_transaction(
5556
&self,
@@ -61,14 +62,14 @@ impl ChainApi for TestApi {
6162

6263
match self.block_id_to_number(at) {
6364
Ok(Some(num)) if num > 5 => {
64-
return futures::future::ready(
65+
return ready(
6566
Ok(Err(InvalidTransaction::Stale.into()))
6667
)
6768
},
6869
_ => {},
6970
}
7071

71-
futures::future::ready(
72+
ready(
7273
Ok(Ok(ValidTransaction {
7374
priority: 4,
7475
requires: if nonce > 1 && self.nonce_dependant {
@@ -105,6 +106,10 @@ impl ChainApi for TestApi {
105106
let encoded = uxt.encode();
106107
(blake2_256(&encoded).into(), encoded.len())
107108
}
109+
110+
fn block_body(&self, _id: &BlockId<Self::Block>) -> Self::BodyFuture {
111+
ready(Ok(None))
112+
}
108113
}
109114

110115
fn uxt(transfer: Transfer) -> Extrinsic {
@@ -150,13 +155,13 @@ fn benchmark_main(c: &mut Criterion) {
150155

151156
c.bench_function("sequential 50 tx", |b| {
152157
b.iter(|| {
153-
bench_configured(Pool::new(Default::default(), TestApi::new_dependant()), 50);
158+
bench_configured(Pool::new(Default::default(), TestApi::new_dependant().into()), 50);
154159
});
155160
});
156161

157162
c.bench_function("random 100 tx", |b| {
158163
b.iter(|| {
159-
bench_configured(Pool::new(Default::default(), TestApi::default()), 100);
164+
bench_configured(Pool::new(Default::default(), TestApi::default().into()), 100);
160165
});
161166
});
162167
}

client/transaction-pool/graph/src/pool.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ pub trait ChainApi: Send + Sync {
6868
type Error: From<error::Error> + error::IntoPoolError;
6969
/// Validate transaction future.
7070
type ValidationFuture: Future<Output=Result<TransactionValidity, Self::Error>> + Send + Unpin;
71+
/// Body future (since block body might be remote)
72+
type BodyFuture: Future<Output = Result<Option<Vec<<Self::Block as traits::Block>::Extrinsic>>, Self::Error>> + Unpin + Send + 'static;
7173

7274
/// Verify extrinsic at given block.
7375
fn validate_transaction(
@@ -84,6 +86,9 @@ pub trait ChainApi: Send + Sync {
8486

8587
/// Returns hash and encoding length of the extrinsic.
8688
fn hash_and_length(&self, uxt: &ExtrinsicFor<Self>) -> (Self::Hash, usize);
89+
90+
/// Returns a block body given the block id.
91+
fn block_body(&self, at: &BlockId<Self::Block>) -> Self::BodyFuture;
8792
}
8893

8994
/// Pool configuration options.
@@ -120,7 +125,7 @@ pub struct Pool<B: ChainApi> {
120125

121126
impl<B: ChainApi> Pool<B> {
122127
/// Create a new transaction pool.
123-
pub fn new(options: Options, api: B) -> Self {
128+
pub fn new(options: Options, api: Arc<B>) -> Self {
124129
Pool {
125130
validated_pool: Arc::new(ValidatedPool::new(options, api)),
126131
}
@@ -488,6 +493,7 @@ mod tests {
488493
type Hash = u64;
489494
type Error = error::Error;
490495
type ValidationFuture = futures::future::Ready<error::Result<TransactionValidity>>;
496+
type BodyFuture = futures::future::Ready<error::Result<Option<Vec<Extrinsic>>>>;
491497

492498
/// Verify extrinsic at given block.
493499
fn validate_transaction(
@@ -560,14 +566,18 @@ mod tests {
560566
len
561567
)
562568
}
569+
570+
fn block_body(&self, _id: &BlockId<Self::Block>) -> Self::BodyFuture {
571+
futures::future::ready(Ok(None))
572+
}
563573
}
564574

565575
fn uxt(transfer: Transfer) -> Extrinsic {
566576
Extrinsic::Transfer(transfer, Default::default())
567577
}
568578

569579
fn pool() -> Pool<TestApi> {
570-
Pool::new(Default::default(), TestApi::default())
580+
Pool::new(Default::default(), TestApi::default().into())
571581
}
572582

573583
#[test]
@@ -713,7 +723,7 @@ mod tests {
713723
ready: limit.clone(),
714724
future: limit.clone(),
715725
..Default::default()
716-
}, TestApi::default());
726+
}, TestApi::default().into());
717727

718728
let hash1 = block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer {
719729
from: AccountId::from_h256(H256::from_low_u64_be(1)),
@@ -748,7 +758,7 @@ mod tests {
748758
ready: limit.clone(),
749759
future: limit.clone(),
750760
..Default::default()
751-
}, TestApi::default());
761+
}, TestApi::default().into());
752762

753763
// when
754764
block_on(pool.submit_one(&BlockId::Number(0), uxt(Transfer {
@@ -924,7 +934,7 @@ mod tests {
924934
ready: limit.clone(),
925935
future: limit.clone(),
926936
..Default::default()
927-
}, TestApi::default());
937+
}, TestApi::default().into());
928938

929939
let xt = uxt(Transfer {
930940
from: AccountId::from_h256(H256::from_low_u64_be(1)),
@@ -958,7 +968,7 @@ mod tests {
958968
let (tx, rx) = std::sync::mpsc::sync_channel(1);
959969
let mut api = TestApi::default();
960970
api.delay = Arc::new(Mutex::new(rx.into()));
961-
let pool = Arc::new(Pool::new(Default::default(), api));
971+
let pool = Arc::new(Pool::new(Default::default(), api.into()));
962972

963973
// when
964974
let xt = uxt(Transfer {

client/transaction-pool/graph/src/validated_pool.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub type ValidatedTransactionFor<B> = ValidatedTransaction<
6363

6464
/// Pool that deals with validated transactions.
6565
pub(crate) struct ValidatedPool<B: ChainApi> {
66-
api: B,
66+
api: Arc<B>,
6767
options: Options,
6868
listener: RwLock<Listener<ExHash<B>, BlockHash<B>>>,
6969
pool: RwLock<base::BasePool<
@@ -76,7 +76,7 @@ pub(crate) struct ValidatedPool<B: ChainApi> {
7676

7777
impl<B: ChainApi> ValidatedPool<B> {
7878
/// Create a new transaction pool.
79-
pub fn new(options: Options, api: B) -> Self {
79+
pub fn new(options: Options, api: Arc<B>) -> Self {
8080
let base_pool = base::BasePool::new(options.reject_future_transactions);
8181
ValidatedPool {
8282
api,

client/transaction-pool/src/api.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
use std::{marker::PhantomData, pin::Pin, sync::Arc};
2020
use codec::{Decode, Encode};
2121
use futures::{
22-
channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready},
22+
channel::oneshot, executor::{ThreadPool, ThreadPoolBuilder}, future::{Future, FutureExt, ready, Ready},
2323
};
2424

2525
use sc_client_api::{
2626
blockchain::HeaderBackend,
27-
light::{Fetcher, RemoteCallRequest}
27+
light::{Fetcher, RemoteCallRequest, RemoteBodyRequest},
28+
BlockBody,
2829
};
2930
use sp_core::Hasher;
3031
use sp_runtime::{
@@ -63,14 +64,19 @@ impl<Client, Block> FullChainApi<Client, Block> where
6364

6465
impl<Client, Block> sc_transaction_graph::ChainApi for FullChainApi<Client, Block> where
6566
Block: BlockT,
66-
Client: ProvideRuntimeApi<Block> + BlockIdTo<Block> + 'static + Send + Sync,
67+
Client: ProvideRuntimeApi<Block> + BlockBody<Block> + BlockIdTo<Block> + 'static + Send + Sync,
6768
Client::Api: TaggedTransactionQueue<Block>,
6869
sp_api::ApiErrorFor<Client, Block>: Send,
6970
{
7071
type Block = Block;
7172
type Hash = Block::Hash;
7273
type Error = error::Error;
7374
type ValidationFuture = Pin<Box<dyn Future<Output = error::Result<TransactionValidity>> + Send>>;
75+
type BodyFuture = Ready<error::Result<Option<Vec<<Self::Block as BlockT>::Extrinsic>>>>;
76+
77+
fn block_body(&self, id: &BlockId<Self::Block>) -> Self::BodyFuture {
78+
ready(self.client.block_body(&id).map_err(|e| error::Error::from(e)))
79+
}
7480

7581
fn validate_transaction(
7682
&self,
@@ -149,6 +155,7 @@ impl<Client, F, Block> sc_transaction_graph::ChainApi for LightChainApi<Client,
149155
type Hash = Block::Hash;
150156
type Error = error::Error;
151157
type ValidationFuture = Box<dyn Future<Output = error::Result<TransactionValidity>> + Send + Unpin>;
158+
type BodyFuture = Pin<Box<dyn Future<Output = error::Result<Option<Vec<<Self::Block as BlockT>::Extrinsic>>>> + Send>>;
152159

153160
fn validate_transaction(
154161
&self,
@@ -197,4 +204,33 @@ impl<Client, F, Block> sc_transaction_graph::ChainApi for LightChainApi<Client,
197204
(<<Block::Header as HeaderT>::Hashing as HashT>::hash(x), x.len())
198205
})
199206
}
207+
208+
fn block_body(&self, id: &BlockId<Self::Block>) -> Self::BodyFuture {
209+
let header = self.client.header(*id)
210+
.and_then(|h| h.ok_or(sp_blockchain::Error::UnknownBlock(format!("{}", id))));
211+
let header = match header {
212+
Ok(header) => header,
213+
Err(err) => {
214+
log::warn!(target: "txpool", "Failed to query header: {:?}", err);
215+
return Box::pin(ready(Ok(None)));
216+
}
217+
};
218+
219+
let fetcher = self.fetcher.clone();
220+
async move {
221+
let transactions = fetcher.remote_body({
222+
RemoteBodyRequest {
223+
header,
224+
retry_count: None,
225+
}
226+
})
227+
.await
228+
.unwrap_or_else(|e| {
229+
log::warn!(target: "txpool", "Failed to fetch block body: {:?}", e);
230+
Vec::new()
231+
});
232+
233+
Ok(Some(transactions))
234+
}.boxed()
235+
}
200236
}

0 commit comments

Comments
 (0)