Initial scaffold for Block Downloader

This commit is contained in:
Francisco Gindre 2019-09-12 20:24:54 -03:00
parent 8456ccc5b2
commit 8917a3bfba
21 changed files with 1535 additions and 43 deletions

View File

@ -1 +1,2 @@
github "grpc/grpc-swift" github "grpc/grpc-swift"
github "stephencelis/SQLite.swift"

View File

@ -1 +1,2 @@
github "grpc/grpc-swift" "0.9.1" github "grpc/grpc-swift" "0.9.1"
github "stephencelis/SQLite.swift" "0.12.2"

View File

@ -10,4 +10,3 @@ framework module ZcashLightClientKit {
} }
} }

View File

@ -22,6 +22,8 @@ Pod::Spec.new do |s|
s.ios.deployment_target = '11.0' s.ios.deployment_target = '11.0'
s.dependency 'SwiftGRPC' s.dependency 'SwiftGRPC'
s.dependency 'SQLite.swift'
s.ios.vendored_libraries = 'lib/libzcashlc.a' s.ios.vendored_libraries = 'lib/libzcashlc.a'

View File

@ -8,6 +8,20 @@
/* 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 */; };
0DB456F4232A860200057720 /* ZcashCompactBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456F3232A860200057720 /* ZcashCompactBlock.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 */; };
0DB456FF232A867800057720 /* compact_formats.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB456FA232A867800057720 /* compact_formats.pb.swift */; };
0DB45702232A86EF00057720 /* LightWalletGRPCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB45701232A86EF00057720 /* LightWalletGRPCService.swift */; };
0DB45705232AA06200057720 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB45704232AA06200057720 /* Storage.swift */; };
0DB45709232AA81200057720 /* Protocolbuffer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB45708232AA81200057720 /* Protocolbuffer+Extensions.swift */; };
0DB4570D232ACD3100057720 /* ZcashRustBackendWelding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB4570C232ACD3100057720 /* ZcashRustBackendWelding.swift */; };
0DB45711232ADD4B00057720 /* CompactBlockStoring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB45710232ADD4B00057720 /* CompactBlockStoring.swift */; };
0DB45713232AEAF200057720 /* LightWalletService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB45712232AEAF200057720 /* LightWalletService.swift */; };
0DB45714232B0AA800057720 /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6823284A2C0053EFAC /* BoringSSL.framework */; };
0DB45715232B0AA800057720 /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6623284A2C0053EFAC /* CgRPC.framework */; };
0DB45716232B0AA800057720 /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6723284A2C0053EFAC /* SwiftGRPC.framework */; };
0DB45717232B0AA800057720 /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6923284A2C0053EFAC /* SwiftProtobuf.framework */; };
0DC64E6A23284A2C0053EFAC /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6623284A2C0053EFAC /* CgRPC.framework */; }; 0DC64E6A23284A2C0053EFAC /* CgRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6623284A2C0053EFAC /* CgRPC.framework */; };
0DC64E6B23284A2C0053EFAC /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6723284A2C0053EFAC /* SwiftGRPC.framework */; }; 0DC64E6B23284A2C0053EFAC /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6723284A2C0053EFAC /* SwiftGRPC.framework */; };
0DC64E6C23284A2C0053EFAC /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6823284A2C0053EFAC /* BoringSSL.framework */; }; 0DC64E6C23284A2C0053EFAC /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6823284A2C0053EFAC /* BoringSSL.framework */; };
@ -32,6 +46,19 @@
/* 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>"; };
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>"; };
0DB456F8232A867800057720 /* service.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = service.pb.swift; sourceTree = "<group>"; };
0DB456F9232A867800057720 /* service.grpc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = service.grpc.swift; sourceTree = "<group>"; };
0DB456FA232A867800057720 /* compact_formats.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = compact_formats.pb.swift; sourceTree = "<group>"; };
0DB456FB232A867800057720 /* compact_formats.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = compact_formats.proto; sourceTree = "<group>"; };
0DB45701232A86EF00057720 /* LightWalletGRPCService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LightWalletGRPCService.swift; sourceTree = "<group>"; };
0DB45704232AA06200057720 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = "<group>"; };
0DB45706232AA6AF00057720 /* ZcashLightClientKit.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = ZcashLightClientKit.modulemap; sourceTree = "<group>"; };
0DB45708232AA81200057720 /* Protocolbuffer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Protocolbuffer+Extensions.swift"; sourceTree = "<group>"; };
0DB4570C232ACD3100057720 /* ZcashRustBackendWelding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashRustBackendWelding.swift; sourceTree = "<group>"; };
0DB45710232ADD4B00057720 /* CompactBlockStoring.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompactBlockStoring.swift; sourceTree = "<group>"; };
0DB45712232AEAF200057720 /* LightWalletService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightWalletService.swift; sourceTree = "<group>"; };
0DC64E6623284A2C0053EFAC /* CgRPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CgRPC.framework; path = Carthage/Build/iOS/CgRPC.framework; sourceTree = "<group>"; }; 0DC64E6623284A2C0053EFAC /* CgRPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CgRPC.framework; path = Carthage/Build/iOS/CgRPC.framework; sourceTree = "<group>"; };
0DC64E6723284A2C0053EFAC /* SwiftGRPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftGRPC.framework; path = Carthage/Build/iOS/SwiftGRPC.framework; sourceTree = "<group>"; }; 0DC64E6723284A2C0053EFAC /* SwiftGRPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftGRPC.framework; path = Carthage/Build/iOS/SwiftGRPC.framework; sourceTree = "<group>"; };
0DC64E6823284A2C0053EFAC /* BoringSSL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BoringSSL.framework; path = Carthage/Build/iOS/BoringSSL.framework; sourceTree = "<group>"; }; 0DC64E6823284A2C0053EFAC /* BoringSSL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BoringSSL.framework; path = Carthage/Build/iOS/BoringSSL.framework; sourceTree = "<group>"; };
@ -44,7 +71,6 @@
103AFE95228312A30074BC98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 103AFE95228312A30074BC98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
103AFEA12283166B0074BC98 /* libzcashlc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libzcashlc.a; path = target/universal/debug/libzcashlc.a; sourceTree = "<group>"; }; 103AFEA12283166B0074BC98 /* libzcashlc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libzcashlc.a; path = target/universal/debug/libzcashlc.a; sourceTree = "<group>"; };
103AFEA322831BB00074BC98 /* ZcashRustBackend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashRustBackend.swift; sourceTree = "<group>"; }; 103AFEA322831BB00074BC98 /* ZcashRustBackend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashRustBackend.swift; sourceTree = "<group>"; };
103AFEA8228320F00074BC98 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
103AFEA9228320F00074BC98 /* zcashlc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zcashlc.h; sourceTree = "<group>"; }; 103AFEA9228320F00074BC98 /* zcashlc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zcashlc.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -66,15 +92,86 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
103AFE8F228312A30074BC98 /* ZcashLightClientKit.framework in Frameworks */, 103AFE8F228312A30074BC98 /* ZcashLightClientKit.framework in Frameworks */,
0DB45714232B0AA800057720 /* BoringSSL.framework in Frameworks */,
0DB45715232B0AA800057720 /* CgRPC.framework in Frameworks */,
0DB45716232B0AA800057720 /* SwiftGRPC.framework in Frameworks */,
0DB45717232B0AA800057720 /* SwiftProtobuf.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
0DB456F2232A85D900057720 /* Model */ = {
isa = PBXGroup;
children = (
0DB456F3232A860200057720 /* ZcashCompactBlock.swift */,
);
path = Model;
sourceTree = "<group>";
};
0DB456F5232A863700057720 /* Service */ = {
isa = PBXGroup;
children = (
0DB45701232A86EF00057720 /* LightWalletGRPCService.swift */,
0DB456F2232A85D900057720 /* Model */,
0DB456F6232A864B00057720 /* ProtoBuf */,
0DB45712232AEAF200057720 /* LightWalletService.swift */,
);
path = Service;
sourceTree = "<group>";
};
0DB456F6232A864B00057720 /* ProtoBuf */ = {
isa = PBXGroup;
children = (
0DB45707232AA70900057720 /* Extensions */,
0DB456FA232A867800057720 /* compact_formats.pb.swift */,
0DB4570A232AA84000057720 /* proto */,
0DB456F9232A867800057720 /* service.grpc.swift */,
0DB456F8232A867800057720 /* service.pb.swift */,
);
path = ProtoBuf;
sourceTree = "<group>";
};
0DB45703232AA03C00057720 /* Storage */ = {
isa = PBXGroup;
children = (
0DB45704232AA06200057720 /* Storage.swift */,
0DB45710232ADD4B00057720 /* CompactBlockStoring.swift */,
);
path = Storage;
sourceTree = "<group>";
};
0DB45707232AA70900057720 /* Extensions */ = {
isa = PBXGroup;
children = (
0DB45708232AA81200057720 /* Protocolbuffer+Extensions.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
0DB4570A232AA84000057720 /* proto */ = {
isa = PBXGroup;
children = (
0DB456FB232A867800057720 /* compact_formats.proto */,
0DB456F7232A867800057720 /* service.proto */,
);
path = proto;
sourceTree = "<group>";
};
0DB4570B232ACD1700057720 /* Rust */ = {
isa = PBXGroup;
children = (
103AFEA322831BB00074BC98 /* ZcashRustBackend.swift */,
0DB4570C232ACD3100057720 /* ZcashRustBackendWelding.swift */,
);
path = Rust;
sourceTree = "<group>";
};
103AFE7B228312A30074BC98 = { 103AFE7B228312A30074BC98 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0DB45706232AA6AF00057720 /* ZcashLightClientKit.modulemap */,
103AFE87228312A30074BC98 /* ZcashLightClientKit */, 103AFE87228312A30074BC98 /* ZcashLightClientKit */,
103AFE92228312A30074BC98 /* ZcashLightClientKitTests */, 103AFE92228312A30074BC98 /* ZcashLightClientKitTests */,
103AFE86228312A30074BC98 /* Products */, 103AFE86228312A30074BC98 /* Products */,
@ -94,9 +191,11 @@
103AFE87228312A30074BC98 /* ZcashLightClientKit */ = { 103AFE87228312A30074BC98 /* ZcashLightClientKit */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0DB45703232AA03C00057720 /* Storage */,
0DB456F5232A863700057720 /* Service */,
103AFEA7228320F00074BC98 /* zcashlc */, 103AFEA7228320F00074BC98 /* zcashlc */,
103AFE88228312A30074BC98 /* ZcashLightClientKit.h */, 103AFE88228312A30074BC98 /* ZcashLightClientKit.h */,
103AFEA322831BB00074BC98 /* ZcashRustBackend.swift */, 0DB4570B232ACD1700057720 /* Rust */,
103AFE89228312A30074BC98 /* Info.plist */, 103AFE89228312A30074BC98 /* Info.plist */,
); );
path = ZcashLightClientKit; path = ZcashLightClientKit;
@ -127,7 +226,6 @@
103AFEA7228320F00074BC98 /* zcashlc */ = { 103AFEA7228320F00074BC98 /* zcashlc */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
103AFEA8228320F00074BC98 /* module.modulemap */,
103AFEA9228320F00074BC98 /* zcashlc.h */, 103AFEA9228320F00074BC98 /* zcashlc.h */,
); );
path = zcashlc; path = zcashlc;
@ -285,7 +383,17 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0DB45713232AEAF200057720 /* LightWalletService.swift in Sources */,
0DB456FD232A867800057720 /* service.pb.swift in Sources */,
0DB45702232A86EF00057720 /* LightWalletGRPCService.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 */,
0DB4570D232ACD3100057720 /* ZcashRustBackendWelding.swift in Sources */,
0DB45711232ADD4B00057720 /* CompactBlockStoring.swift in Sources */,
0DB45705232AA06200057720 /* Storage.swift in Sources */,
0DB456FF232A867800057720 /* compact_formats.pb.swift in Sources */,
0DB456F4232A860200057720 /* ZcashCompactBlock.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -507,6 +615,10 @@
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = ZcashLightClientKitTests/Info.plist; INFOPLIST_FILE = ZcashLightClientKitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -525,6 +637,10 @@
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = ZcashLightClientKitTests/Info.plist; INFOPLIST_FILE = ZcashLightClientKitTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",

View File

@ -0,0 +1,9 @@
//
// ZcashRust+Utils.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation

View File

@ -9,11 +9,7 @@
import Foundation import Foundation
public class ZcashRustBackend { public class ZcashRustBackend: ZcashRustBackendWelding {
static func osStrFromURL(_ url: URL) -> (String, UInt) {
let path = url.absoluteString
return (path, UInt(path.lengthOfBytes(using: .utf8)))
}
public static func getLastError() -> String? { public static func getLastError() -> String? {
let errorLen = zcashlc_last_error_length() let errorLen = zcashlc_last_error_length()
@ -28,12 +24,12 @@ public class ZcashRustBackend {
} }
public static func initDataDb(dbData: URL) -> Bool { public static func initDataDb(dbData: URL) -> Bool {
let dbData = osStrFromURL(dbData) 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]? { public static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? {
let dbData = osStrFromURL(dbData) 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 {
return nil return nil
@ -47,12 +43,12 @@ public class ZcashRustBackend {
} }
public static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) -> Bool { public static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) -> Bool {
let dbData = osStrFromURL(dbData) 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? { public static func getAddress(dbData: URL, account: Int32) -> String? {
let dbData = osStrFromURL(dbData) let dbData = dbData.osStr()
let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account) let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account)
if addressCStr == nil { if addressCStr == nil {
@ -65,17 +61,17 @@ public class ZcashRustBackend {
} }
public static func getBalance(dbData: URL, account: Int32) -> Int64 { public static func getBalance(dbData: URL, account: Int32) -> Int64 {
let dbData = osStrFromURL(dbData) 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 { public static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 {
let dbData = osStrFromURL(dbData) 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? { public static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
let dbData = osStrFromURL(dbData) 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)
if memoCStr == nil { if memoCStr == nil {
@ -88,7 +84,7 @@ public class ZcashRustBackend {
} }
public static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? { public static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
let dbData = osStrFromURL(dbData) 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)
if memoCStr == nil { if memoCStr == nil {
@ -101,26 +97,35 @@ public class ZcashRustBackend {
} }
public static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 { public static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 {
let dbCache = osStrFromURL(dbCache) let dbCache = dbCache.osStr()
let dbData = osStrFromURL(dbData) 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 { public static func rewindToHeight(dbData: URL, height: Int32) -> Bool {
let dbData = osStrFromURL(dbData) 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 { public static func scanBlocks(dbCache: URL, dbData: URL) -> Bool {
let dbCache = osStrFromURL(dbCache) let dbCache = dbCache.osStr()
let dbData = osStrFromURL(dbData) 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 { public static func sendToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParams: URL, outputParams: URL) -> Int64 {
let dbData = osStrFromURL(dbData) let dbData = dbData.osStr()
let spendParams = osStrFromURL(spendParams) let spendParams = spendParams.osStr()
let outputParams = osStrFromURL(outputParams) let outputParams = outputParams.osStr()
return zcashlc_send_to_address(dbData.0, dbData.1, account, extsk, to, value, memo, spendParams.0, spendParams.1, outputParams.0, outputParams.1) return zcashlc_send_to_address(dbData.0, dbData.1, account, extsk, to, value, memo, spendParams.0, spendParams.1, outputParams.0, outputParams.1)
} }
} }
private extension URL {
func osStr() -> (String, UInt) {
let path = self.absoluteString
return (path, UInt(path.lengthOfBytes(using: .utf8)))
}
}

View File

@ -0,0 +1,39 @@
//
// ZcashRustBackendWelding.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
protocol ZcashRustBackendWelding {
static func getLastError() -> String?
static func initDataDb(dbData: URL) -> Bool
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]?
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) -> Bool
static func getAddress(dbData: URL, account: Int32) -> String?
static func getBalance(dbData: URL, account: Int32) -> Int64
static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String?
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String?
static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32
static func rewindToHeight(dbData: URL, height: Int32) -> Bool
static func scanBlocks(dbCache: URL, dbData: URL) -> Bool
static func sendToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParams: URL, outputParams: URL) -> Int64
}

View File

@ -0,0 +1,87 @@
//
// ServiceHelper.swift
// gRPC-PoC
//
// Created by Francisco Gindre on 29/08/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
import SwiftGRPC
class Environment {
static let lightwalletdKey = "LIGHTWALLETD_ADDRESS"
static var address: String {
return ""
}
}
class LightWalletGRPCService {
static let shared = LightWalletGRPCService()
let compactTxStreamer: CompactTxStreamerServiceClient
private init() {
compactTxStreamer = CompactTxStreamerServiceClient(address: Environment.address, secure: false, arguments:[])
}
func blockRange(startHeight: UInt64, endHeight: UInt64? = nil, result: @escaping (CallResult)->()) throws -> CompactTxStreamerGetBlockRangeCall {
try compactTxStreamer.getBlockRange(BlockRange(startHeight: startHeight, endHeight: endHeight)) { result($0) }
}
func latestBlock() throws -> BlockID {
try compactTxStreamer.getLatestBlock(ChainSpec())
}
func getTx(hash:String) throws -> RawTransaction {
var filter = TxFilter()
filter.hash = Data(hash.utf8)
return try compactTxStreamer.getTransaction(filter)
}
func getAllBlocksSinceSaplingLaunch(_ result: @escaping (CallResult)->()) throws -> CompactTxStreamerGetBlockRangeCall {
try compactTxStreamer.getBlockRange(BlockRange.sinceSaplingActivation(), completion: result)
}
}
extension LightWalletGRPCService: LightWalletService {
func latestBlockHeight(result: @escaping (Result<UInt64, LightWalletServiceError>) -> ()) {
do {
try compactTxStreamer.getLatestBlock(ChainSpec()) { (blockID, callResult) in
guard let blockHeight = blockID?.height else {
result(.failure(LightWalletServiceError.generalError))
return
}
result(.success(blockHeight))
}
} catch {
// TODO: Handle Error
print(error.localizedDescription)
result(.failure(LightWalletServiceError.generalError))
}
}
func blockRange(_ range: Range<UInt64>, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
result(.failure(LightWalletServiceError.generalError))
}
}
extension LightWalletGRPCService: LightWalletSyncService {
func latestBlockHeight() throws -> UInt64 {
do {
return try latestBlock().height
} catch {
// TODO: Specify error
throw LightWalletServiceError.generalError
}
}
}

View File

@ -0,0 +1,40 @@
//
// LightWalletService.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
public enum LightWalletServiceError: Error {
case generalError
}
public protocol LightWalletSyncService {
/// Return the latest block height known to the service.
func latestBlockHeight() throws -> UInt64
}
public protocol LightWalletService {
/**
Return the latest block height known to the service.
- Parameter result: a result containing the height or an Error
*/
func latestBlockHeight(result: @escaping (Result<UInt64,LightWalletServiceError>) -> ())
/**
Return the given range of blocks.
- Parameter range: the inclusive range to fetch.
For instance if 1..5 is given, then every block in that will be fetched, including 1 and 5.
*/
func blockRange(_ range: Range<UInt64>, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void )
}

