Search in sources :

Example 1 with Sha256Hash

use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.

the class SparrowUtxoConfigPersister method doWrite.

@Override
protected void doWrite(UtxoConfigData data) throws Exception {
    Wallet wallet = getWallet();
    if (wallet == null) {
        // Wallet is already closed
        return;
    }
    Map<String, UtxoConfigPersisted> currentData = new HashMap<>(data.getUtxoConfigs());
    Map<Sha256Hash, UtxoMixData> changedUtxoMixes = currentData.entrySet().stream().collect(Collectors.toMap(entry -> Sha256Hash.wrap(entry.getKey()), entry -> new UtxoMixData(entry.getValue().getMixsDone(), entry.getValue().getExpired()), (u, v) -> {
        throw new IllegalStateException("Duplicate utxo config hashes");
    }, HashMap::new));
    MapDifference<Sha256Hash, UtxoMixData> mapDifference = Maps.difference(changedUtxoMixes, wallet.getUtxoMixes());
    Map<Sha256Hash, UtxoMixData> removedUtxoMixes = mapDifference.entriesOnlyOnRight();
    wallet.getUtxoMixes().putAll(changedUtxoMixes);
    wallet.getUtxoMixes().keySet().removeAll(removedUtxoMixes.keySet());
    if (!changedUtxoMixes.isEmpty() || !removedUtxoMixes.isEmpty()) {
        EventManager.get().post(new WalletUtxoMixesChangedEvent(wallet, changedUtxoMixes, removedUtxoMixes));
    }
}
Also used : Logger(org.slf4j.Logger) UtxoMixData(com.sparrowwallet.drongo.wallet.UtxoMixData) Wallet(com.sparrowwallet.drongo.wallet.Wallet) LoggerFactory(org.slf4j.LoggerFactory) UtxoConfigPersisted(com.samourai.whirlpool.client.wallet.data.utxoConfig.UtxoConfigPersisted) HashMap(java.util.HashMap) Maps(com.google.common.collect.Maps) WalletUtxoMixesChangedEvent(com.sparrowwallet.sparrow.event.WalletUtxoMixesChangedEvent) Collectors(java.util.stream.Collectors) UtxoConfigData(com.samourai.whirlpool.client.wallet.data.utxoConfig.UtxoConfigData) MapDifference(com.google.common.collect.MapDifference) AppServices(com.sparrowwallet.sparrow.AppServices) Map(java.util.Map) EventManager(com.sparrowwallet.sparrow.EventManager) UtxoConfigPersister(com.samourai.whirlpool.client.wallet.data.utxoConfig.UtxoConfigPersister) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) WalletUtxoMixesChangedEvent(com.sparrowwallet.sparrow.event.WalletUtxoMixesChangedEvent) HashMap(java.util.HashMap) UtxoMixData(com.sparrowwallet.drongo.wallet.UtxoMixData) Wallet(com.sparrowwallet.drongo.wallet.Wallet) UtxoConfigPersisted(com.samourai.whirlpool.client.wallet.data.utxoConfig.UtxoConfigPersisted) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash)

Example 2 with Sha256Hash

use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.

the class SparrowDataSource method fetchWalletResponse.

