@@ -10,6 +10,20 @@ use crate::{
1010
1111use super :: P2pNetworkPubsubEffectfulAction ;
1212
13+ #[ derive( Debug ) ]
14+ pub enum PubSubError {
15+ /// The message does not contain a signature.
16+ MissingSignature ,
17+ /// The message does not contain a verifying key.
18+ MissingVerifyingKey ,
19+ /// Failed to retrieve the originator's public key.
20+ OriginatorFailed ,
21+ /// Serialization of the message without signature and key failed.
22+ SerializationError ,
23+ /// The message's signature is invalid.
24+ InvalidSignature ,
25+ }
26+
1327impl P2pNetworkPubsubEffectfulAction {
1428 pub fn effects < Store , S > ( self , _meta : & redux:: ActionMeta , store : & mut Store )
1529 where
@@ -36,54 +50,83 @@ impl P2pNetworkPubsubEffectfulAction {
3650 addr,
3751 messages,
3852 } => {
53+ let mut valid_messages = Vec :: with_capacity ( messages. len ( ) ) ;
54+
3955 for message in messages {
40- let result = if let Some ( signature) = message. signature . clone ( ) {
41- if let Ok ( Some ( pk) ) = originator ( & message) {
42- // the message is mutable only in this function
43- let mut message = message;
44- let Ok ( data) = encode_without_signature_and_key ( & mut message) else {
45- // should never happen;
46- // we just decode this message, so it should encode without error
47- bug_condition ! ( "serialization error" ) ;
48- return ;
56+ match validate_message ( message, store) {
57+ Ok ( valid_msg) => valid_messages. push ( valid_msg) ,
58+ Err ( error) => {
59+ let error_msg = match error {
60+ PubSubError :: MissingSignature => {
61+ "message doesn't contain signature"
62+ }
63+ PubSubError :: MissingVerifyingKey => {
64+ "message doesn't contain verifying key"
65+ }
66+ PubSubError :: OriginatorFailed => "originator function failed" ,
67+ PubSubError :: InvalidSignature => "invalid signature" ,
68+ PubSubError :: SerializationError => {
69+ // Should never happen;
70+ // We just decoded this message, so it should encode
71+ // without errors.
72+ bug_condition ! ( "serialization error" ) ;
73+ "serialization error"
74+ }
4975 } ;
50- // keep the binding immutable
51- let message = message;
52-
53- if store. service ( ) . verify_publication ( & pk, & data, & signature) {
54- store. dispatch ( P2pNetworkPubsubAction :: IncomingMessage {
55- peer_id,
56- message,
57- seen_limit,
58- } ) ;
59- Ok ( ( ) )
60- } else {
61- Err ( "invalid signature" )
62- }
63- } else {
64- Err ( "message doesn't contain verifying key" )
76+
77+ store. dispatch ( P2pNetworkSchedulerAction :: Error {
78+ addr,
79+ error : P2pNetworkConnectionError :: PubSubError (
80+ error_msg. to_string ( ) ,
81+ ) ,
82+ } ) ;
83+
84+ return ; // Early exit, no need to process the rest
6585 }
66- } else {
67- Err ( "message doesn't contain signature" )
68- } ;
69-
70- if let Err ( error) = result {
71- store. dispatch ( P2pNetworkSchedulerAction :: Error {
72- addr,
73- error : P2pNetworkConnectionError :: PubSubError ( error. to_string ( ) ) ,
74- } ) ;
75-
76- // TODO: should this error short-circuit the whole batch?
77- // if yes, shouldn't every message be verified first before
78- // dispatching `P2pNetworkPubsubAction::IncomingMessage`?
79- return ;
8086 }
8187 }
88+
89+ // All good, we can continue with these validated messages
90+ for message in valid_messages {
91+ store. dispatch ( P2pNetworkPubsubAction :: IncomingMessage {
92+ peer_id,
93+ message,
94+ seen_limit,
95+ } ) ;
96+ }
8297 }
8398 }
8499 }
85100}
86101
102+ fn validate_message < Store , S > (
103+ message : pb:: Message ,
104+ store : & mut Store ,
105+ ) -> Result < pb:: Message , PubSubError >
106+ where
107+ Store : crate :: P2pStore < S > ,
108+ Store :: Service : P2pCryptoService ,
109+ {
110+ let signature = message
111+ . signature
112+ . clone ( )
113+ . ok_or ( PubSubError :: MissingSignature ) ?;
114+
115+ let pk = originator ( & message)
116+ . map_err ( |_| PubSubError :: OriginatorFailed ) ?
117+ . ok_or ( PubSubError :: MissingVerifyingKey ) ?;
118+
119+ let mut message = message;
120+ let data = encode_without_signature_and_key ( & mut message)
121+ . map_err ( |_| PubSubError :: SerializationError ) ?;
122+
123+ if store. service ( ) . verify_publication ( & pk, & data, & signature) {
124+ Ok ( message)
125+ } else {
126+ Err ( PubSubError :: InvalidSignature )
127+ }
128+ }
129+
87130pub fn originator ( message : & pb:: Message ) -> Result < Option < PublicKey > , DecodingError > {
88131 message
89132 . key
0 commit comments