1717use crate :: {
1818 ExHashT ,
1919 chain:: { Client , FinalityProofProvider } ,
20- config:: { BoxFinalityProofRequestBuilder , ProtocolId , TransactionPool } ,
20+ config:: { BoxFinalityProofRequestBuilder , ProtocolId , TransactionPool , TransactionImportFuture , TransactionImport } ,
2121 error,
2222 utils:: interval
2323} ;
2424
2525use bytes:: { Bytes , BytesMut } ;
26- use futures:: prelude:: * ;
26+ use futures:: { prelude:: * , stream :: FuturesUnordered } ;
2727use generic_proto:: { GenericProto , GenericProtoOut } ;
2828use libp2p:: { Multiaddr , PeerId } ;
2929use libp2p:: core:: { ConnectedPoint , connection:: { ConnectionId , ListenerId } } ;
@@ -101,6 +101,13 @@ mod rep {
101101 pub const UNEXPECTED_STATUS : Rep = Rep :: new ( -( 1 << 20 ) , "Unexpected status message" ) ;
102102 /// Reputation change when we are a light client and a peer is behind us.
103103 pub const PEER_BEHIND_US_LIGHT : Rep = Rep :: new ( -( 1 << 8 ) , "Useless for a light peer" ) ;
104+ /// Reputation change when a peer sends us any extrinsic.
105+ ///
106+ /// This forces node to verify it, thus the negative value here. Once extrinsic is verified,
107+ /// reputation change should be refunded with `ANY_EXTRINSIC_REFUND`
108+ pub const ANY_EXTRINSIC : Rep = Rep :: new ( -( 1 << 4 ) , "Any extrinsic" ) ;
109+ /// Reputation change when a peer sends us any extrinsic that is not invalid.
110+ pub const ANY_EXTRINSIC_REFUND : Rep = Rep :: new ( 1 << 4 , "Any extrinsic (refund)" ) ;
104111 /// Reputation change when a peer sends us an extrinsic that we didn't know about.
105112 pub const GOOD_EXTRINSIC : Rep = Rep :: new ( 1 << 7 , "Good extrinsic" ) ;
106113 /// Reputation change when a peer sends us a bad extrinsic.
@@ -182,6 +189,24 @@ impl Metrics {
182189 }
183190}
184191
192+ struct PendingTransaction {
193+ validation : TransactionImportFuture ,
194+ peer_id : PeerId ,
195+ }
196+
197+ impl Future for PendingTransaction {
198+ type Output = ( PeerId , TransactionImport ) ;
199+
200+ fn poll ( self : Pin < & mut Self > , cx : & mut std:: task:: Context < ' _ > ) -> Poll < Self :: Output > {
201+ let this = Pin :: into_inner ( self ) ;
202+ if let Poll :: Ready ( import_result) = this. validation . poll_unpin ( cx) {
203+ return Poll :: Ready ( ( this. peer_id . clone ( ) , import_result) ) ;
204+ }
205+
206+ Poll :: Pending
207+ }
208+ }
209+
185210// Lock must always be taken in order declared here.
186211pub struct Protocol < B : BlockT , H : ExHashT > {
187212 /// Interval at which we call `tick`.
@@ -190,6 +215,8 @@ pub struct Protocol<B: BlockT, H: ExHashT> {
190215 propagate_timeout : Pin < Box < dyn Stream < Item = ( ) > + Send > > ,
191216 /// Pending list of messages to return from `poll` as a priority.
192217 pending_messages : VecDeque < CustomMessageOutcome < B > > ,
218+ /// Pending extrinsic verification tasks.
219+ pending_transactions : FuturesUnordered < PendingTransaction > ,
193220 config : ProtocolConfig ,
194221 genesis_hash : B :: Hash ,
195222 sync : ChainSync < B > ,
@@ -394,6 +421,7 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
394421 tick_timeout : Box :: pin ( interval ( TICK_TIMEOUT ) ) ,
395422 propagate_timeout : Box :: pin ( interval ( PROPAGATE_TIMEOUT ) ) ,
396423 pending_messages : VecDeque :: new ( ) ,
424+ pending_transactions : FuturesUnordered :: new ( ) ,
397425 config,
398426 context_data : ContextData {
399427 peers : HashMap :: new ( ) ,
@@ -1121,17 +1149,25 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
11211149 let hash = self . transaction_pool . hash_of ( & t) ;
11221150 peer. known_extrinsics . insert ( hash) ;
11231151
1124- self . transaction_pool . import (
1125- self . peerset_handle . clone ( ) . into ( ) ,
1126- who. clone ( ) ,
1127- rep:: GOOD_EXTRINSIC ,
1128- rep:: BAD_EXTRINSIC ,
1129- t,
1130- ) ;
1152+ self . peerset_handle . report_peer ( who. clone ( ) , rep:: ANY_EXTRINSIC ) ;
1153+
1154+ self . pending_transactions . push ( PendingTransaction {
1155+ peer_id : who. clone ( ) ,
1156+ validation : self . transaction_pool . import ( t) ,
1157+ } ) ;
11311158 }
11321159 }
11331160 }
11341161
1162+ fn on_handle_extrinsic_import ( & mut self , who : PeerId , import : TransactionImport ) {
1163+ match import {
1164+ TransactionImport :: KnownGood => self . peerset_handle . report_peer ( who, rep:: ANY_EXTRINSIC_REFUND ) ,
1165+ TransactionImport :: NewGood => self . peerset_handle . report_peer ( who, rep:: GOOD_EXTRINSIC ) ,
1166+ TransactionImport :: Bad => self . peerset_handle . report_peer ( who, rep:: BAD_EXTRINSIC ) ,
1167+ TransactionImport :: None => { } ,
1168+ }
1169+ }
1170+
11351171 /// Propagate one extrinsic.
11361172 pub fn propagate_extrinsic (
11371173 & mut self ,
@@ -1953,7 +1989,7 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviour for Protocol<B, H> {
19531989 & mut self . context_data . stats ,
19541990 & mut self . context_data . peers ,
19551991 & id,
1956- GenericMessage :: BlockRequest ( r)
1992+ GenericMessage :: BlockRequest ( r) ,
19571993 )
19581994 }
19591995 }
@@ -1970,7 +2006,7 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviour for Protocol<B, H> {
19702006 & mut self . context_data . stats ,
19712007 & mut self . context_data . peers ,
19722008 & id,
1973- GenericMessage :: BlockRequest ( r)
2009+ GenericMessage :: BlockRequest ( r) ,
19742010 )
19752011 }
19762012 }
@@ -1988,9 +2024,13 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviour for Protocol<B, H> {
19882024 & mut self . context_data . stats ,
19892025 & mut self . context_data . peers ,
19902026 & id,
1991- GenericMessage :: FinalityProofRequest ( r) )
2027+ GenericMessage :: FinalityProofRequest ( r) ,
2028+ )
19922029 }
19932030 }
2031+ if let Poll :: Ready ( Some ( ( peer_id, result) ) ) = self . pending_transactions . poll_next_unpin ( cx) {
2032+ self . on_handle_extrinsic_import ( peer_id, result) ;
2033+ }
19942034 if let Some ( message) = self . pending_messages . pop_front ( ) {
19952035 return Poll :: Ready ( NetworkBehaviourAction :: GenerateEvent ( message) ) ;
19962036 }
0 commit comments