@Override
protected WalletResponse fetchWalletResponse() throws Exception {
    WalletResponse walletResponse = new WalletResponse();
    walletResponse.wallet = new WalletResponse.Wallet();
    Map<Sha256Hash, BlockTransaction> allTransactions = new HashMap<>();
    Map<Sha256Hash, String> allTransactionsZpubs = new HashMap<>();
    List<WalletResponse.Address> addresses = new ArrayList<>();
    List<WalletResponse.Tx> txes = new ArrayList<>();
    List<UnspentOutput> unspentOutputs = new ArrayList<>();
    int storedBlockHeight = 0;
    String[] zpubs = getWalletSupplier().getPubs(true);
    for (String zpub : zpubs) {
        Wallet wallet = getWallet(zpub);
        if (wallet == null) {
            log.debug("No wallet for " + zpub + " found");
            continue;
        }
        Map<Sha256Hash, BlockTransaction> walletTransactions = wallet.getWalletTransactions();
        allTransactions.putAll(walletTransactions);
        walletTransactions.keySet().forEach(txid -> allTransactionsZpubs.put(txid, zpub));
        if (wallet.getStoredBlockHeight() != null) {
            storedBlockHeight = Math.max(storedBlockHeight, wallet.getStoredBlockHeight());
        }
        WalletResponse.Address address = new WalletResponse.Address();
        List<ExtendedKey.Header> headers = ExtendedKey.Header.getHeaders(Network.get());
        ExtendedKey.Header header = headers.stream().filter(head -> head.getDefaultScriptType().equals(wallet.getScriptType()) && !head.isPrivateKey()).findFirst().orElse(ExtendedKey.Header.xpub);
        address.address = wallet.getKeystores().get(0).getExtendedPublicKey().toString(header);
        int receiveIndex = wallet.getNode(KeyPurpose.RECEIVE).getHighestUsedIndex() == null ? 0 : wallet.getNode(KeyPurpose.RECEIVE).getHighestUsedIndex() + 1;
        address.account_index = wallet.getMixConfig() != null ? Math.max(receiveIndex, wallet.getMixConfig().getReceiveIndex()) : receiveIndex;
        int changeIndex = wallet.getNode(KeyPurpose.CHANGE).getHighestUsedIndex() == null ? 0 : wallet.getNode(KeyPurpose.CHANGE).getHighestUsedIndex() + 1;
        address.change_index = wallet.getMixConfig() != null ? Math.max(changeIndex, wallet.getMixConfig().getChangeIndex()) : changeIndex;
        address.n_tx = walletTransactions.size();
        addresses.add(address);
        for (Map.Entry<BlockTransactionHashIndex, WalletNode> utxo : wallet.getWalletUtxos().entrySet()) {
            BlockTransaction blockTransaction = wallet.getWalletTransaction(utxo.getKey().getHash());
            if (blockTransaction != null && utxo.getKey().getStatus() != Status.FROZEN) {
                unspentOutputs.add(Whirlpool.getUnspentOutput(utxo.getValue(), blockTransaction, (int) utxo.getKey().getIndex()));
            }
        }
    }
    for (BlockTransaction blockTransaction : allTransactions.values()) {
        WalletResponse.Tx tx = new WalletResponse.Tx();
        tx.block_height = blockTransaction.getHeight();
        tx.hash = blockTransaction.getHashAsString();
        tx.locktime = blockTransaction.getTransaction().getLocktime();
        tx.version = (int) blockTransaction.getTransaction().getVersion();
        tx.inputs = new WalletResponse.TxInput[blockTransaction.getTransaction().getInputs().size()];
        for (int i = 0; i < blockTransaction.getTransaction().getInputs().size(); i++) {
            TransactionInput txInput = blockTransaction.getTransaction().getInputs().get(i);
            tx.inputs[i] = new WalletResponse.TxInput();
            tx.inputs[i].vin = txInput.getIndex();
            tx.inputs[i].sequence = txInput.getSequenceNumber();
            if (allTransactionsZpubs.containsKey(txInput.getOutpoint().getHash())) {
                tx.inputs[i].prev_out = new WalletResponse.TxOut();
                tx.inputs[i].prev_out.txid = txInput.getOutpoint().getHash().toString();
                tx.inputs[i].prev_out.vout = (int) txInput.getOutpoint().getIndex();
                BlockTransaction spentTransaction = allTransactions.get(txInput.getOutpoint().getHash());
                if (spentTransaction != null) {
                    TransactionOutput spentOutput = spentTransaction.getTransaction().getOutputs().get((int) txInput.getOutpoint().getIndex());
                    tx.inputs[i].prev_out.value = spentOutput.getValue();
                }
                tx.inputs[i].prev_out.xpub = new UnspentOutput.Xpub();
                tx.inputs[i].prev_out.xpub.m = allTransactionsZpubs.get(txInput.getOutpoint().getHash());
            }
        }
        tx.out = new WalletResponse.TxOutput[blockTransaction.getTransaction().getOutputs().size()];
        for (int i = 0; i < blockTransaction.getTransaction().getOutputs().size(); i++) {
            TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get(i);
            tx.out[i] = new WalletResponse.TxOutput();
            tx.out[i].n = txOutput.getIndex();
            tx.out[i].value = txOutput.getValue();
            tx.out[i].xpub = new UnspentOutput.Xpub();
            tx.out[i].xpub.m = allTransactionsZpubs.get(blockTransaction.getHash());
        }
        txes.add(tx);
    }
    walletResponse.addresses = addresses.toArray(new WalletResponse.Address[0]);
    walletResponse.txs = txes.toArray(new WalletResponse.Tx[0]);
    walletResponse.unspent_outputs = unspentOutputs.toArray(new UnspentOutput[0]);
    walletResponse.info = new WalletResponse.Info();
    walletResponse.info.latest_block = new WalletResponse.InfoBlock();
    walletResponse.info.latest_block.height = AppServices.getCurrentBlockHeight() == null ? storedBlockHeight : AppServices.getCurrentBlockHeight();
    walletResponse.info.latest_block.hash = Sha256Hash.ZERO_HASH.toString();
    walletResponse.info.latest_block.time = AppServices.getLatestBlockHeader() == null ? 1 : AppServices.getLatestBlockHeader().getTime();
    walletResponse.info.fees = new LinkedHashMap<>();
    for (MinerFeeTarget target : MinerFeeTarget.values()) {
        walletResponse.info.fees.put(target.getValue(), getMinerFeeSupplier().getFee(target));
    }
    return walletResponse;
}
Also used : TransactionOutput(com.sparrowwallet.drongo.protocol.TransactionOutput) WalletResponse(com.samourai.wallet.api.backend.beans.WalletResponse) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) UnspentOutput(com.samourai.wallet.api.backend.beans.UnspentOutput) TransactionInput(com.sparrowwallet.drongo.protocol.TransactionInput) MinerFeeTarget(com.samourai.wallet.api.backend.MinerFeeTarget) WhirlpoolWallet(com.samourai.whirlpool.client.wallet.WhirlpoolWallet) HD_Wallet(com.samourai.wallet.hd.HD_Wallet) ExtendedKey(com.sparrowwallet.drongo.ExtendedKey)

