Search in sources :

Example 6 with Storage

use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.

the class PayNymController method broadcastNotificationTransaction.

private void broadcastNotificationTransaction(Wallet decryptedWallet, WalletTransaction walletTransaction, PaymentCode paymentCode, PayNym payNym) {
    try {
        PaymentCode externalPaymentCode = payNym.paymentCode();
        WalletNode input0Node = walletTransaction.getSelectedUtxos().entrySet().iterator().next().getValue();
        Keystore keystore = input0Node.getWallet().isNested() ? decryptedWallet.getChildWallet(input0Node.getWallet().getName()).getKeystores().get(0) : decryptedWallet.getKeystores().get(0);
        ECKey input0Key = keystore.getKey(input0Node);
        TransactionOutPoint input0Outpoint = walletTransaction.getTransaction().getInputs().iterator().next().getOutpoint();
        SecretPoint secretPoint = new SecretPoint(input0Key.getPrivKeyBytes(), externalPaymentCode.getNotificationKey().getPubKey());
        byte[] blindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), input0Outpoint.bitcoinSerialize());
        byte[] blindedPaymentCode = PaymentCode.blind(paymentCode.getPayload(), blindingMask);
        WalletTransaction finalWalletTx = getWalletTransaction(decryptedWallet, payNym, blindedPaymentCode, walletTransaction.getSelectedUtxos().keySet());
        PSBT psbt = finalWalletTx.createPSBT();
        decryptedWallet.sign(psbt);
        decryptedWallet.finalise(psbt);
        Transaction transaction = psbt.extractTransaction();
        ElectrumServer.BroadcastTransactionService broadcastTransactionService = new ElectrumServer.BroadcastTransactionService(transaction);
        broadcastTransactionService.setOnSucceeded(successEvent -> {
            ElectrumServer.TransactionMempoolService transactionMempoolService = new ElectrumServer.TransactionMempoolService(walletTransaction.getWallet(), transaction.getTxId(), new HashSet<>(walletTransaction.getSelectedUtxos().values()));
            transactionMempoolService.setDelay(Duration.seconds(2));
            transactionMempoolService.setPeriod(Duration.seconds(5));
            transactionMempoolService.setRestartOnFailure(false);
            transactionMempoolService.setOnSucceeded(mempoolWorkerStateEvent -> {
                Set<String> scriptHashes = transactionMempoolService.getValue();
                if (!scriptHashes.isEmpty()) {
                    transactionMempoolService.cancel();
                    List<Wallet> addedWallets = addChildWallets(payNym, externalPaymentCode);
                    Wallet masterWallet = getMasterWallet();
                    Storage storage = AppServices.get().getOpenWallets().get(masterWallet);
                    EventManager.get().post(new ChildWalletsAddedEvent(storage, masterWallet, addedWallets));
                    retrievePayNymProgress.setVisible(false);
                    followingList.refresh();
                    BlockTransaction blockTransaction = walletTransaction.getWallet().getWalletTransaction(transaction.getTxId());
                    if (blockTransaction != null && blockTransaction.getLabel() == null) {
                        blockTransaction.setLabel("Link " + payNym.nymName());
                        TransactionEntry transactionEntry = new TransactionEntry(walletTransaction.getWallet(), blockTransaction, Collections.emptyMap(), Collections.emptyMap());
                        EventManager.get().post(new WalletEntryLabelsChangedEvent(walletTransaction.getWallet(), List.of(transactionEntry)));
                    }
                }
                if (transactionMempoolService.getIterationCount() > 5 && transactionMempoolService.isRunning()) {
                    transactionMempoolService.cancel();
                    retrievePayNymProgress.setVisible(false);
                    followingList.refresh();
                    log.error("Timeout searching for broadcasted notification transaction");
                    AppServices.showErrorDialog("Timeout searching for broadcasted transaction", "The transaction was broadcast but the server did not register it in the mempool. It is safe to try linking again.");
                }
            });
            transactionMempoolService.setOnFailed(mempoolWorkerStateEvent -> {
                transactionMempoolService.cancel();
                log.error("Error searching for broadcasted notification transaction", mempoolWorkerStateEvent.getSource().getException());
                retrievePayNymProgress.setVisible(false);
                followingList.refresh();
                AppServices.showErrorDialog("Timeout searching for broadcasted transaction", "The transaction was broadcast but the server did not register it in the mempool. It is safe to try linking again.");
            });
            transactionMempoolService.start();
        });
        broadcastTransactionService.setOnFailed(failedEvent -> {
            log.error("Error broadcasting notification transaction", failedEvent.getSource().getException());
            retrievePayNymProgress.setVisible(false);
            followingList.refresh();
            AppServices.showErrorDialog("Error broadcasting notification transaction", failedEvent.getSource().getException().getMessage());
        });
        retrievePayNymProgress.setVisible(true);
        notificationTransactions.put(transaction.getTxId(), payNym);
        broadcastTransactionService.start();
    } catch (Exception e) {
        log.error("Error creating notification transaction", e);
        retrievePayNymProgress.setVisible(false);
        followingList.refresh();
        AppServices.showErrorDialog("Error creating notification transaction", e.getMessage());
    }
}
Also used : ECKey(com.sparrowwallet.drongo.crypto.ECKey) SecureString(com.sparrowwallet.drongo.SecureString) SecretPoint(com.sparrowwallet.drongo.bip47.SecretPoint) PaymentCode(com.sparrowwallet.drongo.bip47.PaymentCode) PSBT(com.sparrowwallet.drongo.psbt.PSBT) ElectrumServer(com.sparrowwallet.sparrow.net.ElectrumServer) Storage(com.sparrowwallet.sparrow.io.Storage) TransactionEntry(com.sparrowwallet.sparrow.wallet.TransactionEntry)

