Search in sources :

Example 1 with UTXO

use of org.bitcoinj.core.UTXO in project bitcoin-wallet by bitcoin-wallet.

the class SweepWalletFragment method requestWalletBalance.

private void requestWalletBalance() {
    ProgressDialogFragment.showProgress(fragmentManager, getString(R.string.sweep_wallet_fragment_request_wallet_balance_progress));
    final RequestWalletBalanceTask.ResultCallback callback = new RequestWalletBalanceTask.ResultCallback() {

        @Override
        public void onResult(final Set<UTXO> utxos) {
            ProgressDialogFragment.dismissProgress(fragmentManager);
            // Filter UTXOs we've already spent and sort the rest.
            final Set<Transaction> walletTxns = application.getWallet().getTransactions(false);
            final Set<UTXO> sortedUtxos = new TreeSet<>(UTXO_COMPARATOR);
            for (final UTXO utxo : utxos) if (!utxoSpentBy(walletTxns, utxo))
                sortedUtxos.add(utxo);
            // Fake transaction funding the wallet to sweep.
            final Map<Sha256Hash, Transaction> fakeTxns = new HashMap<>();
            for (final UTXO utxo : sortedUtxos) {
                Transaction fakeTx = fakeTxns.get(utxo.getHash());
                if (fakeTx == null) {
                    fakeTx = new FakeTransaction(Constants.NETWORK_PARAMETERS, utxo.getHash());
                    fakeTx.getConfidence().setConfidenceType(ConfidenceType.BUILDING);
                    fakeTxns.put(fakeTx.getHash(), fakeTx);
                }
                final TransactionOutput fakeOutput = new TransactionOutput(Constants.NETWORK_PARAMETERS, fakeTx, utxo.getValue(), utxo.getScript().getProgram());
                // Fill with output dummies as needed.
                while (fakeTx.getOutputs().size() < utxo.getIndex()) fakeTx.addOutput(new TransactionOutput(Constants.NETWORK_PARAMETERS, fakeTx, Coin.NEGATIVE_SATOSHI, new byte[] {}));
                // Add the actual output we will spend later.
                fakeTx.addOutput(fakeOutput);
            }
            walletToSweep.clearTransactions(0);
            for (final Transaction tx : fakeTxns.values()) walletToSweep.addWalletTransaction(new WalletTransaction(WalletTransaction.Pool.UNSPENT, tx));
            log.info("built wallet to sweep:\n{}", walletToSweep.toString(false, true, false, null));
            updateView();
        }

        private boolean utxoSpentBy(final Set<Transaction> transactions, final UTXO utxo) {
            for (final Transaction tx : transactions) {
                for (final TransactionInput input : tx.getInputs()) {
                    final TransactionOutPoint outpoint = input.getOutpoint();
                    if (outpoint.getHash().equals(utxo.getHash()) && outpoint.getIndex() == utxo.getIndex())
                        return true;
                }
            }
            return false;
        }

        @Override
        public void onFail(final int messageResId, final Object... messageArgs) {
            ProgressDialogFragment.dismissProgress(fragmentManager);
            final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.sweep_wallet_fragment_request_wallet_balance_failed_title);
            dialog.setMessage(getString(messageResId, messageArgs));
            dialog.setPositiveButton(R.string.button_retry, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(final DialogInterface dialog, final int which) {
                    requestWalletBalance();
                }
            });
            dialog.setNegativeButton(R.string.button_dismiss, null);
            dialog.show();
        }
    };
    final Address address = walletToSweep.getImportedKeys().iterator().next().toAddress(Constants.NETWORK_PARAMETERS);
    new RequestWalletBalanceTask(backgroundHandler, callback).requestWalletBalance(activity.getAssets(), address);
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) TransactionOutput(org.bitcoinj.core.TransactionOutput) Address(org.bitcoinj.core.Address) HashMap(java.util.HashMap) DialogInterface(android.content.DialogInterface) Sha256Hash(org.bitcoinj.core.Sha256Hash) TransactionInput(org.bitcoinj.core.TransactionInput) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint) UTXO(org.bitcoinj.core.UTXO) Transaction(org.bitcoinj.core.Transaction) WalletTransaction(org.bitcoinj.wallet.WalletTransaction) TreeSet(java.util.TreeSet) WalletTransaction(org.bitcoinj.wallet.WalletTransaction) DialogBuilder(de.schildbach.wallet.ui.DialogBuilder) TransactionOutPoint(org.bitcoinj.core.TransactionOutPoint)

Example 2 with UTXO

use of org.bitcoinj.core.UTXO in project bitcoin-wallet by bitcoin-wallet.

the class RequestWalletBalanceTask method requestWalletBalance.

