Search in sources :

Example 1 with TxProcessorResult

use of com.samourai.boltzmann.processor.TxProcessorResult in project samourai-wallet-android by Samourai-Wallet.

the class CahootReviewFragment method CalculateEntropy.

private Observable<TxProcessorResult> CalculateEntropy(Cahoots payload) {
    return Observable.create(emitter -> {
        Map<String, Long> inputs = new HashMap<>();
        Map<String, Long> outputs = new HashMap<>();
        int counter = 0;
        for (Map.Entry<String, Long> entry : payload.getOutpoints().entrySet()) {
            inputs.put(stubAddress[counter], entry.getValue());
            counter++;
        }
        for (int i = 0; i < payload.getTransaction().getOutputs().size(); i++) {
            TransactionOutput output = payload.getTransaction().getOutputs().get(i);
            outputs.put(stubAddress[counter + i], output.getValue().value);
        }
        TxProcessor txProcessor = new TxProcessor(BoltzmannSettings.MAX_DURATION_DEFAULT, BoltzmannSettings.MAX_TXOS_DEFAULT);
        Txos txos = new Txos(inputs, outputs);
        TxProcessorResult result = txProcessor.processTx(txos, 0.005f, TxosLinkerOptionEnum.PRECHECK, TxosLinkerOptionEnum.LINKABILITY, TxosLinkerOptionEnum.MERGE_INPUTS);
        emitter.onNext(result);
    });
}
Also used : TransactionOutput(org.bitcoinj.core.TransactionOutput) HashMap(java.util.HashMap) TxProcessor(com.samourai.boltzmann.processor.TxProcessor) HashMap(java.util.HashMap) Map(java.util.Map) TxProcessorResult(com.samourai.boltzmann.processor.TxProcessorResult) Txos(com.samourai.boltzmann.beans.Txos)

Example 2 with TxProcessorResult

use of com.samourai.boltzmann.processor.TxProcessorResult in project samourai-wallet-android by Samourai-Wallet.

the class SendActivity method prepareSpend.

