refactoring trade protocol

This commit is contained in:
Manfred Karrer 2014-07-05 01:00:35 +02:00
parent 5da272bdbf
commit cb4ca6b2a7
7 changed files with 184 additions and 733 deletions

View File

@ -7,6 +7,7 @@ import com.google.inject.Inject;
import io.bitsquare.btc.BlockChainFacade;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.crypto.CryptoFacade;
import io.bitsquare.gui.popups.Popups;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.TradeMessage;
import io.bitsquare.msg.listeners.TakeOfferRequestListener;
@ -233,6 +234,32 @@ public class Trading
log.debug("trading onPayoutTxPublishedMessage");
}
@Override
public void onFault(Throwable throwable, OffererAsBuyerProtocol.State state)
{
log.error("Error while executing trade process at state: " + state + " / " + throwable);
Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable);
}
@Override
public void onWaitingForPeerResponse(OffererAsBuyerProtocol.State state)
{
log.debug("Waiting for peers response at state " + state);
}
@Override
public void onCompleted(OffererAsBuyerProtocol.State state)
{
log.debug("Trade protocol completed at state " + state);
}
@Override
public void onWaitingForUserInteraction(OffererAsBuyerProtocol.State state)
{
log.debug("Waiting for UI activity at state " + state);
}
@Override
public void onDepositTxConfirmedInBlockchain()
{

View File

@ -14,4 +14,12 @@ public interface OffererAsBuyerProtocolListener
void onDepositTxConfirmedUpdate(TransactionConfidence confidence);
void onPayoutTxPublished(String payoutTxID);
void onFault(Throwable throwable, OffererAsBuyerProtocol.State state);
void onWaitingForPeerResponse(OffererAsBuyerProtocol.State state);
void onCompleted(OffererAsBuyerProtocol.State state);
void onWaitingForUserInteraction(OffererAsBuyerProtocol.State state);
}

View File

