Search in sources :

Example 21 with PaymentCode

use of com.samourai.wallet.bip47.rpc.PaymentCode in project samourai-wallet-android by Samourai-Wallet.

the class JobRefreshService method onHandleWork.

@Override
protected void onHandleWork(@NonNull Intent intent) {
    boolean dragged = intent.getBooleanExtra("dragged", false);
    boolean launch = intent.getBooleanExtra("launch", false);
    boolean notifTx = intent.getBooleanExtra("notifTx", false);
    Log.d("JobRefreshService", "doInBackground()");
    APIFactory.getInstance(this.getApplicationContext()).stayingAlive();
    APIFactory.getInstance(this.getApplicationContext()).initWallet();
    try {
        int acc = 0;
        if (AddressFactory.getInstance().getHighestTxReceiveIdx(acc) > HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getReceive().getAddrIdx()) {
            HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getReceive().setAddrIdx(AddressFactory.getInstance().getHighestTxReceiveIdx(acc));
        }
        if (AddressFactory.getInstance().getHighestTxChangeIdx(acc) > HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getChange().getAddrIdx()) {
            HD_WalletFactory.getInstance(this.getApplicationContext()).get().getAccount(acc).getChange().setAddrIdx(AddressFactory.getInstance().getHighestTxChangeIdx(acc));
        }
        if (AddressFactory.getInstance().getHighestBIP49ReceiveIdx() > BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().getAddrIdx()) {
            BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().setAddrIdx(AddressFactory.getInstance().getHighestBIP49ReceiveIdx());
        }
        if (AddressFactory.getInstance().getHighestBIP49ChangeIdx() > BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().getAddrIdx()) {
            BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().setAddrIdx(AddressFactory.getInstance().getHighestBIP49ChangeIdx());
        }
        if (AddressFactory.getInstance().getHighestBIP84ReceiveIdx() > BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().getAddrIdx()) {
            BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getReceive().setAddrIdx(AddressFactory.getInstance().getHighestBIP84ReceiveIdx());
        }
        if (AddressFactory.getInstance().getHighestBIP84ChangeIdx() > BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().getAddrIdx()) {
            BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).getChange().setAddrIdx(AddressFactory.getInstance().getHighestBIP84ChangeIdx());
        }
    } catch (IOException | MnemonicException.MnemonicLengthException | NullPointerException ioe) {
        ioe.printStackTrace();
    } finally {
        Intent _intent = new Intent("com.samourai.wallet.BalanceFragment.DISPLAY");
        LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(_intent);
    }
    PrefsUtil.getInstance(this.getApplicationContext()).setValue(PrefsUtil.FIRST_RUN, false);
    if (notifTx && !AppUtil.getInstance(this.getApplicationContext()).isOfflineMode()) {
        // 
        try {
            PaymentCode pcode = BIP47Util.getInstance(this.getApplicationContext()).getPaymentCode();
            // Log.i("BalanceFragment", "payment code:" + pcode.toString());
            // Log.i("BalanceFragment", "notification address:" + pcode.notificationAddress().getAddressString());
            APIFactory.getInstance(this.getApplicationContext()).getNotifAddress(pcode.notificationAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).getAddressString());
        } catch (AddressFormatException afe) {
            afe.printStackTrace();
            Toast.makeText(this.getApplicationContext(), "HD wallet error", Toast.LENGTH_SHORT).show();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // 
        // check on outgoing payment code notification tx
        // 
        List<Pair<String, String>> outgoingUnconfirmed = BIP47Meta.getInstance().getOutgoingUnconfirmed();
        // Log.i("BalanceFragment", "outgoingUnconfirmed:" + outgoingUnconfirmed.size());
        for (Pair<String, String> pair : outgoingUnconfirmed) {
            // Log.i("BalanceFragment", "outgoing payment code:" + pair.getLeft());
            // Log.i("BalanceFragment", "outgoing payment code tx:" + pair.getRight());
            int confirmations = APIFactory.getInstance(this.getApplicationContext()).getNotifTxConfirmations(pair.getRight());
            if (confirmations > 0) {
                BIP47Meta.getInstance().setOutgoingStatus(pair.getLeft(), BIP47Meta.STATUS_SENT_CFM);
            }
            if (confirmations == -1) {
                BIP47Meta.getInstance().setOutgoingStatus(pair.getLeft(), BIP47Meta.STATUS_NOT_SENT);
            }
        }
        Intent _intent = new Intent("com.samourai.wallet.MainActivity2.RESTART_SERVICE");
        LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(_intent);
    }
    if (launch) {
        if (PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.GUID_V, 0) < 4) {
            Log.i("JobIntentService", "guid_v < 4");
            try {
                String _guid = AccessFactory.getInstance(this.getApplicationContext()).createGUID();
                String _hash = AccessFactory.getInstance(this.getApplicationContext()).getHash(_guid, new CharSequenceX(AccessFactory.getInstance(this.getApplicationContext()).getPIN()), AESUtil.DefaultPBKDF2Iterations);
                PayloadUtil.getInstance(this.getApplicationContext()).saveWalletToJSON(new CharSequenceX(_guid + AccessFactory.getInstance().getPIN()));
                PrefsUtil.getInstance(this.getApplicationContext()).setValue(PrefsUtil.ACCESS_HASH, _hash);
                PrefsUtil.getInstance(this.getApplicationContext()).setValue(PrefsUtil.ACCESS_HASH2, _hash);
                Log.i("JobIntentService", "guid_v == 4");
            } catch (MnemonicException.MnemonicLengthException | IOException | JSONException | DecryptionException e) {
                ;
            }
        }
        if (!PrefsUtil.getInstance(this.getApplicationContext().getApplicationContext()).getValue(PrefsUtil.XPUB44LOCK, false)) {
            try {
                String[] s = HD_WalletFactory.getInstance(this.getApplicationContext()).get().getXPUBs();
                APIFactory.getInstance(this.getApplicationContext()).lockXPUB(s[0], 44, null);
            } catch (IOException | MnemonicException.MnemonicLengthException e) {
                ;
            }
        }
        if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUB49LOCK, false)) {
            String ypub = BIP49Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).ypubstr();
            APIFactory.getInstance(this.getApplicationContext()).lockXPUB(ypub, 49, null);
        }
        if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUB84LOCK, false)) {
            String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccount(0).zpubstr();
            APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, null);
        }
        if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUBPRELOCK, false)) {
            String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccountAt(WhirlpoolMeta.getInstance(this.getApplicationContext()).getWhirlpoolPremixAccount()).zpubstr();
            APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, PrefsUtil.XPUBPRELOCK);
        }
        if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUBPOSTLOCK, false)) {
            String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccountAt(WhirlpoolMeta.getInstance(this.getApplicationContext()).getWhirlpoolPostmix()).zpubstr();
            APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, PrefsUtil.XPUBPRELOCK);
        }
        if (!PrefsUtil.getInstance(this.getApplicationContext()).getValue(PrefsUtil.XPUBBADBANKLOCK, false)) {
            String zpub = BIP84Util.getInstance(this.getApplicationContext()).getWallet().getAccountAt(WhirlpoolMeta.getInstance(this.getApplicationContext()).getWhirlpoolBadBank()).zpubstr();
            APIFactory.getInstance(this.getApplicationContext()).lockXPUB(zpub, 84, PrefsUtil.XPUBBADBANKLOCK);
        }
    } else {
        try {
            PayloadUtil.getInstance(this.getApplicationContext()).saveWalletToJSON(new CharSequenceX(AccessFactory.getInstance(this.getApplicationContext()).getGUID() + AccessFactory.getInstance(this.getApplicationContext()).getPIN()));
        } catch (Exception ignored) {
            ;
        }
    }
    Intent _intent = new Intent("com.samourai.wallet.BalanceFragment.DISPLAY");
    LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(_intent);
}
Also used : AddressFormatException(org.bitcoinj.core.AddressFormatException) PaymentCode(com.samourai.wallet.bip47.rpc.PaymentCode) CharSequenceX(com.samourai.wallet.util.CharSequenceX) JSONException(org.json.JSONException) Intent(android.content.Intent) IOException(java.io.IOException) MnemonicException(org.bitcoinj.crypto.MnemonicException) JSONException(org.json.JSONException) DecryptionException(com.samourai.wallet.crypto.DecryptionException) AddressFormatException(org.bitcoinj.core.AddressFormatException) IOException(java.io.IOException) DecryptionException(com.samourai.wallet.crypto.DecryptionException) Pair(org.apache.commons.lang3.tuple.Pair)