View File

@ -0,0 +1,45 @@
//
// ZcashCompactBlock.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
public struct ZcashCompactBlock {
var height: UInt64
var data: Data
}
extension ZcashCompactBlock {
init?(compactBlock: CompactBlock) {
do {
self.height = compactBlock.height
self.data = try compactBlock.serializedData()
} catch {
return nil
}
}
}
extension ZcashCompactBlock: Equatable {
public static func == (lhs: Self, rhs: Self) -> Bool {
if lhs.height != rhs.height {
return false
}
return lhs.data == rhs.data
}
}
extension ZcashCompactBlock: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(height)
hasher.combine(data)
}
}

View File

@ -0,0 +1,53 @@
//
// Protocolbuffer+Extensions.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
extension Range where Element == UInt64 {
func blockRange() -> BlockRange {
BlockRange(startHeight: lowerBound, endHeight: upperBound)
}
}
extension BlockID {
static let saplingActivationHeight: UInt64 = 280_000
init(height: UInt64) {
self = BlockID()
self.height = height
}
static var saplingActivation: BlockID {
BlockID(height: saplingActivationHeight)
}
}
extension BlockRange {
init(startHeight: UInt64, endHeight: UInt64? = nil) {
self = BlockRange()
self.start = BlockID(height: startHeight)
if let endHeight = endHeight {
self.end = BlockID(height: endHeight)
}
}
static func sinceSaplingActivation(to height: UInt64? = nil) -> BlockRange {
var blockRange = BlockRange()
blockRange.start = BlockID.saplingActivation
if let height = height {
blockRange.end = BlockID.init(height: height)
}
return blockRange
}
}