Example 7 with Storage

use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.

the class PayNymController method broadcastNotificationTransaction.

public void broadcastNotificationTransaction(PayNym payNym) {
    Wallet masterWallet = getMasterWallet();
    WalletTransaction walletTransaction;
    try {
        walletTransaction = getWalletTransaction(masterWallet, payNym, new byte[80], null);
    } catch (InsufficientFundsException e) {
        try {
            Wallet wallet = AppServices.get().getWallet(walletId);
            walletTransaction = getWalletTransaction(wallet, payNym, new byte[80], null);
        } catch (InsufficientFundsException e2) {
            AppServices.showErrorDialog("Insufficient Funds", "There are not enough funds in this wallet to broadcast the notification transaction.");
            followingList.refresh();
            return;
        }
    }
    final WalletTransaction walletTx = walletTransaction;
    final PaymentCode paymentCode = masterWallet.getPaymentCode();
    Wallet wallet = walletTransaction.getWallet();
    Storage storage = AppServices.get().getOpenWallets().get(wallet);
    if (wallet.isEncrypted()) {
        WalletPasswordDialog dlg = new WalletPasswordDialog(wallet.getMasterName(), WalletPasswordDialog.PasswordRequirement.LOAD);
        Optional<SecureString> password = dlg.showAndWait();
        if (password.isPresent()) {
            Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(wallet.copy(), password.get());
            decryptWalletService.setOnSucceeded(workerStateEvent -> {
                EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Done"));
                Wallet decryptedWallet = decryptWalletService.getValue();
                broadcastNotificationTransaction(decryptedWallet, walletTx, paymentCode, payNym);
                decryptedWallet.clearPrivate();
            });
            decryptWalletService.setOnFailed(workerStateEvent -> {
                EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Failed"));
                followingList.refresh();
                AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage());
            });
            EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.START, "Decrypting wallet..."));
            decryptWalletService.start();
        }
    } else {
        broadcastNotificationTransaction(wallet, walletTx, paymentCode, payNym);
    }
}
Also used : PaymentCode(com.sparrowwallet.drongo.bip47.PaymentCode) Storage(com.sparrowwallet.sparrow.io.Storage) SecureString(com.sparrowwallet.drongo.SecureString)

