(Failing) init Wallet test

This commit is contained in:
Francisco Gindre 2019-09-13 17:57:41 -03:00
parent 8917a3bfba
commit 7c38c61cc9
6 changed files with 235 additions and 14 deletions

View File

@ -8,6 +8,10 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
0B45933D22C612CB002A66BA /* ZcashRustBackendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B45933C22C612CB002A66BA /* ZcashRustBackendTests.swift */; }; 0B45933D22C612CB002A66BA /* ZcashRustBackendTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B45933C22C612CB002A66BA /* ZcashRustBackendTests.swift */; };
0DA33493232C0BC200CAC082 /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA33492232C0BC200CAC082 /* Wallet.swift */; };
0DA33496232C11DF00CAC082 /* SeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA33495232C11DF00CAC082 /* SeedProvider.swift */; };
0DA33498232C1A8200CAC082 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA33497232C1A8200CAC082 /* Constants.swift */; };
0DA3349A232C1B6F00CAC082 /* WalletTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA33499232C1B6F00CAC082 /* WalletTests.swift */; };
0DB456F4232A860200057720 /* ZcashCompactBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F3232A860200057720 /* ZcashCompactBlock.swift */; }; 0DB456F4232A860200057720 /* ZcashCompactBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F3232A860200057720 /* ZcashCompactBlock.swift */; };
0DB456FD232A867800057720 /* service.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F8232A867800057720 /* service.pb.swift */; }; 0DB456FD232A867800057720 /* service.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F8232A867800057720 /* service.pb.swift */; };
0DB456FE232A867800057720 /* service.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F9232A867800057720 /* service.grpc.swift */; }; 0DB456FE232A867800057720 /* service.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F9232A867800057720 /* service.grpc.swift */; };
@ -46,6 +50,10 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
0B45933C22C612CB002A66BA /* ZcashRustBackendTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashRustBackendTests.swift; sourceTree = "<group>"; }; 0B45933C22C612CB002A66BA /* ZcashRustBackendTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashRustBackendTests.swift; sourceTree = "<group>"; };
0DA33492232C0BC200CAC082 /* Wallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; };
0DA33495232C11DF00CAC082 /* SeedProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedProvider.swift; sourceTree = "<group>"; };
0DA33497232C1A8200CAC082 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
0DA33499232C1B6F00CAC082 /* WalletTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletTests.swift; sourceTree = "<group>"; };
0DB456F3232A860200057720 /* ZcashCompactBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashCompactBlock.swift; sourceTree = "<group>"; }; 0DB456F3232A860200057720 /* ZcashCompactBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashCompactBlock.swift; sourceTree = "<group>"; };
0DB456F7232A867800057720 /* service.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = service.proto; sourceTree = "<group>"; }; 0DB456F7232A867800057720 /* service.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = service.proto; sourceTree = "<group>"; };
0DB456F8232A867800057720 /* service.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = service.pb.swift; sourceTree = "<group>"; }; 0DB456F8232A867800057720 /* service.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = service.pb.swift; sourceTree = "<group>"; };
@ -102,6 +110,14 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
0DA33494232C11C600CAC082 /* Providers */ = {
isa = PBXGroup;
children = (
0DA33495232C11DF00CAC082 /* SeedProvider.swift */,
);
path = Providers;
sourceTree = "<group>";
};
0DB456F2232A85D900057720 /* Model */ = { 0DB456F2232A85D900057720 /* Model */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -191,12 +207,15 @@
103AFE87228312A30074BC98 /* ZcashLightClientKit */ = { 103AFE87228312A30074BC98 /* ZcashLightClientKit */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0DA33494232C11C600CAC082 /* Providers */,
0DB45703232AA03C00057720 /* Storage */, 0DB45703232AA03C00057720 /* Storage */,
0DB456F5232A863700057720 /* Service */, 0DB456F5232A863700057720 /* Service */,
103AFEA7228320F00074BC98 /* zcashlc */, 103AFEA7228320F00074BC98 /* zcashlc */,
103AFE88228312A30074BC98 /* ZcashLightClientKit.h */, 103AFE88228312A30074BC98 /* ZcashLightClientKit.h */,
0DB4570B232ACD1700057720 /* Rust */, 0DB4570B232ACD1700057720 /* Rust */,
103AFE89228312A30074BC98 /* Info.plist */, 103AFE89228312A30074BC98 /* Info.plist */,
0DA33492232C0BC200CAC082 /* Wallet.swift */,
0DA33497232C1A8200CAC082 /* Constants.swift */,
); );
path = ZcashLightClientKit; path = ZcashLightClientKit;
sourceTree = "<group>"; sourceTree = "<group>";
@ -206,6 +225,7 @@
children = ( children = (
103AFE93228312A30074BC98 /* ZcashLightClientKitTests.swift */, 103AFE93228312A30074BC98 /* ZcashLightClientKitTests.swift */,
0B45933C22C612CB002A66BA /* ZcashRustBackendTests.swift */, 0B45933C22C612CB002A66BA /* ZcashRustBackendTests.swift */,
0DA33499232C1B6F00CAC082 /* WalletTests.swift */,
103AFE95228312A30074BC98 /* Info.plist */, 103AFE95228312A30074BC98 /* Info.plist */,
); );
path = ZcashLightClientKitTests; path = ZcashLightClientKitTests;
@ -383,15 +403,18 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0DA33493232C0BC200CAC082 /* Wallet.swift in Sources */,
0DB45713232AEAF200057720 /* LightWalletService.swift in Sources */, 0DB45713232AEAF200057720 /* LightWalletService.swift in Sources */,
0DB456FD232A867800057720 /* service.pb.swift in Sources */, 0DB456FD232A867800057720 /* service.pb.swift in Sources */,
0DB45702232A86EF00057720 /* LightWalletGRPCService.swift in Sources */, 0DB45702232A86EF00057720 /* LightWalletGRPCService.swift in Sources */,
0DA33496232C11DF00CAC082 /* SeedProvider.swift in Sources */,
0DB456FE232A867800057720 /* service.grpc.swift in Sources */, 0DB456FE232A867800057720 /* service.grpc.swift in Sources */,
103AFEA422831BB00074BC98 /* ZcashRustBackend.swift in Sources */, 103AFEA422831BB00074BC98 /* ZcashRustBackend.swift in Sources */,
0DB45709232AA81200057720 /* Protocolbuffer+Extensions.swift in Sources */, 0DB45709232AA81200057720 /* Protocolbuffer+Extensions.swift in Sources */,
0DB4570D232ACD3100057720 /* ZcashRustBackendWelding.swift in Sources */, 0DB4570D232ACD3100057720 /* ZcashRustBackendWelding.swift in Sources */,
0DB45711232ADD4B00057720 /* CompactBlockStoring.swift in Sources */, 0DB45711232ADD4B00057720 /* CompactBlockStoring.swift in Sources */,
0DB45705232AA06200057720 /* Storage.swift in Sources */, 0DB45705232AA06200057720 /* Storage.swift in Sources */,
0DA33498232C1A8200CAC082 /* Constants.swift in Sources */,
0DB456FF232A867800057720 /* compact_formats.pb.swift in Sources */, 0DB456FF232A867800057720 /* compact_formats.pb.swift in Sources */,
0DB456F4232A860200057720 /* ZcashCompactBlock.swift in Sources */, 0DB456F4232A860200057720 /* ZcashCompactBlock.swift in Sources */,
); );
@ -402,6 +425,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0B45933D22C612CB002A66BA /* ZcashRustBackendTests.swift in Sources */, 0B45933D22C612CB002A66BA /* ZcashRustBackendTests.swift in Sources */,
0DA3349A232C1B6F00CAC082 /* WalletTests.swift in Sources */,
103AFE94228312A30074BC98 /* ZcashLightClientKitTests.swift in Sources */, 103AFE94228312A30074BC98 /* ZcashLightClientKitTests.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -0,0 +1,74 @@
//
// Constants.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 13/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
/**
* Miner's fee in zatoshi.
*/
let MINERS_FEE_ZATOSHI: UInt64 = 10_000
/**
* The number of zatoshi that equal 1 ZEC.
*/
let ZATOSHI_PER_ZEC: UInt64 = 100_000_000
/**
* The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
* prior to this height, at all.
*/
let SAPLING_ACTIVATION_HEIGHT: UInt64 = 280_000
/**
* The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
*/
let MAX_REORG_SIZE = 100
/**
* The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled
* by the rust backend but it is helpful to know what it is set to and shdould be kept in sync.
*/
let EXPIRY_OFFSET = 20
//
// Defaults
//
/**
* Default size of batches of blocks to request from the compact block service.
*/
let DEFAULT_BATCH_SIZE = 100
/**
* Default amount of time, in milliseconds, to poll for new blocks. Typically, this should be about half the average
* block time.
*/
let DEFAULT_POLL_INTERVAL: UInt64 = 75_000
/**
* Default attempts at retrying.
*/
let DEFAULT_RETRIES = 5
/**
* The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
* this before retyring.
*/
let DEFAULT_MAX_BACKOFF_INTERVAL: UInt64 = 600_000
/**
* Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the
* reorg but smaller than the theoretical max reorg size of 100.
*/
let DEFAULT_REWIND_DISTANCE = 10
/**
* The number of blocks to allow before considering our data to be stale. This usually helps with what to do when
* returning from the background and is exposed via the Synchronizer's isStale function.
*/
let DEFAULT_STALE_TOLERANCE = 10

