Search in sources :

Example 6 with Sha256Hash

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

the class DbPersistence method update.

private void update(Storage storage, Wallet wallet, String password) throws StorageException {
    DirtyPersistables dirtyPersistables = dirtyPersistablesMap.get(wallet);
    if (dirtyPersistables == null) {
        return;
    }
    log.debug("Updating " + wallet.getFullName() + " on " + Thread.currentThread().getName());
    log.debug(dirtyPersistables.toString());
    Jdbi jdbi = getJdbi(storage, password);
    List<String> schemas = jdbi.withHandle(handle -> {
        return handle.createQuery("show schemas").mapTo(String.class).list();
    });
    if (!schemas.contains(getSchema(wallet))) {
        log.debug("Not persisting update for missing schema " + getSchema(wallet));
        return;
    }
    jdbi.useHandle(handle -> {
        WalletDao walletDao = handle.attach(WalletDao.class);
        try {
            if (dirtyPersistables.deleteAccount && !wallet.isMasterWallet()) {
                handle.execute("drop schema `" + getSchema(wallet) + "` cascade");
                return;
            }
            walletDao.setSchema(getSchema(wallet));
            if (dirtyPersistables.clearHistory) {
                WalletNodeDao walletNodeDao = handle.attach(WalletNodeDao.class);
                BlockTransactionDao blockTransactionDao = handle.attach(BlockTransactionDao.class);
                DetachedLabelDao detachedLabelDao = handle.attach(DetachedLabelDao.class);
                detachedLabelDao.clearAndAddAll(wallet);
                walletNodeDao.clearHistory(wallet);
                blockTransactionDao.clear(wallet.getId());
            }
            if (!dirtyPersistables.historyNodes.isEmpty()) {
                WalletNodeDao walletNodeDao = handle.attach(WalletNodeDao.class);
                BlockTransactionDao blockTransactionDao = handle.attach(BlockTransactionDao.class);
                Set<Sha256Hash> referencedTxIds = new HashSet<>();
                for (WalletNode addressNode : dirtyPersistables.historyNodes) {
                    if (addressNode.getId() == null) {
                        WalletNode purposeNode = wallet.getNode(addressNode.getKeyPurpose());
                        if (purposeNode.getId() == null) {
                            long purposeNodeId = walletNodeDao.insertWalletNode(purposeNode.getDerivationPath(), purposeNode.getLabel(), wallet.getId(), null);
                            purposeNode.setId(purposeNodeId);
                        }
                        long nodeId = walletNodeDao.insertWalletNode(addressNode.getDerivationPath(), addressNode.getLabel(), wallet.getId(), purposeNode.getId());
                        addressNode.setId(nodeId);
                    }
                    Set<BlockTransactionHashIndex> txos = addressNode.getTransactionOutputs().stream().flatMap(txo -> txo.isSpent() ? Stream.of(txo, txo.getSpentBy()) : Stream.of(txo)).collect(Collectors.toSet());
                    List<Long> existingIds = txos.stream().map(Persistable::getId).filter(Objects::nonNull).collect(Collectors.toList());
                    referencedTxIds.addAll(txos.stream().map(BlockTransactionHash::getHash).collect(Collectors.toSet()));
                    walletNodeDao.deleteNodeTxosNotInList(addressNode, existingIds.isEmpty() ? List.of(-1L) : existingIds);
                    for (BlockTransactionHashIndex txo : addressNode.getTransactionOutputs()) {
                        walletNodeDao.addOrUpdate(addressNode, txo);
                    }
                }
                for (Sha256Hash txid : referencedTxIds) {
                    BlockTransaction blkTx = wallet.getTransactions().get(txid);
                    blockTransactionDao.addOrUpdate(wallet, txid, blkTx);
                }
                if (!dirtyPersistables.clearHistory) {
                    DetachedLabelDao detachedLabelDao = handle.attach(DetachedLabelDao.class);
                    detachedLabelDao.clearAndAddAll(wallet);
                }
            }
            if (dirtyPersistables.label != null) {
                walletDao.updateLabel(wallet.getId(), dirtyPersistables.label.length() > 255 ? dirtyPersistables.label.substring(0, 255) : dirtyPersistables.label);
            }
            if (dirtyPersistables.blockHeight != null) {
                walletDao.updateStoredBlockHeight(wallet.getId(), dirtyPersistables.blockHeight);
            }
            if (dirtyPersistables.gapLimit != null) {
                walletDao.updateGapLimit(wallet.getId(), dirtyPersistables.gapLimit);
            }
            if (dirtyPersistables.watchLast != null) {
                walletDao.updateWatchLast(wallet.getId(), dirtyPersistables.watchLast);
            }
            if (!dirtyPersistables.labelEntries.isEmpty()) {
                BlockTransactionDao blockTransactionDao = handle.attach(BlockTransactionDao.class);
                WalletNodeDao walletNodeDao = handle.attach(WalletNodeDao.class);
                for (Entry entry : dirtyPersistables.labelEntries) {
                    if (entry instanceof TransactionEntry && ((TransactionEntry) entry).getBlockTransaction().getId() != null) {
                        blockTransactionDao.updateLabel(((TransactionEntry) entry).getBlockTransaction().getId(), entry.getLabel());
                    } else if (entry instanceof NodeEntry) {
                        WalletNode addressNode = ((NodeEntry) entry).getNode();
                        if (addressNode.getId() == null) {
                            WalletNode purposeNode = wallet.getNode(addressNode.getKeyPurpose());
                            if (purposeNode.getId() == null) {
                                long purposeNodeId = walletNodeDao.insertWalletNode(purposeNode.getDerivationPath(), purposeNode.getLabel(), wallet.getId(), null);
                                purposeNode.setId(purposeNodeId);
                            }
                            long nodeId = walletNodeDao.insertWalletNode(addressNode.getDerivationPath(), addressNode.getLabel(), wallet.getId(), purposeNode.getId());
                            addressNode.setId(nodeId);
                        }
                        walletNodeDao.updateNodeLabel(addressNode.getId(), entry.getLabel());
                    } else if (entry instanceof HashIndexEntry && ((HashIndexEntry) entry).getHashIndex().getId() != null) {
                        walletNodeDao.updateTxoLabel(((HashIndexEntry) entry).getHashIndex().getId(), entry.getLabel());
                    }
                }
            }
            if (!dirtyPersistables.utxoStatuses.isEmpty()) {
                WalletNodeDao walletNodeDao = handle.attach(WalletNodeDao.class);
                for (BlockTransactionHashIndex utxo : dirtyPersistables.utxoStatuses) {
                    walletNodeDao.updateTxoStatus(utxo.getId(), utxo.getStatus() == null ? null : utxo.getStatus().ordinal());
                }
            }
            if (dirtyPersistables.mixConfig) {
                MixConfigDao mixConfigDao = handle.attach(MixConfigDao.class);
                mixConfigDao.addOrUpdate(wallet, wallet.getMixConfig());
            }
            if (!dirtyPersistables.changedUtxoMixes.isEmpty()) {
                UtxoMixDataDao utxoMixDataDao = handle.attach(UtxoMixDataDao.class);
                for (Map.Entry<Sha256Hash, UtxoMixData> utxoMixDataEntry : dirtyPersistables.changedUtxoMixes.entrySet()) {
                    utxoMixDataDao.addOrUpdate(wallet, utxoMixDataEntry.getKey(), utxoMixDataEntry.getValue());
                }
            }
            if (!dirtyPersistables.removedUtxoMixes.isEmpty()) {
                UtxoMixDataDao utxoMixDataDao = handle.attach(UtxoMixDataDao.class);
                List<Long> ids = dirtyPersistables.removedUtxoMixes.values().stream().map(Persistable::getId).filter(Objects::nonNull).collect(Collectors.toList());
                utxoMixDataDao.deleteUtxoMixData(ids);
            }
            if (!dirtyPersistables.labelKeystores.isEmpty()) {
                KeystoreDao keystoreDao = handle.attach(KeystoreDao.class);
                for (Keystore keystore : dirtyPersistables.labelKeystores) {
                    keystoreDao.updateLabel(keystore.getLabel(), keystore.getId());
                }
            }
            if (!dirtyPersistables.encryptionKeystores.isEmpty()) {
                KeystoreDao keystoreDao = handle.attach(KeystoreDao.class);
                for (Keystore keystore : dirtyPersistables.encryptionKeystores) {
                    keystoreDao.updateKeystoreEncryption(keystore);
                }
            }
            dirtyPersistablesMap.remove(wallet);
        } finally {
            walletDao.setSchema(DEFAULT_SCHEMA);
        }
    });
}
Also used : java.util(java.util) FlywayException(org.flywaydb.core.api.FlywayException) AsymmetricKeyDeriver(com.sparrowwallet.drongo.crypto.AsymmetricKeyDeriver) com.sparrowwallet.drongo.wallet(com.sparrowwallet.drongo.wallet) LoggerFactory(org.slf4j.LoggerFactory) ByteBuffer(java.nio.ByteBuffer) StandardCopyOption(java.nio.file.StandardCopyOption) SecureRandom(java.security.SecureRandom) Files(com.google.common.io.Files) Utils(com.sparrowwallet.drongo.Utils) InvalidPasswordException(com.sparrowwallet.drongo.crypto.InvalidPasswordException) Subscribe(com.google.common.eventbus.Subscribe) H2DatabasePlugin(org.jdbi.v3.core.h2.H2DatabasePlugin) ExecutorService(java.util.concurrent.ExecutorService) com.sparrowwallet.sparrow.wallet(com.sparrowwallet.sparrow.wallet) Jdbi(org.jdbi.v3.core.Jdbi) Argon2KeyDeriver(com.sparrowwallet.drongo.crypto.Argon2KeyDeriver) SqlObjectPlugin(org.jdbi.v3.sqlobject.SqlObjectPlugin) Logger(org.slf4j.Logger) com.sparrowwallet.sparrow.event(com.sparrowwallet.sparrow.event) BasicThreadFactory(org.apache.commons.lang3.concurrent.BasicThreadFactory) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) Executors(java.util.concurrent.Executors) ChangeFileEncryption(org.h2.tools.ChangeFileEncryption) TimeUnit(java.util.concurrent.TimeUnit) HikariConfig(com.zaxxer.hikari.HikariConfig) Stream(java.util.stream.Stream) java.io(java.io) com.sparrowwallet.sparrow.io(com.sparrowwallet.sparrow.io) HikariDataSource(com.zaxxer.hikari.HikariDataSource) EventManager(com.sparrowwallet.sparrow.EventManager) ECKey(com.sparrowwallet.drongo.crypto.ECKey) Flyway(org.flywaydb.core.Flyway) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) HikariPool(com.zaxxer.hikari.pool.HikariPool) FlywayValidateException(org.flywaydb.core.api.exception.FlywayValidateException) FileChannel(java.nio.channels.FileChannel) Jdbi(org.jdbi.v3.core.Jdbi) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash)

