@@ -783,9 +783,11 @@ impl OutputCache {
783783 confirmed_tx : & Transaction ,
784784 block_id : Id < GenBlock > ,
785785 ) -> WalletResult < Vec < ( Id < Transaction > , WalletTx ) > > {
786+ // TODO: maybe make it an enum
786787 struct ConflictCheck {
787788 frozen_token_id : Option < TokenId > ,
788789 confirmed_account_nonce : Option < ( AccountType , AccountNonce ) > ,
790+ conflicting_order_command : Option < ( OrderAccountCommandTag , OrderId ) > ,
789791 }
790792
791793 let conflict_checks = confirmed_tx
@@ -804,6 +806,7 @@ impl OutputCache {
804806 outpoint. account ( ) . into ( ) ,
805807 outpoint. nonce ( ) ,
806808 ) ) ,
809+ conflicting_order_command : None ,
807810 } ) ,
808811 TxInput :: AccountCommand ( nonce, cmd) => match cmd {
809812 AccountCommand :: MintTokens ( _, _)
@@ -816,13 +819,34 @@ impl OutputCache {
816819 | AccountCommand :: FillOrder ( _, _, _) => Some ( ConflictCheck {
817820 frozen_token_id : None ,
818821 confirmed_account_nonce : Some ( ( cmd. into ( ) , * nonce) ) ,
822+ conflicting_order_command : None ,
819823 } ) ,
820824 | AccountCommand :: FreezeToken ( token_id, _) => Some ( ConflictCheck {
821825 frozen_token_id : Some ( * token_id) ,
822826 confirmed_account_nonce : Some ( ( cmd. into ( ) , * nonce) ) ,
827+ conflicting_order_command : None ,
823828 } ) ,
824829 } ,
825- TxInput :: OrderAccountCommand ( _) => None ,
830+ TxInput :: OrderAccountCommand ( cmd) => {
831+ let order_id = match cmd {
832+ OrderAccountCommand :: FillOrder ( order_id, _)
833+ | OrderAccountCommand :: FreezeOrder ( order_id)
834+ | OrderAccountCommand :: ConcludeOrder ( order_id) => * order_id,
835+ } ;
836+ let cmd_tag: OrderAccountCommandTag = cmd. into ( ) ;
837+ match cmd_tag {
838+ // ConcludeOrder and FreezeOrder are exclusive: only one tx can win.
839+ // Any unconfirmed tx with the same command for the same order conflicts.
840+ OrderAccountCommandTag :: ConcludeOrder
841+ | OrderAccountCommandTag :: FreezeOrder => Some ( ConflictCheck {
842+ frozen_token_id : None ,
843+ confirmed_account_nonce : None ,
844+ conflicting_order_command : Some ( ( cmd_tag, order_id) ) ,
845+ } ) ,
846+ // Multiple fills for the same order can coexist.
847+ OrderAccountCommandTag :: FillOrder => None ,
848+ }
849+ }
826850 }
827851 } )
828852 . collect :: < Vec < _ > > ( ) ;
@@ -857,6 +881,21 @@ impl OutputCache {
857881 continue ;
858882 }
859883 }
884+
885+ if let Some ( ( confirmed_cmd_tag, confirmed_order_id) ) =
886+ conflict_check. conflicting_order_command
887+ {
888+ if confirmed_tx. get_id ( ) != tx. get_transaction ( ) . get_id ( )
889+ && uses_conflicting_order_command (
890+ unconfirmed_tx,
891+ confirmed_cmd_tag,
892+ confirmed_order_id,
893+ )
894+ {
895+ conflicting_txs. insert ( tx. get_transaction ( ) . get_id ( ) ) ;
896+ continue ;
897+ }
898+ }
860899 }
861900 WalletTx :: Block ( _) => {
862901 utils:: debug_panic_or_log!( "Cannot be block reward" ) ;
@@ -2062,6 +2101,41 @@ fn uses_conflicting_nonce(
20622101 } )
20632102}
20642103
2104+ fn uses_conflicting_order_command (
2105+ unconfirmed_tx : & WalletTx ,
2106+ confirmed_cmd_tag : OrderAccountCommandTag ,
2107+ confirmed_order_id : OrderId ,
2108+ ) -> bool {
2109+ unconfirmed_tx. inputs ( ) . iter ( ) . any ( |input| match input {
2110+ TxInput :: OrderAccountCommand ( cmd) => {
2111+ let unconfirmed_order_id = match cmd {
2112+ OrderAccountCommand :: FillOrder ( id, _)
2113+ | OrderAccountCommand :: FreezeOrder ( id)
2114+ | OrderAccountCommand :: ConcludeOrder ( id) => * id,
2115+ } ;
2116+ // It is only a conflict if it is the same order id
2117+ if unconfirmed_order_id != confirmed_order_id {
2118+ return false ;
2119+ }
2120+
2121+ let unconfirmed_cmd_tag: OrderAccountCommandTag = cmd. into ( ) ;
2122+ match confirmed_cmd_tag {
2123+ // Confirmed fill orders do not conflict with anything
2124+ OrderAccountCommandTag :: FillOrder => false ,
2125+ // Confirmed conclude order conflict with any other unconfirmed operation on the
2126+ // order
2127+ OrderAccountCommandTag :: ConcludeOrder => true ,
2128+ // Confirmed Freeze order conflicts with any unconfirmed Fill or Freeze order
2129+ OrderAccountCommandTag :: FreezeOrder => match unconfirmed_cmd_tag {
2130+ OrderAccountCommandTag :: FillOrder | OrderAccountCommandTag :: FreezeOrder => true ,
2131+ OrderAccountCommandTag :: ConcludeOrder => false ,
2132+ } ,
2133+ }
2134+ }
2135+ TxInput :: Utxo ( _) | TxInput :: Account ( _) | TxInput :: AccountCommand ( _, _) => false ,
2136+ } )
2137+ }
2138+
20652139#[ derive( thiserror:: Error , Debug , Eq , PartialEq ) ]
20662140pub enum OutputCacheInconsistencyError {
20672141 #[ error( "Transaction from {0:?} is confirmed and among unconfirmed descendants" ) ]
0 commit comments