[wip] autoshield poc with uvks

This commit is contained in:
Francisco Gindre 2021-04-02 19:18:16 -03:00
parent 8046bed300
commit 65aa7d8474
34 changed files with 561 additions and 327 deletions

24
Cargo.lock generated
View File

@ -437,7 +437,7 @@ checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "equihash"
version = "0.1.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#3dcdc51b369d9470d69baecdd5e992f45a57cbcd"
dependencies = [
"blake2b_simd",
"byteorder",
@ -693,9 +693,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.91"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
[[package]]
name = "libsqlite3-sys"
@ -859,9 +859,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@ -1288,9 +1288,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
[[package]]
name = "syn"
version = "1.0.67"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702"
checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
dependencies = [
"proc-macro2",
"quote",
@ -1540,7 +1540,7 @@ checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
[[package]]
name = "zcash_client_backend"
version = "0.5.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#3dcdc51b369d9470d69baecdd5e992f45a57cbcd"
dependencies = [
"base64",
"bech32",
@ -1551,6 +1551,7 @@ dependencies = [
"hdwallet",
"hex",
"jubjub",
"log",
"nom",
"percent-encoding",
"protobuf",
@ -1567,7 +1568,7 @@ dependencies = [
[[package]]
name = "zcash_client_sqlite"
version = "0.3.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#3dcdc51b369d9470d69baecdd5e992f45a57cbcd"
dependencies = [
"bech32",
"bs58 0.4.0",
@ -1577,6 +1578,7 @@ dependencies = [
"protobuf",
"rand_core 0.5.1",
"rusqlite",
"secp256k1",
"time",
"zcash_client_backend",
"zcash_primitives",
@ -1585,7 +1587,7 @@ dependencies = [
[[package]]
name = "zcash_primitives"
version = "0.5.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#3dcdc51b369d9470d69baecdd5e992f45a57cbcd"
dependencies = [
"aes",
"bitvec 0.18.5",
@ -1614,7 +1616,7 @@ dependencies = [
[[package]]
name = "zcash_proofs"
version = "0.5.0"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#111161b47ee788867989c3c52627034659799be8"
source = "git+https://github.com/nuttycom/librustzcash?branch=autoshield-poc-daa#3dcdc51b369d9470d69baecdd5e992f45a57cbcd"
dependencies = [
"bellman",
"blake2b_simd",

View File

@ -57,5 +57,5 @@ zcash_proofs = {git = "https://github.com/nuttycom/librustzcash", branch = "auto
[features]
mainnet = ["zcash_client_sqlite/mainnet", "zcash_client_sqlite/transparent-inputs", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
testnet = ["zcash_client_sqlite/transparent-inputs", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
mainnet = ["zcash_client_sqlite/mainnet", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
testnet = ["zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]

View File

@ -74,7 +74,25 @@ class DerivationToolTests: XCTestCase {
}
func testDeriveSecretKeyFromSeed() throws {
XCTAssertEqual(try DerivationTool.default.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "127ec31a3482e53940aaefbc41c9621a344c84e4e16cc2c9af380d81b8f7bb74")
XCTAssertEqual(try DerivationTool.default.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "KwqfQoTCuQdCLvzpAEtkt1o8J62WJuZXD3cGRAf1bgmPWuLamHLo")
}
func testDeriveUnifiedKeysFromSeed() throws {
let unifiedKeys = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1)
XCTAssertEqual(unifiedKeys.count, 1)
XCTAssertEqual(unifiedKeys[0].extfxk, expectedViewingKey)
XCTAssertEqual(expectedTransparentAddress, try DerivationTool.default.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
}
func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws {
let unifiedKeys = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10)
XCTAssertEqual(unifiedKeys.count, 10)
XCTAssertEqual(unifiedKeys[0].extfxk, expectedViewingKey)
XCTAssertEqual(expectedTransparentAddress, try DerivationTool.default.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
}
}

View File

@ -5,12 +5,12 @@ target 'ZcashLightClientSample' do
use_frameworks!
pod "KRProgressHUD"
# Pods for ZcashLightClientSample
pod 'ZcashLightClientKit', :path => '../../', :testspecs => ['Tests']
pod 'ZcashLightClientKit', :path => '../../', :testspecs => ['Tests', 'DerivationToolTests']
pod 'gRPC-Swift', '= 1.0.0-alpha.19'
pod 'PaginatedTableView'
pod 'NotificationBubbles'
pod 'MnemonicSwift', '~> 2.0.0'
pod 'gRPC-Swift-Plugins', '= 1.0.0-alpha.19'
pod 'gRPC-Swift-Plugins', '= 1.0.0-alpha.19'
target 'ZcashLightClientSampleTests' do
use_frameworks!
inherit! :search_paths

View File

@ -69,6 +69,9 @@ PODS:
- ZcashLightClientKit (0.10.0):
- gRPC-Swift (= 1.0.0-alpha.19)
- SQLite.swift (~> 0.12.2)
- ZcashLightClientKit/DerivationToolTests (0.10.0):
- gRPC-Swift (= 1.0.0-alpha.19)
- SQLite.swift (~> 0.12.2)
- ZcashLightClientKit/Tests (0.10.0):
- gRPC-Swift (= 1.0.0-alpha.19)
- SQLite.swift (~> 0.12.2)
@ -81,6 +84,7 @@ DEPENDENCIES:
- NotificationBubbles
- PaginatedTableView
- ZcashLightClientKit (from `../../`)
- ZcashLightClientKit/DerivationToolTests (from `../../`)
- ZcashLightClientKit/Tests (from `../../`)
SPEC REPOS:
@ -145,8 +149,8 @@ SPEC CHECKSUMS:
SwiftNIOTLS: 46bb3a0ff37d6b52ae6baf5207ec3cd411da327c
SwiftNIOTransportServices: 801923921fbecdcde1e1c1ff38e812167d01ead1
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
ZcashLightClientKit: a1a36be74ca95e2802ba3d6bcc40e9b2753eb0da
ZcashLightClientKit: 2489ea17976192891b4c509e355194f1fea9d8f4
PODFILE CHECKSUM: db5fd49340d00419df0653aac7d56eaeb37d71b6
PODFILE CHECKSUM: 459c257dc96354d8f60d386deee2f61d3dff05e6
COCOAPODS: 1.10.1

View File

@ -40,9 +40,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
spendParamsURL: try! __spendParamsURL(),
outputParamsURL: try! __outputParamsURL(),
loggerProxy: loggerProxy)
try! wallet.initialize(viewingKeys: try DerivationTool.default.deriveViewingKeys(seed: DemoAppConfig.seed, numberOfAccounts: 1),
walletBirthday: BlockHeight(DemoAppConfig.birthdayHeight)) // Init or DIE
let unifiedViewingKeys = try! DerivationTool.default.deriveUnifiedViewingKeysFromSeed(DemoAppConfig.seed, accounts: 1)
try! wallet.initialize(unifiedViewingKeys: unifiedViewingKeys, walletBirthday: DemoAppConfig.birthdayHeight)
var storage = SampleStorage.shared
storage!.seed = Data(DemoAppConfig.seed)
storage!.privateKey = try! DerivationTool.default.deriveSpendingKeys(seed: DemoAppConfig.seed, numberOfAccounts: 1)[0]

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ewq-Xy-xHb">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ewq-Xy-xHb">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18092"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -21,7 +21,7 @@
<tableViewSection id="HAA-1f-le3">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Dic-ex-pwz" style="IBUITableViewCellStyleDefault" id="thm-RZ-Mhh">
<rect key="frame" x="0.0" y="28" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="24.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="thm-RZ-Mhh" id="zOR-bL-Uwc">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -41,7 +41,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="AMo-WC-MIN" style="IBUITableViewCellStyleDefault" id="rCB-Ax-4Nk">
<rect key="frame" x="0.0" y="71.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="68" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rCB-Ax-4Nk" id="ac2-bZ-mAy">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -61,7 +61,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="22C-pR-Rhi" style="IBUITableViewCellStyleDefault" id="qk9-yY-QrM">
<rect key="frame" x="0.0" y="115" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="111.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qk9-yY-QrM" id="eYr-ez-FSd">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -81,7 +81,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="v8L-AQ-cAg" style="IBUITableViewCellStyleDefault" id="RKO-CX-5oF">
<rect key="frame" x="0.0" y="158.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="155" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="RKO-CX-5oF" id="WdD-zf-ng7">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -101,7 +101,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="CS3-Hm-JPK" style="IBUITableViewCellStyleDefault" id="lX6-BP-STv">
<rect key="frame" x="0.0" y="202" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="198.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="lX6-BP-STv" id="uYl-mR-smC">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -121,7 +121,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="hfc-dh-b2p" style="IBUITableViewCellStyleDefault" id="U6y-0k-TWn">
<rect key="frame" x="0.0" y="245.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="242" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="U6y-0k-TWn" id="7aj-Lt-9o9">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -141,7 +141,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="oRc-aQ-3vN" style="IBUITableViewCellStyleDefault" id="rBT-Qj-4GX">
<rect key="frame" x="0.0" y="289" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="285.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rBT-Qj-4GX" id="7t0-PZ-KW4">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -161,7 +161,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="mo0-CA-kMx" style="IBUITableViewCellStyleDefault" id="cYW-no-fyA">
<rect key="frame" x="0.0" y="332.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="329" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="cYW-no-fyA" id="uu3-KF-LDB">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -181,7 +181,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="3ht-A5-ABT" style="IBUITableViewCellStyleDefault" id="Bvc-KS-SGJ">
<rect key="frame" x="0.0" y="376" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="372.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Bvc-KS-SGJ" id="Hsp-0f-x3X">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -201,7 +201,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Hl7-xV-yrM" style="IBUITableViewCellStyleDefault" id="6sF-sD-nYj">
<rect key="frame" x="0.0" y="419.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="416" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="6sF-sD-nYj" id="Uwh-62-xaj">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -221,7 +221,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="HyY-vt-5nR" style="IBUITableViewCellStyleDefault" id="KkJ-uD-G5q">
<rect key="frame" x="0.0" y="463" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="459.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="KkJ-uD-G5q" id="VL6-QM-S0g">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -241,7 +241,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="XCC-pZ-eel" style="IBUITableViewCellStyleDefault" id="dgB-c9-cv9">
<rect key="frame" x="0.0" y="506.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="503" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="dgB-c9-cv9" id="C46-42-3yU">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -261,7 +261,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="B3i-Nh-NA5" style="IBUITableViewCellStyleDefault" id="VPb-7U-IKD">
<rect key="frame" x="0.0" y="550" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="546.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VPb-7U-IKD" id="IWX-T9-THE">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -281,7 +281,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="qHq-xq-jFS" style="IBUITableViewCellStyleDefault" id="XHY-aU-r1N">
<rect key="frame" x="0.0" y="593.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="590" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="XHY-aU-r1N" id="fbk-CU-wgr">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -333,7 +333,7 @@
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="TransactionCell" textLabel="U7p-Y7-W1b" detailTextLabel="ngx-lY-C9z" style="IBUITableViewCellStyleSubtitle" id="0Hj-GS-f83">
<rect key="frame" x="0.0" y="28" width="414" height="55.5"/>
<rect key="frame" x="0.0" y="24.5" width="414" height="55.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0Hj-GS-f83" id="kvD-mY-4FK">
<rect key="frame" x="0.0" y="0.0" width="414" height="55.5"/>
@ -392,7 +392,7 @@
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="TransactionCell" textLabel="ZgQ-vD-hBa" detailTextLabel="hDe-Pg-Ygb" style="IBUITableViewCellStyleSubtitle" id="GMs-Mo-bHf">
<rect key="frame" x="0.0" y="28" width="414" height="55.5"/>
<rect key="frame" x="0.0" y="24.5" width="414" height="55.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="GMs-Mo-bHf" id="nOf-Pp-I0d">
<rect key="frame" x="0.0" y="0.0" width="414" height="55.5"/>
@ -442,7 +442,7 @@
<tableViewSection id="Imd-sb-3mE">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="MpE-wV-n7T" detailTextLabel="MTZ-wv-E8d" style="IBUITableViewCellStyleValue1" id="uXj-iO-KC7">
<rect key="frame" x="0.0" y="28" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="24.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="uXj-iO-KC7" id="u8d-s3-Cfw">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -466,7 +466,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Lz1-6q-dQ6" detailTextLabel="7dw-1w-ESS" style="IBUITableViewCellStyleValue1" id="0ZY-GI-cSR">
<rect key="frame" x="0.0" y="71.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="68" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0ZY-GI-cSR" id="9iI-wa-toz">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -490,7 +490,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="ZSW-Nk-44G" detailTextLabel="3it-Im-6mo" style="IBUITableViewCellStyleValue1" id="vOD-TS-02F">
<rect key="frame" x="0.0" y="115" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="111.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="vOD-TS-02F" id="fLc-fy-nhk">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -514,7 +514,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="dPr-pp-SCj" detailTextLabel="K4H-bj-ib8" style="IBUITableViewCellStyleValue1" id="XBY-8p-p9S">
<rect key="frame" x="0.0" y="158.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="155" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="XBY-8p-p9S" id="CpS-YZ-N9j">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -538,7 +538,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Wfw-cd-nlP" detailTextLabel="jYD-YI-5xs" style="IBUITableViewCellStyleValue1" id="P41-F8-Ckh">
<rect key="frame" x="0.0" y="202" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="198.5" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="P41-F8-Ckh" id="833-jd-Oel">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -562,7 +562,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="xAE-4b-AOI" detailTextLabel="oC7-12-jMn" style="IBUITableViewCellStyleValue1" id="XXE-Lf-J0N">
<rect key="frame" x="0.0" y="245.5" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="242" width="414" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="XXE-Lf-J0N" id="HsE-jx-cyi">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
@ -1396,50 +1396,29 @@
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="9yg-Sp-H2E">
<rect key="frame" x="16" y="77" width="382" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="FE1-89-7l2"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<connections>
<outlet property="delegate" destination="Ugl-B2-O3O" id="Z8u-00-LZw"/>
</connections>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1NQ-co-Y8P">
<rect key="frame" x="186.5" y="165" width="41.5" height="20.5"/>
<rect key="frame" x="186.5" y="77" width="41.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Verified Balance:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p9L-dk-3rL">
<rect key="frame" x="143.5" y="137.5" width="127.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WbJ-AR-1Pj">
<rect key="frame" x="186.5" y="198" width="41.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="ZXk-2m-Kua">
<rect key="frame" x="65.5" y="225.5" width="283" height="150"/>
<rect key="frame" x="87" y="258.5" width="240" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1h3-3y-iS9">
<rect key="frame" x="0.0" y="0.0" width="283" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="v9k-94-gxX"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="29"/>
<state key="normal" title="Get UTXOs!"/>
<connections>
<action selector="getButtonTapped:" destination="Ugl-B2-O3O" eventType="touchUpInside" id="Vlr-m4-asM"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tX1-H6-Zs8">
<rect key="frame" x="0.0" y="50" width="283" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="JJc-9O-Kdl"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="29"/>
<state key="normal" title="Get UTXO from cache!"/>
<connections>
<action selector="getFromCacheTapped:" destination="Ugl-B2-O3O" eventType="touchUpInside" id="3Pl-RP-4qg"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rFx-Kk-dDU" userLabel="Shield these funds!">
<rect key="frame" x="0.0" y="100" width="283" height="50"/>
<rect key="frame" x="0.0" y="0.0" width="240" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="tRE-yf-7sR"/>
</constraints>
@ -1452,21 +1431,19 @@
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mv9-ye-VIn">
<rect key="frame" x="16" y="415.5" width="382" height="0.0"/>
<rect key="frame" x="16" y="348.5" width="382" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pcE-rS-DWU">
<rect key="frame" x="0.0" y="455.5" width="414" height="318.5"/>
<rect key="frame" x="0.0" y="388.5" width="414" height="385.5"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</subviews>
<constraints>
<constraint firstItem="Mv9-ye-VIn" firstAttribute="leading" secondItem="Dcv-Hc-vFg" secondAttribute="leading" constant="16" id="8Og-mD-yax"/>
<constraint firstAttribute="trailing" secondItem="9yg-Sp-H2E" secondAttribute="trailing" constant="16" id="9WS-lo-XzQ"/>
<constraint firstAttribute="trailing" secondItem="Mv9-ye-VIn" secondAttribute="trailing" constant="16" id="XHM-Ae-k4o"/>
<constraint firstItem="9yg-Sp-H2E" firstAttribute="leading" secondItem="Dcv-Hc-vFg" secondAttribute="leading" constant="16" id="x6l-fj-8ez"/>
</constraints>
</stackView>
</subviews>
@ -1485,11 +1462,11 @@
</view>
<navigationItem key="navigationItem" id="VUG-Af-cu9"/>
<connections>
<outlet property="getButton" destination="1h3-3y-iS9" id="pdY-q5-oIL"/>
<outlet property="getFromCache" destination="tX1-H6-Zs8" id="FQS-Hl-Hl9"/>
<outlet property="messageLabel" destination="Mv9-ye-VIn" id="c6d-Fe-mrx"/>
<outlet property="tAddressField" destination="9yg-Sp-H2E" id="oQV-JY-09h"/>
<outlet property="validAddressLabel" destination="1NQ-co-Y8P" id="mHT-cp-vnn"/>
<outlet property="shieldFundsButton" destination="rFx-Kk-dDU" id="VWE-aS-0fu"/>
<outlet property="totalBalanceLabel" destination="WbJ-AR-1Pj" id="eWj-1C-HBs"/>
<outlet property="transparentAddressLabel" destination="1NQ-co-Y8P" id="PcX-vz-CDf"/>
<outlet property="verifiedBalanceLabel" destination="p9L-dk-3rL" id="TLN-Nl-Qb3"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="GFR-y5-3AF" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>

View File

@ -35,4 +35,3 @@ enum ZcashNetwork {
case mainNet
case testNet
}

View File

@ -10,12 +10,12 @@ import UIKit
import ZcashLightClientKit
import KRProgressHUD
class GetUTXOsViewController: UIViewController {
@IBOutlet weak var tAddressField: UITextField!
@IBOutlet weak var getButton: UIButton!
@IBOutlet weak var getFromCache: UIButton!
@IBOutlet weak var shieldFundsButton: UIButton!
@IBOutlet weak var validAddressLabel: UILabel!
@IBOutlet weak var transparentAddressLabel: UILabel!
@IBOutlet weak var verifiedBalanceLabel: UILabel!
@IBOutlet weak var totalBalanceLabel: UILabel!
@IBOutlet weak var messageLabel: UILabel!
@IBOutlet weak var shieldFundsButton: UIButton!
override func viewDidLoad() {
@ -26,63 +26,13 @@ class GetUTXOsViewController: UIViewController {
}
func updateUI() {
let valid = Initializer.shared.isValidTransparentAddress(tAddressField.text ?? "")
let tAddress = try! DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)
self.transparentAddressLabel.text = tAddress
self.validAddressLabel.text = valid ? "Valid TransparentAddress" : "Invalid Transparent address"
self.validAddressLabel.textColor = valid ? UIColor.systemGreen : UIColor.systemRed
let balance = try! AppDelegate.shared.sharedSynchronizer.getTransparentBalance(address: tAddress)
self.getButton.isEnabled = valid
self.getFromCache.isEnabled = valid
}
@IBAction func getButtonTapped(_ sender: Any) {
guard Initializer.shared.isValidTransparentAddress(tAddressField.text ?? ""),
let tAddr = tAddressField.text else {
self.messageLabel.text = "Invalid t-Address"
return
}
KRProgressHUD.showMessage("fetching")
AppDelegate.shared.sharedSynchronizer.refreshUTXOs(address: tAddr) { (result) in
DispatchQueue.main.async { [weak self] in
KRProgressHUD.dismiss()
switch result {
case .success(let utxos):
do {
let balance = try AppDelegate.shared.sharedSynchronizer.getTransparentBalance(address: tAddr)
self?.messageLabel.text = """
Stored \(utxos.inserted.count) UTXOs for address \(tAddr)
\(utxos.skipped.count) Skipped
\(balance)
"""
} catch {
self?.messageLabel.text = "Error \(error)"
}
case .failure(let error):
self?.messageLabel.text = "Error \(error)"
}
}
}
}
@IBAction func getFromCacheTapped(_ sender: Any) {
guard Initializer.shared.isValidTransparentAddress(tAddressField.text ?? ""),
let tAddr = tAddressField.text else {
self.messageLabel.text = "Invalid t-Address"
return
}
do {
let utxos = try AppDelegate.shared.sharedSynchronizer.cachedUTXOs(address: tAddr)
self.messageLabel.text = "found \(utxos.count) UTXOs for address \(tAddr) on cache"
} catch {
self.messageLabel.text = "Error \(error)"
}
}
@IBAction func viewTapped(_ recognizer: UITapGestureRecognizer) {
self.tAddressField.resignFirstResponder()
self.totalBalanceLabel.text = String(balance.total.asHumanReadableZecBalance())
self.verifiedBalanceLabel.text = String(balance.verified.asHumanReadableZecBalance())
}
@IBAction func shieldFunds(_ sender: Any) {
@ -120,14 +70,3 @@ extension GetUTXOsViewController: UITextFieldDelegate {
}
}
extension WalletBalance {
var description: String {
"""
WalletBalance:
verified: \(self.verified)
Total: \(self.total)
"""
}
}

View File

@ -43,5 +43,16 @@ Pod::Spec.new do |s|
}
test_spec.dependency 'gRPC-Swift', '= 1.0.0-alpha.19'
test_spec.dependency 'SQLite.swift', '~> 0.12.2'
end
s.test_spec 'DerivationToolTests' do | test_spec |
test_spec.source_files = 'DerivationToolTests/**/*.{swift}'
test_spec.script_phase = {
:name => 'Build generate constants and build librustzcash',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh --testing',
:execution_position => :before_compile
}
test_spec.dependency 'gRPC-Swift', '= 1.0.0-alpha.19'
test_spec.dependency 'SQLite.swift', '~> 0.12.2'
end
end

View File

@ -39,8 +39,6 @@ class MigrationManager {
static let latestPendingDbMigrationVersion: Int32 = PendingDbMigration.none.rawValue
func performMigration(seedBytes: [UInt8]) throws {
let currentPendingDbVersion = try pendingDb.connection().getUserVersion()
try migrateDataDb(seedBytes: seedBytes)
try migrateCacheDb()
try migratePendingDb()
@ -134,10 +132,9 @@ class MigrationManager {
LoggerProxy.debug("db.execute(\"\(migrationStatement)\")")
try db.execute(migrationStatement)
LoggerProxy.debug("db.run() succeeded")
// derive transparent (shielding) addresses
// derive transparent (shielding) addresses
let accountsDao = AccountSQDAO(dbProvider: self.dataDb)
let accounts = try accountsDao.getAll()
@ -154,7 +151,7 @@ class MigrationManager {
}
// sanity check
guard try accountsDao.getAll().first(where: { $0.transparentAddress == placeholder}) == nil else {
guard try accountsDao.getAll().first(where: { $0.transparentAddress == placeholder }) == nil else {
LoggerProxy.error("Accounts Migration performed but the transparent addresses were not derived")
throw StorageError.migrationFailed(underlyingError: KeyDerivationErrors.unableToDerive)
}

View File

@ -58,16 +58,18 @@ class SimpleConnectionProvider: ConnectionProvider {
var path: String
var readonly: Bool
var db: Connection?
init(path: String, readonly: Bool = false) {
self.path = path
self.readonly = readonly
}
var c: Connection!
func connection() throws -> Connection {
if c == nil {
c = try Connection(path, readonly: readonly)
guard let c = db else {
let c = try Connection(path, readonly: readonly)
self.db = c
return c
}
return c
}

View File

@ -131,7 +131,7 @@ extension CompactBlockDownloader: CompactBlockDownloading {
}
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try! lightwalletService.fetchUTXOs(for: tAddress, height: startHeight)
try lightwalletService.fetchUTXOs(for: tAddress, height: startHeight)
}
func fetchUnspentTransactionOutputs(tAddress: String, startHeight: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void) {

View File

@ -391,8 +391,7 @@ public class CompactBlockProcessor {
// clear cache
try downloader.rewind(to: height)
}
private func nextBatch() throws {
// get latest block height
@ -671,7 +670,6 @@ public class CompactBlockProcessor {
let storedUTXOs = storeUTXOs(utxos, in: dataDb)
NotificationCenter.default.post(name: .blockProcessorStoredUTXOs, object: self, userInfo: [CompactBlockProcessorNotificationKey.refreshedUTXOs : storedUTXOs])
} catch {

View File

@ -14,8 +14,6 @@ protocol AccountEntity {
var transparentAddress: String { get set }
}
struct Account: AccountEntity, Encodable, Decodable {
enum CodingKeys: String, CodingKey {

View File

@ -31,5 +31,5 @@ public extension ZcashSDK {
/**
minimum balance needed to do a shielding transaction
*/
public static let shieldingThreshold: Int64 = 10000
static let shieldingThreshold: Int64 = 10000
}

View File

@ -200,7 +200,6 @@ public class Initializer {
return accounts
}
/**
__TEMPORARILY UNAVAILABLE__
@ -218,17 +217,7 @@ public class Initializer {
- viewingKeys: Extended Full Viewing Keys to initialize the DBs with
*/
func initialize(viewingKeys: [String], walletBirthday: BlockHeight) throws {
let derivationTool = DerivationTool()
for vk in viewingKeys {
do {
guard try derivationTool.isValidExtendedViewingKey(vk) else {
throw InitializerError.invalidViewingKey(key: vk)
}
} catch {
throw InitializerError.invalidViewingKey(key: vk)
}
}
public func initialize(unifiedViewingKeys: [UnifiedViewingKey], walletBirthday: BlockHeight) throws {
do {
try rustBackend.initDataDb(dbData: dataDbURL)
@ -253,7 +242,7 @@ public class Initializer {
lowerBoundHeight = max(birthday.height, lastDownloaded)
do {
guard try rustBackend.initAccountsTable(dbData: dataDbURL, exfvks: viewingKeys) else {
guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: unifiedViewingKeys) else {
throw rustBackend.lastError() ?? InitializerError.accountInitFailed
}
} catch RustWeldingError.dataDbNotEmpty {

View File

@ -103,28 +103,33 @@ class ZcashRustBackend: ZcashRustBackendWelding {
zcashlc_vec_string_free(extsksCStr, UInt(accounts), capacity)
return extsks
}
static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool {
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool {
let dbData = dbData.osStr()
let viewingKeys = exfvks.map { UnsafePointer(strdup($0)) }
guard exfvks.count > 0 else {
throw RustWeldingError.malformedStringInput
}
let res = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, viewingKeys, UInt(viewingKeys.count));
viewingKeys.compactMap({ UnsafeMutablePointer(mutating: $0) }).forEach({ free($0) })
guard res else {
if let error = lastError() {
throw error
}
return false
}
return res
false
}
// static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool {
// let dbData = dbData.osStr()
// let viewingKeys = exfvks.map { UnsafePointer(strdup($0)) }
//
// guard exfvks.count > 0 else {
// throw RustWeldingError.malformedStringInput
// }
//
// let res = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, viewingKeys, UInt(viewingKeys.count));
//
// viewingKeys.compactMap({ UnsafeMutablePointer(mutating: $0) }).forEach({ free($0) })
//
// guard res else {
// if let error = lastError() {
// throw error
// }
// return false
// }
// return res
//
// }
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) throws {
let dbData = dbData.osStr()
@ -344,6 +349,40 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return extsks
}
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] {
guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts)) else {
if let error = lastError() {
throw error
}
throw RustWeldingError.unableToDeriveKeys
}
let uvks_size = uvks_struct.pointee.len
guard let uvks_array_pointer = uvks_struct.pointee.ptr, uvks_size > 0 else {
throw RustWeldingError.unableToDeriveKeys
}
var uvks = [UnifiedViewingKey]()
for i: Int in 0 ..< Int(uvks_size) {
let itemPointer = uvks_array_pointer.advanced(by: i)
guard let extfvk = String(validatingUTF8: itemPointer.pointee.extfvk) else {
throw RustWeldingError.unableToDeriveKeys
}
guard let extpub = String(validatingUTF8: itemPointer.pointee.extpub) else {
throw RustWeldingError.unableToDeriveKeys
}
uvks.append((extfvk,extpub))
}
zcashlc_free_uvk_array(uvks_struct)
return uvks
}
static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String? {
guard let zaddrCStr = zcashlc_derive_shielded_address_from_seed(seed, UInt(seed.count), accountIndex) else {
if let error = lastError() {
@ -402,6 +441,20 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return sk
}
static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String {
guard !pubkey.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard let tAddrCStr = zcashlc_derive_transparent_address_from_public_key([CChar](pubkey.utf8CString)), let tAddr = String(validatingUTF8: tAddrCStr) else {
if let error = lastError() {
throw error
}
throw RustWeldingError.unableToDeriveKeys
}
return tAddr
}
static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? {
guard !tsk.containsCStringNullBytesBeforeStringEnding() else {

View File

@ -15,6 +15,7 @@ public enum RustWeldingError: Error {
case saplingSpendParametersNotFound
case malformedStringInput
case noConsensusBranchId(height: Int32)
case unableToDeriveKeys
}
public struct ZcashRustBackendWeldingConstants {
@ -64,13 +65,20 @@ public protocol ZcashRustBackendWelding {
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]?
/**
initialize the accounts table from a given seed and a number of accounts
initialize the accounts table from a set of unified viewing keys
- Parameters:
- dbData: location of the data db
- exfvks: byte array of the zip32 seed
- Returns: a boolean indicating if the database was initialized or an error
*/
static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool
- uvks: an array of UnifiedViewingKeys
*/
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool
// /**
// initialize the accounts table from a given seed and a number of accounts
// - Parameters:
// - dbData: location of the data db
// - exfvks: byte array of the zip32 seed
// - Returns: a boolean indicating if the database was initialized or an error
// */
// static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool
/**
initialize the blocks table from a given checkpoint (birthday)
@ -302,6 +310,13 @@ public protocol ZcashRustBackendWelding {
static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String?
/**
Derives a tranparent address from a public key
- Parameter pubkey: public key represented as a string
*/
static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey]
/**
Gets the consensus branch id for the given height
- Parameter height: the height you what to know the branch id for

View File

@ -337,11 +337,18 @@ extension LightWalletGRPCService: LightWalletService {
}
})
var resultingCall = calls[0]
let resultingCall = calls[0]
do {
try calls.dropFirst().reduce(into: resultingCall) { r, c in
r.status.and(c.status) }.status.wait()
let response = try calls.dropFirst().reduce(into: resultingCall) { r, c in
_ = r.status.and(c.status)
}.status.wait()
switch response.code {
case .ok:
result(.success(utxos))
default:
result(.failure(.mapCode(response)))
}
} catch {
result(.failure(error.mapToServiceError()))

View File

@ -45,7 +45,6 @@ extension ShieldFundsError: LocalizedError {
}
}
public protocol WalletBalance {
var verified: Int64 { get set }
var total: Int64 { get set }
@ -58,7 +57,6 @@ implementations like SdkSynchronizer fulfill.
public protocol Synchronizer {
/**
Value representing the Status of this Synchronizer. As the status changes, a new
value will be emitted by KVO
@ -79,7 +77,7 @@ public protocol Synchronizer {
- Throws: Initializer Errors and RustWeldingError if fails
- Note: The subsequent initializations don't have any effect or failure
*/
func initialize(viewingKeys: [String], walletBirthday: BlockHeight) throws
func initialize(unifiedViewingKeys: [UnifiedViewingKey], walletBirthday: BlockHeight) throws
/**
Starts this synchronizer within the given scope.
@ -198,7 +196,6 @@ public protocol Synchronizer {
*/
func getShieldedVerifiedBalance(accountIndex: Int) -> Int64
/**
Stops the synchronizer and rescans the known blocks with the current keys.
- Parameter policy: the rewind policy
@ -213,7 +210,6 @@ public protocol Synchronizer {
The Status of the synchronizer
*/
public enum Status {
/**
Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
*/
@ -248,7 +244,6 @@ public enum TransactionKind {
case all
}
/**
Type of rewind available
birthday: rewinds the local state to this wallet's birthday

View File

@ -17,6 +17,8 @@ public protocol KeyValidation {
}
public typealias UnifiedViewingKey = (extfxk: String, extpub: String)
public protocol KeyDeriving {
/**
Given a seed and a number of accounts, return the associated viewing keys.
@ -69,18 +71,12 @@ public protocol KeyDeriving {
func deriveShieldedAddress(viewingKey: String) throws -> String
/**
Validates the given viewing key
- Throws DerivationError when it's invalid
Derives a transparent address from seedbytes, specifying account and index
*/
func validateViewingKey(viewingKey: String) throws
// WIP probably shouldn't be used just yet. Why?
// - because we need the private key associated with this seed and this function doesn't return it.
// - the underlying implementation needs to be split out into a few lower-level calls
func deriveTransparentAddress(seed: [UInt8], account: Int, index: Int) throws -> String
/**
Derives a SecretKey to spend transparent funds from the given seed
Derives a SecretKey to spend transparent funds from a transparent secret key wif encoded
*/
func deriveTransparentPrivateKey(seed: [UInt8], account: Int, index: Int) throws -> String
@ -89,6 +85,13 @@ public protocol KeyDeriving {
*/
func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String
func deriveTransparentAddressFromPublicKey(_ pubkey: String) throws -> String
/**
derives unified viewing keys from seedbytes, specifying a number of accounts
- Returns an array of unified viewing key tuples.
*/
func deriveUnifiedViewingKeysFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey]
}
public enum KeyDerivationErrors: Error {
@ -98,7 +101,7 @@ public enum KeyDerivationErrors: Error {
}
public class DerivationTool: KeyDeriving {
var rustwelding: ZcashRustBackendWelding.Type = ZcashRustBackend.self
public static let `default` = DerivationTool()
@ -223,9 +226,27 @@ public class DerivationTool: KeyDeriving {
}
}
public func validateViewingKey(viewingKey: String) throws {
// TODO
// throw KeyDerivationErrors.unableToDerive
public func deriveUnifiedViewingKeysFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] {
guard numberOfAccounts > 0 else {
throw KeyDerivationErrors.invalidInput
}
do {
return try rustwelding.deriveUnifiedViewingKeyFromSeed(seed, numberOfAccounts: numberOfAccounts)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
}
public func deriveTransparentAddressFromPublicKey(_ pubkey: String) throws -> String {
guard !pubkey.isEmpty else {
throw KeyDerivationErrors.invalidInput
}
do {
return try rustwelding.derivedTransparentAddressFromPublicKey(pubkey)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
}
/**
@ -244,6 +265,7 @@ public class DerivationTool: KeyDeriving {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
}
}
extension DerivationTool: KeyValidation {
@ -272,7 +294,6 @@ extension DerivationTool: KeyValidation {
}
}
/**
Derives the transparent address from a WIF Private Key
- Throws:

View File

@ -78,11 +78,6 @@ class WalletTransactionEncoder: TransactionEncoder {
guard ensureParams(spend: self.spendParamsURL, output: self.spendParamsURL) else {
throw TransactionEncoderError.missingParams
}
let scannedHeight = try repository.lastScannedHeight()
guard let latestHeight = Int32(exactly: scannedHeight) else {
throw RustWeldingError.genericError(message: "could not convert \(scannedHeight)")
}
let txId = rustBackend.createToAddress(dbData: self.dataDbURL,
account: Int32(accountIndex),

View File

@ -98,10 +98,6 @@ public class SDKSynchronizer: Synchronizer {
*/
public convenience init(initializer: Initializer) throws {
var config = CompactBlockProcessor.Configuration(cacheDb: initializer.cacheDbURL,
dataDb: initializer.dataDbURL,
walletBirthday: initializer.walletBirthday.height)
try self.init(status: .disconnected,
initializer: initializer,
transactionManager: try OutboundTransactionManagerBuilder.build(initializer: initializer),
@ -132,8 +128,8 @@ public class SDKSynchronizer: Synchronizer {
self.blockProcessor.stop()
}
public func initialize(viewingKeys: [String], walletBirthday: BlockHeight) throws {
try self.initializer.initialize(viewingKeys: viewingKeys, walletBirthday: walletBirthday)
public func initialize(unifiedViewingKeys: [UnifiedViewingKey], walletBirthday: BlockHeight) throws {
try self.initializer.initialize(unifiedViewingKeys: unifiedViewingKeys, walletBirthday: walletBirthday)
try self.blockProcessor.setStartHeight(WalletBirthday.birthday(with: walletBirthday).height)
}
@ -142,8 +138,7 @@ public class SDKSynchronizer: Synchronizer {
- Throws: CompactBlockProcessorError when failures occur
*/
public func start(retry: Bool = false) throws {
guard status == .stopped || status == .disconnected || status == .synced else {
assert(true,"warning: synchronizer started when already started") // TODO: remove this assertion sometime in the near future
return

View File

@ -3,6 +3,16 @@
#include <stdint.h>
#include <stdlib.h>
typedef struct {
char *extfvk;
char *extpub;
} FFIUnifiedViewingKey;
typedef struct {
FFIUnifiedViewingKey *ptr;
uintptr_t len;
} FFIUVKBoxedSlice;
int32_t zcashlc_branch_id_for_height(int32_t height);
/**
@ -81,6 +91,12 @@ char *zcashlc_derive_shielded_address_from_seed(const uint8_t *seed,
*/
char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk);
/**
* derives a shielded address from the given viewing key.
* call zcashlc_string_free with the returned pointer when done using it
*/
char *zcashlc_derive_transparent_address_from_public_key(const char *pubkey);
/**
* Derives a transparent address from the given secret key enconded as a WIF string
*/
@ -105,11 +121,17 @@ char *zcashlc_derive_transparent_private_key_from_seed(const uint8_t *seed,
int32_t account,
int32_t index);
FFIUVKBoxedSlice *zcashlc_derive_unified_viewing_keys_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t accounts);
/**
* Copies the last error message into the provided allocated buffer.
*/
int32_t zcashlc_error_message_utf8(char *buf, int32_t length);
void zcashlc_free_uvk_array(FFIUVKBoxedSlice *uvks);
/**
* Returns the address for the account.
*
@ -190,7 +212,9 @@ char **zcashlc_init_accounts_table(const uint8_t *db_data,
bool zcashlc_init_accounts_table_with_keys(const uint8_t *db_data,
uintptr_t db_data_len,
const char *const *extfvks,
uintptr_t extfvks_len);
uintptr_t extfvks_len,
const char *const *extpubs,
uintptr_t extpubs_len);
/**
* Initialises the data database with the given block.

View File

@ -21,11 +21,12 @@ class NetworkUpgradeTests: XCTestCase {
override func setUpWithError() throws {
coordinator = try TestCoordinator(
spendingKey: spendingKey,
walletBirthday: birthday,
channelProvider: ChannelProvider()
)
// coordinator = try TestCoordinator(
// spendingKey: spendingKey,
// unifiedViewingKey: <#UnifiedViewingKey#>,
// walletBirthday: birthday,
// channelProvider: ChannelProvider()
// )
try coordinator.reset(saplingActivation: birthday)
}

View File

@ -47,14 +47,22 @@ class TestCoordinator {
convenience init(seed: String,
walletBirthday: BlockHeight,
channelProvider: ChannelProvider) throws {
guard let spendingKey = try DerivationTool.default.deriveSpendingKeys(seed: TestSeed().seed(),// todo: fix this
numberOfAccounts: 1).first else {
guard let spendingKey = try DerivationTool.default.deriveSpendingKeys(
seed: TestSeed().seed(),
numberOfAccounts: 1).first else {
throw CoordinatorError.builderError
}
try self.init(spendingKey: spendingKey, walletBirthday: walletBirthday, channelProvider: channelProvider)
guard let uvk = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed(TestSeed().seed(), numberOfAccounts: 1).first else {
throw CoordinatorError.builderError
}
try self.init(spendingKey: spendingKey, unifiedViewingKey: uvk, walletBirthday: walletBirthday, channelProvider: channelProvider)
}
required init(spendingKey: String,
required init(
spendingKey: String,
unifiedViewingKey: UnifiedViewingKey,
walletBirthday: BlockHeight,
channelProvider: ChannelProvider) throws {
self.spendingKey = spendingKey
@ -80,7 +88,8 @@ class TestCoordinator {
downloader: downloader,
spendParamsURL: try __spendParamsURL(),
outputParamsURL: try __outputParamsURL(),
spendingKey: spendingKey,
spendingKey: spendingKey,
unifiedViewingKey: unifiedViewingKey,
walletBirthday: WalletBirthday.birthday(with: birthday),
loggerProxy: SampleLogger(logLevel: .debug))
@ -234,6 +243,7 @@ class TestSynchronizerBuilder {
spendParamsURL: URL,
outputParamsURL: URL,
spendingKey: String,
unifiedViewingKey: UnifiedViewingKey,
walletBirthday: WalletBirthday,
loggerProxy: Logger? = nil
) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) {
@ -249,9 +259,10 @@ class TestSynchronizerBuilder {
downloader: downloader,
spendParamsURL: spendParamsURL,
outputParamsURL: outputParamsURL,
walletBirthday: walletBirthday.height,
loggerProxy: loggerProxy
)
try initializer.initialize(viewingKeys: [try DerivationTool().deriveViewingKey(spendingKey: spendingKey)], walletBirthday: walletBirthday.height)
try initializer.initialize(unifiedViewingKeys: [unifiedViewingKey], walletBirthday: walletBirthday.height)
return ([spendingKey], try SDKSynchronizer(initializer: initializer)
)
@ -275,6 +286,10 @@ class TestSynchronizerBuilder {
guard let spendingKey = try DerivationTool().deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
throw TestCoordinator.CoordinatorError.builderError
}
guard let uvk = try DerivationTool().deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: 1).first else {
throw TestCoordinator.CoordinatorError.builderError
}
return try build(rustBackend: rustBackend,
lowerBoundHeight: lowerBoundHeight,
cacheDbURL: cacheDbURL,
@ -287,6 +302,7 @@ class TestSynchronizerBuilder {
spendParamsURL: spendParamsURL,
outputParamsURL: outputParamsURL,
spendingKey: spendingKey,
unifiedViewingKey: uvk,
walletBirthday: walletBirthday)
}

View File

@ -29,23 +29,23 @@ class WalletTests: XCTestCase {
}
}
func testWalletInitialization() {
let wallet = Initializer(cacheDbURL: cacheData,
dataDbURL: dbData,
pendingDbURL: try! TestDbBuilder.pendingTransactionsDbURL(),
endpoint: LightWalletEndpointBuilder.default,
spendParamsURL: try! __spendParamsURL(),
outputParamsURL: try! __outputParamsURL()
)
XCTAssertNoThrow(try wallet.initialize(viewingKeys: ["zxviewtestsapling1qwxyzvdmqqqqpqy3knx32fpja779wzg76kmglgguvr74g773f3aw3gy37rar6y9d37knvskz6thnea55s05cz3a7q38835hq4w58yevn763cn2wf7k2mpj247ynxpt9qm0nn39slkz5dk572hxr43pxqtg5kz3pqcj8z8uhz0l2vx8gxe90uf4pgw7ks23f0hz2hm47k9ym42cmns3tenhxzlyur2nvx68h4fmk9nrs44ymcqz434zsuxpvhklrjzn00gc43fdghn5szc5x2w"], walletBirthday: 663194))
// fileExists actually sucks, so attempting to delete the file and checking what happens is far better :)
XCTAssertNoThrow( try FileManager.default.removeItem(at: dbData!) )
// TODO: Initialize cacheDB on start, will be done when Synchronizer is ready and integrated
// XCTAssertNoThrow( try FileManager.default.removeItem(at: cacheData!) )
}
// func testWalletInitialization() {
//
// let wallet = Initializer(cacheDbURL: cacheData,
// dataDbURL: dbData,
// pendingDbURL: try! TestDbBuilder.pendingTransactionsDbURL(),
// endpoint: LightWalletEndpointBuilder.default,
// spendParamsURL: try! __spendParamsURL(),
// outputParamsURL: try! __outputParamsURL()
// )
//
// XCTAssertNoThrow(try wallet.initialize(viewingKeys: ["zxviewtestsapling1qwxyzvdmqqqqpqy3knx32fpja779wzg76kmglgguvr74g773f3aw3gy37rar6y9d37knvskz6thnea55s05cz3a7q38835hq4w58yevn763cn2wf7k2mpj247ynxpt9qm0nn39slkz5dk572hxr43pxqtg5kz3pqcj8z8uhz0l2vx8gxe90uf4pgw7ks23f0hz2hm47k9ym42cmns3tenhxzlyur2nvx68h4fmk9nrs44ymcqz434zsuxpvhklrjzn00gc43fdghn5szc5x2w"], walletBirthday: 663194))
//
// // fileExists actually sucks, so attempting to delete the file and checking what happens is far better :)
// XCTAssertNoThrow( try FileManager.default.removeItem(at: dbData!) )
// // TODO: Initialize cacheDB on start, will be done when Synchronizer is ready and integrated
//// XCTAssertNoThrow( try FileManager.default.removeItem(at: cacheData!) )
// }
}
struct WalletBirthdayProvider {

View File

@ -82,12 +82,12 @@ class WalletTransactionEncoderTests: XCTestCase {
func testSpendGlobalQueue() throws {
var txId: Int64 = -1
let expectation = XCTestExpectation(description: self.description)
let branchId = try rustBackend.consensusBranchIdFor(height: Int32(exactly: try repository.lastScannedHeight())!)
DispatchQueue.global().async {
txId = self.rustBackend.createToAddress(dbData: self.dataDbHandle.readWriteDb,
account: 0,
extsk: self.spendingKey, consensusBranchId: branchId,
extsk: self.spendingKey,
to: self.recipientAddress,
value: Int64(self.zpend),
memo: nil,

View File

@ -37,18 +37,6 @@ class ZcashRustBackendTests: XCTestCase {
}
func testInitWithViewingKeys() throws {
let viewingKey = "zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy"
XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!))
let _ = try ZcashRustBackend.initAccountsTable(dbData: dbData!, exfvks: [viewingKey])
XCTAssertNil(ZcashRustBackend.getLastError())
XCTAssertEqual(ZcashRustBackend.getAddress(dbData: dbData!, account: 0),"zs1vp7kvlqr4n9gpehztr76lcn6skkss9p8keqs3nv8avkdtjrcctrvmk9a7u494kluv756jeee5k0")
}
func testDeriveExtendedSpendingKeys() {
let seed = Array("testreferencealicetestreferencealice".utf8)
@ -112,13 +100,6 @@ class ZcashRustBackendTests: XCTestCase {
}
func testSendToAddress() {
let tx = try! ZcashRustBackend.createToAddress(dbData: dataDbHandle.readWriteDb, account: 0, extsk: spendingKey, consensusBranchId: ZcashRustBackend.consensusBranchIdFor(height: 663150), to: recipientAddress, value: Int64(zpend), memo: nil, spendParamsPath: __spendParamsURL().path, outputParamsPath: __outputParamsURL().path)
XCTAssert(tx > 0)
XCTAssertNil(ZcashRustBackend.lastError())
}
func testIsValidTransparentAddressFalse() {
var isValid: Bool? = nil

View File

@ -38,6 +38,22 @@ enum DarksideDataset: String {
}
class DarksideWalletService: LightWalletService {
func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(for tAddress: String, height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
}
func fetchUTXOs(for tAddress: String, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
}

View File

@ -18,6 +18,22 @@ struct LightWalletServiceMockResponse: LightWalletServiceResponse {
}
class MockLightWalletService: LightWalletService {
func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(for tAddress: String, height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
}
func fetchUTXOs(for tAddress: String, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
}

View File

@ -77,6 +77,54 @@ extension LightWalletServiceMockResponse {
}
class MockRustBackend: ZcashRustBackendWelding {
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool {
false
}
static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 {
-1
}
static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 {
-1
}
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool {
false
}
static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance {
throw RustWeldingError.genericError(message: "unimplemented")
}
static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
-1
}
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
-1
}
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
throw KeyDerivationErrors.unableToDerive
}
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
throw KeyDerivationErrors.unableToDerive
}
static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? {
throw KeyDerivationErrors.unableToDerive
}
static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String {
throw KeyDerivationErrors.unableToDerive
}
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] {
throw KeyDerivationErrors.unableToDerive
}
static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool {
false
}
@ -236,7 +284,8 @@ class MockRustBackend: ZcashRustBackendWelding {
}
static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
mockCreateToAddress ?? rustBackend.createToAddress(dbData: dbData, account: account, extsk: extsk, consensusBranchId: consensusBranchId, to: to, value: value, memo: memo, spendParamsPath: spendParamsPath, outputParamsPath: outputParamsPath)
// mockCreateToAddress ?? rustBackend.createToAddress(dbData: dbData, account: account, extsk: extsk, consensusBranchId: consensusBranchId, to: to, value: value, memo: memo, spendParamsPath: spendParamsPath, outputParamsPath: outputParamsPath)
-1
}
static func shouldSucceed(successRate: Float) -> Bool {

View File

@ -24,6 +24,8 @@ use zcash_client_backend::{
},
keys::{
derive_secret_key_from_seed,
derive_public_key_from_seed,
derive_transparent_address_from_public_key,
derive_transparent_address_from_secret_key,
spending_key, Wif,
},
@ -56,7 +58,7 @@ use zcash_proofs::prover::LocalTxProver;
use std::convert::{TryFrom, TryInto};
use base58::ToBase58;
use sha2::{Digest, Sha256};
use secp256k1::key::SecretKey;
use secp256k1::key::{SecretKey, PublicKey};
fn unwrap_exc_or<T>(exc: Result<T, ()>, def: T) -> T {
match exc {
@ -172,11 +174,17 @@ pub extern "C" fn zcashlc_init_accounts_table(
};
let extsks: Vec<_> = (0..accounts)
.map(|account| spending_key(&seed, NETWORK.coin_type(), account))
.map(|account| spending_key(&seed, NETWORK.coin_type(), AccountId(account)))
.collect();
let extfvks: Vec<_> = extsks.iter().map(ExtendedFullViewingKey::from).collect();
let t_addreses: Vec<_> = (0..accounts)
.map(|account| {
let tsk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), 0).unwrap();
derive_transparent_address_from_secret_key(&tsk)
}).collect();
init_accounts_table(&db_data, &extfvks)
init_accounts_table(&db_data, &extfvks, &t_addreses)
.map(|_| {
// Return the ExtendedSpendingKeys for the created accounts.
let mut v: Vec<_> = extsks
@ -206,28 +214,36 @@ pub extern "C" fn zcashlc_init_accounts_table(
pub extern "C" fn zcashlc_init_accounts_table_with_keys(
db_data: *const u8,
db_data_len: usize,
extfvks: *const *const c_char,
extfvks_len: usize,
uvks: *mut FFIUVKBoxedSlice,
) -> bool {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let extfvks = unsafe {
std::slice::from_raw_parts(extfvks, extfvks_len)
.into_iter()
.map(|s| CStr::from_ptr(*s).to_str().unwrap())
.map(|vkstr| {
decode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
&vkstr,
)
.unwrap()
.unwrap()
})
.collect::<Vec<_>>()
};
let s: Box<FFIUVKBoxedSlice> = unsafe { Box::from_raw(uvks) };
match init_accounts_table(&db_data, &extfvks) {
let slice: &mut [FFIUnifiedViewingKey] = unsafe { slice::from_raw_parts_mut(s.ptr, s.len) };
let mut extfvks: Vec<ExtendedFullViewingKey> = Vec::new();
let mut t_addreses: Vec<TransparentAddress> = Vec::new();
for u in slice.into_iter() {
let vkstr = unsafe { CStr::from_ptr(u.extfvk).to_str().unwrap() };
let extfvk = decode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
&vkstr,
)
.unwrap()
.unwrap();
extfvks.push(extfvk);
let extpub_str = unsafe { CStr::from_ptr(u.extpub).to_str().unwrap() };
let pubkey = PublicKey::from_str(&extpub_str).unwrap();
let t_addr = derive_transparent_address_from_public_key(&pubkey);
t_addreses.push(t_addr);
}
match init_accounts_table(&db_data, &extfvks, &t_addreses) {
Ok(()) => Ok(true),
Err(e) => Err(format_err!("Error while initializing accounts: {}", e)),
}
@ -256,7 +272,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys(
};
let extsks: Vec<_> = (0..accounts)
.map(|account| spending_key(&seed, NETWORK.coin_type(), account))
.map(|account| spending_key(&seed, NETWORK.coin_type(), AccountId(account)))
.collect();
// Return the ExtendedSpendingKeys for the created accounts.
@ -278,6 +294,93 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys(
});
unwrap_exc_or_null(res)
}
#[repr(C)]
pub struct FFIUnifiedViewingKey {
extfvk: *mut c_char,
extpub: *mut c_char,
}
#[repr(C)]
pub struct FFIUVKBoxedSlice {
ptr: *mut FFIUnifiedViewingKey,
len: usize, // number of elems
}
fn unified_viewing_key_new(
extfvk: &ExtendedFullViewingKey,
extpub: &PublicKey) -> FFIUnifiedViewingKey {
let encoded_extfvk = encode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
extfvk,
);
let encoded_pubkey = hex::encode(&extpub.serialize());
FFIUnifiedViewingKey {
extfvk: CString::new(encoded_extfvk).unwrap().into_raw(),
extpub: CString::new(encoded_pubkey).unwrap().into_raw()
}
}
fn uvk_vec_to_ffi (v: Vec<FFIUnifiedViewingKey>)
-> *mut FFIUVKBoxedSlice
{
// Going from Vec<_> to Box<[_]> just drops the (extra) `capacity`
let boxed_slice: Box<[FFIUnifiedViewingKey]> = v.into_boxed_slice();
let len = boxed_slice.len();
let fat_ptr: *mut [FFIUnifiedViewingKey] =
Box::into_raw(boxed_slice)
;
let slim_ptr: *mut FFIUnifiedViewingKey = fat_ptr as _;
Box::into_raw(
Box::new(FFIUVKBoxedSlice { ptr: slim_ptr, len })
)
}
#[no_mangle]
pub unsafe extern "C" fn zcashlc_free_uvk_array(uvks: *mut FFIUVKBoxedSlice)
{
if uvks.is_null() {
return;
}
let s: Box<FFIUVKBoxedSlice> = Box::from_raw(uvks);
let slice: &mut [FFIUnifiedViewingKey] = slice::from_raw_parts_mut(s.ptr, s.len);
drop(Box::from_raw(slice));
drop(s);
}
#[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_unified_viewing_keys_from_seed(
seed: *const u8,
seed_len: usize,
accounts: i32,
) -> *mut FFIUVKBoxedSlice {
let res = catch_panic(|| {
let seed = slice::from_raw_parts(seed, seed_len);
let accounts = if accounts > 0 {
accounts as u32
} else {
return Err(format_err!("accounts argument must be greater than zero"));
};
let uvks: Vec<_> = (0..accounts)
.map(|account| {
let extfvk = ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), AccountId(account)));
let extpub = derive_public_key_from_seed(&NETWORK, &seed, AccountId(account), 0).unwrap();
unified_viewing_key_new(&extfvk, &extpub)
})
.collect();
Ok(uvk_vec_to_ffi(uvks))
});
unwrap_exc_or_null(res)
}
/// Derives Extended Full Viewing Keys from the given seed into 'accounts' number of accounts.
/// Returns the Extended Full Viewing Keys for the accounts. The caller should store these
/// securely
@ -300,7 +403,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys(
let extsks: Vec<_> = (0..accounts)
.map(|account| {
ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), account))
ExtendedFullViewingKey::from(&spending_key(&seed, NETWORK.coin_type(), AccountId(account)))
})
.collect();
@ -338,7 +441,7 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
} else {
return Err(format_err!("accounts argument must be greater than zero"));
};
let address = spending_key(&seed, NETWORK.coin_type(), account_index)
let address = spending_key(&seed, NETWORK.coin_type(), AccountId(account_index))
.default_address()
.unwrap()
.1;
@ -348,10 +451,23 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
unwrap_exc_or_null(res)
}
// fn derive_shielded_address_from_spending_k<P: Parameters>(params: &P, extsk: &ExtendedSpendingKey) -> String {
// let address = extsk.default_address().unwrap().1;
// encode_payment_address(params.hrp_sapling_payment_address(), &address)
// }
/// derives a shielded address from the given viewing key.
/// call zcashlc_string_free with the returned pointer when done using it
#[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_public_key(
pubkey: *const c_char,
) -> *mut c_char {
let res = catch_panic(|| {
let public_key_str = CStr::from_ptr(pubkey).to_str()?;
let pk = PublicKey::from_str(&public_key_str)?;
let taddr =
derive_transparent_address_from_public_key(&pk)
.encode(&NETWORK);
Ok(CString::new(taddr).unwrap().into_raw())
});
unwrap_exc_or_null(res)
}
/// derives a shielded address from the given viewing key.
/// call zcashlc_string_free with the returned pointer when done using it
@ -1082,7 +1198,7 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
return Err(format_err!("index argument must be positive"));
};
let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index);
let taddr = derive_transparent_address_from_secret_key(sk.unwrap())
let taddr = derive_transparent_address_from_secret_key(&sk.unwrap())
.encode(&NETWORK);
Ok(CString::new(taddr).unwrap().into_raw())
@ -1103,7 +1219,7 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key(
// derive the corresponding t-address
let taddr =
derive_transparent_address_from_secret_key(sk)
derive_transparent_address_from_secret_key(&sk)
.encode(&NETWORK);
Ok(CString::new(taddr).unwrap().into_raw())
});