@@ -21,13 +21,37 @@ use crate::{
2121 MaybeWithStatus , WithHash ,
2222 } ,
2323 TransactionStatus :: Applied ,
24- UserCommand , WithStatus ,
24+ UserCommand , WellFormednessError , WithStatus ,
2525 } ,
2626 } ,
27- verifier:: Verifier ,
27+ verifier:: { Verifier , VerifierError } ,
2828 Account , AccountId , BaseLedger , Mask , TokenId , VerificationKey ,
2929} ;
3030
31+ #[ derive( Debug , thiserror:: Error ) ]
32+ pub enum TransactionPoolErrors {
33+ /// Invalid transactions, rejeceted diffs, etc...
34+ #[ error( "Transaction pool errors: {0:?}" ) ]
35+ BatchedErrors ( Vec < TransactionError > ) ,
36+ /// Errors that should panic the node (bugs in implementation)
37+ #[ error( "Unexpected error: {0}" ) ]
38+ Unexpected ( String ) ,
39+ }
40+
41+ #[ derive( Debug , thiserror:: Error ) ]
42+ pub enum TransactionError {
43+ #[ error( transparent) ]
44+ Verifier ( #[ from] VerifierError ) ,
45+ #[ error( transparent) ]
46+ WellFormedness ( #[ from] WellFormednessError ) ,
47+ }
48+
49+ impl From < String > for TransactionPoolErrors {
50+ fn from ( value : String ) -> Self {
51+ Self :: Unexpected ( value)
52+ }
53+ }
54+
3155mod consensus {
3256 use crate :: scan_state:: currency:: { BlockTimeSpan , Epoch , Length } ;
3357
@@ -475,6 +499,7 @@ enum Batch {
475499 Of ( usize ) ,
476500}
477501
502+ #[ derive( Debug ) ]
478503pub enum CommandError {
479504 InvalidNonce {
480505 account_nonce : Nonce ,
@@ -729,6 +754,7 @@ impl IndexedPool {
729754 if unchecked. expected_target_nonce ( )
730755 != first_queued. data . forget_check ( ) . applicable_at_nonce ( )
731756 {
757+ // Ocaml panics here as well
732758 panic ! ( "indexed pool nonces inconsistent when adding from backtrack." )
733759 }
734760
@@ -833,8 +859,8 @@ impl IndexedPool {
833859 } )
834860 . unwrap ( ) ;
835861
836- let keep_queue = sender_queue. split_off ( cmd_index) ;
837- let drop_queue = sender_queue. clone ( ) ;
862+ let drop_queue = sender_queue. split_off ( cmd_index) ;
863+ let keep_queue = sender_queue;
838864 assert ! ( !drop_queue. is_empty( ) ) ;
839865
840866 let currency_to_remove = drop_queue. iter ( ) . fold ( Amount :: zero ( ) , |acc, cmd| {
@@ -963,7 +989,9 @@ impl IndexedPool {
963989 self . check_expiry ( global_slot_since_genesis, & unchecked) ?;
964990 let consumed = currency_consumed ( & unchecked) . ok_or ( CommandError :: Overflow ) ?;
965991 if !unchecked. fee_token ( ) . is_default ( ) {
966- return Err ( CommandError :: BadToken ) ;
992+ return Err ( CommandError :: UnwantedFeeToken {
993+ token_id : unchecked. fee_token ( ) ,
994+ } ) ;
967995 }
968996 consumed
969997 } ;
@@ -1042,8 +1070,7 @@ impl IndexedPool {
10421070 } )
10431071 . unwrap ( ) ;
10441072
1045- let _ = queued_cmds. split_off ( replacement_index) ;
1046- let drop_queue = queued_cmds. clone ( ) ;
1073+ let drop_queue = queued_cmds. split_off ( replacement_index) ;
10471074
10481075 let to_drop = drop_queue. front ( ) . unwrap ( ) . data . forget_check ( ) ;
10491076 assert ! ( cmd_applicable_at_nonce <= to_drop. applicable_at_nonce( ) ) ;
@@ -2072,7 +2099,7 @@ impl TransactionPool {
20722099 & self ,
20732100 diff : diff:: Diff ,
20742101 accounts : & BTreeMap < AccountId , Account > ,
2075- ) -> Result < Vec < valid:: UserCommand > , String > {
2102+ ) -> Result < Vec < valid:: UserCommand > , TransactionPoolErrors > {
20762103 let well_formedness_errors: HashSet < _ > = diff
20772104 . list
20782105 . iter ( )
@@ -2083,9 +2110,11 @@ impl TransactionPool {
20832110 . collect ( ) ;
20842111
20852112 if !well_formedness_errors. is_empty ( ) {
2086- return Err ( format ! (
2087- "Some commands have one or more well-formedness errors: {:?}" ,
2113+ return Err ( TransactionPoolErrors :: BatchedErrors (
20882114 well_formedness_errors
2115+ . into_iter ( )
2116+ . map ( TransactionError :: WellFormedness )
2117+ . collect_vec ( ) ,
20892118 ) ) ;
20902119 }
20912120
@@ -2132,7 +2161,7 @@ impl TransactionPool {
21322161
21332162 from_unapplied_sequence:: Cache :: new ( merged)
21342163 } )
2135- . map_err ( |e| format ! ( "Invalid {:?}" , e ) ) ?;
2164+ . map_err ( TransactionPoolErrors :: Unexpected ) ?;
21362165
21372166 let diff = diff
21382167 . into_iter ( )
@@ -2142,17 +2171,25 @@ impl TransactionPool {
21422171 } )
21432172 . collect :: < Vec < _ > > ( ) ;
21442173
2145- Verifier
2174+ let ( verified , invalid ) : ( Vec < _ > , Vec < _ > ) = Verifier
21462175 . verify_commands ( diff, None )
21472176 . into_iter ( )
2148- . map ( |cmd| {
2149- // TODO: Handle invalids
2150- match cmd {
2151- crate :: verifier:: VerifyCommandsResult :: Valid ( cmd) => Ok ( cmd) ,
2152- e => Err ( format ! ( "invalid tx: {:?}" , e) ) ,
2153- }
2154- } )
2155- . collect ( )
2177+ . partition ( Result :: is_ok) ;
2178+
2179+ let verified: Vec < _ > = verified. into_iter ( ) . map ( Result :: unwrap) . collect ( ) ;
2180+ let invalid: Vec < _ > = invalid. into_iter ( ) . map ( Result :: unwrap_err) . collect ( ) ;
2181+
2182+ if !invalid. is_empty ( ) {
2183+ let transaction_pool_errors = invalid
2184+ . into_iter ( )
2185+ . map ( TransactionError :: Verifier )
2186+ . collect ( ) ;
2187+ Err ( TransactionPoolErrors :: BatchedErrors (
2188+ transaction_pool_errors,
2189+ ) )
2190+ } else {
2191+ Ok ( verified)
2192+ }
21562193 }
21572194
21582195 fn get_rebroadcastable < F > ( & mut self , has_timed_out : F ) -> Vec < Vec < UserCommand > >
0 commit comments