Search in sources :

Example 31 with UTXO

use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.

the class CahootsUtil method doStowaway4.

// 
// sender
// 
public Cahoots doStowaway4(Stowaway stowaway3) throws Exception {
    debug("CahootsUtil", "sender account (4):" + stowaway3.getAccount());
    HashMap<String, String> utxo2Address = new HashMap<String, String>();
    List<UTXO> utxos = null;
    if (stowaway3.getAccount() == WhirlpoolMeta.getInstance(context).getWhirlpoolPostmix()) {
        utxos = APIFactory.getInstance(context).getUtxosPostMix(true);
    } else {
        utxos = APIFactory.getInstance(context).getUtxos(true);
    }
    for (UTXO utxo : utxos) {
        for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
            utxo2Address.put(outpoint.getTxHash().toString() + "-" + outpoint.getTxOutputN(), outpoint.getAddress());
            debug("CahootsUtil", "outpoint address:" + outpoint.getTxHash().toString() + "-" + outpoint.getTxOutputN() + "," + outpoint.getAddress());
        }
    }
    Transaction transaction = stowaway3.getPSBT().getTransaction();
    HashMap<String, ECKey> keyBag_B = new HashMap<String, ECKey>();
    for (TransactionInput input : transaction.getInputs()) {
        TransactionOutPoint outpoint = input.getOutpoint();
        String key = outpoint.getHash().toString() + "-" + outpoint.getIndex();
        if (utxo2Address.containsKey(key)) {
            String address = utxo2Address.get(key);
            ECKey eckey = SendFactory.getPrivKey(address, stowaway3.getAccount());
            keyBag_B.put(outpoint.toString(), eckey);
        }
    }
    // 
    // 
    // step4: B verif, sig, broadcast
    // 
    // 
    Stowaway stowaway4 = new Stowaway(stowaway3);
    stowaway4.inc(null, null, keyBag_B);
    return stowaway4;
}
Also used : UTXO(com.samourai.wallet.send.UTXO) Transaction(org.bitcoinj.core.Transaction) HashMap(java.util.HashMap) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) ECKey(org.bitcoinj.core.ECKey) TransactionInput(org.bitcoinj.core.TransactionInput) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint)

Example 32 with UTXO

use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.

the class CahootsUtil method doSTONEWALLx2_1.

