Add more checks for delayed payout tx

This commit is contained in:
chimp1984 2020-04-07 23:04:57 -05:00
parent 99f542bc4b
commit 8cf6d42309
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
5 changed files with 62 additions and 11 deletions

View file

@ -724,11 +724,29 @@ public class TradeWalletService {
return delayedPayoutTx;
}
public boolean verifiesDepositTxAndDelayedPayoutTx(@SuppressWarnings("unused") Transaction depositTx,
Transaction delayedPayoutTx) {
// todo add more checks
if (delayedPayoutTx.getLockTime() == 0) {
log.error("Time lock is not set");
public boolean verifiesDepositTxAndDelayedPayoutTx(Transaction depositTx,
Transaction delayedPayoutTx,
long lockTime) {
TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
if (delayedPayoutTx.getInputs().size() != 1) {
log.error("Number of inputs must be 1");
return false;
}
TransactionOutput connectedOutput = delayedPayoutTx.getInput(0).getConnectedOutput();
if (connectedOutput == null) {
log.error("connectedOutput must not be null");
return false;
}
if (!connectedOutput.equals(p2SHMultiSigOutput)) {
log.error("connectedOutput must be p2SHMultiSigOutput");
return false;
}
if (delayedPayoutTx.getLockTime() != lockTime) {
log.error("LockTime must match trades lockTime");
return false;
}
@ -1228,11 +1246,10 @@ public class TradeWalletService {
private boolean removeDust(Transaction transaction) {
List<TransactionOutput> originalTransactionOutputs = transaction.getOutputs();
List<TransactionOutput> keepTransactionOutputs = new ArrayList<>();
for (TransactionOutput transactionOutput: originalTransactionOutputs) {
for (TransactionOutput transactionOutput : originalTransactionOutputs) {
if (transactionOutput.getValue().isLessThan(Restrictions.getMinNonDustOutput())) {
log.info("your transaction would have contained a dust output of {}", transactionOutput.toString());
}
else {
} else {
keepTransactionOutputs.add(transactionOutput);
}
}

View file

@ -29,6 +29,7 @@ import org.bitcoinj.core.TransactionOutput;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
@ -71,6 +72,9 @@ public class DonationAddressValidation {
// In case the seller has deactivated the DAO the default address will be used.
String defaultDonationAddressString = Param.RECIPIENT_BTC_ADDRESS.getDefaultValue();
checkArgument(delayedPayoutTx.getOutputs().size() == 1,
"preparedDelayedPayoutTx must have 1 output");
TransactionOutput output = delayedPayoutTx.getOutput(0);
NetworkParameters params = btcWalletService.getParams();
Address address = output.getAddressFromP2PKHScript(params);

View file

@ -42,7 +42,9 @@ public class BuyerVerifiesFinalDelayedPayoutTx extends TradeTask {
Transaction depositTx = checkNotNull(trade.getDepositTx());
Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx());
if (processModel.getTradeWalletService().verifiesDepositTxAndDelayedPayoutTx(depositTx, delayedPayoutTx)) {
if (processModel.getTradeWalletService().verifiesDepositTxAndDelayedPayoutTx(depositTx,
delayedPayoutTx,
trade.getLockTime())) {
complete();
} else {
failed("DelayedPayoutTx is not spending depositTx correctly");

View file

@ -17,14 +17,22 @@
package bisq.core.trade.protocol.tasks.buyer;
import bisq.core.offer.Offer;
import bisq.core.trade.DonationAddressValidation;
import bisq.core.trade.Trade;
import bisq.core.trade.protocol.tasks.TradeTask;
import bisq.common.taskrunner.TaskRunner;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionInput;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class BuyerVerifiesPreparedDelayedPayoutTx extends TradeTask {
@SuppressWarnings({"unused"})
@ -37,9 +45,29 @@ public class BuyerVerifiesPreparedDelayedPayoutTx extends TradeTask {
try {
runInterceptHook();
DonationAddressValidation.validate(processModel.getPreparedDelayedPayoutTx(),
Transaction preparedDelayedPayoutTx = processModel.getPreparedDelayedPayoutTx();
// Check donation address
DonationAddressValidation.validate(preparedDelayedPayoutTx,
processModel.getDaoFacade(),
processModel.getBtcWalletService());
// Check amount
Offer offer = checkNotNull(trade.getOffer());
Coin msOutputAmount = offer.getBuyerSecurityDeposit()
.add(offer.getSellerSecurityDeposit())
.add(checkNotNull(trade.getTradeAmount()));
checkArgument(preparedDelayedPayoutTx.getOutput(0).getValue().equals(msOutputAmount),
"output value of deposit tx and delayed payout tx must match");
// Check lock time
checkArgument(preparedDelayedPayoutTx.getLockTime() == trade.getLockTime(),
"preparedDelayedPayoutTx lock time must match trade.getLockTime()");
// Check seq num
checkArgument(preparedDelayedPayoutTx.getInputs().stream().anyMatch(e -> e.getSequenceNumber() == TransactionInput.NO_SEQUENCE - 1),
"Sequence number must be 0xFFFFFFFE");
complete();
} catch (DonationAddressValidation.DonationAddressException e) {
failed("Sellers donation address is invalid." +

View file

@ -231,7 +231,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (DevEnv.isDevMode()) {
UserThread.runAfter(() -> {
amount.set("0.001");
price.set("75000"); // for CNY
price.set("0.0001"); // for BSQ
minAmount.set(amount.get());
onFocusOutPriceAsPercentageTextField(true, false);
applyMakerFee();