Search in sources :

Example 1 with PreparedDepositTxAndMakerInputs

use of bisq.core.btc.data.PreparedDepositTxAndMakerInputs in project bisq-core by bisq-network.

the class BuyerAsMakerCreatesAndSignsDepositTx method run.

@Override
protected void run() {
    try {
        runInterceptHook();
        checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
        BtcWalletService walletService = processModel.getBtcWalletService();
        String id = processModel.getOffer().getId();
        TradingPeer tradingPeer = processModel.getTradingPeer();
        final Offer offer = trade.getOffer();
        // params
        final boolean makerIsBuyer = true;
        final byte[] contractHash = Hash.getSha256Hash(trade.getContractAsJson());
        trade.setContractHash(contractHash);
        log.debug("\n\n------------------------------------------------------------\n" + "Contract as json\n" + trade.getContractAsJson() + "\n------------------------------------------------------------\n");
        final Coin makerInputAmount = offer.getBuyerSecurityDeposit();
        Optional<AddressEntry> addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
        checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present");
        AddressEntry makerMultiSigAddressEntry = addressEntryOptional.get();
        makerMultiSigAddressEntry.setCoinLockedInMultiSig(makerInputAmount);
        walletService.saveAddressEntryList();
        final Coin msOutputAmount = makerInputAmount.add(trade.getTxFee()).add(offer.getSellerSecurityDeposit()).add(trade.getTradeAmount());
        final List<RawTransactionInput> takerRawTransactionInputs = tradingPeer.getRawTransactionInputs();
        final long takerChangeOutputValue = tradingPeer.getChangeOutputValue();
        final String takerChangeAddressString = tradingPeer.getChangeOutputAddress();
        final Address makerAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
        final Address makerChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
        final byte[] buyerPubKey = processModel.getMyMultiSigPubKey();
        checkArgument(Arrays.equals(buyerPubKey, makerMultiSigAddressEntry.getPubKey()), "buyerPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
        final byte[] sellerPubKey = tradingPeer.getMultiSigPubKey();
        final byte[] arbitratorBtcPubKey = trade.getArbitratorBtcPubKey();
        PreparedDepositTxAndMakerInputs result = processModel.getTradeWalletService().makerCreatesAndSignsDepositTx(makerIsBuyer, contractHash, makerInputAmount, msOutputAmount, takerRawTransactionInputs, takerChangeOutputValue, takerChangeAddressString, makerAddress, makerChangeAddress, buyerPubKey, sellerPubKey, arbitratorBtcPubKey);
        processModel.setPreparedDepositTx(result.depositTransaction);
        processModel.setRawTransactionInputs(result.rawMakerInputs);
        complete();
    } catch (Throwable t) {
        failed(t);
    }
}
Also used : Address(org.bitcoinj.core.Address) AddressEntry(bisq.core.btc.AddressEntry) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) Coin(org.bitcoinj.core.Coin) TradingPeer(bisq.core.trade.protocol.TradingPeer) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) Offer(bisq.core.offer.Offer) PreparedDepositTxAndMakerInputs(bisq.core.btc.data.PreparedDepositTxAndMakerInputs)

Example 2 with PreparedDepositTxAndMakerInputs

use of bisq.core.btc.data.PreparedDepositTxAndMakerInputs in project bisq-core by bisq-network.

the class TradeWalletService method makerCreatesAndSignsDepositTx.

/**
 * The maker creates the deposit transaction using the takers input(s) and optional output and signs his input(s).
 *
 * @param makerIsBuyer              The flag indicating if we are in the maker as buyer role or the opposite.
 * @param contractHash              The hash of the contract to be added to the OP_RETURN output.
 * @param makerInputAmount          The input amount of the maker.
 * @param msOutputAmount            The output amount to our MS output.
 * @param takerRawTransactionInputs Raw data for the connected outputs for all inputs of the taker (normally 1 input)
 * @param takerChangeOutputValue    Optional taker change output value
 * @param takerChangeAddressString  Optional taker change address
 * @param makerAddress              The maker's address.
 * @param makerChangeAddress        The maker's change address.
 * @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 A data container holding the serialized transaction and the maker raw inputs
 * @throws SigningException
 * @throws TransactionVerificationException
 * @throws WalletException
 */
