Search in sources :

Example 96 with Transaction

use of org.bitcoinj.core.Transaction in project bisq-core by bisq-network.

the class BsqWalletService method getPreparedSendBtcTx.

// /////////////////////////////////////////////////////////////////////////////////////////
// Send BTC (non-BSQ) with BTC fee (e.g. the issuance output from a  lost comp. request)
// /////////////////////////////////////////////////////////////////////////////////////////
public Transaction getPreparedSendBtcTx(String receiverAddress, Coin receiverAmount) throws AddressFormatException, InsufficientBsqException, WalletException, TransactionVerificationException {
    Transaction tx = new Transaction(params);
    checkArgument(Restrictions.isAboveDust(receiverAmount), "The amount is too low (dust limit).");
    tx.addOutput(receiverAmount, Address.fromBase58(params, receiverAddress));
    SendRequest sendRequest = SendRequest.forTx(tx);
    sendRequest.fee = Coin.ZERO;
    sendRequest.feePerKb = Coin.ZERO;
    sendRequest.ensureMinRequiredFee = false;
    sendRequest.aesKey = aesKey;
    sendRequest.shuffleOutputs = false;
    sendRequest.signInputs = false;
    sendRequest.ensureMinRequiredFee = false;
    sendRequest.changeAddress = getUnusedAddress();
    sendRequest.coinSelector = nonBsqCoinSelector;
    try {
        wallet.completeTx(sendRequest);
    } catch (InsufficientMoneyException e) {
        throw new InsufficientBsqException(e.missing);
    }
    checkWalletConsistency(wallet);
    verifyTransaction(tx);
    // printTx("prepareSendTx", tx);
    return tx;
}
Also used : SendRequest(org.bitcoinj.wallet.SendRequest) Transaction(org.bitcoinj.core.Transaction) InsufficientMoneyException(org.bitcoinj.core.InsufficientMoneyException)

Example 97 with Transaction

use of org.bitcoinj.core.Transaction in project bisq-core by bisq-network.

the class BtcWalletService method getSendRequest.

private SendRequest getSendRequest(String fromAddress, String toAddress, Coin amount, Coin fee, @Nullable KeyParameter aesKey, AddressEntry.Context context) throws AddressFormatException, AddressEntryException {
    Transaction tx = new Transaction(params);
    final Coin receiverAmount = amount.subtract(fee);
    Preconditions.checkArgument(Restrictions.isAboveDust(receiverAmount), "The amount is too low (dust limit).");
    tx.addOutput(receiverAmount, Address.fromBase58(params, toAddress));
    SendRequest sendRequest = SendRequest.forTx(tx);
    sendRequest.fee = fee;
    sendRequest.feePerKb = Coin.ZERO;
    sendRequest.ensureMinRequiredFee = false;
    sendRequest.aesKey = aesKey;
    sendRequest.shuffleOutputs = false;
    Optional<AddressEntry> addressEntry = findAddressEntry(fromAddress, context);
    if (!addressEntry.isPresent())
        throw new AddressEntryException("WithdrawFromAddress is not found in our wallet.");
    checkNotNull(addressEntry.get(), "addressEntry.get() must not be null");
    checkNotNull(addressEntry.get().getAddress(), "addressEntry.get().getAddress() must not be null");
    sendRequest.coinSelector = new BtcCoinSelector(addressEntry.get().getAddress());
    sendRequest.changeAddress = addressEntry.get().getAddress();
    return sendRequest;
}
Also used : Coin(org.bitcoinj.core.Coin) SendRequest(org.bitcoinj.wallet.SendRequest) AddressEntryException(bisq.core.btc.AddressEntryException) Transaction(org.bitcoinj.core.Transaction) AddressEntry(bisq.core.btc.AddressEntry)

Example 98 with Transaction

use of org.bitcoinj.core.Transaction in project bisq-core by bisq-network.

the class BtcWalletService method getSendRequestForMultipleAddresses.

