Java Code Examples for org.bitcoinj.core.Transaction#hashForSignature()

The following examples show how to use org.bitcoinj.core.Transaction#hashForSignature() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 6 votes vote down vote up
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);
    }
}
 
Example 2
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 6 votes vote down vote up
public byte[] signMediatedPayoutTx(Transaction depositTx,
                                   Coin buyerPayoutAmount,
                                   Coin sellerPayoutAmount,
                                   String buyerPayoutAddressString,
                                   String sellerPayoutAddressString,
                                   DeterministicKey myMultiSigKeyPair,
                                   byte[] buyerPubKey,
                                   byte[] sellerPubKey)
        throws AddressFormatException, TransactionVerificationException {
    Transaction preparedPayoutTx = createPayoutTx(depositTx, buyerPayoutAmount, sellerPayoutAmount, buyerPayoutAddressString, sellerPayoutAddressString);
    // MS redeemScript
    Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
    // MS output from prev. tx is index 0
    Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(myMultiSigKeyPair, "myMultiSigKeyPair must not be null");
    if (myMultiSigKeyPair.isEncrypted()) {
        checkNotNull(aesKey);
    }
    ECKey.ECDSASignature mySignature = myMultiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
    WalletService.printTx("prepared mediated payoutTx for sig creation", preparedPayoutTx);
    WalletService.verifyTransaction(preparedPayoutTx);
    return mySignature.encodeToDER();
}
 
Example 3
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * Seller signs payout transaction, buyer has not signed yet.
 *
 * @param depositTx                 deposit transaction
 * @param buyerPayoutAmount         payout amount for buyer
 * @param sellerPayoutAmount        payout amount for seller
 * @param buyerPayoutAddressString  address for buyer
 * @param sellerPayoutAddressString address for seller
 * @param multiSigKeyPair           DeterministicKey for MultiSig from seller
 * @param buyerPubKey               the public key of the buyer
 * @param sellerPubKey              the public key of the seller
 * @return DER encoded canonical signature
 * @throws AddressFormatException if the buyer or seller base58 address doesn't parse or its checksum is invalid
 * @throws TransactionVerificationException if there was an unexpected problem with the payout tx or its signature
 */
public byte[] buyerSignsPayoutTx(Transaction depositTx,
                                 Coin buyerPayoutAmount,
                                 Coin sellerPayoutAmount,
                                 String buyerPayoutAddressString,
                                 String sellerPayoutAddressString,
                                 DeterministicKey multiSigKeyPair,
                                 byte[] buyerPubKey,
                                 byte[] sellerPubKey)
        throws AddressFormatException, TransactionVerificationException {
    Transaction preparedPayoutTx = createPayoutTx(depositTx, buyerPayoutAmount, sellerPayoutAmount,
            buyerPayoutAddressString, sellerPayoutAddressString);
    // MS redeemScript
    Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
    // MS output from prev. tx is index 0
    Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(multiSigKeyPair, "multiSigKeyPair must not be null");
    if (multiSigKeyPair.isEncrypted()) {
        checkNotNull(aesKey);
    }
    ECKey.ECDSASignature buyerSignature = multiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
    WalletService.printTx("prepared payoutTx", preparedPayoutTx);
    WalletService.verifyTransaction(preparedPayoutTx);
    return buyerSignature.encodeToDER();
}
 
Example 4
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 6 votes vote down vote up
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);
    }
}
 
Example 5
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 6 votes vote down vote up
public byte[] signDelayedPayoutTx(Transaction delayedPayoutTx,
                                  DeterministicKey myMultiSigKeyPair,
                                  byte[] buyerPubKey,
                                  byte[] sellerPubKey)
        throws AddressFormatException, TransactionVerificationException {

    Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
    Sha256Hash sigHash = delayedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(myMultiSigKeyPair, "myMultiSigKeyPair must not be null");
    if (myMultiSigKeyPair.isEncrypted()) {
        checkNotNull(aesKey);
    }

    ECKey.ECDSASignature mySignature = myMultiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
    WalletService.printTx("delayedPayoutTx for sig creation", delayedPayoutTx);
    WalletService.verifyTransaction(delayedPayoutTx);
    return mySignature.encodeToDER();
}
 
