From def779e5bce0144a4b82bb64644a70506cd94e02 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 28 Jun 2022 22:40:52 +0100 Subject: [PATCH] Migrate to ZIP 316 UFVKs This also brings in various associated changes to the FFI methods in zcash-light-client-kit as a result of moving to the main branch of zcash/librustzcash. --- .../DatabaseMigrationManager.swift | 9 +- .../Processor/CompactBlockProcessor.swift | 3 +- .../FetchUnspentTxOutputsOperation.swift | 1 - .../Entity/AccountEntity.swift | 23 ++-- .../UnspentTransactionOutputEntity.swift | 1 + Sources/ZcashLightClientKit/Initializer.swift | 2 + .../Model/WalletTypes.swift | 16 +-- .../Rust/ZcashRustBackend.swift | 106 +++++++++--------- .../Rust/ZcashRustBackendWelding.swift | 32 +++--- .../ZcashLightClientKit/Synchronizer.swift | 4 +- .../Synchronizer/SDKSynchronizer.swift | 10 +- .../Tool/DerivationTool.swift | 58 +++++----- .../PersistentTransactionManager.swift | 8 +- .../Transaction/TransactionEncoder.swift | 8 +- .../Transaction/TransactionManager.swift | 2 +- .../WalletTransactionEncoder.swift | 10 +- Tests/DarksideTests/ShieldFundsTests.swift | 9 +- .../BlockScanOperationTests.swift | 8 +- .../DerivatioToolTestnetTests.swift | 31 +++-- .../DerivationToolMainnetTests.swift | 29 +++-- Tests/TestUtils/Stubs.swift | 17 +-- 21 files changed, 191 insertions(+), 196 deletions(-) diff --git a/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift b/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift index 7c52010c..2a032199 100644 --- a/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift +++ b/Sources/ZcashLightClientKit/Block/DatabaseStorage/DatabaseMigrationManager.swift @@ -44,7 +44,11 @@ class MigrationManager { } func performMigration(ufvks: [UnifiedFullViewingKey]) throws { - try migrateDataDb(ufvks: ufvks) + // TODO: DataDB migrations will be handled by rustBackend.initDataDb + // once https://github.com/zcash/librustzcash/pull/600 merges, and in + // the interim the old migrations here will fail if we try to run them + // due to changes to table column names in zcash/librustzcash. + //try migrateDataDb(ufvks: ufvks) try migrateCacheDb() try migratePendingDb() } @@ -115,7 +119,8 @@ class MigrationManager { let derivationTool = DerivationTool(networkType: self.network) for tuple in zip(accounts, viewingKeys) { - let tAddr = try derivationTool.deriveTransparentAddressFromPublicKey(tuple.1.extpub) + // TODO: Should the v1 migration be changed to "migrate from pre-v1 database to v2"? + let tAddr = try derivationTool.deriveTransparentAddressFromPublicKey(tuple.1.encoding) var account = tuple.0 account.transparentAddress = tAddr try accountsDao.update(account) diff --git a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift index 73990491..d43a2ac7 100644 --- a/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift +++ b/Sources/ZcashLightClientKit/Block/Processor/CompactBlockProcessor.swift @@ -1287,7 +1287,7 @@ private struct UnifiedAddressShim { } extension UnifiedAddressShim: UnifiedAddress { - var tAddress: TransparentAddress { + var encoding: String { account.transparentAddress } @@ -1334,7 +1334,6 @@ extension CompactBlockProcessor { do { try self.rustBackend.putUnspentTransparentOutput( dbData: dataDb, - address: utxo.address, txid: utxo.txid.bytes, index: utxo.index, script: utxo.script.bytes, diff --git a/Sources/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift b/Sources/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift index fd7a8210..6c7df1ca 100644 --- a/Sources/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift +++ b/Sources/ZcashLightClientKit/Block/Processor/FetchUnspentTxOutputsOperation.swift @@ -84,7 +84,6 @@ class FetchUnspentTxOutputsOperation: ZcashOperation { do { try self.rustbackend.putUnspentTransparentOutput( dbData: dataDb, - address: utxo.address, txid: utxo.txid.bytes, index: utxo.index, script: utxo.script.bytes, diff --git a/Sources/ZcashLightClientKit/Entity/AccountEntity.swift b/Sources/ZcashLightClientKit/Entity/AccountEntity.swift index 04665cdc..bea0a35a 100644 --- a/Sources/ZcashLightClientKit/Entity/AccountEntity.swift +++ b/Sources/ZcashLightClientKit/Entity/AccountEntity.swift @@ -9,7 +9,7 @@ import Foundation protocol AccountEntity { var account: Int { get set } - var extfvk: String { get set } + var ufvk: String { get set } var address: String { get set } var transparentAddress: String { get set } } @@ -17,14 +17,14 @@ protocol AccountEntity { struct Account: AccountEntity, Encodable, Decodable { enum CodingKeys: String, CodingKey { case account - case extfvk + case ufvk case address case transparentAddress = "transparent_address" } var account: Int - var extfvk: String + var ufvk: String var address: String @@ -32,22 +32,13 @@ struct Account: AccountEntity, Encodable, Decodable { } extension Account: UnifiedAddress { - var tAddress: TransparentAddress { - get { - transparentAddress - } - set { - transparentAddress = newValue - } - } - - var zAddress: SaplingShieldedAddress { + var encoding: String { get { address } // swiftlint:disable unused_setter_value set { - address = transparentAddress + address = encoding } } } @@ -55,7 +46,7 @@ extension Account: UnifiedAddress { extension Account: Hashable { func hash(into hasher: inout Hasher) { hasher.combine(account) - hasher.combine(extfvk) + hasher.combine(ufvk) hasher.combine(address) hasher.combine(transparentAddress) } @@ -63,7 +54,7 @@ extension Account: Hashable { static func == (lhs: Self, rhs: Self) -> Bool { guard lhs.account == rhs.account, - lhs.extfvk == rhs.extfvk, + lhs.ufvk == rhs.ufvk, lhs.address == rhs.address, lhs.transparentAddress == rhs.transparentAddress else { return false } diff --git a/Sources/ZcashLightClientKit/Entity/UnspentTransactionOutputEntity.swift b/Sources/ZcashLightClientKit/Entity/UnspentTransactionOutputEntity.swift index 6b1e62d6..6c8b3861 100644 --- a/Sources/ZcashLightClientKit/Entity/UnspentTransactionOutputEntity.swift +++ b/Sources/ZcashLightClientKit/Entity/UnspentTransactionOutputEntity.swift @@ -8,6 +8,7 @@ import Foundation public protocol UnspentTransactionOutputEntity { + // TODO: Remove address field? var address: String { get set } var txid: Data { get set } var index: Int { get set } diff --git a/Sources/ZcashLightClientKit/Initializer.swift b/Sources/ZcashLightClientKit/Initializer.swift index 61434b0f..6b6a65f0 100644 --- a/Sources/ZcashLightClientKit/Initializer.swift +++ b/Sources/ZcashLightClientKit/Initializer.swift @@ -234,6 +234,8 @@ public class Initializer { } } catch RustWeldingError.dataDbNotEmpty { // this is fine + } catch RustWeldingError.malformedStringInput { + throw RustWeldingError.malformedStringInput } catch { throw rustBackend.lastError() ?? InitializerError.accountInitFailed } diff --git a/Sources/ZcashLightClientKit/Model/WalletTypes.swift b/Sources/ZcashLightClientKit/Model/WalletTypes.swift index 91860a00..73803dd6 100644 --- a/Sources/ZcashLightClientKit/Model/WalletTypes.swift +++ b/Sources/ZcashLightClientKit/Model/WalletTypes.swift @@ -5,29 +5,19 @@ // Created by Francisco Gindre on 4/6/21. // -/** - Groups a Sapling Extended Full Viewing Key an a tranparent address extended public key. - */ - -public typealias ExtendedFullViewingKey = String -public typealias ExtendedPublicKey = String - /** A ZIP 316 Unified Full Viewing Key. - - TODO: Use the correct ZIP 316 format. */ public protocol UnifiedFullViewingKey { - var extfvk: ExtendedFullViewingKey { get set } - var extpub: ExtendedPublicKey { get set } + var account: UInt32 { get set } + var encoding: String { get set } } public typealias TransparentAddress = String public typealias SaplingShieldedAddress = String public protocol UnifiedAddress { - var tAddress: TransparentAddress { get } - var zAddress: SaplingShieldedAddress { get } + var encoding: String { get } } public struct WalletBalance: Equatable { diff --git a/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift b/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift index ab14658b..68a001cb 100644 --- a/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift +++ b/Sources/ZcashLightClientKit/Rust/ZcashRustBackend.swift @@ -93,6 +93,21 @@ class ZcashRustBackend: ZcashRustBackendWelding { return true } + + static func isValidUnifiedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool { + guard !key.containsCStringNullBytesBeforeStringEnding() else { + return false + } + + guard zcashlc_is_valid_unified_full_viewing_key([CChar](key.utf8CString), networkType.networkId) else { + if let error = lastError() { + throw error + } + return false + } + + return true + } static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? { let dbData = dbData.osStr() @@ -116,27 +131,20 @@ class ZcashRustBackend: ZcashRustBackendWelding { var ffiUfvks: [FFIUnifiedViewingKey] = [] for ufvk in ufvks { - guard !ufvk.extfvk.containsCStringNullBytesBeforeStringEnding() else { - throw RustWeldingError.malformedStringInput - } - guard !ufvk.extpub.containsCStringNullBytesBeforeStringEnding() else { + guard !ufvk.encoding.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - guard try self.isValidExtendedFullViewingKey(ufvk.extfvk, networkType: networkType) else { + guard try self.isValidUnifiedFullViewingKey(ufvk.encoding, networkType: networkType) else { // TODO Fix throw RustWeldingError.malformedStringInput } - let extfvkCStr = [CChar](String(ufvk.extfvk).utf8CString) + let ufvkCStr = [CChar](String(ufvk.encoding).utf8CString) - let extfvkPtr = UnsafeMutablePointer.allocate(capacity: extfvkCStr.count) - extfvkPtr.initialize(from: extfvkCStr, count: extfvkCStr.count) + let ufvkPtr = UnsafeMutablePointer.allocate(capacity: ufvkCStr.count) + ufvkPtr.initialize(from: ufvkCStr, count: ufvkCStr.count) - let extpubCStr = [CChar](String(ufvk.extpub).utf8CString) - let extpubPtr = UnsafeMutablePointer.allocate(capacity: extpubCStr.count) - extpubPtr.initialize(from: extpubCStr, count: extpubCStr.count) - - ffiUfvks.append(FFIUnifiedViewingKey(extfvk: extfvkPtr, extpub: extpubPtr)) + ffiUfvks.append(FFIUnifiedViewingKey(account_id: ufvk.account, encoding: ufvkPtr)) } var result = false @@ -151,8 +159,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { defer { for ufvk in ffiUfvks { - ufvk.extfvk.deallocate() - ufvk.extpub.deallocate() + ufvk.encoding.deallocate() } } @@ -262,17 +269,12 @@ class ZcashRustBackend: ZcashRustBackendWelding { return result } - static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool { + static func putUnspentTransparentOutput(dbData: URL, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool { let dbData = dbData.osStr() - guard !address.containsCStringNullBytesBeforeStringEnding() else { - throw RustWeldingError.malformedStringInput - } - guard zcashlc_put_utxo( dbData.0, dbData.1, - [CChar](address.utf8CString), txid, UInt(txid.count), Int32(index), @@ -387,7 +389,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { dbCache: URL, dbData: URL, account: Int32, - tsk: String, + xprv: String, extsk: String, memo: String?, spendParamsPath: String, @@ -401,7 +403,7 @@ class ZcashRustBackend: ZcashRustBackendWelding { dbData.0, dbData.1, account, - [CChar](tsk.utf8CString), + [CChar](xprv.utf8CString), [CChar](extsk.utf8CString), [CChar](memoBytes.utf8CString), spendParamsPath, @@ -490,11 +492,11 @@ class ZcashRustBackend: ZcashRustBackendWelding { static func deriveUnifiedFullViewingKeyFromSeed( _ seed: [UInt8], - numberOfAccounts: Int, + numberOfAccounts: Int32, networkType: NetworkType ) throws -> [UnifiedFullViewingKey] { guard - let ufvksStruct = zcashlc_derive_unified_viewing_keys_from_seed( + let ufvksStruct = zcashlc_derive_unified_full_viewing_keys_from_seed( seed, UInt(seed.count), Int32(numberOfAccounts), @@ -518,15 +520,11 @@ class ZcashRustBackend: ZcashRustBackendWelding { for item in 0 ..< Int(ufvksSize) { let itemPointer = ufvksArrayPointer.advanced(by: item) - guard let extfvk = String(validatingUTF8: itemPointer.pointee.extfvk) else { + guard let encoding = String(validatingUTF8: itemPointer.pointee.encoding) else { throw RustWeldingError.unableToDeriveKeys } - guard let extpub = String(validatingUTF8: itemPointer.pointee.extpub) else { - throw RustWeldingError.unableToDeriveKeys - } - - ufvks.append(UFVK(extfvk: extfvk, extpub: extpub)) + ufvks.append(UFVK(account: UInt32(item), encoding: encoding)) } zcashlc_free_uvk_array(ufvksStruct) @@ -534,13 +532,13 @@ class ZcashRustBackend: ZcashRustBackendWelding { return ufvks } - static func deriveShieldedAddressFromSeed( + static func deriveUnifiedAddressFromSeed( seed: [UInt8], accountIndex: Int32, networkType: NetworkType ) throws -> String? { guard - let zaddrCStr = zcashlc_derive_shielded_address_from_seed( + let uaddrCStr = zcashlc_derive_unified_address_from_seed( seed, UInt(seed.count), accountIndex, @@ -552,23 +550,23 @@ class ZcashRustBackend: ZcashRustBackendWelding { } return nil } - let zAddr = String(validatingUTF8: zaddrCStr) + let uAddr = String(validatingUTF8: uaddrCStr) - zcashlc_string_free(zaddrCStr) + zcashlc_string_free(uaddrCStr) - return zAddr + return uAddr } - static func deriveShieldedAddressFromViewingKey( - _ extfvk: String, + static func deriveUnifiedAddressFromViewingKey( + _ ufvk: String, networkType: NetworkType ) throws -> String? { - guard !extfvk.containsCStringNullBytesBeforeStringEnding() else { + guard !ufvk.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } guard - let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key( - [CChar](extfvk.utf8CString), + let zaddrCStr = zcashlc_derive_unified_address_from_viewing_key( + [CChar](ufvk.utf8CString), networkType.networkId ) else { @@ -577,11 +575,11 @@ class ZcashRustBackend: ZcashRustBackendWelding { } return nil } - let zAddr = String(validatingUTF8: zaddrCStr) + let uAddr = String(validatingUTF8: zaddrCStr) zcashlc_string_free(zaddrCStr) - return zAddr + return uAddr } static func deriveTransparentAddressFromSeed( @@ -610,18 +608,16 @@ class ZcashRustBackend: ZcashRustBackendWelding { return tAddr } - static func deriveTransparentPrivateKeyFromSeed( + static func deriveTransparentAccountPrivateKeyFromSeed( seed: [UInt8], account: Int, - index: Int, networkType: NetworkType ) throws -> String? { guard - let skCStr = zcashlc_derive_transparent_private_key_from_seed( + let skCStr = zcashlc_derive_transparent_account_private_key_from_seed( seed, UInt(seed.count), Int32(account), - Int32(index), networkType.networkId ) else { @@ -659,12 +655,20 @@ class ZcashRustBackend: ZcashRustBackendWelding { return tAddr } - static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? { + static func deriveTransparentAddressFromAccountPrivateKey( + _ tsk: String, + index: Int, + networkType: NetworkType + ) throws -> String? { guard !tsk.containsCStringNullBytesBeforeStringEnding() else { throw RustWeldingError.malformedStringInput } - guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString), networkType.networkId) else { + guard let tAddrCStr = zcashlc_derive_transparent_address_from_account_private_key( + [CChar](tsk.utf8CString), + Int32(index), + networkType.networkId + ) else { if let error = lastError() { throw error } @@ -688,8 +692,8 @@ class ZcashRustBackend: ZcashRustBackendWelding { } private struct UFVK: UnifiedFullViewingKey { - var extfvk: ExtendedFullViewingKey - var extpub: ExtendedPublicKey + var account: UInt32 + var encoding: String } private extension ZcashRustBackend { diff --git a/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift b/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift index 9dda42e2..811643e8 100644 --- a/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift +++ b/Sources/ZcashLightClientKit/Rust/ZcashRustBackendWelding.swift @@ -57,6 +57,12 @@ public protocol ZcashRustBackendWelding { */ static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool + /** + - Returns: true when the address is valid and a UFVK. false in any other case + - Throws: Error when there's another problem not related to validity of the string in question + */ + static func isValidUnifiedFullViewingKey(_ ufvk: String, networkType: NetworkType) throws -> Bool + /** initialize the accounts table from a given seed and a number of accounts - Parameters: @@ -67,7 +73,7 @@ public protocol ZcashRustBackendWelding { static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? /** - initialize the accounts table from a set of unified viewing keys + initialize the accounts table from a set of unified full viewing keys - Parameters: - dbData: location of the data db - ufvks: an array of UnifiedFullViewingKeys @@ -203,7 +209,6 @@ public protocol ZcashRustBackendWelding { puts a UTXO into the data db database - Parameters: - dbData: location of the data db file - - address: the address of the UTXO - txid: the txid bytes for the UTXO - index: the index of the UTXO - value: the value of the UTXO @@ -212,7 +217,6 @@ public protocol ZcashRustBackendWelding { */ static func putUnspentTransparentOutput( dbData: URL, - address: String, txid: [UInt8], index: Int, script: [UInt8], @@ -289,7 +293,7 @@ public protocol ZcashRustBackendWelding { - dbCache: URL for the Cache DB - dbData: URL for the Data DB - account: the account index that will originate the transaction - - tsk: transparent Secret Key for the shielded funds. + - xprv: transparent account private key for the shielded funds. - extsk: extended spending key string - memo: the memo string for this transaction - spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located @@ -300,7 +304,7 @@ public protocol ZcashRustBackendWelding { dbCache: URL, dbData: URL, account: Int32, - tsk: String, + xprv: String, extsk: String, memo: String?, spendParamsPath: String, @@ -335,21 +339,21 @@ public protocol ZcashRustBackendWelding { static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? /** - Derives a shielded address from a seed + Derives a unified address from a seed - Parameter seed: an array of bytes of the seed - Parameter accountIndex: the index of the account you want the address for - Returns: an optional String containing the Shielded address - Throws: RustBackendError if fatal error occurs */ - static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? + static func deriveUnifiedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? /** - Derives a shielded address from an Extended Full Viewing Key - - Parameter extfvk: a string containing the extended full viewing key + Derives a unified address from a Unified Full Viewing Key + - Parameter ufvk: a string containing the extended full viewing key - Returns: an optional String containing the Shielded address - Throws: RustBackendError if fatal error occurs */ - static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? + static func deriveUnifiedAddressFromViewingKey(_ ufvk: String, networkType: NetworkType) throws -> String? /** Derives a shielded address from an Extended Full Viewing Key @@ -360,18 +364,18 @@ public protocol ZcashRustBackendWelding { static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? /** - Derives a transparent secret key from Seed + Derives a transparent account private key from Seed - Parameter seed: an array of bytes containing the seed - Returns: an optional String containing the transparent secret (private) key */ - static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? + static func deriveTransparentAccountPrivateKeyFromSeed(seed: [UInt8], account: Int, networkType: NetworkType) throws -> String? /** Derives a transparent address from a secret key - Parameter tsk: a hex string containing the Secret Key - Returns: an optional String containing the transparent address. */ - static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? + static func deriveTransparentAddressFromAccountPrivateKey(_ tsk: String, index: Int, networkType: NetworkType) throws -> String? /** Derives a tranparent address from a public key @@ -379,7 +383,7 @@ public protocol ZcashRustBackendWelding { */ static func derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) throws -> String - static func deriveUnifiedFullViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedFullViewingKey] + static func deriveUnifiedFullViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int32, networkType: NetworkType) throws -> [UnifiedFullViewingKey] /** Gets the consensus branch id for the given height diff --git a/Sources/ZcashLightClientKit/Synchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer.swift index 67f11235..f3ade0dc 100644 --- a/Sources/ZcashLightClientKit/Synchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer.swift @@ -144,12 +144,12 @@ public protocol Synchronizer { /// Sends zatoshi. /// - Parameter spendingKey: the key that allows spends to occur. - /// - Parameter transparentSecretKey: the key that allows to spend transaprent funds + /// - Parameter transparentAccountPrivateKey: the key that allows to spend transparent funds /// - Parameter memo: the optional memo to include as part of the transaction. /// - Parameter accountIndex: the optional account id that will be used to shield your funds to. By default, the first account is used. func shieldFunds( spendingKey: String, - transparentSecretKey: String, + transparentAccountPrivateKey: String, memo: String?, from accountIndex: Int, resultBlock: @escaping (_ result: Result) -> Void diff --git a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift index dd682704..fc2fef78 100644 --- a/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift +++ b/Sources/ZcashLightClientKit/Synchronizer/SDKSynchronizer.swift @@ -505,7 +505,7 @@ public class SDKSynchronizer: Synchronizer { public func shieldFunds( spendingKey: String, - transparentSecretKey: String, + transparentAccountPrivateKey: String, memo: String?, from accountIndex: Int, resultBlock: @escaping (Result) -> Void @@ -514,7 +514,7 @@ public class SDKSynchronizer: Synchronizer { let derivationTool = DerivationTool(networkType: self.network.networkType) do { - let tAddr = try derivationTool.deriveTransparentAddressFromPrivateKey(transparentSecretKey) + let tAddr = try derivationTool.deriveTransparentAddressFromAccountPrivateKey(transparentAccountPrivateKey, index: 0) // TODO: FIX let tBalance = try utxoRepository.balance(address: tAddr, latestHeight: self.latestDownloadedHeight()) // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet. @@ -523,13 +523,13 @@ public class SDKSynchronizer: Synchronizer { return } let viewingKey = try derivationTool.deriveViewingKey(spendingKey: spendingKey) - let zAddr = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey) + let uAddr = try derivationTool.deriveUnifiedAddress(viewingKey: viewingKey) - let shieldingSpend = try transactionManager.initSpend(zatoshi: tBalance.verified, toAddress: zAddr, memo: memo, from: 0) + let shieldingSpend = try transactionManager.initSpend(zatoshi: tBalance.verified, toAddress: uAddr, memo: memo, from: 0) transactionManager.encodeShieldingTransaction( spendingKey: spendingKey, - tsk: transparentSecretKey, + xprv: transparentAccountPrivateKey, pendingTransaction: shieldingSpend ) { [weak self] result in guard let self = self else { return } diff --git a/Sources/ZcashLightClientKit/Tool/DerivationTool.swift b/Sources/ZcashLightClientKit/Tool/DerivationTool.swift index 2bde51e7..34e1cd56 100644 --- a/Sources/ZcashLightClientKit/Tool/DerivationTool.swift +++ b/Sources/ZcashLightClientKit/Tool/DerivationTool.swift @@ -48,7 +48,7 @@ public protocol KeyDeriving { func deriveSpendingKeys(seed: [UInt8], numberOfAccounts: Int) throws -> [String] /** - Given a seed and account index, return the associated address. + Given a seed and account index, return the associated unified address. - Parameter seed: the seed from which to derive the address. - Parameter accountIndex: the index of the account to use for deriving the address. Multiple @@ -56,17 +56,17 @@ public protocol KeyDeriving { - Returns: the address that corresponds to the seed and account index. */ - func deriveShieldedAddress(seed: [UInt8], accountIndex: Int) throws -> String + func deriveUnifiedAddress(seed: [UInt8], accountIndex: Int) throws -> String /** - Given a viewing key string, return the associated address. + Given a unified viewing key string, return the associated unified address. - Parameter viewingKey: the viewing key to use for deriving the address. The viewing key is tied to a specific account so no account index is required. - Returns: the address that corresponds to the viewing key. */ - func deriveShieldedAddress(viewingKey: String) throws -> String + func deriveUnifiedAddress(viewingKey: String) throws -> String /** Derives a transparent address from seedbytes, specifying account and index @@ -74,14 +74,14 @@ public protocol KeyDeriving { func deriveTransparentAddress(seed: [UInt8], account: Int, index: Int) throws -> String /** - Derives a SecretKey to spend transparent funds from a transparent secret key wif encoded + Derives the account private key to spend transparent funds from a specific seed and account */ - func deriveTransparentPrivateKey(seed: [UInt8], account: Int, index: Int) throws -> String + func deriveTransparentAccountPrivateKey(seed: [UInt8], account: Int) throws -> String /** - Derives a transparent address from the given transparent Secret Key + Derives a transparent address from the given transparent account private key */ - func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String + func deriveTransparentAddressFromAccountPrivateKey(_ xprv: String, index: Int) throws -> String func deriveTransparentAddressFromPublicKey(_ pubkey: String) throws -> String @@ -127,8 +127,11 @@ public class DerivationTool: KeyDeriving { } do { - guard let keys = try rustwelding.deriveExtendedFullViewingKeys(seed: seed, accounts: numberOfAccounts, networkType: networkType) else { - throw KeyDerivationErrors.unableToDerive + let ufvks = try rustwelding.deriveUnifiedFullViewingKeyFromSeed(seed, numberOfAccounts: numberOfAccounts, networkType: networkType) + + var keys: [String] = [] + for ufvk in ufvks { + keys.append(ufvk.encoding) } return keys } catch { @@ -178,7 +181,7 @@ public class DerivationTool: KeyDeriving { } /** - Given a seed and account index, return the associated address. + Given a seed and account index, return the associated unified address. - Parameter seed: the seed from which to derive the address. - Parameter accountIndex: the index of the account to use for deriving the address. Multiple @@ -186,13 +189,13 @@ public class DerivationTool: KeyDeriving { - Returns: the address that corresponds to the seed and account index. */ - public func deriveShieldedAddress(seed: [UInt8], accountIndex: Int) throws -> String { + public func deriveUnifiedAddress(seed: [UInt8], accountIndex: Int) throws -> String { guard accountIndex >= 0, let accountIndex = Int32(exactly: accountIndex) else { throw KeyDerivationErrors.invalidInput } do { - guard let address = try rustwelding.deriveShieldedAddressFromSeed(seed: seed, accountIndex: accountIndex, networkType: networkType) else { + guard let address = try rustwelding.deriveUnifiedAddressFromSeed(seed: seed, accountIndex: accountIndex, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return address @@ -202,16 +205,16 @@ public class DerivationTool: KeyDeriving { } /** - Given a viewing key string, return the associated address. + Given a unified viewing key string, return the associated unified address. - Parameter viewingKey: the viewing key to use for deriving the address. The viewing key is tied to a specific account so no account index is required. - Returns: the address that corresponds to the viewing key. */ - public func deriveShieldedAddress(viewingKey: String) throws -> String { + public func deriveUnifiedAddress(viewingKey: String) throws -> String { do { - guard let zaddr = try rustwelding.deriveShieldedAddressFromViewingKey(viewingKey, networkType: networkType) else { + guard let zaddr = try rustwelding.deriveUnifiedAddressFromViewingKey(viewingKey, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return zaddr @@ -237,7 +240,7 @@ public class DerivationTool: KeyDeriving { } public func deriveUnifiedFullViewingKeysFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedFullViewingKey] { - guard numberOfAccounts > 0 else { + guard numberOfAccounts > 0, let numberOfAccounts = Int32(exactly: numberOfAccounts) else { throw KeyDerivationErrors.invalidInput } do { @@ -252,9 +255,8 @@ public class DerivationTool: KeyDeriving { */ public func deriveUnifiedAddressFromUnifiedFullViewingKey(_ ufvk: UnifiedFullViewingKey) throws -> UnifiedAddress { do { - let tAddress = try deriveTransparentAddressFromPublicKey(ufvk.extpub) - let zAddress = try deriveShieldedAddress(viewingKey: ufvk.extfvk) - return ConcreteUnifiedAddress(tAddress: tAddress, zAddress: zAddress) + let encoding = try deriveUnifiedAddress(viewingKey: ufvk.encoding) + return ConcreteUnifiedAddress(encoding: encoding) } catch { throw KeyDerivationErrors.unableToDerive } @@ -273,17 +275,16 @@ public class DerivationTool: KeyDeriving { } /** - Derives the transparent funds private key from the given seed + Derives the transparent funds account private key from the given seed - Throws: - KeyDerivationErrors.derivationError with the underlying error when it fails - KeyDerivationErrors.unableToDerive when there's an unknown error */ - public func deriveTransparentPrivateKey(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String { + public func deriveTransparentAccountPrivateKey(seed: [UInt8], account: Int = 0) throws -> String { do { - guard let seedKey = try rustwelding.deriveTransparentPrivateKeyFromSeed( + guard let seedKey = try rustwelding.deriveTransparentAccountPrivateKeyFromSeed( seed: seed, account: account, - index: index, networkType: networkType ) else { throw KeyDerivationErrors.unableToDerive @@ -321,14 +322,14 @@ extension DerivationTool: KeyValidation { } /** - Derives the transparent address from a WIF Private Key + Derives the transparent address from an account private key - Throws: - KeyDerivationErrors.derivationError with the underlying error when it fails - KeyDerivationErrors.unableToDerive when there's an unknown error */ - public func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String { + public func deriveTransparentAddressFromAccountPrivateKey(_ xprv: String, index: Int) throws -> String { do { - guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk, networkType: networkType) else { + guard let tAddr = try rustwelding.deriveTransparentAddressFromAccountPrivateKey(xprv, index: index, networkType: networkType) else { throw KeyDerivationErrors.unableToDerive } return tAddr @@ -339,6 +340,5 @@ extension DerivationTool: KeyValidation { } private struct ConcreteUnifiedAddress: UnifiedAddress { - var tAddress: TransparentAddress - var zAddress: SaplingShieldedAddress + var encoding: String } diff --git a/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift b/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift index c93db928..c5084d2c 100644 --- a/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift +++ b/Sources/ZcashLightClientKit/Transaction/PersistentTransactionManager.swift @@ -66,7 +66,7 @@ class PersistentTransactionManager: OutboundTransactionManager { func encodeShieldingTransaction( spendingKey: String, - tsk: String, + xprv: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result) -> Void ) { @@ -77,7 +77,7 @@ class PersistentTransactionManager: OutboundTransactionManager { guard let viewingKey = try? derivationTool.deriveViewingKey(spendingKey: spendingKey), - let zAddr = try? derivationTool.deriveShieldedAddress(viewingKey: viewingKey) + let uAddr = try? derivationTool.deriveUnifiedAddress(viewingKey: viewingKey) else { result( .failure( @@ -90,7 +90,7 @@ class PersistentTransactionManager: OutboundTransactionManager { return } - guard pendingTransaction.toAddress == zAddr else { + guard pendingTransaction.toAddress == uAddr else { result( .failure( TransactionManagerError.shieldingEncodingFailed( @@ -111,7 +111,7 @@ class PersistentTransactionManager: OutboundTransactionManager { do { let encodedTransaction = try self.encoder.createShieldingTransaction( spendingKey: spendingKey, - tSecretKey: tsk, + tAccountPrivateKey: xprv, memo: pendingTransaction.memo?.asZcashTransactionMemo(), from: pendingTransaction.accountIndex ) diff --git a/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift b/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift index f8fcdc80..fa3695ff 100644 --- a/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift +++ b/Sources/ZcashLightClientKit/Transaction/TransactionEncoder.swift @@ -71,7 +71,7 @@ protocol TransactionEncoder { - Parameters: - Parameter spendingKey: a string containing the spending key - - Parameter tSecretKey: transparent secret key to spend the UTXOs + - Parameter tAccountPrivateKey: transparent account private key to spend the UTXOs - Parameter memo: string containing the memo (optional) - Parameter accountIndex: index of the account that will be used to send the funds @@ -79,7 +79,7 @@ protocol TransactionEncoder { */ func createShieldingTransaction( spendingKey: String, - tSecretKey: String, + tAccountPrivateKey: String, memo: String?, from accountIndex: Int ) throws -> EncodedTransaction @@ -91,7 +91,7 @@ protocol TransactionEncoder { - Parameters: - Parameter spendingKey: a string containing the spending key - - Parameter tSecretKey: transparent secret key to spend the UTXOs + - Parameter tAccountPrivateKey: transparent account private key to spend the UTXOs - Parameter memo: string containing the memo (optional) - Parameter accountIndex: index of the account that will be used to send the funds @@ -100,7 +100,7 @@ protocol TransactionEncoder { func createShieldingTransaction( spendingKey: String, - tSecretKey: String, + tAccountPrivateKey: String, memo: String?, from accountIndex: Int, result: @escaping TransactionEncoderResultBlock diff --git a/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift b/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift index c2273879..fb78c9b8 100644 --- a/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift +++ b/Sources/ZcashLightClientKit/Transaction/TransactionManager.swift @@ -16,7 +16,7 @@ transactions through to completion. protocol OutboundTransactionManager { func initSpend(zatoshi: Zatoshi, toAddress: String, memo: String?, from accountIndex: Int) throws -> PendingTransactionEntity - func encodeShieldingTransaction(spendingKey: String, tsk: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result) -> Void) + func encodeShieldingTransaction(spendingKey: String, xprv: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result) -> Void) func encode(spendingKey: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result) -> Void) diff --git a/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift b/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift index 9394d004..d0074ae5 100644 --- a/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift +++ b/Sources/ZcashLightClientKit/Transaction/WalletTransactionEncoder.swift @@ -133,13 +133,13 @@ class WalletTransactionEncoder: TransactionEncoder { func createShieldingTransaction( spendingKey: String, - tSecretKey: String, + tAccountPrivateKey: String, memo: String?, from accountIndex: Int ) throws -> EncodedTransaction { let txId = try createShieldingSpend( spendingKey: spendingKey, - tsk: tSecretKey, + xprv: tAccountPrivateKey, memo: memo, accountIndex: accountIndex ) @@ -160,7 +160,7 @@ class WalletTransactionEncoder: TransactionEncoder { func createShieldingTransaction( spendingKey: String, - tSecretKey: String, + tAccountPrivateKey: String, memo: String?, from accountIndex: Int, result: @escaping TransactionEncoderResultBlock @@ -170,7 +170,7 @@ class WalletTransactionEncoder: TransactionEncoder { } } - func createShieldingSpend(spendingKey: String, tsk: String, memo: String?, accountIndex: Int) throws -> Int { + func createShieldingSpend(spendingKey: String, xprv: String, memo: String?, accountIndex: Int) throws -> Int { guard ensureParams(spend: self.spendParamsURL, output: self.spendParamsURL) else { throw TransactionEncoderError.missingParams } @@ -179,7 +179,7 @@ class WalletTransactionEncoder: TransactionEncoder { dbCache: self.cacheDbURL, dbData: self.dataDbURL, account: Int32(accountIndex), - tsk: tsk, + xprv: xprv, extsk: spendingKey, memo: memo, spendParamsPath: self.spendParamsURL.path, diff --git a/Tests/DarksideTests/ShieldFundsTests.swift b/Tests/DarksideTests/ShieldFundsTests.swift index 836d4f13..07e7e2ae 100644 --- a/Tests/DarksideTests/ShieldFundsTests.swift +++ b/Tests/DarksideTests/ShieldFundsTests.swift @@ -195,13 +195,12 @@ class ShieldFundsTests: XCTestCase { // 9. shield the funds let shieldFundsExpectation = XCTestExpectation(description: "shield funds") - let transparentSecretKey = try DerivationTool( + let transparentAccountPrivateKey = try DerivationTool( networkType: network.networkType ) - .deriveTransparentPrivateKey( + .deriveTransparentAccountPrivateKey( seed: TestSeed().seed(), - account: 0, - index: 0 + account: 0 ) shouldContinue = false @@ -211,7 +210,7 @@ class ShieldFundsTests: XCTestCase { // shield the funds coordinator.synchronizer.shieldFunds( spendingKey: coordinator.spendingKey, - transparentSecretKey: transparentSecretKey, + transparentAccountPrivateKey: transparentAccountPrivateKey, memo: "shield funds", from: 0 ) { result in diff --git a/Tests/NetworkTests/BlockScanOperationTests.swift b/Tests/NetworkTests/BlockScanOperationTests.swift index d9b701b6..020f6b0f 100644 --- a/Tests/NetworkTests/BlockScanOperationTests.swift +++ b/Tests/NetworkTests/BlockScanOperationTests.swift @@ -20,8 +20,8 @@ class BlockScanOperationTests: XCTestCase { var dataDbURL: URL! var ufvk = UFVFakeKey( - extfvk: "zxviewtestsapling1qw88ayg8qqqqpqyhg7jnh9mlldejfqwu46pm40ruwstd8znq3v3l4hjf33qcu2a5e36katshcfhcxhzgyfugj2lkhmt40j45cv38rv3frnghzkxcx73k7m7afw9j7ujk7nm4dx5mv02r26umxqgar7v3x390w2h3crqqgjsjly7jy4vtwzrmustm5yudpgcydw7x78awca8wqjvkqj8p8e3ykt7lrgd7xf92fsfqjs5vegfsja4ekzpfh5vtccgvs5747xqm6qflmtqpr8s9u", // swiftlint:disable:this line_length - extpub: "02075a7f5f7507d64022dad5954849f216b0f1b09b2d588be663d8e7faeb5aaf61" + account: 0, + encoding: "uviewtest1q48t999peecrfkq7ykcxckfkjt77w3lckk5mptlrtuy7xltjnzg8fm5434cxe9p9838ljs24yv83rluhk33ew098dkarapzyj4vk5kfxp5zn2jp3ww74jwd48r05aqjvgqxzx3nqn6zfqh3cmwdtmz0mc5624tvdza55q7mguxrehwcy4y0uktcpp4tkpex4qhazddux4yt6hr0sc9fkqmfr5tyz6ldd7yrq93tyj7446u4kst3vhmd40uga636p56hr0hjfdhgp07qyh90kmsl3qnmld6c8h7u06vekkjywmxv07mqzz9muwcl6weczrn5vf3p27uc9ufrumdp64zdzulzvc373wx3gl0yntntujhcsjhrwk9xwyjpvyuf0s8q3mgjs7uy3pg960w40dthpngcnauhgg9xq8cdcyfkq7ctnngqg4nkp5eh9knd4ckwjyd9czdd240lumul96r2fuerlvjeha6cyn9ftm7gr6xqjmq0zy6tv" // swiftlint:disable:this line_length ) var walletBirthDay = Checkpoint.birthday( @@ -260,6 +260,6 @@ extension BlockScanOperationTests: CompactBlockProgressDelegate { } struct UFVFakeKey: UnifiedFullViewingKey { - var extfvk: ExtendedFullViewingKey - var extpub: ExtendedPublicKey + var account: UInt32 + var encoding: String } diff --git a/Tests/OfflineTests/DerivationToolTests/DerivatioToolTestnetTests.swift b/Tests/OfflineTests/DerivationToolTests/DerivatioToolTestnetTests.swift index 8ab77302..9d6a55d6 100644 --- a/Tests/OfflineTests/DerivationToolTests/DerivatioToolTestnetTests.swift +++ b/Tests/OfflineTests/DerivationToolTests/DerivatioToolTestnetTests.swift @@ -12,11 +12,12 @@ import XCTest class DerivatioToolTestnetTests: XCTestCase { var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment? var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! - let testRecipientAddress = "ztestsapling1475xtm56czrzmleqzzlu4cxvjjfsy2p6rv78q07232cpsx5ee52k0mn5jyndq09mampkgvrxnwg" //TODO: Parameterize this from environment + let testRecipientAddress = "utest1uqmec4a2njqz2z2rwppchsd06qe7a0jh4jmsqr0yy99m9er9646zlxunf3v8qr0hncgv86e8a62vxy0qa32qzetmj8s57yudmyx9zav6f52nurclsqjkqtjtpz6vg679p6wkczpl2wu" //TODO: Parameterize this from environment let expectedSpendingKey = "secret-extended-key-test1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6lk8xce3d4jw7s8ln5yjp6fqv2g0nzue2hc0kv5t004vklvlenncscq9flwh5vf5qnv0hnync72n7gjn70u47765v3kyrxytx50g730svvmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqe49swv" - let expectedViewingKey = "zxviewtestsapling1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6l5smlqrckkl2x5rnrauzc4gp665q3zyw0qf2sfdsx5wpp832htfavqk72uchuuvq2dpmgk8jfaza5t5l56u66fpx0sr8ewp9s3wj2txavmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqgegsaj" + let expectedViewingKey = "uviewtest16dqd5q7zd3xfxlcm2jm5k95zd92ed3qcm5jr9uq6yl5y2h6vuwfpxlnndckv5hpwsajgvq26xgdcdns8mqclecl0zh4sph45t4ncfnhcsus0k6sashfknsp9ltxrxlf096ljkwmp7psh3z2vmcd3rcc72qaujsl2y23ajexhr7qza29u9k95frs8qqgvy83rgymt7mmw09a02a5ytjpa502tshlsgl2j736jlfuzt27gezlajrs2tw9c99uqxrj5sx942vdr7w6yk2ltz96yq7n96fd9nr48c59dh9znqtwtm0nt9tmt7vzwhdwzt00tgp57mn85hpe6w00upmjv52kct9y" + let expectedSaplingExtendedViewingKey = "zxviewtestsapling1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6l5smlqrckkl2x5rnrauzc4gp665q3zyw0qf2sfdsx5wpp832htfavqk72uchuuvq2dpmgk8jfaza5t5l56u66fpx0sr8ewp9s3wj2txavmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqgegsaj" let derivationTool = DerivationTool(networkType: NetworkType.testnet) let expectedTransparentAddress = "tmXuTnE11JojToagTqxXUn6KvdxDE3iLKbp" @@ -36,7 +37,7 @@ class DerivatioToolTestnetTests: XCTestCase { } func testDeriveViewingKeyFromSpendingKeys() throws { - XCTAssertEqual(expectedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey)) + XCTAssertEqual(expectedSaplingExtendedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey)) } func testDeriveSpendingKeysFromSeed() throws { @@ -54,15 +55,15 @@ class DerivatioToolTestnetTests: XCTestCase { } - func testDeriveShieldedAddressFromSeed() throws { + func testDeriveUnifiedAddressFromSeed() throws { let seedBytes = [UInt8](seedData) - let shieldedAddress = try derivationTool.deriveShieldedAddress(seed: seedBytes, accountIndex: 0) + let shieldedAddress = try derivationTool.deriveUnifiedAddress(seed: seedBytes, accountIndex: 0) XCTAssertEqual(shieldedAddress, testRecipientAddress) } - func testDeriveShieldedAddressFromViewingKey() throws { - XCTAssertEqual(try derivationTool.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress) + func testDeriveUnifiedAddressFromViewingKey() throws { + XCTAssertEqual(try derivationTool.deriveUnifiedAddress(viewingKey: expectedViewingKey), testRecipientAddress) } func testDeriveTransparentAddressFromSeed() throws { @@ -70,30 +71,28 @@ class DerivatioToolTestnetTests: XCTestCase { } func testIsValidViewingKey() throws { - XCTAssertTrue(try derivationTool.isValidExtendedViewingKey(self.expectedViewingKey)) + XCTAssertTrue(try derivationTool.isValidExtendedViewingKey(self.expectedSaplingExtendedViewingKey)) XCTAssertFalse(try derivationTool.isValidExtendedViewingKey("zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy")) } - func testDeriveSecretKeyFromSeed() throws { - XCTAssertEqual(try derivationTool.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "L2BCTxmSDiBRb33kGFd4pwGhp9r3FZqG3LZihgTkkg1J14vwtDbq") + func testDeriveTransparentAccountPrivateKeyFromSeed() throws { + XCTAssertEqual(try derivationTool.deriveTransparentAccountPrivateKey(seed: [UInt8](seedData)), "xprv9yURYog8Ds8XB36PVzPadbVaCPwVm4CZVMejW9bPPTqBCY8oLssPbe1MhJhPzSbVeg7cWZtuXxuUy2urADuAJUaN27c5f9nErx68SQokG1b") } func testDeriveUnifiedKeysFromSeed() throws { let unifiedKeys = try derivationTool.deriveUnifiedFullViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1) XCTAssertEqual(unifiedKeys.count, 1) - XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) - - XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + XCTAssertEqual(unifiedKeys[0].account, 0) + XCTAssertEqual(unifiedKeys[0].encoding, expectedViewingKey) } func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws { let unifiedKeys = try derivationTool.deriveUnifiedFullViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10) XCTAssertEqual(unifiedKeys.count, 10) - XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) - - XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + XCTAssertEqual(unifiedKeys[0].account, 0) + XCTAssertEqual(unifiedKeys[0].encoding, expectedViewingKey) } } diff --git a/Tests/OfflineTests/DerivationToolTests/DerivationToolMainnetTests.swift b/Tests/OfflineTests/DerivationToolTests/DerivationToolMainnetTests.swift index 3bd5aee5..333ee57d 100644 --- a/Tests/OfflineTests/DerivationToolTests/DerivationToolMainnetTests.swift +++ b/Tests/OfflineTests/DerivationToolTests/DerivationToolMainnetTests.swift @@ -11,11 +11,12 @@ import ZcashLightClientKit class DerivationToolMainnetTests: XCTestCase { var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment? var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! - let testRecipientAddress = "zs1vp7kvlqr4n9gpehztr76lcn6skkss9p8keqs3nv8avkdtjrcctrvmk9a7u494kluv756jeee5k0" //TODO: Parameterize this from environment + let testRecipientAddress = "u1l9f0l4348negsncgr9pxd9d3qaxagmqv3lnexcplmufpq7muffvfaue6ksevfvd7wrz7xrvn95rc5zjtn7ugkmgh5rnxswmcj30y0pw52pn0zjvy38rn2esfgve64rj5pcmazxgpyuj" //TODO: Parameterize this from environment let expectedSpendingKey = "secret-extended-key-main1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkyuegyhh5d4rdr8025nl7e0hm8r2txx3fuea5mquy3wnsr9tlajsg4wwvw0xcfk8357k4h850rgj72kt4rx3fjdz99zs9f4neda35cq8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszc7nc9vv" - let expectedViewingKey = "zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy" + let expectedViewingKey = "uview1jpddskrm73gpgrsx00y4dryapkhjlzrm5wfdcue77a26u3e7u28qu0xfsgzwt72rs60rjnwujr93al6sxchste78p8vvrlperlvladfwkyryakdutykdcqgqn9dfn9my6k3aka5ej78leksj6aptqs9yzcysszwzwr6zmrcqycxxlg87ten6ers6urmxthe3pvvh07ga7t4uz92a5y0jgej94a7u9q3nezjqj4zm634x2wc2d8d39nu74jew79phf9u025p82d8qshq0pnzcjcnke0g72gva28qsx0wvtad7qjwld5khgudwlxmx24av2mq4k5k9zypheeppcpnujc9rqpm" + let expectedSaplingExtendedViewingKey = "zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy" let derivationTool = DerivationTool(networkType: NetworkType.mainnet) let expectedTransparentAddress = "t1dRJRY7GmyeykJnMH38mdQoaZtFhn1QmGz" @@ -35,7 +36,7 @@ class DerivationToolMainnetTests: XCTestCase { } func testDeriveViewingKeyFromSpendingKeys() throws { - XCTAssertEqual(expectedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey)) + XCTAssertEqual(expectedSaplingExtendedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey)) } func testDeriveSpendingKeysFromSeed() throws { @@ -53,15 +54,15 @@ class DerivationToolMainnetTests: XCTestCase { } - func testDeriveShieldedAddressFromSeed() throws { + func testDeriveUnifiedAddressFromSeed() throws { let seedBytes = [UInt8](seedData) - let shieldedAddress = try derivationTool.deriveShieldedAddress(seed: seedBytes, accountIndex: 0) + let shieldedAddress = try derivationTool.deriveUnifiedAddress(seed: seedBytes, accountIndex: 0) XCTAssertEqual(shieldedAddress, testRecipientAddress) } - func testDeriveShieldedAddressFromViewingKey() throws { - XCTAssertEqual(try derivationTool.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress) + func testDeriveUnifiedAddressFromViewingKey() throws { + XCTAssertEqual(try derivationTool.deriveUnifiedAddress(viewingKey: expectedViewingKey), testRecipientAddress) } func testDeriveTransparentAddressFromSeed() throws { @@ -74,26 +75,24 @@ class DerivationToolMainnetTests: XCTestCase { XCTAssertFalse(try derivationTool.isValidExtendedViewingKey("zxviews1q0dm7hkzky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7")) } - func testDeriveSecretKeyFromSeed() throws { - XCTAssertEqual(try derivationTool.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "KwqfQoTCuQdCLvzpAEtkt1o8J62WJuZXD3cGRAf1bgmPWuLamHLo") + func testDeriveTransparentAccountPrivateKeyFromSeed() throws { + XCTAssertEqual(try derivationTool.deriveTransparentAccountPrivateKey(seed: [UInt8](seedData)), "xprv9yCTU6giJ1qZ1DLC5rc7KMzwY9s8rSRXYqmoAKffAExpUVUKLhcdvN9ERdxjEW8tQq4pxerLKZE3WcNUKZCeX19rVTxpV2msTyNMNiFT3Nw") } func testDeriveUnifiedKeysFromSeed() throws { let unifiedKeys = try derivationTool.deriveUnifiedFullViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1) XCTAssertEqual(unifiedKeys.count, 1) - XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) - - XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + XCTAssertEqual(unifiedKeys[0].account, 0) + XCTAssertEqual(unifiedKeys[0].encoding, expectedViewingKey) } func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws { let unifiedKeys = try derivationTool.deriveUnifiedFullViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10) XCTAssertEqual(unifiedKeys.count, 10) - XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey) - - XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub)) + XCTAssertEqual(unifiedKeys[0].account, 0) + XCTAssertEqual(unifiedKeys[0].encoding, expectedViewingKey) } func testShouldFailOnInvalidChecksumAddresses() throws { diff --git a/Tests/TestUtils/Stubs.swift b/Tests/TestUtils/Stubs.swift index e129f231..efedf0ae 100644 --- a/Tests/TestUtils/Stubs.swift +++ b/Tests/TestUtils/Stubs.swift @@ -103,7 +103,6 @@ class MockRustBackend: ZcashRustBackendWelding { static func putUnspentTransparentOutput( dbData: URL, - address: String, txid: [UInt8], index: Int, script: [UInt8], @@ -136,7 +135,7 @@ class MockRustBackend: ZcashRustBackendWelding { dbCache: URL, dbData: URL, account: Int32, - tsk: String, + xprv: String, extsk: String, memo: String?, spendParamsPath: String, @@ -150,11 +149,11 @@ class MockRustBackend: ZcashRustBackendWelding { throw KeyDerivationErrors.unableToDerive } - static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? { + static func deriveTransparentAccountPrivateKeyFromSeed(seed: [UInt8], account: Int, networkType: NetworkType) throws -> String? { throw KeyDerivationErrors.unableToDerive } - static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? { + static func deriveTransparentAddressFromAccountPrivateKey(_ xprv: String, index: Int, networkType: NetworkType) throws -> String? { throw KeyDerivationErrors.unableToDerive } @@ -162,7 +161,7 @@ class MockRustBackend: ZcashRustBackendWelding { throw KeyDerivationErrors.unableToDerive } - static func deriveUnifiedFullViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedFullViewingKey] { + static func deriveUnifiedFullViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int32, networkType: NetworkType) throws -> [UnifiedFullViewingKey] { throw KeyDerivationErrors.unableToDerive } @@ -170,6 +169,10 @@ class MockRustBackend: ZcashRustBackendWelding { false } + static func isValidUnifiedFullViewingKey(_ ufvk: String, networkType: NetworkType) throws -> Bool { + false + } + static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], networkType: NetworkType) throws -> String? { nil } @@ -190,11 +193,11 @@ class MockRustBackend: ZcashRustBackendWelding { nil } - static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? { + static func deriveUnifiedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? { nil } - static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? { + static func deriveUnifiedAddressFromViewingKey(_ ufvk: String, networkType: NetworkType) throws -> String? { nil }