add multisig wallet state and wait for multisig to complete
refactor trade protocol
This commit is contained in:
parent
f61fd09127
commit
50126874a0
@ -107,7 +107,10 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
// #################### Phase INIT
|
// #################### Phase INIT
|
||||||
// When trade protocol starts no funds are on stake
|
// When trade protocol starts no funds are on stake
|
||||||
PREPARATION(Phase.INIT),
|
PREPARATION(Phase.INIT),
|
||||||
CONTRACT_SIGNATURE_REQUESTED(Phase.INIT), // TODO (woodser): add more states for initializing multisig, etc to support trade initialization notifications
|
MULTISIG_PREPARED(Phase.INIT),
|
||||||
|
MULTISIG_MADE(Phase.INIT),
|
||||||
|
MULTISIG_COMPLETED(Phase.INIT),
|
||||||
|
CONTRACT_SIGNATURE_REQUESTED(Phase.INIT),
|
||||||
CONTRACT_SIGNED(Phase.INIT),
|
CONTRACT_SIGNED(Phase.INIT),
|
||||||
|
|
||||||
// At first part maker/taker have different roles
|
// At first part maker/taker have different roles
|
||||||
@ -894,7 +897,6 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
|
|
||||||
// create block listener
|
// create block listener
|
||||||
depositTxListener = new MoneroWalletListener() {
|
depositTxListener = new MoneroWalletListener() {
|
||||||
|
|
||||||
Long unlockHeight = null;
|
Long unlockHeight = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -903,6 +905,9 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
// ignore if no longer listening
|
// ignore if no longer listening
|
||||||
if (depositTxListener == null) return;
|
if (depositTxListener == null) return;
|
||||||
|
|
||||||
|
// use latest height
|
||||||
|
height = havenoWallet.getHeight();
|
||||||
|
|
||||||
// ignore if before unlock height
|
// ignore if before unlock height
|
||||||
if (unlockHeight != null && height < unlockHeight) return;
|
if (unlockHeight != null && height < unlockHeight) return;
|
||||||
|
|
||||||
|
@ -3,16 +3,15 @@ package bisq.core.trade.protocol;
|
|||||||
import bisq.core.trade.ArbitratorTrade;
|
import bisq.core.trade.ArbitratorTrade;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.DepositRequest;
|
import bisq.core.trade.messages.DepositRequest;
|
||||||
import bisq.core.trade.messages.InitMultisigRequest;
|
import bisq.core.trade.messages.DepositResponse;
|
||||||
import bisq.core.trade.messages.InitTradeRequest;
|
import bisq.core.trade.messages.InitTradeRequest;
|
||||||
import bisq.core.trade.messages.SignContractRequest;
|
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
||||||
|
import bisq.core.trade.messages.SignContractResponse;
|
||||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||||
import bisq.core.trade.protocol.tasks.ArbitratorSendsInitTradeAndMultisigRequests;
|
import bisq.core.trade.protocol.tasks.ArbitratorSendsInitTradeAndMultisigRequests;
|
||||||
import bisq.core.trade.protocol.tasks.ArbitratorProcessesDepositRequest;
|
import bisq.core.trade.protocol.tasks.ArbitratorProcessesDepositRequest;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ArbitratorProcessesReserveTx;
|
import bisq.core.trade.protocol.tasks.ArbitratorProcessesReserveTx;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
|
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
|
|
||||||
import bisq.core.util.Validator;
|
import bisq.core.util.Validator;
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
@ -59,60 +58,12 @@ public class ArbitratorProtocol extends DisputeProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||||
System.out.println("ArbitratorProtocol.handleInitMultisigRequest()");
|
log.warn("Arbitrator ignoring SignContractResponse");
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(anyPhase(Trade.Phase.INIT)
|
|
||||||
.with(request)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
ProcessInitMultisigRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
|
||||||
System.out.println("ArbitratorProtocol.handleSignContractRequest()");
|
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message); // TODO (woodser): synchronize access since concurrent requests processed
|
|
||||||
expect(anyPhase(Trade.Phase.INIT)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleDepositRequest(DepositRequest request, NodeAddress sender) {
|
public void handleDepositRequest(DepositRequest request, NodeAddress sender) {
|
||||||
System.out.println("ArbitratorProtocol.handleDepositRequest()");
|
System.out.println("ArbitratorProtocol.handleDepositRequest() " + trade.getId());
|
||||||
synchronized (trade) {
|
synchronized (trade) {
|
||||||
latchTrade();
|
latchTrade();
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
Validator.checkTradeId(processModel.getOfferId(), request);
|
||||||
@ -139,6 +90,16 @@ public class ArbitratorProtocol extends DisputeProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||||
|
log.warn("Arbitrator ignoring DepositResponse");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
||||||
|
log.warn("Arbitrator ignoring PaymentAccountPayloadRequest");
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Message dispatcher
|
// Message dispatcher
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -28,30 +28,22 @@ import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
|||||||
import bisq.core.trade.messages.PaymentReceivedMessage;
|
import bisq.core.trade.messages.PaymentReceivedMessage;
|
||||||
import bisq.core.trade.messages.SignContractRequest;
|
import bisq.core.trade.messages.SignContractRequest;
|
||||||
import bisq.core.trade.messages.SignContractResponse;
|
import bisq.core.trade.messages.SignContractResponse;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessDepositResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
|
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessPaymentAccountPayloadRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.SendSignContractRequestAfterMultisig;
|
|
||||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
import bisq.core.trade.protocol.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
||||||
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
|
import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
|
||||||
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse;
|
import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse;
|
||||||
import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx;
|
||||||
import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer;
|
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerSendsInitTradeRequestIfUnreserved;
|
import bisq.core.trade.protocol.tasks.maker.MakerSendsInitTradeRequestIfUnreserved;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
|
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
|
||||||
import bisq.core.util.Validator;
|
|
||||||
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
import bisq.common.handlers.ResultHandler;
|
import bisq.common.handlers.ResultHandler;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol {
|
public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol {
|
||||||
@ -68,8 +60,6 @@ public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol
|
|||||||
// MakerProtocol
|
// MakerProtocol
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO (woodser): these methods are duplicated with SellerAsMakerProtocol due to single inheritance
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitTradeRequest(InitTradeRequest message,
|
public void handleInitTradeRequest(InitTradeRequest message,
|
||||||
NodeAddress peer,
|
NodeAddress peer,
|
||||||
@ -102,162 +92,27 @@ public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleInitMultisigRequest()");
|
super.handleInitMultisigRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(anyPhase(Trade.Phase.INIT)
|
|
||||||
.with(request)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
ProcessInitMultisigRequest.class,
|
|
||||||
SendSignContractRequestAfterMultisig.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
super.handleSignContractRequest(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNATURE_REQUESTED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNATURE_REQUESTED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
// process sign contract request after contract signature requested
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNATURE_REQUESTED) new Thread(() -> handleSignContractRequest(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
super.handleSignContractResponse(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
// process sign contract response after contract signed
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNED) new Thread(() -> handleSignContractResponse(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleDepositResponse()");
|
super.handleDepositResponse(response, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), response);
|
|
||||||
processModel.setTradeMessage(response);
|
|
||||||
expect(state(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST)
|
|
||||||
.with(response)
|
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessDepositResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, response);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, response, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handlePaymentAccountPayloadRequest() " + trade.getId());
|
super.handlePaymentAccountPayloadRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
if (trade.getState() == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(state(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)
|
|
||||||
.with(request)
|
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessPaymentAccountPayloadRequest.class,
|
|
||||||
MakerRemovesOpenOffer.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
stopTimeout();
|
|
||||||
this.errorMessageHandler = null;
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -297,7 +152,7 @@ public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol
|
|||||||
.with(message)
|
.with(message)
|
||||||
.from(peer))
|
.from(peer))
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
MakerRemovesOpenOffer.class,
|
MaybeRemoveOpenOffer.class,
|
||||||
BuyerProcessDelayedPayoutTxSignatureRequest.class,
|
BuyerProcessDelayedPayoutTxSignatureRequest.class,
|
||||||
BuyerVerifiesPreparedDelayedPayoutTx.class,
|
BuyerVerifiesPreparedDelayedPayoutTx.class,
|
||||||
BuyerSignsDelayedPayoutTx.class,
|
BuyerSignsDelayedPayoutTx.class,
|
||||||
|
@ -33,12 +33,6 @@ import bisq.core.trade.messages.SignContractRequest;
|
|||||||
import bisq.core.trade.messages.SignContractResponse;
|
import bisq.core.trade.messages.SignContractResponse;
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessDepositResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessPaymentAccountPayloadRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.SendSignContractRequestAfterMultisig;
|
|
||||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
import bisq.core.trade.protocol.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||||
import bisq.core.trade.protocol.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
||||||
@ -54,13 +48,11 @@ import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx;
|
|||||||
import bisq.core.trade.protocol.tasks.taker.TakerReservesTradeFunds;
|
import bisq.core.trade.protocol.tasks.taker.TakerReservesTradeFunds;
|
||||||
import bisq.core.trade.protocol.tasks.taker.TakerSendsInitTradeRequestToArbitrator;
|
import bisq.core.trade.protocol.tasks.taker.TakerSendsInitTradeRequestToArbitrator;
|
||||||
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
|
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
|
||||||
import bisq.core.util.Validator;
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
import bisq.common.handlers.ResultHandler;
|
import bisq.common.handlers.ResultHandler;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -86,8 +78,6 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol
|
|||||||
// Take offer
|
// Take offer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO (woodser): these methods are duplicated with SellerAsTakerProtocol due to single inheritance
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTakeOffer(TradeResultHandler tradeResultHandler,
|
public void onTakeOffer(TradeResultHandler tradeResultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
@ -119,161 +109,27 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleInitMultisigRequest()");
|
super.handleInitMultisigRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(anyPhase(Trade.Phase.INIT)
|
|
||||||
.with(request)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
ProcessInitMultisigRequest.class,
|
|
||||||
SendSignContractRequestAfterMultisig.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
super.handleSignContractRequest(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNATURE_REQUESTED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNATURE_REQUESTED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
// process sign contract request after contract signature requested
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNATURE_REQUESTED) new Thread(() -> handleSignContractRequest(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse()");
|
super.handleSignContractResponse(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNED) new Thread(() -> handleSignContractResponse(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleDepositResponse()");
|
super.handleDepositResponse(response, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), response);
|
|
||||||
processModel.setTradeMessage(response);
|
|
||||||
expect(state(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST)
|
|
||||||
.with(response)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessDepositResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, response);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, response, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handlePaymentAccountPayloadRequest()");
|
super.handlePaymentAccountPayloadRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
if (trade.getState() == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(state(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)
|
|
||||||
.with(request)
|
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessPaymentAccountPayloadRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
stopTimeout();
|
|
||||||
this.errorMessageHandler = null;
|
|
||||||
tradeResultHandler.handleResult(trade); // trade is initialized
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -142,8 +142,8 @@ public abstract class BuyerProtocol extends DisputeProtocol {
|
|||||||
.using(new TradeTaskRunner(trade,
|
.using(new TradeTaskRunner(trade,
|
||||||
() -> {
|
() -> {
|
||||||
this.errorMessageHandler = null;
|
this.errorMessageHandler = null;
|
||||||
resultHandler.handleResult();
|
|
||||||
handleTaskRunnerSuccess(event);
|
handleTaskRunnerSuccess(event);
|
||||||
|
resultHandler.handleResult();
|
||||||
},
|
},
|
||||||
(errorMessage) -> {
|
(errorMessage) -> {
|
||||||
handleTaskRunnerFault(event, errorMessage);
|
handleTaskRunnerFault(event, errorMessage);
|
||||||
|
@ -183,10 +183,6 @@ public class ProcessModel implements Model, PersistablePayload {
|
|||||||
@Setter
|
@Setter
|
||||||
private String multisigAddress;
|
private String multisigAddress;
|
||||||
@Nullable
|
@Nullable
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private boolean multisigSetupComplete; // TODO (woodser): redundant with multisigAddress existing, remove
|
|
||||||
|
|
||||||
|
|
||||||
// We want to indicate the user the state of the message delivery of the
|
// We want to indicate the user the state of the message delivery of the
|
||||||
// PaymentSentMessage. As well we do an automatic re-send in case it was not ACKed yet.
|
// PaymentSentMessage. As well we do an automatic re-send in case it was not ACKed yet.
|
||||||
@ -247,7 +243,6 @@ public class ProcessModel implements Model, PersistablePayload {
|
|||||||
Optional.ofNullable(preparedMultisigHex).ifPresent(e -> builder.setPreparedMultisigHex(preparedMultisigHex));
|
Optional.ofNullable(preparedMultisigHex).ifPresent(e -> builder.setPreparedMultisigHex(preparedMultisigHex));
|
||||||
Optional.ofNullable(madeMultisigHex).ifPresent(e -> builder.setMadeMultisigHex(madeMultisigHex));
|
Optional.ofNullable(madeMultisigHex).ifPresent(e -> builder.setMadeMultisigHex(madeMultisigHex));
|
||||||
Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress));
|
Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress));
|
||||||
Optional.ofNullable(multisigSetupComplete).ifPresent(e -> builder.setMultisigSetupComplete(multisigSetupComplete));
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +274,6 @@ public class ProcessModel implements Model, PersistablePayload {
|
|||||||
processModel.setPreparedMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getPreparedMultisigHex()));
|
processModel.setPreparedMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getPreparedMultisigHex()));
|
||||||
processModel.setMadeMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getMadeMultisigHex()));
|
processModel.setMadeMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getMadeMultisigHex()));
|
||||||
processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress()));
|
processModel.setMultisigAddress(ProtoUtil.stringOrNullFromProto(proto.getMultisigAddress()));
|
||||||
processModel.setMultisigSetupComplete(proto.getMultisigSetupComplete());
|
|
||||||
|
|
||||||
String paymentStartedMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentStartedMessageState());
|
String paymentStartedMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentStartedMessageState());
|
||||||
MessageState paymentStartedMessageState = ProtoUtil.enumFromProto(MessageState.class, paymentStartedMessageStateString);
|
MessageState paymentStartedMessageState = ProtoUtil.enumFromProto(MessageState.class, paymentStartedMessageStateString);
|
||||||
|
@ -21,23 +21,17 @@ package bisq.core.trade.protocol;
|
|||||||
import bisq.core.trade.SellerAsMakerTrade;
|
import bisq.core.trade.SellerAsMakerTrade;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.PaymentSentMessage;
|
import bisq.core.trade.messages.PaymentSentMessage;
|
||||||
|
import bisq.core.trade.messages.SignContractRequest;
|
||||||
|
import bisq.core.trade.messages.SignContractResponse;
|
||||||
import bisq.core.trade.messages.DepositResponse;
|
import bisq.core.trade.messages.DepositResponse;
|
||||||
import bisq.core.trade.messages.DepositTxMessage;
|
import bisq.core.trade.messages.DepositTxMessage;
|
||||||
import bisq.core.trade.messages.InitMultisigRequest;
|
import bisq.core.trade.messages.InitMultisigRequest;
|
||||||
import bisq.core.trade.messages.InitTradeRequest;
|
import bisq.core.trade.messages.InitTradeRequest;
|
||||||
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
||||||
import bisq.core.trade.messages.SignContractRequest;
|
|
||||||
import bisq.core.trade.messages.SignContractResponse;
|
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessDepositResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
|
import bisq.core.trade.protocol.tasks.ProcessInitTradeRequest;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessPaymentAccountPayloadRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.SendSignContractRequestAfterMultisig;
|
|
||||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
import bisq.core.trade.protocol.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer;
|
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerSendsInitTradeRequestIfUnreserved;
|
import bisq.core.trade.protocol.tasks.maker.MakerSendsInitTradeRequestIfUnreserved;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
|
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
|
||||||
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
|
||||||
@ -45,13 +39,11 @@ import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureR
|
|||||||
import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx;
|
||||||
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx;
|
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx;
|
||||||
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerProcessDepositTxMessage;
|
import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerProcessDepositTxMessage;
|
||||||
import bisq.core.util.Validator;
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
import bisq.common.handlers.ResultHandler;
|
import bisq.common.handlers.ResultHandler;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtocol {
|
public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtocol {
|
||||||
@ -68,8 +60,6 @@ public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtoc
|
|||||||
// MakerProtocol
|
// MakerProtocol
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO (woodser): these methods are duplicated with BuyerAsMakerProtocol due to single inheritance
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitTradeRequest(InitTradeRequest message,
|
public void handleInitTradeRequest(InitTradeRequest message,
|
||||||
NodeAddress peer,
|
NodeAddress peer,
|
||||||
@ -102,161 +92,27 @@ public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtoc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleInitMultisigRequest()");
|
super.handleInitMultisigRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(anyPhase(Trade.Phase.INIT)
|
|
||||||
.with(request)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
ProcessInitMultisigRequest.class,
|
|
||||||
SendSignContractRequestAfterMultisig.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
super.handleSignContractRequest(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNATURE_REQUESTED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNATURE_REQUESTED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
// process sign contract request after contract signature requested
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNATURE_REQUESTED) new Thread(() -> handleSignContractRequest(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse()");
|
super.handleSignContractResponse(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNED) new Thread(() -> handleSignContractResponse(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleDepositResponse()");
|
super.handleDepositResponse(response, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), response);
|
|
||||||
processModel.setTradeMessage(response);
|
|
||||||
expect(state(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST)
|
|
||||||
.with(response)
|
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessDepositResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, response);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, response, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handlePaymentAccountPayloadRequest()");
|
super.handlePaymentAccountPayloadRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
if (trade.getState() == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(state(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)
|
|
||||||
.with(request)
|
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessPaymentAccountPayloadRequest.class,
|
|
||||||
MakerRemovesOpenOffer.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
stopTimeout();
|
|
||||||
this.errorMessageHandler = null;
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -301,7 +157,7 @@ public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtoc
|
|||||||
.with(message)
|
.with(message)
|
||||||
.from(peer))
|
.from(peer))
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
MakerRemovesOpenOffer.class,
|
MaybeRemoveOpenOffer.class,
|
||||||
SellerAsMakerProcessDepositTxMessage.class,
|
SellerAsMakerProcessDepositTxMessage.class,
|
||||||
SellerAsMakerFinalizesDepositTx.class,
|
SellerAsMakerFinalizesDepositTx.class,
|
||||||
SellerCreatesDelayedPayoutTx.class,
|
SellerCreatesDelayedPayoutTx.class,
|
||||||
|
@ -23,20 +23,14 @@ import bisq.core.trade.SellerAsTakerTrade;
|
|||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.handlers.TradeResultHandler;
|
import bisq.core.trade.handlers.TradeResultHandler;
|
||||||
import bisq.core.trade.messages.PaymentSentMessage;
|
import bisq.core.trade.messages.PaymentSentMessage;
|
||||||
|
import bisq.core.trade.messages.SignContractRequest;
|
||||||
|
import bisq.core.trade.messages.SignContractResponse;
|
||||||
import bisq.core.trade.messages.DepositResponse;
|
import bisq.core.trade.messages.DepositResponse;
|
||||||
import bisq.core.trade.messages.InitMultisigRequest;
|
import bisq.core.trade.messages.InitMultisigRequest;
|
||||||
import bisq.core.trade.messages.InputsForDepositTxResponse;
|
import bisq.core.trade.messages.InputsForDepositTxResponse;
|
||||||
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
||||||
import bisq.core.trade.messages.SignContractRequest;
|
|
||||||
import bisq.core.trade.messages.SignContractResponse;
|
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.tasks.ApplyFilter;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessDepositResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessPaymentAccountPayloadRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
|
|
||||||
import bisq.core.trade.protocol.tasks.ProcessSignContractResponse;
|
|
||||||
import bisq.core.trade.protocol.tasks.SendSignContractRequestAfterMultisig;
|
|
||||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
import bisq.core.trade.protocol.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||||
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
|
||||||
@ -48,14 +42,12 @@ import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx;
|
|||||||
import bisq.core.trade.protocol.tasks.taker.TakerReservesTradeFunds;
|
import bisq.core.trade.protocol.tasks.taker.TakerReservesTradeFunds;
|
||||||
import bisq.core.trade.protocol.tasks.taker.TakerSendsInitTradeRequestToArbitrator;
|
import bisq.core.trade.protocol.tasks.taker.TakerSendsInitTradeRequestToArbitrator;
|
||||||
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
|
import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment;
|
||||||
import bisq.core.util.Validator;
|
|
||||||
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
import bisq.common.handlers.ResultHandler;
|
import bisq.common.handlers.ResultHandler;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -79,8 +71,6 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc
|
|||||||
// Take offer
|
// Take offer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO (woodser): these methods are duplicated with BuyerAsTakerProtocol due to single inheritance
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTakeOffer(TradeResultHandler tradeResultHandler,
|
public void onTakeOffer(TradeResultHandler tradeResultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
@ -112,163 +102,28 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleInitMultisigRequest()");
|
super.handleInitMultisigRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(anyPhase(Trade.Phase.INIT)
|
|
||||||
.with(request)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
ProcessInitMultisigRequest.class,
|
|
||||||
SendSignContractRequestAfterMultisig.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
super.handleSignContractRequest(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNATURE_REQUESTED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNATURE_REQUESTED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
// process sign contract request after contract signature requested
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNATURE_REQUESTED) new Thread(() -> handleSignContractRequest(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
super.handleSignContractResponse(message, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
if (trade.getState() == Trade.State.CONTRACT_SIGNED) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), message);
|
|
||||||
processModel.setTradeMessage(message);
|
|
||||||
expect(state(Trade.State.CONTRACT_SIGNED)
|
|
||||||
.with(message)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessSignContractResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, message);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, message, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.CONTRACT_SIGNED) new Thread(() -> handleSignContractResponse(message, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handleDepositResponse()");
|
super.handleDepositResponse(response, sender);
|
||||||
synchronized (trade) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), response);
|
|
||||||
processModel.setTradeMessage(response);
|
|
||||||
expect(state(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST)
|
|
||||||
.with(response)
|
|
||||||
.from(sender))
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessDepositResponse.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
startTimeout(TRADE_TIMEOUT);
|
|
||||||
handleTaskRunnerSuccess(sender, response);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, response, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
||||||
System.out.println(getClass().getCanonicalName() + ".handlePaymentAccountPayloadRequest() " + trade.getId());
|
super.handlePaymentAccountPayloadRequest(request, sender);
|
||||||
synchronized (trade) {
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
if (trade.getState() == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
|
|
||||||
latchTrade();
|
|
||||||
Validator.checkTradeId(processModel.getOfferId(), request);
|
|
||||||
processModel.setTradeMessage(request);
|
|
||||||
expect(state(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)
|
|
||||||
.with(request)
|
|
||||||
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
|
||||||
.setup(tasks(
|
|
||||||
// TODO (woodser): validate request
|
|
||||||
ProcessPaymentAccountPayloadRequest.class)
|
|
||||||
.using(new TradeTaskRunner(trade,
|
|
||||||
() -> {
|
|
||||||
stopTimeout();
|
|
||||||
this.errorMessageHandler = null;
|
|
||||||
tradeResultHandler.handleResult(trade); // trade is initialized
|
|
||||||
handleTaskRunnerSuccess(sender, request);
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
handleTaskRunnerFault(sender, request, errorMessage);
|
|
||||||
}))
|
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
|
||||||
awaitTradeLatch();
|
|
||||||
} else {
|
|
||||||
EasyBind.subscribe(trade.stateProperty(), state -> {
|
|
||||||
if (state == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Incoming message when buyer has clicked payment started button
|
// Incoming message when buyer has clicked payment started button
|
||||||
|
@ -138,8 +138,8 @@ public abstract class SellerProtocol extends DisputeProtocol {
|
|||||||
SellerSendsPaymentReceivedMessage.class)
|
SellerSendsPaymentReceivedMessage.class)
|
||||||
.using(new TradeTaskRunner(trade, () -> {
|
.using(new TradeTaskRunner(trade, () -> {
|
||||||
this.errorMessageHandler = null;
|
this.errorMessageHandler = null;
|
||||||
resultHandler.handleResult();
|
|
||||||
handleTaskRunnerSuccess(event);
|
handleTaskRunnerSuccess(event);
|
||||||
|
resultHandler.handleResult();
|
||||||
}, (errorMessage) -> {
|
}, (errorMessage) -> {
|
||||||
handleTaskRunnerFault(event, errorMessage);
|
handleTaskRunnerFault(event, errorMessage);
|
||||||
})))
|
})))
|
||||||
|
@ -23,12 +23,22 @@ import bisq.core.trade.TradeManager;
|
|||||||
import bisq.core.trade.TradeUtils;
|
import bisq.core.trade.TradeUtils;
|
||||||
import bisq.core.trade.handlers.TradeResultHandler;
|
import bisq.core.trade.handlers.TradeResultHandler;
|
||||||
import bisq.core.trade.messages.PaymentSentMessage;
|
import bisq.core.trade.messages.PaymentSentMessage;
|
||||||
|
import bisq.core.trade.messages.DepositResponse;
|
||||||
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
|
import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage;
|
||||||
import bisq.core.trade.messages.InitMultisigRequest;
|
import bisq.core.trade.messages.InitMultisigRequest;
|
||||||
|
import bisq.core.trade.messages.PaymentAccountPayloadRequest;
|
||||||
import bisq.core.trade.messages.SignContractRequest;
|
import bisq.core.trade.messages.SignContractRequest;
|
||||||
|
import bisq.core.trade.messages.SignContractResponse;
|
||||||
import bisq.core.trade.messages.TradeMessage;
|
import bisq.core.trade.messages.TradeMessage;
|
||||||
import bisq.core.trade.messages.UpdateMultisigRequest;
|
import bisq.core.trade.messages.UpdateMultisigRequest;
|
||||||
|
import bisq.core.trade.protocol.tasks.MaybeSendSignContractRequest;
|
||||||
|
import bisq.core.trade.protocol.tasks.ProcessDepositResponse;
|
||||||
|
import bisq.core.trade.protocol.tasks.ProcessInitMultisigRequest;
|
||||||
|
import bisq.core.trade.protocol.tasks.ProcessPaymentAccountPayloadRequest;
|
||||||
|
import bisq.core.trade.protocol.tasks.ProcessSignContractRequest;
|
||||||
|
import bisq.core.trade.protocol.tasks.ProcessSignContractResponse;
|
||||||
import bisq.core.trade.protocol.tasks.ProcessUpdateMultisigRequest;
|
import bisq.core.trade.protocol.tasks.ProcessUpdateMultisigRequest;
|
||||||
|
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
|
||||||
import bisq.core.util.Validator;
|
import bisq.core.util.Validator;
|
||||||
|
|
||||||
import bisq.network.p2p.AckMessage;
|
import bisq.network.p2p.AckMessage;
|
||||||
@ -54,7 +64,7 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -213,8 +223,162 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
protected abstract void onTradeMessage(TradeMessage message, NodeAddress peer);
|
protected abstract void onTradeMessage(TradeMessage message, NodeAddress peer);
|
||||||
public abstract void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress peer);
|
|
||||||
public abstract void handleSignContractRequest(SignContractRequest request, NodeAddress peer);
|
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
|
||||||
|
System.out.println(getClass().getCanonicalName() + ".handleInitMultisigRequest()");
|
||||||
|
synchronized (trade) {
|
||||||
|
latchTrade();
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), request);
|
||||||
|
processModel.setTradeMessage(request);
|
||||||
|
expect(anyPhase(Trade.Phase.INIT)
|
||||||
|
.with(request)
|
||||||
|
.from(sender))
|
||||||
|
.setup(tasks(
|
||||||
|
ProcessInitMultisigRequest.class,
|
||||||
|
MaybeSendSignContractRequest.class)
|
||||||
|
.using(new TradeTaskRunner(trade,
|
||||||
|
() -> {
|
||||||
|
startTimeout(TRADE_TIMEOUT);
|
||||||
|
handleTaskRunnerSuccess(sender, request);
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
handleTaskRunnerFault(sender, request, errorMessage);
|
||||||
|
}))
|
||||||
|
.withTimeout(TRADE_TIMEOUT))
|
||||||
|
.executeTasks(true);
|
||||||
|
awaitTradeLatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
|
||||||
|
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
||||||
|
synchronized (trade) {
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), message);
|
||||||
|
if (trade.getState() == Trade.State.MULTISIG_COMPLETED || trade.getState() == Trade.State.CONTRACT_SIGNATURE_REQUESTED) {
|
||||||
|
latchTrade();
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), message);
|
||||||
|
processModel.setTradeMessage(message);
|
||||||
|
expect(anyState(Trade.State.MULTISIG_COMPLETED, Trade.State.CONTRACT_SIGNATURE_REQUESTED)
|
||||||
|
.with(message)
|
||||||
|
.from(sender))
|
||||||
|
.setup(tasks(
|
||||||
|
// TODO (woodser): validate request
|
||||||
|
ProcessSignContractRequest.class)
|
||||||
|
.using(new TradeTaskRunner(trade,
|
||||||
|
() -> {
|
||||||
|
startTimeout(TRADE_TIMEOUT);
|
||||||
|
handleTaskRunnerSuccess(sender, message);
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
handleTaskRunnerFault(sender, message, errorMessage);
|
||||||
|
}))
|
||||||
|
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
||||||
|
.executeTasks(true);
|
||||||
|
awaitTradeLatch();
|
||||||
|
} else {
|
||||||
|
// process sign contract request after multisig created
|
||||||
|
EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||||
|
if (state == Trade.State.MULTISIG_COMPLETED) new Thread(() -> handleSignContractRequest(message, sender)).start(); // process notification without trade lock
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
|
||||||
|
System.out.println(getClass().getCanonicalName() + ".handleSignContractResponse() " + trade.getId());
|
||||||
|
synchronized (trade) {
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), message);
|
||||||
|
if (trade.getState() == Trade.State.CONTRACT_SIGNED) {
|
||||||
|
latchTrade();
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), message);
|
||||||
|
processModel.setTradeMessage(message);
|
||||||
|
expect(state(Trade.State.CONTRACT_SIGNED)
|
||||||
|
.with(message)
|
||||||
|
.from(sender))
|
||||||
|
.setup(tasks(
|
||||||
|
// TODO (woodser): validate request
|
||||||
|
ProcessSignContractResponse.class)
|
||||||
|
.using(new TradeTaskRunner(trade,
|
||||||
|
() -> {
|
||||||
|
startTimeout(TRADE_TIMEOUT);
|
||||||
|
handleTaskRunnerSuccess(sender, message);
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
handleTaskRunnerFault(sender, message, errorMessage);
|
||||||
|
}))
|
||||||
|
.withTimeout(TRADE_TIMEOUT)) // extend timeout
|
||||||
|
.executeTasks(true);
|
||||||
|
awaitTradeLatch();
|
||||||
|
} else {
|
||||||
|
// process sign contract response after contract signed
|
||||||
|
EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||||
|
if (state == Trade.State.CONTRACT_SIGNED) new Thread(() -> handleSignContractResponse(message, sender)).start(); // process notification without trade lock
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||||
|
System.out.println(getClass().getCanonicalName() + ".handleDepositResponse()");
|
||||||
|
synchronized (trade) {
|
||||||
|
latchTrade();
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), response);
|
||||||
|
processModel.setTradeMessage(response);
|
||||||
|
expect(state(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST)
|
||||||
|
.with(response)
|
||||||
|
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
||||||
|
.setup(tasks(
|
||||||
|
// TODO (woodser): validate request
|
||||||
|
ProcessDepositResponse.class)
|
||||||
|
.using(new TradeTaskRunner(trade,
|
||||||
|
() -> {
|
||||||
|
startTimeout(TRADE_TIMEOUT);
|
||||||
|
handleTaskRunnerSuccess(sender, response);
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
handleTaskRunnerFault(sender, response, errorMessage);
|
||||||
|
}))
|
||||||
|
.withTimeout(TRADE_TIMEOUT))
|
||||||
|
.executeTasks(true);
|
||||||
|
awaitTradeLatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handlePaymentAccountPayloadRequest(PaymentAccountPayloadRequest request, NodeAddress sender) {
|
||||||
|
System.out.println(getClass().getCanonicalName() + ".handlePaymentAccountPayloadRequest()");
|
||||||
|
synchronized (trade) {
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), request);
|
||||||
|
if (trade.getState() == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
|
||||||
|
latchTrade();
|
||||||
|
Validator.checkTradeId(processModel.getOfferId(), request);
|
||||||
|
processModel.setTradeMessage(request);
|
||||||
|
expect(state(Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG)
|
||||||
|
.with(request)
|
||||||
|
.from(sender)) // TODO (woodser): ensure this asserts sender == response.getSenderNodeAddress()
|
||||||
|
.setup(tasks(
|
||||||
|
// TODO (woodser): validate request
|
||||||
|
ProcessPaymentAccountPayloadRequest.class,
|
||||||
|
MaybeRemoveOpenOffer.class)
|
||||||
|
.using(new TradeTaskRunner(trade,
|
||||||
|
() -> {
|
||||||
|
stopTimeout();
|
||||||
|
this.errorMessageHandler = null;
|
||||||
|
handleTaskRunnerSuccess(sender, request);
|
||||||
|
if (tradeResultHandler != null) tradeResultHandler.handleResult(trade); // trade is initialized
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
handleTaskRunnerFault(sender, request, errorMessage);
|
||||||
|
}))
|
||||||
|
.withTimeout(TRADE_TIMEOUT))
|
||||||
|
.executeTasks(true);
|
||||||
|
awaitTradeLatch();
|
||||||
|
} else {
|
||||||
|
EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||||
|
if (state == Trade.State.MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) new Thread(() -> handlePaymentAccountPayloadRequest(request, sender)).start(); // process notification without trade lock
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO (woodser): update to use fluent for consistency
|
// TODO (woodser): update to use fluent for consistency
|
||||||
public void handleUpdateMultisigRequest(UpdateMultisigRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) {
|
public void handleUpdateMultisigRequest(UpdateMultisigRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) {
|
||||||
@ -237,7 +401,6 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
|||||||
awaitTradeLatch();
|
awaitTradeLatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// FluentProtocol
|
// FluentProtocol
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -20,6 +20,7 @@ package bisq.core.trade.protocol.tasks;
|
|||||||
import bisq.common.app.Version;
|
import bisq.common.app.Version;
|
||||||
import bisq.common.taskrunner.TaskRunner;
|
import bisq.common.taskrunner.TaskRunner;
|
||||||
import bisq.core.btc.model.XmrAddressEntry;
|
import bisq.core.btc.model.XmrAddressEntry;
|
||||||
|
import bisq.core.trade.ArbitratorTrade;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.Trade.State;
|
import bisq.core.trade.Trade.State;
|
||||||
import bisq.core.trade.messages.SignContractRequest;
|
import bisq.core.trade.messages.SignContractRequest;
|
||||||
@ -32,13 +33,13 @@ import monero.wallet.model.MoneroTxWallet;
|
|||||||
|
|
||||||
// TODO (woodser): separate classes for deposit tx creation and contract request, or combine into ProcessInitMultisigRequest
|
// TODO (woodser): separate classes for deposit tx creation and contract request, or combine into ProcessInitMultisigRequest
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SendSignContractRequestAfterMultisig extends TradeTask {
|
public class MaybeSendSignContractRequest extends TradeTask {
|
||||||
|
|
||||||
private boolean ack1 = false; // TODO (woodser) these represent onArrived(), not the ack
|
private boolean ack1 = false; // TODO (woodser) these represent onArrived(), not the ack
|
||||||
private boolean ack2 = false;
|
private boolean ack2 = false;
|
||||||
|
|
||||||
@SuppressWarnings({"unused"})
|
@SuppressWarnings({"unused"})
|
||||||
public SendSignContractRequestAfterMultisig(TaskRunner taskHandler, Trade trade) {
|
public MaybeSendSignContractRequest(TaskRunner taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,10 +48,16 @@ public class SendSignContractRequestAfterMultisig extends TradeTask {
|
|||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
// skip if multisig wallet not complete
|
// skip if arbitrator
|
||||||
if (!processModel.isMultisigSetupComplete()) {
|
if (trade instanceof ArbitratorTrade) {
|
||||||
complete();
|
complete();
|
||||||
return; // TODO: woodser: this does not ack original request?
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip if multisig wallet not complete
|
||||||
|
if (processModel.getMultisigAddress() == null) {
|
||||||
|
complete();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip if deposit tx already created
|
// skip if deposit tx already created
|
||||||
@ -71,7 +78,7 @@ public class SendSignContractRequestAfterMultisig extends TradeTask {
|
|||||||
// TODO (woodser): save frozen key images and unfreeze if trade fails before deposited to multisig
|
// TODO (woodser): save frozen key images and unfreeze if trade fails before deposited to multisig
|
||||||
|
|
||||||
// save process state
|
// save process state
|
||||||
processModel.setDepositTxXmr(depositTx);
|
processModel.setDepositTxXmr(depositTx); // TODO: trade.getSelf().setDepositTx()
|
||||||
trade.getSelf().setDepositTxHash(depositTx.getHash());
|
trade.getSelf().setDepositTxHash(depositTx.getHash());
|
||||||
trade.getSelf().setPayoutAddressString(trade.getXmrWalletService().getAddressEntry(processModel.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).get().getAddressString()); // TODO (woodser): allow custom payout address?
|
trade.getSelf().setPayoutAddressString(trade.getXmrWalletService().getAddressEntry(processModel.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).get().getAddressString()); // TODO (woodser): allow custom payout address?
|
||||||
|
|
@ -23,9 +23,7 @@ import bisq.core.trade.MakerTrade;
|
|||||||
import bisq.core.trade.TakerTrade;
|
import bisq.core.trade.TakerTrade;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.messages.InitMultisigRequest;
|
import bisq.core.trade.messages.InitMultisigRequest;
|
||||||
import bisq.core.trade.protocol.TradeListener;
|
|
||||||
import bisq.core.trade.protocol.TradingPeer;
|
import bisq.core.trade.protocol.TradingPeer;
|
||||||
import bisq.network.p2p.AckMessage;
|
|
||||||
import bisq.network.p2p.NodeAddress;
|
import bisq.network.p2p.NodeAddress;
|
||||||
import bisq.network.p2p.SendDirectMessageListener;
|
import bisq.network.p2p.SendDirectMessageListener;
|
||||||
|
|
||||||
@ -92,8 +90,9 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
|||||||
log.info("Preparing multisig wallet for trade {}", trade.getId());
|
log.info("Preparing multisig wallet for trade {}", trade.getId());
|
||||||
multisigWallet = xmrWalletService.createMultisigWallet(trade.getId());
|
multisigWallet = xmrWalletService.createMultisigWallet(trade.getId());
|
||||||
processModel.setPreparedMultisigHex(multisigWallet.prepareMultisig());
|
processModel.setPreparedMultisigHex(multisigWallet.prepareMultisig());
|
||||||
|
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_PREPARED);
|
||||||
updateParticipants = true;
|
updateParticipants = true;
|
||||||
} else if (!processModel.isMultisigSetupComplete()) {
|
} else if (processModel.getMultisigAddress() == null) {
|
||||||
multisigWallet = xmrWalletService.getMultisigWallet(trade.getId());
|
multisigWallet = xmrWalletService.getMultisigWallet(trade.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,15 +102,16 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
|||||||
log.info("Making multisig wallet for trade {}", trade.getId());
|
log.info("Making multisig wallet for trade {}", trade.getId());
|
||||||
MoneroMultisigInitResult result = multisigWallet.makeMultisig(Arrays.asList(peers[0].getPreparedMultisigHex(), peers[1].getPreparedMultisigHex()), 2, xmrWalletService.getWalletPassword()); // TODO (woodser): xmrWalletService.makeMultisig(tradeId, multisigHexes, threshold)?
|
MoneroMultisigInitResult result = multisigWallet.makeMultisig(Arrays.asList(peers[0].getPreparedMultisigHex(), peers[1].getPreparedMultisigHex()), 2, xmrWalletService.getWalletPassword()); // TODO (woodser): xmrWalletService.makeMultisig(tradeId, multisigHexes, threshold)?
|
||||||
processModel.setMadeMultisigHex(result.getMultisigHex());
|
processModel.setMadeMultisigHex(result.getMultisigHex());
|
||||||
|
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_MADE);
|
||||||
updateParticipants = true;
|
updateParticipants = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// exchange multisig keys if applicable
|
// exchange multisig keys if applicable
|
||||||
if (!processModel.isMultisigSetupComplete() && peers[0].getMadeMultisigHex() != null && peers[1].getMadeMultisigHex() != null) {
|
if (processModel.getMultisigAddress() == null && peers[0].getMadeMultisigHex() != null && peers[1].getMadeMultisigHex() != null) {
|
||||||
log.info("Exchanging multisig wallet keys for trade {}", trade.getId());
|
log.info("Exchanging multisig wallet keys for trade {}", trade.getId());
|
||||||
multisigWallet.exchangeMultisigKeys(Arrays.asList(peers[0].getMadeMultisigHex(), peers[1].getMadeMultisigHex()), xmrWalletService.getWalletPassword());
|
multisigWallet.exchangeMultisigKeys(Arrays.asList(peers[0].getMadeMultisigHex(), peers[1].getMadeMultisigHex()), xmrWalletService.getWalletPassword());
|
||||||
processModel.setMultisigSetupComplete(true); // TODO: (woodser): remove this field?
|
|
||||||
processModel.setMultisigAddress(multisigWallet.getPrimaryAddress());
|
processModel.setMultisigAddress(multisigWallet.getPrimaryAddress());
|
||||||
|
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED);
|
||||||
processModel.getProvider().getXmrWalletService().closeMultisigWallet(trade.getId()); // save and close multisig wallet once it's created
|
processModel.getProvider().getXmrWalletService().closeMultisigWallet(trade.getId()); // save and close multisig wallet once it's created
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package bisq.core.trade.protocol.tasks.maker;
|
package bisq.core.trade.protocol.tasks.maker;
|
||||||
|
|
||||||
|
import bisq.core.trade.MakerTrade;
|
||||||
import bisq.core.trade.Trade;
|
import bisq.core.trade.Trade;
|
||||||
import bisq.core.trade.protocol.tasks.TradeTask;
|
import bisq.core.trade.protocol.tasks.TradeTask;
|
||||||
|
|
||||||
@ -27,8 +28,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class MakerRemovesOpenOffer extends TradeTask {
|
public class MaybeRemoveOpenOffer extends TradeTask {
|
||||||
public MakerRemovesOpenOffer(TaskRunner<Trade> taskHandler, Trade trade) {
|
public MaybeRemoveOpenOffer(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
super(taskHandler, trade);
|
super(taskHandler, trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +38,9 @@ public class MakerRemovesOpenOffer extends TradeTask {
|
|||||||
try {
|
try {
|
||||||
runInterceptHook();
|
runInterceptHook();
|
||||||
|
|
||||||
|
if (trade instanceof MakerTrade) {
|
||||||
processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer()));
|
processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer()));
|
||||||
|
}
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
@ -128,8 +128,7 @@ class GrpcTradesService extends TradesImplBase {
|
|||||||
responseObserver.onCompleted();
|
responseObserver.onCompleted();
|
||||||
},
|
},
|
||||||
errorMessage -> {
|
errorMessage -> {
|
||||||
if (!errorMessageHandler.isErrorHandled())
|
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
|
||||||
});
|
});
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
cause.printStackTrace();
|
cause.printStackTrace();
|
||||||
|
@ -43,7 +43,7 @@ import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForD
|
|||||||
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs;
|
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs;
|
||||||
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage;
|
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage;
|
||||||
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx;
|
import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer;
|
import bisq.core.trade.protocol.tasks.maker.MaybeRemoveOpenOffer;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime;
|
import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime;
|
||||||
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
|
import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment;
|
||||||
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
|
import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx;
|
||||||
@ -157,7 +157,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
|||||||
BuyerAsMakerSendsInputsForDepositTxResponse.class,
|
BuyerAsMakerSendsInputsForDepositTxResponse.class,
|
||||||
|
|
||||||
BuyerProcessDelayedPayoutTxSignatureRequest.class,
|
BuyerProcessDelayedPayoutTxSignatureRequest.class,
|
||||||
MakerRemovesOpenOffer.class,
|
MaybeRemoveOpenOffer.class,
|
||||||
BuyerVerifiesPreparedDelayedPayoutTx.class,
|
BuyerVerifiesPreparedDelayedPayoutTx.class,
|
||||||
BuyerSignsDelayedPayoutTx.class,
|
BuyerSignsDelayedPayoutTx.class,
|
||||||
BuyerSendsDelayedPayoutTxSignatureResponse.class,
|
BuyerSendsDelayedPayoutTxSignatureResponse.class,
|
||||||
@ -215,7 +215,7 @@ public class DebugView extends InitializableView<GridPane, Void> {
|
|||||||
SellerAsMakerSendsInputsForDepositTxResponse.class,
|
SellerAsMakerSendsInputsForDepositTxResponse.class,
|
||||||
|
|
||||||
//SellerAsMakerProcessDepositTxMessage.class,
|
//SellerAsMakerProcessDepositTxMessage.class,
|
||||||
MakerRemovesOpenOffer.class,
|
MaybeRemoveOpenOffer.class,
|
||||||
SellerAsMakerFinalizesDepositTx.class,
|
SellerAsMakerFinalizesDepositTx.class,
|
||||||
SellerCreatesDelayedPayoutTx.class,
|
SellerCreatesDelayedPayoutTx.class,
|
||||||
SellerSendDelayedPayoutTxSignatureRequest.class,
|
SellerSendDelayedPayoutTxSignatureRequest.class,
|
||||||
|
@ -403,6 +403,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
|||||||
// #################### Phase PREPARATION
|
// #################### Phase PREPARATION
|
||||||
case PREPARATION:
|
case PREPARATION:
|
||||||
case CONTRACT_SIGNATURE_REQUESTED:
|
case CONTRACT_SIGNATURE_REQUESTED:
|
||||||
|
case CONTRACT_SIGNED:
|
||||||
sellerState.set(UNDEFINED);
|
sellerState.set(UNDEFINED);
|
||||||
buyerState.set(BuyerState.UNDEFINED);
|
buyerState.set(BuyerState.UNDEFINED);
|
||||||
break;
|
break;
|
||||||
|
@ -1624,43 +1624,46 @@ message Trade {
|
|||||||
enum State {
|
enum State {
|
||||||
PB_ERROR_STATE = 0;
|
PB_ERROR_STATE = 0;
|
||||||
PREPARATION = 1;
|
PREPARATION = 1;
|
||||||
CONTRACT_SIGNATURE_REQUESTED = 2;
|
MULTISIG_PREPARED = 2;
|
||||||
CONTRACT_SIGNED = 3;
|
MULTISIG_MADE = 3;
|
||||||
TAKER_PUBLISHED_TAKER_FEE_TX = 4;
|
MULTISIG_COMPLETED = 4;
|
||||||
MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST = 5;
|
CONTRACT_SIGNATURE_REQUESTED = 5;
|
||||||
MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST = 6;
|
CONTRACT_SIGNED = 6;
|
||||||
MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST = 7;
|
TAKER_PUBLISHED_TAKER_FEE_TX = 7;
|
||||||
MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST = 8;
|
MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST = 8;
|
||||||
TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST = 9;
|
MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST = 9;
|
||||||
ARBITRATOR_PUBLISHED_DEPOSIT_TX = 10;
|
MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST = 10;
|
||||||
TAKER_SAW_DEPOSIT_TX_IN_NETWORK = 11;
|
MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST = 11;
|
||||||
TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG = 12;
|
TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST = 12;
|
||||||
TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG = 13;
|
ARBITRATOR_PUBLISHED_DEPOSIT_TX = 13;
|
||||||
TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG = 14;
|
TAKER_SAW_DEPOSIT_TX_IN_NETWORK = 14;
|
||||||
TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG = 15;
|
TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG = 15;
|
||||||
MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG = 16;
|
TAKER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG = 16;
|
||||||
MAKER_SAW_DEPOSIT_TX_IN_NETWORK = 17;
|
TAKER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG = 17;
|
||||||
DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN = 18;
|
TAKER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG = 18;
|
||||||
BUYER_CONFIRMED_IN_UI_PAYMENT_SENT = 19;
|
MAKER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG = 19;
|
||||||
BUYER_SENT_PAYMENT_SENT_MSG = 20;
|
MAKER_SAW_DEPOSIT_TX_IN_NETWORK = 20;
|
||||||
BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG = 21;
|
DEPOSIT_UNLOCKED_IN_BLOCK_CHAIN = 21;
|
||||||
BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG = 22;
|
BUYER_CONFIRMED_IN_UI_PAYMENT_SENT = 22;
|
||||||
BUYER_SEND_FAILED_PAYMENT_SENT_MSG = 23;
|
BUYER_SENT_PAYMENT_SENT_MSG = 23;
|
||||||
SELLER_RECEIVED_PAYMENT_SENT_MSG = 24;
|
BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG = 24;
|
||||||
SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT = 25;
|
BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG = 25;
|
||||||
SELLER_SENT_PAYMENT_RECEIVED_MSG = 26;
|
BUYER_SEND_FAILED_PAYMENT_SENT_MSG = 26;
|
||||||
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG = 27;
|
SELLER_RECEIVED_PAYMENT_SENT_MSG = 27;
|
||||||
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG = 28;
|
SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT = 28;
|
||||||
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG = 29;
|
SELLER_SENT_PAYMENT_RECEIVED_MSG = 29;
|
||||||
SELLER_PUBLISHED_PAYOUT_TX = 30;
|
SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG = 30;
|
||||||
SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG = 31;
|
SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG = 31;
|
||||||
SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG = 32;
|
SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG = 32;
|
||||||
SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG = 33;
|
SELLER_PUBLISHED_PAYOUT_TX = 33;
|
||||||
SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG = 34;
|
SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG = 34;
|
||||||
BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG = 35;
|
SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG = 35;
|
||||||
BUYER_SAW_PAYOUT_TX_IN_NETWORK = 36;
|
SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG = 36;
|
||||||
BUYER_PUBLISHED_PAYOUT_TX = 37;
|
SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG = 37;
|
||||||
WITHDRAW_COMPLETED = 38;
|
BUYER_RECEIVED_PAYOUT_TX_PUBLISHED_MSG = 38;
|
||||||
|
BUYER_SAW_PAYOUT_TX_IN_NETWORK = 39;
|
||||||
|
BUYER_PUBLISHED_PAYOUT_TX = 40;
|
||||||
|
WITHDRAW_COMPLETED = 41;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Phase {
|
enum Phase {
|
||||||
@ -1789,7 +1792,6 @@ message ProcessModel {
|
|||||||
string prepared_multisig_hex = 1007;
|
string prepared_multisig_hex = 1007;
|
||||||
string made_multisig_hex = 1008;
|
string made_multisig_hex = 1008;
|
||||||
string multisig_address = 1009;
|
string multisig_address = 1009;
|
||||||
bool multisig_setup_complete = 1010; // TODO: remove this field
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message TradingPeer {
|
message TradingPeer {
|
||||||
|
Loading…
Reference in New Issue
Block a user