Example 6
Source File: SWWallet.java    From GreenBits with GNU General Public License v3.0 6 votes vote down vote up
@Override
public List<byte[]> signTransaction(final Transaction tx, final PreparedTransaction ptx, final List<Output> prevOuts) {
    final List<TransactionInput> txInputs = tx.getInputs();
    final List<byte[]> sigs = new ArrayList<>(txInputs.size());

    for (int i = 0; i < txInputs.size(); ++i) {
        final Output prevOut = prevOuts.get(i);

        final Script script = new Script(Wally.hex_to_bytes(prevOut.script));
        final Sha256Hash hash;
        if (prevOut.scriptType.equals(GATx.P2SH_P2WSH_FORTIFIED_OUT))
            hash = tx.hashForSignatureWitness(i, script.getProgram(), Coin.valueOf(prevOut.value), Transaction.SigHash.ALL, false);
        else
            hash = tx.hashForSignature(i, script.getProgram(), Transaction.SigHash.ALL, false);

        final SWWallet key = getMyKey(prevOut.subAccount).derive(prevOut.branch).derive(prevOut.pointer);
        final ECKey eckey = ECKey.fromPrivate(key.mRootKey.getPrivKey());
        sigs.add(getTxSignature(eckey.sign(Sha256Hash.wrap(hash.getBytes()))));
    }
    return sigs;
}
 
Example 7
Source File: LNEstablishHandlerTest.java    From thundernetwork with GNU Affero General Public License v3.0 6 votes vote down vote up
@Test
public void shouldSendMessageD () {
    channel2.writeInbound(channel1.readOutbound());
    channel1.writeInbound(channel2.readOutbound());
    channel2.writeInbound(channel1.readOutbound());

    Channel channel = processor1.channel;

    //Should send keys, secretHash and amounts
    LNEstablishDMessage message = (LNEstablishDMessage) channel2.readOutbound();

    Transaction escape = channel.getEscapeTransactionServer();
    Transaction fastEscape = channel.getFastEscapeTransactionServer();

    Sha256Hash hashEscape = escape.hashForSignature(0, channel.getScriptAnchorOutputServer(), Transaction.SigHash.ALL, false);
    Sha256Hash hashFastEscape = fastEscape.hashForSignature(0, channel.getScriptAnchorOutputServer(), Transaction.SigHash.ALL, false);

    assertTrue(channel.getKeyClientA().verify(hashEscape, TransactionSignature.decodeFromBitcoin(message.signatureEscape, true)));
    assertTrue(channel.getKeyClientA().verify(hashFastEscape, TransactionSignature.decodeFromBitcoin(message.signatureFastEscape, true)));

    channel1.writeInbound(message);
    after();
}
 
