@@ -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
@@ -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 } ;
@@ -2072,7 +2100,7 @@ impl TransactionPool {
20722100 & self ,
20732101 diff : diff:: Diff ,
20742102 accounts : & BTreeMap < AccountId , Account > ,
2075- ) -> Result < Vec < valid:: UserCommand > , String > {
2103+ ) -> Result < Vec < valid:: UserCommand > , TransactionPoolErrors > {
20762104 let well_formedness_errors: HashSet < _ > = diff
20772105 . list
20782106 . iter ( )
@@ -2083,9 +2111,11 @@ impl TransactionPool {
20832111 . collect ( ) ;
20842112
20852113 if !well_formedness_errors. is_empty ( ) {
2086- return Err ( format ! (
2087- "Some commands have one or more well-formedness errors: {:?}" ,
2114+ return Err ( TransactionPoolErrors :: BatchedErrors (
20882115 well_formedness_errors
2116+ . into_iter ( )
2117+ . map ( TransactionError :: WellFormedness )
2118+ . collect_vec ( ) ,
20892119 ) ) ;
20902120 }
20912121
@@ -2132,7 +2162,7 @@ impl TransactionPool {
21322162
21332163 from_unapplied_sequence:: Cache :: new ( merged)
21342164 } )
2135- . map_err ( |e| format ! ( "Invalid {:?}" , e ) ) ?;
2165+ . map_err ( TransactionPoolErrors :: Unexpected ) ?;
21362166
21372167 let diff = diff
21382168 . into_iter ( )
@@ -2142,17 +2172,25 @@ impl TransactionPool {
21422172 } )
21432173 . collect :: < Vec < _ > > ( ) ;
21442174
2145- Verifier
2175+ let ( verified , invalid ) : ( Vec < _ > , Vec < _ > ) = Verifier
21462176 . verify_commands ( diff, None )
21472177 . 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 ( )
2178+ . partition ( Result :: is_ok) ;
2179+
2180+ let verified: Vec < _ > = verified. into_iter ( ) . map ( Result :: unwrap) . collect ( ) ;
2181+ let invalid: Vec < _ > = invalid. into_iter ( ) . map ( Result :: unwrap_err) . collect ( ) ;
2182+
2183+ if !invalid. is_empty ( ) {
2184+ let transaction_pool_errors = invalid
2185+ . into_iter ( )
2186+ . map ( TransactionError :: Verifier )
2187+ . collect ( ) ;
2188+ Err ( TransactionPoolErrors :: BatchedErrors (
2189+ transaction_pool_errors,
2190+ ) )
2191+ } else {
2192+ Ok ( verified)
2193+ }
21562194 }
21572195
21582196 fn get_rebroadcastable < F > ( & mut self , has_timed_out : F ) -> Vec < Vec < UserCommand > >
0 commit comments