Example 7 with Sha256Hash

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

the class UtxoMixDataMapper method map.

@Override
public Map.Entry<Sha256Hash, UtxoMixData> map(ResultSet rs, StatementContext ctx) throws SQLException {
    Sha256Hash hash = Sha256Hash.wrap(rs.getBytes("hash"));
    Long expired = rs.getLong("expired");
    if (rs.wasNull()) {
        expired = null;
    }
    UtxoMixData utxoMixData = new UtxoMixData(rs.getInt("mixesDone"), expired);
    utxoMixData.setId(rs.getLong("id"));
    return new Map.Entry<>() {

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

        @Override
        public UtxoMixData getValue() {
            return utxoMixData;
        }

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

Example 8 with Sha256Hash

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

the class PSBTEntry method parseTaprootKeyDerivation.

public static Map<KeyDerivation, List<Sha256Hash>> parseTaprootKeyDerivation(byte[] data) throws PSBTParseException {
    if (data.length < 1) {
        throw new PSBTParseException("Invalid taproot key derivation: no bytes");
    }
    VarInt varInt = new VarInt(data, 0);
    int offset = varInt.getOriginalSizeInBytes();
    if (data.length < offset + (varInt.value * 32)) {
        throw new PSBTParseException("Invalid taproot key derivation: not enough bytes for leaf hashes");
    }
    List<Sha256Hash> leafHashes = new ArrayList<>();
    for (int i = 0; i < varInt.value; i++) {
        leafHashes.add(Sha256Hash.wrap(Arrays.copyOfRange(data, offset + (i * 32), offset + (i * 32) + 32)));
    }
    KeyDerivation keyDerivation = parseKeyDerivation(Arrays.copyOfRange(data, offset + (leafHashes.size() * 32), data.length));
    return Map.of(keyDerivation, leafHashes);
}
Also used : VarInt(com.sparrowwallet.drongo.protocol.VarInt) KeyDerivation(com.sparrowwallet.drongo.KeyDerivation) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) ArrayList(java.util.ArrayList)

Example 9 with Sha256Hash

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

the class PSBTEntry method serializeTaprootKeyDerivation.

public static byte[] serializeTaprootKeyDerivation(List<Sha256Hash> leafHashes, KeyDerivation keyDerivation) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    VarInt hashesLen = new VarInt(leafHashes.size());
    baos.writeBytes(hashesLen.encode());
    for (Sha256Hash leafHash : leafHashes) {
        baos.writeBytes(leafHash.getBytes());
    }
    baos.writeBytes(serializeKeyDerivation(keyDerivation));
    return baos.toByteArray();
}
Also used : VarInt(com.sparrowwallet.drongo.protocol.VarInt) Sha256Hash(com.sparrowwallet.drongo.protocol.Sha256Hash) ByteArrayOutputStream(java.io.ByteArrayOutputStream)

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