private boolean prepareSpend() {
    restoreChangeIndexes();
    double btc_amount = 0.0;
    try {
        btc_amount = NumberFormat.getInstance(Locale.US).parse(btcEditText.getText().toString().trim()).doubleValue();
    // Log.i("SendFragment", "amount entered:" + btc_amount);
    } catch (NumberFormatException nfe) {
        btc_amount = 0.0;
    } catch (ParseException pe) {
        btc_amount = 0.0;
    }
    double dAmount = btc_amount;
    amount = (long) (Math.round(dAmount * 1e8));
    if (selectedCahootsType == SelectCahootsType.type.STOWAWAY) {
        setButtonForStowaway(true);
        return true;
    } else {
        setButtonForStowaway(false);
    }
    address = strDestinationBTCAddress == null ? toAddressEditText.getText().toString().trim() : strDestinationBTCAddress;
    if (account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
        changeType = 84;
    } else if (PrefsUtil.getInstance(SendActivity.this).getValue(PrefsUtil.USE_LIKE_TYPED_CHANGE, true) == false) {
        changeType = 84;
    } else if (FormatsUtil.getInstance().isValidBech32(address) || Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) {
        changeType = FormatsUtil.getInstance().isValidBech32(address) ? 84 : 49;
    } else {
        changeType = 44;
    }
    receivers = new HashMap<String, BigInteger>();
    receivers.put(address, BigInteger.valueOf(amount));
    if (account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
        change_index = idxBIP84PostMixInternal;
    } else if (changeType == 84) {
        change_index = idxBIP84Internal;
    } else if (changeType == 49) {
        change_index = idxBIP49Internal;
    } else {
        change_index = idxBIP44Internal;
    }
    // if possible, get UTXO by input 'type': p2pkh, p2sh-p2wpkh or p2wpkh, else get all UTXO
    long neededAmount = 0L;
    if (FormatsUtil.getInstance().isValidBech32(address) || account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
        neededAmount += FeeUtil.getInstance().estimatedFeeSegwit(0, 0, UTXOFactory.getInstance().getCountP2WPKH(), 4).longValue();
    // Log.d("SendActivity", "segwit:" + neededAmount);
    } else if (Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) {
        neededAmount += FeeUtil.getInstance().estimatedFeeSegwit(0, UTXOFactory.getInstance().getCountP2SH_P2WPKH(), 0, 4).longValue();
    // Log.d("SendActivity", "segwit:" + neededAmount);
    } else {
        neededAmount += FeeUtil.getInstance().estimatedFeeSegwit(UTXOFactory.getInstance().getCountP2PKH(), 0, 4).longValue();
    // Log.d("SendActivity", "p2pkh:" + neededAmount);
    }
    neededAmount += amount;
    neededAmount += SamouraiWallet.bDust.longValue();
    // get all UTXO
    List<UTXO> utxos = new ArrayList<>();
    if (preselectedUTXOs != null && preselectedUTXOs.size() > 0) {
        // sort in descending order by value
        for (UTXOCoin utxoCoin : preselectedUTXOs) {
            UTXO u = new UTXO();
            List<MyTransactionOutPoint> outs = new ArrayList<MyTransactionOutPoint>();
            outs.add(utxoCoin.getOutPoint());
            u.setOutpoints(outs);
            utxos.add(u);
        }
    } else {
        utxos = SpendUtil.getUTXOS(SendActivity.this, address, neededAmount, account);
    }
    List<UTXO> utxosP2WPKH = new ArrayList<UTXO>(UTXOFactory.getInstance().getAllP2WPKH().values());
    List<UTXO> utxosP2SH_P2WPKH = new ArrayList<UTXO>(UTXOFactory.getInstance().getAllP2SH_P2WPKH().values());
    List<UTXO> utxosP2PKH = new ArrayList<UTXO>(UTXOFactory.getInstance().getAllP2PKH().values());
    if ((preselectedUTXOs == null || preselectedUTXOs.size() == 0) && account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
        utxos = new ArrayList<UTXO>(UTXOFactory.getInstance().getAllPostMix().values());
        utxosP2WPKH = new ArrayList<UTXO>(UTXOFactory.getInstance().getAllPostMix().values());
        utxosP2PKH.clear();
        utxosP2SH_P2WPKH.clear();
    }
    selectedUTXO = new ArrayList<UTXO>();
    long totalValueSelected = 0L;
    long change = 0L;
    BigInteger fee = null;
    boolean canDoBoltzmann = true;
    // insufficient funds
    if (amount > balance) {
        Toast.makeText(SendActivity.this, R.string.insufficient_funds, Toast.LENGTH_SHORT).show();
    }
    if (preselectedUTXOs != null) {
        canDoBoltzmann = false;
        SPEND_TYPE = SPEND_SIMPLE;
    } else // entire balance (can only be simple spend)
    if (amount == balance) {
        // make sure we are using simple spend
        SPEND_TYPE = SPEND_SIMPLE;
        canDoBoltzmann = false;
        // Log.d("SendActivity", "amount == balance");
        // take all utxos, deduct fee
        selectedUTXO.addAll(utxos);
        for (UTXO u : selectedUTXO) {
            totalValueSelected += u.getValue();
        }
    // Log.d("SendActivity", "balance:" + balance);
    // Log.d("SendActivity", "total value selected:" + totalValueSelected);
    } else {
        ;
    }
    org.apache.commons.lang3.tuple.Pair<ArrayList<MyTransactionOutPoint>, ArrayList<TransactionOutput>> pair = null;
    if (SPEND_TYPE == SPEND_RICOCHET) {
        boolean samouraiFeeViaBIP47 = false;
        if (BIP47Meta.getInstance().getOutgoingStatus(BIP47Meta.strSamouraiDonationPCode) == BIP47Meta.STATUS_SENT_CFM) {
            samouraiFeeViaBIP47 = true;
        }
        ricochetJsonObj = RicochetMeta.getInstance(SendActivity.this).script(amount, FeeUtil.getInstance().getSuggestedFee().getDefaultPerKB().longValue(), address, 4, strPCode, samouraiFeeViaBIP47, ricochetStaggeredDelivery.isChecked());
        if (ricochetJsonObj != null) {
            try {
                long totalAmount = ricochetJsonObj.getLong("total_spend");
                if (totalAmount > balance) {
                    Toast.makeText(SendActivity.this, R.string.insufficient_funds, Toast.LENGTH_SHORT).show();
                    ricochetHopsSwitch.setChecked(false);
                    return false;
                }
                long hop0Fee = ricochetJsonObj.getJSONArray("hops").getJSONObject(0).getLong("fee");
                long perHopFee = ricochetJsonObj.getJSONArray("hops").getJSONObject(0).getLong("fee_per_hop");
                long ricochetFee = hop0Fee + (RicochetMeta.defaultNbHops * perHopFee);
                if (selectedCahootsType == SelectCahootsType.type.NONE) {
                    tvTotalFee.setText(Coin.valueOf(ricochetFee).toPlainString().concat(" BTC"));
                } else {
                    tvTotalFee.setText("__");
                }
                ricochetMessage = getText(R.string.ricochet_spend1) + " " + address + " " + getText(R.string.ricochet_spend2) + " " + Coin.valueOf(totalAmount).toPlainString() + " " + getText(R.string.ricochet_spend3);
                btnSend.setText("send ".concat(String.format(Locale.ENGLISH, "%.8f", getBtcValue((double) totalAmount)).concat(" BTC")));
                return true;
            } catch (JSONException je) {
                return false;
            }
        }
        return true;
    } else if (SPEND_TYPE == SPEND_BOLTZMANN) {
        Log.d("SendActivity", "needed amount:" + neededAmount);
        List<UTXO> _utxos1 = null;
        List<UTXO> _utxos2 = null;
        long valueP2WPKH = UTXOFactory.getInstance().getTotalP2WPKH();
        long valueP2SH_P2WPKH = UTXOFactory.getInstance().getTotalP2SH_P2WPKH();
        long valueP2PKH = UTXOFactory.getInstance().getTotalP2PKH();
        if (account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
            valueP2WPKH = UTXOFactory.getInstance().getTotalPostMix();
            valueP2SH_P2WPKH = 0L;
            valueP2PKH = 0L;
            utxosP2SH_P2WPKH.clear();
            utxosP2PKH.clear();
        }
        Log.d("SendActivity", "value P2WPKH:" + valueP2WPKH);
        Log.d("SendActivity", "value P2SH_P2WPKH:" + valueP2SH_P2WPKH);
        Log.d("SendActivity", "value P2PKH:" + valueP2PKH);
        boolean selectedP2WPKH = false;
        boolean selectedP2SH_P2WPKH = false;
        boolean selectedP2PKH = false;
        if ((valueP2WPKH > (neededAmount * 2)) && account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
            Log.d("SendActivity", "set 1 P2WPKH 2x");
            _utxos1 = utxosP2WPKH;
            selectedP2WPKH = true;
        } else if ((valueP2WPKH > (neededAmount * 2)) && FormatsUtil.getInstance().isValidBech32(address)) {
            Log.d("SendActivity", "set 1 P2WPKH 2x");
            _utxos1 = utxosP2WPKH;
            selectedP2WPKH = true;
        } else if (!FormatsUtil.getInstance().isValidBech32(address) && (valueP2SH_P2WPKH > (neededAmount * 2)) && Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) {
            Log.d("SendActivity", "set 1 P2SH_P2WPKH 2x");
            _utxos1 = utxosP2SH_P2WPKH;
            selectedP2SH_P2WPKH = true;
        } else if (!FormatsUtil.getInstance().isValidBech32(address) && (valueP2PKH > (neededAmount * 2)) && !Address.fromBase58(SamouraiWallet.getInstance().getCurrentNetworkParams(), address).isP2SHAddress()) {
            Log.d("SendActivity", "set 1 P2PKH 2x");
            _utxos1 = utxosP2PKH;
            selectedP2PKH = true;
        } else if (valueP2WPKH > (neededAmount * 2)) {
            Log.d("SendActivity", "set 1 P2WPKH 2x");
            _utxos1 = utxosP2WPKH;
            selectedP2WPKH = true;
        } else if (valueP2SH_P2WPKH > (neededAmount * 2)) {
            Log.d("SendActivity", "set 1 P2SH_P2WPKH 2x");
            _utxos1 = utxosP2SH_P2WPKH;
            selectedP2SH_P2WPKH = true;
        } else if (valueP2PKH > (neededAmount * 2)) {
            Log.d("SendActivity", "set 1 P2PKH 2x");
            _utxos1 = utxosP2PKH;
            selectedP2PKH = true;
        } else {
            ;
        }
        if (_utxos1 == null || _utxos1.size() == 0) {
            if (valueP2SH_P2WPKH > neededAmount) {
                Log.d("SendActivity", "set 1 P2SH_P2WPKH");
                _utxos1 = utxosP2SH_P2WPKH;
                selectedP2SH_P2WPKH = true;
            } else if (valueP2WPKH > neededAmount) {
                Log.d("SendActivity", "set 1 P2WPKH");
                _utxos1 = utxosP2WPKH;
                selectedP2WPKH = true;
            } else if (valueP2PKH > neededAmount) {
                Log.d("SendActivity", "set 1 P2PKH");
                _utxos1 = utxosP2PKH;
                selectedP2PKH = true;
            } else {
                ;
            }
        }
        if (_utxos1 != null && _utxos1.size() > 0) {
            if (!selectedP2SH_P2WPKH && valueP2SH_P2WPKH > neededAmount) {
                Log.d("SendActivity", "set 2 P2SH_P2WPKH");
                _utxos2 = utxosP2SH_P2WPKH;
                selectedP2SH_P2WPKH = true;
            }
            if (!selectedP2SH_P2WPKH && !selectedP2WPKH && valueP2WPKH > neededAmount) {
                Log.d("SendActivity", "set 2 P2WPKH");
                _utxos2 = utxosP2WPKH;
                selectedP2WPKH = true;
            }
            if (!selectedP2SH_P2WPKH && !selectedP2WPKH && !selectedP2PKH && valueP2PKH > neededAmount) {
                Log.d("SendActivity", "set 2 P2PKH");
                _utxos2 = utxosP2PKH;
                selectedP2PKH = true;
            } else {
                ;
            }
        }
        if ((_utxos1 == null || _utxos1.size() == 0) && (_utxos2 == null || _utxos2.size() == 0)) {
            // can't do boltzmann, revert to SPEND_SIMPLE
            canDoBoltzmann = false;
            SPEND_TYPE = SPEND_SIMPLE;
        } else {
            Log.d("SendActivity", "boltzmann spend");
            Collections.shuffle(_utxos1);
            if (_utxos2 != null && _utxos2.size() > 0) {
                Collections.shuffle(_utxos2);
            }
            // boltzmann spend (STONEWALL)
            pair = SendFactory.getInstance(SendActivity.this).boltzmann(_utxos1, _utxos2, BigInteger.valueOf(amount), address, account);
            if (pair == null) {
                // can't do boltzmann, revert to SPEND_SIMPLE
                canDoBoltzmann = false;
                restoreChangeIndexes();
                SPEND_TYPE = SPEND_SIMPLE;
            } else {
                canDoBoltzmann = true;
            }
        }
    } else {
        ;
    }
    if (SPEND_TYPE == SPEND_SIMPLE && amount == balance && preselectedUTXOs == null) {
        // do nothing, utxo selection handles above
        ;
    } else // simple spend (less than balance)
    if (SPEND_TYPE == SPEND_SIMPLE) {
        List<UTXO> _utxos = utxos;
        // sort in ascending order by value
        Collections.sort(_utxos, new UTXO.UTXOComparator());
        Collections.reverse(_utxos);
        // get smallest 1 UTXO > than spend + fee + dust
        for (UTXO u : _utxos) {
            Triple<Integer, Integer, Integer> outpointTypes = FeeUtil.getInstance().getOutpointCount(new Vector(u.getOutpoints()));
            if (u.getValue() >= (amount + SamouraiWallet.bDust.longValue() + FeeUtil.getInstance().estimatedFeeSegwit(outpointTypes.getLeft(), outpointTypes.getMiddle(), outpointTypes.getRight(), 2).longValue())) {
                selectedUTXO.add(u);
                totalValueSelected += u.getValue();
                Log.d("SendActivity", "spend type:" + SPEND_TYPE);
                Log.d("SendActivity", "single output");
                Log.d("SendActivity", "amount:" + amount);
                Log.d("SendActivity", "value selected:" + u.getValue());
                Log.d("SendActivity", "total value selected:" + totalValueSelected);
                Log.d("SendActivity", "nb inputs:" + u.getOutpoints().size());
                break;
            }
        }
        if (selectedUTXO.size() == 0) {
            // sort in descending order by value
            Collections.sort(_utxos, new UTXO.UTXOComparator());
            int selected = 0;
            int p2pkh = 0;
            int p2sh_p2wpkh = 0;
            int p2wpkh = 0;
            // get largest UTXOs > than spend + fee + dust
            for (UTXO u : _utxos) {
                selectedUTXO.add(u);
                totalValueSelected += u.getValue();
                selected += u.getOutpoints().size();
                // Log.d("SendActivity", "value selected:" + u.getValue());
                // Log.d("SendActivity", "total value selected/threshold:" + totalValueSelected + "/" + (amount + SamouraiWallet.bDust.longValue() + FeeUtil.getInstance().estimatedFee(selected, 2).longValue()));
                Triple<Integer, Integer, Integer> outpointTypes = FeeUtil.getInstance().getOutpointCount(new Vector<MyTransactionOutPoint>(u.getOutpoints()));
                p2pkh += outpointTypes.getLeft();
                p2sh_p2wpkh += outpointTypes.getMiddle();
                p2wpkh += outpointTypes.getRight();
                if (totalValueSelected >= (amount + SamouraiWallet.bDust.longValue() + FeeUtil.getInstance().estimatedFeeSegwit(p2pkh, p2sh_p2wpkh, p2wpkh, 2).longValue())) {
                    Log.d("SendActivity", "spend type:" + SPEND_TYPE);
                    Log.d("SendActivity", "multiple outputs");
                    Log.d("SendActivity", "amount:" + amount);
                    Log.d("SendActivity", "total value selected:" + totalValueSelected);
                    Log.d("SendActivity", "nb inputs:" + selected);
                    break;
                }
            }
        }
    } else if (pair != null) {
        selectedUTXO.clear();
        receivers.clear();
        long inputAmount = 0L;
        long outputAmount = 0L;
        for (MyTransactionOutPoint outpoint : pair.getLeft()) {
            UTXO u = new UTXO();
            List<MyTransactionOutPoint> outs = new ArrayList<MyTransactionOutPoint>();
            outs.add(outpoint);
            u.setOutpoints(outs);
            totalValueSelected += u.getValue();
            selectedUTXO.add(u);
            inputAmount += u.getValue();
        }
        for (TransactionOutput output : pair.getRight()) {
            try {
                Script script = new Script(output.getScriptBytes());
                if (Bech32Util.getInstance().isP2WPKHScript(Hex.toHexString(output.getScriptBytes()))) {
                    receivers.put(Bech32Util.getInstance().getAddressFromScript(script), BigInteger.valueOf(output.getValue().longValue()));
                } else {
                    receivers.put(script.getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString(), BigInteger.valueOf(output.getValue().longValue()));
                }
                outputAmount += output.getValue().longValue();
            } catch (Exception e) {
                Toast.makeText(SendActivity.this, R.string.error_bip126_output, Toast.LENGTH_SHORT).show();
                return false;
            }
        }
        fee = BigInteger.valueOf(inputAmount - outputAmount);
    } else {
        Toast.makeText(SendActivity.this, R.string.cannot_select_utxo, Toast.LENGTH_SHORT).show();
        return false;
    }
    // do spend here
    if (selectedUTXO.size() > 0) {
        // estimate fee for simple spend, already done if boltzmann
        if (SPEND_TYPE == SPEND_SIMPLE) {
            List<MyTransactionOutPoint> outpoints = new ArrayList<MyTransactionOutPoint>();
            for (UTXO utxo : selectedUTXO) {
                outpoints.addAll(utxo.getOutpoints());
            }
            Triple<Integer, Integer, Integer> outpointTypes = FeeUtil.getInstance().getOutpointCount(new Vector(outpoints));
            if (amount == balance) {
                fee = FeeUtil.getInstance().estimatedFeeSegwit(outpointTypes.getLeft(), outpointTypes.getMiddle(), outpointTypes.getRight(), 1);
                amount -= fee.longValue();
                receivers.clear();
                receivers.put(address, BigInteger.valueOf(amount));
                // 
                // fee sanity check
                // 
                restoreChangeIndexes();
                Transaction tx = SendFactory.getInstance(SendActivity.this).makeTransaction(account, outpoints, receivers);
                tx = SendFactory.getInstance(SendActivity.this).signTransaction(tx, account);
                byte[] serialized = tx.bitcoinSerialize();
                Log.d("SendActivity", "size:" + serialized.length);
                Log.d("SendActivity", "vsize:" + tx.getVirtualTransactionSize());
                Log.d("SendActivity", "fee:" + fee.longValue());
                if ((tx.hasWitness() && (fee.longValue() < tx.getVirtualTransactionSize())) || (!tx.hasWitness() && (fee.longValue() < serialized.length))) {
                    Toast.makeText(SendActivity.this, R.string.insufficient_fee, Toast.LENGTH_SHORT).show();
                    return false;
                }
            // 
            // 
            // 
            } else {
                fee = FeeUtil.getInstance().estimatedFeeSegwit(outpointTypes.getLeft(), outpointTypes.getMiddle(), outpointTypes.getRight(), 2);
            }
        }
        Log.d("SendActivity", "spend type:" + SPEND_TYPE);
        Log.d("SendActivity", "amount:" + amount);
        Log.d("SendActivity", "total value selected:" + totalValueSelected);
        Log.d("SendActivity", "fee:" + fee.longValue());
        Log.d("SendActivity", "nb inputs:" + selectedUTXO.size());
        change = totalValueSelected - (amount + fee.longValue());
        if (change > 0L && change < SamouraiWallet.bDust.longValue() && SPEND_TYPE == SPEND_SIMPLE) {
            AlertDialog.Builder dlg = new AlertDialog.Builder(SendActivity.this).setTitle(R.string.app_name).setMessage(R.string.change_is_dust).setCancelable(false).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int whichButton) {
                    dialog.dismiss();
                }
            });
            if (!isFinishing()) {
                dlg.show();
            }
            return false;
        }
        _change = change;
        final BigInteger _fee = fee;
        String dest = null;
        if (strPCode != null && strPCode.length() > 0) {
            dest = BIP47Meta.getInstance().getDisplayLabel(strPCode);
        } else {
            dest = address;
        }
        strCannotDoBoltzmann = "";
        if (SendAddressUtil.getInstance().get(address) == 1) {
            strPrivacyWarning = getString(R.string.send_privacy_warning) + "\n\n";
        } else {
            strPrivacyWarning = "";
        }
        if (!canDoBoltzmann) {
            restoreChangeIndexes();
            sendTransactionDetailsView.getStoneWallSwitch().setOnClickListener(null);
            sendTransactionDetailsView.getStoneWallSwitch().setEnabled(false);
            sendTransactionDetailsView.enableStonewall(false);
            sendTransactionDetailsView.setEntropyBarStoneWallX1(null);
            sendTransactionDetailsView.getStoneWallSwitch().setOnCheckedChangeListener(onCheckedChangeListener);
            if (account == WhirlpoolMeta.getInstance(SendActivity.this).getWhirlpoolPostmix()) {
                strCannotDoBoltzmann = getString(R.string.boltzmann_cannot) + "\n\n";
            }
        }
        message = strCannotDoBoltzmann + strPrivacyWarning + "Send " + Coin.valueOf(amount).toPlainString() + " to " + dest + " (fee:" + Coin.valueOf(_fee.longValue()).toPlainString() + ")?\n";
        if (selectedCahootsType == SelectCahootsType.type.NONE) {
            tvTotalFee.setText(Coin.valueOf(_fee.longValue()).toPlainString().concat(" BTC"));
        } else {
            tvTotalFee.setText("__");
        }
        double value = Double.parseDouble(String.valueOf(_fee.add(BigInteger.valueOf(amount))));
        btnSend.setText("send ".concat(String.format(Locale.ENGLISH, "%.8f", getBtcValue(value))).concat(" BTC"));
        switch(selectedCahootsType) {
            case STONEWALLX2_MANUAL:
                {
                    sendTransactionDetailsView.showStonewallX2Layout("Manual", 1000);
                    btnSend.setBackgroundResource(R.drawable.button_blue);
                    btnSend.setText(getString(R.string.begin_stonewallx2));
                    break;
                }
            case STONEWALLX2_SAMOURAI:
                {
                    sendTransactionDetailsView.showStonewallX2Layout("Samourai Wallet", 1000);
                    break;
                }
            case STOWAWAY:
                {
                    // mixingPartner.setText("Samourai Wallet");
                    sendTransactionDetailsView.showStowawayLayout(address, null, 1000);
                    btnSend.setBackgroundResource(R.drawable.button_blue);
                    btnSend.setText(getString(R.string.begin_stowaway));
                    break;
                }
            case NONE:
                {
                    sendTransactionDetailsView.showStonewallx1Layout(null);
                    // for ricochet entropy will be 0 always
                    if (SPEND_TYPE == SPEND_RICOCHET) {
                        break;
                    }
                    if (receivers.size() <= 1) {
                        sendTransactionDetailsView.setEntropyBarStoneWallX1ZeroBits();
                        break;
                    }
                    if (receivers.size() > 8) {
                        sendTransactionDetailsView.setEntropyBarStoneWallX1(null);
                        break;
                    }
                    CalculateEntropy(selectedUTXO, receivers).subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<TxProcessorResult>() {

                        @Override
                        public void onSubscribe(Disposable d) {
                        }

                        @Override
                        public void onNext(TxProcessorResult entropyResult) {
                            sendTransactionDetailsView.setEntropyBarStoneWallX1(entropyResult);
                        }

                        @Override
                        public void onError(Throwable e) {
                            sendTransactionDetailsView.setEntropyBarStoneWallX1(null);
                            e.printStackTrace();
                        }

                        @Override
                        public void onComplete() {
                        }
                    });
                    break;
                }
            default:
                {
                    btnSend.setBackgroundResource(R.drawable.button_green);
                    btnSend.setText("send ".concat(String.format(Locale.ENGLISH, "%.8f", getBtcValue((double) amount))).concat(" BTC"));
                }
        }
        return true;
    }
    return false;
}
Also used : AlertDialog(android.app.AlertDialog) TransactionOutput(org.bitcoinj.core.TransactionOutput) DialogInterface(android.content.DialogInterface) ArrayList(java.util.ArrayList) TxProcessorResult(com.samourai.boltzmann.processor.TxProcessorResult) Observer(io.reactivex.Observer) ArrayList(java.util.ArrayList) List(java.util.List) Vector(java.util.Vector) CompositeDisposable(io.reactivex.disposables.CompositeDisposable) Disposable(io.reactivex.disposables.Disposable) Script(org.bitcoinj.script.Script) JSONException(org.json.JSONException) JSONException(org.json.JSONException) IOException(java.io.IOException) ParseException(java.text.ParseException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) MnemonicException(org.bitcoinj.crypto.MnemonicException) Triple(org.apache.commons.lang3.tuple.Triple) BigInteger(java.math.BigInteger) UTXOCoin(com.samourai.wallet.utxos.models.UTXOCoin) Transaction(org.bitcoinj.core.Transaction) BigInteger(java.math.BigInteger) ParseException(java.text.ParseException)

