mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-26 08:25:23 -04:00
Use P2SH Multisig instead of classic MS
This commit is contained in:
parent
b10b6ff203
commit
700c58071c
3 changed files with 35 additions and 19 deletions
|
@ -239,7 +239,7 @@ public class TradeWalletService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add MultiSig output
|
// 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.
|
// Tx fee for deposit tx will be paid by offerer.
|
||||||
TransactionOutput msOutput = new TransactionOutput(params, depositTx, msOutputAmount, multiSigOutputScript.getProgram());
|
TransactionOutput msOutput = new TransactionOutput(params, depositTx, msOutputAmount, multiSigOutputScript.getProgram());
|
||||||
depositTx.addOutput(msOutput);
|
depositTx.addOutput(msOutput);
|
||||||
|
@ -293,7 +293,7 @@ public class TradeWalletService {
|
||||||
checkArgument(takerConnectedOutputsForAllInputs.size() > 0);
|
checkArgument(takerConnectedOutputsForAllInputs.size() > 0);
|
||||||
|
|
||||||
// Check if takers Multisig script is identical to mine
|
// 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))
|
if (!takersDepositTx.getOutput(0).getScriptPubKey().equals(multiSigOutputScript))
|
||||||
throw new TransactionVerificationException("Takers multiSigOutputScript does not match to my multiSigOutputScript");
|
throw new TransactionVerificationException("Takers multiSigOutputScript does not match to my multiSigOutputScript");
|
||||||
|
|
||||||
|
@ -373,14 +373,15 @@ public class TradeWalletService {
|
||||||
Coin offererPayoutAmount,
|
Coin offererPayoutAmount,
|
||||||
Coin takerPayoutAmount,
|
Coin takerPayoutAmount,
|
||||||
String takerAddressString,
|
String takerAddressString,
|
||||||
AddressEntry addressEntry)
|
AddressEntry addressEntry,
|
||||||
|
byte[] offererPubKey,
|
||||||
|
byte[] takerPubKey,
|
||||||
|
byte[] arbitratorPubKey)
|
||||||
throws AddressFormatException, TransactionVerificationException {
|
throws AddressFormatException, TransactionVerificationException {
|
||||||
|
|
||||||
Transaction payoutTx = createPayoutTx(depositTx, offererPayoutAmount, takerPayoutAmount, addressEntry.getAddressString(), takerAddressString);
|
Transaction payoutTx = createPayoutTx(depositTx, offererPayoutAmount, takerPayoutAmount, addressEntry.getAddressString(), takerAddressString);
|
||||||
|
// We need MS script not the P2SH
|
||||||
TransactionInput input = payoutTx.getInput(0);
|
Script multiSigScript = getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||||
TransactionOutput multiSigOutput = input.getConnectedOutput();
|
|
||||||
Script multiSigScript = multiSigOutput.getScriptPubKey();
|
|
||||||
Sha256Hash sigHash = payoutTx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
|
Sha256Hash sigHash = payoutTx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
|
||||||
ECKey.ECDSASignature offererSignature = addressEntry.getKeyPair().sign(sigHash);
|
ECKey.ECDSASignature offererSignature = addressEntry.getKeyPair().sign(sigHash);
|
||||||
|
|
||||||
|
@ -395,25 +396,27 @@ public class TradeWalletService {
|
||||||
Coin takerPayoutAmount,
|
Coin takerPayoutAmount,
|
||||||
String offererAddressString,
|
String offererAddressString,
|
||||||
AddressEntry addressEntry,
|
AddressEntry addressEntry,
|
||||||
|
byte[] offererPubKey,
|
||||||
|
byte[] takerPubKey,
|
||||||
|
byte[] arbitratorPubKey,
|
||||||
FutureCallback<Transaction> callback)
|
FutureCallback<Transaction> callback)
|
||||||
throws AddressFormatException, TransactionVerificationException, WalletException {
|
throws AddressFormatException, TransactionVerificationException, WalletException {
|
||||||
|
|
||||||
Transaction payoutTx = createPayoutTx(depositTx, offererPayoutAmount, takerPayoutAmount, offererAddressString, addressEntry.getAddressString());
|
Transaction payoutTx = createPayoutTx(depositTx, offererPayoutAmount, takerPayoutAmount, offererAddressString, addressEntry.getAddressString());
|
||||||
|
// We need MS script not the P2SH
|
||||||
TransactionInput input = payoutTx.getInput(0);
|
Script multiSigScript = getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||||
TransactionOutput multiSigOutput = input.getConnectedOutput();
|
|
||||||
Script multiSigScript = multiSigOutput.getScriptPubKey();
|
|
||||||
Sha256Hash sigHash = payoutTx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
|
Sha256Hash sigHash = payoutTx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
|
||||||
ECKey.ECDSASignature takerSignature = addressEntry.getKeyPair().sign(sigHash);
|
ECKey.ECDSASignature takerSignature = addressEntry.getKeyPair().sign(sigHash);
|
||||||
TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false);
|
TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false);
|
||||||
TransactionSignature offererTxSig = new TransactionSignature(offererSignature, 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);
|
input.setScriptSig(inputScript);
|
||||||
|
|
||||||
verifyTransaction(payoutTx);
|
verifyTransaction(payoutTx);
|
||||||
checkWalletConsistency();
|
checkWalletConsistency();
|
||||||
checkScriptSig(payoutTx, input, 0);
|
checkScriptSig(payoutTx, input, 0);
|
||||||
input.verify(multiSigOutput);
|
input.verify(input.getConnectedOutput());
|
||||||
|
|
||||||
printTxWithInputs("payoutTx", payoutTx);
|
printTxWithInputs("payoutTx", payoutTx);
|
||||||
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(payoutTx);
|
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(payoutTx);
|
||||||
|
@ -424,13 +427,20 @@ public class TradeWalletService {
|
||||||
// Private methods
|
// 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 offererKey = ECKey.fromPublicOnly(offererPubKey);
|
||||||
ECKey takerKey = ECKey.fromPublicOnly(takerPubKey);
|
ECKey takerKey = ECKey.fromPublicOnly(takerPubKey);
|
||||||
ECKey arbitratorKey = ECKey.fromPublicOnly(arbitratorPubKey);
|
ECKey arbitratorKey = ECKey.fromPublicOnly(arbitratorPubKey);
|
||||||
|
|
||||||
List<ECKey> keys = ImmutableList.of(offererKey, takerKey, arbitratorKey);
|
List<ECKey> 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<ECKey> keys = ImmutableList.of(offererKey, takerKey, arbitratorKey);
|
||||||
|
return ScriptBuilder.createRedeemScript(2, keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Transaction createPayoutTx(Transaction depositTx, Coin offererPayoutAmount, Coin takerPayoutAmount,
|
private Transaction createPayoutTx(Transaction depositTx, Coin offererPayoutAmount, Coin takerPayoutAmount,
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
package io.bitsquare.trade.protocol.trade.offerer.tasks;
|
package io.bitsquare.trade.protocol.trade.offerer.tasks;
|
||||||
|
|
||||||
import io.bitsquare.btc.TradeWalletService;
|
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.Task;
|
||||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
|
||||||
|
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
|
@ -48,7 +48,10 @@ public class SignPayoutTx extends Task<BuyerAsOffererModel> {
|
||||||
offererPayoutAmount,
|
offererPayoutAmount,
|
||||||
takerPayoutAmount,
|
takerPayoutAmount,
|
||||||
model.getTakerPayoutAddress(),
|
model.getTakerPayoutAddress(),
|
||||||
model.getWalletService().getAddressEntry(trade.getId()));
|
model.getWalletService().getAddressEntry(trade.getId()),
|
||||||
|
model.getOffererPubKey(),
|
||||||
|
model.getTakerPubKey(),
|
||||||
|
model.getArbitratorPubKey());
|
||||||
|
|
||||||
model.setOffererPayoutTx(result.getPayoutTx());
|
model.setOffererPayoutTx(result.getPayoutTx());
|
||||||
model.setOffererSignature(result.getOffererSignature());
|
model.setOffererSignature(result.getOffererSignature());
|
||||||
|
|
|
@ -48,6 +48,9 @@ public class SignAndPublishPayoutTx extends Task<SellerAsTakerModel> {
|
||||||
model.getTakerPayoutAmount(),
|
model.getTakerPayoutAmount(),
|
||||||
model.getOffererPayoutAddress(),
|
model.getOffererPayoutAddress(),
|
||||||
model.getAddressEntry(),
|
model.getAddressEntry(),
|
||||||
|
model.getOffererPubKey(),
|
||||||
|
model.getTakerPubKey(),
|
||||||
|
model.getArbitratorPubKey(),
|
||||||
new FutureCallback<Transaction>() {
|
new FutureCallback<Transaction>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Transaction transaction) {
|
public void onSuccess(Transaction transaction) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue