sc_transaction_pool/
transaction_pool_wrapper.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Transaction pool wrapper. Provides a type for wrapping object providing actual implementation of
20//! transaction pool.
21
22use crate::{
23	builder::FullClientTransactionPool,
24	graph::{base_pool::Transaction, ExtrinsicFor, ExtrinsicHash},
25	ChainApi, FullChainApi,
26};
27use async_trait::async_trait;
28use sc_transaction_pool_api::{
29	ChainEvent, ImportNotificationStream, LocalTransactionFor, LocalTransactionPool,
30	MaintainedTransactionPool, PoolFuture, PoolStatus, ReadyTransactions, TransactionFor,
31	TransactionPool, TransactionSource, TransactionStatusStreamFor, TxHash,
32};
33use sp_runtime::traits::Block as BlockT;
34use std::{collections::HashMap, future::Future, pin::Pin, sync::Arc};
35
36/// The wrapper for actual object providing implementation of TransactionPool.
37///
38/// This wraps actual implementation of the TransactionPool, e.g. fork-aware or single-state.
39pub struct TransactionPoolWrapper<Block, Client>(
40	pub Box<dyn FullClientTransactionPool<Block, Client>>,
41)
42where
43	Block: BlockT,
44	Client: sp_api::ProvideRuntimeApi<Block>
45		+ sc_client_api::BlockBackend<Block>
46		+ sc_client_api::blockchain::HeaderBackend<Block>
47		+ sp_runtime::traits::BlockIdTo<Block>
48		+ sp_blockchain::HeaderMetadata<Block, Error = sp_blockchain::Error>
49		+ 'static,
50	Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>;
51
52impl<Block, Client> TransactionPool for TransactionPoolWrapper<Block, Client>
53where
54	Block: BlockT,
55	Client: sp_api::ProvideRuntimeApi<Block>
56		+ sc_client_api::BlockBackend<Block>
57		+ sc_client_api::blockchain::HeaderBackend<Block>
58		+ sp_runtime::traits::BlockIdTo<Block>
59		+ sp_blockchain::HeaderMetadata<Block, Error = sp_blockchain::Error>
60		+ 'static,
61	Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,
62{
63	type Block = Block;
64	type Hash = ExtrinsicHash<FullChainApi<Client, Block>>;
65	type InPoolTransaction = Transaction<
66		ExtrinsicHash<FullChainApi<Client, Block>>,
67		ExtrinsicFor<FullChainApi<Client, Block>>,
68	>;
69	type Error = <FullChainApi<Client, Block> as ChainApi>::Error;
70
71	fn submit_at(
72		&self,
73		at: <Self::Block as BlockT>::Hash,
74		source: TransactionSource,
75		xts: Vec<TransactionFor<Self>>,
76	) -> PoolFuture<Vec<Result<TxHash<Self>, Self::Error>>, Self::Error> {
77		self.0.submit_at(at, source, xts)
78	}
79
80	fn submit_one(
81		&self,
82		at: <Self::Block as BlockT>::Hash,
83		source: TransactionSource,
84		xt: TransactionFor<Self>,
85	) -> PoolFuture<TxHash<Self>, Self::Error> {
86		self.0.submit_one(at, source, xt)
87	}
88
89	fn submit_and_watch(
90		&self,
91		at: <Self::Block as BlockT>::Hash,
92		source: TransactionSource,
93		xt: TransactionFor<Self>,
94	) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error> {
95		self.0.submit_and_watch(at, source, xt)
96	}
97
98	fn ready_at(
99		&self,
100		at: <Self::Block as BlockT>::Hash,
101	) -> Pin<
102		Box<
103			dyn Future<
104					Output = Box<dyn ReadyTransactions<Item = Arc<Self::InPoolTransaction>> + Send>,
105				> + Send,
106		>,
107	> {
108		self.0.ready_at(at)
109	}
110
111	fn ready(&self) -> Box<dyn ReadyTransactions<Item = Arc<Self::InPoolTransaction>> + Send> {
112		self.0.ready()
113	}
114
115	fn remove_invalid(&self, hashes: &[TxHash<Self>]) -> Vec<Arc<Self::InPoolTransaction>> {
116		self.0.remove_invalid(hashes)
117	}
118
119	fn futures(&self) -> Vec<Self::InPoolTransaction> {
120		self.0.futures()
121	}
122
123	fn status(&self) -> PoolStatus {
124		self.0.status()
125	}
126
127	fn import_notification_stream(&self) -> ImportNotificationStream<TxHash<Self>> {
128		self.0.import_notification_stream()
129	}
130
131	fn on_broadcasted(&self, propagations: HashMap<TxHash<Self>, Vec<String>>) {
132		self.0.on_broadcasted(propagations)
133	}
134
135	fn hash_of(&self, xt: &TransactionFor<Self>) -> TxHash<Self> {
136		self.0.hash_of(xt)
137	}
138
139	fn ready_transaction(&self, hash: &TxHash<Self>) -> Option<Arc<Self::InPoolTransaction>> {
140		self.0.ready_transaction(hash)
141	}
142
143	fn ready_at_with_timeout(
144		&self,
145		at: <Self::Block as BlockT>::Hash,
146		timeout: std::time::Duration,
147	) -> Pin<
148		Box<
149			dyn Future<
150					Output = Box<dyn ReadyTransactions<Item = Arc<Self::InPoolTransaction>> + Send>,
151				> + Send
152				+ '_,
153		>,
154	> {
155		self.0.ready_at_with_timeout(at, timeout)
156	}
157}
158
159#[async_trait]
160impl<Block, Client> MaintainedTransactionPool for TransactionPoolWrapper<Block, Client>
161where
162	Block: BlockT,
163	Client: sp_api::ProvideRuntimeApi<Block>
164		+ sc_client_api::BlockBackend<Block>
165		+ sc_client_api::blockchain::HeaderBackend<Block>
166		+ sp_runtime::traits::BlockIdTo<Block>
167		+ sp_blockchain::HeaderMetadata<Block, Error = sp_blockchain::Error>
168		+ 'static,
169	Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,
170{
171	async fn maintain(&self, event: ChainEvent<Self::Block>) {
172		self.0.maintain(event).await;
173	}
174}
175
176impl<Block, Client> LocalTransactionPool for TransactionPoolWrapper<Block, Client>
177where
178	Block: BlockT,
179	Client: sp_api::ProvideRuntimeApi<Block>
180		+ sc_client_api::BlockBackend<Block>
181		+ sc_client_api::blockchain::HeaderBackend<Block>
182		+ sp_runtime::traits::BlockIdTo<Block>
183		+ sp_blockchain::HeaderMetadata<Block, Error = sp_blockchain::Error>
184		+ 'static,
185	Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,
186{
187	type Block = Block;
188	type Hash = ExtrinsicHash<FullChainApi<Client, Block>>;
189	type Error = <FullChainApi<Client, Block> as ChainApi>::Error;
190
191	fn submit_local(
192		&self,
193		at: <Self::Block as BlockT>::Hash,
194		xt: LocalTransactionFor<Self>,
195	) -> Result<Self::Hash, Self::Error> {
196		self.0.submit_local(at, xt)
197	}
198}