private SendRequest getSendRequestForMultipleAddresses(Set<String> fromAddresses, String toAddress, Coin amount, Coin fee, @Nullable String changeAddress, @Nullable KeyParameter aesKey) throws AddressFormatException, AddressEntryException, InsufficientMoneyException {
    Transaction tx = new Transaction(params);
    checkArgument(Restrictions.isAboveDust(amount), "The amount is too low (dust limit).");
    final Coin netValue = amount.subtract(fee);
    if (netValue.isNegative())
        throw new InsufficientMoneyException(netValue.multiply(-1), "The mining fee for that transaction exceed the available amount.");
    tx.addOutput(netValue, Address.fromBase58(params, toAddress));
    SendRequest sendRequest = SendRequest.forTx(tx);
    sendRequest.fee = fee;
    sendRequest.feePerKb = Coin.ZERO;
    sendRequest.ensureMinRequiredFee = false;
    sendRequest.aesKey = aesKey;
    sendRequest.shuffleOutputs = false;
    Set<AddressEntry> addressEntries = fromAddresses.stream().map(address -> {
        Optional<AddressEntry> addressEntryOptional = findAddressEntry(address, AddressEntry.Context.AVAILABLE);
        if (!addressEntryOptional.isPresent())
            addressEntryOptional = findAddressEntry(address, AddressEntry.Context.OFFER_FUNDING);
        if (!addressEntryOptional.isPresent())
            addressEntryOptional = findAddressEntry(address, AddressEntry.Context.TRADE_PAYOUT);
        if (!addressEntryOptional.isPresent())
            addressEntryOptional = findAddressEntry(address, AddressEntry.Context.ARBITRATOR);
        return addressEntryOptional;
    }).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toSet());
    if (addressEntries.isEmpty())
        throw new AddressEntryException("No Addresses for withdraw found in our wallet");
    sendRequest.coinSelector = new BtcCoinSelector(walletsSetup.getAddressesFromAddressEntries(addressEntries));
    Optional<AddressEntry> addressEntryOptional = Optional.<AddressEntry>empty();
    AddressEntry changeAddressAddressEntry = null;
    if (changeAddress != null)
        addressEntryOptional = findAddressEntry(changeAddress, AddressEntry.Context.AVAILABLE);
    changeAddressAddressEntry = addressEntryOptional.orElseGet(() -> getFreshAddressEntry());
    checkNotNull(changeAddressAddressEntry, "change address must not be null");
    sendRequest.changeAddress = changeAddressAddressEntry.getAddress();
    return sendRequest;
}
Also used : Arrays(java.util.Arrays) Transaction(org.bitcoinj.core.Transaction) TransactionConfidence(org.bitcoinj.core.TransactionConfidence) Coin(org.bitcoinj.core.Coin) Wallet(org.bitcoinj.wallet.Wallet) LoggerFactory(org.slf4j.LoggerFactory) Inject(javax.inject.Inject) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) TransactionVerificationException(bisq.core.btc.exceptions.TransactionVerificationException) ImmutableList(com.google.common.collect.ImmutableList) AddressEntryList(bisq.core.btc.AddressEntryList) SendRequest(org.bitcoinj.wallet.SendRequest) ErrorMessageHandler(bisq.common.handlers.ErrorMessageHandler) KeyCrypterScrypt(org.bitcoinj.crypto.KeyCrypterScrypt) KeyParameter(org.spongycastle.crypto.params.KeyParameter) DeterministicKey(org.bitcoinj.crypto.DeterministicKey) Nullable(javax.annotation.Nullable) ScriptBuilder(org.bitcoinj.script.ScriptBuilder) AddressFormatException(org.bitcoinj.core.AddressFormatException) AddressEntryException(bisq.core.btc.AddressEntryException) WalletException(bisq.core.btc.exceptions.WalletException) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) Logger(org.slf4j.Logger) InsufficientFundsException(bisq.core.btc.InsufficientFundsException) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Set(java.util.Set) InsufficientMoneyException(org.bitcoinj.core.InsufficientMoneyException) Collectors(java.util.stream.Collectors) FutureCallback(com.google.common.util.concurrent.FutureCallback) Futures(com.google.common.util.concurrent.Futures) List(java.util.List) AddressEntry(bisq.core.btc.AddressEntry) TransactionInput(org.bitcoinj.core.TransactionInput) Preferences(bisq.core.user.Preferences) TransactionOutput(org.bitcoinj.core.TransactionOutput) Optional(java.util.Optional) FeeService(bisq.core.provider.fee.FeeService) Address(org.bitcoinj.core.Address) Preconditions(com.google.common.base.Preconditions) NotNull(org.jetbrains.annotations.NotNull) Restrictions(bisq.core.btc.Restrictions) Coin(org.bitcoinj.core.Coin) SendRequest(org.bitcoinj.wallet.SendRequest) AddressEntryException(bisq.core.btc.AddressEntryException) Transaction(org.bitcoinj.core.Transaction) Optional(java.util.Optional) AddressEntry(bisq.core.btc.AddressEntry) InsufficientMoneyException(org.bitcoinj.core.InsufficientMoneyException)