Example 3 with Sha256Hash

use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.

the class SorobanController method getWalletTransaction.

private WalletTransaction getWalletTransaction(Wallet wallet, WalletTransaction walletTransaction, Transaction transaction, Map<Sha256Hash, BlockTransaction> inputTransactions) {
    Map<BlockTransactionHashIndex, WalletNode> allWalletUtxos = wallet.getWalletTxos();
    Map<BlockTransactionHashIndex, WalletNode> walletUtxos = new LinkedHashMap<>();
    Map<BlockTransactionHashIndex, WalletNode> externalUtxos = new LinkedHashMap<>();
    for (TransactionInput txInput : transaction.getInputs()) {
        Optional<BlockTransactionHashIndex> optWalletUtxo = allWalletUtxos.keySet().stream().filter(txo -> txo.getHash().equals(txInput.getOutpoint().getHash()) && txo.getIndex() == txInput.getOutpoint().getIndex()).findFirst();
        if (optWalletUtxo.isPresent()) {
            walletUtxos.put(optWalletUtxo.get(), allWalletUtxos.get(optWalletUtxo.get()));
        } else {
            BlockTransactionHashIndex externalUtxo;
            if (inputTransactions != null && inputTransactions.containsKey(txInput.getOutpoint().getHash())) {
                BlockTransaction blockTransaction = inputTransactions.get(txInput.getOutpoint().getHash());
                TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get((int) txInput.getOutpoint().getIndex());
                externalUtxo = new BlockTransactionHashIndex(blockTransaction.getHash(), blockTransaction.getHeight(), blockTransaction.getDate(), blockTransaction.getFee(), txInput.getOutpoint().getIndex(), txOutput.getValue());
            } else {
                externalUtxo = new BlockTransactionHashIndex(txInput.getOutpoint().getHash(), 0, null, null, txInput.getOutpoint().getIndex(), 0);
            }
            externalUtxos.put(externalUtxo, null);
        }
    }
    List<Map<BlockTransactionHashIndex, WalletNode>> selectedUtxoSets = new ArrayList<>();
    selectedUtxoSets.add(walletUtxos);
    selectedUtxoSets.add(externalUtxos);
    Map<Address, WalletNode> walletAddresses = wallet.getWalletAddresses();
    List<Payment> payments = new ArrayList<>();
    Map<WalletNode, Long> changeMap = new LinkedHashMap<>();
    for (TransactionOutput txOutput : transaction.getOutputs()) {
        Address address = txOutput.getScript().getToAddress();
        if (address != null) {
            Optional<Payment> optPayment = walletTransaction == null ? Optional.empty() : walletTransaction.getPayments().stream().filter(payment -> payment.getAddress().equals(address) && payment.getAmount() == txOutput.getValue()).findFirst();
            if (optPayment.isPresent()) {
                payments.add(optPayment.get());
            } else if (walletAddresses.containsKey(address) && walletAddresses.get(address).getKeyPurpose() == KeyPurpose.CHANGE) {
                changeMap.put(walletAddresses.get(address), txOutput.getValue());
            } else {
                Payment payment = new Payment(address, null, txOutput.getValue(), false);
                if (transaction.getOutputs().stream().anyMatch(txo -> txo != txOutput && txo.getValue() == txOutput.getValue())) {
                    payment.setType(Payment.Type.MIX);
                }
                payments.add(payment);
            }
        }
    }
    long fee = calculateFee(walletTransaction, selectedUtxoSets, transaction);
    return new WalletTransaction(wallet, transaction, Collections.emptyList(), selectedUtxoSets, payments, changeMap, fee, inputTransactions);
}
Also used : Address(com.sparrowwallet.drongo.address.Address) Transaction(com.sparrowwallet.drongo.protocol.Transaction) java.util(java.util) Logger(org.slf4j.Logger) PSBT(com.sparrowwallet.drongo.psbt.PSBT) com.sparrowwallet.drongo.wallet(com.sparrowwallet.drongo.wallet) LoggerFactory(org.slf4j.LoggerFactory) Collectors(java.util.stream.Collectors) Cahoots(com.samourai.wallet.cahoots.Cahoots) KeyPurpose(com.sparrowwallet.drongo.KeyPurpose) ElectrumServer(com.sparrowwallet.sparrow.net.ElectrumServer) TransactionOutput(com.sparrowwallet.drongo.protocol.TransactionOutput) TransactionDiagram(com.sparrowwallet.sparrow.control.TransactionDiagram) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) PSBTParseException(com.sparrowwallet.drongo.psbt.PSBTParseException) Pattern(java.util.regex.Pattern) TransactionInput(com.sparrowwallet.drongo.protocol.TransactionInput) TransactionOutput(com.sparrowwallet.drongo.protocol.TransactionOutput) Address(com.sparrowwallet.drongo.address.Address) TransactionInput(com.sparrowwallet.drongo.protocol.TransactionInput)

