@@ -35,12 +35,14 @@ extern crate error_chain;
3535extern crate log;
3636
3737mod error;
38+ mod rotator;
3839
3940use std:: {
4041 cmp:: Ordering ,
4142 collections:: HashMap ,
4243 ops:: Deref ,
4344 sync:: Arc ,
45+ time:: { Duration , Instant } ,
4446} ;
4547
4648use codec:: { Decode , Encode } ;
@@ -53,12 +55,18 @@ use extrinsic_pool::{
5355} ;
5456use polkadot_api:: PolkadotApi ;
5557use primitives:: { AccountId , BlockId , Hash , Index , UncheckedExtrinsic as FutureProofUncheckedExtrinsic } ;
58+ use rotator:: PoolRotator ;
5659use runtime:: { Address , UncheckedExtrinsic } ;
5760use substrate_runtime_primitives:: traits:: { Bounded , Checkable , Hash as HashT , BlakeTwo256 } ;
5861
5962pub use extrinsic_pool:: txpool:: { Options , Status , LightStatus , VerifiedTransaction as VerifiedTransactionOps } ;
6063pub use error:: { Error , ErrorKind , Result } ;
6164
65+ /// Maximum time the transaction will be kept in the pool.
66+ ///
67+ /// Transactions that don't get included within the limit are removed from the pool.
68+ const POOL_TIME : Duration = Duration :: from_secs ( 60 * 5 ) ;
69+
6270/// Type alias for convenience.
6371pub type CheckedExtrinsic = <UncheckedExtrinsic as Checkable < fn ( Address ) -> std:: result:: Result < AccountId , & ' static str > > >:: Checked ;
6472
@@ -70,6 +78,7 @@ pub struct VerifiedTransaction {
7078 sender : Option < AccountId > ,
7179 hash : Hash ,
7280 encoded_size : usize ,
81+ valid_till : Instant ,
7382}
7483
7584impl VerifiedTransaction {
@@ -148,8 +157,8 @@ impl txpool::Scoring<VerifiedTransaction> for Scoring {
148157 if old. is_fully_verified ( ) {
149158 assert ! ( new. is_fully_verified( ) , "Scoring::choose called with transactions from different senders" ) ;
150159 if old. index ( ) == new. index ( ) {
151- // TODO [ToDr] Do we allow replacement? If yes then it should be Choice::ReplaceOld
152- return Choice :: RejectNew ;
160+ // Allow replacing transactions so that we never fail to import to the pool.
161+ return Choice :: ReplaceOld ;
153162 }
154163 }
155164
@@ -187,17 +196,21 @@ impl txpool::Scoring<VerifiedTransaction> for Scoring {
187196pub struct Ready < ' a , A : ' a + PolkadotApi > {
188197 at_block : BlockId ,
189198 api : & ' a A ,
199+ rotator : & ' a PoolRotator ,
190200 known_nonces : HashMap < AccountId , :: primitives:: Index > ,
201+ now : Instant ,
191202}
192203
193204impl < ' a , A : ' a + PolkadotApi > Ready < ' a , A > {
194205 /// Create a new readiness evaluator at the given block. Requires that
195206 /// the ID has already been checked for local corresponding and available state.
196- fn create ( at : BlockId , api : & ' a A ) -> Self {
207+ fn create ( at : BlockId , api : & ' a A , rotator : & ' a PoolRotator ) -> Self {
197208 Ready {
198209 at_block : at,
199210 api,
200- known_nonces : HashMap :: new ( ) ,
211+ rotator,
212+ known_nonces : Default :: default ( ) ,
213+ now : Instant :: now ( ) ,
201214 }
202215 }
203216}
@@ -207,7 +220,9 @@ impl<'a, T: 'a + PolkadotApi> Clone for Ready<'a, T> {
207220 Ready {
208221 at_block : self . at_block . clone ( ) ,
209222 api : self . api ,
223+ rotator : self . rotator ,
210224 known_nonces : self . known_nonces . clone ( ) ,
225+ now : self . now . clone ( ) ,
211226 }
212227 }
213228}
@@ -230,6 +245,11 @@ impl<'a, A: 'a + PolkadotApi> txpool::Ready<VerifiedTransaction> for Ready<'a, A
230245
231246 trace ! ( target: "transaction-pool" , "Next index for sender is {}; xt index is {}" , next_index, xt. original. extrinsic. index) ;
232247
248+ if self . rotator . ban_if_stale ( & self . now , xt) {
249+ debug ! ( target: "transaction-pool" , "[{}] Banning as stale." , xt. hash) ;
250+ return Readiness :: Stale ;
251+ }
252+
233253 let result = match xt. original . extrinsic . index . cmp ( & next_index) {
234254 // TODO: this won't work perfectly since accounts can now be killed, returning the nonce
235255 // to zero.
@@ -251,11 +271,12 @@ impl<'a, A: 'a + PolkadotApi> txpool::Ready<VerifiedTransaction> for Ready<'a, A
251271
252272pub struct Verifier < ' a , A : ' a > {
253273 api : & ' a A ,
274+ rotator : & ' a PoolRotator ,
254275 at_block : BlockId ,
255276}
256277
257278impl < ' a , A > Verifier < ' a , A > where
258- A : ' a + PolkadotApi ,
279+ A : ' a + PolkadotApi ,
259280{
260281 const NO_ACCOUNT : & ' static str = "Account not found." ;
261282
@@ -289,6 +310,11 @@ impl<'a, A> txpool::Verifier<UncheckedExtrinsic> for Verifier<'a, A> where
289310
290311 debug ! ( target: "transaction-pool" , "Transaction submitted: {}" , :: substrate_primitives:: hexdisplay:: HexDisplay :: from( & encoded) ) ;
291312
313+ if self . rotator . is_banned ( & hash) {
314+ debug ! ( target: "transaction-pool" , "[{}] Transaction is temporarily banned" , hash) ;
315+ bail ! ( ErrorKind :: TemporarilyBanned ) ;
316+ }
317+
292318 let inner = match uxt. clone ( ) . check_with ( |a| self . lookup ( a) ) {
293319 Ok ( xt) => Some ( xt) ,
294320 // keep the transaction around in the future pool and attempt to promote it later.
@@ -298,17 +324,18 @@ impl<'a, A> txpool::Verifier<UncheckedExtrinsic> for Verifier<'a, A> where
298324 let sender = inner. as_ref ( ) . map ( |x| x. signed . clone ( ) ) ;
299325
300326 if encoded_size < 1024 {
301- debug ! ( target: "transaction-pool" , "Transaction verified: {} => {:?}" , hash, uxt) ;
327+ debug ! ( target: "transaction-pool" , "[{}] Transaction verified: {:?}" , hash, uxt) ;
302328 } else {
303- debug ! ( target: "transaction-pool" , "Transaction verified: {} ({} bytes is too large to display)" , hash, encoded_size) ;
329+ debug ! ( target: "transaction-pool" , "[{}] Transaction verified: ({} bytes is too large to display)" , hash, encoded_size) ;
304330 }
305331
306332 Ok ( VerifiedTransaction {
307333 original : uxt,
308334 inner,
309335 sender,
310336 hash,
311- encoded_size
337+ encoded_size,
338+ valid_till : Instant :: now ( ) + POOL_TIME ,
312339 } )
313340 }
314341}
@@ -319,16 +346,18 @@ impl<'a, A> txpool::Verifier<UncheckedExtrinsic> for Verifier<'a, A> where
319346pub struct TransactionPool < A > {
320347 inner : Pool < Hash , VerifiedTransaction , Scoring , Error > ,
321348 api : Arc < A > ,
349+ rotator : PoolRotator ,
322350}
323351
324352impl < A > TransactionPool < A > where
325- A : PolkadotApi ,
353+ A : PolkadotApi ,
326354{
327355 /// Create a new transaction pool.
328356 pub fn new ( options : Options , api : Arc < A > ) -> Self {
329357 TransactionPool {
330358 inner : Pool :: new ( options, Scoring ) ,
331359 api,
360+ rotator : Default :: default ( ) ,
332361 }
333362 }
334363
@@ -337,6 +366,7 @@ impl<A> TransactionPool<A> where
337366 let verifier = Verifier {
338367 api : & * self . api ,
339368 at_block : block,
369+ rotator : & self . rotator ,
340370 } ;
341371 self . inner . submit ( verifier, vec ! [ uxt] ) . map ( |mut v| v. swap_remove ( 0 ) )
342372 }
@@ -347,6 +377,7 @@ impl<A> TransactionPool<A> where
347377 let verifier = Verifier {
348378 api : & * self . api ,
349379 at_block : block,
380+ rotator : & self . rotator ,
350381 } ;
351382
352383 self . inner . submit ( verifier, to_reverify. into_iter ( ) . map ( |tx| tx. original . clone ( ) ) ) ?;
@@ -372,15 +403,18 @@ impl<A> TransactionPool<A> where
372403
373404 /// Cull old transactions from the queue.
374405 pub fn cull ( & self , block : BlockId ) -> Result < usize > {
375- let ready = Ready :: create ( block, & * self . api ) ;
406+ self . rotator . clear_timeouts ( & Instant :: now ( ) ) ;
407+
408+ let ready = Ready :: create ( block, & * self . api , & self . rotator ) ;
376409 Ok ( self . inner . cull ( None , ready) )
377410 }
378411
379412 /// Cull transactions from the queue and then compute the pending set.
380413 pub fn cull_and_get_pending < F , T > ( & self , block : BlockId , f : F ) -> Result < T > where
381414 F : FnOnce ( txpool:: PendingIterator < VerifiedTransaction , Ready < A > , Scoring , Listener < Hash > > ) -> T ,
382415 {
383- let ready = Ready :: create ( block, & * self . api ) ;
416+ self . rotator . clear_timeouts ( & Instant :: now ( ) ) ;
417+ let ready = Ready :: create ( block, & * self . api , & self . rotator ) ;
384418 self . inner . cull ( None , ready. clone ( ) ) ;
385419 Ok ( self . inner . pending ( ready, f) )
386420 }
@@ -424,6 +458,7 @@ impl<A> ExtrinsicPool<FutureProofUncheckedExtrinsic, BlockId, Hash> for Transact
424458
425459 let verifier = Verifier {
426460 api : & * self . api ,
461+ rotator : & self . rotator ,
427462 at_block : block,
428463 } ;
429464
0 commit comments