Example 99 with Transaction

use of org.bitcoinj.core.Transaction in project bisq-core by bisq-network.

the class BtcWalletService method addInputsForMinerFee.

private Transaction addInputsForMinerFee(Transaction preparedTx, byte[] opReturnData) throws InsufficientMoneyException {
    // safety check counter to avoid endless loops
    int counter = 0;
    // estimated size of input sig
    final int sigSizePerInput = 106;
    // typical size for a tx with 3 inputs
    int txSizeWithUnsignedInputs = 300;
    final Coin txFeePerByte = feeService.getTxFeePerByte();
    Address changeAddress = getFreshAddressEntry().getAddress();
    checkNotNull(changeAddress, "changeAddress must not be null");
    final BtcCoinSelector coinSelector = new BtcCoinSelector(walletsSetup.getAddressesByContext(AddressEntry.Context.AVAILABLE));
    final List<TransactionInput> preparedBsqTxInputs = preparedTx.getInputs();
    final List<TransactionOutput> preparedBsqTxOutputs = preparedTx.getOutputs();
    int numInputs = preparedBsqTxInputs.size();
    Transaction resultTx = null;
    boolean isFeeOutsideTolerance;
    do {
        counter++;
        if (counter >= 10) {
            checkNotNull(resultTx, "resultTx must not be null");
            log.error("Could not calculate the fee. Tx=" + resultTx);
            break;
        }
        Transaction tx = new Transaction(params);
        preparedBsqTxInputs.forEach(tx::addInput);
        preparedBsqTxOutputs.forEach(tx::addOutput);
        SendRequest sendRequest = SendRequest.forTx(tx);
        sendRequest.shuffleOutputs = false;
        sendRequest.aesKey = aesKey;
        // signInputs needs to be false as it would try to sign all inputs (BSQ inputs are not in this wallet)
        sendRequest.signInputs = false;
        sendRequest.fee = txFeePerByte.multiply(txSizeWithUnsignedInputs + sigSizePerInput * numInputs);
        sendRequest.feePerKb = Coin.ZERO;
        sendRequest.ensureMinRequiredFee = false;
        sendRequest.coinSelector = coinSelector;
        sendRequest.changeAddress = changeAddress;
        wallet.completeTx(sendRequest);
        resultTx = sendRequest.tx;
        // add OP_RETURN output
        resultTx.addOutput(new TransactionOutput(params, resultTx, Coin.ZERO, ScriptBuilder.createOpReturnScript(opReturnData).getProgram()));
        numInputs = resultTx.getInputs().size();
        txSizeWithUnsignedInputs = resultTx.bitcoinSerialize().length;
        final long estimatedFeeAsLong = txFeePerByte.multiply(txSizeWithUnsignedInputs + sigSizePerInput * numInputs).value;
        // calculated fee must be inside of a tolerance range with tx fee
        isFeeOutsideTolerance = Math.abs(resultTx.getFee().value - estimatedFeeAsLong) > 1000;
    } while (isFeeOutsideTolerance);
    return resultTx;
}
Also used : TransactionOutput(org.bitcoinj.core.TransactionOutput) SendRequest(org.bitcoinj.wallet.SendRequest) Address(org.bitcoinj.core.Address) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) TransactionInput(org.bitcoinj.core.TransactionInput) Coin(org.bitcoinj.core.Coin) Transaction(org.bitcoinj.core.Transaction)

