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.
This commit is contained in:
parent
b0343d4c38
commit
def779e5bc
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -94,6 +94,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()
|
||||
var capacity = UInt(0)
|
||||
|
@ -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<CChar>.allocate(capacity: extfvkCStr.count)
|
||||
extfvkPtr.initialize(from: extfvkCStr, count: extfvkCStr.count)
|
||||
let ufvkPtr = UnsafeMutablePointer<CChar>.allocate(capacity: ufvkCStr.count)
|
||||
ufvkPtr.initialize(from: ufvkCStr, count: ufvkCStr.count)
|
||||
|
||||
let extpubCStr = [CChar](String(ufvk.extpub).utf8CString)
|
||||
let extpubPtr = UnsafeMutablePointer<CChar>.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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<PendingTransactionEntity, Error>) -> Void
|
||||
|
|
|
@ -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<PendingTransactionEntity, Error>) -> 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 }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
|
|||
|
||||
func encodeShieldingTransaction(
|
||||
spendingKey: String,
|
||||
tsk: String,
|
||||
xprv: String,
|
||||
pendingTransaction: PendingTransactionEntity,
|
||||
result: @escaping (Result<PendingTransactionEntity, Error>) -> 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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<PendingTransactionEntity, Error>) -> Void)
|
||||
func encodeShieldingTransaction(spendingKey: String, xprv: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result<PendingTransactionEntity, Error>) -> Void)
|
||||
|
||||
func encode(spendingKey: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result<PendingTransactionEntity, Error>) -> Void)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue