@@ -117,6 +117,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
117
117
private int reprocessPaymentSentMessageCount ;
118
118
private int reprocessPaymentReceivedMessageCount ;
119
119
private boolean makerInitTradeRequestNacked = false ;
120
+ private boolean autoMarkPaymentReceivedOnNack = true ;
120
121
121
122
///////////////////////////////////////////////////////////////////////////////////////////
122
123
// Constructor
@@ -746,6 +747,7 @@ public final FluentProtocol.Setup tasks(Class<? extends Task<Trade>>... tasks) {
746
747
// ACK msg
747
748
///////////////////////////////////////////////////////////////////////////////////////////
748
749
750
+ // TODO: this has grown in complexity over time and could use refactoring
749
751
private void onAckMessage (AckMessage ackMessage , NodeAddress sender ) {
750
752
751
753
// ignore if trade is completely finished
@@ -818,6 +820,7 @@ private void onAckMessage(AckMessage ackMessage, NodeAddress sender) {
818
820
// ack message from buyer
819
821
if (peer == trade .getBuyer ()) {
820
822
trade .getBuyer ().setPaymentReceivedAckMessage (ackMessage );
823
+ processModel .getTradeManager ().requestPersistence ();
821
824
822
825
// handle successful ack
823
826
if (ackMessage .isSuccess ()) {
@@ -827,24 +830,21 @@ private void onAckMessage(AckMessage ackMessage, NodeAddress sender) {
827
830
// handle nack
828
831
else {
829
832
log .warn ("We received a NACK for our PaymentReceivedMessage to the buyer for {} {}" , trade .getClass ().getSimpleName (), trade .getId ());
830
-
833
+
831
834
// nack includes updated multisig hex since v1.1.1
832
835
if (ackMessage .getUpdatedMultisigHex () != null ) {
833
836
trade .getBuyer ().setUpdatedMultisigHex (ackMessage .getUpdatedMultisigHex ());
834
-
835
- // reset state if not processed
836
- if (trade .isPaymentReceived () && !trade .isPayoutPublished () && !isPaymentReceivedMessageAckedByEither ()) {
837
- log .warn ("Resetting state to payment sent for {} {}" , trade .getClass ().getSimpleName (), trade .getId ());
838
- trade .resetToPaymentSentState ();
839
- }
837
+ processModel .getTradeManager ().requestPersistence ();
838
+ boolean autoResent = handlePaymentReceivedNack (ackMessage );
839
+ if (autoResent ) return ; // skip remaining processing if auto resent
840
840
}
841
841
}
842
- processModel .getTradeManager ().requestPersistence ();
843
842
}
844
843
845
844
// ack message from arbitrator
846
845
else if (peer == trade .getArbitrator ()) {
847
846
trade .getArbitrator ().setPaymentReceivedAckMessage (ackMessage );
847
+ processModel .getTradeManager ().requestPersistence ();
848
848
849
849
// handle nack
850
850
if (!ackMessage .isSuccess ()) {
@@ -853,15 +853,11 @@ else if (peer == trade.getArbitrator()) {
853
853
// nack includes updated multisig hex since v1.1.1
854
854
if (ackMessage .getUpdatedMultisigHex () != null ) {
855
855
trade .getArbitrator ().setUpdatedMultisigHex (ackMessage .getUpdatedMultisigHex ());
856
-
857
- // reset state if not processed
858
- if (trade .isPaymentReceived () && !trade .isPayoutPublished () && !isPaymentReceivedMessageAckedByEither ()) {
859
- log .warn ("Resetting state to payment sent for {} {}" , trade .getClass ().getSimpleName (), trade .getId ());
860
- trade .resetToPaymentSentState ();
861
- }
856
+ processModel .getTradeManager ().requestPersistence ();
857
+ boolean autoResent = handlePaymentReceivedNack (ackMessage );
858
+ if (autoResent ) return ; // skip remaining processing if auto resent
862
859
}
863
860
}
864
- processModel .getTradeManager ().requestPersistence ();
865
861
} else {
866
862
log .warn ("Received AckMessage from unexpected peer for {}, sender={}, trade={} {}, messageUid={}, success={}, errorMsg={}" , ackMessage .getSourceMsgClassName (), sender , trade .getClass ().getSimpleName (), trade .getId (), ackMessage .getSourceUid (), ackMessage .isSuccess (), ackMessage .getErrorMessage ());
867
863
return ;
@@ -886,6 +882,26 @@ else if (peer == trade.getArbitrator()) {
886
882
trade .onAckMessage (ackMessage , sender );
887
883
}
888
884
885
+ private boolean handlePaymentReceivedNack (AckMessage ackMessage ) {
886
+ synchronized (trade .getLock ()) {
887
+ if (trade .isPaymentReceived () && !trade .isPayoutPublished () && !isPaymentReceivedMessageAckedByEither ()) {
888
+ log .warn ("Resetting state to payment sent for {} {}" , trade .getClass ().getSimpleName (), trade .getId ());
889
+ trade .resetToPaymentSentState ();
890
+
891
+ // automatically mark payment received again once on nack
892
+ if (autoMarkPaymentReceivedOnNack ) {
893
+ autoMarkPaymentReceivedOnNack = false ;
894
+ log .warn ("Automatically marking payment received on NACK for {} {} after error={}" , trade .getClass ().getSimpleName (), trade .getId (), ackMessage .getErrorMessage ());
895
+ UserThread .execute (() -> {
896
+ ((SellerProtocol ) this ).onPaymentReceived (null , null );
897
+ });
898
+ return true ;
899
+ }
900
+ }
901
+ return false ;
902
+ }
903
+ }
904
+
889
905
private void handleFirstMakerInitTradeRequestNack (AckMessage ackMessage ) {
890
906
log .warn ("Maker received NACK to InitTradeRequest from arbitrator for {} {}, messageUid={}, errorMessage={}" , trade .getClass ().getSimpleName (), trade .getId (), ackMessage .getSourceUid (), ackMessage .getErrorMessage ());
891
907
ThreadUtils .execute (() -> {
0 commit comments