Example 100 with Transaction

use of org.bitcoinj.core.Transaction in project bisq-core by bisq-network.

the class MakerSetupDepositTxListener method run.

@Override
protected void run() {
    try {
        runInterceptHook();
        if (trade.getDepositTx() == null && processModel.getPreparedDepositTx() != null) {
            BtcWalletService walletService = processModel.getBtcWalletService();
            final NetworkParameters params = walletService.getParams();
            Transaction preparedDepositTx = new Transaction(params, processModel.getPreparedDepositTx());
            checkArgument(!preparedDepositTx.getOutputs().isEmpty(), "preparedDepositTx.getOutputs() must not be empty");
            Address depositTxAddress = preparedDepositTx.getOutput(0).getAddressFromP2SH(params);
            final TransactionConfidence confidence = walletService.getConfidenceForAddress(depositTxAddress);
            if (isInNetwork(confidence)) {
                applyConfidence(confidence);
            } else {
                confidenceListener = new AddressConfidenceListener(depositTxAddress) {

                    @Override
                    public void onTransactionConfidenceChanged(TransactionConfidence confidence) {
                        if (isInNetwork(confidence))
                            applyConfidence(confidence);
                    }
                };
                walletService.addAddressConfidenceListener(confidenceListener);
                tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> {
                    if (trade.isDepositPublished()) {
                        swapReservedForTradeEntry();
                        // hack to remove tradeStateSubscription at callback
                        UserThread.execute(this::unSubscribe);
                    }
                });
            }
        }
        // we complete immediately, our object stays alive because the balanceListener is stored in the WalletService
        complete();
    } catch (Throwable t) {
        failed(t);
    }
}
Also used : BtcWalletService(bisq.core.btc.wallet.BtcWalletService) Transaction(org.bitcoinj.core.Transaction) TransactionConfidence(org.bitcoinj.core.TransactionConfidence) Trade(bisq.core.trade.Trade) Subscription(org.fxmisc.easybind.Subscription) NetworkParameters(org.bitcoinj.core.NetworkParameters) Slf4j(lombok.extern.slf4j.Slf4j) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) TaskRunner(bisq.common.taskrunner.TaskRunner) AddressEntry(bisq.core.btc.AddressEntry) EasyBind(org.fxmisc.easybind.EasyBind) UserThread(bisq.common.UserThread) Address(org.bitcoinj.core.Address) AddressConfidenceListener(bisq.core.btc.listeners.AddressConfidenceListener) TradeTask(bisq.core.trade.protocol.tasks.TradeTask) AddressConfidenceListener(bisq.core.btc.listeners.AddressConfidenceListener) Transaction(org.bitcoinj.core.Transaction) Address(org.bitcoinj.core.Address) BtcWalletService(bisq.core.btc.wallet.BtcWalletService) NetworkParameters(org.bitcoinj.core.NetworkParameters) TransactionConfidence(org.bitcoinj.core.TransactionConfidence)

Aggregations

Transaction (org.bitcoinj.core.Transaction)214 Coin (org.bitcoinj.core.Coin)71 TransactionInput (org.bitcoinj.core.TransactionInput)48 TransactionOutput (org.bitcoinj.core.TransactionOutput)42 TransactionOutPoint (org.bitcoinj.core.TransactionOutPoint)38 Address (org.bitcoinj.core.Address)35 ECKey (org.bitcoinj.core.ECKey)32 Script (org.bitcoinj.script.Script)32 ArrayList (java.util.ArrayList)31 HashMap (java.util.HashMap)29 SendRequest (org.bitcoinj.wallet.SendRequest)25 Wallet (org.bitcoinj.wallet.Wallet)25 IOException (java.io.IOException)24 List (java.util.List)24 InsufficientMoneyException (org.bitcoinj.core.InsufficientMoneyException)20 MyTransactionOutPoint (com.samourai.wallet.send.MyTransactionOutPoint)19 AddressFormatException (org.bitcoinj.core.AddressFormatException)19 Sha256Hash (org.bitcoinj.core.Sha256Hash)19 UTXO (com.samourai.wallet.send.UTXO)17 Nullable (javax.annotation.Nullable)17