Example 8 with Storage

use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.

the class SendController method addChildWallets.

private void addChildWallets(Wallet wallet, PaymentCode externalPaymentCode, Transaction transaction, PayNym payNym) {
    List<Wallet> addedWallets = addChildWallets(externalPaymentCode, payNym);
    Wallet masterWallet = getWalletForm().getMasterWallet();
    Storage storage = AppServices.get().getOpenWallets().get(masterWallet);
    EventManager.get().post(new ChildWalletsAddedEvent(storage, masterWallet, addedWallets));
    BlockTransaction blockTransaction = wallet.getWalletTransaction(transaction.getTxId());
    if (blockTransaction != null && blockTransaction.getLabel() == null) {
        blockTransaction.setLabel("Link " + (payNym == null ? externalPaymentCode.toAbbreviatedString() : payNym.nymName()));
        TransactionEntry transactionEntry = new TransactionEntry(wallet, blockTransaction, Collections.emptyMap(), Collections.emptyMap());
        EventManager.get().post(new WalletEntryLabelsChangedEvent(wallet, List.of(transactionEntry)));
    }
    if (paymentTabs.getTabs().size() > 0 && !addedWallets.isEmpty()) {
        Wallet addedWallet = addedWallets.stream().filter(w -> w.getScriptType() == ScriptType.P2WPKH).findFirst().orElse(addedWallets.iterator().next());
        PaymentController controller = (PaymentController) paymentTabs.getTabs().get(0).getUserData();
        controller.setPayNym(payNym == null ? PayNym.fromWallet(addedWallet) : payNym);
    }
    Glyph successGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.CHECK_CIRCLE);
    successGlyph.getStyleClass().add("success");
    successGlyph.setFontSize(50);
    AppServices.showAlertDialog("Notification Successful", "The notification transaction was successfully sent for payment code " + externalPaymentCode.toAbbreviatedString() + (payNym == null ? "" : " (" + payNym.nymName() + ")") + ".\n\nYou can send to it by entering the payment code, or selecting `PayNym or Payment code` in the Pay to dropdown.", Alert.AlertType.INFORMATION, successGlyph, ButtonType.OK);
}
Also used : Storage(com.sparrowwallet.sparrow.io.Storage) Glyph(org.controlsfx.glyphfont.Glyph)

Example 9 with Storage

use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.

the class SendController method broadcastNotification.

public void broadcastNotification(ActionEvent event) {
    Wallet wallet = getWalletForm().getWallet();
    Storage storage = AppServices.get().getOpenWallets().get(wallet);
    if (wallet.isEncrypted()) {
        WalletPasswordDialog dlg = new WalletPasswordDialog(wallet.getMasterName(), WalletPasswordDialog.PasswordRequirement.LOAD);
        Optional<SecureString> password = dlg.showAndWait();
        if (password.isPresent()) {
            Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(wallet.copy(), password.get());
            decryptWalletService.setOnSucceeded(workerStateEvent -> {
                EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Done"));
                Wallet decryptedWallet = decryptWalletService.getValue();
                broadcastNotification(decryptedWallet);
                decryptedWallet.clearPrivate();
            });
            decryptWalletService.setOnFailed(workerStateEvent -> {
                EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Failed"));
                AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage());
            });
            EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.START, "Decrypting wallet..."));
            decryptWalletService.start();
        }
    } else {
        broadcastNotification(wallet);
    }
}
Also used : Storage(com.sparrowwallet.sparrow.io.Storage) SecureString(com.sparrowwallet.drongo.SecureString)

Example 10 with Storage

use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.

the class SendController method broadcastPremix.

