ZcashLightClientKit/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift

315 lines
12 KiB
Swift
Raw Normal View History

//
// PendingTransactionDao.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 11/19/19.
//
import Foundation
import SQLite
struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable {
enum CodingKeys: String, CodingKey {
case toAddress = "to_address"
case toInternalAccount = "to_internal"
case accountIndex = "account_index"
case minedHeight = "mined_height"
case expiryHeight = "expiry_height"
case cancelled
case encodeAttempts = "encode_attempts"
case submitAttempts = "submit_attempts"
case errorMessage = "error_message"
case errorCode = "error_code"
case createTime = "create_time"
case raw
case id
case value
case memo
case rawTransactionId = "txid"
case fee
}
var recipient: PendingTransactionRecipient
var accountIndex: Int
var minedHeight: BlockHeight
var expiryHeight: BlockHeight
var cancelled: Int
var encodeAttempts: Int
var submitAttempts: Int
var errorMessage: String?
var errorCode: Int?
var createTime: TimeInterval
var raw: Data?
var id: Int?
var value: Zatoshi
var memo: Data?
var rawTransactionId: Data?
var fee: Zatoshi?
2021-09-17 06:49:58 -07:00
static func from(entity: PendingTransactionEntity) -> PendingTransaction {
PendingTransaction(
recipient: entity.recipient,
2021-09-17 06:49:58 -07:00
accountIndex: entity.accountIndex,
minedHeight: entity.minedHeight,
expiryHeight: entity.expiryHeight,
cancelled: entity.cancelled,
encodeAttempts: entity.encodeAttempts,
submitAttempts: entity.submitAttempts,
errorMessage: entity.errorMessage,
errorCode: entity.errorCode,
createTime: entity.createTime,
raw: entity.raw,
id: entity.id,
value: entity.value,
memo: entity.memo,
rawTransactionId: entity.raw,
fee: entity.fee
2021-09-17 06:49:58 -07:00
)
}
init(
recipient: PendingTransactionRecipient,
accountIndex: Int,
minedHeight: BlockHeight,
expiryHeight: BlockHeight,
cancelled: Int,
encodeAttempts: Int,
submitAttempts: Int,
errorMessage: String?,
errorCode: Int?,
createTime: TimeInterval,
raw: Data?,
id: Int?,
value: Zatoshi,
memo: Data?,
rawTransactionId: Data?,
fee: Zatoshi?
) {
self.recipient = recipient
self.accountIndex = accountIndex
self.minedHeight = minedHeight
self.expiryHeight = expiryHeight
self.cancelled = cancelled
self.encodeAttempts = encodeAttempts
self.submitAttempts = submitAttempts
self.errorMessage = errorMessage
self.errorCode = errorCode
self.createTime = createTime
self.raw = raw
self.id = id
self.value = value
self.memo = memo
self.rawTransactionId = rawTransactionId
self.fee = fee
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let toAddress: String? = try container.decodeIfPresent(String.self, forKey: .toAddress)
let toInternalAccount: Int? = try container.decodeIfPresent(Int.self, forKey: .toInternalAccount)
switch (toAddress, toInternalAccount) {
case let (.some(address), nil):
guard let recipient = Recipient.forEncodedAddress(encoded: address) else {
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.malformedEntity(fields: ["toAddress"])
}
self.recipient = .address(recipient.0)
case let (nil, .some(accountId)):
self.recipient = .internalAccount(UInt32(accountId))
default:
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.malformedEntity(fields: ["toAddress", "toInternalAccount"])
}
self.accountIndex = try container.decode(Int.self, forKey: .accountIndex)
self.minedHeight = try container.decode(BlockHeight.self, forKey: .minedHeight)
self.expiryHeight = try container.decode(BlockHeight.self, forKey: .expiryHeight)
self.cancelled = try container.decode(Int.self, forKey: .cancelled)
self.encodeAttempts = try container.decode(Int.self, forKey: .encodeAttempts)
self.submitAttempts = try container.decode(Int.self, forKey: .submitAttempts)
self.errorMessage = try container.decodeIfPresent(String.self, forKey: .errorMessage)
self.errorCode = try container.decodeIfPresent(Int.self, forKey: .errorCode)
self.createTime = try container.decode(TimeInterval.self, forKey: .createTime)
self.raw = try container.decodeIfPresent(Data.self, forKey: .raw)
self.id = try container.decodeIfPresent(Int.self, forKey: .id)
let zatoshiValue = try container.decode(Int64.self, forKey: .value)
self.value = Zatoshi(zatoshiValue)
self.memo = try container.decodeIfPresent(Data.self, forKey: .memo)
self.rawTransactionId = try container.decodeIfPresent(Data.self, forKey: .rawTransactionId)
2022-10-21 14:19:08 -07:00
if let feeValue = try container.decodeIfPresent(Int64.self, forKey: .fee) {
self.fee = Zatoshi(feeValue)
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var toAddress: String?
var accountId: Int?
switch recipient {
case .address(let recipient):
toAddress = recipient.stringEncoded
case .internalAccount(let acct):
accountId = Int(acct)
}
try container.encodeIfPresent(toAddress, forKey: .toAddress)
try container.encodeIfPresent(accountId, forKey: .toInternalAccount)
try container.encode(self.accountIndex, forKey: .accountIndex)
try container.encode(self.minedHeight, forKey: .minedHeight)
try container.encode(self.expiryHeight, forKey: .expiryHeight)
try container.encode(self.cancelled, forKey: .cancelled)
try container.encode(self.encodeAttempts, forKey: .encodeAttempts)
try container.encode(self.submitAttempts, forKey: .submitAttempts)
try container.encodeIfPresent(self.errorMessage, forKey: .errorMessage)
try container.encodeIfPresent(self.errorCode, forKey: .errorCode)
try container.encode(self.createTime, forKey: .createTime)
try container.encodeIfPresent(self.raw, forKey: .raw)
try container.encodeIfPresent(self.id, forKey: .id)
try container.encode(self.value.amount, forKey: .value)
try container.encodeIfPresent(self.memo, forKey: .memo)
try container.encodeIfPresent(self.rawTransactionId, forKey: .rawTransactionId)
2022-10-21 14:19:08 -07:00
try container.encodeIfPresent(self.fee?.amount, forKey: .fee)
}
func isSameTransactionId<T>(other: T) -> Bool where T: RawIdentifiable {
self.rawTransactionId == other.rawTransactionId
}
}
extension PendingTransaction {
init(value: Zatoshi, recipient: PendingTransactionRecipient, memo: MemoBytes?, account index: Int) {
var memoData: Data?
if let memo = memo {
memoData = Data(memo.bytes)
}
2021-09-17 06:49:58 -07:00
self = PendingTransaction(
recipient: recipient,
2021-09-17 06:49:58 -07:00
accountIndex: index,
minedHeight: -1,
expiryHeight: -1,
cancelled: 0,
encodeAttempts: 0,
submitAttempts: 0,
errorMessage: nil,
errorCode: nil,
createTime: Date().timeIntervalSince1970,
raw: nil,
id: nil,
value: value,
memo: memoData,
rawTransactionId: nil,
fee: nil
2021-09-17 06:49:58 -07:00
)
}
}
class PendingTransactionSQLDAO: PendingTransactionRepository {
2021-09-17 06:49:58 -07:00
enum TableColumns {
static var toAddress = Expression<String?>("to_address")
static var toInternalAccount = Expression<Int?>("to_internal")
static var accountIndex = Expression<Int>("account_index")
static var minedHeight = Expression<Int?>("mined_height")
static var expiryHeight = Expression<Int?>("expiry_height")
static var cancelled = Expression<Int?>("cancelled")
static var encodeAttempts = Expression<Int?>("encode_attempts")
static var errorMessage = Expression<String?>("error_message")
static var submitAttempts = Expression<Int?>("submit_attempts")
static var errorCode = Expression<Int?>("error_code")
static var createTime = Expression<TimeInterval?>("create_time")
static var raw = Expression<Blob?>("raw")
static var id = Expression<Int>("id")
static var value = Expression<Zatoshi>("value")
static var memo = Expression<Blob?>("memo")
static var rawTransactionId = Expression<Blob?>("txid")
static var fee = Expression<Zatoshi?>("fee")
}
static let table = Table("pending_transactions")
var dbProvider: ConnectionProvider
init(dbProvider: ConnectionProvider) {
self.dbProvider = dbProvider
}
func closeDBConnection() {
dbProvider.close()
}
func create(_ transaction: PendingTransactionEntity) throws -> Int {
2021-09-15 05:21:29 -07:00
let pendingTx = transaction as? PendingTransaction ?? PendingTransaction.from(entity: transaction)
return try Int(dbProvider.connection().run(Self.table.insert(pendingTx)))
}
func update(_ transaction: PendingTransactionEntity) throws {
2021-09-15 05:21:29 -07:00
let pendingTx = transaction as? PendingTransaction ?? PendingTransaction.from(entity: transaction)
guard let id = pendingTx.id else {
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.malformedEntity(fields: ["id"])
}
let updatedRows = try dbProvider.connection().run(Self.table.filter(TableColumns.id == id).update(pendingTx))
if updatedRows == 0 {
LoggerProxy.error("attempted to update pending transactions but no rows were updated")
}
}
func delete(_ transaction: PendingTransactionEntity) throws {
guard let id = transaction.id else {
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.malformedEntity(fields: ["id"])
2021-09-17 06:49:58 -07:00
}
do {
try dbProvider.connection().run(Self.table.filter(TableColumns.id == id).delete())
} catch {
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.updateFailed
}
}
func cancel(_ transaction: PendingTransactionEntity) throws {
2021-09-15 05:21:29 -07:00
var pendingTx = transaction as? PendingTransaction ?? PendingTransaction.from(entity: transaction)
pendingTx.cancelled = 1
guard let txId = pendingTx.id else {
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.malformedEntity(fields: ["id"])
}
try dbProvider.connection().run(Self.table.filter(TableColumns.id == txId).update(pendingTx))
}
func find(by id: Int) throws -> PendingTransactionEntity? {
guard let row = try dbProvider.connection().pluck(Self.table.filter(TableColumns.id == id).limit(1)) else {
return nil
}
do {
2021-09-15 05:21:29 -07:00
let pendingTx: PendingTransaction = try row.decode()
2021-09-15 05:21:29 -07:00
return pendingTx
} catch {
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
throw DatabaseStorageError.operationFailed
}
}
func getAll() throws -> [PendingTransactionEntity] {
let allTxs: [PendingTransaction] = try dbProvider.connection().prepare(Self.table).map { row in
try row.decode()
2021-09-17 06:49:58 -07:00
}
return allTxs
}
func applyMinedHeight(_ height: BlockHeight, id: Int) throws {
let transaction = Self.table.filter(TableColumns.id == id)
2021-09-17 06:49:58 -07:00
let updatedRows = try dbProvider.connection()
.run(transaction.update([TableColumns.minedHeight <- height]))
2021-09-17 06:49:58 -07:00
if updatedRows == 0 {
LoggerProxy.error("attempted to update a row but none was updated")
}
}
}