// 
// counterparty
// 
public Cahoots doSTONEWALLx2_1(STONEWALLx2 stonewall0) throws Exception {
    List<UTXO> utxos = getCahootsUTXO(stonewall0.getCounterpartyAccount());
    Collections.shuffle(utxos);
    debug("CahootsUtil", "BIP84 utxos:" + utxos.size());
    List<UTXO> selectedUTXO = new ArrayList<UTXO>();
    long totalContributedAmount = 0L;
    for (int step = 0; step < 3; step++) {
        if (stonewall0.getCounterpartyAccount() == 0) {
            step = 2;
        }
        List<String> seenTxs = new ArrayList<String>();
        selectedUTXO = new ArrayList<UTXO>();
        totalContributedAmount = 0L;
        for (UTXO utxo : utxos) {
            switch(step) {
                case 0:
                    if (utxo.getPath() != null && utxo.getPath().length() > 3 && utxo.getPath().charAt(2) != '0') {
                        continue;
                    }
                    break;
                case 1:
                    if (utxo.getPath() != null && utxo.getPath().length() > 3 && utxo.getPath().charAt(2) != '1') {
                        continue;
                    }
                    break;
                default:
                    break;
            }
            UTXO _utxo = new UTXO();
            for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
                if (!seenTxs.contains(outpoint.getTxHash().toString())) {
                    _utxo.getOutpoints().add(outpoint);
                    seenTxs.add(outpoint.getTxHash().toString());
                }
            }
            if (_utxo.getOutpoints().size() > 0) {
                selectedUTXO.add(_utxo);
                totalContributedAmount += _utxo.getValue();
                debug("CahootsUtil", "BIP84 selected utxo:" + _utxo.getValue());
            }
            if (totalContributedAmount > stonewall0.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
                break;
            }
        }
        if (totalContributedAmount > stonewall0.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
            break;
        }
    }
    if (!(totalContributedAmount > stonewall0.getSpendAmount() + SamouraiWallet.bDust.longValue())) {
        return null;
    }
    debug("CahootsUtil", "BIP84 selected utxos:" + selectedUTXO.size());
    NetworkParameters params = stonewall0.getParams();
    // 
    // 
    // step1: A utxos -> B (take largest that cover amount)
    // 
    // 
    String zpub = BIP84Util.getInstance(context).getWallet().getAccountAt(stonewall0.getCounterpartyAccount()).zpubstr();
    HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>> inputsA = new HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>>();
    for (UTXO utxo : selectedUTXO) {
        for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
            _TransactionOutPoint _outpoint = new _TransactionOutPoint(outpoint);
            ECKey eckey = SendFactory.getPrivKey(_outpoint.getAddress(), stonewall0.getCounterpartyAccount());
            String path = APIFactory.getInstance(context).getUnspentPaths().get(_outpoint.getAddress());
            inputsA.put(_outpoint, Triple.of(eckey.getPubKey(), stonewall0.getFingerprintCollab(), path));
        }
    }
    HashMap<_TransactionOutput, Triple<byte[], byte[], String>> outputsA = new HashMap<_TransactionOutput, Triple<byte[], byte[], String>>();
    if (stonewall0.getCounterpartyAccount() == WhirlpoolMeta.getInstance(context).getWhirlpoolPostmix()) {
        // contributor mix output
        int idx = AddressFactory.getInstance(context).getHighestPostChangeIdx();
        SegwitAddress segwitAddress0 = BIP84Util.getInstance(context).getAddressAt(stonewall0.getCounterpartyAccount(), 1, idx);
        Pair<Byte, byte[]> pair0 = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress0.getBech32AsString());
        byte[] scriptPubKey_A0 = Bech32Segwit.getScriptPubkey(pair0.getLeft(), pair0.getRight());
        _TransactionOutput output_A0 = new _TransactionOutput(params, null, Coin.valueOf(stonewall0.getSpendAmount()), scriptPubKey_A0);
        outputsA.put(output_A0, Triple.of(segwitAddress0.getECKey().getPubKey(), stonewall0.getFingerprintCollab(), "M/1/" + idx));
        // contributor change output
        ++idx;
        SegwitAddress segwitAddress1 = BIP84Util.getInstance(context).getAddressAt(stonewall0.getCounterpartyAccount(), 1, idx);
        Pair<Byte, byte[]> pair1 = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress1.getBech32AsString());
        byte[] scriptPubKey_A1 = Bech32Segwit.getScriptPubkey(pair1.getLeft(), pair1.getRight());
        _TransactionOutput output_A1 = new _TransactionOutput(params, null, Coin.valueOf(totalContributedAmount - stonewall0.getSpendAmount()), scriptPubKey_A1);
        outputsA.put(output_A1, Triple.of(segwitAddress1.getECKey().getPubKey(), stonewall0.getFingerprintCollab(), "M/1/" + idx));
        stonewall0.setCollabChange(segwitAddress1.getBech32AsString());
    } else {
        // contributor mix output
        int idx = BIP84Util.getInstance(context).getWallet().getAccount(0).getReceive().getAddrIdx();
        SegwitAddress segwitAddress0 = BIP84Util.getInstance(context).getAddressAt(0, 0, idx);
        if (segwitAddress0.getBech32AsString().equalsIgnoreCase(stonewall0.getDestination())) {
            segwitAddress0 = BIP84Util.getInstance(context).getAddressAt(0, 0, idx + 1);
        }
        Pair<Byte, byte[]> pair0 = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress0.getBech32AsString());
        byte[] scriptPubKey_A0 = Bech32Segwit.getScriptPubkey(pair0.getLeft(), pair0.getRight());
        _TransactionOutput output_A0 = new _TransactionOutput(params, null, Coin.valueOf(stonewall0.getSpendAmount()), scriptPubKey_A0);
        outputsA.put(output_A0, Triple.of(segwitAddress0.getECKey().getPubKey(), stonewall0.getFingerprintCollab(), "M/0/" + idx));
        // contributor change output
        idx = BIP84Util.getInstance(context).getWallet().getAccount(0).getChange().getAddrIdx();
        SegwitAddress segwitAddress1 = BIP84Util.getInstance(context).getAddressAt(0, 1, idx);
        Pair<Byte, byte[]> pair1 = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress1.getBech32AsString());
        byte[] scriptPubKey_A1 = Bech32Segwit.getScriptPubkey(pair1.getLeft(), pair1.getRight());
        _TransactionOutput output_A1 = new _TransactionOutput(params, null, Coin.valueOf(totalContributedAmount - stonewall0.getSpendAmount()), scriptPubKey_A1);
        outputsA.put(output_A1, Triple.of(segwitAddress1.getECKey().getPubKey(), stonewall0.getFingerprintCollab(), "M/1/" + idx));
        stonewall0.setCollabChange(segwitAddress1.getBech32AsString());
    }
    STONEWALLx2 stonewall1 = new STONEWALLx2(stonewall0);
    stonewall1.inc(inputsA, outputsA, null);
    return stonewall1;
}
Also used : HashMap(java.util.HashMap) SegwitAddress(com.samourai.wallet.segwit.SegwitAddress) NetworkParameters(org.bitcoinj.core.NetworkParameters) ArrayList(java.util.ArrayList) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) ECKey(org.bitcoinj.core.ECKey) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) Triple(org.apache.commons.lang3.tuple.Triple) UTXO(com.samourai.wallet.send.UTXO)

