Skip to content

Commit

Permalink
Update zcash to last verion. Fix and refactoring code.
Browse files Browse the repository at this point in the history
  • Loading branch information
ant013 authored and esen committed Apr 24, 2023
1 parent bb12146 commit d5df1ef
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 135 deletions.
22 changes: 2 additions & 20 deletions UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2077,7 +2077,6 @@
D09200C6293F21720091981A /* RestoreNonStandardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09200C0293F21710091981A /* RestoreNonStandardViewModel.swift */; };
D09200C8293F21720091981A /* RestoreNonStandardModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09200C1293F21720091981A /* RestoreNonStandardModule.swift */; };
D09200C9293F21720091981A /* RestoreNonStandardModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09200C1293F21720091981A /* RestoreNonStandardModule.swift */; };
D0C87E66298D17D5000CA9BE /* libzcashlc in Frameworks */ = {isa = PBXBuildFile; productRef = D0C87E65298D17D5000CA9BE /* libzcashlc */; };
D0D5BCBC2976CB9F00587FDB /* PasswordInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D5BCBB2976CB9F00587FDB /* PasswordInputView.swift */; };
D0D5BCBD2976CB9F00587FDB /* PasswordInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D5BCBB2976CB9F00587FDB /* PasswordInputView.swift */; };
D0D5BCC02976D3B300587FDB /* PsswordInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D5BCBF2976D3B300587FDB /* PsswordInputCell.swift */; };
Expand Down Expand Up @@ -3497,7 +3496,6 @@
D3604E8828F03D9E0066C366 /* DashKit in Frameworks */,
D3C187B32907A60800FE1900 /* HdWalletKit in Frameworks */,
D3604E5028F02AE70066C366 /* UniswapKit in Frameworks */,
D0C87E66298D17D5000CA9BE /* libzcashlc in Frameworks */,
D3604E7328F03B0A0066C366 /* ScanQrKit in Frameworks */,
D3BF1E63274CBBCE00229A00 /* DeepDiff in Frameworks */,
D3993DA528F4229F008720FB /* ZcashLightClientKit in Frameworks */,
Expand Down Expand Up @@ -6645,7 +6643,6 @@
D3C187DD290FCFE400FE1900 /* StorageKit */,
D339A93C29126D0F00B895BE /* HsCryptoKit */,
6B423FD32913785800EE5E70 /* BitcoinCore */,
D0C87E65298D17D5000CA9BE /* libzcashlc */,
6BDA29AC29D6F384003847ED /* ECashKit */,
6BDA29AF29D6F934003847ED /* HsToolKit */,
);
Expand Down Expand Up @@ -6727,7 +6724,6 @@
D3C187DC290FCFE400FE1900 /* XCRemoteSwiftPackageReference "StorageKit.Swift" */,
D339A93B29126D0E00B895BE /* XCRemoteSwiftPackageReference "HsCryptoKit.Swift" */,
6B423FD22913785800EE5E70 /* XCRemoteSwiftPackageReference "BitcoinCore.Swift" */,
D0C87E64298D17D5000CA9BE /* XCRemoteSwiftPackageReference "zcash-light-client-ffi" */,
6BDA29A929D6EA9B003847ED /* XCRemoteSwiftPackageReference "ECashKit.Swift" */,
6BDA29AE29D6F934003847ED /* XCRemoteSwiftPackageReference "HsToolKit.Swift" */,
);
Expand Down Expand Up @@ -9294,15 +9290,6 @@
version = 1.0.2;
};
};
D0C87E64298D17D5000CA9BE /* XCRemoteSwiftPackageReference "zcash-light-client-ffi" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/zcash-hackworks/zcash-light-client-ffi";
requirement = {
kind = versionRange;
maximumVersion = 1.0.0;
minimumVersion = 0.2.0;
};
};
D0DA740B272A6EFC0072BE86 /* XCRemoteSwiftPackageReference "UnicodeURL" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/nysander/UnicodeURL.git";
Expand Down Expand Up @@ -9475,8 +9462,8 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/zcash/ZcashLightClientKit";
requirement = {
kind = revision;
revision = 690b5aa67f67dfa414f1b4aea07a1bf11fa9687e;
kind = exactVersion;
version = "0.21.0-beta";
};
};
D3993DAA28F42549008720FB /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */ = {
Expand Down Expand Up @@ -9624,11 +9611,6 @@
package = 6BDA29AE29D6F934003847ED /* XCRemoteSwiftPackageReference "HsToolKit.Swift" */;
productName = HsToolKit;
};
D0C87E65298D17D5000CA9BE /* libzcashlc */ = {
isa = XCSwiftPackageProductDependency;
package = D0C87E64298D17D5000CA9BE /* XCRemoteSwiftPackageReference "zcash-light-client-ffi" */;
productName = libzcashlc;
};
D0DA740C272A6EFC0072BE86 /* IDNSDK */ = {
isa = XCSwiftPackageProductDependency;
package = D0DA740B272A6EFC0072BE86 /* XCRemoteSwiftPackageReference "UnicodeURL" */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import HsExtensions
import Combine

class ZcashAdapter {
private static let endPoint = "lightwalletd.electriccoin.co" //"mainnet.lightwalletd.com"
private let queue = DispatchQueue(label: "io.horizontalsystems.unstoppable.zcash-adapter", qos: .userInitiated)

private let disposeBag = DisposeBag()
Expand All @@ -28,9 +29,9 @@ class ZcashAdapter {
private let uniqueId: String
private let seedData: [UInt8]
private let birthday: BlockHeight
private let viewingKey: UnifiedFullViewingKey // this being a single account does not need to be an array
private let spendingKey: UnifiedSpendingKey
private let logger: HsToolKit.Logger?
private var viewingKey: UnifiedFullViewingKey? // this being a single account does not need to be an array
private var spendingKey: UnifiedSpendingKey?
private var logger: HsToolKit.Logger?

private(set) var network: ZcashNetwork
private(set) var fee: Decimal
Expand Down Expand Up @@ -86,7 +87,7 @@ class ZcashAdapter {
}

init(wallet: Wallet, restoreSettings: RestoreSettings) throws {
logger = /*App.shared.logger.scoped(with: "ZCashKit")*/HsToolKit.Logger(minLogLevel: .debug)//
logger = App.shared.logger.scoped(with: "ZCashKit") //HsToolKit.Logger(minLogLevel: .debug)

guard let seed = wallet.account.type.mnemonicSeed else {
throw AdapterError.unsupportedAccount
Expand All @@ -95,8 +96,6 @@ class ZcashAdapter {
network = ZcashNetworkBuilder.network(for: .mainnet)
fee = network.constants.defaultFee().decimalValue.decimalValue

let endPoint = "lightwalletd.electriccoin.co" //"mainnet.lightwalletd.com"

token = wallet.token
transactionSource = wallet.transactionSource
uniqueId = wallet.account.id
Expand All @@ -115,30 +114,8 @@ class ZcashAdapter {

let seedData = [UInt8](seed)
self.seedData = seedData
let derivationTool = DerivationTool(networkType: network.networkType)

guard let unifiedSpendingKey = try? derivationTool.deriveUnifiedSpendingKey(seed: seedData, accountIndex: 0),
let unifiedViewingKey = try? unifiedSpendingKey.deriveFullViewingKey() else {
throw AppError.ZcashError.noReceiveAddress
}

let initializer = Initializer(
cacheDbURL: nil,
fsBlockDbRoot: try ZcashAdapter.fsBlockDbRootURL(uniqueId: uniqueId, network: network),
dataDbURL: try ZcashAdapter.dataDbURL(uniqueId: uniqueId, network: network),
pendingDbURL: try ZcashAdapter.pendingDbURL(uniqueId: uniqueId, network: network),
endpoint: LightWalletEndpoint(address: endPoint, port: 9067, secure: true, streamingCallTimeoutInMillis: 10 * 60 * 60 * 1000),
network: network,
spendParamsURL: try ZcashAdapter.spendParamsURL(uniqueId: uniqueId),
outputParamsURL: try ZcashAdapter.outputParamsURL(uniqueId: uniqueId),
saplingParamsSourceURL: SaplingParamsSourceURL.default,
alias: .custom(uniqueId),
logLevel: .error
)

spendingKey = unifiedSpendingKey
viewingKey = unifiedViewingKey

let initializer = try ZcashAdapter.initializer(network: network, uniqueId: uniqueId)
synchronizer = SDKSynchronizer(initializer: initializer)

// subscribe on sync states
Expand All @@ -159,16 +136,27 @@ class ZcashAdapter {
NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
subscribe(disposeBag, saplingDownloader.stateObservable) { [weak self] in self?.downloaderStatusUpdated(state: $0) }

prepare(seedData: seedData, viewingKeys: [unifiedViewingKey], walletBirthday: birthday)
prepare(initializer: initializer, seedData: seedData, walletBirthday: birthday)
}

private func prepare(seedData: [UInt8]?, viewingKeys: [UnifiedFullViewingKey], walletBirthday: BlockHeight) {
private func prepare(initializer: Initializer, seedData: [UInt8], walletBirthday: BlockHeight) {
preparing = true
state = .preparing

Task {
do {
let result = try await synchronizer.prepare(with: seedData, viewingKeys: viewingKeys, walletBirthday: walletBirthday)
let tool = initializer.makeDerivationTool()
guard let unifiedSpendingKey = try? await tool.deriveUnifiedSpendingKey(seed: seedData, accountIndex: 0),
let unifiedViewingKey = try? await tool.deriveUnifiedFullViewingKey(from: unifiedSpendingKey) else {

throw AppError.ZcashError.cantCreateKeys
}

spendingKey = unifiedSpendingKey
viewingKey = unifiedViewingKey


let result = try await synchronizer.prepare(with: seedData, viewingKeys: [unifiedViewingKey], walletBirthday: walletBirthday)
if case .seedRequired = result {
throw AppError.ZcashError.seedRequired
}
Expand Down Expand Up @@ -293,7 +281,7 @@ class ZcashAdapter {
case .foundTransactions(let transactions, let inRange):
logger?.log(level: .debug, message: "found \(transactions.count) mined txs in range: \(inRange)")
transactions.forEach { overview in
logger?.log(level: .debug, message: "tx: \(overview.value.decimalValue.decimalString) : \(overview.fee?.decimalString()) : \(overview.raw?.hs.hex)")
logger?.log(level: .debug, message: "tx: v =\(overview.value.decimalValue.decimalString) : fee = \(overview.fee?.decimalString() ?? "N/A") : height = \(overview.minedHeight?.description ?? "N/A")")
}
Task {
let newTxs = await transactionPool?.sync(transactions: transactions) ?? []
Expand All @@ -302,7 +290,7 @@ class ZcashAdapter {
})
}
case .minedTransaction(let pendingEntity):
logger?.log(level: .debug, message: "found pending tx")
logger?.log(level: .debug, message: "found pending tx: v =\(pendingEntity.value.decimalValue.decimalString) : fee = \(pendingEntity.fee?.decimalString() ?? "N/A")")
update(transactions: [pendingEntity])
default:
logger?.log(level: .debug, message: "Event: \(event)")
Expand Down Expand Up @@ -478,9 +466,9 @@ class ZcashAdapter {

deinit {
NotificationCenter.default.removeObserver(self)
Task {
await synchronizer.stop()
logger?.log(level: .debug, message: "Synchronizer Was Stopped")
Task { [weak self] in
await self?.synchronizer.stop()
self?.logger?.log(level: .debug, message: "Synchronizer Was Stopped")
}
}

Expand All @@ -491,6 +479,22 @@ extension ZcashAdapter {
BlockHeight.ofLatestCheckpoint(network: network)
}

static func initializer(network: ZcashNetwork, uniqueId: String) throws -> Initializer {
Initializer(
cacheDbURL: nil,
fsBlockDbRoot: try fsBlockDbRootURL(uniqueId: uniqueId, network: network),
dataDbURL: try dataDbURL(uniqueId: uniqueId, network: network),
pendingDbURL: try pendingDbURL(uniqueId: uniqueId, network: network),
endpoint: LightWalletEndpoint(address: endPoint, port: 9067, secure: true, streamingCallTimeoutInMillis: 10 * 60 * 60 * 1000),
network: network,
spendParamsURL: try spendParamsURL(uniqueId: uniqueId),
outputParamsURL: try outputParamsURL(uniqueId: uniqueId),
saplingParamsSourceURL: SaplingParamsSourceURL.default,
alias: .custom(uniqueId),
logLevel: .error
)
}

private static func dataDirectoryUrl() throws -> URL {
let fileManager = FileManager.default

Expand Down Expand Up @@ -553,9 +557,15 @@ extension ZcashAdapter: IAdapter {
return
}

guard zAddress != nil else { // else we need to try prepare library again
if zAddress == nil { // else we need to try prepare library again
logger?.log(level: .debug, message: "No address, try to prepare kit again!")
prepare(seedData: seedData, viewingKeys: [viewingKey], walletBirthday: birthday)
do {
let initializer = try Self.initializer(network: network, uniqueId: uniqueId)
prepare(initializer: initializer, seedData: seedData, walletBirthday: birthday)
} catch {
logger?.log(level: .error, message: "Can't start adapter: \(error.localizedDescription)")
}

return
}

Expand Down Expand Up @@ -619,7 +629,7 @@ extension ZcashAdapter: IAdapter {
return """
ZcashAdapter
z-address: \(String(describing: zAddress))
spendingKeys: \(spendingKey.description)
spendingKeys: \(spendingKey?.description ?? "N/A")
balanceState: \(balanceState)
"""
}
Expand Down Expand Up @@ -729,7 +739,10 @@ extension ZcashAdapter: ISendZcashAdapter {
}

func sendSingle(amount: Decimal, address: Recipient, memo: Memo?) -> Single<()> {
let spendingKey = spendingKey
guard let spendingKey else {
return .error(AppError.ZcashError.noReceiveAddress)
}

return Single.create { [weak self] observer in
guard let self else {
observer(.error(AppError.unknownError))
Expand All @@ -744,6 +757,7 @@ extension ZcashAdapter: ISendZcashAdapter {
memo: memo)
self.logger?.log(level: .debug, message: "Successful send TX: \(pendingEntity.createTime) : \(pendingEntity.value.decimalValue.description) : \(pendingEntity.recipient.asString ?? "") : \(pendingEntity.memo?.encodedString ?? "NoMemo")")
self.reSyncPending()
observer(.success(()))
} catch {
observer(.error(error))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,61 +47,12 @@ class ZcashTransactionPool {
return wrapped
}

private func zcashTransactions(_ transactions: [ZcashTransaction.Sent]) async -> [ZcashTransactionWrapper] {
var wrapped = [ZcashTransactionWrapper]()
for tx in transactions {
if let tx = try? await transactionWithAdditional(tx: tx) {
wrapped.append(tx)
}
}
return wrapped
}

private func zcashTransactions(_ transactions: [ZcashTransaction.Received]) async -> [ZcashTransactionWrapper] {
var wrapped = [ZcashTransactionWrapper]()
for tx in transactions {
if let tx = try? await transactionWithAdditional(tx: tx) {
wrapped.append(tx)
}
}
return wrapped
}

private func transactionWithAdditional(tx: ZcashTransaction.Overview) async throws -> ZcashTransactionWrapper? {
let memos: [Memo] = (try? await synchronizer.getMemos(for: tx)) ?? []
let recipients = await synchronizer.getRecipients(for: tx)
print("OVERVIEW TX: TXID: \(tx.id) \(tx.value.decimalString())")
memos.forEach { memo in
print("Found Memo: \(memo)")
}
recipients.forEach { recipient in
print("Found Recipient: \(recipient)")
}
return ZcashTransactionWrapper(tx: tx, memo: memos.first, recipient: recipients.first)
}

private func transactionWithAdditional(tx: ZcashTransaction.Sent) async throws -> ZcashTransactionWrapper? {
let memos: [Memo] = (try? await synchronizer.getMemos(for: tx)) ?? []
let recipients = await synchronizer.getRecipients(for: tx)
print("OVERVIEW TX: TXID: \(tx.id) \(tx.value.decimalString())")
memos.forEach { memo in
print("Found Memo: \(memo)")
}
recipients.forEach { recipient in
print("Found Recipient: \(recipient)")
}
return ZcashTransactionWrapper(tx: tx, memo: memos.first, recipient: recipients.first)
}

private func transactionWithAdditional(tx: ZcashTransaction.Received) async throws -> ZcashTransactionWrapper? {
let memos: [Memo] = (try? await synchronizer.getMemos(for: tx)) ?? []
print("OVERVIEW TX: TXID: \(tx.id) \(tx.value.decimalString())")
memos.forEach { memo in
print("Found Memo: \(memo)")
}
return ZcashTransactionWrapper(tx: tx, memo: memos.first, recipient: nil)
}

@discardableResult private func sync(own: inout Set<ZcashTransactionWrapper>, incoming: [ZcashTransactionWrapper]) -> [ZcashTransactionWrapper] {
var newTxs = [ZcashTransactionWrapper]()
incoming.forEach { transaction in
Expand All @@ -115,30 +66,9 @@ class ZcashTransactionPool {
func initTransactions() async {
let overviews = await synchronizer.clearedTransactions
let pending = await synchronizer.pendingTransactions
let sent = await synchronizer.sentTransactions
let received = await synchronizer.receivedTransactions
print("Found | overviews: \(overviews.count) | pending: \(pending.count) | sent: \(sent.count) | received: \(received.count)")

pendingTransactions = Set(zcashTransactions(pending))
confirmedTransactions = Set(await zcashTransactions(overviews))

let sentWrapped = await zcashTransactions(sent)
let receivedWrapped = await zcashTransactions(received)

print("===> Overviews:")
confirmedTransactions.forEach { tx in
print("ID: \(tx.id ?? "N/A") | Value: \(tx.value) | Fee: \(tx.fee?.decimalString() ?? "N/A") | Recipient: \(tx.toAddress ?? "N/A")")
}

print("===> Sent:")
sentWrapped.forEach { tx in
print("ID: \(tx.id ?? "N/A") | Value: \(tx.value) | Fee: \(tx.fee?.decimalString() ?? "N/A") | Recipient: \(tx.toAddress ?? "N/A")")
}

print("===> received:")
receivedWrapped.forEach { tx in
print("ID: \(tx.id ?? "N/A") | Value: \(tx.value) | Fee: \(tx.fee?.decimalString() ?? "N/A") | Recipient: \(tx.toAddress ?? "N/A")")
}
}

func sync(transactions: [PendingTransactionEntity]) -> [ZcashTransactionWrapper] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ class MetadataMonitor {
// Get the file URLs, to wait for them below.
let urls = results.compactMap { item -> URL? in
// check if file really changed in time because query returns 3 times same file
logger?.debug("=> MONITOR : url : \((item.value(forAttribute: NSMetadataItemURLKey) as? URL)?.path)")
logger?.debug("=> MONITOR : url : \((item.value(forAttribute: NSMetadataItemURLKey) as? URL)?.path ?? "N/A")")
if let url = item.value(forAttribute: NSMetadataItemURLKey) as? URL {
logger?.debug("=> MONITOR : changeTime : \(item.value(forAttribute: NSMetadataItemFSContentChangeDateKey) as? Date)")
logger?.debug("=> MONITOR : changeTime : \(String(describing: item.value(forAttribute: NSMetadataItemFSContentChangeDateKey) as? Date))")
let changeTime = item.value(forAttribute: NSMetadataItemFSContentChangeDateKey) as? Date
logger?.debug("=> MONITOR : lastChangeTime : \(fileChangedTime[url])")
logger?.debug("=> MONITOR : lastChangeTime : \(String(describing: fileChangedTime[url]))")
if let changeTime,
let lastChangeTime = fileChangedTime[url],
changeTime == lastChangeTime {
Expand Down
Loading

0 comments on commit d5df1ef

Please sign in to comment.