Search in sources :

Example 1 with InputsAndChangeOutput

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

the class SellerAsTakerCreatesDepositTxInputs method run.

@Override
protected void run() {
    try {
        runInterceptHook();
        if (trade.getTradeAmount() != null) {
            Coin txFee = trade.getTxFee();
            Coin takerInputAmount = trade.getOffer().getSellerSecurityDeposit().add(txFee).add(txFee).add(trade.getTradeAmount());
            BtcWalletService walletService = processModel.getBtcWalletService();
            Address takersAddress = walletService.getOrCreateAddressEntry(processModel.getOffer().getId(), AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
            Address takersChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
            InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, txFee, takersAddress, takersChangeAddress);
            processModel.setRawTransactionInputs(result.rawTransactionInputs);
            processModel.setChangeOutputValue(result.changeOutputValue);
            processModel.setChangeOutputAddress(result.changeOutputAddress);
            complete();
        } else {
            failed("trade.getTradeAmount() = null");
        }
    } catch (Throwable t) {
        failed(t);
    }
}
Also used : Coin(org.bitcoinj.core.Coin) Address(org.bitcoinj.core.Address) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) InputsAndChangeOutput(bisq.core.btc.data.InputsAndChangeOutput)

Example 2 with InputsAndChangeOutput

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

the class BuyerAsTakerCreatesDepositTxInputs method run.

@Override
protected void run() {
    try {
        runInterceptHook();
        // In case we pay the taker fee in bsq we reduce tx fee by that as the burned bsq satoshis goes to miners.
        Coin bsqTakerFee = trade.isCurrencyForTakerFeeBtc() ? Coin.ZERO : trade.getTakerFee();
        Coin txFee = trade.getTxFee();
        Coin takerInputAmount = trade.getOffer().getBuyerSecurityDeposit().add(txFee).add(txFee).subtract(bsqTakerFee);
        BtcWalletService walletService = processModel.getBtcWalletService();
        Address takersAddress = walletService.getOrCreateAddressEntry(processModel.getOffer().getId(), AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
        Address takersChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
        InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, txFee.subtract(bsqTakerFee), takersAddress, takersChangeAddress);
        processModel.setRawTransactionInputs(result.rawTransactionInputs);
        processModel.setChangeOutputValue(result.changeOutputValue);
        processModel.setChangeOutputAddress(result.changeOutputAddress);
        complete();
    } catch (Throwable t) {
        failed(t);
    }
}
Also used : Coin(org.bitcoinj.core.Coin) Address(org.bitcoinj.core.Address) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) InputsAndChangeOutput(bisq.core.btc.data.InputsAndChangeOutput)

Example 3 with InputsAndChangeOutput

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

the class TradeWalletService method takerCreatesDepositsTxInputs.

// /////////////////////////////////////////////////////////////////////////////////////////
// Trade
// /////////////////////////////////////////////////////////////////////////////////////////
// We construct the deposit transaction in the way that the buyer is always the first entry (inputs, outputs, MS keys) and then the seller.
// In the creation of the deposit tx the taker/maker roles are the determining roles instead of buyer/seller.
// In the payout tx is is the buyer/seller role. We keep the buyer/seller ordering over all transactions to not get confusion with ordering,
// which is important to follow correctly specially for the order of the MS keys.
/**
 * The taker creates a dummy transaction to get the input(s) and optional change output for the amount and the takersAddress for that trade.
 * That will be used to send to the maker for creating the deposit transaction.
 *
 * @param inputAmount   Amount of takers input
 * @param txFee         Mining fee
 * @param takersAddress Address of taker
 * @return A data container holding the inputs, the output value and address
 * @throws TransactionVerificationException
 * @throws WalletException
 */