public PreparedDepositTxAndMakerInputs makerCreatesAndSignsDepositTx(boolean makerIsBuyer, byte[] contractHash, Coin makerInputAmount, Coin msOutputAmount, List<RawTransactionInput> takerRawTransactionInputs, long takerChangeOutputValue, @Nullable String takerChangeAddressString, Address makerAddress, Address makerChangeAddress, byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey) throws SigningException, TransactionVerificationException, WalletException, AddressFormatException {
    log.debug("makerCreatesAndSignsDepositTx called");
    log.debug("makerIsBuyer " + makerIsBuyer);
    log.debug("makerInputAmount " + makerInputAmount.toFriendlyString());
    log.debug("msOutputAmount " + msOutputAmount.toFriendlyString());
    log.debug("takerRawInputs " + takerRawTransactionInputs.toString());
    log.debug("takerChangeOutputValue " + takerChangeOutputValue);
    log.debug("takerChangeAddressString " + takerChangeAddressString);
    log.debug("makerAddress " + makerAddress);
    log.debug("makerChangeAddress " + makerChangeAddress);
    log.debug("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
    log.debug("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
    log.debug("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
    checkArgument(!takerRawTransactionInputs.isEmpty());
    // First we construct a dummy TX to get the inputs and outputs we want to use for the real deposit tx.
    // Similar to the way we did in the createTakerDepositTxInputs method.
    Transaction dummyTx = new Transaction(params);
    TransactionOutput dummyOutput = new TransactionOutput(params, dummyTx, makerInputAmount, new ECKey().toAddress(params));
    dummyTx.addOutput(dummyOutput);
    addAvailableInputsAndChangeOutputs(dummyTx, makerAddress, makerChangeAddress, Coin.ZERO);
    // Normally we have only 1 input but we support multiple inputs if the user has paid in with several transactions.
    List<TransactionInput> makerInputs = dummyTx.getInputs();
    TransactionOutput makerOutput = null;
    // We don't support more then 1 optional change output
    checkArgument(dummyTx.getOutputs().size() < 3, "dummyTx.getOutputs().size() >= 3");
    // Only save change outputs, the dummy output is ignored (that's why we start with index 1)
    if (dummyTx.getOutputs().size() > 1)
        makerOutput = dummyTx.getOutput(1);
    // Now we construct the real deposit tx
    Transaction preparedDepositTx = new Transaction(params);
    ArrayList<RawTransactionInput> makerRawTransactionInputs = new ArrayList<>();
    if (makerIsBuyer) {
        // Add buyer inputs
        for (TransactionInput input : makerInputs) {
            preparedDepositTx.addInput(input);
            makerRawTransactionInputs.add(getRawInputFromTransactionInput(input));
        }
        // the sellers input is not signed so we attach empty script bytes
        for (RawTransactionInput rawTransactionInput : takerRawTransactionInputs) preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[] {}, rawTransactionInput));
    } else {
        // the sellers input is not signed so we attach empty script bytes
        for (RawTransactionInput rawTransactionInput : takerRawTransactionInputs) preparedDepositTx.addInput(getTransactionInput(preparedDepositTx, new byte[] {}, rawTransactionInput));
        // Add seller inputs
        for (TransactionInput input : makerInputs) {
            preparedDepositTx.addInput(input);
            makerRawTransactionInputs.add(getRawInputFromTransactionInput(input));
        }
    }
    // Add MultiSig output
    Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
    // Tx fee for deposit tx will be paid by buyer.
    TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, preparedDepositTx, msOutputAmount, p2SHMultiSigOutputScript.getProgram());
    preparedDepositTx.addOutput(p2SHMultiSigOutput);
    // We add the hash ot OP_RETURN with a 0 amount output
    TransactionOutput contractHashOutput = new TransactionOutput(params, preparedDepositTx, Coin.ZERO, ScriptBuilder.createOpReturnScript(contractHash).getProgram());
    preparedDepositTx.addOutput(contractHashOutput);
    TransactionOutput takerTransactionOutput = null;
    if (takerChangeOutputValue > 0 && takerChangeAddressString != null)
        takerTransactionOutput = new TransactionOutput(params, preparedDepositTx, Coin.valueOf(takerChangeOutputValue), Address.fromBase58(params, takerChangeAddressString));
    if (makerIsBuyer) {
        // Add optional buyer outputs
        if (makerOutput != null)
            preparedDepositTx.addOutput(makerOutput);
        // Add optional seller outputs
        if (takerTransactionOutput != null)
            preparedDepositTx.addOutput(takerTransactionOutput);
    } else {
        // Add optional seller outputs
        if (takerTransactionOutput != null)
            preparedDepositTx.addOutput(takerTransactionOutput);
        // Add optional buyer outputs
        if (makerOutput != null)
            preparedDepositTx.addOutput(makerOutput);
    }
    // Sign inputs
    int start = makerIsBuyer ? 0 : takerRawTransactionInputs.size();
    int end = makerIsBuyer ? makerInputs.size() : preparedDepositTx.getInputs().size();
    for (int i = start; i < end; i++) {
        TransactionInput input = preparedDepositTx.getInput(i);
        signInput(preparedDepositTx, input, i);
        WalletService.checkScriptSig(preparedDepositTx, input, i);
    }
    WalletService.printTx("prepared depositTx", preparedDepositTx);
    WalletService.verifyTransaction(preparedDepositTx);
    return new PreparedDepositTxAndMakerInputs(makerRawTransactionInputs, preparedDepositTx.bitcoinSerialize());
}
Also used : Script(org.bitcoinj.script.Script) TransactionOutput(org.bitcoinj.core.TransactionOutput) Transaction(org.bitcoinj.core.Transaction) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) ArrayList(java.util.ArrayList) ECKey(org.bitcoinj.core.ECKey) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) TransactionInput(org.bitcoinj.core.TransactionInput) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) PreparedDepositTxAndMakerInputs(bisq.core.btc.data.PreparedDepositTxAndMakerInputs)