Example 3 with TxProcessorResult

use of com.samourai.boltzmann.processor.TxProcessorResult in project samourai-wallet-android by Samourai-Wallet.

the class SendActivity method CalculateEntropy.

private Observable<TxProcessorResult> CalculateEntropy(ArrayList<UTXO> selectedUTXO, HashMap<String, BigInteger> receivers) {
    return Observable.create(emitter -> {
        Map<String, Long> inputs = new HashMap<>();
        Map<String, Long> outputs = new HashMap<>();
        for (Map.Entry<String, BigInteger> mapEntry : receivers.entrySet()) {
            String toAddress = mapEntry.getKey();
            BigInteger value = mapEntry.getValue();
            outputs.put(toAddress, value.longValue());
        }
        for (int i = 0; i < selectedUTXO.size(); i++) {
            inputs.put(stubAddress[i], selectedUTXO.get(i).getValue());
        }
        TxProcessor txProcessor = new TxProcessor(BoltzmannSettings.MAX_DURATION_DEFAULT, BoltzmannSettings.MAX_TXOS_DEFAULT);
        Txos txos = new Txos(inputs, outputs);
        TxProcessorResult result = txProcessor.processTx(txos, 0.005f, TxosLinkerOptionEnum.PRECHECK, TxosLinkerOptionEnum.LINKABILITY, TxosLinkerOptionEnum.MERGE_INPUTS);
        emitter.onNext(result);
    });
}
Also used : HashMap(java.util.HashMap) TxProcessor(com.samourai.boltzmann.processor.TxProcessor) BigInteger(java.math.BigInteger) Map(java.util.Map) HashMap(java.util.HashMap) TxProcessorResult(com.samourai.boltzmann.processor.TxProcessorResult) Txos(com.samourai.boltzmann.beans.Txos)

Aggregations

TxProcessorResult (com.samourai.boltzmann.processor.TxProcessorResult)3 Txos (com.samourai.boltzmann.beans.Txos)2 TxProcessor (com.samourai.boltzmann.processor.TxProcessor)2 BigInteger (java.math.BigInteger)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 TransactionOutput (org.bitcoinj.core.TransactionOutput)2 AlertDialog (android.app.AlertDialog)1 DialogInterface (android.content.DialogInterface)1 UTXOCoin (com.samourai.wallet.utxos.models.UTXOCoin)1 Observer (io.reactivex.Observer)1 CompositeDisposable (io.reactivex.disposables.CompositeDisposable)1 Disposable (io.reactivex.disposables.Disposable)1 IOException (java.io.IOException)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 ParseException (java.text.ParseException)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Vector (java.util.Vector)1 Triple (org.apache.commons.lang3.tuple.Triple)1