Example 33 with UTXO

use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.

the class CahootsUtil method getCahootsUTXO.

public static List<UTXO> getCahootsUTXO(int account) {
    List<UTXO> ret = new ArrayList<UTXO>();
    List<UTXO> _utxos = null;
    if (account == WhirlpoolMeta.getInstance(context).getWhirlpoolPostmix()) {
        _utxos = APIFactory.getInstance(context).getUtxosPostMix(true);
    } else {
        _utxos = APIFactory.getInstance(context).getUtxos(true);
    }
    for (UTXO utxo : _utxos) {
        String script = Hex.toHexString(utxo.getOutpoints().get(0).getScriptBytes());
        if (script.startsWith("0014") && APIFactory.getInstance(context).getUnspentPaths().get(utxo.getOutpoints().get(0).getAddress()) != null) {
            ret.add(utxo);
        }
    }
    return ret;
}
Also used : UTXO(com.samourai.wallet.send.UTXO) ArrayList(java.util.ArrayList)

Example 34 with UTXO

use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.

the class CahootsUtil method doStowaway2.

// 
// sender
// 
public Cahoots doStowaway2(Stowaway stowaway1) throws Exception {
    debug("CahootsUtil", "sender account (2):" + stowaway1.getAccount());
    Transaction transaction = stowaway1.getTransaction();
    debug("CahootsUtil", "step2 tx:" + org.spongycastle.util.encoders.Hex.toHexString(transaction.bitcoinSerialize()));
    int nbIncomingInputs = transaction.getInputs().size();
    List<UTXO> utxos = getCahootsUTXO(stowaway1.getAccount());
    // sort in ascending order by value
    Collections.sort(utxos, new UTXO.UTXOComparator());
    Collections.reverse(utxos);
    debug("CahootsUtil", "BIP84 utxos:" + utxos.size());
    List<UTXO> selectedUTXO = new ArrayList<UTXO>();
    int nbTotalSelectedOutPoints = 0;
    long totalSelectedAmount = 0L;
    List<UTXO> lowUTXO = new ArrayList<UTXO>();
    for (UTXO utxo : utxos) {
        if (utxo.getValue() < stowaway1.getSpendAmount()) {
            lowUTXO.add(utxo);
        }
    }
    List<List<UTXO>> listOfLists = new ArrayList<List<UTXO>>();
    Collections.shuffle(lowUTXO);
    listOfLists.add(lowUTXO);
    listOfLists.add(utxos);
    for (List<UTXO> list : listOfLists) {
        selectedUTXO.clear();
        totalSelectedAmount = 0L;
        nbTotalSelectedOutPoints = 0;
        for (UTXO utxo : list) {
            selectedUTXO.add(utxo);
            totalSelectedAmount += utxo.getValue();
            debug("BIP84 selected utxo:", "" + utxo.getValue());
            nbTotalSelectedOutPoints += utxo.getOutpoints().size();
            if (totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
                // discard "extra" utxo, if any
                List<UTXO> _selectedUTXO = new ArrayList<UTXO>();
                Collections.reverse(selectedUTXO);
                int _nbTotalSelectedOutPoints = 0;
                long _totalSelectedAmount = 0L;
                for (UTXO utxoSel : selectedUTXO) {
                    _selectedUTXO.add(utxoSel);
                    _totalSelectedAmount += utxoSel.getValue();
                    debug("CahootsUtil", "BIP84 post selected utxo:" + utxoSel.getValue());
                    _nbTotalSelectedOutPoints += utxoSel.getOutpoints().size();
                    if (_totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, _nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
                        selectedUTXO.clear();
                        selectedUTXO.addAll(_selectedUTXO);
                        totalSelectedAmount = _totalSelectedAmount;
                        nbTotalSelectedOutPoints = _nbTotalSelectedOutPoints;
                        break;
                    }
                }
                break;
            }
        }
        if (totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
            break;
        }
    }
    /*
        if(lowUTXO.size() > 0)    {
            Collections.shuffle(lowUTXO);
            for (UTXO utxo : lowUTXO) {
                selectedUTXO.add(utxo);
                totalSelectedAmount += utxo.getValue();
                debug("BIP84 selected utxo:", "" + utxo.getValue());
                nbTotalSelectedOutPoints += utxo.getOutpoints().size();
                if (totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {

                    // discard "extra" utxo, if any
                    List<UTXO> _selectedUTXO = new ArrayList<UTXO>();
                    Collections.reverse(selectedUTXO);
                    int _nbTotalSelectedOutPoints = 0;
                    long _totalSelectedAmount = 0L;
                    for (UTXO utxoSel : selectedUTXO) {
                        _selectedUTXO.add(utxoSel);
                        _totalSelectedAmount += utxoSel.getValue();
                        debug("CahootsUtil", "BIP84 post selected utxo:" + utxoSel.getValue());
                        _nbTotalSelectedOutPoints += utxoSel.getOutpoints().size();
                        if (_totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, _nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
                            selectedUTXO.clear();
                            selectedUTXO.addAll(_selectedUTXO);
                            totalSelectedAmount = _totalSelectedAmount;
                            nbTotalSelectedOutPoints = _nbTotalSelectedOutPoints;
                            break;
                        }
                    }

                    break;
                }
            }

        }
        if (!(totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue())) {
            selectedUTXO.clear();
            totalSelectedAmount = 0L;
            nbTotalSelectedOutPoints = 0;
            for (UTXO utxo : utxos) {
                selectedUTXO.add(utxo);
                totalSelectedAmount += utxo.getValue();
                debug("BIP84 selected utxo:", "" + utxo.getValue());
                nbTotalSelectedOutPoints += utxo.getOutpoints().size();
                if (totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {

                    // discard "extra" utxo, if any
                    List<UTXO> _selectedUTXO = new ArrayList<UTXO>();
                    Collections.reverse(selectedUTXO);
                    int _nbTotalSelectedOutPoints = 0;
                    long _totalSelectedAmount = 0L;
                    for (UTXO utxoSel : selectedUTXO) {
                        _selectedUTXO.add(utxoSel);
                        _totalSelectedAmount += utxoSel.getValue();
                        debug("CahootsUtil", "BIP84 post selected utxo:" + utxoSel.getValue());
                        _nbTotalSelectedOutPoints += utxoSel.getOutpoints().size();
                        if (_totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, _nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
                            selectedUTXO.clear();
                            selectedUTXO.addAll(_selectedUTXO);
                            totalSelectedAmount = _totalSelectedAmount;
                            nbTotalSelectedOutPoints = _nbTotalSelectedOutPoints;
                            break;
                        }
                    }

                    break;
                }
            }
        }
        */
    if (!(totalSelectedAmount > FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue() + stowaway1.getSpendAmount() + SamouraiWallet.bDust.longValue())) {
        return null;
    }
    debug("CahootsUtil", "BIP84 selected utxos:" + selectedUTXO.size());
    long fee = FeeUtil.getInstance().estimatedFeeSegwit(0, 0, nbTotalSelectedOutPoints + nbIncomingInputs, 2).longValue();
    debug("CahootsUtil", "fee:" + fee);
    NetworkParameters params = stowaway1.getParams();
    // 
    // 
    // step2: B verif, utxos -> A (take smallest that cover amount)
    // 
    // 
    String zpub = BIP84Util.getInstance(context).getWallet().getAccountAt(stowaway1.getAccount()).zpubstr();
    HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>> inputsB = new HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>>();
    for (UTXO utxo : selectedUTXO) {
        for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
            _TransactionOutPoint _outpoint = new _TransactionOutPoint(outpoint);
            ECKey eckey = SendFactory.getPrivKey(_outpoint.getAddress(), stowaway1.getAccount());
            String path = APIFactory.getInstance(context).getUnspentPaths().get(_outpoint.getAddress());
            inputsB.put(_outpoint, Triple.of(eckey.getPubKey(), stowaway1.getFingerprint(), path));
        }
    }
    debug("CahootsUtil", "inputsB:" + inputsB.size());
    // change output
    SegwitAddress segwitAddress = null;
    int idx = 0;
    if (stowaway1.getAccount() == WhirlpoolMeta.getInstance(context).getWhirlpoolPostmix()) {
        idx = AddressFactory.getInstance(context).getHighestPostChangeIdx();
        HD_Address addr = BIP84Util.getInstance(context).getWallet().getAccountAt(stowaway1.getAccount()).getChange().getAddressAt(idx);
        segwitAddress = new SegwitAddress(addr.getPubKey(), SamouraiWallet.getInstance().getCurrentNetworkParams());
    } else {
        idx = BIP84Util.getInstance(context).getWallet().getAccount(0).getChange().getAddrIdx();
        segwitAddress = BIP84Util.getInstance(context).getAddressAt(1, idx);
    }
    HashMap<_TransactionOutput, Triple<byte[], byte[], String>> outputsB = new HashMap<_TransactionOutput, Triple<byte[], byte[], String>>();
    Pair<Byte, byte[]> pair = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress.getBech32AsString());
    byte[] scriptPubKey_B = Bech32Segwit.getScriptPubkey(pair.getLeft(), pair.getRight());
    _TransactionOutput output_B0 = new _TransactionOutput(params, null, Coin.valueOf((totalSelectedAmount - stowaway1.getSpendAmount()) - fee), scriptPubKey_B);
    outputsB.put(output_B0, Triple.of(segwitAddress.getECKey().getPubKey(), stowaway1.getFingerprint(), "M/1/" + idx));
    debug("CahootsUtil", "outputsB:" + outputsB.size());
    Stowaway stowaway2 = new Stowaway(stowaway1);
    stowaway2.inc(inputsB, outputsB, null);
    stowaway2.setFeeAmount(fee);
    return stowaway2;
}
Also used : HashMap(java.util.HashMap) SegwitAddress(com.samourai.wallet.segwit.SegwitAddress) ArrayList(java.util.ArrayList) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) ECKey(org.bitcoinj.core.ECKey) ArrayList(java.util.ArrayList) List(java.util.List) HD_Address(com.samourai.wallet.hd.HD_Address) NetworkParameters(org.bitcoinj.core.NetworkParameters) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) Triple(org.apache.commons.lang3.tuple.Triple) UTXO(com.samourai.wallet.send.UTXO) Transaction(org.bitcoinj.core.Transaction)