Example 3 with PreparedDepositTxAndMakerInputs

use of bisq.core.btc.data.PreparedDepositTxAndMakerInputs in project bisq-core by bisq-network.

the class SellerAsMakerCreatesAndSignsDepositTx method run.

@Override
protected void run() {
    try {
        runInterceptHook();
        checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null");
        BtcWalletService walletService = processModel.getBtcWalletService();
        String id = processModel.getOffer().getId();
        TradingPeer tradingPeer = processModel.getTradingPeer();
        final Offer offer = trade.getOffer();
        // params
        final boolean makerIsBuyer = false;
        final byte[] contractHash = Hash.getSha256Hash(trade.getContractAsJson());
        trade.setContractHash(contractHash);
        log.debug("\n\n------------------------------------------------------------\n" + "Contract as json\n" + trade.getContractAsJson() + "\n------------------------------------------------------------\n");
        final Coin makerInputAmount = offer.getSellerSecurityDeposit().add(trade.getTradeAmount());
        Optional<AddressEntry> addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG);
        checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present");
        AddressEntry makerMultiSigAddressEntry = addressEntryOptional.get();
        makerMultiSigAddressEntry.setCoinLockedInMultiSig(makerInputAmount);
        walletService.saveAddressEntryList();
        final Coin msOutputAmount = makerInputAmount.add(trade.getTxFee()).add(offer.getBuyerSecurityDeposit());
        final List<RawTransactionInput> takerRawTransactionInputs = tradingPeer.getRawTransactionInputs();
        final long takerChangeOutputValue = tradingPeer.getChangeOutputValue();
        final String takerChangeAddressString = tradingPeer.getChangeOutputAddress();
        final Address makerAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
        final Address makerChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
        final byte[] buyerPubKey = tradingPeer.getMultiSigPubKey();
        final byte[] sellerPubKey = processModel.getMyMultiSigPubKey();
        checkArgument(Arrays.equals(sellerPubKey, makerMultiSigAddressEntry.getPubKey()), "sellerPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
        final byte[] arbitratorBtcPubKey = trade.getArbitratorBtcPubKey();
        PreparedDepositTxAndMakerInputs result = processModel.getTradeWalletService().makerCreatesAndSignsDepositTx(makerIsBuyer, contractHash, makerInputAmount, msOutputAmount, takerRawTransactionInputs, takerChangeOutputValue, takerChangeAddressString, makerAddress, makerChangeAddress, buyerPubKey, sellerPubKey, arbitratorBtcPubKey);
        processModel.setPreparedDepositTx(result.depositTransaction);
        processModel.setRawTransactionInputs(result.rawMakerInputs);
        complete();
    } catch (Throwable t) {
        failed(t);
    }
}
Also used : Address(org.bitcoinj.core.Address) AddressEntry(bisq.core.btc.AddressEntry) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) Coin(org.bitcoinj.core.Coin) TradingPeer(bisq.core.trade.protocol.TradingPeer) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) Offer(bisq.core.offer.Offer) PreparedDepositTxAndMakerInputs(bisq.core.btc.data.PreparedDepositTxAndMakerInputs)

Aggregations

PreparedDepositTxAndMakerInputs (bisq.core.btc.data.PreparedDepositTxAndMakerInputs)3 RawTransactionInput (bisq.core.btc.data.RawTransactionInput)3 AddressEntry (bisq.core.btc.AddressEntry)2 BtcWalletService (bisq.core.btc.wallet.BtcWalletService)2 Offer (bisq.core.offer.Offer)2 TradingPeer (bisq.core.trade.protocol.TradingPeer)2 Address (org.bitcoinj.core.Address)2 Coin (org.bitcoinj.core.Coin)2 ArrayList (java.util.ArrayList)1 ECKey (org.bitcoinj.core.ECKey)1 Transaction (org.bitcoinj.core.Transaction)1 TransactionInput (org.bitcoinj.core.TransactionInput)1 TransactionOutPoint (org.bitcoinj.core.TransactionOutPoint)1 TransactionOutput (org.bitcoinj.core.TransactionOutput)1 Script (org.bitcoinj.script.Script)1