[#1141] Implement firstUnenhancedHeight
- Transaction repository extended to provide first unenhanced height or nil [#1141] Implement firstUnenhancedHeight (#1145) - tests and mocks extended to be aware of firstUnenhancedBlock
This commit is contained in:
parent
3629861b7a
commit
f1c4947a2c
|
@ -10,6 +10,7 @@ import Foundation
|
|||
final class ChecksBeforeSyncAction {
|
||||
let internalSyncProgress: InternalSyncProgress
|
||||
let storage: CompactBlockRepository
|
||||
|
||||
init(container: DIContainer) {
|
||||
internalSyncProgress = container.resolve(InternalSyncProgress.self)
|
||||
storage = container.resolve(CompactBlockRepository.self)
|
||||
|
|
|
@ -10,6 +10,7 @@ import Foundation
|
|||
final class ClearAlreadyScannedBlocksAction {
|
||||
let storage: CompactBlockRepository
|
||||
let transactionRepository: TransactionRepository
|
||||
|
||||
init(container: DIContainer) {
|
||||
storage = container.resolve(CompactBlockRepository.self)
|
||||
transactionRepository = container.resolve(TransactionRepository.self)
|
||||
|
|
|
@ -9,6 +9,7 @@ import Foundation
|
|||
|
||||
final class ClearCacheAction {
|
||||
let storage: CompactBlockRepository
|
||||
|
||||
init(container: DIContainer) {
|
||||
storage = container.resolve(CompactBlockRepository.self)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ final class EnhanceAction {
|
|||
let internalSyncProgress: InternalSyncProgress
|
||||
let logger: Logger
|
||||
let transactionRepository: TransactionRepository
|
||||
|
||||
init(container: DIContainer, configProvider: CompactBlockProcessor.ConfigProvider) {
|
||||
blockEnhancer = container.resolve(BlockEnhancer.self)
|
||||
self.configProvider = configProvider
|
||||
|
|
|
@ -34,15 +34,74 @@ struct Block: Codable {
|
|||
let hash: Data
|
||||
let time: Int
|
||||
let saplingTree: Data
|
||||
|
||||
|
||||
static let table = Table("blocks")
|
||||
}
|
||||
|
||||
struct VTransaction: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accountId = "account_id"
|
||||
case idTx = "id_tx"
|
||||
case minedHeight = "mined_height"
|
||||
case txIndex = "tx_index"
|
||||
case txId = "txid"
|
||||
case expiryHeight = "expiry_height"
|
||||
case raw = "raw"
|
||||
case accountBalanceDelta = "account_balance_delta"
|
||||
case feePaid = "fee_paid"
|
||||
case expiredUnmined = "expired_unmined"
|
||||
case hasChange = "has_change"
|
||||
case sentNoteCount = "sent_note_count"
|
||||
case recievedNoteCount = "received_note_count"
|
||||
case memoCount = "memo_count"
|
||||
case blockTime = "block_time"
|
||||
}
|
||||
|
||||
enum TableStructure {
|
||||
static let accountId = Expression<Int>(VTransaction.CodingKeys.accountId.rawValue)
|
||||
static let idTx = Expression<Int>(VTransaction.CodingKeys.idTx.rawValue)
|
||||
static let minedHeight = Expression<Int>(VTransaction.CodingKeys.minedHeight.rawValue)
|
||||
static let txIndex = Expression<Int>(VTransaction.CodingKeys.txIndex.rawValue)
|
||||
static let txId = Expression<Data>(VTransaction.CodingKeys.txId.rawValue)
|
||||
static let expiryHeight = Expression<Int?>(VTransaction.CodingKeys.expiryHeight.rawValue)
|
||||
static let raw = Expression<Data?>(VTransaction.CodingKeys.raw.rawValue)
|
||||
static let accountBalanceDelta = Expression<Int>(VTransaction.CodingKeys.accountBalanceDelta.rawValue)
|
||||
static let feePaid = Expression<Int?>(VTransaction.CodingKeys.feePaid.rawValue)
|
||||
static let expiredUnmined = Expression<Int>(VTransaction.CodingKeys.expiredUnmined.rawValue)
|
||||
static let hasChange = Expression<Bool>(VTransaction.CodingKeys.hasChange.rawValue)
|
||||
static let sentNoteCount = Expression<Int>(VTransaction.CodingKeys.sentNoteCount.rawValue)
|
||||
static let recievedNoteCount = Expression<Int>(VTransaction.CodingKeys.recievedNoteCount.rawValue)
|
||||
static let memoCount = Expression<Int>(VTransaction.CodingKeys.memoCount.rawValue)
|
||||
static let blockTime = Expression<Int>(VTransaction.CodingKeys.blockTime.rawValue)
|
||||
}
|
||||
|
||||
let accountId: Int
|
||||
let idTx: Int
|
||||
let minedHeight: Int
|
||||
let txIndex: Int
|
||||
let txId: Data
|
||||
let expiryHeight: Int?
|
||||
let raw: Data?
|
||||
let accountBalanceDelta: Int
|
||||
let feePaid: Int?
|
||||
let expiredUnmined: Int
|
||||
let hasChange: Bool
|
||||
let sentNoteCount: Int
|
||||
let recievedNoteCount: Int
|
||||
let memoCount: Int
|
||||
let blockTime: Int
|
||||
|
||||
static let table = Table("v_transactions")
|
||||
}
|
||||
|
||||
class BlockSQLDAO: BlockDao {
|
||||
let dbProvider: ConnectionProvider
|
||||
let table: Table
|
||||
let height = Expression<Int>("height")
|
||||
|
||||
let minedHeight = Expression<Int>("mined_height")
|
||||
let raw = Expression<Data?>("raw")
|
||||
|
||||
init(dbProvider: ConnectionProvider) {
|
||||
self.dbProvider = dbProvider
|
||||
self.table = Table("Blocks")
|
||||
|
@ -103,6 +162,30 @@ class BlockSQLDAO: BlockDao {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func firstUnenhancedHeight(in range: CompactBlockRange? = nil) throws -> BlockHeight? {
|
||||
do {
|
||||
return try dbProvider
|
||||
.connection()
|
||||
.prepare(
|
||||
VTransaction.table
|
||||
.order(minedHeight.asc)
|
||||
.filter(raw == nil)
|
||||
.limit(1)
|
||||
)
|
||||
.map {
|
||||
do {
|
||||
let vTransaction: VTransaction = try $0.decode()
|
||||
return vTransaction.minedHeight
|
||||
} catch {
|
||||
throw ZcashError.blockDAOFirstUnenhancedCantDecode(error)
|
||||
}
|
||||
}
|
||||
.first
|
||||
} catch {
|
||||
throw ZcashError.blockDAOFirstUnenhancedHeight(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension BlockSQLDAO: BlockRepository {
|
||||
|
|
|
@ -49,6 +49,10 @@ class TransactionSQLDAO: TransactionRepository {
|
|||
try blockDao.latestBlock()
|
||||
}
|
||||
|
||||
func firstUnenhancedHeight() throws -> BlockHeight? {
|
||||
try blockDao.firstUnenhancedHeight()
|
||||
}
|
||||
|
||||
func isInitialized() async throws -> Bool {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -94,10 +94,18 @@ public enum ZcashError: Equatable, Error {
|
|||
/// - `sqliteError` is error produced by SQLite library.
|
||||
/// ZBDAO0004
|
||||
case blockDAOLatestBlock(_ sqliteError: Error)
|
||||
/// Fetched latesxt block information from DB but can't decode them.
|
||||
/// Fetched latest block information from DB but can't decode them.
|
||||
/// - `error` is decoding error.
|
||||
/// ZBDAO0005
|
||||
case blockDAOLatestBlockCantDecode(_ error: Error)
|
||||
/// SQLite query failed when fetching the first unenhanced block from the database.
|
||||
/// - `sqliteError` is error produced by SQLite library.
|
||||
/// ZBDAO0006
|
||||
case blockDAOFirstUnenhancedHeight(_ sqliteError: Error)
|
||||
/// Fetched unenhanced block information from DB but can't decode them.
|
||||
/// - `error` is decoding error.
|
||||
/// ZBDAO0007
|
||||
case blockDAOFirstUnenhancedCantDecode(_ error: Error)
|
||||
/// Error from rust layer when calling ZcashRustBackend.createAccount
|
||||
/// - `rustError` contains error generated by the rust layer.
|
||||
/// ZRUST0001
|
||||
|
@ -552,7 +560,9 @@ public enum ZcashError: Equatable, Error {
|
|||
case .blockDAOCantDecode: return "Fetched block information from DB but can't decode them."
|
||||
case .blockDAOLatestBlockHeight: return "SQLite query failed when fetching height of the latest block from the database."
|
||||
case .blockDAOLatestBlock: return "SQLite query failed when fetching the latest block from the database."
|
||||
case .blockDAOLatestBlockCantDecode: return "Fetched latesxt block information from DB but can't decode them."
|
||||
case .blockDAOLatestBlockCantDecode: return "Fetched latest block information from DB but can't decode them."
|
||||
case .blockDAOFirstUnenhancedHeight: return "SQLite query failed when fetching the first unenhanced block from the database."
|
||||
case .blockDAOFirstUnenhancedCantDecode: return "Fetched unenhanced block information from DB but can't decode them."
|
||||
case .rustCreateAccount: return "Error from rust layer when calling ZcashRustBackend.createAccount"
|
||||
case .rustCreateToAddress: return "Error from rust layer when calling ZcashRustBackend.createToAddress"
|
||||
case .rustDecryptAndStoreTransaction: return "Error from rust layer when calling ZcashRustBackend.decryptAndStoreTransaction"
|
||||
|
@ -710,6 +720,8 @@ public enum ZcashError: Equatable, Error {
|
|||
case .blockDAOLatestBlockHeight: return .blockDAOLatestBlockHeight
|
||||
case .blockDAOLatestBlock: return .blockDAOLatestBlock
|
||||
case .blockDAOLatestBlockCantDecode: return .blockDAOLatestBlockCantDecode
|
||||
case .blockDAOFirstUnenhancedHeight: return .blockDAOFirstUnenhancedHeight
|
||||
case .blockDAOFirstUnenhancedCantDecode: return .blockDAOFirstUnenhancedCantDecode
|
||||
case .rustCreateAccount: return .rustCreateAccount
|
||||
case .rustCreateToAddress: return .rustCreateToAddress
|
||||
case .rustDecryptAndStoreTransaction: return .rustDecryptAndStoreTransaction
|
||||
|
|
|
@ -57,8 +57,12 @@ public enum ZcashErrorCode: String {
|
|||
case blockDAOLatestBlockHeight = "ZBDAO0003"
|
||||
/// SQLite query failed when fetching the latest block from the database.
|
||||
case blockDAOLatestBlock = "ZBDAO0004"
|
||||
/// Fetched latesxt block information from DB but can't decode them.
|
||||
/// Fetched latest block information from DB but can't decode them.
|
||||
case blockDAOLatestBlockCantDecode = "ZBDAO0005"
|
||||
/// SQLite query failed when fetching the first unenhanced block from the database.
|
||||
case blockDAOFirstUnenhancedHeight = "ZBDAO0006"
|
||||
/// Fetched unenhanced block information from DB but can't decode them.
|
||||
case blockDAOFirstUnenhancedCantDecode = "ZBDAO0007"
|
||||
/// Error from rust layer when calling ZcashRustBackend.createAccount
|
||||
case rustCreateAccount = "ZRUST0001"
|
||||
/// Error from rust layer when calling ZcashRustBackend.createToAddress
|
||||
|
|
|
@ -122,10 +122,18 @@ enum ZcashErrorDefinition {
|
|||
/// - `sqliteError` is error produced by SQLite library.
|
||||
// sourcery: code="ZBDAO0004"
|
||||
case blockDAOLatestBlock(_ sqliteError: Error)
|
||||
/// Fetched latesxt block information from DB but can't decode them.
|
||||
/// Fetched latest block information from DB but can't decode them.
|
||||
/// - `error` is decoding error.
|
||||
// sourcery: code="ZBDAO0005"
|
||||
case blockDAOLatestBlockCantDecode(_ error: Error)
|
||||
/// SQLite query failed when fetching the first unenhanced block from the database.
|
||||
/// - `sqliteError` is error produced by SQLite library.
|
||||
// sourcery: code="ZBDAO0006"
|
||||
case blockDAOFirstUnenhancedHeight(_ sqliteError: Error)
|
||||
/// Fetched unenhanced block information from DB but can't decode them.
|
||||
/// - `error` is decoding error.
|
||||
// sourcery: code="ZBDAO0007"
|
||||
case blockDAOFirstUnenhancedCantDecode(_ error: Error)
|
||||
|
||||
// MARK: - Rust
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ protocol TransactionRepository {
|
|||
func blockForHeight(_ height: BlockHeight) async throws -> Block?
|
||||
func lastScannedHeight() async throws -> BlockHeight
|
||||
func lastScannedBlock() async throws -> Block?
|
||||
func firstUnenhancedHeight() throws -> BlockHeight?
|
||||
func isInitialized() async throws -> Bool
|
||||
func find(id: Int) async throws -> ZcashTransaction.Overview
|
||||
func find(rawID: Data) async throws -> ZcashTransaction.Overview
|
||||
|
|
|
@ -115,6 +115,10 @@ extension MockTransactionRepository: TransactionRepository {
|
|||
nil
|
||||
}
|
||||
|
||||
func firstUnenhancedHeight() throws -> ZcashLightClientKit.BlockHeight? {
|
||||
nil
|
||||
}
|
||||
|
||||
func isInitialized() throws -> Bool {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -1709,6 +1709,28 @@ class TransactionRepositoryMock: TransactionRepository {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - firstUnenhancedHeight
|
||||
|
||||
var firstUnenhancedHeightThrowableError: Error?
|
||||
var firstUnenhancedHeightCallsCount = 0
|
||||
var firstUnenhancedHeightCalled: Bool {
|
||||
return firstUnenhancedHeightCallsCount > 0
|
||||
}
|
||||
var firstUnenhancedHeightReturnValue: BlockHeight?
|
||||
var firstUnenhancedHeightClosure: (() throws -> BlockHeight?)?
|
||||
|
||||
func firstUnenhancedHeight() throws -> BlockHeight? {
|
||||
if let error = firstUnenhancedHeightThrowableError {
|
||||
throw error
|
||||
}
|
||||
firstUnenhancedHeightCallsCount += 1
|
||||
if let closure = firstUnenhancedHeightClosure {
|
||||
return try closure()
|
||||
} else {
|
||||
return firstUnenhancedHeightReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - isInitialized
|
||||
|
||||
var isInitializedThrowableError: Error?
|
||||
|
|
Loading…
Reference in New Issue