113 lines
3.1 KiB
Swift
113 lines
3.1 KiB
Swift
//
|
|
// CompactBlockStorage.swift
|
|
// ZcashLightClientKit
|
|
//
|
|
// Created by Francisco Gindre on 10/13/19.
|
|
// Copyright © 2019 Electric Coin Company. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import SQLite
|
|
|
|
protocol ConnectionProvider {
|
|
func connection() throws -> Connection
|
|
}
|
|
|
|
class CompactBlockStorage: CompactBlockDAO {
|
|
var dbProvider: ConnectionProvider
|
|
|
|
init(connectionProvider: ConnectionProvider) {
|
|
dbProvider = connectionProvider
|
|
}
|
|
|
|
private func compactBlocksTable() -> Table {
|
|
Table("compactblocks")
|
|
}
|
|
private func heightColumn() -> Expression<Int64> {
|
|
Expression<Int64>("height")
|
|
}
|
|
private func dataColumn() -> Expression<Blob> {
|
|
Expression<Blob>("data")
|
|
}
|
|
func createTable() throws {
|
|
do {
|
|
let compactBlocks = compactBlocksTable()
|
|
let height = heightColumn()
|
|
let data = dataColumn()
|
|
|
|
let db = try dbProvider.connection()
|
|
|
|
try db.run(compactBlocks.create(ifNotExists: true) { table in
|
|
table.column(height, primaryKey: true)
|
|
table.column(data)
|
|
}
|
|
)
|
|
|
|
try db.run(compactBlocks.createIndex(height, ifNotExists: true))
|
|
} catch {
|
|
throw StorageError.couldNotCreate
|
|
}
|
|
}
|
|
|
|
func insert(_ block: ZcashCompactBlock) throws {
|
|
try dbProvider.connection().run(compactBlocksTable().insert(block))
|
|
}
|
|
|
|
func insert(_ blocks: [ZcashCompactBlock]) throws {
|
|
let compactBlocks = compactBlocksTable()
|
|
let db = try dbProvider.connection()
|
|
try db.transaction(.immediate) {
|
|
for block in blocks {
|
|
try db.run(compactBlocks.insert(block))
|
|
}
|
|
}
|
|
}
|
|
|
|
func latestBlockHeight() throws -> BlockHeight {
|
|
guard let maxHeight = try dbProvider.connection().scalar(compactBlocksTable().select(heightColumn().max)) else {
|
|
return BlockHeight.empty()
|
|
}
|
|
|
|
guard let blockHeight = BlockHeight(exactly: maxHeight) else {
|
|
throw StorageError.operationFailed
|
|
}
|
|
|
|
return blockHeight
|
|
}
|
|
|
|
func rewind(to height: BlockHeight) throws {
|
|
try dbProvider.connection().run(compactBlocksTable().filter(heightColumn() >= Int64(height)).delete())
|
|
}
|
|
}
|
|
|
|
extension CompactBlockStorage: CompactBlockRepository {
|
|
func latestHeight() throws -> BlockHeight {
|
|
try latestBlockHeight()
|
|
}
|
|
|
|
func latestHeightAsync() async throws -> BlockHeight {
|
|
let task = Task(priority: .userInitiated) {
|
|
try latestBlockHeight()
|
|
}
|
|
return try await task.value
|
|
}
|
|
|
|
func write(blocks: [ZcashCompactBlock]) throws {
|
|
try insert(blocks)
|
|
}
|
|
|
|
func writeAsync(blocks: [ZcashCompactBlock]) async throws {
|
|
let task = Task(priority: .userInitiated) {
|
|
try insert(blocks)
|
|
}
|
|
try await task.value
|
|
}
|
|
|
|
func rewindAsync(to height: BlockHeight) async throws {
|
|
let task = Task(priority: .userInitiated) {
|
|
try rewind(to: height)
|
|
}
|
|
try await task.value
|
|
}
|
|
}
|