@@ -184,6 +184,51 @@ pub trait MaintainTransactionPool<C: Components> {
184184 ) -> error:: Result < ( ) > ;
185185}
186186
187+ fn on_block_imported < Api , Backend , Block , Executor , PoolApi > (
188+ id : & BlockId < Block > ,
189+ client : & Client < Backend , Executor , Block , Api > ,
190+ transaction_pool : & TransactionPool < PoolApi > ,
191+ ) -> error:: Result < ( ) > where
192+ Api : TaggedTransactionQueue < Block > ,
193+ Block : BlockT < Hash = <Blake2Hasher as :: primitives:: Hasher >:: Out > ,
194+ Backend : client:: backend:: Backend < Block , Blake2Hasher > ,
195+ Client < Backend , Executor , Block , Api > : ProvideRuntimeApi < Api = Api > ,
196+ Executor : client:: CallExecutor < Block , Blake2Hasher > ,
197+ PoolApi : txpool:: ChainApi < Hash = Block :: Hash , Block = Block > ,
198+ {
199+ use runtime_primitives:: transaction_validity:: TransactionValidity ;
200+
201+ // Avoid calling into runtime if there is nothing to prune from the pool anyway.
202+ if transaction_pool. status ( ) . is_empty ( ) {
203+ return Ok ( ( ) )
204+ }
205+
206+ let block = client. block ( id) ?;
207+ let tags = match block {
208+ None => return Ok ( ( ) ) ,
209+ Some ( block) => {
210+ let parent_id = BlockId :: hash ( * block. block . header ( ) . parent_hash ( ) ) ;
211+ let mut tags = vec ! [ ] ;
212+ for tx in block. block . extrinsics ( ) {
213+ let tx = client. runtime_api ( ) . validate_transaction ( & parent_id, & tx) ?;
214+ match tx {
215+ TransactionValidity :: Valid { mut provides, .. } => {
216+ tags. append ( & mut provides) ;
217+ } ,
218+ // silently ignore invalid extrinsics,
219+ // cause they might just be inherent
220+ _ => { }
221+ }
222+
223+ }
224+ tags
225+ }
226+ } ;
227+
228+ transaction_pool. prune_tags ( id, tags) . map_err ( |e| format ! ( "{:?}" , e) ) ?;
229+ Ok ( ( ) )
230+ }
231+
187232impl < C : Components > MaintainTransactionPool < Self > for C where
188233 ComponentClient < C > : ProvideRuntimeApi < Api = C :: RuntimeApi > ,
189234 C :: RuntimeApi : TaggedTransactionQueue < ComponentBlock < C > > ,
@@ -194,36 +239,7 @@ impl<C: Components> MaintainTransactionPool<Self> for C where
194239 client : & ComponentClient < C > ,
195240 transaction_pool : & TransactionPool < C :: TransactionPoolApi > ,
196241 ) -> error:: Result < ( ) > {
197- use runtime_primitives:: transaction_validity:: TransactionValidity ;
198-
199- // Avoid calling into runtime if there is nothing to prune from the pool anyway.
200- if transaction_pool. status ( ) . is_empty ( ) {
201- return Ok ( ( ) )
202- }
203-
204- let block = client. block ( id) ?;
205- let tags = match block {
206- None => return Ok ( ( ) ) ,
207- Some ( block) => {
208- let mut tags = vec ! [ ] ;
209- for tx in block. block . extrinsics ( ) {
210- let tx = client. runtime_api ( ) . validate_transaction ( id, & tx) ?;
211- match tx {
212- TransactionValidity :: Valid { mut provides, .. } => {
213- tags. append ( & mut provides) ;
214- } ,
215- // silently ignore invalid extrinsics,
216- // cause they might just be inherent
217- _ => { }
218- }
219-
220- }
221- tags
222- }
223- } ;
224-
225- transaction_pool. prune_tags ( id, tags) . map_err ( |e| format ! ( "{:?}" , e) ) ?;
226- Ok ( ( ) )
242+ on_block_imported ( id, client, transaction_pool)
227243 }
228244}
229245
@@ -520,3 +536,53 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
520536 Factory :: build_light_import_queue ( config, client)
521537 }
522538}
539+
540+ #[ cfg( test) ]
541+ mod tests {
542+ use super :: * ;
543+ use codec:: Encode ;
544+ use consensus_common:: BlockOrigin ;
545+ use substrate_test_client:: {
546+ self ,
547+ TestClient ,
548+ keyring:: Keyring ,
549+ runtime:: { Extrinsic , Transfer } ,
550+ } ;
551+
552+ #[ test]
553+ fn should_remove_transactions_from_the_pool ( ) {
554+ let client = Arc :: new ( substrate_test_client:: new ( ) ) ;
555+ let pool = TransactionPool :: new ( Default :: default ( ) , :: transaction_pool:: ChainApi :: new ( client. clone ( ) ) ) ;
556+ let transaction = {
557+ let transfer = Transfer {
558+ amount : 5 ,
559+ nonce : 0 ,
560+ from : Keyring :: Alice . to_raw_public ( ) . into ( ) ,
561+ to : Default :: default ( ) ,
562+ } ;
563+ let signature = Keyring :: from_raw_public ( transfer. from . to_fixed_bytes ( ) ) . unwrap ( ) . sign ( & transfer. encode ( ) ) . into ( ) ;
564+ Extrinsic { transfer, signature }
565+ } ;
566+ // store the transaction in the pool
567+ pool. submit_one ( & BlockId :: hash ( client. best_block_header ( ) . unwrap ( ) . hash ( ) ) , transaction. clone ( ) ) . unwrap ( ) ;
568+
569+ // import the block
570+ let mut builder = client. new_block ( ) . unwrap ( ) ;
571+ builder. push ( transaction. clone ( ) ) . unwrap ( ) ;
572+ let block = builder. bake ( ) . unwrap ( ) ;
573+ let id = BlockId :: hash ( block. header ( ) . hash ( ) ) ;
574+ client. import ( BlockOrigin :: Own , block) . unwrap ( ) ;
575+
576+ // fire notification - this should clean up the queue
577+ assert_eq ! ( pool. status( ) . ready, 1 ) ;
578+ on_block_imported (
579+ & id,
580+ & client,
581+ & pool,
582+ ) . unwrap ( ) ;
583+
584+ // then
585+ assert_eq ! ( pool. status( ) . ready, 0 ) ;
586+ assert_eq ! ( pool. status( ) . future, 0 ) ;
587+ }
588+ }
0 commit comments