Initial scaffold for Block Downloader
This commit is contained in:
parent
8456ccc5b2
commit
8917a3bfba
|
@ -1 +1,2 @@
|
|||
github "grpc/grpc-swift" "0.9.1"
|
||||
github "stephencelis/SQLite.swift" "0.12.2"
|
||||
|
|
|
@ -10,4 +10,3 @@ framework module ZcashLightClientKit {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ Pod::Spec.new do |s|
|
|||
s.ios.deployment_target = '11.0'
|
||||
|
||||
s.dependency 'SwiftGRPC'
|
||||
s.dependency 'SQLite.swift'
|
||||
|
||||
|
||||
|
||||
s.ios.vendored_libraries = 'lib/libzcashlc.a'
|
||||
|
|
|
@ -8,6 +8,20 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
0DC64E6B23284A2C0053EFAC /* SwiftGRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6723284A2C0053EFAC /* SwiftGRPC.framework */; };
|
||||
0DC64E6C23284A2C0053EFAC /* BoringSSL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DC64E6823284A2C0053EFAC /* BoringSSL.framework */; };
|
||||
|
@ -32,6 +46,19 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -44,7 +71,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -66,15 +92,86 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
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;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase 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 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0DB45706232AA6AF00057720 /* ZcashLightClientKit.modulemap */,
|
||||
103AFE87228312A30074BC98 /* ZcashLightClientKit */,
|
||||
103AFE92228312A30074BC98 /* ZcashLightClientKitTests */,
|
||||
103AFE86228312A30074BC98 /* Products */,
|
||||
|
@ -94,9 +191,11 @@
|
|||
103AFE87228312A30074BC98 /* ZcashLightClientKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0DB45703232AA03C00057720 /* Storage */,
|
||||
0DB456F5232A863700057720 /* Service */,
|
||||
103AFEA7228320F00074BC98 /* zcashlc */,
|
||||
103AFE88228312A30074BC98 /* ZcashLightClientKit.h */,
|
||||
103AFEA322831BB00074BC98 /* ZcashRustBackend.swift */,
|
||||
0DB4570B232ACD1700057720 /* Rust */,
|
||||
103AFE89228312A30074BC98 /* Info.plist */,
|
||||
);
|
||||
path = ZcashLightClientKit;
|
||||
|
@ -127,7 +226,6 @@
|
|||
103AFEA7228320F00074BC98 /* zcashlc */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
103AFEA8228320F00074BC98 /* module.modulemap */,
|
||||
103AFEA9228320F00074BC98 /* zcashlc.h */,
|
||||
);
|
||||
path = zcashlc;
|
||||
|
@ -285,7 +383,17 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
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 */,
|
||||
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;
|
||||
};
|
||||
|
@ -507,6 +615,10 @@
|
|||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
);
|
||||
INFOPLIST_FILE = ZcashLightClientKitTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -525,6 +637,10 @@
|
|||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
);
|
||||
INFOPLIST_FILE = ZcashLightClientKitTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -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
|
|
@ -9,11 +9,7 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
public class ZcashRustBackend {
|
||||
static func osStrFromURL(_ url: URL) -> (String, UInt) {
|
||||
let path = url.absoluteString
|
||||
return (path, UInt(path.lengthOfBytes(using: .utf8)))
|
||||
}
|
||||
public class ZcashRustBackend: ZcashRustBackendWelding {
|
||||
|
||||
public static func getLastError() -> String? {
|
||||
let errorLen = zcashlc_last_error_length()
|
||||
|
@ -28,12 +24,12 @@ public class ZcashRustBackend {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
if extsksCStr == 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 {
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
if addressCStr == nil {
|
||||
|
@ -65,17 +61,17 @@ public class ZcashRustBackend {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
if memoCStr == nil {
|
||||
|
@ -88,7 +84,7 @@ public class ZcashRustBackend {
|
|||
}
|
||||
|
||||
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)
|
||||
if memoCStr == nil {
|
||||
|
@ -101,26 +97,35 @@ public class ZcashRustBackend {
|
|||
}
|
||||
|
||||
public static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 {
|
||||
let dbCache = osStrFromURL(dbCache)
|
||||
let dbData = osStrFromURL(dbData)
|
||||
let dbCache = dbCache.osStr()
|
||||
let dbData = dbData.osStr()
|
||||
return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
public static func scanBlocks(dbCache: URL, dbData: URL) -> Bool {
|
||||
let dbCache = osStrFromURL(dbCache)
|
||||
let dbData = osStrFromURL(dbData)
|
||||
let dbCache = dbCache.osStr()
|
||||
let dbData = dbData.osStr()
|
||||
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 {
|
||||
let dbData = osStrFromURL(dbData)
|
||||
let spendParams = osStrFromURL(spendParams)
|
||||
let outputParams = osStrFromURL(outputParams)
|
||||
let dbData = dbData.osStr()
|
||||
let spendParams = spendParams.osStr()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private extension URL {
|
||||
|
||||
func osStr() -> (String, UInt) {
|
||||
let path = self.absoluteString
|
||||
return (path, UInt(path.lengthOfBytes(using: .utf8)))
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 )
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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) {}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -11,25 +11,58 @@ import XCTest
|
|||
|
||||
class ZcashLightClientKitTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
static var latestBlock: BlockID = try! LightWalletGRPCService.shared.latestBlock()
|
||||
|
||||
func testEnvironmentLaunch() {
|
||||
|
||||
let address = Environment.address
|
||||
|
||||
XCTAssertFalse(address.isEmpty, "Your \'\(Environment.lightwalletdKey)\' key is missing from your launch environment variables")
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
func testService() {
|
||||
|
||||
// and that it has a non-zero size
|
||||
XCTAssert(Self.latestBlock.height > 0)
|
||||
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
XCTAssert(ZcashRustBackend.getLastError() == nil)
|
||||
func testBlockRangeService() {
|
||||
|
||||
let expect = XCTestExpectation(description: self.debugDescription)
|
||||
let _ = try? LightWalletGRPCService.shared.getAllBlocksSinceSaplingLaunch(){ result in
|
||||
print(result)
|
||||
expect.fulfill()
|
||||
XCTAssert(result.success)
|
||||
XCTAssertNotNil(result.resultData)
|
||||
}
|
||||
wait(for: [expect], timeout: 10)
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
// This is an example of a performance test case.
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,4 +44,8 @@ class ZcashRustBackendTests: XCTestCase {
|
|||
XCTAssertEqual(addr2, nil)
|
||||
}
|
||||
|
||||
func testInitCacheDb() {
|
||||
XCTFail("Not Implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue