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