Example 8
Source File: LNPaymentLogicImpl.java    From thundernetwork with GNU Affero General Public License v3.0 5 votes vote down vote up
private void parseCMessage (LNPaymentCMessage message) {
    paymentSignatures.clear();
    signature1 = TransactionSignature.decodeFromBitcoin(message.newCommitSignature1, true);
    signature2 = TransactionSignature.decodeFromBitcoin(message.newCommitSignature2, true);

    Transaction channelTransaction = getServerTransaction();

    Sha256Hash hash1 = channelTransaction.hashForSignature(0, channel.getScriptAnchorOutputServer(), Transaction.SigHash.ALL, false);
    Sha256Hash hash2 = channelTransaction.hashForSignature(1, channel.getScriptAnchorOutputClient(), Transaction.SigHash.ALL, false);

    if (!channel.keyClient.verify(hash1, signature1)) {
        throw new LNPaymentException("Signature1 is not correct..");
    }

    if (!channel.keyClient.verify(hash2, signature2)) {
        throw new LNPaymentException("Signature2 is not correct..");
    }

    List<PaymentData> allPayments = new ArrayList<>(statusTemp.remainingPayments);
    allPayments.addAll(statusTemp.newPayments);
    List<Transaction> paymentTransactions = getServerPaymentTransactions();

    if (allPayments.size() != message.newPaymentSignatures.size()) {
        throw new LNPaymentException("Size of payment signature list is incorrect");
    }

    for (int i = 0; i < allPayments.size(); ++i) {
        Transaction transaction = paymentTransactions.get(i);
        PaymentData payment = allPayments.get(i);
        TransactionSignature signature = TransactionSignature.decodeFromBitcoin(message.newPaymentSignatures.get(i), true);
        Script scriptPubKey = channelTransaction.getOutput(i + 2).getScriptPubKey();

        Sha256Hash hash = transaction.hashForSignature(0, scriptPubKey, Transaction.SigHash.ALL, false);
        if (!channel.keyClient.verify(hash, signature)) {
            throw new LNPaymentException("Payment Signature " + i + "  is not correct..");
        }
        paymentSignatures.add(signature);
    }

}
 
Example 9
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
 * Seller creates and signs payout transaction and adds signature of buyer to complete the transaction.
 *
 * @param depositTx                 deposit transaction
 * @param buyerSignature            DER encoded canonical signature of buyer
 * @param buyerPayoutAmount         payout amount for buyer
 * @param sellerPayoutAmount        payout amount for seller
 * @param buyerPayoutAddressString  address for buyer
 * @param sellerPayoutAddressString address for seller
 * @param multiSigKeyPair           seller's key pair for MultiSig
 * @param buyerPubKey               the public key of the buyer
 * @param sellerPubKey              the public key of the seller
 * @return the payout transaction
 * @throws AddressFormatException if the buyer or seller base58 address doesn't parse or its checksum is invalid
 * @throws TransactionVerificationException if there was an unexpected problem with the payout tx or its signatures
 * @throws WalletException if the seller's wallet is null or structurally inconsistent
 */
public Transaction sellerSignsAndFinalizesPayoutTx(Transaction depositTx,
                                                   byte[] buyerSignature,
                                                   Coin buyerPayoutAmount,
                                                   Coin sellerPayoutAmount,
                                                   String buyerPayoutAddressString,
                                                   String sellerPayoutAddressString,
                                                   DeterministicKey multiSigKeyPair,
                                                   byte[] buyerPubKey,
                                                   byte[] sellerPubKey)
        throws AddressFormatException, TransactionVerificationException, WalletException {
    Transaction payoutTx = createPayoutTx(depositTx, buyerPayoutAmount, sellerPayoutAmount, buyerPayoutAddressString, sellerPayoutAddressString);
    // MS redeemScript
    Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
    // MS output from prev. tx is index 0
    Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(multiSigKeyPair, "multiSigKeyPair must not be null");
    if (multiSigKeyPair.isEncrypted()) {
        checkNotNull(aesKey);
    }
    ECKey.ECDSASignature sellerSignature = multiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
    TransactionSignature buyerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(buyerSignature),
            Transaction.SigHash.ALL, false);
    TransactionSignature sellerTxSig = new TransactionSignature(sellerSignature, Transaction.SigHash.ALL, false);
    // Take care of order of signatures. Need to be reversed here. See comment below at getMultiSigRedeemScript (seller, buyer)
    Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig),
            redeemScript);
    TransactionInput input = payoutTx.getInput(0);
    input.setScriptSig(inputScript);
    WalletService.printTx("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;
}
 
Example 10
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * Seller signs payout transaction, buyer has not signed yet.
 *
 * @param depositTx                 Deposit transaction
 * @param buyerPayoutAmount         Payout amount for buyer
 * @param sellerPayoutAmount        Payout amount for seller
 * @param buyerPayoutAddressString  Address for buyer
 * @param sellerPayoutAddressString Address for seller
 * @param multiSigKeyPair           DeterministicKey for MultiSig from seller
 * @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 DER encoded canonical signature
 * @throws AddressFormatException
 * @throws TransactionVerificationException
 */
