From 700c58071c707b5792f0ac5134ebcfce78bfb441 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Tue, 17 Mar 2015 20:43:59 +0100 Subject: [PATCH] Use P2SH Multisig instead of classic MS --- .../io/bitsquare/btc/TradeWalletService.java | 42 ++++++++++++------- .../trade/offerer/tasks/SignPayoutTx.java | 9 ++-- .../taker/tasks/SignAndPublishPayoutTx.java | 3 ++ 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java index 3b36c73748..bfc6268cfb 100644 --- a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java +++ b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java @@ -239,7 +239,7 @@ public class TradeWalletService { } // Add MultiSig output - Script multiSigOutputScript = getMultiSigOutputScript(offererPubKey, takerPubKey, arbitratorPubKey); + Script multiSigOutputScript = getP2SHMultiSigOutputScript(offererPubKey, takerPubKey, arbitratorPubKey); // Tx fee for deposit tx will be paid by offerer. TransactionOutput msOutput = new TransactionOutput(params, depositTx, msOutputAmount, multiSigOutputScript.getProgram()); depositTx.addOutput(msOutput); @@ -293,7 +293,7 @@ public class TradeWalletService { checkArgument(takerConnectedOutputsForAllInputs.size() > 0); // Check if takers Multisig script is identical to mine - Script multiSigOutputScript = getMultiSigOutputScript(offererPubKey, takerPubKey, arbitratorPubKey); + Script multiSigOutputScript = getP2SHMultiSigOutputScript(offererPubKey, takerPubKey, arbitratorPubKey); if (!takersDepositTx.getOutput(0).getScriptPubKey().equals(multiSigOutputScript)) throw new TransactionVerificationException("Takers multiSigOutputScript does not match to my multiSigOutputScript"); @@ -373,14 +373,15 @@ public class TradeWalletService { Coin offererPayoutAmount, Coin takerPayoutAmount, String takerAddressString, - AddressEntry addressEntry) + AddressEntry addressEntry, + byte[] offererPubKey, + byte[] takerPubKey, + byte[] arbitratorPubKey) throws AddressFormatException, TransactionVerificationException { Transaction payoutTx = createPayoutTx(depositTx, offererPayoutAmount, takerPayoutAmount, addressEntry.getAddressString(), takerAddressString); - - TransactionInput input = payoutTx.getInput(0); - TransactionOutput multiSigOutput = input.getConnectedOutput(); - Script multiSigScript = multiSigOutput.getScriptPubKey(); + // We need MS script not the P2SH + Script multiSigScript = getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey); Sha256Hash sigHash = payoutTx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false); ECKey.ECDSASignature offererSignature = addressEntry.getKeyPair().sign(sigHash); @@ -395,25 +396,27 @@ public class TradeWalletService { Coin takerPayoutAmount, String offererAddressString, AddressEntry addressEntry, + byte[] offererPubKey, + byte[] takerPubKey, + byte[] arbitratorPubKey, FutureCallback callback) throws AddressFormatException, TransactionVerificationException, WalletException { Transaction payoutTx = createPayoutTx(depositTx, offererPayoutAmount, takerPayoutAmount, offererAddressString, addressEntry.getAddressString()); - - TransactionInput input = payoutTx.getInput(0); - TransactionOutput multiSigOutput = input.getConnectedOutput(); - Script multiSigScript = multiSigOutput.getScriptPubKey(); + // We need MS script not the P2SH + Script multiSigScript = getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey); Sha256Hash sigHash = payoutTx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false); ECKey.ECDSASignature takerSignature = addressEntry.getKeyPair().sign(sigHash); TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false); TransactionSignature offererTxSig = new TransactionSignature(offererSignature, Transaction.SigHash.ALL, false); - Script inputScript = ScriptBuilder.createMultiSigInputScript(ImmutableList.of(offererTxSig, takerTxSig)); + Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(offererTxSig, takerTxSig), multiSigScript); + TransactionInput input = payoutTx.getInput(0); input.setScriptSig(inputScript); verifyTransaction(payoutTx); checkWalletConsistency(); checkScriptSig(payoutTx, input, 0); - input.verify(multiSigOutput); + input.verify(input.getConnectedOutput()); printTxWithInputs("payoutTx", payoutTx); ListenableFuture broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(payoutTx); @@ -424,13 +427,20 @@ public class TradeWalletService { // Private methods /////////////////////////////////////////////////////////////////////////////////////////// - private Script getMultiSigOutputScript(byte[] offererPubKey, byte[] takerPubKey, byte[] arbitratorPubKey) { + private Script getP2SHMultiSigOutputScript(byte[] offererPubKey, byte[] takerPubKey, byte[] arbitratorPubKey) { ECKey offererKey = ECKey.fromPublicOnly(offererPubKey); ECKey takerKey = ECKey.fromPublicOnly(takerPubKey); ECKey arbitratorKey = ECKey.fromPublicOnly(arbitratorPubKey); - List keys = ImmutableList.of(offererKey, takerKey, arbitratorKey); - return ScriptBuilder.createMultiSigOutputScript(2, keys); + return ScriptBuilder.createP2SHOutputScript(2, keys); + } + + private Script getMultiSigRedeemScript(byte[] offererPubKey, byte[] takerPubKey, byte[] arbitratorPubKey) { + ECKey offererKey = ECKey.fromPublicOnly(offererPubKey); + ECKey takerKey = ECKey.fromPublicOnly(takerPubKey); + ECKey arbitratorKey = ECKey.fromPublicOnly(arbitratorPubKey); + List keys = ImmutableList.of(offererKey, takerKey, arbitratorKey); + return ScriptBuilder.createRedeemScript(2, keys); } private Transaction createPayoutTx(Transaction depositTx, Coin offererPayoutAmount, Coin takerPayoutAmount, diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignPayoutTx.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignPayoutTx.java index a218d653d2..b1e2613719 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignPayoutTx.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/SignPayoutTx.java @@ -18,10 +18,10 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks; import io.bitsquare.btc.TradeWalletService; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel; import io.bitsquare.common.taskrunner.Task; import io.bitsquare.common.taskrunner.TaskRunner; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel; import org.bitcoinj.core.Coin; @@ -48,7 +48,10 @@ public class SignPayoutTx extends Task { offererPayoutAmount, takerPayoutAmount, model.getTakerPayoutAddress(), - model.getWalletService().getAddressEntry(trade.getId())); + model.getWalletService().getAddressEntry(trade.getId()), + model.getOffererPubKey(), + model.getTakerPubKey(), + model.getArbitratorPubKey()); model.setOffererPayoutTx(result.getPayoutTx()); model.setOffererSignature(result.getOffererSignature()); diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java index 43636f214f..40434f48cc 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java @@ -48,6 +48,9 @@ public class SignAndPublishPayoutTx extends Task { model.getTakerPayoutAmount(), model.getOffererPayoutAddress(), model.getAddressEntry(), + model.getOffererPubKey(), + model.getTakerPubKey(), + model.getArbitratorPubKey(), new FutureCallback() { @Override public void onSuccess(Transaction transaction) {