public InputsAndChangeOutput takerCreatesDepositsTxInputs(Coin inputAmount, Coin txFee, Address takersAddress, Address takersChangeAddress) throws TransactionVerificationException, WalletException {
    log.debug("takerCreatesDepositsTxInputs called");
    log.debug("inputAmount " + inputAmount.toFriendlyString());
    log.debug("txFee " + txFee.toFriendlyString());
    log.debug("takersAddress " + takersAddress.toString());
    // We add the mining fee 2 times to the deposit tx:
    // 1. Will be spent when publishing the deposit tx (paid by buyer)
    // 2. Will be added to the MS amount, so when publishing the payout tx the fee is already there and the outputs are not changed by fee reduction
    // The fee for the payout will be paid by the seller.
    /*
         The tx we create has that structure:

         IN[0]  any input > inputAmount (including tx fee) (unsigned)
         IN[1...n] optional inputs supported, but normally there is just 1 input (unsigned)
         OUT[0] dummyOutputAmount (inputAmount - tx fee)
         OUT[1] Optional Change = inputAmount - dummyOutputAmount - tx fee

         We are only interested in the inputs and the optional change output.
         */
    // inputAmount includes the tx fee. So we subtract the fee to get the dummyOutputAmount.
    Coin dummyOutputAmount = inputAmount.subtract(txFee);
    Transaction dummyTX = new Transaction(params);
    // The output is just used to get the right inputs and change outputs, so we use an anonymous ECKey, as it will never be used for anything.
    // We don't care about fee calculation differences between the real tx and that dummy tx as we use a static tx fee.
    TransactionOutput dummyOutput = new TransactionOutput(params, dummyTX, dummyOutputAmount, new ECKey().toAddress(params));
    dummyTX.addOutput(dummyOutput);
    // Find the needed inputs to pay the output, optionally add 1 change output.
    // Normally only 1 input and no change output is used, but we support multiple inputs and 1 change output.
    // Our spending transaction output is from the create offer fee payment.
    addAvailableInputsAndChangeOutputs(dummyTX, takersAddress, takersChangeAddress, txFee);
    // The completeTx() call signs the input, but we don't want to pass over signed tx inputs so we remove the signature
    WalletService.removeSignatures(dummyTX);
    WalletService.verifyTransaction(dummyTX);
    // WalletService.printTx("dummyTX", dummyTX);
    List<RawTransactionInput> rawTransactionInputList = dummyTX.getInputs().stream().map(e -> {
        checkNotNull(e.getConnectedOutput(), "e.getConnectedOutput() must not be null");
        checkNotNull(e.getConnectedOutput().getParentTransaction(), "e.getConnectedOutput().getParentTransaction() must not be null");
        checkNotNull(e.getValue(), "e.getValue() must not be null");
        return getRawInputFromTransactionInput(e);
    }).collect(Collectors.toList());
    // We don't support more then 1 change outputs, so there are max. 2 outputs
    checkArgument(dummyTX.getOutputs().size() < 3);
    // Only interested in optional change output, the dummy output at index 0 is ignored (that's why we use index 1)
    TransactionOutput changeOutput = dummyTX.getOutputs().size() == 2 ? dummyTX.getOutputs().get(1) : null;
    long changeOutputValue = 0L;
    String changeOutputAddress = null;
    if (changeOutput != null) {
        changeOutputValue = changeOutput.getValue().getValue();
        Address addressFromP2PKHScript = changeOutput.getAddressFromP2PKHScript(params);
        checkNotNull(addressFromP2PKHScript, "changeOutput.getAddressFromP2PKHScript(params) must not be null");
        changeOutputAddress = addressFromP2PKHScript.toString();
    }
    return new InputsAndChangeOutput(new ArrayList<>(rawTransactionInputList), changeOutputValue, changeOutputAddress);
}
Also used : Transaction(org.bitcoinj.core.Transaction) TransactionConfidence(org.bitcoinj.core.TransactionConfidence) Coin(org.bitcoinj.core.Coin) Wallet(org.bitcoinj.wallet.Wallet) LoggerFactory(org.slf4j.LoggerFactory) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) NetworkParameters(org.bitcoinj.core.NetworkParameters) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) TransactionSignature(org.bitcoinj.crypto.TransactionSignature) TransactionVerificationException(bisq.core.btc.exceptions.TransactionVerificationException) VerificationException(org.bitcoinj.core.VerificationException) ImmutableList(com.google.common.collect.ImmutableList) Res(bisq.core.locale.Res) SendRequest(org.bitcoinj.wallet.SendRequest) KeyParameter(org.spongycastle.crypto.params.KeyParameter) Sha256Hash(org.bitcoinj.core.Sha256Hash) DeterministicKey(org.bitcoinj.crypto.DeterministicKey) Context(org.bitcoinj.core.Context) Nullable(javax.annotation.Nullable) ScriptBuilder(org.bitcoinj.script.ScriptBuilder) PreparedDepositTxAndMakerInputs(bisq.core.btc.data.PreparedDepositTxAndMakerInputs) AddressFormatException(org.bitcoinj.core.AddressFormatException) WalletException(bisq.core.btc.exceptions.WalletException) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) SigningException(bisq.core.btc.exceptions.SigningException) Logger(org.slf4j.Logger) Utils(org.bitcoinj.core.Utils) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Log(bisq.common.app.Log) BisqEnvironment(bisq.core.app.BisqEnvironment) InputsAndChangeOutput(bisq.core.btc.data.InputsAndChangeOutput) InsufficientMoneyException(org.bitcoinj.core.InsufficientMoneyException) Collectors(java.util.stream.Collectors) FutureCallback(com.google.common.util.concurrent.FutureCallback) ECKey(org.bitcoinj.core.ECKey) List(java.util.List) Script(org.bitcoinj.script.Script) AddressEntry(bisq.core.btc.AddressEntry) TransactionInput(org.bitcoinj.core.TransactionInput) TransactionOutput(org.bitcoinj.core.TransactionOutput) Address(org.bitcoinj.core.Address) NotNull(org.jetbrains.annotations.NotNull) Coin(org.bitcoinj.core.Coin) TransactionOutput(org.bitcoinj.core.TransactionOutput) Transaction(org.bitcoinj.core.Transaction) Address(org.bitcoinj.core.Address) RawTransactionInput(bisq.core.btc.data.RawTransactionInput) InputsAndChangeOutput(bisq.core.btc.data.InputsAndChangeOutput) ECKey(org.bitcoinj.core.ECKey)

Aggregations

InputsAndChangeOutput (bisq.core.btc.data.InputsAndChangeOutput)3 Address (org.bitcoinj.core.Address)3 Coin (org.bitcoinj.core.Coin)3 BtcWalletService (bisq.core.btc.wallet.BtcWalletService)2 Log (bisq.common.app.Log)1 BisqEnvironment (bisq.core.app.BisqEnvironment)1 AddressEntry (bisq.core.btc.AddressEntry)1 PreparedDepositTxAndMakerInputs (bisq.core.btc.data.PreparedDepositTxAndMakerInputs)1 RawTransactionInput (bisq.core.btc.data.RawTransactionInput)1 SigningException (bisq.core.btc.exceptions.SigningException)1 TransactionVerificationException (bisq.core.btc.exceptions.TransactionVerificationException)1 WalletException (bisq.core.btc.exceptions.WalletException)1 Res (bisq.core.locale.Res)1 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)1 ImmutableList (com.google.common.collect.ImmutableList)1 FutureCallback (com.google.common.util.concurrent.FutureCallback)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Collectors (java.util.stream.Collectors)1