use of org.bitcoinj.crypto.TransactionSignature in project bitsquare by bitsquare.
the class TradeWalletService method emergencySignAndPublishPayoutTx.
// Emergency payout tool. Used only in cased when the payput from the arbitrator does not work because some data
// in the trade/dispute are messed up.
public Transaction emergencySignAndPublishPayoutTx(String depositTxHex, Coin buyerPayoutAmount, Coin sellerPayoutAmount, Coin arbitratorPayoutAmount, String buyerAddressString, String sellerAddressString, String arbitratorAddressString, @Nullable String buyerPrivateKeyAsHex, @Nullable String sellerPrivateKeyAsHex, String arbitratorPrivateKeyAsHex, String buyerPubKeyAsHex, String sellerPubKeyAsHex, String arbitratorPubKeyAsHex, String P2SHMultiSigOutputScript, FutureCallback<Transaction> callback) throws AddressFormatException, TransactionVerificationException, WalletException {
log.info("signAndPublishPayoutTx called");
log.info("depositTxHex " + depositTxHex);
log.info("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
log.info("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
log.info("arbitratorPayoutAmount " + arbitratorPayoutAmount.toFriendlyString());
log.info("buyerAddressString " + buyerAddressString);
log.info("sellerAddressString " + sellerAddressString);
log.info("arbitratorAddressString " + arbitratorAddressString);
log.info("buyerPrivateKeyAsHex (not displayed for security reasons)");
log.info("sellerPrivateKeyAsHex (not displayed for security reasons)");
log.info("arbitratorPrivateKeyAsHex (not displayed for security reasons)");
log.info("buyerPubKeyAsHex " + buyerPubKeyAsHex);
log.info("sellerPubKeyAsHex " + sellerPubKeyAsHex);
log.info("arbitratorPubKeyAsHex " + arbitratorPubKeyAsHex);
log.info("P2SHMultiSigOutputScript " + P2SHMultiSigOutputScript);
checkNotNull((buyerPrivateKeyAsHex != null || sellerPrivateKeyAsHex != null), "either buyerPrivateKeyAsHex or sellerPrivateKeyAsHex must not be null");
byte[] buyerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(buyerPubKeyAsHex)).getPubKey();
byte[] sellerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(sellerPubKeyAsHex)).getPubKey();
final byte[] arbitratorPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(arbitratorPubKeyAsHex)).getPubKey();
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
if (!p2SHMultiSigOutputScript.toString().contains(P2SHMultiSigOutputScript))
log.error("p2SHMultiSigOutputScript does not match. Probably a pubkey is not correct.");
Coin msOutput = buyerPayoutAmount.add(sellerPayoutAmount).add(arbitratorPayoutAmount).add(FeePolicy.getFixedTxFeeForTrades());
TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, null, msOutput, p2SHMultiSigOutputScript.getProgram());
Transaction depositTx = new Transaction(params);
depositTx.addOutput(p2SHMultiSigOutput);
Transaction payoutTx = new Transaction(params);
Sha256Hash spendTxHash = Sha256Hash.wrap(depositTxHex);
payoutTx.addInput(new TransactionInput(params, depositTx, p2SHMultiSigOutputScript.getProgram(), new TransactionOutPoint(params, 0, spendTxHash), msOutput));
if (buyerPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(buyerPayoutAmount, new Address(params, buyerAddressString));
if (sellerPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(sellerPayoutAmount, new Address(params, sellerAddressString));
if (arbitratorPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(arbitratorPayoutAmount, new Address(params, arbitratorAddressString));
// take care of sorting!
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature tradersSignature;
if (buyerPrivateKeyAsHex != null && !buyerPrivateKeyAsHex.isEmpty()) {
final ECKey buyerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(buyerPrivateKeyAsHex));
checkNotNull(buyerPrivateKey, "buyerPrivateKey must not be null");
tradersSignature = buyerPrivateKey.sign(sigHash, aesKey).toCanonicalised();
} else {
checkNotNull(sellerPrivateKeyAsHex, "sellerPrivateKeyAsHex must not be null");
final ECKey sellerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(sellerPrivateKeyAsHex));
checkNotNull(sellerPrivateKey, "sellerPrivateKey must not be null");
tradersSignature = sellerPrivateKey.sign(sigHash, aesKey).toCanonicalised();
}
final ECKey key = ECKey.fromPrivate(Utils.HEX.decode(arbitratorPrivateKeyAsHex));
checkNotNull(key, "key must not be null");
ECKey.ECDSASignature arbitratorSignature = key.sign(sigHash, aesKey).toCanonicalised();
TransactionSignature tradersTxSig = new TransactionSignature(tradersSignature, Transaction.SigHash.ALL, false);
TransactionSignature arbitratorTxSig = new TransactionSignature(arbitratorSignature, Transaction.SigHash.ALL, false);
// Take care of order of signatures. See comment below at getMultiSigRedeemScript (sort order needed here: arbitrator, seller, buyer)
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(arbitratorTxSig, tradersTxSig), redeemScript);
TransactionInput input = payoutTx.getInput(0);
input.setScriptSig(inputScript);
printTxWithInputs("payoutTx", payoutTx);
verifyTransaction(payoutTx);
checkWalletConsistency();
if (walletAppKit != null) {
ListenableFuture<Transaction> future = walletAppKit.peerGroup().broadcastTransaction(payoutTx).future();
Futures.addCallback(future, callback);
}
return payoutTx;
}
use of org.bitcoinj.crypto.TransactionSignature in project bitsquare by bitsquare.
the class TradeWalletService method signInput.
private void signInput(Transaction transaction, TransactionInput input, int inputIndex) throws SigningException {
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
checkNotNull(wallet);
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
checkNotNull(sigKey, "signInput: sigKey must not be null. input.getOutpoint()=" + input.getOutpoint().toString());
if (sigKey.isEncrypted())
checkNotNull(aesKey);
Sha256Hash hash = transaction.hashForSignature(inputIndex, scriptPubKey, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature signature = sigKey.sign(hash, aesKey);
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);
if (scriptPubKey.isSentToRawPubKey()) {
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
} else if (scriptPubKey.isSentToAddress()) {
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
} else {
throw new SigningException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
}
}
use of org.bitcoinj.crypto.TransactionSignature in project bitsquare by bitsquare.
the class TradeWalletService method buyerSignsAndFinalizesPayoutTx.
/**
* Buyer creates and signs payout transaction and adds signature of seller to complete the transaction
*
* @param depositTx Deposit transaction
* @param sellerSignature DER encoded canonical signature of seller
* @param buyerPayoutAmount Payout amount for buyer
* @param sellerPayoutAmount Payout amount for seller
* @param buyerPayoutAddressString Address for buyer
* @param sellerPayoutAddressString Address for seller
* @param multiSigKeyPair Buyer's keypair for MultiSig
* @param lockTime Lock time
* @param buyerPubKey The public key of the buyer.
* @param sellerPubKey The public key of the seller.
* @param arbitratorPubKey The public key of the arbitrator.
* @return The payout transaction
* @throws AddressFormatException
* @throws TransactionVerificationException
* @throws WalletException
*/
public Transaction buyerSignsAndFinalizesPayoutTx(Transaction depositTx, byte[] sellerSignature, Coin buyerPayoutAmount, Coin sellerPayoutAmount, String buyerPayoutAddressString, String sellerPayoutAddressString, DeterministicKey multiSigKeyPair, long lockTime, byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey) throws AddressFormatException, TransactionVerificationException, WalletException {
log.trace("buyerSignsAndFinalizesPayoutTx called");
log.trace("depositTx " + depositTx.toString());
log.trace("sellerSignature r " + ECKey.ECDSASignature.decodeFromDER(sellerSignature).r.toString());
log.trace("sellerSignature s " + ECKey.ECDSASignature.decodeFromDER(sellerSignature).s.toString());
log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
log.trace("buyerPayoutAddressString " + buyerPayoutAddressString);
log.trace("sellerPayoutAddressString " + sellerPayoutAddressString);
log.trace("multiSigKeyPair (not displayed for security reasons)");
log.trace("lockTime " + lockTime);
log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
Transaction payoutTx = createPayoutTx(depositTx, buyerPayoutAmount, sellerPayoutAmount, buyerPayoutAddressString, sellerPayoutAddressString, lockTime);
// MS redeemScript
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
// MS output from prev. tx is index 0
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
checkNotNull(multiSigKeyPair, "multiSigAddressEntry.getKeyPair() must not be null");
if (multiSigKeyPair.isEncrypted())
checkNotNull(aesKey);
ECKey.ECDSASignature buyerSignature = multiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
TransactionSignature sellerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(sellerSignature), Transaction.SigHash.ALL, false);
TransactionSignature buyerTxSig = new TransactionSignature(buyerSignature, Transaction.SigHash.ALL, false);
// Take care of order of signatures. Need to be reversed here. See comment below at getMultiSigRedeemScript (arbitrator, seller, buyer)
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig), redeemScript);
TransactionInput input = payoutTx.getInput(0);
input.setScriptSig(inputScript);
printTxWithInputs("payoutTx", payoutTx);
verifyTransaction(payoutTx);
checkWalletConsistency();
checkScriptSig(payoutTx, input, 0);
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
input.verify(input.getConnectedOutput());
// We need to broadcast on our own when we reahced the block height. Both peers will do the broadcast.
return payoutTx;
}
use of org.bitcoinj.crypto.TransactionSignature in project bisq-core by bisq-network.
the class TradeWalletService method emergencySignAndPublishPayoutTx.
// Emergency payout tool. Used only in cased when the payput from the arbitrator does not work because some data
// in the trade/dispute are messed up.
// We keep here arbitratorPayoutAmount just in case (requires cooperation from peer anyway)
public Transaction emergencySignAndPublishPayoutTx(String depositTxHex, Coin buyerPayoutAmount, Coin sellerPayoutAmount, Coin arbitratorPayoutAmount, Coin txFee, String buyerAddressString, String sellerAddressString, String arbitratorAddressString, @Nullable String buyerPrivateKeyAsHex, @Nullable String sellerPrivateKeyAsHex, String arbitratorPrivateKeyAsHex, String buyerPubKeyAsHex, String sellerPubKeyAsHex, String arbitratorPubKeyAsHex, String P2SHMultiSigOutputScript, FutureCallback<Transaction> callback) throws AddressFormatException, TransactionVerificationException, WalletException {
log.info("signAndPublishPayoutTx called");
log.info("depositTxHex " + depositTxHex);
log.info("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
log.info("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
log.info("arbitratorPayoutAmount " + arbitratorPayoutAmount.toFriendlyString());
log.info("buyerAddressString " + buyerAddressString);
log.info("sellerAddressString " + sellerAddressString);
log.info("arbitratorAddressString " + arbitratorAddressString);
log.info("buyerPrivateKeyAsHex (not displayed for security reasons)");
log.info("sellerPrivateKeyAsHex (not displayed for security reasons)");
log.info("arbitratorPrivateKeyAsHex (not displayed for security reasons)");
log.info("buyerPubKeyAsHex " + buyerPubKeyAsHex);
log.info("sellerPubKeyAsHex " + sellerPubKeyAsHex);
log.info("arbitratorPubKeyAsHex " + arbitratorPubKeyAsHex);
log.info("P2SHMultiSigOutputScript " + P2SHMultiSigOutputScript);
checkNotNull((buyerPrivateKeyAsHex != null || sellerPrivateKeyAsHex != null), "either buyerPrivateKeyAsHex or sellerPrivateKeyAsHex must not be null");
byte[] buyerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(buyerPubKeyAsHex)).getPubKey();
byte[] sellerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(sellerPubKeyAsHex)).getPubKey();
final byte[] arbitratorPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(arbitratorPubKeyAsHex)).getPubKey();
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
Coin msOutput = buyerPayoutAmount.add(sellerPayoutAmount).add(arbitratorPayoutAmount).add(txFee);
TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, null, msOutput, p2SHMultiSigOutputScript.getProgram());
Transaction depositTx = new Transaction(params);
depositTx.addOutput(p2SHMultiSigOutput);
Transaction payoutTx = new Transaction(params);
Sha256Hash spendTxHash = Sha256Hash.wrap(depositTxHex);
payoutTx.addInput(new TransactionInput(params, depositTx, p2SHMultiSigOutputScript.getProgram(), new TransactionOutPoint(params, 0, spendTxHash), msOutput));
if (buyerPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
if (sellerPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
if (arbitratorPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(arbitratorPayoutAmount, Address.fromBase58(params, arbitratorAddressString));
// take care of sorting!
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature tradersSignature;
if (buyerPrivateKeyAsHex != null && !buyerPrivateKeyAsHex.isEmpty()) {
final ECKey buyerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(buyerPrivateKeyAsHex));
checkNotNull(buyerPrivateKey, "buyerPrivateKey must not be null");
tradersSignature = buyerPrivateKey.sign(sigHash, aesKey).toCanonicalised();
} else {
checkNotNull(sellerPrivateKeyAsHex, "sellerPrivateKeyAsHex must not be null");
final ECKey sellerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(sellerPrivateKeyAsHex));
checkNotNull(sellerPrivateKey, "sellerPrivateKey must not be null");
tradersSignature = sellerPrivateKey.sign(sigHash, aesKey).toCanonicalised();
}
final ECKey key = ECKey.fromPrivate(Utils.HEX.decode(arbitratorPrivateKeyAsHex));
checkNotNull(key, "key must not be null");
ECKey.ECDSASignature arbitratorSignature = key.sign(sigHash, aesKey).toCanonicalised();
TransactionSignature tradersTxSig = new TransactionSignature(tradersSignature, Transaction.SigHash.ALL, false);
TransactionSignature arbitratorTxSig = new TransactionSignature(arbitratorSignature, Transaction.SigHash.ALL, false);
// Take care of order of signatures. See comment below at getMultiSigRedeemScript (sort order needed here: arbitrator, seller, buyer)
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(arbitratorTxSig, tradersTxSig), redeemScript);
TransactionInput input = payoutTx.getInput(0);
input.setScriptSig(inputScript);
WalletService.printTx("payoutTx", payoutTx);
WalletService.verifyTransaction(payoutTx);
WalletService.checkWalletConsistency(wallet);
broadcastTx(payoutTx, callback, 20);
return payoutTx;
}
use of org.bitcoinj.crypto.TransactionSignature in project bisq-core by bisq-network.
the class TradeWalletService method traderSignAndFinalizeDisputedPayoutTx.
/**
* A trader who got the signed tx from the arbitrator finalizes the payout tx
*
* @param depositTxSerialized Serialized deposit tx
* @param arbitratorSignature DER encoded canonical signature of arbitrator
* @param buyerPayoutAmount Payout amount of the buyer
* @param sellerPayoutAmount Payout amount of the seller
* @param buyerAddressString The address of the buyer.
* @param sellerAddressString The address of the seller.
* @param tradersMultiSigKeyPair The keypair for the MultiSig of the trader who calls that method
* @param buyerPubKey The public key of the buyer.
* @param sellerPubKey The public key of the seller.
* @param arbitratorPubKey The public key of the arbitrator.
* @return The completed payout tx
* @throws AddressFormatException
* @throws TransactionVerificationException
* @throws WalletException
*/
public Transaction traderSignAndFinalizeDisputedPayoutTx(byte[] depositTxSerialized, byte[] arbitratorSignature, Coin buyerPayoutAmount, Coin sellerPayoutAmount, String buyerAddressString, String sellerAddressString, DeterministicKey tradersMultiSigKeyPair, byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey) throws AddressFormatException, TransactionVerificationException, WalletException {
Transaction depositTx = new Transaction(params, depositTxSerialized);
log.trace("signAndFinalizeDisputedPayoutTx called");
log.trace("depositTx " + depositTx);
log.trace("arbitratorSignature r " + ECKey.ECDSASignature.decodeFromDER(arbitratorSignature).r.toString());
log.trace("arbitratorSignature s " + ECKey.ECDSASignature.decodeFromDER(arbitratorSignature).s.toString());
log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
log.trace("buyerAddressString " + buyerAddressString);
log.trace("sellerAddressString " + sellerAddressString);
log.trace("tradersMultiSigKeyPair (not displayed for security reasons)");
log.info("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.info("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.info("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
Transaction payoutTx = new Transaction(params);
payoutTx.addInput(p2SHMultiSigOutput);
if (buyerPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
if (sellerPayoutAmount.isGreaterThan(Coin.ZERO))
payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
// take care of sorting!
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
checkNotNull(tradersMultiSigKeyPair, "tradersMultiSigKeyPair must not be null");
if (tradersMultiSigKeyPair.isEncrypted())
checkNotNull(aesKey);
ECKey.ECDSASignature tradersSignature = tradersMultiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
TransactionSignature tradersTxSig = new TransactionSignature(tradersSignature, Transaction.SigHash.ALL, false);
TransactionSignature arbitratorTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(arbitratorSignature), Transaction.SigHash.ALL, false);
// Take care of order of signatures. See comment below at getMultiSigRedeemScript (sort order needed here: arbitrator, seller, buyer)
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(arbitratorTxSig, tradersTxSig), redeemScript);
TransactionInput input = payoutTx.getInput(0);
input.setScriptSig(inputScript);
WalletService.printTx("disputed payoutTx", payoutTx);
WalletService.verifyTransaction(payoutTx);
WalletService.checkWalletConsistency(wallet);
WalletService.checkScriptSig(payoutTx, input, 0);
checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
input.verify(input.getConnectedOutput());
return payoutTx;
}
Aggregations