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);
}
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());
}
}
});
}
Aggregations