public void broadcastPremix(ActionEvent event) {
    // Ensure all child wallets have been saved
    Wallet masterWallet = getWalletForm().getWallet().isMasterWallet() ? getWalletForm().getWallet() : getWalletForm().getWallet().getMasterWallet();
    for (Wallet childWallet : masterWallet.getChildWallets()) {
        if (!childWallet.isNested()) {
            Storage storage = AppServices.get().getOpenWallets().get(childWallet);
            if (!storage.isPersisted(childWallet)) {
                try {
                    storage.saveWallet(childWallet);
                } catch (Exception e) {
                    AppServices.showErrorDialog("Error saving wallet " + childWallet.getName(), e.getMessage());
                }
            }
        }
    }
    // The WhirlpoolWallet has already been configured for the tx0 preview
    Whirlpool whirlpool = AppServices.getWhirlpoolServices().getWhirlpool(getWalletForm().getStorage().getWalletId(masterWallet));
    Map<BlockTransactionHashIndex, WalletNode> utxos = walletTransactionProperty.get().getSelectedUtxos();
    Whirlpool.Tx0BroadcastService tx0BroadcastService = new Whirlpool.Tx0BroadcastService(whirlpool, whirlpoolProperty.get(), utxos.keySet());
    tx0BroadcastService.setOnRunning(workerStateEvent -> {
        premixButton.setDisable(true);
        addWalletTransactionNodes();
    });
    tx0BroadcastService.setOnSucceeded(workerStateEvent -> {
        premixButton.setDisable(false);
        Sha256Hash txid = tx0BroadcastService.getValue();
        clear(null);
    });
    tx0BroadcastService.setOnFailed(workerStateEvent -> {
        premixButton.setDisable(false);
        Throwable exception = workerStateEvent.getSource().getException();
        while (exception.getCause() != null) {
            exception = exception.getCause();
        }
        AppServices.showErrorDialog("Error broadcasting premix transaction", exception.getMessage());
    });
    ServiceProgressDialog progressDialog = new ServiceProgressDialog("Whirlpool", "Broadcast Premix Transaction", "/image/whirlpool.png", tx0BroadcastService);
    AppServices.moveToActiveWindowScreen(progressDialog);
    tx0BroadcastService.start();
}
Also used : Storage(com.sparrowwallet.sparrow.io.Storage) Whirlpool(com.sparrowwallet.sparrow.whirlpool.Whirlpool) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) InvalidAddressException(com.sparrowwallet.drongo.address.InvalidAddressException) IOException(java.io.IOException)

Aggregations

Storage (com.sparrowwallet.sparrow.io.Storage)12 SecureString (com.sparrowwallet.drongo.SecureString)8 PaymentCode (com.sparrowwallet.drongo.bip47.PaymentCode)4 InvalidAddressException (com.sparrowwallet.drongo.address.InvalidAddressException)2 SecretPoint (com.sparrowwallet.drongo.bip47.SecretPoint)2 ECKey (com.sparrowwallet.drongo.crypto.ECKey)2 Wallet (com.sparrowwallet.drongo.wallet.Wallet)2 StorageEvent (com.sparrowwallet.sparrow.event.StorageEvent)2 TransactionEntry (com.sparrowwallet.sparrow.wallet.TransactionEntry)2 IOException (java.io.IOException)2 Subscribe (com.google.common.eventbus.Subscribe)1 InvalidPasswordException (com.sparrowwallet.drongo.crypto.InvalidPasswordException)1 ScriptType (com.sparrowwallet.drongo.protocol.ScriptType)1 Sha256Hash (com.sparrowwallet.drongo.protocol.Sha256Hash)1 PSBT (com.sparrowwallet.drongo.psbt.PSBT)1 WalletPasswordDialog (com.sparrowwallet.sparrow.control.WalletPasswordDialog)1 WalletDataChangedEvent (com.sparrowwallet.sparrow.event.WalletDataChangedEvent)1 WalletHistoryClearedEvent (com.sparrowwallet.sparrow.event.WalletHistoryClearedEvent)1 ElectrumServer (com.sparrowwallet.sparrow.net.ElectrumServer)1 Whirlpool (com.sparrowwallet.sparrow.whirlpool.Whirlpool)1