Example 4 with Sha256Hash

use of com.sparrowwallet.drongo.protocol.Sha256Hash 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)

Example 5 with Sha256Hash

use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.

the class BlockTransactionMapper method map.

@Override
public Map.Entry<Sha256Hash, BlockTransaction> map(ResultSet rs, StatementContext ctx) throws SQLException {
    Sha256Hash txid = Sha256Hash.wrap(rs.getBytes("txid"));
    byte[] txBytes = rs.getBytes("transaction");
    Transaction transaction = null;
    if (txBytes != null) {
        transaction = new Transaction(txBytes);
    }
    Long fee = rs.getLong("fee");
    if (rs.wasNull()) {
        fee = null;
    }
    BlockTransaction blockTransaction = new BlockTransaction(Sha256Hash.wrap(rs.getBytes("hash")), rs.getInt("height"), rs.getTimestamp("date"), fee, transaction, rs.getBytes("blockHash") == null ? null : Sha256Hash.wrap(rs.getBytes("blockHash")), rs.getString("label"));
    blockTransaction.setId(rs.getLong("id"));
    return new Map.Entry<>() {

        @Override
        public Sha256Hash getKey() {
            return txid;
        }

        @Override
        public BlockTransaction getValue() {
            return blockTransaction;
        }

        @Override
        public BlockTransaction setValue(BlockTransaction value) {
            return null;
        }
    };
}
Also used : Transaction(com.sparrowwallet.drongo.protocol.Transaction) BlockTransaction(com.sparrowwallet.drongo.wallet.BlockTransaction) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) BlockTransaction(com.sparrowwallet.drongo.wallet.BlockTransaction)

Aggregations

Sha256Hash (com.sparrowwallet.drongo.protocol.Sha256Hash)9 Collectors (java.util.stream.Collectors)3 Logger (org.slf4j.Logger)3 LoggerFactory (org.slf4j.LoggerFactory)3 Transaction (com.sparrowwallet.drongo.protocol.Transaction)2 TransactionInput (com.sparrowwallet.drongo.protocol.TransactionInput)2 TransactionOutput (com.sparrowwallet.drongo.protocol.TransactionOutput)2 VarInt (com.sparrowwallet.drongo.protocol.VarInt)2 com.sparrowwallet.drongo.wallet (com.sparrowwallet.drongo.wallet)2 UtxoMixData (com.sparrowwallet.drongo.wallet.UtxoMixData)2 EventManager (com.sparrowwallet.sparrow.EventManager)2 java.util (java.util)2 MapDifference (com.google.common.collect.MapDifference)1 Maps (com.google.common.collect.Maps)1 Subscribe (com.google.common.eventbus.Subscribe)1 Files (com.google.common.io.Files)1 MinerFeeTarget (com.samourai.wallet.api.backend.MinerFeeTarget)1 UnspentOutput (com.samourai.wallet.api.backend.beans.UnspentOutput)1 WalletResponse (com.samourai.wallet.api.backend.beans.WalletResponse)1 Cahoots (com.samourai.wallet.cahoots.Cahoots)1