Example 22 with PaymentCode

use of com.samourai.wallet.bip47.rpc.PaymentCode in project samourai-wallet-android by Samourai-Wallet.

the class RicochetMeta method script.

public JSONObject script(long spendAmount, long feePerKBAmount, String strDestination, int nbHops, String strPCode, boolean samouraiFeeViaBIP47, boolean useTimeLock) {
    JSONObject jObj = new JSONObject();
    try {
        BigInteger biSpend = BigInteger.valueOf(spendAmount);
        // default 4 hops min. for base fee, each additional hop 0.001
        BigInteger biSamouraiFee = BigInteger.valueOf(samouraiFeeAmountV2.longValue() * ((nbHops - defaultNbHops) + 1));
        BigInteger biFeePerKB = BigInteger.valueOf(feePerKBAmount);
        long latestBlock = APIFactory.getInstance(context).getLatestBlockHeight();
        long nTimeLock = 0L;
        if (useTimeLock && latestBlock > 0L) {
            nTimeLock = latestBlock;
        }
        jObj.put("ts", System.currentTimeMillis() / 1000L);
        jObj.put("hops", nbHops);
        jObj.put("spend_amount", biSpend.longValue());
        jObj.put("samourai_fee", biSamouraiFee.longValue());
        jObj.put("samourai_fee_via_bip47", samouraiFeeViaBIP47);
        jObj.put("feeKB", biFeePerKB.longValue());
        jObj.put("destination", strDestination);
        if (strPCode != null) {
            jObj.put("pcode", strPCode);
        }
        if (useTimeLock) {
            jObj.put("nTimeLock", nTimeLock);
        }
        JSONObject jHop = new JSONObject();
        JSONArray jHops = new JSONArray();
        int hopSz = 0;
        if (samouraiFeeViaBIP47) {
            hopSz = FeeUtil.getInstance().estimatedSize(1, 2);
        } else {
            hopSz = FeeUtil.getInstance().estimatedSize(1, 1);
        }
        BigInteger biFeePerHop = FeeUtil.getInstance().calculateFee(hopSz, biFeePerKB);
        Pair<List<UTXO>, BigInteger> pair = getHop0UTXO(spendAmount, nbHops, biFeePerHop.longValue(), samouraiFeeViaBIP47);
        List<UTXO> utxos = pair.getLeft();
        long totalValueSelected = 0L;
        for (UTXO u : utxos) {
            totalValueSelected += u.getValue();
        }
        // Log.d("RicochetMeta", "totalValueSelected (return):" + totalValueSelected);
        // hop0 'leaves' wallet, change returned to wallet
        BigInteger hop0 = biSpend.add(biSamouraiFee).add(biFeePerHop.multiply(BigInteger.valueOf((long) nbHops)));
        // BigInteger hop0Fee = FeeUtil.getInstance().calculateFee(hop0sz, biFeePerKB);
        BigInteger hop0Fee = pair.getRight();
        // Log.d("RicochetMeta", "hop0Fee (return):" + hop0Fee.longValue());
        Transaction txHop0 = getHop0Tx(utxos, hop0.longValue(), getDestinationAddress(index), hop0Fee.longValue(), samouraiFeeViaBIP47, nTimeLock);
        if (txHop0 == null) {
            return null;
        }
        // Log.d("RicochetMeta", "searching for:" + getDestinationAddress(index));
        int prevTxN = 0;
        for (int i = 0; i < txHop0.getOutputs().size(); i++) {
            Script script = txHop0.getOutputs().get(i).getScriptPubKey();
            // Log.d("RicochetMeta", "script:" + Hex.toHexString(script.getProgram()));
            String address = null;
            if (Hex.toHexString(script.getProgram()).startsWith("0014")) {
                String hrp = null;
                if (SamouraiWallet.getInstance().getCurrentNetworkParams() instanceof TestNet3Params) {
                    hrp = "tb";
                } else {
                    hrp = "bc";
                }
                try {
                    String _script = Hex.toHexString(script.getProgram());
                    address = Bech32Segwit.encode(hrp, (byte) 0x00, Hex.decode(_script.substring(4).getBytes()));
                } catch (Exception e) {
                    ;
                }
            // Log.d("RicochetMeta", "bech32:" + address);
            } else {
                address = new Script(script.getProgram()).getToAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
            // Log.d("RicochetMeta", "address from script:" + address);
            }
            if (address.equals(getDestinationAddress(index))) {
                prevTxN = i;
                // Log.d("RicochetMeta", "tx output n:" + prevTxN);
                break;
            }
        }
        jHop.put("seq", 0);
        jHop.put("spend_amount", hop0.longValue());
        jHop.put("fee", hop0Fee.longValue());
        jHop.put("fee_per_hop", biFeePerHop.longValue());
        jHop.put("index", index);
        jHop.put("destination", getDestinationAddress(index));
        // Log.d("RicochetMeta", "destination:" + getDestinationAddress(index));
        int prevIndex = index;
        index++;
        jHop.put("tx", new String(Hex.encode(txHop0.bitcoinSerialize())));
        jHop.put("hash", txHop0.getHash().toString());
        if (useTimeLock) {
            jHop.put("nTimeLock", nTimeLock);
        }
        jHops.put(jHop);
        List<Pair<String, Long>> samouraiFees = new ArrayList<Pair<String, Long>>();
        if (samouraiFeeViaBIP47) {
            long baseVal = samouraiFeeAmountV2.longValue() / 4L;
            long totalVal = 0L;
            SecureRandom random = new SecureRandom();
            int _outgoingIdx = BIP47Meta.getInstance().getOutgoingIdx(BIP47Meta.strSamouraiDonationPCode);
            for (int i = 0; i < 4; i++) {
                int val = random.nextInt(25000);
                int sign = random.nextInt(1);
                if (sign == 0) {
                    val *= -1L;
                }
                long feeVal = 0L;
                if (i == 3) {
                    feeVal = samouraiFeeAmountV2.longValue() - totalVal;
                } else {
                    feeVal = baseVal + val;
                    totalVal += feeVal;
                }
                // 
                try {
                    PaymentCode pcode = new PaymentCode(BIP47Meta.strSamouraiDonationPCode);
                    PaymentAddress paymentAddress = BIP47Util.getInstance(context).getSendAddress(pcode, _outgoingIdx + i);
                    // String strAddress = paymentAddress.getSendECKey().toAddress(SamouraiWallet.getInstance().getCurrentNetworkParams()).toString();
                    // 
                    // derive as bech32
                    // 
                    SegwitAddress segwitAddress = new SegwitAddress(paymentAddress.getSendECKey().getPubKey(), SamouraiWallet.getInstance().getCurrentNetworkParams());
                    String strAddress = segwitAddress.getBech32AsString();
                    samouraiFees.add(Pair.of(strAddress, feeVal));
                // samouraiFees.add(Pair.of(strAddress, 200000L / 4L));
                } catch (Exception e) {
                    samouraiFees.add(Pair.of(SendNotifTxFactory.SAMOURAI_NOTIF_TX_FEE_ADDRESS, feeVal));
                }
            }
        }
        Transaction txHop = null;
        String prevTxHash = txHop0.getHash().toString();
        String prevScriptPubKey = Hex.toHexString(txHop0.getOutput(prevTxN).getScriptPubKey().getProgram());
        BigInteger remainingSamouraiFee = BigInteger.ZERO;
        long prevSpendValue = hop0.longValue();
        if (!samouraiFeeViaBIP47) {
            prevSpendValue -= biSamouraiFee.longValue();
        } else {
            remainingSamouraiFee = samouraiFeeAmountV2;
        }
        int _hop = 0;
        for (int i = (nbHops - 1); i >= 0; i--) {
            _hop++;
            BigInteger hopx = null;
            if (samouraiFeeViaBIP47) {
                remainingSamouraiFee = remainingSamouraiFee.subtract(BigInteger.valueOf(samouraiFees.get(_hop - 1).getRight()));
                hopx = biSpend.add(biFeePerHop.multiply(BigInteger.valueOf((long) i))).add(remainingSamouraiFee);
            } else {
                hopx = biSpend.add(biFeePerHop.multiply(BigInteger.valueOf((long) i)));
            }
            if (useTimeLock && latestBlock > 0L) {
                nTimeLock = latestBlock + _hop;
            }
            // Log.d("RicochetMeta", "doing hop:" + _hop);
            if (samouraiFeeViaBIP47 && ((_hop - 1) < 4)) {
                txHop = getHopTx(prevTxHash, prevTxN, prevIndex, prevSpendValue, hopx.longValue(), _hop < nbHops ? getDestinationAddress(index) : strDestination, samouraiFees.get(_hop - 1), nTimeLock);
            } else {
                txHop = getHopTx(prevTxHash, prevTxN, prevIndex, prevSpendValue, hopx.longValue(), _hop < nbHops ? getDestinationAddress(index) : strDestination, null, nTimeLock);
            }
            if (txHop == null) {
                return null;
            }
            jHop = new JSONObject();
            jHop.put("seq", (nbHops - i));
            jHop.put("spend_amount", hopx.longValue());
            jHop.put("fee", biFeePerHop.longValue());
            jHop.put("prev_tx_hash", prevTxHash);
            jHop.put("prev_tx_n", prevTxN);
            jHop.put("prev_spend_value", prevSpendValue);
            jHop.put("script", prevScriptPubKey);
            jHop.put("tx", new String(Hex.encode(txHop.bitcoinSerialize())));
            jHop.put("hash", txHop.getHash().toString());
            if (useTimeLock) {
                jHop.put("nTimeLock", nTimeLock);
            }
            if (_hop < nbHops) {
                jHop.put("index", index);
                jHop.put("destination", getDestinationAddress(index));
                // Log.d("RicochetMeta", "destination:" + getDestinationAddress(index));
                prevIndex = index;
                index++;
            } else {
                jHop.put("destination", strDestination);
            // Log.d("RicochetMeta", "destination:" + strDestination);
            }
            if (samouraiFeeViaBIP47) {
                jObj.put("samourai_fee_address", samouraiFees.get(_hop - 1).getLeft());
                jObj.put("samourai_fee_amount", samouraiFees.get(_hop - 1).getRight());
            }
            jHops.put(jHop);
            prevTxHash = txHop.getHash().toString();
            prevTxN = 0;
            prevSpendValue = hopx.longValue();
            prevScriptPubKey = Hex.toHexString(txHop.getOutputs().get(0).getScriptPubKey().getProgram());
        }
        jObj.put("hops", jHops);
        BigInteger totalAmount = hop0.add(hop0Fee);
        jObj.put("total_spend", totalAmount.longValue());
    } catch (JSONException je) {
        return null;
    }
    System.out.println("RicochetMeta:" + jObj.toString());
    return jObj;
}
Also used : Script(org.bitcoinj.script.Script) PaymentCode(com.samourai.wallet.bip47.rpc.PaymentCode) SegwitAddress(com.samourai.wallet.segwit.SegwitAddress) JSONArray(org.json.JSONArray) ArrayList(java.util.ArrayList) SecureRandom(java.security.SecureRandom) JSONException(org.json.JSONException) PaymentAddress(com.samourai.wallet.bip47.rpc.PaymentAddress) MyTransactionOutPoint(com.samourai.wallet.send.MyTransactionOutPoint) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) JSONException(org.json.JSONException) ScriptException(org.bitcoinj.script.ScriptException) MnemonicException(org.bitcoinj.crypto.MnemonicException) IOException(java.io.IOException) UTXO(com.samourai.wallet.send.UTXO) TestNet3Params(org.bitcoinj.params.TestNet3Params) JSONObject(org.json.JSONObject) Transaction(org.bitcoinj.core.Transaction) BigInteger(java.math.BigInteger) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Pair(org.apache.commons.lang3.tuple.Pair)