View File

@ -0,0 +1,300 @@
// DO NOT EDIT.
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: compact_formats.proto
//
// For information on using the generated types, please see the documenation:
// https://github.com/apple/swift-protobuf/
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that your are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// CompactBlock is a packaging of ONLY the data from a block that's needed to:
/// 1. Detect a payment to your shielded Sapling address
/// 2. Detect a spend of your shielded Sapling notes
/// 3. Update your witnesses to generate new Sapling spend proofs.
struct CompactBlock {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// the version of this wire format, for storage
var protoVersion: UInt32 = 0
/// the height of this block
var height: UInt64 = 0
var hash: Data = SwiftProtobuf.Internal.emptyData
var prevHash: Data = SwiftProtobuf.Internal.emptyData
var time: UInt32 = 0
/// (hash, prevHash, and time) OR (full header)
var header: Data = SwiftProtobuf.Internal.emptyData
/// compact transactions from this block
var vtx: [CompactTx] = []
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
struct CompactTx {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// Index and hash will allow the receiver to call out to chain
/// explorers or other data structures to retrieve more information
/// about this transaction.
var index: UInt64 = 0
var hash: Data = SwiftProtobuf.Internal.emptyData
/// The transaction fee: present if server can provide. In the case of a
/// stateless server and a transaction with transparent inputs, this will be
/// unset because the calculation requires reference to prior transactions.
/// in a pure-Sapling context, the fee will be calculable as:
/// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
var fee: UInt32 = 0
var spends: [CompactSpend] = []
var outputs: [CompactOutput] = []
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
struct CompactSpend {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var nf: Data = SwiftProtobuf.Internal.emptyData
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
struct CompactOutput {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var cmu: Data = SwiftProtobuf.Internal.emptyData
var epk: Data = SwiftProtobuf.Internal.emptyData
var ciphertext: Data = SwiftProtobuf.Internal.emptyData
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc"
extension CompactBlock: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".CompactBlock"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "protoVersion"),
2: .same(proto: "height"),
3: .same(proto: "hash"),
4: .same(proto: "prevHash"),
5: .same(proto: "time"),
6: .same(proto: "header"),
7: .same(proto: "vtx"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt32Field(value: &self.protoVersion)
case 2: try decoder.decodeSingularUInt64Field(value: &self.height)
case 3: try decoder.decodeSingularBytesField(value: &self.hash)
case 4: try decoder.decodeSingularBytesField(value: &self.prevHash)
case 5: try decoder.decodeSingularUInt32Field(value: &self.time)
case 6: try decoder.decodeSingularBytesField(value: &self.header)
case 7: try decoder.decodeRepeatedMessageField(value: &self.vtx)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.protoVersion != 0 {
try visitor.visitSingularUInt32Field(value: self.protoVersion, fieldNumber: 1)
}
if self.height != 0 {
try visitor.visitSingularUInt64Field(value: self.height, fieldNumber: 2)
}
if !self.hash.isEmpty {
try visitor.visitSingularBytesField(value: self.hash, fieldNumber: 3)
}
if !self.prevHash.isEmpty {
try visitor.visitSingularBytesField(value: self.prevHash, fieldNumber: 4)
}
if self.time != 0 {
try visitor.visitSingularUInt32Field(value: self.time, fieldNumber: 5)
}
if !self.header.isEmpty {
try visitor.visitSingularBytesField(value: self.header, fieldNumber: 6)
}
if !self.vtx.isEmpty {
try visitor.visitRepeatedMessageField(value: self.vtx, fieldNumber: 7)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: CompactBlock, rhs: CompactBlock) -> Bool {
if lhs.protoVersion != rhs.protoVersion {return false}
if lhs.height != rhs.height {return false}
if lhs.hash != rhs.hash {return false}
if lhs.prevHash != rhs.prevHash {return false}
if lhs.time != rhs.time {return false}
if lhs.header != rhs.header {return false}
if lhs.vtx != rhs.vtx {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension CompactTx: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".CompactTx"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "index"),
2: .same(proto: "hash"),
3: .same(proto: "fee"),
4: .same(proto: "spends"),
5: .same(proto: "outputs"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt64Field(value: &self.index)
case 2: try decoder.decodeSingularBytesField(value: &self.hash)
case 3: try decoder.decodeSingularUInt32Field(value: &self.fee)
case 4: try decoder.decodeRepeatedMessageField(value: &self.spends)
case 5: try decoder.decodeRepeatedMessageField(value: &self.outputs)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.index != 0 {
try visitor.visitSingularUInt64Field(value: self.index, fieldNumber: 1)
}
if !self.hash.isEmpty {
try visitor.visitSingularBytesField(value: self.hash, fieldNumber: 2)
}
if self.fee != 0 {
try visitor.visitSingularUInt32Field(value: self.fee, fieldNumber: 3)
}
if !self.spends.isEmpty {
try visitor.visitRepeatedMessageField(value: self.spends, fieldNumber: 4)
}
if !self.outputs.isEmpty {
try visitor.visitRepeatedMessageField(value: self.outputs, fieldNumber: 5)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: CompactTx, rhs: CompactTx) -> Bool {
if lhs.index != rhs.index {return false}
if lhs.hash != rhs.hash {return false}
if lhs.fee != rhs.fee {return false}
if lhs.spends != rhs.spends {return false}
if lhs.outputs != rhs.outputs {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension CompactSpend: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".CompactSpend"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "nf"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self.nf)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.nf.isEmpty {
try visitor.visitSingularBytesField(value: self.nf, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: CompactSpend, rhs: CompactSpend) -> Bool {
if lhs.nf != rhs.nf {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension CompactOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".CompactOutput"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "cmu"),
2: .same(proto: "epk"),
3: .same(proto: "ciphertext"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self.cmu)
case 2: try decoder.decodeSingularBytesField(value: &self.epk)
case 3: try decoder.decodeSingularBytesField(value: &self.ciphertext)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.cmu.isEmpty {
try visitor.visitSingularBytesField(value: self.cmu, fieldNumber: 1)
}
if !self.epk.isEmpty {
try visitor.visitSingularBytesField(value: self.epk, fieldNumber: 2)
}
if !self.ciphertext.isEmpty {
try visitor.visitSingularBytesField(value: self.ciphertext, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: CompactOutput, rhs: CompactOutput) -> Bool {
if lhs.cmu != rhs.cmu {return false}
if lhs.epk != rhs.epk {return false}
if lhs.ciphertext != rhs.ciphertext {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,48 @@
syntax = "proto3";
package cash.z.wallet.sdk.rpc;
option go_package = "walletrpc";
option swift_prefix = "";
// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
// bytes fields of hashes are in canonical little-endian format.
// CompactBlock is a packaging of ONLY the data from a block that's needed to:
// 1. Detect a payment to your shielded Sapling address
// 2. Detect a spend of your shielded Sapling notes
// 3. Update your witnesses to generate new Sapling spend proofs.
message CompactBlock {
uint32 protoVersion = 1; // the version of this wire format, for storage
uint64 height = 2; // the height of this block
bytes hash = 3;
bytes prevHash = 4;
uint32 time = 5;
bytes header = 6; // (hash, prevHash, and time) OR (full header)
repeated CompactTx vtx = 7; // compact transactions from this block
}
message CompactTx {
// Index and hash will allow the receiver to call out to chain
// explorers or other data structures to retrieve more information
// about this transaction.
uint64 index = 1;
bytes hash = 2;
// The transaction fee: present if server can provide. In the case of a
// stateless server and a transaction with transparent inputs, this will be
// unset because the calculation requires reference to prior transactions.
// in a pure-Sapling context, the fee will be calculable as:
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
uint32 fee = 3;
repeated CompactSpend spends = 4;
repeated CompactOutput outputs = 5;
}
message CompactSpend {
bytes nf = 1;
}
message CompactOutput {
bytes cmu = 1;
bytes epk = 2;
bytes ciphertext = 3;
}

View File

@ -0,0 +1,49 @@
syntax = "proto3";
package cash.z.wallet.sdk.rpc;
option go_package = "walletrpc";
option swift_prefix = "";
import "compact_formats.proto";
// A BlockID message contains identifiers to select a block: a height or a
// hash. If the hash is present it takes precedence.
message BlockID {
uint64 height = 1;
bytes hash = 2;
}
// BlockRange technically allows ranging from hash to hash etc but this is not
// currently intended for support, though there is no reason you couldn't do
// it. Further permutations are left as an exercise.
message BlockRange {
BlockID start = 1;
BlockID end = 2;
}
// A TxFilter contains the information needed to identify a particular
// transaction: either a block and an index, or a direct transaction hash.
message TxFilter {
BlockID block = 1;
uint64 index = 2;
bytes hash = 3;
}
// RawTransaction contains the complete transaction data.
message RawTransaction {
bytes data = 1;
}
message SendResponse {
int32 errorCode = 1;
string errorMessage = 2;
}
// Empty placeholder. Someday we may want to specify e.g. a particular chain fork.
message ChainSpec {}
service CompactTxStreamer {
rpc GetLatestBlock(ChainSpec) returns (BlockID) {}
rpc GetBlock(BlockID) returns (CompactBlock) {}
rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {}
rpc GetTransaction(TxFilter) returns (RawTransaction) {}
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
}

View File

@ -0,0 +1,208 @@
//
// DO NOT EDIT.
//
// Generated by the protocol buffer compiler.
// Source: service.proto
//
//
// Copyright 2018, gRPC Authors All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Dispatch
import Foundation
import SwiftGRPC
import SwiftProtobuf
internal protocol CompactTxStreamerGetLatestBlockCall: ClientCallUnary {}
fileprivate final class CompactTxStreamerGetLatestBlockCallBase: ClientCallUnaryBase<ChainSpec, BlockID>, CompactTxStreamerGetLatestBlockCall {
override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock" }
}
internal protocol CompactTxStreamerGetBlockCall: ClientCallUnary {}
fileprivate final class CompactTxStreamerGetBlockCallBase: ClientCallUnaryBase<BlockID, CompactBlock>, CompactTxStreamerGetBlockCall {
override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock" }
}
internal protocol CompactTxStreamerGetBlockRangeCall: ClientCallServerStreaming {
/// Do not call this directly, call `receive()` in the protocol extension below instead.
func _receive(timeout: DispatchTime) throws -> CompactBlock?
/// Call this to wait for a result. Nonblocking.
func receive(completion: @escaping (ResultOrRPCError<CompactBlock?>) -> Void) throws
}
internal extension CompactTxStreamerGetBlockRangeCall {
/// Call this to wait for a result. Blocking.
func receive(timeout: DispatchTime = .distantFuture) throws -> CompactBlock? { return try self._receive(timeout: timeout) }
}
fileprivate final class CompactTxStreamerGetBlockRangeCallBase: ClientCallServerStreamingBase<BlockRange, CompactBlock>, CompactTxStreamerGetBlockRangeCall {
override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange" }
}
internal protocol CompactTxStreamerGetTransactionCall: ClientCallUnary {}
fileprivate final class CompactTxStreamerGetTransactionCallBase: ClientCallUnaryBase<TxFilter, RawTransaction>, CompactTxStreamerGetTransactionCall {
override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction" }
}
internal protocol CompactTxStreamerSendTransactionCall: ClientCallUnary {}
fileprivate final class CompactTxStreamerSendTransactionCallBase: ClientCallUnaryBase<RawTransaction, SendResponse>, CompactTxStreamerSendTransactionCall {
override class var method: String { return "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction" }
}
/// Instantiate CompactTxStreamerServiceClient, then call methods of this protocol to make API calls.
internal protocol CompactTxStreamerService: ServiceClient {
/// Synchronous. Unary.
func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata) throws -> BlockID
/// Asynchronous. Unary.
@discardableResult
func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata, completion: @escaping (BlockID?, CallResult) -> Void) throws -> CompactTxStreamerGetLatestBlockCall
/// Synchronous. Unary.
func getBlock(_ request: BlockID, metadata customMetadata: Metadata) throws -> CompactBlock
/// Asynchronous. Unary.
@discardableResult
func getBlock(_ request: BlockID, metadata customMetadata: Metadata, completion: @escaping (CompactBlock?, CallResult) -> Void) throws -> CompactTxStreamerGetBlockCall
/// Asynchronous. Server-streaming.
/// Send the initial message.
/// Use methods on the returned object to get streamed responses.
func getBlockRange(_ request: BlockRange, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetBlockRangeCall
/// Synchronous. Unary.
func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata) throws -> RawTransaction
/// Asynchronous. Unary.
@discardableResult
func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata, completion: @escaping (RawTransaction?, CallResult) -> Void) throws -> CompactTxStreamerGetTransactionCall
/// Synchronous. Unary.
func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata) throws -> SendResponse
/// Asynchronous. Unary.
@discardableResult
func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata, completion: @escaping (SendResponse?, CallResult) -> Void) throws -> CompactTxStreamerSendTransactionCall
}
internal extension CompactTxStreamerService {
/// Synchronous. Unary.
func getLatestBlock(_ request: ChainSpec) throws -> BlockID {
return try self.getLatestBlock(request, metadata: self.metadata)
}
/// Asynchronous. Unary.
@discardableResult
func getLatestBlock(_ request: ChainSpec, completion: @escaping (BlockID?, CallResult) -> Void) throws -> CompactTxStreamerGetLatestBlockCall {
return try self.getLatestBlock(request, metadata: self.metadata, completion: completion)
}
/// Synchronous. Unary.
func getBlock(_ request: BlockID) throws -> CompactBlock {
return try self.getBlock(request, metadata: self.metadata)
}
/// Asynchronous. Unary.
@discardableResult
func getBlock(_ request: BlockID, completion: @escaping (CompactBlock?, CallResult) -> Void) throws -> CompactTxStreamerGetBlockCall {
return try self.getBlock(request, metadata: self.metadata, completion: completion)
}
/// Asynchronous. Server-streaming.
func getBlockRange(_ request: BlockRange, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetBlockRangeCall {
return try self.getBlockRange(request, metadata: self.metadata, completion: completion)
}
/// Synchronous. Unary.
func getTransaction(_ request: TxFilter) throws -> RawTransaction {
return try self.getTransaction(request, metadata: self.metadata)
}
/// Asynchronous. Unary.
@discardableResult
func getTransaction(_ request: TxFilter, completion: @escaping (RawTransaction?, CallResult) -> Void) throws -> CompactTxStreamerGetTransactionCall {
return try self.getTransaction(request, metadata: self.metadata, completion: completion)
}
/// Synchronous. Unary.
func sendTransaction(_ request: RawTransaction) throws -> SendResponse {
return try self.sendTransaction(request, metadata: self.metadata)
}
/// Asynchronous. Unary.
@discardableResult
func sendTransaction(_ request: RawTransaction, completion: @escaping (SendResponse?, CallResult) -> Void) throws -> CompactTxStreamerSendTransactionCall {
return try self.sendTransaction(request, metadata: self.metadata, completion: completion)
}
}
internal final class CompactTxStreamerServiceClient: ServiceClientBase, CompactTxStreamerService {
/// Synchronous. Unary.
internal func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata) throws -> BlockID {
return try CompactTxStreamerGetLatestBlockCallBase(channel)
.run(request: request, metadata: customMetadata)
}
/// Asynchronous. Unary.
@discardableResult
internal func getLatestBlock(_ request: ChainSpec, metadata customMetadata: Metadata, completion: @escaping (BlockID?, CallResult) -> Void) throws -> CompactTxStreamerGetLatestBlockCall {
return try CompactTxStreamerGetLatestBlockCallBase(channel)
.start(request: request, metadata: customMetadata, completion: completion)
}
/// Synchronous. Unary.
internal func getBlock(_ request: BlockID, metadata customMetadata: Metadata) throws -> CompactBlock {
return try CompactTxStreamerGetBlockCallBase(channel)
.run(request: request, metadata: customMetadata)
}
/// Asynchronous. Unary.
@discardableResult
internal func getBlock(_ request: BlockID, metadata customMetadata: Metadata, completion: @escaping (CompactBlock?, CallResult) -> Void) throws -> CompactTxStreamerGetBlockCall {
return try CompactTxStreamerGetBlockCallBase(channel)
.start(request: request, metadata: customMetadata, completion: completion)
}
/// Asynchronous. Server-streaming.
/// Send the initial message.
/// Use methods on the returned object to get streamed responses.
internal func getBlockRange(_ request: BlockRange, metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> CompactTxStreamerGetBlockRangeCall {
return try CompactTxStreamerGetBlockRangeCallBase(channel)
.start(request: request, metadata: customMetadata, completion: completion)
}
/// Synchronous. Unary.
internal func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata) throws -> RawTransaction {
return try CompactTxStreamerGetTransactionCallBase(channel)
.run(request: request, metadata: customMetadata)
}
/// Asynchronous. Unary.
@discardableResult
internal func getTransaction(_ request: TxFilter, metadata customMetadata: Metadata, completion: @escaping (RawTransaction?, CallResult) -> Void) throws -> CompactTxStreamerGetTransactionCall {
return try CompactTxStreamerGetTransactionCallBase(channel)
.start(request: request, metadata: customMetadata, completion: completion)
}
/// Synchronous. Unary.
internal func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata) throws -> SendResponse {
return try CompactTxStreamerSendTransactionCallBase(channel)
.run(request: request, metadata: customMetadata)
}
/// Asynchronous. Unary.
@discardableResult
internal func sendTransaction(_ request: RawTransaction, metadata customMetadata: Metadata, completion: @escaping (SendResponse?, CallResult) -> Void) throws -> CompactTxStreamerSendTransactionCall {
return try CompactTxStreamerSendTransactionCallBase(channel)
.start(request: request, metadata: customMetadata, completion: completion)
}
}

View File

@ -0,0 +1,408 @@
// DO NOT EDIT.
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: service.proto
//
// For information on using the generated types, please see the documenation:
// https://github.com/apple/swift-protobuf/
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that your are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// A BlockID message contains identifiers to select a block: a height or a
/// hash. If the hash is present it takes precedence.
struct BlockID {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var height: UInt64 = 0
var hash: Data = SwiftProtobuf.Internal.emptyData
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
/// BlockRange technically allows ranging from hash to hash etc but this is not
/// currently intended for support, though there is no reason you couldn't do
/// it. Further permutations are left as an exercise.
struct BlockRange {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var start: BlockID {
get {return _storage._start ?? BlockID()}
set {_uniqueStorage()._start = newValue}
}
/// Returns true if `start` has been explicitly set.
var hasStart: Bool {return _storage._start != nil}
/// Clears the value of `start`. Subsequent reads from it will return its default value.
mutating func clearStart() {_uniqueStorage()._start = nil}
var end: BlockID {
get {return _storage._end ?? BlockID()}
set {_uniqueStorage()._end = newValue}
}
/// Returns true if `end` has been explicitly set.
var hasEnd: Bool {return _storage._end != nil}
/// Clears the value of `end`. Subsequent reads from it will return its default value.
mutating func clearEnd() {_uniqueStorage()._end = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _storage = _StorageClass.defaultInstance
}
/// A TxFilter contains the information needed to identify a particular
/// transaction: either a block and an index, or a direct transaction hash.
struct TxFilter {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var block: BlockID {
get {return _storage._block ?? BlockID()}
set {_uniqueStorage()._block = newValue}
}
/// Returns true if `block` has been explicitly set.
var hasBlock: Bool {return _storage._block != nil}
/// Clears the value of `block`. Subsequent reads from it will return its default value.
mutating func clearBlock() {_uniqueStorage()._block = nil}
var index: UInt64 {
get {return _storage._index}
set {_uniqueStorage()._index = newValue}
}
var hash: Data {
get {return _storage._hash}
set {_uniqueStorage()._hash = newValue}
}
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _storage = _StorageClass.defaultInstance
}
/// RawTransaction contains the complete transaction data.
struct RawTransaction {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var data: Data = SwiftProtobuf.Internal.emptyData
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
struct SendResponse {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var errorCode: Int32 = 0
var errorMessage: String = String()
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
/// Empty placeholder. Someday we may want to specify e.g. a particular chain fork.
struct ChainSpec {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc"
extension BlockID: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".BlockID"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "height"),
2: .same(proto: "hash"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularUInt64Field(value: &self.height)
case 2: try decoder.decodeSingularBytesField(value: &self.hash)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.height != 0 {
try visitor.visitSingularUInt64Field(value: self.height, fieldNumber: 1)
}
if !self.hash.isEmpty {
try visitor.visitSingularBytesField(value: self.hash, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: BlockID, rhs: BlockID) -> Bool {
if lhs.height != rhs.height {return false}
if lhs.hash != rhs.hash {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension BlockRange: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".BlockRange"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "start"),
2: .same(proto: "end"),
]
fileprivate class _StorageClass {
var _start: BlockID? = nil
var _end: BlockID? = nil
static let defaultInstance = _StorageClass()
private init() {}
init(copying source: _StorageClass) {
_start = source._start
_end = source._end
}
}
fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularMessageField(value: &_storage._start)
case 2: try decoder.decodeSingularMessageField(value: &_storage._end)
default: break
}
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
if let v = _storage._start {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}
if let v = _storage._end {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: BlockRange, rhs: BlockRange) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._start != rhs_storage._start {return false}
if _storage._end != rhs_storage._end {return false}
return true
}
if !storagesAreEqual {return false}
}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension TxFilter: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TxFilter"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "block"),
2: .same(proto: "index"),
3: .same(proto: "hash"),
]
fileprivate class _StorageClass {
var _block: BlockID? = nil
var _index: UInt64 = 0
var _hash: Data = SwiftProtobuf.Internal.emptyData
static let defaultInstance = _StorageClass()
private init() {}
init(copying source: _StorageClass) {
_block = source._block
_index = source._index
_hash = source._hash
}
}
fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularMessageField(value: &_storage._block)
case 2: try decoder.decodeSingularUInt64Field(value: &_storage._index)
case 3: try decoder.decodeSingularBytesField(value: &_storage._hash)
default: break
}
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
if let v = _storage._block {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}
if _storage._index != 0 {
try visitor.visitSingularUInt64Field(value: _storage._index, fieldNumber: 2)
}
if !_storage._hash.isEmpty {
try visitor.visitSingularBytesField(value: _storage._hash, fieldNumber: 3)
}
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: TxFilter, rhs: TxFilter) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._block != rhs_storage._block {return false}
if _storage._index != rhs_storage._index {return false}
if _storage._hash != rhs_storage._hash {return false}
return true
}
if !storagesAreEqual {return false}
}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension RawTransaction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".RawTransaction"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "data"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self.data)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.data.isEmpty {
try visitor.visitSingularBytesField(value: self.data, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: RawTransaction, rhs: RawTransaction) -> Bool {
if lhs.data != rhs.data {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension SendResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".SendResponse"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "errorCode"),
2: .same(proto: "errorMessage"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1: try decoder.decodeSingularInt32Field(value: &self.errorCode)
case 2: try decoder.decodeSingularStringField(value: &self.errorMessage)
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.errorCode != 0 {
try visitor.visitSingularInt32Field(value: self.errorCode, fieldNumber: 1)
}
if !self.errorMessage.isEmpty {
try visitor.visitSingularStringField(value: self.errorMessage, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: SendResponse, rhs: SendResponse) -> Bool {
if lhs.errorCode != rhs.errorCode {return false}
if lhs.errorMessage != rhs.errorMessage {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension ChainSpec: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".ChainSpec"
static let _protobuf_nameMap = SwiftProtobuf._NameMap()
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let _ = try decoder.nextFieldNumber() {
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: ChainSpec, rhs: ChainSpec) -> Bool {
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,32 @@
//
// CompactBlockStoring.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
protocol CompactBlockStoring {
///
/// Gets the highest block that is currently stored.
///
func getLatestHeight() -> UInt64
///
/// Write the given blocks to this store, which may be anything from an in-memory cache to a DB.
///
func write(result: [CompactBlock])
///
/// Remove every block above and including the given height.
///
/// After this operation, the data store will look the same as one that has not yet stored the given block height.
/// Meaning, if max height is 100 block and rewindTo(50) is called, then the highest block remaining will be 49.
///
func rewindTo(height: Int)
}

View File

@ -0,0 +1,13 @@
//
// Storage.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
class ZcashStorage {
}

View File

@ -11,25 +11,58 @@ import XCTest
class ZcashLightClientKitTests: XCTestCase { class ZcashLightClientKitTests: XCTestCase {
override func setUp() { static var latestBlock: BlockID = try! LightWalletGRPCService.shared.latestBlock()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() { func testEnvironmentLaunch() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
} let address = Environment.address
XCTAssertFalse(address.isEmpty, "Your \'\(Environment.lightwalletdKey)\' key is missing from your launch environment variables")
}
func testService() {
// and that it has a non-zero size
XCTAssert(Self.latestBlock.height > 0)
}
func testBlockRangeService() {
func testExample() { let expect = XCTestExpectation(description: self.debugDescription)
// This is an example of a functional test case. let _ = try? LightWalletGRPCService.shared.getAllBlocksSinceSaplingLaunch(){ result in
// Use XCTAssert and related functions to verify your tests produce the correct results. print(result)
XCTAssert(ZcashRustBackend.getLastError() == nil) expect.fulfill()
} XCTAssert(result.success)
XCTAssertNotNil(result.resultData)
func testPerformanceExample() { }
// This is an example of a performance test case. wait(for: [expect], timeout: 10)
self.measure { }
// Put the code you want to measure the time of here.
} func testBlockRangeServiceTilLastest() {
} let expectedCount: UInt64 = 99
var count: UInt64 = 0
let expect = XCTestExpectation(description: self.debugDescription)
let startHeight = Self.latestBlock.height - expectedCount
let endHeight = Self.latestBlock.height
guard let call = try? LightWalletGRPCService.shared.blockRange(startHeight: startHeight, endHeight: endHeight,result: {
result in
XCTAssert(result.success)
}) else {
XCTFail("failed to create getBlockRange( \(startHeight) ..<= \(endHeight)")
return
}
wait(for: [expect], timeout: 20)
while let _ = try? call.receive() {
expect.fulfill()
count += 1
}
XCTAssertEqual(expectedCount + 1, count)
}
} }

View File

@ -43,5 +43,9 @@ class ZcashRustBackendTests: XCTestCase {
XCTAssert(ZcashRustBackend.getLastError() != nil) XCTAssert(ZcashRustBackend.getLastError() != nil)
XCTAssertEqual(addr2, nil) XCTAssertEqual(addr2, nil)
} }
func testInitCacheDb() {
XCTFail("Not Implemented")
}
} }