public byte[] buyerSignsPayoutTx(Transaction depositTx,
                                 Coin buyerPayoutAmount,
                                 Coin sellerPayoutAmount,
                                 String buyerPayoutAddressString,
                                 String sellerPayoutAddressString,
                                 DeterministicKey multiSigKeyPair,
                                 byte[] buyerPubKey,
                                 byte[] sellerPubKey,
                                 byte[] arbitratorPubKey)
        throws AddressFormatException, TransactionVerificationException {
    log.trace("sellerSignsPayoutTx called");
    log.trace("depositTx " + depositTx.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.info("buyerPubKey HEX=" + ECKey.fromPublicOnly(buyerPubKey).getPublicKeyAsHex());
    log.info("sellerPubKey HEX=" + ECKey.fromPublicOnly(sellerPubKey).getPublicKeyAsHex());
    log.info("arbitratorPubKey HEX=" + ECKey.fromPublicOnly(arbitratorPubKey).getPublicKeyAsHex());
    Transaction preparedPayoutTx = createPayoutTx(depositTx,
            buyerPayoutAmount,
            sellerPayoutAmount,
            buyerPayoutAddressString,
            sellerPayoutAddressString);
    // MS redeemScript
    Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
    // MS output from prev. tx is index 0
    Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(multiSigKeyPair, "multiSigKeyPair must not be null");
    if (multiSigKeyPair.isEncrypted())
        checkNotNull(aesKey);

    ECKey.ECDSASignature buyerSignature = multiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();

    WalletService.printTx("prepared payoutTx", preparedPayoutTx);

    WalletService.verifyTransaction(preparedPayoutTx);

    return buyerSignature.encodeToDER();
}
 
Example 11
Source File: AbstractScriptBuilderWithVar.java    From balzac with Apache License 2.0 4 votes vote down vote up
/**
 * Replace all the signatures placeholder with the actual signatures. Each
 * placeholder is already associated with the key and the modifiers.
 * 
 * @param tx         the transaction to be signed
 * @param inputIndex the index of the input that will contain this script
 * @param outScript  the redeemed output script
 * @return a <b>copy</b> of this builder
 * @throws KeyStoreException if an error occurs retrieving private keys
 */
@SuppressWarnings("unchecked")
public T setAllSignatures(ECKeyStore keystore, Transaction tx, int inputIndex, byte[] outScript, boolean isP2PKH)
    throws KeyStoreException {

    List<ScriptChunk> newChunks = new ArrayList<>();

    for (ScriptChunk chunk : getChunks()) {

        ScriptBuilderWithVar sb = new ScriptBuilderWithVar();
        if (isSignature(chunk)) {
            String mapKey = getMapKey(chunk);
            SignatureUtil sig = this.signatures.get(mapKey);

            // check if the private key is a variable
            String keyID = sig.keyID;
            if (keyID.startsWith(FREEVAR_PREFIX)) {
                // check that the variable is bound
                String varName = keyID.substring(FREEVAR_PREFIX.length());
                checkState(isBound(varName), "variable " + varName + " must be bound to retrieve the key");
                keyID = getValue(varName, String.class);
            }

            checkState(keystore != null, "keystore must be set to retrieve the private keys");
            checkState(keystore.containsKey(keyID), "key " + keyID + " not found on the specified keystore");

            PrivateKey privkey = keystore.getKey(keyID);
            ECKey key = ECKey.fromPrivate(privkey.getBytes());
            SigHash hashType = sig.hashType;
            boolean anyoneCanPay = sig.anyoneCanPay;

            // create the signature
            TransactionSignature txSig = tx.calculateSignature(inputIndex, key, outScript, hashType, anyoneCanPay);
            Sha256Hash hash = tx.hashForSignature(inputIndex, outScript, (byte) txSig.sighashFlags);
            boolean isValid = ECKey.verify(hash.getBytes(), txSig, privkey.toPublicKey().getBytes());
            checkState(isValid);
            checkState(txSig.isCanonical());
            sb.data(txSig.encodeToBitcoin());
            if (isP2PKH) {
                sb.data(privkey.toPublicKey().getBytes());
            }
        }
        else {
            sb.addChunk(chunk);
        }

        newChunks.addAll(sb.getChunks());
    }
    super.getChunks().clear();
    super.getChunks().addAll(newChunks);

    this.signatures.clear();
    return (T) this;
}
 
Example 12
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 4 votes vote down vote up
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,
                                                   TxBroadcaster.Callback 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;
}
 