Aggregations

PaymentCode (com.samourai.wallet.bip47.rpc.PaymentCode)21 IOException (java.io.IOException)15 MnemonicException (org.bitcoinj.crypto.MnemonicException)15 JSONException (org.json.JSONException)14 PaymentAddress (com.samourai.wallet.bip47.rpc.PaymentAddress)12 ArrayList (java.util.ArrayList)10 AddressFormatException (org.bitcoinj.core.AddressFormatException)10 MyTransactionOutPoint (com.samourai.wallet.send.MyTransactionOutPoint)9 Intent (android.content.Intent)8 DecryptionException (com.samourai.wallet.crypto.DecryptionException)8 ECKey (org.bitcoinj.core.ECKey)8 InvalidKeyException (java.security.InvalidKeyException)7 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)7 NoSuchProviderException (java.security.NoSuchProviderException)7 InvalidKeySpecException (java.security.spec.InvalidKeySpecException)7 CharSequenceX (com.samourai.wallet.util.CharSequenceX)6 SegwitAddress (com.samourai.wallet.segwit.SegwitAddress)5 Script (org.bitcoinj.script.Script)5 JSONObject (org.json.JSONObject)5 NotSecp256k1Exception (com.samourai.wallet.bip47.rpc.NotSecp256k1Exception)4