@ -20,8 +20,15 @@ import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static io.bitsquare.util.Validator.*;
import static io.bitsquare.util.Validator.nonEmptyStringOf;
import static io.bitsquare.util.Validator.nonNegativeLongOf;
/**
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing from the peer.
* That class handles the role of the taker as the Bitcoin seller.
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
* Any data from incoming messages as well data used to send to the peer need to be validated before further processing.
*/
public class TakerAsSellerProtocol
{
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class);
@ -92,7 +99,7 @@ public class TakerAsSellerProtocol
public void start()
{
String messagePubKeyAsHex = validString(offer.getMessagePubKeyAsHex());
String messagePubKeyAsHex = nonEmptyStringOf(offer.getMessagePubKeyAsHex());
GetPeerAddress.run(this::onResultGetPeerAddress, this::onFault, messageFacade, messagePubKeyAsHex);
state = State.GetPeerAddress;
@ -105,7 +112,7 @@ public class TakerAsSellerProtocol
public void onResultGetPeerAddress(PeerAddress peerAddress)
{
this.peerAddress = validPeerAddress(peerAddress);
this.peerAddress = checkNotNull(peerAddress);
RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, this.peerAddress, messageFacade, tradeId);
state = State.RequestTakeOffer;
@ -143,7 +150,7 @@ public class TakerAsSellerProtocol
public void onResultPayTakeOfferFee(Transaction transaction)
{
checkNotNull(transaction);
String transactionId = validString(transaction.getHashAsString());
String transactionId = nonEmptyStringOf(transaction.getHashAsString());
trade.setTakeOfferFeeTxID(transactionId);
@ -178,11 +185,11 @@ public class TakerAsSellerProtocol
checkState(state == State.SendTakeOfferFeePayedTxId);
peersAccountId = validString(message.getAccountID());
peersAccountId = nonEmptyStringOf(message.getAccountID());
peersBankAccount = checkNotNull(message.getBankAccount());
offererPubKey = validString(message.getOffererPubKey());
preparedOffererDepositTxAsHex = validString(message.getPreparedOffererDepositTxAsHex());
offererTxOutIndex = validNonNegativeLong(message.getOffererTxOutIndex());
offererPubKey = nonEmptyStringOf(message.getOffererPubKey());
preparedOffererDepositTxAsHex = nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex());
offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex());
VerifyOffererAccount.run(this::onResultVerifyOffererAccount,
this::onFault,

View File

@ -1,9 +1,9 @@
package io.bitsquare.trade.protocol.tasks.offerer;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Utils;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage;
import io.bitsquare.trade.protocol.tasks.FaultHandler;
import io.bitsquare.trade.protocol.tasks.ResultHandler;
@ -15,9 +15,9 @@ public class SendDepositTxIdToTaker
{
private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class);
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade trade)
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, String tradeId, Transaction depositTransaction)
{
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(trade.getId(), Utils.bytesToHexString(trade.getDepositTransaction().bitcoinSerialize()));
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(tradeId, Utils.bytesToHexString(depositTransaction.bitcoinSerialize()));
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
{
@Override

View File

@ -1,11 +1,9 @@
package io.bitsquare.trade.protocol.tasks.offerer;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Transaction;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage;
import io.bitsquare.trade.protocol.tasks.FaultHandler;
import io.bitsquare.trade.protocol.tasks.ResultHandler;
@ -24,34 +22,30 @@ public class SendSignedPayoutTx
PeerAddress peerAddress,
MessageFacade messageFacade,
WalletFacade walletFacade,
Trade trade,
String takerPayoutAddress)
String tradeId,
String takerPayoutAddress,
String offererPayoutAddress,
String depositTransactionId,
BigInteger collateral,
BigInteger tradeAmount)
{
try
{
Transaction depositTransaction = trade.getDepositTransaction();
BigInteger collateral = trade.getCollateralAmount();
BigInteger offererPaybackAmount = trade.getTradeAmount().add(collateral);
BigInteger offererPaybackAmount = tradeAmount.add(collateral);
BigInteger takerPaybackAmount = collateral;
log.trace("offererPaybackAmount " + offererPaybackAmount);
log.trace("takerPaybackAmount " + takerPaybackAmount);
log.trace("depositTransaction.getHashAsString() " + depositTransaction.getHashAsString());
log.trace("takerPayoutAddress " + takerPayoutAddress);
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransaction.getHashAsString(),
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransactionId,
offererPaybackAmount,
takerPaybackAmount,
takerPayoutAddress,
trade.getId());
tradeId);
ECKey.ECDSASignature offererSignature = result.getKey();
String offererSignatureR = offererSignature.r.toString();
String offererSignatureS = offererSignature.s.toString();
String depositTxAsHex = result.getValue();
String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString();
BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(trade.getId(),
BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(tradeId,
depositTxAsHex,
offererSignatureR,
offererSignatureS,
@ -59,13 +53,6 @@ public class SendSignedPayoutTx
takerPaybackAmount,
offererPayoutAddress);
log.trace("depositTxAsHex " + depositTxAsHex);
log.trace("offererSignatureR " + offererSignatureR);
log.trace("offererSignatureS " + offererSignatureS);
log.trace("offererPaybackAmount " + offererPaybackAmount);
log.trace("takerPaybackAmount " + takerPaybackAmount);
log.trace("offererPayoutAddress " + offererPayoutAddress);
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
{
@Override

View File

@ -1,6 +1,6 @@
package io.bitsquare.util;
import net.tomp2p.peers.PeerAddress;
import java.math.BigInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -11,24 +11,31 @@ public class Validator
{
private static final Logger log = LoggerFactory.getLogger(Validator.class);
public static String validString(String value)
public static String nonEmptyStringOf(String value)
{
checkNotNull(value);
checkArgument(value.length() > 0);
return value;
}
public static long validNonNegativeLong(long value)
public static long nonNegativeLongOf(long value)
{
checkArgument(value >= 0);
return value;
}
public static PeerAddress validPeerAddress(PeerAddress value)
public static BigInteger nonZeroBigIntegerOf(BigInteger value)
{
checkNotNull(value);
checkArgument(value.compareTo(BigInteger.ZERO) != 0);
return value;
}
public static BigInteger nonNegativeBigIntegerOf(BigInteger value)
{
checkNotNull(value);
checkArgument(value.compareTo(BigInteger.ZERO) >= 0);
return value;
}
}