Fix faulty signature check in finalizeDelayedPayoutTx

Make sure to use the segwit version of Script.correctlySpends in
TradeWalletService.finalizeDelayedPayoutTx, which requires the input
value and witness to be passed explicitly (as the latter holds the
actual signature). This was causing BuyerFinalizesDelayedPayoutTx to
fail to do any kind of signature check.

Also refactor the method slightly and remove a redundant call to
WalletService.checkScriptSig (which does the same thing as
TransactionInput.verify) in the branch used by the seller.
This commit is contained in:
Steven Barclay 2020-11-14 22:50:03 +00:00
parent 69d1e16f5e
commit 3574204e7d
No known key found for this signature in database
GPG Key ID: 9FED6BF1176D500B
3 changed files with 32 additions and 21 deletions

View File

@ -746,13 +746,14 @@ public class TradeWalletService {
return mySignature.encodeToDER();
}
public Transaction finalizeDelayedPayoutTx(Transaction delayedPayoutTx,
byte[] buyerPubKey,
byte[] sellerPubKey,
byte[] buyerSignature,
byte[] sellerSignature,
boolean requireConnectedOutput)
throws AddressFormatException, TransactionVerificationException, WalletException, SignatureDecodeException {
public Transaction finalizeUnconnectedDelayedPayoutTx(Transaction delayedPayoutTx,
byte[] buyerPubKey,
byte[] sellerPubKey,
byte[] buyerSignature,
byte[] sellerSignature,
Coin inputValue)
throws AddressFormatException, TransactionVerificationException, SignatureDecodeException {
Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
ECKey.ECDSASignature buyerECDSASignature = ECKey.ECDSASignature.decodeFromDER(buyerSignature);
ECKey.ECDSASignature sellerECDSASignature = ECKey.ECDSASignature.decodeFromDER(sellerSignature);
@ -764,15 +765,25 @@ public class TradeWalletService {
input.setWitness(witness);
WalletService.printTx("finalizeDelayedPayoutTx", delayedPayoutTx);
WalletService.verifyTransaction(delayedPayoutTx);
if (requireConnectedOutput) {
WalletService.checkWalletConsistency(wallet);
WalletService.checkScriptSig(delayedPayoutTx, input, 0);
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
input.verify(input.getConnectedOutput());
} else {
Script scriptPubKey = get2of2MultiSigOutputScript(buyerPubKey, sellerPubKey, false);
input.getScriptSig().correctlySpends(delayedPayoutTx, 0, scriptPubKey, Script.ALL_VERIFY_FLAGS);
}
Script scriptPubKey = get2of2MultiSigOutputScript(buyerPubKey, sellerPubKey, false);
input.getScriptSig().correctlySpends(delayedPayoutTx, 0, witness, inputValue, scriptPubKey, Script.ALL_VERIFY_FLAGS);
return delayedPayoutTx;
}
public Transaction finalizeDelayedPayoutTx(Transaction delayedPayoutTx,
byte[] buyerPubKey,
byte[] sellerPubKey,
byte[] buyerSignature,
byte[] sellerSignature)
throws AddressFormatException, TransactionVerificationException, WalletException, SignatureDecodeException {
TransactionInput input = delayedPayoutTx.getInput(0);
finalizeUnconnectedDelayedPayoutTx(delayedPayoutTx, buyerPubKey, sellerPubKey, buyerSignature, sellerSignature, input.getValue());
WalletService.checkWalletConsistency(wallet);
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
input.verify(input.getConnectedOutput());
return delayedPayoutTx;
}

View File

@ -28,9 +28,10 @@ public class BuyerFinalizesDelayedPayoutTx extends TradeTask {
try {
runInterceptHook();
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx());
BtcWalletService btcWalletService = processModel.getBtcWalletService();
String id = processModel.getOffer().getId();
Transaction preparedDepositTx = btcWalletService.getTxFromSerializedTx(processModel.getPreparedDepositTx());
Transaction preparedDelayedPayoutTx = checkNotNull(processModel.getPreparedDelayedPayoutTx());
byte[] buyerMultiSigPubKey = processModel.getMyMultiSigPubKey();
checkArgument(Arrays.equals(buyerMultiSigPubKey,
@ -41,13 +42,13 @@ public class BuyerFinalizesDelayedPayoutTx extends TradeTask {
byte[] buyerSignature = processModel.getDelayedPayoutTxSignature();
byte[] sellerSignature = processModel.getTradingPeer().getDelayedPayoutTxSignature();
Transaction signedDelayedPayoutTx = processModel.getTradeWalletService().finalizeDelayedPayoutTx(
Transaction signedDelayedPayoutTx = processModel.getTradeWalletService().finalizeUnconnectedDelayedPayoutTx(
preparedDelayedPayoutTx,
buyerMultiSigPubKey,
sellerMultiSigPubKey,
buyerSignature,
sellerSignature,
false);
preparedDepositTx.getOutput(0).getValue());
trade.applyDelayedPayoutTxBytes(signedDelayedPayoutTx.bitcoinSerialize());
log.info("DelayedPayoutTxBytes = {}", Utilities.bytesAsHexString(trade.getDelayedPayoutTxBytes()));

View File

@ -63,8 +63,7 @@ public class SellerFinalizesDelayedPayoutTx extends TradeTask {
buyerMultiSigPubKey,
sellerMultiSigPubKey,
buyerSignature,
sellerSignature,
true);
sellerSignature);
trade.applyDelayedPayoutTx(signedDelayedPayoutTx);
log.info("DelayedPayoutTxBytes = {}", Utilities.bytesAsHexString(trade.getDelayedPayoutTxBytes()));