Example 13
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * 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;
}
 
Example 14
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * That arbitrator signs the payout transaction
 *
 * @param depositTxSerialized Serialized deposit tx
 * @param buyerPayoutAmount   The payout amount of the buyer.
 * @param sellerPayoutAmount  The payout amount of the seller.
 * @param buyerAddressString  The address of the buyer.
 * @param sellerAddressString The address of the seller.
 * @param arbitratorKeyPair   The keypair of the arbitrator.
 * @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 DER encoded canonical signature of arbitrator
 * @throws AddressFormatException
 * @throws TransactionVerificationException
 */
public byte[] arbitratorSignsDisputedPayoutTx(byte[] depositTxSerialized,
                                              Coin buyerPayoutAmount,
                                              Coin sellerPayoutAmount,
                                              String buyerAddressString,
                                              String sellerAddressString,
                                              DeterministicKey arbitratorKeyPair,
                                              byte[] buyerPubKey,
                                              byte[] sellerPubKey,
                                              byte[] arbitratorPubKey)
        throws AddressFormatException, TransactionVerificationException {
    Transaction depositTx = new Transaction(params, depositTxSerialized);
    log.trace("signDisputedPayoutTx called");
    log.trace("depositTx " + depositTx.toString());
    log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
    log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
    log.trace("buyerAddressString " + buyerAddressString);
    log.trace("sellerAddressString " + sellerAddressString);
    log.trace("arbitratorKeyPair (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());

    // Our MS is index 0
    TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
    Transaction preparedPayoutTx = new Transaction(params);
    preparedPayoutTx.addInput(p2SHMultiSigOutput);
    if (buyerPayoutAmount.isGreaterThan(Coin.ZERO))
        preparedPayoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
    if (sellerPayoutAmount.isGreaterThan(Coin.ZERO))
        preparedPayoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));

    // take care of sorting!
    Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
    Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
    checkNotNull(arbitratorKeyPair, "arbitratorKeyPair must not be null");
    if (arbitratorKeyPair.isEncrypted())
        checkNotNull(aesKey);

    ECKey.ECDSASignature arbitratorSignature = arbitratorKeyPair.sign(sigHash, aesKey).toCanonicalised();

    WalletService.verifyTransaction(preparedPayoutTx);

    //WalletService.printTx("preparedPayoutTx", preparedPayoutTx);

    return arbitratorSignature.encodeToDER();
}
 
Example 15
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * 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 key pair 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 if the buyer or seller base58 address doesn't parse or its checksum is invalid
 * @throws TransactionVerificationException if there was an unexpected problem with the payout tx or its signature
 * @throws WalletException if the trade wallet is null or structurally inconsistent
 */
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);
    TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
    Transaction payoutTx = new Transaction(params);
    payoutTx.addInput(p2SHMultiSigOutput);
    if (buyerPayoutAmount.isPositive()) {
        payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
    }
    if (sellerPayoutAmount.isPositive()) {
        payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
    }

    // take care of sorting!
    Script redeemScript = get2of3MultiSigRedeemScript(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;
}
 
