use of org.bitcoinj.wallet.Wallet in project bitcoin-wallet by bitcoin-wallet.
the class EncryptKeysDialogFragment method handleGo.
private void handleGo() {
final String oldPassword = Strings.emptyToNull(oldPasswordView.getText().toString().trim());
final String newPassword = Strings.emptyToNull(newPasswordView.getText().toString().trim());
if (oldPassword != null && newPassword != null)
log.info("changing spending password");
else if (newPassword != null)
log.info("setting spending password");
else if (oldPassword != null)
log.info("removing spending password");
else
throw new IllegalStateException();
state = State.CRYPTING;
updateView();
backgroundHandler.post(() -> {
// For the old key, we use the key crypter that was used to derive the password in the first
// place.
final KeyCrypter oldKeyCrypter = wallet.getKeyCrypter();
final KeyParameter oldKey = oldKeyCrypter != null && oldPassword != null ? oldKeyCrypter.deriveKey(oldPassword) : null;
// For the new key, we create a new key crypter according to the desired parameters.
final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(application.scryptIterationsTarget());
final KeyParameter newKey = newPassword != null ? keyCrypter.deriveKey(newPassword) : null;
handler.post(() -> {
// Decrypt from old password
if (wallet.isEncrypted()) {
if (oldKey == null) {
log.info("wallet is encrypted, but did not provide spending password");
state = State.INPUT;
oldPasswordView.requestFocus();
} else {
try {
wallet.decrypt(oldKey);
state = State.DONE;
log.info("wallet successfully decrypted");
} catch (final Wallet.BadWalletEncryptionKeyException x) {
log.info("wallet decryption failed, bad spending password: " + x.getMessage());
badPasswordView.setVisibility(View.VISIBLE);
state = State.INPUT;
oldPasswordView.requestFocus();
}
}
}
// Use opportunity to maybe upgrade wallet
if (wallet.isDeterministicUpgradeRequired(Constants.UPGRADE_OUTPUT_SCRIPT_TYPE) && !wallet.isEncrypted())
wallet.upgradeToDeterministic(Constants.UPGRADE_OUTPUT_SCRIPT_TYPE, null);
// Encrypt to new password
if (newKey != null && !wallet.isEncrypted()) {
wallet.encrypt(keyCrypter, newKey);
config.updateLastEncryptKeysTime();
log.info("wallet successfully encrypted, using key derived by new spending password ({} scrypt iterations)", keyCrypter.getScryptParameters().getN());
state = State.DONE;
}
updateView();
if (state == State.DONE) {
WalletUtils.autoBackupWallet(activity, wallet);
// trigger load manually because of missing callbacks for encryption state
activityViewModel.walletEncrypted.load();
handler.postDelayed(() -> dismiss(), 2000);
}
});
});
}
use of org.bitcoinj.wallet.Wallet in project bitcoin-wallet by bitcoin-wallet.
the class BlockchainService method onCreate.
@Override
public void onCreate() {
serviceUpTime = Stopwatch.createStarted();
log.debug(".onCreate()");
super.onCreate();
application = (WalletApplication) getApplication();
config = application.getConfiguration();
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
log.info("acquiring {}", wakeLock);
wakeLock.acquire();
connectivityNotification.setColor(getColor(R.color.fg_network_significant));
connectivityNotification.setContentTitle(getString(config.isTrustedPeersOnly() ? R.string.notification_connectivity_syncing_trusted_peer : R.string.notification_connectivity_syncing_message));
connectivityNotification.setContentIntent(PendingIntent.getActivity(BlockchainService.this, 0, new Intent(BlockchainService.this, WalletActivity.class), 0));
connectivityNotification.setWhen(System.currentTimeMillis());
connectivityNotification.setOngoing(true);
connectivityNotification.setPriority(NotificationCompat.PRIORITY_LOW);
startForeground(0);
backgroundThread = new HandlerThread("backgroundThread", Process.THREAD_PRIORITY_BACKGROUND);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
addressBookDao = AddressBookDatabase.getDatabase(application).addressBookDao();
blockChainFile = new File(getDir("blockstore", Context.MODE_PRIVATE), Constants.Files.BLOCKCHAIN_FILENAME);
config.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
registerReceiver(deviceIdleModeReceiver, new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED));
peerConnectivityListener = new PeerConnectivityListener();
broadcastPeerState(0);
final WalletBalanceLiveData walletBalance = new WalletBalanceLiveData(application);
final SelectedExchangeRateLiveData exchangeRate = new SelectedExchangeRateLiveData(application);
walletBalance.observe(this, balance -> {
final ExchangeRateEntry rate = exchangeRate.getValue();
if (balance != null)
WalletBalanceWidgetProvider.updateWidgets(BlockchainService.this, balance, rate != null ? rate.exchangeRate() : null);
});
exchangeRate.observe(this, rate -> {
final Coin balance = walletBalance.getValue();
if (balance != null)
WalletBalanceWidgetProvider.updateWidgets(BlockchainService.this, balance, rate != null ? rate.exchangeRate() : null);
});
wallet = new WalletLiveData(application);
wallet.observe(this, new Observer<Wallet>() {
@Override
public void onChanged(final Wallet wallet) {
BlockchainService.this.wallet.removeObserver(this);
final boolean blockChainFileExists = blockChainFile.exists();
if (!blockChainFileExists) {
log.info("blockchain does not exist, resetting wallet");
wallet.reset();
}
try {
blockStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, blockChainFile, Constants.Files.BLOCKCHAIN_STORE_CAPACITY, true);
// detect corruptions as early as possible
blockStore.getChainHead();
final long earliestKeyCreationTimeSecs = wallet.getEarliestKeyCreationTime();
if (!blockChainFileExists && earliestKeyCreationTimeSecs > 0) {
try {
log.info("loading checkpoints for birthdate {} from '{}'", Utils.dateTimeFormat(earliestKeyCreationTimeSecs * 1000), Constants.Files.CHECKPOINTS_ASSET);
final Stopwatch watch = Stopwatch.createStarted();
final InputStream checkpointsInputStream = getAssets().open(Constants.Files.CHECKPOINTS_ASSET);
CheckpointManager.checkpoint(Constants.NETWORK_PARAMETERS, checkpointsInputStream, blockStore, earliestKeyCreationTimeSecs);
watch.stop();
log.info("checkpoints loaded, took {}", watch);
} catch (final IOException x) {
log.error("problem reading checkpoints, continuing without", x);
}
}
} catch (final BlockStoreException x) {
blockChainFile.delete();
final String msg = "blockstore cannot be created";
log.error(msg, x);
throw new Error(msg, x);
}
try {
blockChain = new BlockChain(Constants.NETWORK_PARAMETERS, wallet, blockStore);
} catch (final BlockStoreException x) {
throw new Error("blockchain cannot be created", x);
}
observeLiveDatasThatAreDependentOnWalletAndBlockchain();
}
});
}
use of org.bitcoinj.wallet.Wallet in project bitcoin-wallet by bitcoin-wallet.
the class SendCoinsFragment method signAndSendPayment.
private void signAndSendPayment(final KeyParameter encryptionKey) {
setState(SendCoinsViewModel.State.SIGNING);
// final payment intent
final PaymentIntent finalPaymentIntent = viewModel.paymentIntent.mergeWithEditedValues(amountCalculatorLink.getAmount(), viewModel.validatedAddress != null ? viewModel.validatedAddress.address : null);
final Coin finalAmount = finalPaymentIntent.getAmount();
// prepare send request
final Map<FeeCategory, Coin> fees = viewModel.dynamicFees.getValue();
final Wallet wallet = walletActivityViewModel.wallet.getValue();
final SendRequest sendRequest = finalPaymentIntent.toSendRequest();
sendRequest.emptyWallet = viewModel.paymentIntent.mayEditAmount() && finalAmount.equals(wallet.getBalance(BalanceType.AVAILABLE));
sendRequest.feePerKb = fees.get(viewModel.feeCategory);
sendRequest.memo = viewModel.paymentIntent.memo;
sendRequest.exchangeRate = amountCalculatorLink.getExchangeRate();
sendRequest.aesKey = encryptionKey;
final Coin fee = viewModel.dryrunTransaction.getFee();
if (fee.isGreaterThan(finalAmount)) {
setState(SendCoinsViewModel.State.INPUT);
final MonetaryFormat btcFormat = config.getFormat();
final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.send_coins_fragment_significant_fee_title, R.string.send_coins_fragment_significant_fee_message, btcFormat.format(fee), btcFormat.format(finalAmount));
dialog.setPositiveButton(R.string.send_coins_fragment_button_send, (d, which) -> sendPayment(sendRequest, finalAmount));
dialog.setNegativeButton(R.string.button_cancel, null);
dialog.show();
} else {
sendPayment(sendRequest, finalAmount);
}
}
use of org.bitcoinj.wallet.Wallet in project bitcoin-wallet by bitcoin-wallet.
the class SendCoinsFragment method updateView.
private void updateView() {
final Wallet wallet = walletActivityViewModel.wallet.getValue();
final Map<FeeCategory, Coin> fees = viewModel.dynamicFees.getValue();
final BlockchainState blockchainState = application.blockchainState.getValue();
final Map<String, AddressBookEntry> addressBook = AddressBookEntry.asMap(viewModel.addressBook.getValue());
if (viewModel.paymentIntent != null) {
final MonetaryFormat btcFormat = config.getFormat();
getView().setVisibility(View.VISIBLE);
if (viewModel.paymentIntent.hasPayee()) {
payeeNameView.setVisibility(View.VISIBLE);
payeeNameView.setText(viewModel.paymentIntent.payeeName);
payeeVerifiedByView.setVisibility(View.VISIBLE);
final String verifiedBy = viewModel.paymentIntent.payeeVerifiedBy != null ? viewModel.paymentIntent.payeeVerifiedBy : getString(R.string.send_coins_fragment_payee_verified_by_unknown);
payeeVerifiedByView.setText(Constants.CHAR_CHECKMARK + String.format(getString(R.string.send_coins_fragment_payee_verified_by), verifiedBy));
} else {
payeeNameView.setVisibility(View.GONE);
payeeVerifiedByView.setVisibility(View.GONE);
}
if (viewModel.paymentIntent.hasOutputs()) {
payeeGroup.setVisibility(View.VISIBLE);
receivingAddressView.setVisibility(View.GONE);
receivingStaticView.setVisibility(!viewModel.paymentIntent.hasPayee() || viewModel.paymentIntent.payeeVerifiedBy == null ? View.VISIBLE : View.GONE);
receivingStaticLabelView.setText(viewModel.paymentIntent.memo);
if (viewModel.paymentIntent.hasAddress())
receivingStaticAddressView.setText(WalletUtils.formatAddress(viewModel.paymentIntent.getAddress(), Constants.ADDRESS_FORMAT_GROUP_SIZE, Constants.ADDRESS_FORMAT_LINE_SIZE));
else
receivingStaticAddressView.setText(R.string.send_coins_fragment_receiving_address_complex);
} else if (viewModel.validatedAddress != null) {
payeeGroup.setVisibility(View.VISIBLE);
receivingAddressView.setVisibility(View.GONE);
receivingStaticView.setVisibility(View.VISIBLE);
receivingStaticAddressView.setText(WalletUtils.formatAddress(viewModel.validatedAddress.address, Constants.ADDRESS_FORMAT_GROUP_SIZE, Constants.ADDRESS_FORMAT_LINE_SIZE));
final String addressBookLabel = addressBookDao.resolveLabel(viewModel.validatedAddress.address.toString());
final String staticLabel;
if (addressBookLabel != null)
staticLabel = addressBookLabel;
else if (viewModel.validatedAddress.label != null)
staticLabel = viewModel.validatedAddress.label;
else
staticLabel = getString(R.string.address_unlabeled);
receivingStaticLabelView.setText(staticLabel);
receivingStaticLabelView.setTextColor(activity.getColor(viewModel.validatedAddress.label != null ? R.color.fg_significant : R.color.fg_insignificant));
} else if (viewModel.paymentIntent.standard == null) {
payeeGroup.setVisibility(View.VISIBLE);
receivingStaticView.setVisibility(View.GONE);
receivingAddressView.setVisibility(View.VISIBLE);
} else {
payeeGroup.setVisibility(View.GONE);
}
receivingAddressView.setEnabled(viewModel.state == SendCoinsViewModel.State.INPUT);
amountGroup.setVisibility(viewModel.paymentIntent.hasAmount() || (viewModel.state != null && viewModel.state.compareTo(SendCoinsViewModel.State.INPUT) >= 0) ? View.VISIBLE : View.GONE);
amountCalculatorLink.setEnabled(viewModel.state == SendCoinsViewModel.State.INPUT && viewModel.paymentIntent.mayEditAmount());
final boolean directPaymentVisible;
if (viewModel.paymentIntent.hasPaymentUrl()) {
if (viewModel.paymentIntent.isBluetoothPaymentUrl())
directPaymentVisible = bluetoothAdapter != null;
else
directPaymentVisible = true;
} else {
directPaymentVisible = false;
}
directPaymentEnableView.setVisibility(directPaymentVisible ? View.VISIBLE : View.GONE);
directPaymentEnableView.setEnabled(viewModel.state == SendCoinsViewModel.State.INPUT);
hintView.setVisibility(View.GONE);
if (viewModel.state == SendCoinsViewModel.State.INPUT) {
if (blockchainState != null && blockchainState.replaying) {
hintView.setTextColor(activity.getColor(R.color.fg_error));
hintView.setVisibility(View.VISIBLE);
hintView.setText(R.string.send_coins_fragment_hint_replaying);
} else if (viewModel.paymentIntent.mayEditAddress() && viewModel.validatedAddress == null && !receivingAddressView.getText().toString().trim().isEmpty()) {
hintView.setTextColor(activity.getColor(R.color.fg_error));
hintView.setVisibility(View.VISIBLE);
hintView.setText(R.string.send_coins_fragment_receiving_address_error);
} else if (viewModel.dryrunException != null) {
hintView.setTextColor(activity.getColor(R.color.fg_error));
hintView.setVisibility(View.VISIBLE);
if (viewModel.dryrunException instanceof DustySendRequested)
hintView.setText(getString(R.string.send_coins_fragment_hint_dusty_send));
else if (viewModel.dryrunException instanceof InsufficientMoneyException)
hintView.setText(getString(R.string.send_coins_fragment_hint_insufficient_money, btcFormat.format(((InsufficientMoneyException) viewModel.dryrunException).missing)));
else if (viewModel.dryrunException instanceof CouldNotAdjustDownwards)
hintView.setText(getString(R.string.send_coins_fragment_hint_empty_wallet_failed));
else
hintView.setText(viewModel.dryrunException.toString());
} else if (viewModel.dryrunTransaction != null && viewModel.dryrunTransaction.getFee() != null) {
hintView.setVisibility(View.VISIBLE);
final int hintResId;
final int colorResId;
if (viewModel.feeCategory == FeeCategory.ECONOMIC) {
hintResId = R.string.send_coins_fragment_hint_fee_economic;
colorResId = R.color.fg_less_significant;
} else if (viewModel.feeCategory == FeeCategory.PRIORITY) {
hintResId = R.string.send_coins_fragment_hint_fee_priority;
colorResId = R.color.fg_less_significant;
} else {
hintResId = R.string.send_coins_fragment_hint_fee;
colorResId = R.color.fg_insignificant;
}
hintView.setTextColor(activity.getColor(colorResId));
hintView.setText(getString(hintResId, btcFormat.format(viewModel.dryrunTransaction.getFee())));
} else if (viewModel.paymentIntent.mayEditAddress() && viewModel.validatedAddress != null && wallet != null && wallet.isAddressMine(viewModel.validatedAddress.address)) {
hintView.setTextColor(activity.getColor(R.color.fg_insignificant));
hintView.setVisibility(View.VISIBLE);
hintView.setText(R.string.send_coins_fragment_receiving_address_own);
}
}
final Transaction sentTransaction = viewModel.sentTransaction.getValue();
if (sentTransaction != null && wallet != null) {
sentTransactionView.setVisibility(View.VISIBLE);
sentTransactionViewHolder.fullBind(new TransactionsAdapter.ListItem.TransactionItem(activity, sentTransaction, wallet, addressBook, btcFormat, application.maxConnectedPeers()));
} else {
sentTransactionView.setVisibility(View.GONE);
}
if (viewModel.directPaymentAck != null) {
directPaymentMessageView.setVisibility(View.VISIBLE);
directPaymentMessageView.setText(viewModel.directPaymentAck ? R.string.send_coins_fragment_direct_payment_ack : R.string.send_coins_fragment_direct_payment_nack);
} else {
directPaymentMessageView.setVisibility(View.GONE);
}
viewCancel.setEnabled(viewModel.state != SendCoinsViewModel.State.REQUEST_PAYMENT_REQUEST && viewModel.state != SendCoinsViewModel.State.DECRYPTING && viewModel.state != SendCoinsViewModel.State.SIGNING);
viewGo.setEnabled(everythingPlausible() && viewModel.dryrunTransaction != null && wallet != null && fees != null && (blockchainState == null || !blockchainState.replaying));
if (viewModel.state == null || viewModel.state == SendCoinsViewModel.State.REQUEST_PAYMENT_REQUEST) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(null);
} else if (viewModel.state == SendCoinsViewModel.State.INPUT) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(R.string.send_coins_fragment_button_send);
} else if (viewModel.state == SendCoinsViewModel.State.DECRYPTING) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(R.string.send_coins_fragment_state_decrypting);
} else if (viewModel.state == SendCoinsViewModel.State.SIGNING) {
viewCancel.setText(R.string.button_cancel);
viewGo.setText(R.string.send_coins_preparation_msg);
} else if (viewModel.state == SendCoinsViewModel.State.SENDING) {
viewCancel.setText(R.string.send_coins_fragment_button_back);
viewGo.setText(R.string.send_coins_sending_msg);
} else if (viewModel.state == SendCoinsViewModel.State.SENT) {
viewCancel.setText(R.string.send_coins_fragment_button_back);
viewGo.setText(R.string.send_coins_sent_msg);
} else if (viewModel.state == SendCoinsViewModel.State.FAILED) {
viewCancel.setText(R.string.send_coins_fragment_button_back);
viewGo.setText(R.string.send_coins_failed_msg);
}
final boolean privateKeyPasswordViewVisible = (viewModel.state == SendCoinsViewModel.State.INPUT || viewModel.state == SendCoinsViewModel.State.DECRYPTING) && wallet != null && wallet.isEncrypted();
privateKeyPasswordViewGroup.setVisibility(privateKeyPasswordViewVisible ? View.VISIBLE : View.GONE);
privateKeyPasswordView.setEnabled(viewModel.state == SendCoinsViewModel.State.INPUT);
// focus linking
final int activeAmountViewId = amountCalculatorLink.activeTextView().getId();
receivingAddressView.setNextFocusDownId(activeAmountViewId);
receivingAddressView.setNextFocusForwardId(activeAmountViewId);
amountCalculatorLink.setNextFocusId(privateKeyPasswordViewVisible ? R.id.send_coins_private_key_password : R.id.send_coins_go);
privateKeyPasswordView.setNextFocusUpId(activeAmountViewId);
privateKeyPasswordView.setNextFocusDownId(R.id.send_coins_go);
privateKeyPasswordView.setNextFocusForwardId(R.id.send_coins_go);
viewGo.setNextFocusUpId(privateKeyPasswordViewVisible ? R.id.send_coins_private_key_password : activeAmountViewId);
} else {
getView().setVisibility(View.GONE);
}
}
use of org.bitcoinj.wallet.Wallet in project bitcoin-wallet by bitcoin-wallet.
the class SweepWalletFragment method requestWalletBalance.
private void requestWalletBalance() {
viewModel.progress.setValue(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) {
final Wallet wallet = walletActivityViewModel.wallet.getValue();
viewModel.progress.setValue(null);
// Filter UTXOs we've already spent and sort the rest.
final Set<Transaction> walletTxns = wallet.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(), utxo.getHash());
fakeTx.getConfidence().setConfidenceType(ConfidenceType.BUILDING);
fakeTxns.put(fakeTx.getTxId(), 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);
}
final Wallet walletToSweep = viewModel.walletToSweep.getValue();
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, false, null, true, false, null));
viewModel.walletToSweep.setValue(walletToSweep);
}
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) {
viewModel.progress.setValue(null);
viewModel.showDialogWithRetryRequestBalance.setValue(DialogEvent.warn(R.string.sweep_wallet_fragment_request_wallet_balance_failed_title, messageResId, messageArgs));
}
};
final Wallet walletToSweep = viewModel.walletToSweep.getValue();
final ECKey key = walletToSweep.getImportedKeys().iterator().next();
new RequestWalletBalanceTask(backgroundHandler, callback).requestWalletBalance(activity.getAssets(), key);
}
Aggregations