View File

@ -0,0 +1,13 @@
//
// SeedProvider.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 13/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
public protocol SeedProvider {
func seed() -> [UInt8]
}

View File

@ -9,9 +9,9 @@
import Foundation import Foundation
public class ZcashRustBackend: ZcashRustBackendWelding { class ZcashRustBackend: ZcashRustBackendWelding {
public static func getLastError() -> String? { static func getLastError() -> String? {
let errorLen = zcashlc_last_error_length() let errorLen = zcashlc_last_error_length()
if errorLen > 0 { if errorLen > 0 {
let error = UnsafeMutablePointer<Int8>.allocate(capacity: Int(errorLen)) let error = UnsafeMutablePointer<Int8>.allocate(capacity: Int(errorLen))
@ -23,12 +23,12 @@ public class ZcashRustBackend: ZcashRustBackendWelding {
} }
} }
public static func initDataDb(dbData: URL) -> Bool { static func initDataDb(dbData: URL) -> Bool {
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_init_data_database(dbData.0, dbData.1) != 0 return zcashlc_init_data_database(dbData.0, dbData.1) != 0
} }
public static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? { static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts) let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts)
if extsksCStr == nil { if extsksCStr == nil {
@ -42,12 +42,12 @@ public class ZcashRustBackend: ZcashRustBackendWelding {
return extsks return extsks
} }
public static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) -> Bool { static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) -> Bool {
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString)) != 0 return zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString)) != 0
} }
public static func getAddress(dbData: URL, account: Int32) -> String? { static func getAddress(dbData: URL, account: Int32) -> String? {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account) let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account)
@ -60,17 +60,17 @@ public class ZcashRustBackend: ZcashRustBackendWelding {
return address return address
} }
public static func getBalance(dbData: URL, account: Int32) -> Int64 { static func getBalance(dbData: URL, account: Int32) -> Int64 {
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_get_balance(dbData.0, dbData.1, account) return zcashlc_get_balance(dbData.0, dbData.1, account)
} }
public static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 { static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 {
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_get_verified_balance(dbData.0, dbData.1, account) return zcashlc_get_verified_balance(dbData.0, dbData.1, account)
} }
public static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote) let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote)
@ -83,7 +83,7 @@ public class ZcashRustBackend: ZcashRustBackendWelding {
return memo return memo
} }
public static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote) let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote)
@ -96,24 +96,24 @@ public class ZcashRustBackend: ZcashRustBackendWelding {
return memo return memo
} }
public static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 { static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 {
let dbCache = dbCache.osStr() let dbCache = dbCache.osStr()
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1) return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1)
} }
public static func rewindToHeight(dbData: URL, height: Int32) -> Bool { static func rewindToHeight(dbData: URL, height: Int32) -> Bool {
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_rewind_to_height(dbData.0, dbData.1, height) != 0 return zcashlc_rewind_to_height(dbData.0, dbData.1, height) != 0
} }
public static func scanBlocks(dbCache: URL, dbData: URL) -> Bool { static func scanBlocks(dbCache: URL, dbData: URL) -> Bool {
let dbCache = dbCache.osStr() let dbCache = dbCache.osStr()
let dbData = dbData.osStr() let dbData = dbData.osStr()
return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1) != 0 return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1) != 0
} }
public static func sendToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParams: URL, outputParams: URL) -> Int64 { static func sendToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParams: URL, outputParams: URL) -> Int64 {
let dbData = dbData.osStr() let dbData = dbData.osStr()
let spendParams = spendParams.osStr() let spendParams = spendParams.osStr()
let outputParams = outputParams.osStr() let outputParams = outputParams.osStr()

View File

@ -0,0 +1,62 @@
//
// Wallet.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 13/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
/**
Wrapper for the Rust backend. This class basically represents all the Rust-wallet
capabilities and the supporting data required to exercise those abilities.
*/
public class Wallet {
private var rustBackend: ZcashRustBackendWelding.Type
private var dataDbURL: URL
private var paramDestination: URL
private var accountIDs: [Int]
private var seedProvider: SeedProvider
init(rustWelding: ZcashRustBackendWelding.Type, dataDbURL: URL, paramDestination: URL, seedProvider: SeedProvider, accountIDs: [Int] = [0]) {
self.rustBackend = rustWelding.self
self.dataDbURL = dataDbURL
self.paramDestination = paramDestination
self.accountIDs = accountIDs
self.seedProvider = seedProvider
}
func initalize(firstRunStartHeight: UInt64 = SAPLING_ACTIVATION_HEIGHT) {
}
}
/**
Represents the wallet's birthday which can be thought of as a checkpoint at the earliest moment in history where
transactions related to this wallet could exist. Ideally, this would correspond to the latest block height at the
time the wallet key was created. Worst case, the height of Sapling activation could be used (280000).
Knowing a wallet's birthday can significantly reduce the amount of data that it needs to download because none of
the data before that height needs to be scanned for transactions. However, we do need the Sapling tree data in
order to construct valid transactions from that point forward. This birthday contains that tree data, allowing us
to avoid downloading all the compact blocks required in order to generate it.
New wallets can ignore any blocks created before their birthday.
- Parameter height the height at the time the wallet was born
- Parameter hash the block hash corresponding to the given height
- Parameter time the time the wallet was born, in seconds
- Parameter tree the sapling tree corresponding to the given height. This takes around 15 minutes of processing to
generate from scratch because all blocks since activation need to be considered. So when it is calculated in
advance it can save the user a lot of time.
*/
public struct WalletBirthday {
var height: Int64 = -1
var hash: String = ""
var time: TimeInterval = -1
var tree: String = ""
}

View File

@ -0,0 +1,48 @@
//
// WalletTests.swift
// ZcashLightClientKitTests
//
// Created by Francisco Gindre on 13/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
import XCTest
@testable import ZcashLightClientKit
class WalletTests: XCTestCase {
var dbData: URL! = nil
var paramDestination: URL! = nil
var cacheData: URL! = nil
override func setUp() {
let dataDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
dbData = dataDir.appendingPathComponent("data.db")
cacheData = dataDir.appendingPathComponent("cache.db")
paramDestination = dataDir.appendingPathComponent("parameters")
}
override func tearDown() {
if FileManager.default.fileExists(atPath: dbData.absoluteString) {
try! FileManager.default.trashItem(at: dbData, resultingItemURL: nil)
}
}
func testWalletInitialization() {
let wallet = Wallet(rustWelding: ZcashRustBackend.self, dataDbURL: dbData, paramDestination: paramDestination, seedProvider: SampleSeedProvider())
wallet.initalize()
XCTAssertTrue(FileManager.default.fileExists(atPath: dbData.absoluteString))
XCTAssertTrue(FileManager.default.fileExists(atPath: paramDestination.absoluteString))
XCTAssertTrue(FileManager.default.fileExists(atPath: cacheData.absoluteString))
}
}
struct SampleSeedProvider: SeedProvider {
func seed() -> [UInt8] {
Array("seed".utf8)
}
}