Example 35 with UTXO

use of com.samourai.wallet.send.UTXO in project samourai-wallet-android by Samourai-Wallet.

the class CahootsUtil method doStowaway1.

// 
// receiver
// 
public Cahoots doStowaway1(Stowaway stowaway0) throws Exception {
    List<UTXO> utxos = getCahootsUTXO(0);
    // sort in descending order by value
    Collections.sort(utxos, new UTXO.UTXOComparator());
    debug("CahootsUtil", "BIP84 utxos:" + utxos.size());
    List<UTXO> selectedUTXO = new ArrayList<UTXO>();
    long totalContributedAmount = 0L;
    List<UTXO> highUTXO = new ArrayList<UTXO>();
    for (UTXO utxo : utxos) {
        if (utxo.getValue() > stowaway0.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
            highUTXO.add(utxo);
        }
    }
    if (highUTXO.size() > 0) {
        SecureRandom random = new SecureRandom();
        UTXO utxo = highUTXO.get(random.nextInt(highUTXO.size()));
        debug("CahootsUtil", "BIP84 selected random utxo:" + utxo.getValue());
        selectedUTXO.add(utxo);
        totalContributedAmount = utxo.getValue();
    }
    if (selectedUTXO.size() == 0) {
        for (UTXO utxo : utxos) {
            selectedUTXO.add(utxo);
            totalContributedAmount += utxo.getValue();
            debug("CahootsUtil", "BIP84 selected utxo:" + utxo.getValue());
            if (totalContributedAmount > stowaway0.getSpendAmount() + SamouraiWallet.bDust.longValue()) {
                break;
            }
        }
    }
    if (!(totalContributedAmount > stowaway0.getSpendAmount() + SamouraiWallet.bDust.longValue())) {
        return null;
    }
    debug("CahootsUtil", "BIP84 selected utxos:" + selectedUTXO.size());
    NetworkParameters params = stowaway0.getParams();
    // 
    // 
    // step1: A utxos -> B (take largest that cover amount)
    // 
    // 
    String zpub = BIP84Util.getInstance(context).getWallet().getAccount(0).zpubstr();
    HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>> inputsA = new HashMap<_TransactionOutPoint, Triple<byte[], byte[], String>>();
    for (UTXO utxo : selectedUTXO) {
        for (MyTransactionOutPoint outpoint : utxo.getOutpoints()) {
            _TransactionOutPoint _outpoint = new _TransactionOutPoint(outpoint);
            ECKey eckey = SendFactory.getPrivKey(_outpoint.getAddress(), 0);
            String path = APIFactory.getInstance(context).getUnspentPaths().get(_outpoint.getAddress());
            inputsA.put(_outpoint, Triple.of(eckey.getPubKey(), stowaway0.getFingerprintCollab(), path));
        }
    }
    // destination output
    int idx = BIP84Util.getInstance(context).getWallet().getAccount(0).getReceive().getAddrIdx();
    SegwitAddress segwitAddress = BIP84Util.getInstance(context).getAddressAt(0, idx);
    HashMap<_TransactionOutput, Triple<byte[], byte[], String>> outputsA = new HashMap<_TransactionOutput, Triple<byte[], byte[], String>>();
    // byte[] scriptPubKey_A = getScriptPubKey("tb1qewwlc2dksuez3zauf38d82m7uqd4ewkf2avdl8", params);
    Pair<Byte, byte[]> pair = Bech32Segwit.decode(SamouraiWallet.getInstance().isTestNet() ? "tb" : "bc", segwitAddress.getBech32AsString());
    byte[] scriptPubKey_A = Bech32Segwit.getScriptPubkey(pair.getLeft(), pair.getRight());
    _TransactionOutput output_A0 = new _TransactionOutput(params, null, Coin.valueOf(stowaway0.getSpendAmount()), scriptPubKey_A);
    outputsA.put(output_A0, Triple.of(segwitAddress.getECKey().getPubKey(), stowaway0.getFingerprintCollab(), "M/0/" + idx));
    stowaway0.setDestination(segwitAddress.getBech32AsString());
    Stowaway stowaway1 = new Stowaway(stowaway0);
    stowaway1.inc(inputsA, outputsA, null);
    return stowaway1;
}
Also used : HashMap(java.util.HashMap) SegwitAddress(com.samourai.wallet.segwit.SegwitAddress) NetworkParameters(org.bitcoinj.core.NetworkParameters) ArrayList(java.util.ArrayList) SecureRandom(java.security.SecureRandom) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) ECKey(org.bitcoinj.core.ECKey) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) Triple(org.apache.commons.lang3.tuple.Triple) UTXO(com.samourai.wallet.send.UTXO)

Aggregations

UTXO (com.samourai.wallet.send.UTXO)35 MyTransactionOutPoint (com.samourai.wallet.send.MyTransactionOutPoint)33 ArrayList (java.util.ArrayList)23 HashMap (java.util.HashMap)19 Transaction (org.bitcoinj.core.Transaction)17 IOException (java.io.IOException)14 TransactionOutPoint (org.bitcoinj.core.TransactionOutPoint)14 BlockedUTXO (com.samourai.wallet.send.BlockedUTXO)13 BigInteger (java.math.BigInteger)13 MnemonicException (org.bitcoinj.crypto.MnemonicException)13 JSONException (org.json.JSONException)13 JSONObject (org.json.JSONObject)13 ECKey (org.bitcoinj.core.ECKey)12 TransactionInput (org.bitcoinj.core.TransactionInput)10 Intent (android.content.Intent)9 SegwitAddress (com.samourai.wallet.segwit.SegwitAddress)9 Script (org.bitcoinj.script.Script)9 AlertDialog (android.app.AlertDialog)8 DecryptionException (com.samourai.wallet.crypto.DecryptionException)8 DialogInterface (android.content.DialogInterface)6