Example 16
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 4 votes vote down vote up
public void emergencySignAndPublishPayoutTxFrom2of2MultiSig(String depositTxHex,
                                                            Coin buyerPayoutAmount,
                                                            Coin sellerPayoutAmount,
                                                            Coin txFee,
                                                            String buyerAddressString,
                                                            String sellerAddressString,
                                                            String buyerPrivateKeyAsHex,
                                                            String sellerPrivateKeyAsHex,
                                                            String buyerPubKeyAsHex,
                                                            String sellerPubKeyAsHex,
                                                            TxBroadcaster.Callback callback)
        throws AddressFormatException, TransactionVerificationException, WalletException {
    byte[] buyerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(buyerPubKeyAsHex)).getPubKey();
    byte[] sellerPubKey = ECKey.fromPublicOnly(Utils.HEX.decode(sellerPubKeyAsHex)).getPubKey();

    Script p2SHMultiSigOutputScript = get2of2MultiSigOutputScript(buyerPubKey, sellerPubKey);

    Coin msOutput = buyerPayoutAmount.add(sellerPayoutAmount).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.isPositive()) {
        payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
    }
    if (sellerPayoutAmount.isPositive()) {
        payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
    }

    // take care of sorting!
    Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
    Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);

    ECKey buyerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(buyerPrivateKeyAsHex));
    checkNotNull(buyerPrivateKey, "key must not be null");
    ECKey.ECDSASignature buyerECDSASignature = buyerPrivateKey.sign(sigHash, aesKey).toCanonicalised();

    ECKey sellerPrivateKey = ECKey.fromPrivate(Utils.HEX.decode(sellerPrivateKeyAsHex));
    checkNotNull(sellerPrivateKey, "key must not be null");
    ECKey.ECDSASignature sellerECDSASignature = sellerPrivateKey.sign(sigHash, aesKey).toCanonicalised();

    TransactionSignature buyerTxSig = new TransactionSignature(buyerECDSASignature, Transaction.SigHash.ALL, false);
    TransactionSignature sellerTxSig = new TransactionSignature(sellerECDSASignature, Transaction.SigHash.ALL, false);
    Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig), redeemScript);

    TransactionInput input = payoutTx.getInput(0);
    input.setScriptSig(inputScript);
    WalletService.printTx("payoutTx", payoutTx);
    WalletService.verifyTransaction(payoutTx);
    WalletService.checkWalletConsistency(wallet);
    broadcastTx(payoutTx, callback, 20);
}
 
Example 17
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * Buyer creates and signs payout transaction and adds signature of seller to complete the transaction
 *
 * @param depositTx                 Deposit transaction
 * @param buyerSignature            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 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 sellerSignsAndFinalizesPayoutTx(Transaction depositTx,
                                                   byte[] buyerSignature,
                                                   Coin buyerPayoutAmount,
                                                   Coin sellerPayoutAmount,
                                                   String buyerPayoutAddressString,
                                                   String sellerPayoutAddressString,
                                                   DeterministicKey multiSigKeyPair,
                                                   byte[] buyerPubKey,
                                                   byte[] sellerPubKey,
                                                   byte[] arbitratorPubKey)
        throws AddressFormatException, TransactionVerificationException, WalletException {
    log.trace("buyerSignsAndFinalizesPayoutTx called");
    log.trace("depositTx " + depositTx.toString());
    log.trace("buyerSignature r " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).r.toString());
    log.trace("buyerSignature s " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).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.info("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
    log.info("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
    log.info("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());

    Transaction payoutTx = createPayoutTx(depositTx,
            buyerPayoutAmount,
            sellerPayoutAmount,
            buyerPayoutAddressString,
            sellerPayoutAddressString);
    // 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, "multiSigKeyPair must not be null");
    if (multiSigKeyPair.isEncrypted())
        checkNotNull(aesKey);


    ECKey.ECDSASignature sellerSignature = multiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();

    TransactionSignature buyerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(buyerSignature),
            Transaction.SigHash.ALL, false);
    TransactionSignature sellerTxSig = new TransactionSignature(sellerSignature, 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);

    WalletService.printTx("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;
}