public void requestWalletBalance(final AssetManager assets, final Address address) {
    backgroundHandler.post(new Runnable() {

        @Override
        public void run() {
            org.bitcoinj.core.Context.propagate(Constants.CONTEXT);
            try {
                final List<ElectrumServer> servers = loadElectrumServers(assets.open(Constants.Files.ELECTRUM_SERVERS_FILENAME));
                final ElectrumServer server = servers.get(new Random().nextInt(servers.size()));
                log.info("trying to request wallet balance from {}: {}", server.socketAddress, address);
                final Socket socket;
                if (server.type == ElectrumServer.Type.TLS) {
                    final SocketFactory sf = sslTrustAllCertificates();
                    socket = sf.createSocket(server.socketAddress.getHostName(), server.socketAddress.getPort());
                    final SSLSession sslSession = ((SSLSocket) socket).getSession();
                    final Certificate certificate = sslSession.getPeerCertificates()[0];
                    final String certificateFingerprint = sslCertificateFingerprint(certificate);
                    if (server.certificateFingerprint == null) {
                        // signed by CA
                        if (!HttpsURLConnection.getDefaultHostnameVerifier().verify(server.socketAddress.getHostName(), sslSession))
                            throw new SSLHandshakeException("Expected " + server.socketAddress.getHostName() + ", got " + sslSession.getPeerPrincipal());
                    } else {
                        // self-signed
                        if (!certificateFingerprint.equals(server.certificateFingerprint))
                            throw new SSLHandshakeException("Expected " + server.certificateFingerprint + ", got " + certificateFingerprint);
                    }
                } else if (server.type == ElectrumServer.Type.TCP) {
                    socket = new Socket();
                    socket.connect(server.socketAddress, 5000);
                } else {
                    throw new IllegalStateException("Cannot handle: " + server.type);
                }
                final BufferedSink sink = Okio.buffer(Okio.sink(socket));
                sink.timeout().timeout(5000, TimeUnit.MILLISECONDS);
                final BufferedSource source = Okio.buffer(Okio.source(socket));
                source.timeout().timeout(5000, TimeUnit.MILLISECONDS);
                final Moshi moshi = new Moshi.Builder().build();
                final JsonAdapter<JsonRpcRequest> requestAdapter = moshi.adapter(JsonRpcRequest.class);
                final JsonRpcRequest request = new JsonRpcRequest("blockchain.address.listunspent", new String[] { address.toBase58() });
                requestAdapter.toJson(sink, request);
                sink.writeUtf8("\n").flush();
                final JsonAdapter<JsonRpcResponse> responseAdapter = moshi.adapter(JsonRpcResponse.class);
                final JsonRpcResponse response = responseAdapter.fromJson(source);
                if (response.id == request.id) {
                    if (response.result == null)
                        throw new JsonDataException("empty response");
                    final Set<UTXO> utxos = new HashSet<>();
                    for (final JsonRpcResponse.Utxo responseUtxo : response.result) {
                        final Sha256Hash utxoHash = Sha256Hash.wrap(responseUtxo.tx_hash);
                        final int utxoIndex = responseUtxo.tx_pos;
                        final Coin utxoValue = Coin.valueOf(responseUtxo.value);
                        final Script script = ScriptBuilder.createOutputScript(address);
                        final UTXO utxo = new UTXO(utxoHash, utxoIndex, utxoValue, responseUtxo.height, false, script);
                        utxos.add(utxo);
                    }
                    log.info("fetched {} unspent outputs from {}", response.result.length, server.socketAddress);
                    onResult(utxos);
                } else {
                    log.info("id mismatch response:{} vs request:{}", response.id, request.id);
                    onFail(R.string.error_parse, server.socketAddress.toString());
                }
            } catch (final JsonDataException x) {
                log.info("problem parsing json", x);
                onFail(R.string.error_parse, x.getMessage());
            } catch (final IOException x) {
                log.info("problem querying unspent outputs", x);
                onFail(R.string.error_io, x.getMessage());
            }
        }
    });
}
Also used : Moshi(com.squareup.moshi.Moshi) HashSet(java.util.HashSet) Set(java.util.Set) ScriptBuilder(org.bitcoinj.script.ScriptBuilder) Sha256Hash(org.bitcoinj.core.Sha256Hash) BufferedSink(okio.BufferedSink) JsonAdapter(com.squareup.moshi.JsonAdapter) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) Coin(org.bitcoinj.core.Coin) Random(java.util.Random) LinkedList(java.util.LinkedList) List(java.util.List) BufferedSource(okio.BufferedSource) Script(org.bitcoinj.script.Script) SSLSocketFactory(javax.net.ssl.SSLSocketFactory) SocketFactory(javax.net.SocketFactory) SSLSession(javax.net.ssl.SSLSession) IOException(java.io.IOException) UTXO(org.bitcoinj.core.UTXO) JsonDataException(com.squareup.moshi.JsonDataException) Socket(java.net.Socket) SSLSocket(javax.net.ssl.SSLSocket) X509Certificate(java.security.cert.X509Certificate) Certificate(java.security.cert.Certificate)

Aggregations

Set (java.util.Set)2 Sha256Hash (org.bitcoinj.core.Sha256Hash)2 UTXO (org.bitcoinj.core.UTXO)2 DialogInterface (android.content.DialogInterface)1 JsonAdapter (com.squareup.moshi.JsonAdapter)1 JsonDataException (com.squareup.moshi.JsonDataException)1 Moshi (com.squareup.moshi.Moshi)1 DialogBuilder (de.schildbach.wallet.ui.DialogBuilder)1 IOException (java.io.IOException)1 Socket (java.net.Socket)1 Certificate (java.security.cert.Certificate)1 X509Certificate (java.security.cert.X509Certificate)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Random (java.util.Random)1 TreeSet (java.util.TreeSet)1 SocketFactory (javax.net.SocketFactory)1 SSLHandshakeException (javax.net.ssl.SSLHandshakeException)1