Merge pull request #291 from zcash/network-agnostic-build

Network agnostic build
This commit is contained in:
Francisco Gindre 2021-07-30 10:40:55 -03:00 committed by GitHub
commit 7f41511855
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
78 changed files with 2315 additions and 1105 deletions

View File

@ -1,6 +1,6 @@
language: swift
os: osx
osx_image: xcode12.2
osx_image: xcode12.5
xcode_workspace: ./Example/ZcashLightClientSample/ZcashLightClientSample.xcworkspace
xcode_scheme: ZcashLightClientSample
xcode_destination: platform=iOS Simulator,OS=14.2,name=iPhone 8
@ -9,9 +9,6 @@ addons:
packages:
- rustup-init
- sourcery
env:
global:
- ZCASH_NETWORK_ENVIRONMENT: TESTNET
install:
- ${TRAVIS_BUILD_DIR}/Scripts/travis/rust_setup.sh
- ${TRAVIS_BUILD_DIR}/Scripts/travis/ZcashLightClientSample_setup.sh
@ -19,4 +16,4 @@ install:
- curl https://z.cash/downloads/sapling-output.params > ${TRAVIS_BUILD_DIR}/ZcashLightClientKitTests/sapling-spend.params
script:
- swiftlint
- travis_wait 60 xcodebuild -quiet -UseModernBuildSystem=NO -workspace ./Example/ZcashLightClientSample/ZcashLightClientSample.xcworkspace -scheme ZcashLightClientSample -destination platform\=iOS\ Simulator,OS\=14.2,name\=iPhone\ 8 build
- travis_wait 60 xcodebuild -quiet -UseModernBuildSystem=NO -workspace ./Example/ZcashLightClientSample/ZcashLightClientSample.xcworkspace -scheme ZcashLightClientSample -destination platform\=iOS\ Simulator,OS\=14.5,name\=iPhone\ 8 build

2
Cargo.lock generated
View File

@ -703,7 +703,7 @@ dependencies = [
[[package]]
name = "libzcashlc"
version = "0.0.6"
version = "0.0.7"
dependencies = [
"base58",
"bitvec 0.18.5",

View File

@ -1,6 +1,6 @@
[package]
name = "libzcashlc"
version = "0.0.6"
version = "0.0.7"
authors = ["Jack Grigg <jack@z.cash>",
"Francisco Gindre <francisco@z.cash>",
]
@ -50,5 +50,5 @@ zcash_primitives = {git = "https://github.com/nuttycom/librustzcash", branch = "
zcash_proofs = {git = "https://github.com/nuttycom/librustzcash", branch = "autoshield-poc-daa" }
[features]
mainnet = ["zcash_client_sqlite/mainnet", "zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
testnet = ["zcash_client_backend/transparent-inputs", "zcash_primitives/transparent-inputs"]
mainnet = ["zcash_client_sqlite/mainnet"]
testnet = []

View File

@ -0,0 +1,99 @@
//
// DerivatioToolTestnetTests.swift
// ZcashLightClientKit-Unit-DerivationToolTests
//
// Created by Francisco Gindre on 7/26/21.
//
// swift-format-ignore-file
import XCTest
@testable import ZcashLightClientKit
class DerivatioToolTestnetTests: XCTestCase {
var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment?
var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")!
let testRecipientAddress = "ztestsapling1475xtm56czrzmleqzzlu4cxvjjfsy2p6rv78q07232cpsx5ee52k0mn5jyndq09mampkgvrxnwg" //TODO: Parameterize this from environment
let expectedSpendingKey = "secret-extended-key-test1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6lk8xce3d4jw7s8ln5yjp6fqv2g0nzue2hc0kv5t004vklvlenncscq9flwh5vf5qnv0hnync72n7gjn70u47765v3kyrxytx50g730svvmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqe49swv"
let expectedViewingKey = "zxviewtestsapling1qdxykmuaqqqqpqqg3x5c02p4rhw0rtszr8ln4xl7g6wg6qzsqgn445qsu3cq4vd6l5smlqrckkl2x5rnrauzc4gp665q3zyw0qf2sfdsx5wpp832htfavqk72uchuuvq2dpmgk8jfaza5t5l56u66fpx0sr8ewp9s3wj2txavmhhlazn5rj8mshh470fkrmzg4xarhrqlygg8f486307ujhndwhsw2h7ddzf89k3534aeu0ypz2tjgrzlcqtat380vhe8awm03f58cqgegsaj"
let derivationTool = DerivationTool(networkType: NetworkType.testnet)
let expectedTransparentAddress = "tmXuTnE11JojToagTqxXUn6KvdxDE3iLKbp"
func testDeriveViewingKeysFromSeed() throws {
let accounts: Int = 1
let seedBytes = [UInt8](seedData)
let viewingKeys = try derivationTool.deriveViewingKeys(seed: seedBytes, numberOfAccounts: accounts)
XCTAssertEqual(viewingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive")
guard let viewingKey = viewingKeys.first else {
XCTFail("no viewing key generated")
return
}
XCTAssertEqual(expectedViewingKey, viewingKey)
}
func testDeriveViewingKeyFromSpendingKeys() throws {
XCTAssertEqual(expectedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey))
}
func testDeriveSpendingKeysFromSeed() throws {
let accounts: Int = 1
let seedBytes = [UInt8](seedData)
let spendingKeys = try derivationTool.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: accounts)
XCTAssertEqual(spendingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive")
guard let spendingKey = spendingKeys.first else {
XCTFail("no viewing key generated")
return
}
XCTAssertEqual(expectedSpendingKey, spendingKey)
}
func testDeriveShieldedAddressFromSeed() throws {
let seedBytes = [UInt8](seedData)
let shieldedAddress = try derivationTool.deriveShieldedAddress(seed: seedBytes, accountIndex: 0)
XCTAssertEqual(shieldedAddress, testRecipientAddress)
}
func testDeriveShieldedAddressFromViewingKey() throws {
XCTAssertEqual(try derivationTool.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress)
}
func testDeriveTransparentAddressFromSeed() throws {
XCTAssertEqual(try derivationTool.deriveTransparentAddress(seed: [UInt8](seedData)), expectedTransparentAddress)
}
func testIsValidViewingKey() throws {
XCTAssertTrue(try derivationTool.isValidExtendedViewingKey(self.expectedViewingKey))
XCTAssertFalse(try derivationTool.isValidExtendedViewingKey("zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy"))
}
func testDeriveSecretKeyFromSeed() throws {
XCTAssertEqual(try derivationTool.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "L2BCTxmSDiBRb33kGFd4pwGhp9r3FZqG3LZihgTkkg1J14vwtDbq")
}
func testDeriveUnifiedKeysFromSeed() throws {
let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1)
XCTAssertEqual(unifiedKeys.count, 1)
XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey)
XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
}
func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws {
let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10)
XCTAssertEqual(unifiedKeys.count, 10)
XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey)
XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
}
}

View File

@ -8,7 +8,7 @@
import XCTest
import ZcashLightClientKit
class DerivationToolTests: XCTestCase {
class DerivationToolMainnetTests: XCTestCase {
var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment?
var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")!
let testRecipientAddress = "zs1vp7kvlqr4n9gpehztr76lcn6skkss9p8keqs3nv8avkdtjrcctrvmk9a7u494kluv756jeee5k0" //TODO: Parameterize this from environment
@ -17,11 +17,12 @@ class DerivationToolTests: XCTestCase {
let expectedViewingKey = "zxviews1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkysswfhjk79n8l99f2grd26dqg6dy3jcmxsaypxfsu6ara6vsk3x8l544uaksstx9zre879mdg7s9a7zurrx6pf5qg2n323js2s3zlu8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszcq7kwxy"
let derivationTool = DerivationTool(networkType: NetworkType.mainnet)
let expectedTransparentAddress = "t1dRJRY7GmyeykJnMH38mdQoaZtFhn1QmGz"
func testDeriveViewingKeysFromSeed() throws {
let accounts: Int = 1
let seedBytes = [UInt8](seedData)
let viewingKeys = try DerivationTool.default.deriveViewingKeys(seed: seedBytes, numberOfAccounts: accounts)
let viewingKeys = try derivationTool.deriveViewingKeys(seed: seedBytes, numberOfAccounts: accounts)
XCTAssertEqual(viewingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive")
@ -34,14 +35,14 @@ class DerivationToolTests: XCTestCase {
}
func testDeriveViewingKeyFromSpendingKeys() throws {
XCTAssertEqual(expectedViewingKey, try DerivationTool.default.deriveViewingKey(spendingKey: expectedSpendingKey))
XCTAssertEqual(expectedViewingKey, try derivationTool.deriveViewingKey(spendingKey: expectedSpendingKey))
}
func testDeriveSpendingKeysFromSeed() throws {
let accounts: Int = 1
let seedBytes = [UInt8](seedData)
let spendingKeys = try DerivationTool.default.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: accounts)
let spendingKeys = try derivationTool.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: accounts)
XCTAssertEqual(spendingKeys.count, accounts, "the number of viewing keys have to match the number of account requested to derive")
guard let spendingKey = spendingKeys.first else {
@ -55,44 +56,44 @@ class DerivationToolTests: XCTestCase {
func testDeriveShieldedAddressFromSeed() throws {
let seedBytes = [UInt8](seedData)
let shieldedAddress = try DerivationTool.default.deriveShieldedAddress(seed: seedBytes, accountIndex: 0)
let shieldedAddress = try derivationTool.deriveShieldedAddress(seed: seedBytes, accountIndex: 0)
XCTAssertEqual(shieldedAddress, testRecipientAddress)
}
func testDeriveShieldedAddressFromViewingKey() throws {
XCTAssertEqual(try DerivationTool.default.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress)
XCTAssertEqual(try derivationTool.deriveShieldedAddress(viewingKey: expectedViewingKey), testRecipientAddress)
}
func testDeriveTransparentAddressFromSeed() throws {
XCTAssertEqual(try DerivationTool.default.deriveTransparentAddress(seed: [UInt8](seedData)), expectedTransparentAddress)
XCTAssertEqual(try derivationTool.deriveTransparentAddress(seed: [UInt8](seedData)), expectedTransparentAddress)
}
func testIsValidViewingKey() throws {
XCTAssertTrue(try DerivationTool.default.isValidExtendedViewingKey("zxviews1q0dm7hkzqqqqpqplzv3f50rl4vay8uy5zg9e92f62lqg6gzu63rljety32xy5tcyenzuu3n386ws772nm6tp4sads8n37gff6nxmyz8dn9keehmapk0spc6pzx5uxepgu52xnwzxxnuja5tv465t9asppnj3eqncu3s7g3gzg5x8ss4ypkw08xwwyj7ky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7"))
XCTAssertTrue(try derivationTool.isValidExtendedViewingKey("zxviews1q0dm7hkzqqqqpqplzv3f50rl4vay8uy5zg9e92f62lqg6gzu63rljety32xy5tcyenzuu3n386ws772nm6tp4sads8n37gff6nxmyz8dn9keehmapk0spc6pzx5uxepgu52xnwzxxnuja5tv465t9asppnj3eqncu3s7g3gzg5x8ss4ypkw08xwwyj7ky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7"))
XCTAssertFalse(try DerivationTool.default.isValidExtendedViewingKey("zxviews1q0dm7hkzky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7"))
XCTAssertFalse(try derivationTool.isValidExtendedViewingKey("zxviews1q0dm7hkzky5skvnd9ldwj2u8fz2ry94s5q8p9lyp3j96yckudmp087d2jr2rnfuvjp7f56v78vpe658vljjddj7s645q399jd7"))
}
func testDeriveSecretKeyFromSeed() throws {
XCTAssertEqual(try DerivationTool.default.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "KwqfQoTCuQdCLvzpAEtkt1o8J62WJuZXD3cGRAf1bgmPWuLamHLo")
XCTAssertEqual(try derivationTool.deriveTransparentPrivateKey(seed: [UInt8](seedData)), "KwqfQoTCuQdCLvzpAEtkt1o8J62WJuZXD3cGRAf1bgmPWuLamHLo")
}
func testDeriveUnifiedKeysFromSeed() throws {
let unifiedKeys = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1)
let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 1)
XCTAssertEqual(unifiedKeys.count, 1)
XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey)
XCTAssertEqual(expectedTransparentAddress, try DerivationTool.default.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
}
func testDeriveQuiteALotOfUnifiedKeysFromSeed() throws {
let unifiedKeys = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10)
let unifiedKeys = try derivationTool.deriveUnifiedViewingKeysFromSeed([UInt8](seedData), numberOfAccounts: 10)
XCTAssertEqual(unifiedKeys.count, 10)
XCTAssertEqual(unifiedKeys[0].extfvk, expectedViewingKey)
XCTAssertEqual(expectedTransparentAddress, try DerivationTool.default.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
XCTAssertEqual(expectedTransparentAddress, try derivationTool.deriveTransparentAddressFromPublicKey(unifiedKeys[0].extpub))
}
}

View File

@ -26,6 +26,7 @@ end
target 'ZcashLightClientSample-Mainnet' do
inherit! :search_paths
use_frameworks!
pod 'MnemonicSwift', '~> 2.0.0'
pod "KRProgressHUD"
pod 'PaginatedTableView'
pod 'NotificationBubbles'
@ -41,9 +42,7 @@ post_install do |installer|
if target.name == 'ZcashLightClientKit-Unit-Tests'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = "13.0"
end
if target.name == 'ZcashLightClientKit'
config.build_settings['ZCASH_NETWORK_ENVIRONMENT'] = ENV["ZCASH_NETWORK_ENVIRONMENT"]
end
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end

View File

@ -68,13 +68,13 @@ PODS:
- SwiftNIOFoundationCompat (< 3, >= 2.19.0)
- SwiftNIOTLS (< 3, >= 2.19.0)
- SwiftProtobuf (1.16.0)
- ZcashLightClientKit (0.12.0-alpha.10):
- ZcashLightClientKit (0.12.0-alpha.12):
- gRPC-Swift (= 1.0.0)
- SQLite.swift (~> 0.12.2)
- ZcashLightClientKit/DerivationToolTests (0.12.0-alpha.10):
- ZcashLightClientKit/DerivationToolTests (0.12.0-alpha.12):
- gRPC-Swift (= 1.0.0)
- SQLite.swift (~> 0.12.2)
- ZcashLightClientKit/Tests (0.12.0-alpha.10):
- ZcashLightClientKit/Tests (0.12.0-alpha.12):
- gRPC-Swift (= 1.0.0)
- SQLite.swift (~> 0.12.2)
@ -153,8 +153,8 @@ SPEC CHECKSUMS:
SwiftNIOTLS: 4f8df225f03393f08e0b47b4d876ae38167f8a27
SwiftNIOTransportServices: 896c9a4ac98698d32aa2feea7657ade219ae80bb
SwiftProtobuf: 4e16842b83c6fda06b10fac50d73b3f1fce8ab7b
ZcashLightClientKit: cbd3df0c6736cbcb228b5cdc39baad40346ffba3
ZcashLightClientKit: 386288e87e90446638c2314a7b4f3f1ffeee40b5
PODFILE CHECKSUM: 315a67042788e1eccd948b2b8fe580222fd83cd9
PODFILE CHECKSUM: 0e90dc69ac4c19fd97c0ce4835ece810d79ade23
COCOAPODS: 1.10.1

View File

@ -13,6 +13,9 @@
0D4EBA312396CFD70041B507 /* SendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4EBA302396CFD70041B507 /* SendViewController.swift */; };
0D6CE8BD252E3C4A0005D707 /* SaplingParametersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6CE8BC252E3C4A0005D707 /* SaplingParametersViewController.swift */; };
0D756A94236C761E009B041B /* GetAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D756A93236C761E009B041B /* GetAddressViewController.swift */; };
0D76121726B1D5F5001CA417 /* Mainnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D76121526B1D5ED001CA417 /* Mainnet.swift */; };
0D76121926B1D66D001CA417 /* Testnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D76121826B1D66D001CA417 /* Testnet.swift */; };
0D76121A26B1E8F6001CA417 /* SampleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D49A18B241698A800CC0649 /* SampleLogger.swift */; };
0D7A4A83236CCD88001F4DD8 /* SyncBlocksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */; };
0D7C85E523AD5A9B006878FC /* SampleStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7C85E423AD5A9B006878FC /* SampleStorage.swift */; };
0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD3DC6238D88B100DD3EC4 /* GetBalanceViewController.swift */; };
@ -75,6 +78,8 @@
0D4EBA302396CFD70041B507 /* SendViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendViewController.swift; sourceTree = "<group>"; };
0D6CE8BC252E3C4A0005D707 /* SaplingParametersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaplingParametersViewController.swift; sourceTree = "<group>"; };
0D756A93236C761E009B041B /* GetAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAddressViewController.swift; sourceTree = "<group>"; };
0D76121526B1D5ED001CA417 /* Mainnet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mainnet.swift; sourceTree = "<group>"; };
0D76121826B1D66D001CA417 /* Testnet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Testnet.swift; sourceTree = "<group>"; };
0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncBlocksViewController.swift; sourceTree = "<group>"; };
0D7C85E423AD5A9B006878FC /* SampleStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleStorage.swift; sourceTree = "<group>"; };
0D8BB46C23B1DA0700D5E2A1 /* ZcashLightClientSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZcashLightClientSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -189,6 +194,15 @@
path = "Get Address";
sourceTree = "<group>";
};
0D76121426B1D5D7001CA417 /* Constants */ = {
isa = PBXGroup;
children = (
0D76121526B1D5ED001CA417 /* Mainnet.swift */,
0D76121826B1D66D001CA417 /* Testnet.swift */,
);
path = Constants;
sourceTree = "<group>";
};
0D7A4A81236CCCDB001F4DD8 /* Sync Blocks */ = {
isa = PBXGroup;
children = (
@ -224,6 +238,7 @@
0D907F142322CC5900D641FE /* ZcashLightClientSample */ = {
isa = PBXGroup;
children = (
0D76121426B1D5D7001CA417 /* Constants */,
0D1BE47D2581933C00F78BE3 /* Get UTXOs */,
0D1BE44F2581583D00F78BE3 /* Derivation Tool */,
0D6CE8BB252E3C1A0005D707 /* Sapling Parameters */,
@ -659,6 +674,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D76121726B1D5F5001CA417 /* Mainnet.swift in Sources */,
0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */,
0D8BB45323B1DA0700D5E2A1 /* GetAddressViewController.swift in Sources */,
0D8BB45423B1DA0700D5E2A1 /* ViewController.swift in Sources */,
@ -672,6 +688,7 @@
0D8BB45C23B1DA0700D5E2A1 /* SampleStorage.swift in Sources */,
0D8BB45D23B1DA0700D5E2A1 /* TransactionsDataSource.swift in Sources */,
0D8BB45E23B1DA0700D5E2A1 /* PaginatedTransactionsViewController.swift in Sources */,
0D76121A26B1E8F6001CA417 /* SampleLogger.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -684,6 +701,7 @@
0D907F182322CC5900D641FE /* ViewController.swift in Sources */,
0DDFB33C236B743000AED892 /* LatestHeightViewController.swift in Sources */,
0DBF8F9523A80F5A0010B85F /* TransactionDetailViewController.swift in Sources */,
0D76121926B1D66D001CA417 /* Testnet.swift in Sources */,
0DA58B942397DDD9004596EA /* TransactionsTableViewController.swift in Sources */,
0D4EBA312396CFD70041B507 /* SendViewController.swift in Sources */,
0D7A4A83236CCD88001F4DD8 /* SyncBlocksViewController.swift in Sources */,

View File

@ -33,11 +33,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
if let wallet = wallet {
return wallet
} else {
let unifiedViewingKeys = try! DerivationTool.default.deriveUnifiedViewingKeysFromSeed(DemoAppConfig.seed, numberOfAccounts: 1)
let unifiedViewingKeys = try! DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveUnifiedViewingKeysFromSeed(DemoAppConfig.seed, numberOfAccounts: 1)
let wallet = Initializer(cacheDbURL:try! __cacheDbURL(),
dataDbURL: try! __dataDbURL(),
pendingDbURL: try! __pendingDbURL(),
endpoint: DemoAppConfig.endpoint,
network: ZCASH_NETWORK,
spendParamsURL: try! __spendParamsURL(),
outputParamsURL: try! __outputParamsURL(),
viewingKeys: unifiedViewingKeys,
@ -48,7 +49,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
try! wallet.initialize()
var storage = SampleStorage.shared
storage!.seed = Data(DemoAppConfig.seed)
storage!.privateKey = try! DerivationTool.default.deriveSpendingKeys(seed: DemoAppConfig.seed, numberOfAccounts: 1)[0]
storage!.privateKey = try! DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveSpendingKeys(seed: DemoAppConfig.seed, numberOfAccounts: 1)[0]
self.wallet = wallet
return wallet
}
@ -152,15 +153,15 @@ func __documentsDirectory() throws -> URL {
}
func __cacheDbURL() throws -> URL {
try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_CACHES_DB_NAME, isDirectory: false)
try __documentsDirectory().appendingPathComponent(ZCASH_NETWORK.constants.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_CACHES_DB_NAME, isDirectory: false)
}
func __dataDbURL() throws -> URL {
try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_DATA_DB_NAME, isDirectory: false)
try __documentsDirectory().appendingPathComponent(ZCASH_NETWORK.constants.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_DATA_DB_NAME, isDirectory: false)
}
func __pendingDbURL() throws -> URL {
try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_PENDING_DB_NAME)
try __documentsDirectory().appendingPathComponent(ZCASH_NETWORK.constants.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_PENDING_DB_NAME)
}
func __spendParamsURL() throws -> URL {

View File

@ -0,0 +1,12 @@
//
// Mainnet.swift
// ZcashLightClientSample
//
// Created by Francisco Gindre on 7/28/21.
// Copyright © 2021 Electric Coin Company. All rights reserved.
//
import Foundation
import ZcashLightClientKit
let ZCASH_NETWORK = ZcashNetworkBuilder.network(for: .mainnet)

View File

@ -0,0 +1,12 @@
//
// Testnet.swift
// ZcashLightClientSample
//
// Created by Francisco Gindre on 7/28/21.
// Copyright © 2021 Electric Coin Company. All rights reserved.
//
import Foundation
import ZcashLightClientKit
let ZCASH_NETWORK = ZcashNetworkBuilder.network(for: .testnet)

View File

@ -13,17 +13,15 @@ struct DemoAppConfig {
static var host = ZcashSDK.isMainnet ? "lightwalletd.electriccoin.co" : "lightwalletd.testnet.electriccoin.co"
static var port: Int = 9067
static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 935000 : 1386000
static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet
static var seed = try! Mnemonic.deterministicSeedBytes(from: "live combine flight accident slow soda mind bright absent bid hen shy decade biology amazing mix enlist ensure biology rhythm snap duty soap armor")
static var address: String {
"\(host):\(port)"
}
static var processorConfig: CompactBlockProcessor.Configuration {
var config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL())
config.walletBirthday = self.birthdayHeight
return config
}
static var processorConfig: CompactBlockProcessor.Configuration = {
CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), walletBirthday: Self.birthdayHeight, network: ZCASH_NETWORK)
}()
static var endpoint: LightWalletEndpoint {
return LightWalletEndpoint(address: self.host, port: self.port, secure: true)
@ -31,7 +29,13 @@ struct DemoAppConfig {
}
enum ZcashNetwork {
case mainNet
case testNet
extension ZcashSDK {
static var isMainnet: Bool {
switch ZCASH_NETWORK.networkType {
case .mainnet:
return true
case .testnet:
return false
}
}
}

View File

@ -81,19 +81,19 @@ class DerivationToolViewController: UIViewController {
}
func deriveFrom(seedPhrase: String) throws {
let seedBytes = try Mnemonic.deterministicSeedBytes(from: seedPhrase)
guard let spendingKey = try DerivationTool.default.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
let derivationTool = DerivationTool(networkType: ZCASH_NETWORK.networkType)
guard let spendingKey = try derivationTool.deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
throw DerivationErrors.couldNotDeriveSpendingKeys(underlyingError: DerivationErrors.unknown)
}
guard let viewingKey = try DerivationTool.default.deriveViewingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
guard let viewingKey = try derivationTool.deriveViewingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
throw DerivationErrors.couldNotDeriveViewingKeys(underlyingError: DerivationErrors.unknown)
}
let shieldedAddress = try DerivationTool.default.deriveShieldedAddress(viewingKey: viewingKey)
let shieldedAddress = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey)
let transparentAddress = try DerivationTool.default.deriveTransparentAddress(seed: seedBytes)
let transparentAddress = try derivationTool.deriveTransparentAddress(seed: seedBytes)
updateLabels(spendingKey: spendingKey,

View File

@ -15,11 +15,11 @@ class GetAddressViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let derivationTool = DerivationTool(networkType: ZCASH_NETWORK.networkType)
// Do any additional setup after loading the view.
zAddressLabel.text = (try? DerivationTool.default.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)) ?? "No Addresses found"
tAddressLabel.text = (try? DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)) ?? "could not derive t-address"
zAddressLabel.text = (try? derivationTool.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)) ?? "No Addresses found"
tAddressLabel.text = (try? derivationTool.deriveTransparentAddress(seed: DemoAppConfig.seed)) ?? "could not derive t-address"
spendingKeyLabel.text = SampleStorage.shared.privateKey ?? "No Spending Key found"
zAddressLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(addressTapped(_:))))
zAddressLabel.isUserInteractionEnabled = true
@ -60,7 +60,7 @@ class GetAddressViewController: UIViewController {
@IBAction func addressTapped(_ gesture: UIGestureRecognizer) {
loggerProxy.event("copied to clipboard")
UIPasteboard.general.string = try? DerivationTool.default.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)
UIPasteboard.general.string = try? DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)
let alert = UIAlertController(title: "", message: "Address Copied to clipboard", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
@ -68,7 +68,7 @@ class GetAddressViewController: UIViewController {
@IBAction func tAddressTapped(_ gesture: UIGestureRecognizer) {
loggerProxy.event("copied to clipboard")
UIPasteboard.general.string = try? DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)
UIPasteboard.general.string = try? DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveTransparentAddress(seed: DemoAppConfig.seed)
let alert = UIAlertController(title: "", message: "Address Copied to clipboard", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)

View File

@ -26,10 +26,10 @@ class GetUTXOsViewController: UIViewController {
}
func updateUI() {
let tAddress = try! DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)
let tAddress = try! DerivationTool(networkType: ZCASH_NETWORK.networkType).deriveTransparentAddress(seed: DemoAppConfig.seed)
self.transparentAddressLabel.text = tAddress
let balance = try! AppDelegate.shared.sharedSynchronizer.getTransparentBalance(address: tAddress)
let balance = try! AppDelegate.shared.sharedSynchronizer.getTransparentBalance(accountIndex: 0)
self.totalBalanceLabel.text = String(balance.total.asHumanReadableZecBalance())
self.verifiedBalanceLabel.text = String(balance.verified.asHumanReadableZecBalance())
@ -38,9 +38,10 @@ class GetUTXOsViewController: UIViewController {
@IBAction func shieldFunds(_ sender: Any) {
do {
let seed = DemoAppConfig.seed
let sk = try DerivationTool.default.deriveSpendingKeys(seed: seed, numberOfAccounts: 1).first!
let derivationTool = DerivationTool(networkType: ZCASH_NETWORK.networkType)
let sk = try derivationTool.deriveSpendingKeys(seed: seed, numberOfAccounts: 1).first!
let tsk = try DerivationTool.default.deriveTransparentPrivateKey(seed: seed)
let tsk = try derivationTool.deriveTransparentPrivateKey(seed: seed)
KRProgressHUD.showMessage("🛡 Shielding 🛡")
AppDelegate.shared.sharedSynchronizer.shieldFunds(spendingKey: sk, transparentSecretKey: tsk, memo: "shielding is fun!", from: 0) { (result) in
DispatchQueue.main.async {

View File

@ -43,16 +43,13 @@ use_frameworks!
pod 'ZcashLightClientKit'
````
### Set Testnet or Mainnet environment
Before building, make sure that your environment has the variable `ZCASH_NETWORK_ENVIRONMENT` set to `MAINNET` or `TESTNET`.
### Custom build phases warning
When running `pod install` you will see this warning upon success:
```` bash
[!] ZcashLightClientKit has added 2 script phases. Please inspect before executing a build.
See `https://guides.cocoapods.org/syntax/podspec.html#script_phases` for more information.
````
Integrating Rust code with Swift code and delivering it in a consistent and (build) reproducible way, is hard. We've taken the lead to get that burden off your shoulders as much as possible by leveraging the `prepare_command` and `script_phases` features from Cocoapods to carefully generate the `TESTNET` and `MAINNET` builds as simple and less error prone as we could think it could be. Which started as some simple vanilla scripts, ended up being some kind of "Build System" on its own. Nothing is written on stone, and we accept collaborations and improvements in this matter too.
Integrating Rust code with Swift code and delivering it in a consistent and (build) reproducible way, is hard. We've taken the lead to get that burden off your shoulders as much as possible by leveraging the `prepare_command` and `script_phases` features from Cocoapods to carefully generate a build for the Rust layer.
## Build system
@ -68,8 +65,7 @@ ZcashLightClientKit needs files to be present at pod installation time, but that
- `${ZCASH_POD_SRCROOT}/zcashlc/libzcashlc.a` this is the librustzcash build .a file itself
- `lib/libzcashlc.a` (as vendored library that will be added as an asset by xcodeproj)
- `ZcashSDK.generated.swift` which contains sensitive values for the SDK that change depending on the network environment we are building for
- `WalletBirthday+saplingtree.generated.swift` helper functions to import existing wallets
**2. Build Phase**
@ -78,37 +74,17 @@ The build Phase scripts executes within the Xcode Build Step and has all the kno
```` ruby
s.script_phase = {
:name => 'Build generate constants and build librustzcash',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_zcashsdk_constants.sh && sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:execution_position => :before_compile
}
````
This step will generate files needed on the next steps and build the librustzcash with Xcode but *not using cargo's built-in Xcode integration*
**a. Generating ZcashSDK constants**
To run this you need `Sourcery`. We use `Stencil` templates to create these files based on the `ZCASH_NETWORK_ENVIRONMENT` value of your choice. You can either integrate sourcery with cocoapods or as part of your environment.
All generated files will be located in the Pods source root within the `Generated` folder. `ZCASH_SDK_GENERATED_SOURCES_FOLDER` represents that path in the build system.
**b. Building librustzcash and integrating it to the pod structure**
** Building librustzcash and integrating it to the pod structure**
Where the magic happens. Here we will make sure that everything is set up properly to start building librustzcash. When on mainnet, the build will append a parameter to include mainnet features.
**Safeguards points**:
if it appears that you are about to build something smelly, we will let you know. Combining testnet and mainnet values and artifacts and viceversa leads to unstable builds and may cause loss of funds if ran on production.
```
if [ existing_build_mismatch = true ]; then
# clean
echo "build mismatch. You previously build a Different network environment. It appears that your build could be inconsistent if proceeding. Please clean your Pods/ folder and clean your build before running your next build."
exit 1
fi
```
**3. Xcode clean integration**
When performing a clean, we will clean the rust build folders.
### Scripts
On the Scripts folder you will find the following files:
@ -118,12 +94,11 @@ On the Scripts folder you will find the following files:
|-/generate_test_constants.sh
|-/build_librustzcash_xcode.sh
|-/build_librustzcash.sh
|-/generate_zcashsdk_constants.sh
|-/script_commons.sh
````
#### prepare_zcash_sdk.sh
This script is run by the Cocoapods 'preapare_command'.
This script is run by the Cocoapods 'prepare_command'.
```` Ruby
s.prepare_command = <<-CMD
@ -194,22 +169,7 @@ We don't like reinventing the wheel, so we gently borrowed swift lint rules from
## Troubleshooting
### No network environment....
if you see this message when building:
```No network environment. Set ZCASH_NETWORK_ENVIRONMENT to MAINNET or TESTNET```
make sure your dev environment has this variable set before the build starts. *DO NOT CHANGE IT DURING THE BUILD PROCESS*.
If the variable was properly set *after* you've seen this message, you will need to either a) set it manually on the pod's target or b) doing a clean pod install and subsequent build.
#### a) setting the flag manually
1. on your workspace, select the Pods project
2. on the Targets pane, select ZcashLightClientKit
3. go to build settings
4. scroll down to see ZCASH_NETWORK_ENVIRONMENT and complete with TESTNET or MAINNET
![how to complete network environment manually](docs/images/complete_environment_manually.png)
#### b) clean pod install
#### clean pod install
it's not necessary to delete the whole Pods/ directory and download all of your dependencies again
1. on your project root, locate the `Pods/` directory
2. remove ZcashLightClientKit from it
@ -228,14 +188,6 @@ if you get a build error similar to ```_function_name referenced from...```
3. run `pod install`
4. build
### ZcashLightClientKitSample missing .params
ZcashLightClientKit has an external dependency on 2 files containing Sapling parameters. Although you can provide those files as you seem fit, the sample app requires them on the main bundle.
You can download these files from https://z.cash/downloads/sapling-spend.params
and https://z.cash/downloads/sapling-output.params and then move them to the correct folder, which is specified on the error itself.
![how to fix missing params files](docs/images/output_params_error.png)
### can't find crate for ... target may not be installed
This error could be a side effect of having more then one rust toolchain installed.
If you worked with ZcashLightClientKit 0.6.6 or below you might have had to set the compiler to 1.40.0 which can cause this compilation error to happen.

View File

@ -3,16 +3,6 @@
BASEPATH="${PWD}"
TARGET_DIR="target"
FEATURE_FLAGS="--features=mainnet"
NETWORK_TYPE="TESTNET"
FLAVOR_FOLDER="Testnet"
if [ $1 = "--mainnet" ]; then
FEATURE_FLAGS="--features=mainnet"
NETWORK_TYPE="MAINNET"
FLAVOR_FOLDER="Mainnet"
fi
LIB_PATH="ZcashLightClientKit/$FLAVOR_FOLDER/zcashlc"
echo "++++ Building librustzcash $NETWORK_TYPE library ++++"
@ -22,7 +12,7 @@ if [ -f $TARGET_DIR ]; then
rm -rf $TARGET_DIR
fi
cargo build --release $FEATURE_FLAGS && cargo lipo --release
cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --release
if [ -f $LIB_PATH ]; then

View File

@ -7,31 +7,12 @@ if [ ! -f $SCRIPT_COMMONS ]; then
fi
source $SCRIPT_COMMONS
if [ "$1" = "--testing" ]; then
export ZCASH_NETWORK_ENVIRONMENT=$ZCASH_TESTNET
echo "Testing flag detected, forcing $ZCASH_TESTNET"
fi
check_environment
if [ "$ACTION" = "clean" ]; then
echo "CLEAN DETECTED"
clean
exit 0
fi
if [ existing_build_mismatch = true ]; then
# clean
echo "Build mismatch. You previously built a different network environment. It appears that your build could be inconsistent if proceeding. Please clean your Pods/ folder and clean your build before running your next build."
exit 1
fi
if is_mainnet; then
FEATURE_FLAGS="--features=mainnet"
else
FEATURE_FLAGS="--features=testnet"
fi
echo "Building Rust backend"
echo ""
echo "platform name"
@ -45,7 +26,7 @@ fi
echo "fix 'permission denied issue'"
chmod -R +w ${PODS_TARGET_SRCROOT}
echo "cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release"
echo "cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --targets $ZCASH_ACTIVE_ARCHITECTURE --release"
if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then
# Assume we're in Xcode, which means we're probably cross-compiling.
# In this case, we need to add an extra library search path for build scripts and proc-macros,
@ -55,7 +36,7 @@ if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then
export LIBRARY_PATH="${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}"
fi
if [ ! -f ${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME} ]; then
cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --targets $ZCASH_ACTIVE_ARCHITECTURE --release
cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --targets $ZCASH_ACTIVE_ARCHITECTURE --release
persist_environment
fi

View File

@ -1,42 +0,0 @@
#!/bin/sh
SCRIPT_COMMONS="${PODS_TARGET_SRCROOT}/Scripts/script_commons.sh"
if [ -f $SCRIPT_COMMONS ]; then
source $SCRIPT_COMMONS
else
echo "Failed to load $SCRIPT_COMMONS"
exit 1
fi
if ! hash sourcery; then
echo "Sourcery not found on your PATH"
exit 1
fi
export ZCASH_SDK_TEMPLATE="${ZCASH_SRC_PATH}/Stencil"
echo "export ZCASH_SRC_PATH=${ZCASH_SRC_PATH}"
check_environment
if is_mainnet; then
SOURCERY_ARGS="--args dbprefix=ZcashSdk_mainnet_ --args ismainnet=true --args saplingActivationHeight=419_200"
else
SOURCERY_ARGS="--args dbprefix=ZcashSdk_testnet_ --args ismainnet=false --args saplingActivationHeight=280_000"
fi
if [ -d $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]; then
echo "clean up before generating new files: $ZCASH_SDK_GENERATED_SOURCES_FOLDER"
echo "rm -rf ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/*.generated*"
rm -rf "${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/*.generated*"
else
echo "mkdir -p -v $ZCASH_SDK_GENERATED_SOURCES_FOLDER"
mkdir -p -v ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}
fi
echo "Set +w to ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}"
chmod -R +w ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}
echo "sourcery --prune --verbose --templates ${ZCASH_SDK_TEMPLATE} --sources ${ZCASH_SRC_PATH} --output ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} $SOURCERY_ARGS "
sourcery --prune --verbose --templates ${ZCASH_SDK_TEMPLATE} --sources ${ZCASH_SRC_PATH} --output ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} $SOURCERY_ARGS

View File

@ -26,22 +26,3 @@ echo "**************************************************************************
echo " touch ${ZCASH_POD_ROOT}/zcashlc/zcashlc.h"
echo "***************************************************************************"
touch ${ZCASH_POD_SRCROOT}/zcashlc/zcashlc.h
echo "make ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} folder"
mkdir -p ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}
echo "**********************************************"
echo "* create empty ZcashSDK.generated.swift file *"
echo "**********************************************"
echo ""
echo "touch ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/ZcashSDK.generated.swift"
touch ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/ZcashSDK.generated.swift
echo "****************************************************************"
echo "* create empty WalletBirthday+saplingtree.generated.swift file *"
echo "****************************************************************"
echo ""
echo "touch $ZCASH_SDK_GENERATED_SOURCES_FOLDER/WalletBirthday+saplingtree.generated.swift"
touch $ZCASH_SDK_GENERATED_SOURCES_FOLDER/WalletBirthday+saplingtree.generated.swift

View File

@ -4,14 +4,12 @@ export PATH="$HOME/.cargo/bin:$PATH"
export RUST_LIB_PATH="${PODS_TARGET_SRCROOT}/lib"
export ZCASH_POD_SCRIPTS="${PODS_TARGET_SRCROOT}/Scripts"
export ZCASH_LIB_RUST_BUILD_PATH="${PODS_TARGET_SRCROOT}/target"
export ZCASH_BUILD_TYPE_MAINNET_FLAG=".mainnet_build"
export ZCASH_BUILD_TYPE_TESTNET_FLAG=".testnet_build"
export ZCASH_LIB_RUST_NAME="libzcashlc.a"
export ZCASH_TESTNET="TESTNET"
export ZCASH_MAINNET="MAINNET"
export ZCASH_SRC_PATH="${PODS_TARGET_SRCROOT}/ZcashLightClientKit"
export ZCASH_SDK_RUST_LIB_PATH="${ZCASH_SRC_PATH}/zcashlc"
export ZCASH_SDK_GENERATED_SOURCES_FOLDER="${ZCASH_SRC_PATH}/Generated"
function clean {
echo "CLEAN DETECTED"
@ -23,76 +21,3 @@ function clean {
rm -rf "${ZCASH_LIB_RUST_BUILD_PATH}"
fi
}
function check_environment {
if [[ $ZCASH_NETWORK_ENVIRONMENT != $ZCASH_MAINNET ]] && [[ $ZCASH_NETWORK_ENVIRONMENT != $ZCASH_TESTNET ]]; then
echo "No network environment. Set ZCASH_NETWORK_ENVIRONMENT to $ZCASH_MAINNET or $ZCASH_TESTNET"
exit 1
fi
if [[ ! $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]]; then
echo "No 'ZCASH_SDK_GENERATED_SOURCES_FOLDER' variable present. Delete Pods/ and run 'pod install --verbose'"
exit 1
fi
echo "**** Building for $ZCASH_NETWORK_ENVIRONMENT environment ****"
}
function is_mainnet {
if [[ $ZCASH_NETWORK_ENVIRONMENT = $ZCASH_MAINNET ]]; then
true
else
false
fi
}
# Return success (0) if there is a build mismatch, else failure (1) if no mismatch.
function existing_build_mismatch {
#if build exists check that corresponds to the current network environment
if [! -d $ZCASH_LIB_RUST_BUILD_PATH ]; then
return 1
fi
# there's a MAINNET Flag and MAINNET ENVIRONMENT
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_MAINNET" ]]
then
return 1 # no build mismatch
fi
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]]
then
warn_mismatch $ZCASH_MAINNET $ZCASH_NETWORK_ENVIRONMENT
return 0 # build mismatch in place
fi
# There's a TESTNET flag and we are on TESTNET ENVIRONMENT
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]]
then
return 1 # no build mismatch
fi
# There's a TESTNET flag and we are on a MAINNET Environment
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_MAINNET" ]]
then
warn_mismatch $ZCASH_TESTNET $ZCASH_NETWORK_ENVIRONMENT
return 0 # build mismatch in place
fi
echo "=== NO BUILD FLAG, CHECKING ENVIRONMENT ==="
check_environment
return 1 # no build mismatch
}
function warn_mismatch {
echo "*** WARNING: *** build mismatch. Found ${0} but environment is ${1}"
}
function persist_environment {
check_environment
if [ $ZCASH_NETWORK_ENVIRONMENT = "$ZCASH_MAINNET" ]
then
touch $ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG
elif [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]]
then
touch $ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG
fi
}

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'ZcashLightClientKit'
s.version = '0.12.0-alpha.10'
s.version = '0.12.0-alpha.12'
s.summary = 'Zcash Light Client wallet SDK for iOS'
s.description = <<-DESC
@ -30,11 +30,9 @@ Pod::Spec.new do |s|
s.script_phase = {
:name => 'Build generate constants and build librustzcash',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_zcashsdk_constants.sh && sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:execution_position => :before_compile,
:output_files => [
'${PODS_TARGET_SRCROOT}/ZcashLightClientKit/Generated/WalletBirthday+saplingtree.generated.swift',
'${PODS_TARGET_SRCROOT}/ZcashLightClientKit/Generated/ZcashSDK.generated.swift']
}
s.test_spec 'Tests' do | test_spec |
@ -42,7 +40,7 @@ Pod::Spec.new do |s|
test_spec.ios.resources = 'ZcashLightClientKitTests/**/*.{db,params}'
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',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:execution_position => :before_compile
}
test_spec.dependency 'gRPC-Swift', '= 1.0.0'
@ -53,7 +51,7 @@ Pod::Spec.new do |s|
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',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:execution_position => :before_compile
}
test_spec.dependency 'gRPC-Swift', '= 1.0.0'

View File

@ -25,13 +25,15 @@ class MigrationManager {
var cacheDb: ConnectionProvider
var dataDb: ConnectionProvider
var pendingDb: ConnectionProvider
var network: NetworkType
init(cacheDbConnection: ConnectionProvider,
dataDbConnection: ConnectionProvider,
pendingDbConnection: ConnectionProvider) {
pendingDbConnection: ConnectionProvider,
networkType: NetworkType) {
self.cacheDb = cacheDbConnection
self.dataDb = dataDbConnection
self.pendingDb = pendingDbConnection
self.network = networkType
}
static let latestDataDbMigrationVersion: Int32 = DataDbMigrations.version1.rawValue
@ -149,7 +151,7 @@ class MigrationManager {
LoggerProxy.debug(message)
throw StorageError.migrationFailedWithMessage(message: message)
}
let derivationTool = DerivationTool.default
let derivationTool = DerivationTool(networkType: self.network)
for tuple in zip(accounts, viewingKeys) {
let tAddr = try derivationTool.deriveTransparentAddressFromPublicKey(tuple.1.extpub)
@ -177,7 +179,9 @@ class MigrationManager {
return
}
let uvks = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: accounts.count)
let derivationTool = DerivationTool(networkType: self.network)
let uvks = try derivationTool.deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: accounts.count)
try performVersion1Migration(viewingKeys: uvks)
}

View File

@ -90,9 +90,6 @@ class CompactBlockStreamDownloadOperation: ZcashOperation {
}
let latestDownloaded = try storage.latestHeight()
let startHeight = max(self.startHeight ?? BlockHeight.empty(), latestDownloaded)
guard startHeight >= ZcashSDK.SAPLING_ACTIVATION_HEIGHT else {
throw CompactBlockStreamDownloadOperationError.startHeightMissing
}
self.cancelable = self.service.blockStream(startHeight: startHeight, endHeight: latestHeight) { [weak self] result in
switch result {
@ -106,7 +103,11 @@ class CompactBlockStreamDownloadOperation: ZcashOperation {
self?.fail(error: e)
}
case .failure(let e):
self?.fail(error: e)
if case .userCancelled = e {
self?.done = true
} else {
self?.fail(error: e)
}
}
} handler: {[weak self] block in
@ -181,16 +182,14 @@ class CompactBlockBatchDownloadOperation: ZcashOperation {
}
self.startedHandler?()
do {
let localDownloadedHeight = try self.storage.latestHeight()
guard startHeight >= ZcashSDK.SAPLING_ACTIVATION_HEIGHT else {
throw CompactBlockBatchDownloadOperationError.startHeightMissing
}
var localDownloadedHeight = try self.storage.latestHeight()
if localDownloadedHeight != startHeight {
if localDownloadedHeight != BlockHeight.empty() && localDownloadedHeight > startHeight {
LoggerProxy.warn("provided startHeight (\(startHeight)) differs from local latest downloaded height (\(localDownloadedHeight))")
startHeight = localDownloadedHeight + 1
}
var currentHeight = startHeight
self.progressDelegate?.progressUpdated(.download(BlockProgress(startHeight: currentHeight, targetHeight: targetHeight, progressHeight: currentHeight)))

View File

@ -24,6 +24,7 @@ class CompactBlockEnhancementOperation: ZcashOperation {
var repository: TransactionRepository
var maxRetries: Int = 5
var retries: Int = 0
private(set) var network: NetworkType
weak var progressDelegate: CompactBlockProgressDelegate?
private var dataDb: URL
@ -34,6 +35,7 @@ class CompactBlockEnhancementOperation: ZcashOperation {
downloader: CompactBlockDownloading,
repository: TransactionRepository,
range: BlockRange,
networkType: NetworkType,
progressDelegate: CompactBlockProgressDelegate? = nil) {
rustBackend = rustWelding
self.dataDb = dataDb
@ -41,6 +43,7 @@ class CompactBlockEnhancementOperation: ZcashOperation {
self.repository = repository
self.range = range
self.progressDelegate = progressDelegate
self.network = networkType
super.init()
}
@ -112,7 +115,7 @@ class CompactBlockEnhancementOperation: ZcashOperation {
throw error
}
guard rustBackend.decryptAndStoreTransaction(dbData: dataDb, tx: rawBytes) else {
guard rustBackend.decryptAndStoreTransaction(dbData: dataDb, tx: rawBytes, networkType: network) else {
if let rustError = rustBackend.lastError() {
throw EnhancementError.decryptError(error: rustError)
}

View File

@ -27,7 +27,7 @@ public enum CompactBlockProcessorError: Error {
case criticalError
case invalidAccount
case wrongConsensusBranchId(expectedLocally: ConsensusBranchID, found: ConsensusBranchID)
case networkMismatch(expected: ZcashSDK.NetworkType, found: ZcashSDK.NetworkType)
case networkMismatch(expected: NetworkType, found: NetworkType)
case saplingActivationMismatch(expected: BlockHeight, found: BlockHeight)
}
/**
@ -228,20 +228,23 @@ public class CompactBlockProcessor {
public var maxBackoffInterval = ZcashSDK.DEFAULT_MAX_BACKOFF_INTERVAL
public var rewindDistance = ZcashSDK.DEFAULT_REWIND_DISTANCE
public var walletBirthday: BlockHeight
private(set) var network: ZcashNetwork
private(set) var saplingActivation: BlockHeight
init (
cacheDb: URL,
dataDb: URL,
downloadBatchSize: Int,
retries: Int,
maxBackoffInterval: TimeInterval,
rewindDistance: Int,
walletBirthday: BlockHeight,
saplingActivation: BlockHeight
cacheDb: URL,
dataDb: URL,
downloadBatchSize: Int,
retries: Int,
maxBackoffInterval: TimeInterval,
rewindDistance: Int,
walletBirthday: BlockHeight,
saplingActivation: BlockHeight,
network: ZcashNetwork
) {
self.cacheDb = cacheDb
self.dataDb = dataDb
self.network = network
self.downloadBatchSize = downloadBatchSize
self.retries = retries
self.maxBackoffInterval = maxBackoffInterval
@ -250,11 +253,12 @@ public class CompactBlockProcessor {
self.saplingActivation = saplingActivation
}
public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT){
public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight, network: ZcashNetwork){
self.cacheDb = cacheDb
self.dataDb = dataDb
self.walletBirthday = walletBirthday
self.saplingActivation = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
self.saplingActivation = network.constants.SAPLING_ACTIVATION_HEIGHT
self.network = network
}
}
/**
@ -313,7 +317,7 @@ public class CompactBlockProcessor {
private var transactionRepository: TransactionRepository
private var accountRepository: AccountRepository
private var rustBackend: ZcashRustBackendWelding.Type
var config: Configuration = Configuration.standard {
var config: Configuration {
willSet {
self.stop()
}
@ -348,7 +352,7 @@ public class CompactBlockProcessor {
- Throws CompactBlockProcessorError.invalidConfiguration if block height is invalid or if processor is already started
*/
func setStartHeight(_ startHeight: BlockHeight) throws {
guard self.state == .stopped, startHeight >= ZcashSDK.SAPLING_ACTIVATION_HEIGHT else {
guard self.state == .stopped, startHeight >= config.network.constants.SAPLING_ACTIVATION_HEIGHT else {
throw CompactBlockProcessorError.invalidConfiguration
}
@ -387,7 +391,8 @@ public class CompactBlockProcessor {
backend: initializer.rustBackend,
config: Configuration(cacheDb: initializer.cacheDbURL,
dataDb: initializer.dataDbURL,
walletBirthday: initializer.walletBirthday.height),
walletBirthday: initializer.walletBirthday.height,
network: initializer.network),
repository: initializer.transactionRepository,
accountRepository: initializer.accountRepository)
}
@ -493,6 +498,7 @@ public class CompactBlockProcessor {
do {
try Self.validateServerInfo(info,
saplingActivation: self.config.saplingActivation,
localNetwork: self.config.network,
rustBackend: self.rustBackend)
completionBlock()
} catch {
@ -507,15 +513,16 @@ public class CompactBlockProcessor {
static func validateServerInfo(_ info: LightWalletdInfo,
saplingActivation: BlockHeight,
localNetwork: ZcashNetwork,
rustBackend: ZcashRustBackendWelding.Type) throws {
// check network types
guard let remoteNetworkType = ZcashSDK.NetworkType(info.chainName) else {
guard let remoteNetworkType = NetworkType.forChainName(info.chainName) else {
throw CompactBlockProcessorError.generalError(message: "Chain name does not match. Expected either 'test' or 'main' but received '\(info.chainName)'. this is probably an API or programming error")
}
guard remoteNetworkType == ZcashSDK.networkType else {
throw CompactBlockProcessorError.networkMismatch(expected: ZcashSDK.networkType, found: remoteNetworkType)
guard remoteNetworkType == localNetwork.networkType else {
throw CompactBlockProcessorError.networkMismatch(expected: localNetwork.networkType, found: remoteNetworkType)
}
guard saplingActivation == info.saplingActivationHeight else {
@ -523,7 +530,7 @@ public class CompactBlockProcessor {
}
// check branch id
let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight))
let localBranch = try rustBackend.consensusBranchIdFor(height: Int32(info.blockHeight), networkType: localNetwork.networkType)
guard let remoteBranchID = ConsensusBranchID.fromString(info.consensusBranchID)
else {
@ -564,7 +571,7 @@ public class CompactBlockProcessor {
let lastDownloaded = try downloader.lastDownloadedBlockHeight()
let height = Int32(height ?? lastDownloaded)
let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height)
let nearestHeight = rustBackend.getNearestRewindHeight(dbData: config.dataDb, height: height, networkType: self.config.network.networkType)
guard nearestHeight > 0 else {
let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error getting nearest rewind height for height: \(height)")
@ -574,7 +581,7 @@ public class CompactBlockProcessor {
// FIXME: this should be done on the rust layer
let rewindHeight = max(Int32(nearestHeight - 1) , Int32(config.walletBirthday))
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight) else {
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: rewindHeight, networkType: self.config.network.networkType) else {
let error = rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)")
fail(error)
throw error
@ -649,7 +656,7 @@ public class CompactBlockProcessor {
}
}
let validateChainOperation = CompactBlockValidationOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb)
let validateChainOperation = CompactBlockValidationOperation(rustWelding: self.rustBackend, cacheDb: cfg.cacheDb, dataDb: cfg.dataDb, networkType: self.config.network.networkType)
let downloadValidateAdapterOperation = BlockOperation { [weak validateChainOperation, weak downloadBlockOperation] in
validateChainOperation?.error = downloadBlockOperation?.error
@ -698,7 +705,7 @@ public class CompactBlockProcessor {
}
}
let scanBlocksOperation = CompactBlockBatchScanningOperation(rustWelding: rustBackend, cacheDb: config.cacheDb, dataDb: config.dataDb, transactionRepository: transactionRepository, range: range, progressDelegate: self)
let scanBlocksOperation = CompactBlockBatchScanningOperation(rustWelding: rustBackend, cacheDb: config.cacheDb, dataDb: config.dataDb, transactionRepository: transactionRepository, range: range, networkType: self.config.network.networkType, progressDelegate: self)
let validateScanningAdapterOperation = BlockOperation { [weak scanBlocksOperation, weak validateChainOperation] in
scanBlocksOperation?.error = validateChainOperation?.error
@ -727,7 +734,7 @@ public class CompactBlockProcessor {
}
}
let enhanceOperation = CompactBlockEnhancementOperation(rustWelding: rustBackend, dataDb: config.dataDb, downloader: downloader, repository: transactionRepository, range: range.blockRange())
let enhanceOperation = CompactBlockEnhancementOperation(rustWelding: rustBackend, dataDb: config.dataDb, downloader: downloader, repository: transactionRepository, range: range.blockRange(), networkType: self.config.network.networkType)
enhanceOperation.startedHandler = {
LoggerProxy.debug("Started Enhancing range: \(range)")
@ -760,7 +767,7 @@ public class CompactBlockProcessor {
enhanceOperation?.error = scanBlocksOperation?.error
}
let fetchOperation = FetchUnspentTxOutputsOperation(accountRepository: accountRepository, downloader: self.downloader, rustbackend: rustBackend, dataDb: config.dataDb, startHeight: config.walletBirthday)
let fetchOperation = FetchUnspentTxOutputsOperation(accountRepository: accountRepository, downloader: self.downloader, rustbackend: rustBackend, dataDb: config.dataDb, startHeight: config.walletBirthday, networkType: self.config.network.networkType)
fetchOperation.startedHandler = { [weak self] in
DispatchQueue.main.async { [weak self] in
@ -855,7 +862,7 @@ public class CompactBlockProcessor {
// rewind
let rewindHeight = determineLowerBound(errorHeight: height, consecutiveErrors: consecutiveChainValidationErrors, walletBirthday: self.config.walletBirthday)
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight)) else {
guard rustBackend.rewindToHeight(dbData: config.dataDb, height: Int32(rewindHeight), networkType: self.config.network.networkType) else {
fail(rustBackend.lastError() ?? RustWeldingError.genericError(message: "unknown error rewinding to height \(height)"))
return
}
@ -1053,9 +1060,12 @@ public extension CompactBlockProcessor.Configuration {
/**
Standard configuration for most compact block processors
*/
static var standard: CompactBlockProcessor.Configuration {
let pathProvider = DefaultResourceProvider()
return CompactBlockProcessor.Configuration(cacheDb: pathProvider.cacheDbURL, dataDb: pathProvider.dataDbURL)
static func standard(for network: ZcashNetwork, walletBirthday: BlockHeight) -> CompactBlockProcessor.Configuration {
let pathProvider = DefaultResourceProvider(network: network)
return CompactBlockProcessor.Configuration(cacheDb: pathProvider.cacheDbURL,
dataDb: pathProvider.dataDbURL,
walletBirthday: walletBirthday,
network: network)
}
}
@ -1103,7 +1113,7 @@ extension CompactBlockProcessor.State: Equatable {
extension CompactBlockProcessor {
public func utxoCacheBalance(tAddress: String) throws -> WalletBalance {
try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress)
try rustBackend.downloadedUtxoBalance(dbData: config.dataDb, address: tAddress, networkType: config.network.networkType)
}
}
@ -1163,7 +1173,7 @@ extension CompactBlockProcessor {
guard let self = self else { return }
do {
guard try self.rustBackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1) >= 0 else {
guard try self.rustBackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1, networkType: self.config.network.networkType) >= 0 else {
result(.failure(CompactBlockProcessorError.generalError(message: "attempted to clear utxos but -1 was returned")))
return
}
@ -1191,7 +1201,8 @@ extension CompactBlockProcessor {
index: utxo.index,
script: utxo.script.bytes,
value: Int64(utxo.valueZat),
height: utxo.height) ? refreshed.append(utxo) : skipped.append(utxo)
height: utxo.height,
networkType: self.config.network.networkType) ? refreshed.append(utxo) : skipped.append(utxo)
} catch {
LoggerProxy.info("failed to put utxo - error: \(error)")
skipped.append(utxo)
@ -1305,7 +1316,7 @@ extension CompactBlockProcessor {
let info = try service.getInfo()
try CompactBlockProcessor.validateServerInfo(info, saplingActivation: config.saplingActivation, rustBackend: rustBackend)
try CompactBlockProcessor.validateServerInfo(info, saplingActivation: config.saplingActivation, localNetwork: config.network, rustBackend: rustBackend)
// get latest block height
let latestDownloadedBlockHeight: BlockHeight = max(config.walletBirthday,try downloader.lastDownloadedBlockHeight())
@ -1323,4 +1334,3 @@ extension CompactBlockProcessor {
}
}
}

View File

@ -19,11 +19,13 @@ class CompactBlockScanningOperation: ZcashOperation {
private var cacheDb: URL
private var dataDb: URL
private var limit: UInt32
init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, dataDb: URL, limit: UInt32 = 0) {
private var network: NetworkType
init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, dataDb: URL, limit: UInt32 = 0, networkType: NetworkType) {
rustBackend = rustWelding
self.cacheDb = cacheDb
self.dataDb = dataDb
self.limit = limit
self.network = networkType
super.init()
}
@ -33,7 +35,7 @@ class CompactBlockScanningOperation: ZcashOperation {
return
}
self.startedHandler?()
guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: limit) else {
guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: limit, networkType: network) else {
self.error = self.rustBackend.lastError() ?? ZcashOperationError.unknown
LoggerProxy.debug("block scanning failed with error: \(String(describing: self.error))")
self.fail()
@ -112,6 +114,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation {
private var batchSize: UInt32
private var blockRange: CompactBlockRange
private var transactionRepository: TransactionRepository
private var network: NetworkType
init(rustWelding: ZcashRustBackendWelding.Type,
cacheDb: URL,
@ -119,6 +122,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation {
transactionRepository: TransactionRepository,
range: CompactBlockRange,
batchSize: UInt32 = 100,
networkType: NetworkType,
progressDelegate: CompactBlockProgressDelegate? = nil) {
rustBackend = rustWelding
self.cacheDb = cacheDb
@ -127,6 +131,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation {
self.blockRange = range
self.batchSize = batchSize
self.progressDelegate = progressDelegate
self.network = networkType
super.init()
}
@ -139,7 +144,7 @@ class CompactBlockBatchScanningOperation: ZcashOperation {
do {
if batchSize == 0 {
let scanStartTime = Date()
guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: batchSize) else {
guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: batchSize, networkType: network) else {
self.scanFailed(self.rustBackend.lastError() ?? ZcashOperationError.unknown)
return
}
@ -164,7 +169,10 @@ class CompactBlockBatchScanningOperation: ZcashOperation {
}
let previousScannedHeight = lastScannedHeight
let scanStartTime = Date()
guard self.rustBackend.scanBlocks(dbCache: self.cacheDb, dbData: self.dataDb, limit: batchSize) else {
guard self.rustBackend.scanBlocks(dbCache: self.cacheDb,
dbData: self.dataDb,
limit: batchSize,
networkType: network) else {
self.scanFailed(self.rustBackend.lastError() ?? ZcashOperationError.unknown)
return
}

View File

@ -22,11 +22,16 @@ class CompactBlockValidationOperation: ZcashOperation {
private var cacheDb: URL
private var dataDb: URL
private var network: NetworkType
init(rustWelding: ZcashRustBackendWelding.Type, cacheDb: URL, dataDb: URL) {
init(rustWelding: ZcashRustBackendWelding.Type,
cacheDb: URL,
dataDb: URL,
networkType: NetworkType) {
rustBackend = rustWelding
self.cacheDb = cacheDb
self.dataDb = dataDb
self.network = networkType
super.init()
}
@ -36,7 +41,7 @@ class CompactBlockValidationOperation: ZcashOperation {
return
}
self.startedHandler?()
let result = self.rustBackend.validateCombinedChain(dbCache: cacheDb, dbData: dataDb)
let result = self.rustBackend.validateCombinedChain(dbCache: cacheDb, dbData: dataDb, networkType: self.network)
switch result {
case 0:
let error = CompactBlockValidationError.failedWithError(rustBackend.lastError())

View File

@ -22,18 +22,21 @@ class FetchUnspentTxOutputsOperation: ZcashOperation {
private var downloader: CompactBlockDownloading
private var rustbackend: ZcashRustBackendWelding.Type
private var startHeight: BlockHeight
private var network: NetworkType
private var dataDb: URL
init(accountRepository: AccountRepository,
downloader: CompactBlockDownloading,
rustbackend: ZcashRustBackendWelding.Type,
dataDb: URL,
startHeight: BlockHeight) {
startHeight: BlockHeight,
networkType: NetworkType) {
self.dataDb = dataDb
self.accountRepository = accountRepository
self.downloader = downloader
self.rustbackend = rustbackend
self.startHeight = startHeight
self.network = networkType
}
override func main() {
@ -46,7 +49,10 @@ class FetchUnspentTxOutputsOperation: ZcashOperation {
let tAddresses = try accountRepository.getAll().map({ $0.transparentAddress })
do {
for tAddress in tAddresses {
guard try self.rustbackend.clearUtxos(dbData: dataDb, address: tAddress, sinceHeight: startHeight - 1) >= 0 else {
guard try self.rustbackend.clearUtxos(dbData: dataDb,
address: tAddress,
sinceHeight: startHeight - 1,
networkType: network) >= 0 else {
let rustError = rustbackend.lastError() ?? RustWeldingError.genericError(message: "attempted to clear utxos but -1 was returned")
throw rustError
@ -80,7 +86,8 @@ class FetchUnspentTxOutputsOperation: ZcashOperation {
index: utxo.index,
script: utxo.script.bytes,
value: Int64(utxo.valueZat),
height: utxo.height) ? refreshed.append(utxo) : skipped.append(utxo)
height: utxo.height,
networkType: network) ? refreshed.append(utxo) : skipped.append(utxo)
} catch {
LoggerProxy.error("failed to put utxo - error: \(error)")
skipped.append(utxo)

View File

@ -0,0 +1,19 @@
//
// WalletBirthday+Constants.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 7/28/21.
//
import Foundation
public extension WalletBirthday {
static func birthday(with height: BlockHeight, network: ZcashNetwork) -> WalletBirthday {
switch network.networkType {
case .mainnet:
return mainnetBirthday(with: height)
case .testnet:
return testnetBirthday(with: height)
}
}
}

View File

@ -0,0 +1,498 @@
//
// WalletBirthday+mainnet.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 7/28/21.
//
import Foundation
extension WalletBirthday {
static func mainnetBirthday(with height: BlockHeight) -> WalletBirthday {
switch height {
case BlockHeight.min ..< 640_000:
return WalletBirthday(
height: 419_200,
hash: "00000000025a57200d898ac7f21e26bf29028bbe96ec46e05b2c17cc9db9e4f3",
time: 1540779337,
tree: "000000"
)
case 640_000 ..< 643_500:
return WalletBirthday(
height: 640000,
hash: "00000000016cd930734753f5acce6274b391f14330c793e54e7bd9f942d17114",
time: 1574051743,
tree: "0165aed8451b6a6c0a66294267976be6d171f2acf83c2b5b94d976cb32062cfa6301cd5b1e5ce12e7d82d07c1b83f7746ef2be8d0c56f90f82b71a1e422a1ffb400710000142f5056f23557ba4cbc562067d43fdc07477fa740c6a13a4ed6d0667b7c1b5510000000001ee9dbe0b8d268efe7e8a88ae7b0ac91923bd71ee81bba0e35e3b9504be59aa250001a2178e94504352c0dd7d6f711b814f8a332239f688568f1719808fd1d385831e0001967ca804f328397d98bd5e1f36786a9d44b06192e70a38026909fb4ce251943e000001fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
)
case 643_500 ..< 663000:
return WalletBirthday(
height: 643_500,
hash: "000000000041005fd724ff6e29bd1738bed69a4d9ca028e124029525350bd789",
time: 1574579149,
tree: "01999fc372390699b15f71d41745abe6a2ea0db4ffa8894d3c5fe30b9261a1a43a01585112668685bd6783cb01b72d17dc86c6d740c27cccf66b75e959e4e4f5ea3710019b7f6b4457a97eadbe1a39bfcc6ba0a56d37010d0d799e1e652fc29733103e04016a0b4d2705e1feb2021d80e5785608536dde05aea5ef676a5427244228b19e2d00010973d03ad5f79fcac64ab3ffbdaaac1a24b74a3617770bf960fb004cbd422439000001984bfce9361025cc38574f944a3ed7b074b3bf88cfce6f14c4a9be4d91d6dc730105871ec1e3737a39bceb00b0c2d253ff36f472e92c361e7ef360d49ea8dc4c4200000001c145105e1bf401668a8f23ca70c47ee92d23bd366072020c83d26b855eeafd6d0001fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
)
case 663000 ..< 663150:
return WalletBirthday(
height: 663000,
hash: "0000000000bd422264b700bb33cab167ab42392c89db0e7c8ce30d57f346fe69",
time: 1576810013,
tree: "0102f02a8cd23e35502f8efa55893c7a145168ac3fa00d4bd032b55097bbe0335a01b57c362e3c834f2216c72ae0d8a335fd2397cc80073d0f5b29c419028bc6c94c100000000157bfd70afa37c8bf0c60c9e160d2145bdfbcf07837b0ff90bf8a5108722cc85400000000011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
)
case 663150 ..< 663700:
return WalletBirthday(
height: 663150,
hash: "0000000002fd3be4c24c437bd22620901617125ec2a3a6c902ec9a6c06f734fc",
time: 1576821833,
tree: "01ec6278a1bed9e1b080fd60ef50eb17411645e3746ff129283712bc4757ecc833001001b4e1d4a26ac4a2810b57a14f4ffb69395f55dde5674ecd2462af96f9126e054701a36afb68534f640938bdffd80dfcb3f4d5e232488abbf67d049b33a761e7ed6901a16e35205fb7fe626a9b13fc43e1d2b98a9c241f99f93d5e93a735454073025401f5b9bcbf3d0e3c83f95ee79299e8aeadf30af07717bda15ffb7a3d00243b58570001fa6d4c2390e205f81d86b85ace0b48f3ce0afb78eeef3e14c70bcfd7c5f0191c0000011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
)
case 663700 ..< 670000:
return WalletBirthday(
height: 663700,
hash: "0000000000d387fab4c980e9a5b42ec35a39879706398c78fbce873d61f1b26c",
time: 1576863287,
tree: "014bd3b38c782ea2e66c053afd4c29c84fa27003b71de5f9778a631558ee7a1410001001534a90ede3e8dcb7115c84e86b2d184c0f46d5b21023a7292ecfade5e956e66500000001daeb30618bfdfa00999f2989795562775c3fdf95ce279d106c0e608fedc9ea31000001686ac0ccce56b47cab1dd4fceb48812f72d6ac6fff3a2ae5a9dcf27eda409a0b011bc9521263584de20822f9483e7edb5af54150c4823c775b2efc6a1eded9625501a6030f8d4b588681eddb66cad63f09c5c7519db49500fc56ebd481ce5e903c22000163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
)
case 670000 ..< 680000:
return WalletBirthday(
height: 670000,
hash: "000000000086313791aca867bf60fc7434fe2b3fc56926ef46223c6b6b05b5fd",
time: 1577338346,
tree: "01e38b18dcf2de5e9ca5c12a1329176b37219546cfabd9333a9536d2d3ef6cba3e01c159856a741f9da500a9c83935ee7323d63f589a117e66874612e70cdf7a9f4b1001db5e89b8cbf677a87375395940f4715de1bb951f05efbbc4fb34bb1990dd80600155dbaaf5b93f338d1c629fe2a77328c7609c59c6a767a6ccfcc14d3c8c7d826100000001d9e9451fe610b3374b30c711f62a29700ecd2b02e096f02085b896d3fdc3886401006895fa87a8083ae5d0d38df876e764486c67a684706f7750ee19c872dc5d2e01f5cc54720296c3379ac6fb0aa3ed6824bcc40894b3f40d9d2e2d1ed3e6080c3501e9fc6273cadcc40df45ee63984330cfe702a1e7b4c324516d1a80ebcacc4d4170125719ebec43e9148ecc5cfdb2359074badb6fc7759817f6afab999570a75a2000171b36f07e48c45e39f1cc02a99023236f1df60ae924b5ef14ddacc7885994e2b0163f4eec5a2fe00a5f45e71e1542ff01e937d2210c99f03addcce5314a5278b2d0163ab01f46a3bb6ea46f5a19d5bdd59eb3f81e19cfa6d10ab0fd5566c7a16992601fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13"
)
case 680000 ..< 690000:
return WalletBirthday(
height: 680000,
hash: "0000000001f2e08db1ea7ce567a5cd745de87c2eafbd769346b8212cc922d517",
time: 1578091375,
tree: "01bc7b45da508ff7e4b3dbc1184a42a646a18ad0c73907d9462199354f3490ec00001101cf1bc2f3ef2e491a4c04cede4efa561dcb4e9c56562adaa79b96ec8e54b43643000001419a6936943299e8d695fb98c78153499682d1c332efa1fbd19ce3c996be713b01e3743cb66129e262add8996fc588df0b1a33366df4e5d618ec14d0bc8129f537000000000141b1ff5b5fdad24aafa550d42cb9f99c85f6175b3d65060079bb9638cacf654e0141754203644e6f3d5faf15f16492efec723da55b2db473b34299c5582e883e46000000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 690000 ..< 692345:
return WalletBirthday(
height: 690000,
hash: "0000000000b1e6422ecd9292951b36ebb94e8926bbd33df8445b574b4be14f79",
time: 1578845180,
tree: "0117ffc074ef0f54651b2bc78d594e5ff786d9828ae78b1db972cd479669e8dd2401cc1b37d13f3b7d1fa2ead08493d275bfca976dd482e8dd879bf62b987652f63811013d84614158c7810753cc663f7a3da757f84f77744a24490eb07ce07af1daa92e0000017472a22c4064648ff260cbec8d85c273c5cd190dab7800f4978d473322dab1200001c7a1fd3786de051015c90f39143f3cfb89f2ea8bb5155520547ecfbefcdc382a0000000001d0c515cd513b49e397bf96d895a941aed4869ff2ff925939a34572c078dc16470121c1efd29f85680334050ee2a7e0d09fde474f90e573d85b7c9d337a5465625a0000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 692345 ..< 693400:
return WalletBirthday(
height: 692345,
hash: "0000000002584662ea3fb1969a65f05cf1e0c82581b885fbd723eed6ba818e99",
time: 1579021581,
tree: "01a30b15d800be77c5c959f57466a2c6dcf3e583010c1308a6956e23ec1b4658180140ead0f57ec26315bc14ac9a03ee843f34d080f41d2a682d824a02d73569446011000001d4d84c0e533c23813285e3849abff78ff36d2fc4b82c35061aed5e20a13c1859000191e51cd5f2f0afa0de7cd18fde39feb724bdc225fc25a9c75acbae1b641a7719016c33f322bc0205623943faa2a270b2925176cfc642da9625bd567e06b13c4d14000193726f6855f49bda4fb05a256bfcb17bf6ebac59b69ef9bfa73d69ac65ab2c2e01875259d77037ad0de128f071d2b85dfefd4d14c29e3fbd573abf843ebe5d830d0001d0c515cd513b49e397bf96d895a941aed4869ff2ff925939a34572c078dc16470121c1efd29f85680334050ee2a7e0d09fde474f90e573d85b7c9d337a5465625a0000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 693400 ..< 700000:
return WalletBirthday(
height: 693400,
hash: "0000000001708386101e361d211b2a14f3571d0b81f5962b452d563444c7f06a",
time: 1579101218,
tree: "0110939e236e3f13fbf9a044dc4e8d0094b777ee950dca49cb0722556b08fbef2f0197c4a6daa51f5c699ba5f0c3e53b657e54e3d728e60edaf76b4e2215d6aa2d661100000001ef66b21ca159b57a3d54147b0011c096d20cb3aa9590becf8f026c9edadba61a01750454b0edee9cc2f1eaf6d34cb8e495679048008d8cf6c1ab4321bddb828a2901f3dab23e140f2c400b4d4b5e6003ba2c7b316721b0d2858c8e0fcd1f5acbfd4b01eb786638efecd4413cfaadc48a0275035b2d484b92e305cb086c581a07390d21000001a4711f58e3fa6f5d38e2f54ab424c3014c119629fab5ee8a4ed2814d7b17036d01d0c515cd513b49e397bf96d895a941aed4869ff2ff925939a34572c078dc16470121c1efd29f85680334050ee2a7e0d09fde474f90e573d85b7c9d337a5465625a0000000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 700000 ..< 710000:
return WalletBirthday(
height: 700000,
hash: "0000000000c057d167a20ae61b1f77996bc72631dee6ffb11095f0d312230ddc",
time: 1579598443,
tree: "01c6b273aee226912526622b91e48a0ff5caf71f1f47569aff8a1c145102b02328012758ab750e1cb4f933ebca089d23ead6032151a38266aa020ae84557bb61844811016443e86acd06140aa932467bcc7235704cf95081e2e5faaf031112a9abd5f930016d1847eb52f8218773e3d2dd8eb19950dbe693484098d763010d7c338337cf68018117bb5e4ad68438572aaa55cb7d66b4b86b9d8310fbb4e36db7982dcc28591400012c4e84168b1c9a322f6035ddb5989fea843045d22182ee9ce45a6a8f6831954301abf6a411ff1708af6252bf921625f28931c567d92833d7ed2b2b14efd6b06e5001d1f934bce5476ef5d21b384c7dddfcbd8c1f630435acbf26a094bc46757f5d3501e6a69ddf114c92d39370a24e840c46ed42fc54a63986d3aa916a08c2a922c73b0001a626bb2ed07614f7228f79d5fbccf541699895842341602c639ab7516b1c9a1a0000019be74b905f0e99399af0fda6832324ceeeaf57551b11b42c73bcb7cd215ab91400000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 710000 ..< 720000:
return WalletBirthday(
height: 710000,
hash: "00000000003adcad055353d33a0962103e284bc47577c62580535a1dd6be7cf6",
time: 1580351806,
tree: "01bf61bd9326bba72206cc0ac82791fe316277907ba76773b5ae01ea7df948ae04001101200905d2485346e39f07fd989ba05211195251968d6bcb41b8280bc94733bc5d01e44932d89c5309ac906072235443f573a92dcda2acf608c1851af01dbeab19350000000001a73367559bf511fc5212ab3f0f6754a9b7ca59a3da68588e3763c801c031bd1501eb94b48e208bdbd42bb4815940b2f9f5187cc5e42c196f461f7bc6d020ed670f0001f00ddf03aca4e8c2620ff274939a1f1cd6a4eceb147e8aa6a8ba83717d60182700010576ef08575c3dd49296ba7c2ddd914715c4f9a7316da4ae8f5600dafa1b1c39019be74b905f0e99399af0fda6832324ceeeaf57551b11b42c73bcb7cd215ab91400000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 720000 ..< 730000:
return WalletBirthday(
height: 720000,
hash: "000000000225bab0e1491d6abfa4a41c174bc7d0167411e2cb2ebd960dae5158",
time: 1581104786,
tree: "0147c6af2c835328a4c17eff07f76102dc57716a13ce3d3a4f48367c3f2384fe2901e01e9b45be2ad8bedab63db1963c2b8d85e1ed20b6327cf2c55c211234e8a3351101134f80e61b548e384e87f823187d2734b07c516d48eea33a533c6cf7aa47052200000000000000017ce48111238d9e81b7e4147286578f2d686d71b1ec0cae668f567f3fef65bc0b017895f4c380f5169dcb84c7154fe6fcf72d694d30f0ba2535437b443a2cb5ae18000000013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 730000 ..< 735000:
return WalletBirthday(
height: 730000,
hash: "0000000002293b9e058e17fbc357c9b676d276eba338e033e357034c775ab320",
time: 1581858634,
tree: "019a59eba6efd060a61cde70daa7b34202e5fd55fcbf809eaf0aa3252e45810e48001101e106c6f8a17723af8793c1bd0f0e95dbcf5ef0bd80e20195422d8388db48cf24000001907e2c08367bfb45d196771ad267ec773c80ff4306aa7c4d2415ee22d211e90a00000001d72bda7061e4086bb885d6f26e39aa603a1f6db2e4fc71ae65a571c7a31ade27014df2a298ce5d7f8e88617b66ef7dc1fddd854e8dc623c3dc0faaa0eb93137d45017a48dab02dd9a014df0bd310657c3b8e854e24e1137f2ffcb1db693e38a4416d00011a5c078f7dd38704665b7270ebd90366fdd0edccdf284ca1f03c6d7e0536182800013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 735000 ..< 750000:
return WalletBirthday(
height: 735000,
hash: "00000000015c597fab53f58b9e1ededbe8bd83ca0203788e2039eceeb0d65ca6",
time: 1582235356,
tree: "0161f2ff97ff6ac6a90f9bce76c11710460f4944d8695aecc7dc99e34cad0131040011015325b185e23e82562db27817be996ffade9597181244f67efc40561aeb9dde1101daeffadc9e38f755bcb55a847a1278518a0ba4a2ef33b2fe01bbb3eb242ab0070000000000011c51f9077e3f7e28e8e337eaf4bb99b41acbc853a37dcc1e172467a1c919fe4100010bb1f55481b2268ef31997dc0fb6b48a530bc17870220f156d832326c433eb0a010b3768d3bf7868a67823e022f49be67982d0588e7041c498a756024750065a4a0001a9e1bf4bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 750000 ..< 775000:
return WalletBirthday(
height: 750000,
hash: "00000000028522f87172ecefd79b5f54547c8a756976585f29e4dc182a19c46a",
time: 1583365678,
tree: "01a069618d376feebdbf39030c254a1a3cb46d19369837e44b6ad9afb43763167300110000010c256f47b493d8d94dd5ad09a6829a0a5e346400430b222072583afad8ce847101b261be33d5db156d09fa73031e8f37b4fe4193d21c909e2c8e58d86c7e48690a016b4a7608e90189275f7bb8e70f525c333431ceaa8de9d5b119e66ce2faeb79290000017d730339d1d4bf490eda3c1fca77d7b8a769fff083318ec46a81404fef45f046013ad81619e96171627f27cd6e7755c4d8261dc7017a65753f06c6cf9a29af116201474991dfe7d598257dae28820c6058e389a897e232e737c90a5427e8f24e355e0163734115d47b641de26abf2cad5c4ac1cb438869fc91d50e66444980647aed24000000017d066851cc49b2ea0cf9fb6af00adbb1cc3a0b15cb02d39e0a66f031b2dc1f230001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 775000 ..< 800000:
return WalletBirthday(
height: 775000,
hash: "0000000001325ee365bb14184794c700485f4e40142678bba749a54ccbc91aaf",
time: 1585250621,
tree: "014f09c863f64727b7cada08271c34d1ea0ba728ad53ec979c25bcab5a902afd52001100000001a182b7bb8fd9e872892c872fc813b59bafc3b517e55a714ff7c4ae45870a1a4a00018133f585dd7c438f78ee970e97036a471897cd5cb8df897ca46b7f2ae6567b00019338310381f33bfdcfe40b56ca7aff105872e6284d2953c287891201e75a237201e99c0f7b97c5856efabcd2fb46ab456cf5d811c3c39aabbdbb40daa814bcad6701e97f12a640f75d28510cbb7d4cad99d46903017fa9caab9905c108ed13e3c62e00000001e07372caea187301a24f9dbbe3b6a8981bb4225b7f4b362b01000d4b0a0eb071011545fef7ddad5a52664dff5a73fbbb26c2cdf42aec9292349773079432d5bc46017d066851cc49b2ea0cf9fb6af00adbb1cc3a0b15cb02d39e0a66f031b2dc1f230001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 800000 ..< 820000:
return WalletBirthday(
height: 800000,
hash: "00000000013f1f4e5634e896ebdbe63dec115547c1480de0d83c64426f913c27",
time: 1587134100,
tree: "01a8689663d3c4ff2bb9aaeb7b75e66a7c68705d147bea9fe67cf7f1ffa9a071720011000196bff8c908d7015ad5df6bc5f5268a157da076c5d2ba63d222f0353c8810320100000001b0a0c048035d6f3f229bedadb2fb7688d03bc49062eae092666a8a55883afb0d000000013a365306be60039724201a594b84cb24ae09ea92a3077722da662289471f6658000184abf3f567f42573deb9e2ae56557fb6a763f16f90577ba5511b55c090eb6f2e00014da3714363acb83872f51c87fed3d42a1093420c3cb96b74ad65966ce27e8c4e0001e2bf698f5ac10b44da560d11a5e1d5c191a82a968a2be0a6948aa8748b54516001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 820000 ..< 830000:
return WalletBirthday(
height: 820000,
hash: "00000000001bde1cd7d26b21c7c0a4eccf3c16805c6e68f499398463fa91ed93",
time: 1588640783,
tree: "0127679ec6e5f7205bd7088782922da4afd0606bf5404faf74feeebe5f548d3639018f80d63358b79bdbdd5a19c6fe3c76e8542f6a1a309ed1dedad95fe3ca5016681101f1a4674cf60a7a56e52fde0a308481a4c9b77f059687b965dffcd67be7c4a83101ed990844ef4a7751262755367e6e16d5e351f190fca5f07124a8f71efee2cc1900000001e83b41c625d651681527f2a95ff2925b96f77c1311144e191da1a59303e39a4200000001f33bcadb822e6d55ba2fa044e2c790d957bc8dd7a6ea773d92114517a97ea76501e0b92e780e46114e308d615f417d051613215bc5974946a4b056013d6351f52401ae652143148288b1328e1b511803db03fbdf319ee20da5c7e49374331c525d3a0000011e76743978cad6dd5263d5a654db307368cb997b0c984ad51018d007c955972101e2bf698f5ac10b44da560d11a5e1d5c191a82a968a2be0a6948aa8748b54516001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 830000 ..< 840000:
return WalletBirthday(
height: 830000,
hash: "00000000013284f6e727ed7cb6365726a044e050d0009ca4bcfbc7bdcd80f319",
time: 1589394076,
tree: "01a6bcb9b2f15aaa3e69ca0c0688c18b8859d54c9d6388f4d5fce8f72a2bfd990d0011019bcf88f0f1cf6d4cee6b74231c9466cd13b5e5390d4e05fdb1e4f4143cdf7a4f000000000145e054aa42c1c6f9a70581e04b05a565c9e6e2faf8885e9b76afcd841228715d01a20db43a61e0bc593598bc42c7b10c31194385c8fb00543cab4d4756b3eaf9030000014bb574ca908dc46d48278d9f5039b7d93217ea00eb63f682321503fe5b42b03f0001d6bdb5e3f2e34961d6f337c416704b74d0df45349b7b50e30cfaebea4934db1b0001e3586da44e3b0d6a0776f967e86c9bb7542b070ce52a7baac5a8e2a564780743011e76743978cad6dd5263d5a654db307368cb997b0c984ad51018d007c955972101e2bf698f5ac10b44da560d11a5e1d5c191a82a968a2be0a6948aa8748b54516001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
)
case 840000 ..< 850000:
return WalletBirthday(
height: 840000,
hash: "00000000000a0b9a8753dfd46e1205590d35f4d365437a0d20d29317b33743c0",
time: 1590149064,
tree: "01101f7b8112735869abc0e74dac1f272935d09725ff03cd8cb63d472e112fa82a01d635e219273ade2859554e5191898ce9a79cb80f62c272dede1c2a71e183e21e120000000000000000000000000000000000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 850000 ..< 861500:
return WalletBirthday(
height: 850000,
hash: "00000000007b5c713129e71fc1496bcc321cd6cd3efec262c9fd73eb90695faa",
time: 1590901979,
tree: "015063008b28e034d7515616a1d975646927df30ac4f13d96ecf3f7ec1ddd49b26001201ff3ab46b9dedd6374a80ddcc746a63b05f9dacd6dbd21f7e0df00ec6df0156520157bfc70827a774ac00c13012ac96a984d75c54a15605d741f647923d531021420000014d624d2cd2908d1a438f4a70ac392ba151c7167095553556f23ca5612475224001b97205b2715b57b9f04451df4474c73586e8fc438f989b057cb83c24e7c80d5d0001d0ce3df812f137bfb07e56795014bfc66297491dde457df799406286d7287e1c0001a8e22e1a09d435fcf20b2599688e7094ca46d2c273ffcdfee0ee80eb3e1e4d2901e469171a108b4c837f17a8f67f4d02ff9688acc825d2e1ce1ad3f8b24ff1346c0001a8ee7010fb0075cf00f14f7541c57cd0e18167ac8b98c1b20454d3618715811a00000000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 861500 ..< 875000:
return WalletBirthday(
height: 861500,
hash: "0000000000f1525a1691846ed82b5bde1d68f5472a88cdb46e2614a0471c2bb1",
time: 1591768624,
tree: "014c3e4b358ad1a1095473984cb037f6b3a326e7c4d6243371b96d774be49d3b6c012f872ee6f08d4348ac8784a055ceca2003b5652956970110ab8ac34662056a6812000184579254ecf2242817a5372a6c93e695d520ba6994a1549722ef6a1e06c4c241018cbbc978565f1f0505facf3761bd072a9bcf0734c49dff1f0f8a40ac0b02ae0301cdac68e2a12c011704388b381617237292c4a219b56b358999f3cf2196fff53d00000001c2fd85c8cb0e8ff63eaa7722a58aa6fbc6298afaca10e3bd3131e6cdf4f3fd1101931ad087d1cd97f85debd36de84dd1f8b3147d82e7c21bf8f68d9b444fe2c86d0001e99fdf5156ce831cafc19295c3239f54727ee3c8e6a9383da5e99f0d37384c690125cc58b7c9dcf14d773e7291fd53fb94371be34ada296701fcda2d1fa903da1f000129505087ffb37278c6371e20c51c2c5dfecc8317f6b0a676137f84467c4ba621000000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 875000 ..< 900000:
return WalletBirthday(
height: 875000,
hash: "000000000001f4b0caae8da2eed537aedd4a76d8671fa668bad870995861296a",
time: 1592786164,
tree: "019e1115ee6526f412ae2f8185b6f1e41e1288daf1c6e4629c32a12e1880211f64001201fd273a938cd5f5fcf70a758fab2d852efd000db4b6b7a8da860e8e48a5fe7614000000000001ff7f557fdde5c41e043e2fa0160e3b8a7fc0331462d1cec6fff3db133e3dc64c01a71c9ce180b19137b80b28137bb5a393bbc26b4b807faf4d57984d1f98b7fa45017d8e8e44760406694aab9880152fcf2d71a0d3967fbf001b77cd9751d61e1924019cc66c08d0b19b5fd3d69f32be1e76096ceeb1b830532eea9ec8aeea5d91076b0001c93ef42efb351f52c49ee3280457d8de5a657015eb9e5a28c6b63c020c18de13000001166bb2e71749ab956e549119ce9099df3dbb053409ff89d0d86a17d5b02d015d0000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 900000 ..< 930000:
return WalletBirthday(
height: 900000,
hash: "0000000000d99076161c66dd3e86db9f9390921cc8b0ad7d6eface3a5d8ecb1c",
time: 1594669980,
tree: "0162267b975eb64d5e602e9bfa63c56b1326e8eab6fa971847f2d4f8f27d26f90101cc33a70cde4e4e5f5347034f44b503e8660c7380e596961ccab15d7a64044371120140d08a6c2958e7283c3e95053eeb3e5cf502d5857a961e107c8b37ae00dcb30700019f7e8cf60fb1b31d852d6786fe74078ff1cae30fd982ed2ee11176f96103622301d3f9f17d782359f08d500309ded4ddc1488c86906f3bd742aa95b8de0f189524000001b64361426e35478691ef23c34cf977afab4962c0d7d1998b08ccac635149524201a73426649efdd3a6bda5f8a253a4823f8558dc16d8042ba071f13c0575a3955d0181e81df06e97ade7989e0ce8790f75f1d34e6cfeb4347205c4aaa7adf90a180e0001ecd87912a28cfbe4f34bf57bad9827e4013d8d4c8e85c48bfdd06c35eade9920010d393867f4f2bebf9f603bf827dd015aaf3a46dfa8b68d86cdce07aa4fbb97240001d3ddf137881180d7c5fd73d188c4346291168bde688643855eb3cd5f680f9c0001166bb2e71749ab956e549119ce9099df3dbb053409ff89d0d86a17d5b02d015d0000011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 930000 ..< 940000:
return WalletBirthday(
height: 930000,
hash: "0000000000a5b606b5e99c3f155158993395d4b624e0ead68bdb3130fea8c720",
time: 1596931609,
tree: "012ee9cbe55d438e5fdf9fa2df34a989514d038fc50d5913303221392dc3b33257014c2cabd5f58b23406cbcde4034d5b62c3023f30ea9a0ea5ffafb66fb7e4f000e120116683075450cb081d897a78d86224019865ce7e3ead189e74286be307f43ac5c00000001b9da9a7344e04ad7be9cfbc57c89e840703264f5692060a5ea4f7c2e201f5e42000001a3db46e41c1c7e1026ee8b49b9a148f53b00a9c728f72b996c2dc8fafbe4cb2c0001bc597d37e5f726d22ddbe544885571ac89f5fc1746c3e7e198d0bbe85b77196a011439e56aa582ec419f2a0004222be95ea1762876ea33912c5830ab4e8bdc02660163a8ebc9ee4b289becb230ef62829a8c8b4820fcd11409f0b4c849190155a65f00000001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 940000 ..< 950000:
return WalletBirthday(
height: 940000,
hash: "00000000004f3d5203454e18248bc021a2afa1a30b6517f34cd9187f2b8e2489",
time: 1597685856,
tree: "01dd59466cdc00ee8ceb305d15c25ef32aa2d96b7e4536e071c1d14e67aee9ee0b001200000001defc97883745ef01fbca65d4e5c0f8e22b7714b704a1c36fe8a851fdbfe3a1160178cf44f19dda025a44490dd37b96b83758d04cfa3b26476e129173e7c70cb103000167b3485f4aefed9426fc301de1138fedf6949fc806c54acc2b86d897cb6a2041000000000103e2fcbb87cd5fb954d55d094943fbac487ecda1384a8fa7dbf61097a9755e54014104c9c36ff1a2e7eda524840463de4e2c02f10412a33dd754564d76f458c525000001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 940000 ..< 950000:
return WalletBirthday(
height: 950000,
hash: "00000000016bed6cb8b8c2c09791cee821093484fd9ba0f3faad1e78e0d21c17",
time: 1598439138,
tree: "018b0ff026a6c3d70e5592d7b42fa829ec41c5a86faa2d12cbbcdf81e039cbee5301f4decddef8e3183dac4de8d1b9aa3918d7df9293aae3c1931f99a253149fb65312019066138ebf0e6cfefbe9cd7876aada7d3f27834d604f827b56b7a56e1a7b551d0000018d080dcdf356c41f5a86d2062ca9e617965faae9b9a7ea678d3799f526a353130001a5ba52f3a03ce38d7d48afc3d2c9e6d65e90dba09b53ad3d3a5921267375de5d016b84dd3e9242073d7069f797bc81a4ccbe0d3847a3b3b4d1376d9e6d61446605015d52a3c83f77ec5c8e823143e74569c0040e1cb58d2a170ce907ae010ba29c670001be5b81f3b1b8a035bd0894392b0b78bdae4c57f206d3875b933de545f65bd93b000000018e1d474609c9c09894638a0ab3e656aadccaf7ddf12bcc6b6ece44a4cc79e1140001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 951700 ..< 960000:
return WalletBirthday(
height: 951700,
hash: "0000000000e304a23ddbddd62d5fcd7e6b236afe22e529f1ba88f4dfffce432f",
time: 1598567019,
tree: "0154365cc76299ab7ddc51a9fe6fd63babdcbcafbe6d7b293c43493e4ee4dcaa2501fcbde4337c2a268da9e63035ea372706af6c3be6a7dca7ddb39e9f2293835f381201e7134cc658434206a1fc059bec482c4ea3abdb49f51f367dcfc6c854deb573410001e6dfa615206e90b438eedc5cb42ab5b8a1444ed442581f45813fd1a810cf246e000001f8a3271cd56cf8cb3b01b446cfd1e7afeab070a1d7a356da16858ff2d1636b4d01de38353596f623ce0028520063828e4720bfb4ecfcc3fc103d78fc0cbe7af64200000001064fdef5644d3f4f27cd28df0d3b8103c4822871e2883bc09dcf419f1444c85a0000018e1d474609c9c09894638a0ab3e656aadccaf7ddf12bcc6b6ece44a4cc79e1140001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 960000 ..< 970000:
return WalletBirthday(
height: 960000,
hash: "0000000000b5b5e0ba1c01f76b8105878ea3c2f11da53cb0ec684f5d94365421",
time: 1599193083,
tree: "014695c74583a750216dbc0aec38282d86fc17b595bb45a74bbee8fdbf46b5313e01c2253474715b00c618e635815bd16fb8e6368fdaa9bf8f4a1aca34ead6a7eb1c12000000010cf46f452fc9101af9ca34ae364a1c2e20bc05d454068cf1407a2ee3e0c9ca6700000001091c0b4153defbfad723bf14e1ccd07c0258ea1fcd6e9e8cf759834112ec3036000001c2c980c0777874ce748ca549838324eb775cb2ac7a8d42793edbb05ac15c5b4201162d1417d8b9659ec93ac26ba1a888719a43ab1fe0b46a33c05c2aa55fecb41b00018e1d474609c9c09894638a0ab3e656aadccaf7ddf12bcc6b6ece44a4cc79e1140001f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 970000 ..< 980000:
return WalletBirthday(
height: 970000,
hash: "0000000001dca1d101526285476ddf0eef6d238d5b01b7fae8062edfc09812c3",
time: 1599946198,
tree: "01d9e6147caab719ae68cb20d976c78437634e2c999ef3a09c6ba35086d443703d00120001019d135be7b1db088c68bd76703ec2b45066bb1761619745362e61dcf55f644601d0c8f296479a73722c2e2a260ab7017b9a9e6d084b651289cfe6d3c7a00ff54e01f853ab39dbfc81e2aabefd231d3374ff794028168c725ad465e61205692fef4b014f13b6e4475cbd004b4d95aa8205ed7338224e13627ecbb19afd1937dcbc0818000185b4f1ddee3199cd1f7913b223c01c4623cd9d0e1b47df4e36aaca7717b6331f011d6c8ec914cc312ef0962d52240308b22a647f4cbd2d7c2fd420ad5fbcae5619011e43cbb05b8efc885531367e5f611fe7ce7514131be892cce3adad02e151f72b01f0d7e0d589c7e5f8fff0bdd5037aeb5d5d818d413262758c9915ded705e40f70000101d26ff60e77e23fb86a52da565c22d76f81df7f25d543ec0e58a0d692d4be2700000110b2bfd32a99e0b982a41a6dbaebf783bdb9d6af795f5f20056ce7317d15ce1101f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 980000 ..< 998500:
return WalletBirthday(
height: 980000,
hash: "00000000005de60d31b653cdf1637f1bad62af844c6c51f38557a4e8bb74e2d7",
time: 1600700163,
tree: "0184330bda72e9596256847a9597d7d9476aa3d69d9dad2149314751e708da206601cd8a1a61df1e80514cd2c0a7faac8b8d7ce27d6d96bb63cb7c61c1f33e7c654312014098788b75f26108d93f0429202ffffb6cf9ffffd7278383e4d8ad2af642264600011c035ed934a11c1b48e24b6be9b2d483e7747dd082f06abf75f9a092b34cd33c01be00394a99bd33304fc4343cd928857ae7c09c176452f40d9815f9ff3ba3865d013bd7218072e1588aea0568198d37e0d83ba75f155c863355974c4eb864de0103019ed27335bc5452e320ec22a30cfe61508929016157ff2a555181a9a0623e725801328208bea2c5c83487effab780cdb36b4b82e6e7290b06d98817a160f3d79d2800019ed6779a1724a107807baf4dda9481fb940f50d85db701dda43a0989c2d62535000001d1e806194dbe171d4ad1ef8c73c1a469130caced0e24b04b8acef91c42be7a56000107771e04f7d6371bfda40ef9e04419a25c6563dcd359c85bd501de28c3c7f3250110b2bfd32a99e0b982a41a6dbaebf783bdb9d6af795f5f20056ce7317d15ce1101f1c57245fff8dbc2d3efe5a0953eafdedeb06e18a3ad4f1e4042ee76623f803200011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 998500 ..< 1000000:
return WalletBirthday(
height: 998500,
hash: "00000000014cf0915c4f105140e846c62ca6f2e321f4f717cf6762a35c6e8eb4",
time: 1602093677,
tree: "01b86ad8964b68a9a316a3038af14ac9e557a6eed614ee5d337c9fdb8887e9dc6001b71fbc815cc014a7f68648fcad5b9b72920b3d21cce406b5f593a0eab6d91f1212000001aede58c0641825b7531a8b296b9fdc7393090b87588893e8dd5160bd59b2e16300000000014fa30e43b641cf67c84cef81083b81bec3bd677f55def5c7bd948298e64690560134ac55ded091faef2ae8a1043704dfec41b1a95c4cedf1818574752bc40f2033000103ee02ae59c6688dcaadf1c4ff95e7b1a902837e4989a4c4994dce7dac6ecb20014ff8c0fe6bce02ac4ad684996bfa931d61c724015d797642819361d611ebd61201c7ae83949d9502b0eff10618124d335f046e4aae52c19ccad5567feceb342a5200000001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1000000 ..< 1010000:
return WalletBirthday(
height: 1000000,
hash: "000000000062eff9ae053020017bfef24e521a2704c5ec9ead2a4608ac70fc7a",
time: 1602206541,
tree: "01a4d1f92e2c051e039ca80b14a86d35c755d88ff9856a3c562da4ed14f77f5d0e0012000001f1ff712c8269b7eb11df56b23f8263d59bc4bb2bbc449973e1c85f399c433a0401e0e8b56e5d56de16c173d83c2d96d4e2f94ce0cbd323a53434c647deff020c08000129acf59ead19b76e487e47cf1d100e953acedc62afa6b384f91a620321b1585300018179961f79f609e6759032f3466067548244c3fe0bf31d275d1b6595bb2d486401b622d3f80d8231c44483faa2a27e96e06a2e08d099b26d15828e8f0bde0bd42001a8d1f585aeceb5c3f22ffb43014fe89db9f7efc080361d4fa4e8d596ab1224400103ee02ae59c6688dcaadf1c4ff95e7b1a902837e4989a4c4994dce7dac6ecb20014ff8c0fe6bce02ac4ad684996bfa931d61c724015d797642819361d611ebd61201c7ae83949d9502b0eff10618124d335f046e4aae52c19ccad5567feceb342a5200000001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1010000 ..< 1020000:
return WalletBirthday(
height: 1010000,
hash: "0000000000faa7ec382bf9c0c1abae839f663834f8f307a2141b1403bc85fcbb",
time: 1602960322,
tree: "01f89aad9f6ed7532fc8866580ad425ba2a63ade58b064be8448804ccf9a60fd68001201dd7166b177a37db095801301de34572e69cf151db80201ee08d677c8a1a7986f000001d30d2ef05fd6f29519da13f09623f440c0f8dcc8154c56dc7f881c77c3504f2201b3ae640c5770b95f68aa24c57c32c01713e450c63b1bc5535ebc81ef2a26b519018611a216a563b1cf44cb1b27821c076869676b7b341a5b4f2cef10e8896a364101091d319cbcb2ed9b4caef347a32268ca70012899b85cf438ecf4bd6d6700c04e01337e6de0bdb259c3bd864fec2617a2cd9e127a7e6ba4212a1a7b9ae8c65e2d1c01121f952ffbab89fac050c927d06f855f8baa39ceb1584a5144c32b45d6bbe35a0110188995758e67a4c8a9e71aaecc9a7bc94e085d189252b385eab74587424e5c0000011ed4073019f93951e17d7e19f48d922bb6f3a9aa1a4827e619e0ae791c9539240128e88325aeb1eaae03e9085f4128fb62f367aaf4a6340dadffe427c1d66aa445000001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1020000 ..< 1030000:
return WalletBirthday(
height: 1020000,
hash: "0000000000c3c4887bd6f5d3cbf9030914e6d1bdd51370ade6657e831d9e3377",
time: 1603714448,
tree: "014f6722b03c84e99cb0f198c604fec8c1c395fa726f403e239a66b124d4ee2f7200120001d6920ed4fa9340ece9cc4918f8b5aba3b0ebc5be16831e7d56e6acc93a7e73110001c6cc38510b51ef7ef6dfd1d48df4ef97de8a52f19a9964ecb53301de1057760d018c66fe955d1c4a7dbeae31896dda4cc0bc7824abdea432101fed279a628f5a4f000001935ddd089f29e35bd356a176191995f91239127eb93bff018a3447f80615a05100000182e624e6852072075532264ac2cc76bcc92327ce55e1dd464817d4c6b9637a6e018d5dcc90c3e7134891d77aee71063b8d542b337e4d43f55f0db9cef746f5a732000001bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1030000 ..< 1040000:
return WalletBirthday(
height: 1030000,
hash: "000000000216b8552281f6b73332ec873e0eb062f9b83ede4f3102af78446b7c",
time: 1604467637,
tree: "016f037481382b438c1a41d74153ee8a6131db5a9fcfa2526718e7b4fa1577e658001201622ea365daf3d6cbd5b712bb33b77764708d69f852b903f053c47569cabd930a0001e2175829e38f95f1b3415bdaa796a732d83da1b137e1b0aecfa9802b8c8e9a540001c783c98897bc46693d1d2d2891489663f0d9ff12b34f28b3db5a841236d9d76501d671aaba2921e416e7b7b81a89cb8e524cb6c49d89c575e04e0da0461799216f0001ba538b78350bfeae6538bfac75fe8709eb59bb72f6d74d64c92df41ac1e464560001ef2204037f952a1365afd291acf2361dcebda719b5e659de073ebe2f7f3eae1a01264c173c66e9b7c36ac9f7a6c928600107fa40f11b8d81862464f849885c50620189c3e3ed72b0d445f043e2d2d5ec23c693ef67b9a15488911ad35480a6041c6301f7f497a2f9ded8bb6d14d9f1bb83f43396270e1fc7e86c2c789d9b74b9d2d3070001bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1040000 ..< 1050000:
return WalletBirthday(
height: 1040000,
hash: "0000000000852680280d876e4870ca18242527eb247994047dfd4b2601fb1fd1",
time: 1605220381,
tree: "01d4ad84ae2c7072a2632e767ef7d38d6adb125d76b2780d0dc32eb607bf839b3a0012000001677d02da42c17e72416ef72a07d165a142d3ab2d1363b07219c44b220bc58843000001035218b5415347549dd0315585ee95b8b1f811d81aca93a551478e3b04d0a527015df8455e3415c857ca94d357d48e093391715644afcfec96656b0b33bbc8592e0001d722471e81e674f55400ad26e5730a88e4a63138cc741c0aa40961ec9ce8076e000001c4d6088cf30ed54a892b82679f9531247c8dcefd1501d47f45bc35095af2e7070001347a0b5c418e301923ccc684d984b80b8ac1f52888b6d6021f7fe3676eafda1201bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1050000 ..< 1060000:
return WalletBirthday(
height: 1050000,
hash: "000000000174c1aa6e70950d51e574311da9fe75b0ba66c38785c8934a00ad3d",
time: 1605974807,
tree: "019c0533c31d2d90c2ac6d8c9193bc9d57cb77ac24993a93202dd97ee8586dac72017ba6e3eae1efa5fec05a764fac9bd552caeba096e73840c4d6d71a46f3ca0f6b12016388275ca6bed5564c68f57c17aaa50e209a900b8f257b60c7e548d39946dc160000014d6580e971d6502e2ef9278cd5527f07c96ce26548d8e13e290708e517e6a40c0000000150d24a2ea34b9eeac3f79051e6ee9dbb8c482083a57ef1b1ccf5a1f164a00547000191cbb6ea3483a6a60f6598710cb210392b7469be8f650c7ea4491965e51fa51b01f0aa6de369775a9747bf7d5f034ee6a7604437f497ca45df942a45c53a99e93e0001e2aeb2d8da652922c8714924c41335140a40bd1c966dc611a9d88058839a881901347a0b5c418e301923ccc684d984b80b8ac1f52888b6d6021f7fe3676eafda1201bde7578541c07920c1bc94312596adfcee32519cb80a95bcd06a1272c127ff020001b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1060000 ..< 1070000:
return WalletBirthday(
height: 1060000,
hash: "0000000002a74e26908b2caab798d341430d83a012aefb113d9707acd6eb5162",
time: 1606729750,
tree: "014dccd8971611a03b3698c14e48f76d2526109374c0336a4aa0c0559567fafe0a01f0875252b1ec66c1835e362c19ec570b02b47c5a284477adc599f4868535370812018c94b59acb73c782a3b3b2d9c46babb6f6ef03e413b5816794518b839bb8d360011061c3e44c652e1ba70b85886fada65fc781b202335715489e21ebd64de8d92e01af2d971d01ebf43d4f1b99f500fe0a97e2068bf1ee03ac6e309316e7be88f221000143b8807fdc7a87ce8623370eeef95140aaf315c9e9df7bbf64a4faf34f4ba213000000011fe71b62cc883a426b1b623e3df4c91cae8de566fdc9a746253d6350bc48451c0001e15174bb37ccc2ad5cba5f9f879d459bec83e975afe6304d23980c0ab87fa34a0000000001891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1070000 ..< 1080000:
return WalletBirthday(
height: 1080000,
hash: "0000000001a6faf5681b8565d50145fd84547b534c5f869e77cb802518d14341",
time: 1608237278,
tree: "01f3955ce270f5718bf68883ed37b3b9d2de8fd77be7bd95334fbedc6083f16026001200000001bd5dd7584bc157cebc9d63c7ee761ab453892482246aae3ef9db17de80b84a4b000195fa995a764f9afbd6c14984dbc72175f49f2259bcf0abc4a82ac92446532c44000168fb4180546c77370ff4175d40a29c357e5787f820e383028243ba623fce4e61017cd28108a3c64a8923444af9b7409eb5dda47d8536cf5aafc80abf62e9551b3501fc0832fb90a473de0da1ae7f62b03d547655aa82d1f279c5ab5a997d6472085901647f2444d093ad8668eac738fe0ff6b59b8191bcbc13dc53f581e64de755122a000101e8d7f1b32b8bc1ec539b93f6c2912c839a55c36c509711340a5cf6d1803a360103bcde16c3ed62026afcdeb7c33c7aae0bbaaa357e8d67a10457244bdacabf4f0001891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1080000 ..< 1090000:
return WalletBirthday(
height: 1070000,
hash: "0000000000e69217b151ca8349e3c9f0c5406877554924d7a4f90fb6434bed9d",
time: 1607482606,
tree: "01ea25320fb5dffce1469a9018d2dbcd02bc16350761c1b24ef1f7c282ff3e70070179ccaff1ff2218010dfdb5e7cd8ab67c27c0f578fc94133fa2db58cba2a1b83112013d996c5be4fa4e5d75fb2f782f02dbaec8582a86a4a404397c2ed5bbb75b1660000153c736227e8f11677599ac536a2d19a2000035609833788b19062cbe075ea20200011a38e1599c81fa7039f159cee2ef7144f23c729ac1d235d1d81ea111ba1c8e520000000001aeda840e11db19f50b7b64c54de8a389e84a5e64e8c3ea8f4861503f587d9b2301802a64566b4a1fa471e350bd86ef0409f6b4712a8fdede1c537347f41506884100000103bcde16c3ed62026afcdeb7c33c7aae0bbaaa357e8d67a10457244bdacabf4f0001891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1090000 ..< 1100000:
return WalletBirthday(
height: 1090000,
hash: "0000000000a48d9a9ec16a0ee42afba830507824086335e81290a55dfbbe0a0b",
time: 1608990684,
tree: "01bba893b54492e05be51cc957d99591f60e3c30b7bbc134f4a79e1219721d023901ed7c0412fd24ccb7919323fbfe9af815adcc0c4e29e581d5e10cf06ebc5af823120001f98603677f74513affc6586569aa76c60766b4249a25118ddcefef18698a2c6300000001dd255f2e4e75b7eef0d5b4c077025792a979fbe44e4b7fde9a1273a3c4d6450401aaf59d640c3cd74fd1cb67396250e4b536de1d300a3c17783ecfcb5ddeec9d3a0001d94a0cf0b8ea2f688b1e107cf6a013747f5f0af6543552291adda1c28668da6b0001ab131afe01856dc81300246b7df2fdc556fcf764cb3bdeea33e83507b706a0420000000185555efbf4f751c9c4a7068f9c1c3303bc33bc8bbd3847a6fa5b6d5b3d547f6101891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1100000 ..< 1110000:
return WalletBirthday(
height: 1100000,
hash: "00000000022262ee215e5b6269cf159b4c9fb89b8a38f70873dde8dbc4c64669",
time: 1609745782,
tree: "012f5514d9c08767fcc3c8c2cb6d7e00cb68ff2eb69ccc869821f3c901a495fb5c0121aab76f6b245f76d9a89c82a5ba88c6b427bf0154f1689520e8a24fefba106812000001c2965bb8fd73128357ae46fd0451ff0d34a4b391a4a7d54c8d00dc00277b5b2c0001bb34e1eb64d2bad151a251de23fe7ab0d92c0d8125fb3c3aa8ce0a772ac1f83701c45242a1ce86ebb47c2abe6ef76f814b26f56b5883e5f0c520266563633e5d5600015b9ea4977075a83dad3e5e4547f93369f81807b960fa5d0377fea025dc47fd25000000000001103bcd926a1c140a15876ce5dd6bb4e0a32172f9fde5de340bd11fdd87d696670185555efbf4f751c9c4a7068f9c1c3303bc33bc8bbd3847a6fa5b6d5b3d547f6101891b1e6bfec42e97c79ec505c7ae1b584cf47d4ed8f6cdfcad815b02a5496f6701b7fc5791e3650729b7e1e38ee8c4ea9da612a07b4bf412cefaffbab7ac74c547011323ddf890bfd7b94fc609b0d191982cb426b8bf4d900d04709a8b9cb1a27625"
)
case 1110000 ..< 1120000:
return WalletBirthday(
height: 1110000,
hash: "00000000019dd5701deda91aee19f653d7d89983fec6253d5728b738ce1cc575",
time: 1610499871,
tree: "017f230e3a91ab56970595bc9037a6bb38b69390070076c46f9a3d364f96171701001300011ebe10c1b67824d2b71e48010a03f817d80963999e15e3b0364eeccac01e2e70011681651b3c5fe38d3c35445560b9a4599f9370e618c1e72f2b8a69efd47fc9720001ec4a3829e823478478cc46af80d6d4c6b947b422dea6b525b18986dde5698a370001b52370947e83349c731edf7c5ef43dc7f9b14ca47074dee8fd16b14c5663fe4a0001d5b32170d5ffab2c95ac01821260f970881c8a3fb5770aeac7739490135e152f0000000000000000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1120000 ..< 1130000:
return WalletBirthday(
height: 1120000,
hash: "0000000000dcdf40c671af85eec40424e0475fecb06355fb5e37efda51f5dee7",
time: 1611253575,
tree: "01da06acb487d1ceaf8db4dc5ad8183bc8b4e9a4b020188336624bcd83adb7884f0013000000000187183a83d396d7d50514a081195ee24703202e0ec9e3196eb3bdef5e34354548000001d446400bb7cf59eac909c183eb8685cf6cc4517496708ad2bffd07acc46ce524000001e240979184856d63a9bbf849eaf06963acfc861af5a44a30e82193792d58fb4100019498b9b148ee924288e2225a474f2c9a7739500cb3c4821a52679f6a0a26d41000000000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1130000 ..< 1140000:
return WalletBirthday(
height: 1130000,
hash: "000000000009bcbe15ce9e005c9ebda0a1c5213b9573ad29c3a86a1a9f3f6586",
time: 1612007546,
tree: "01cdb094138ff68752216908f08ac0978b612b5b928b1613ec79275071f1c968710013011f9339db47ecf1f7510683dc263074e79825ffb487fccdf81a9f4c748024024600012695a02e2d0d49c3cff6192b46d4c4cacbb86bbd4cd88b6bf65564070bea0f20000195556413de9fadd73e9d5ef1cfb905a021dfea4ffa2f1cb6204438c60d665b5b01c1125574436b79f9fc6364ec470f453570fe7ad0e313878b809a525224166d580199820bae76e624f5c06b7f744e6a6ed57dc03314e91aefd883648c7fe0ff1370014576446ae9961962903fbcd41c9d7ff2d8c41b77244ff39e2f1233286f95301001df16b424017aef9e9138169b7e183c2613ca6ebf9680fd27c9c280c194d0772f000001fd3610fa060d8eca861a55d6bf0042b7e11d67bdac285b4677c995f2b466276101e5f0a7191091bc4ea3b06cc6cef4644b426122d74b91cbece497f7bdaa19526401226d7b2448f34416550c5aa0730c58f1eb72ee60cb9e9d61bd66c81d31b5ef51000000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1140000 ..< 1150000:
return WalletBirthday(
height: 1140000,
hash: "00000000006d9c69d8c4d7818dd2b9b106078317c6e881eab86ba41e4a546337",
time: 1612761940,
tree: "012afd078f200a60fe586c8ebb81208bc6b656f2c24935ed9ae483606368c6101c001301e0a84c415504116132c953c1885150a6335bc3293aa17c89626e02406f944f39000000017c0a218b969475ad665bfdea14177bd73b8510d451bd1f533f29d5f86f92a14201faee45bdbbec94f64fd8b641b3e2c1c473880b14a86134d766b9ffae127f0506014815011726d11513734103e47971902e4e8c1245ab2b96107184f2978a13cb2501eecd48ee70785ed9d31c4edb6da31287fe1b42082466c787262133017fe3ab210183352b54c9e84bed4c1fb4c31dc1bf690e88aec9f477f6e00d51a4bc918cba32018b702b3a1bb47c1455d5ca00cdb6d2eb72256f421937dee7d5453e7108c8df3a00017c41a5948f315986b60909e07a15c2639fb1b13a968aaf322d654aa1e823f60b00000116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1150000 ..< 1155000:
return WalletBirthday(
height: 1150000,
hash: "00000000012e01251034b1cf6ced448544f350f023280e3118cb23863affbb58",
time: 1613515993,
tree: "01a4948b191c1169242c0dfd9c287ce1ad06a681615ec99620fa5936bb05119d3000130001e9eb3a657f63031a386c64296e66b98374a0d74280132543535eb82180a5706801e0807fba775afd5acc8714c1c33ac709faee472841c3874ad477e57a01a01a4c0000000001dd716f606210678f0ce78fa535ba46a5cd1d0f22f7b237491e0136e71e51916400012278350ab0e251df819aa820ab100a1264bf5aa73c94bf5968730fa61668996001430989441afaafa2f64683ff0424b12b5051763ff094a88a4cc96cd00f09b8650113625bb6dc4092d25f906a05fd3e2f1a7c5df03381d0e0760aebc2ad0ecf0f0b01582a57901af4736388425e1bd26fff5b23fe6c74d10b1fd7145c46e57eeed609000116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1153000 ..< 1160000:
return WalletBirthday(
height: 1153000,
hash: "0000000001d06618d059c2c1d9a0dde0369cac8af75c9520409715f2a766b259",
time: 1613742458,
tree: "017aa8d47888728be9104e9dee586acf733b86fb244c4d9abd4b23d3b8f15b5d0b0111cf472e9ddd29f30ad95cf4f0fb7e587cc589735cfc9ec5a36a11e7d3394c711301fb9760d76283fc1af4195cf7d08a1f661cd20ca5201585451e877af846aeb6010000000001dc7dabd7bcce76a04412dbc9ef145d3d10eda33b5f644738c51286e84112c00b014d1745efddec53a2c5f23adc231decbec7a03c72ab4fed682d0affaf29584403018f8c345bf75a7efb9521dfc3cd6192b05b01702fc9a88f9be949a92d9f429f6a017b5ccbfa88f3523ed78b79f0cd86b883a096fb9b829c2a13000c8dee9ac9c72c01deeb9380b9491c7e7d59075ad35b8c8b748ba7d0337a273c3ce2a4e4179c9a2000000001bf57fd5f3e010a317aae249ee1c4583acc2688c9c22f84710f0173cab1f151560116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1160000 ..< 1170000:
return WalletBirthday(
height: 1153000,
hash: "0000000001a7bb6c535053418e8e9e1620c3e5611eebcb15218a0584754e8980",
time: 1614269669,
tree: "01ab89bc17a2fae59a5170033dea2302d8825a71a0e3fdb1a01d50c44fae59cf2a00130113607db0515d576fdaa165b61e9bbebf997bbf039ceb75aa04ccb3dffe492e5f000129140c523912d51834243412016078da091020f5c02bd498cba160342d20b92101f842c5a07a703b080c4d73cfa95460265b10bbb6c7dd5ba4cc50c7e24c4f380e0000000171df72fb201bb6c7f4fb3c9e06ac94ce0eb0f8c0259719d071587c3e5a74e00b00017010f179ca3f1dbb0865b00a418114dbdd67e031e430ee1bbea1b30081f14236016068bc4c06705014dae9c2a5f86f6734b08e39fb4ebd21366531dd93c0d0561d013ecba16781a5b5f4837c648de2a32f96c3d635a3b9e3630dc1bd1b1f4276be170001bf57fd5f3e010a317aae249ee1c4583acc2688c9c22f84710f0173cab1f151560116316e325ad5299b583121e42838f9cb432a88a7042cfeca8d36f8f5e86e234f0000000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1170000 ..< 1180000:
return WalletBirthday(
height: 1170000,
hash: "0000000001225d341f424c445c71b13872ff89300210594f3d9d405ead56f539",
time: 1615024297,
tree: "019968e9b4725455dea88d986b33458d199353a26f1349abbe7f39c3d72f82365701abcab1e8db711ee75949326fa6a0ad302776ff40036cfb4c1c770ea430a1af51130001352edbeb2884d8ed1f39c18125493783d76f495a88fdb32c7e5d7e61de1cfd7001b6966af9deaf4512b7922f65ad099fd11f1c3d34d80c93bf4e6d9aec18686d5201727534576ffd6b0cd7146d0e3516b3c9836e9ba5965e35b35033a3add146254901851e9189feb9e5f62c2df5049c930d0438083c86958cd179543156ada7da910f01392e342052ef08587ebf642bda8e3948b437b915a5d1856d59ced86d9e640a5e01199e767f23a7d41044303fe914e98c9b059b9ce0b85b37b7fa26e43d4fb5b72d000000000000000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1180000 ..< 1190000:
return WalletBirthday(
height: 1180000,
hash: "0000000000521c0d55ce1765092caff595acb5d546147b192fa9272051f55f42",
time: 1615778593,
tree: "0102a70ba9e31d6c24be0fc283577072d815d418da5e1b14cc81923f7bed308460016d9d5c674c15bdaec54c70d528e94be910994213683e3aac2fc94092fd8b4a5b1301dce7f293aee6c2769fe616dd47d46e79b51568c8bc08c67198b20d28eaf12c6f000001ff83e392690a332103433465b2034df2ab6cf35c164149a3951bf0d2bcf2a96601d019ed97502d718643c32851eb1acf6307861a3fe0ce3174697b0c2df4568568011d8eb058dd0a73a4314e04f12a6de50dd18879ee891db5a20c890e1c707f6f01000001cda4d5ff76022119fed8ffb94b8d3a26a0db37a1a886a0f31a57d1c0ce03f106014fb59c2d5dd4cc176d226c57b48d4dfc4d200088d5b69cce675f84e885ee5c1b017d5b561bf80be788ebf12e901e4c544cad95e24d0b21e6145e1718ec9dbfe91101678fbb171e5715c63bfc888d345e755c69c6dbfc2818f05b6e6ca32211ffd44400000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1190000 ..< 1200000:
return WalletBirthday(
height: 1190000,
hash: "00000000019caeb64ab8caa12e1dcdd9a8f391b063ec252887c91526b7ac5e0c",
time: 1616531745,
tree: "017ae2fbedf5cad68ee80df0ae9caef9e0168914780bfd14eae016e2fb89068071001301c78a8f9bfddd9a1f0076048c48d1d58298ac6f4368472a39b0b240d540117c4301b58c9284084704437af784307ab0a334dc9c7aef588bf7d26491274d79c4471301b0af0fff110293b555f17d5ced0a598693ff4cde3e680d988c6ccf498846753e01bb9d0f21f621448c03ee49de4ef3bf0faa4844544f9668197ef5921164d2401601a15d695922c5441e80aa770861f91a97dd460561515d32c9d06bd3c6f98ce26f000000014a772e6ce520bcedf07793ded6148fd3415ecbdd89c3efe183b6048f1fb4791c0001e281c5ec71bc1a301ad0d285f6f1aa2552907645b02f9d43160f5354c2be7c63012b4d8d83df48c8b5c35752268eb71a428aa05103809a887fb36519dedbc8de27017b610946256293c523b36cf95ec60f2c346d866d98d1276bbaba22e46815516d000001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1200000 ..< 1206000:
return WalletBirthday(
height: 1200000,
hash: "0000000000347d5011108fdcf667c93e622e8635c94e586556898e41db18d192",
time: 1617285467,
tree: "01dcc15a1314130c3ae61401ea76c0c1b32b0c44d8486fb6cb8764af9f6dc03d540132d6897fe6cbc340c786a129e69aaac499ba9ae33cebc0ae6163d02dd15db4061300000000011b153a8182d97d204f5ddf0cdbe66543d67ef3b25dac5602987d4dcb57f35c260001a3d62e7611681256eb34d5945fbbc085ccf1d04d6a507295c3c9724f6e899069017fd5efaf2ba1e3c53b0039674b6667e401c83834d53b0970c7ff3a6dad684a540001c77d47e4819c69c3a473b8e4c660bc73c2a4fc0a067e5ad21c6fba9aa031c96e00013729a1708bbe29fcd683e3e3337e8b8ded4fa6abb24cb7bef506168be7fe8a5b0001df26abb60966dedb257d90ef08aa7232474229e08e62ba390336a07c4775a7260001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1206000 ..< 1217000:
return WalletBirthday(
height: 1206000,
hash: "000000000078454a0d74d2df9ae2ca53ee37bfa21ba5d761a96dc426eb3603b8",
time: 1617738149,
tree: "01f423310ab6f632a457f8b91f6c16ba6a0c2b49297f54462e5588d1eb6aaaa0200147dbb8e70cbf50002af16e9e75ebd32c1e5f3f66b43e88001965be754ea82a3e13000001cb1695d6e381645c49c9706709438c8a40cb667b7eabbce3669f293d2738e24d00012a8f5a54b81bb34bbf0a8e8bbff5217f17a423bd379ab08a08506744a6c0272700019827b9160f8772351b07ea603a48a6085ebc61692243ae9dc6b5118c1b5be347000000014226899cc196086727c3a53560a6273406f499e19d1b57cfd6018be889630e0d000180541ee92782f67894645a8a976ccd0934e37c13fbbc7cbb501b7ba78d1a902301df26abb60966dedb257d90ef08aa7232474229e08e62ba390336a07c4775a7260001089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1217000 ..< 1220000:
return WalletBirthday(
height: 1217000,
hash: "000000000101d56be0c460d0e3cd780bf4eeeee79f98b2650ed61f2461ed0e61",
time: 1618567777,
tree: "0196abe4a8e73e641c8bde7f7d4c7455fc530758e5754b513ca76bc959757d773c0013010c2a76ab6a36beee5f415d06f0c4081b2569b8268123f00ac6a6cf95818dcf11000001f913b2dfda97da60e92d1cc81d0533f87794aa1dfd50bd668ffac7cfc1c1e2090001dd5879eeb7e652f8edf6458079cf06a4189700cb2dd6faaea03179a1d24d59050116769e0bf56d11a3fab9b728e76d131b177add630475992c0272ac1f6d14815e00019e4967e62633bd0d8084f78aa945c1a50bd571c71d06098f352a9d329c4d86110001a1e452b5cdaf030e7b4a75b30cbf4a920aa502d03c4b25af22c3ba815870a14700000001ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1220000 ..< 1230000:
return WalletBirthday(
height: 1220000,
hash: "0000000000751d7ffb3aac6f6a66ed01aa4e991a96162c1749dc556e50fe6df0",
time: 1618794113,
tree: "01c3bbf34ce189a5285144c79cc37c4e76385b803947819ea8bc43b1e8eb2c020801861a52e2fb19b150b0b7c7d7f879bd1ac4fa3a11ac9763db4f837f4db048896413013ddab8738a0cc8e00e96c7487d21a9771a7986b7e1e5d5fb0348d46caa18360c01d6b0010e9664a01a47a8acc9bf073255f6fb62f617cb491b249671da85001862000000012fe6dc35a5d51af73b73854855f9861775296a9c56d6aa9455be2762a101d7390168ee29d7b083e5af0d1895b2832a4fc63a9c7b6cea37b75d17d28e6f5842ee0c0159781dcd759c87f8bc8622bc19f9a8732c06b52897bfb6e0ddcbadb111d6a95601036e008ad224efaa9833fa9e790192dad7aab0ba71bf872430f48ba6aa0d1d1b00000169bce4bc91631cf6158d978b5ce6ad03f3e4cc3317c28964b575ca736f8b4d68000001ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1230000 ..< 1240000:
return WalletBirthday(
height: 1230000,
hash: "0000000001bcfbeb53fd5e9647168265bc5fc8e8622049b9cdd07098f0f51601",
time: 1619548843,
tree: "0164566f774ea1f6d7cf21a9fbf9cb3f2e7d1e400097417822a7c233422619c3710013000001bad8de55d9adf4d4ff08f4ad172a5ee80aa0049974c5227d2b07474078f73c2a01e8d5303b72f034efacb9b9aa0697aa5568bf6116f2fdc1e528c03b76ce569c340000000000015334d52667d65b8ff3dcfb3d6ed72c46ad19ea9112813aaf344a3e614eb9012600016cad8c39b711691f2bda74017894c657555a8bf7ef913931ac4f7ba0b48a30120121c25bceccda091622bfac1b7973ffaa638abe1f334b3b56f48dc93dc549c9070001ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1240000 ..< 1250000:
return WalletBirthday(
height: 1240000,
hash: "0000000002473bf56688195f05b6f5acea0f99506fca40ae72f2ab8c1fd7390d",
time: 1620303759,
tree: "017b7c743693588568510844e4bc181d12ab6433dced0542d149cbec2b96ba526500130001cb8eccc27eb266385f9e4b880ff337b2ebdf10238dac74414fde8937dfa2264b0001bb0cb6201a0d003f1e4df17cfd4815c382ced6bf038468873495ff5c9c25412501ba626167f23eb767c229a0498b37e8322326779a3a6454ebcefd639056b3e64400013ff350f9e880271ea2c713c509491605ea24589c369262c18c417fdf1027305e0000000001849b1538147707b1c880e7eee02f29ada52e8a5a6c3a9027087493f41bd8304a00018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1250000 ..< 1255000:
return WalletBirthday(
height: 1250000,
hash: "0000000000f3d2c352c395d66866032bcb67094228dd4a27e561b1c399ea612e",
time: 1621056898,
tree: "01c9a0dd6f6dfaaafe6ae4b432c2d1c41d2a73e564c8cb6d2c5ab637c7001a2456001300000000017da32b486a8ea9f13afb93b99d2b1de69aa969e7c2fd7b9ee958bece70c08d6b000001b3a4486b176dfcedc0b3d9287c0333ff464ecbd02bac7c89bcda7932e6a0a36100010d451c18b56877b8a11cb401ab7024c82b9669ede862a53e461087f57220035001a1c5260bc4dfe010510b8135209c6f64229965f71717f1e693abdcf88a58f36700012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1255000 ..< 1300000:
return WalletBirthday(
height: 1255000,
hash: "0000000000f34f274737e653cc31122e8ba8ca9865c09b65b3c2ecfb2e9687fd",
time: 1621434019,
tree: "016f51c78a2c55fef567e8deac7cb82b1f62f9ee6f5fdea27fc6fd9d1955e30353013f25aaa8aedcf10cd63b622d8c7dc21eb7b30504f99952bbc8efb437ffc482131301d0fa036d389289e37709f7f01d09e689cf55e989ea9d07440d593f21929f960801f69330a08f076f55f5db32aab6f2d1a2ab23e52a9a4e4fbbd21b8204ff23e64d00012f1469ddab73380dc3302f1cdbefb508141e2689a83b754fd9970037eb04fe6a00000000014ba6ac078f45c360c912ef828c138e4bd7d4150cadb2a498a32ec3fe7e22cc720001638de702094b20c64bc4b046cf7724634096aa192b155d191934120653734414013027101973e524ee59f21261bbf9fc152a61856a00f876a7c2b4dec71d50e969012f0bf70e372e536fc3b76ecd7e2b69eebf2fbcf71b828c64b0a8b99390fbf754018e7922ca798cd3e26d3369ca2425ec19baa7d79407a979ec1090ae48fdcd094a01ece344ca21dbd3b681f167163d4792165efe8239390afc13378e50d044fee65a01089a1f9d50a037cc66aba4400b1703bcbb66f5f2993fd0dd3bb726e35940916700000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1300000 ..< 1310000:
return WalletBirthday(
height: 1300000,
hash: "00000000027222bdbcf9c5f807f851f97312ac6e0dbbc2b93f2be21a69c59d44",
time: 1624830312,
tree: "01f5a97e2679a2bb9103caf37b825f92fcd73fff836234844dfcf1815394522b2c01526587b9b9e8aeb0eb572d81fec1f5127b8278ba0f57e451bd6b796596940a2213000131c7ff90fafff6159b8fb6544a2bcbba6c102903158fce8f9a9d3c6654abb23300013555cb7f4f79badeaca9bf2dca5a8704f0929053d50e95c03002f9a4d5286c3a01ad3557e11c1607ec888dc84f5f8899c3c79fb1f50b613946452ec7dd5e53763c0001c4583f4482b949390dba355fc8fa63019c83acd644ddd633cb50211d236f870600000001088da0d78eefd0c222507927e403b972d0890d0c31e08b02268fbe39ac4a6e170001edf82d4e2b4893ea2028ca8c5149e50a4c358b856d73f2de2b9a22034fa78f22012ffde6dccbef68b60cd7b4e7a8fe7989f5954fa4bacad01b247d16b9bfa5084000000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1310000 ..< 1320000:
return WalletBirthday(
height: 1310000,
hash: "00000000011ced7ee934fe237a80b74f04901db85fa82a4eec008fbb11ecf2e5",
time: 1625583320,
tree: "014be5784c617834157df657bafbc419ca3930f25deddaa9f29fc17483b235524800130001cc95eae2b1c3759963275342e56f1b71cd0bb6a4e2c0405f0108eb96f668851201f559a0e5f1b41af70fd6daccb0a48c3c178dfd8d25c09ff5152abded864a264f000000010bf2a42d0faed94259d4747ef48adaedf5772ebc93211f89be1612c1a9644603019f067dfc649ee5291bdf3caf7a307fb939eceb716c5050b63f620f0e41e1724400000000000001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1320000 ..< 1330000:
return WalletBirthday(
height: 1320000,
hash: "00000000001dd2deed141caa32a167fc9c11dc2d95f76f7cdda9f50326411309",
time: 1626337252,
tree: "018095da27911b257bdeaa799f1c36be3767f8ef268e1f232263e88df0aa7b4f6300130001e4e456c3aa306bf54a77176e2462715076b3586fe36716bfc3ec113a239fdb3c0000014e4fa821d93b8944df3d5500fd71b3fca0f4c2a6add80137f7b3379fdc56a4260000000000011cc990619b9371b0240cf3038e8b3b0aaa6c50e78db250a77f0b4c63f49d811a019b4b90179cf9bf8c7556caacf6acb77ac97620777d2dff5be661e576cac55f22000001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1330000 ..< 1336316:
return WalletBirthday(
height: 1330000,
hash: "0000000001126cdf85b463d086c6bf54d67094f6e17db3b08e38c2b4b16de926",
time: 1627091654,
tree: "016cc0651c73617064bf6de5962c99ec81fdce76d58ac2aab8b881e3b35991486d01593438b57eb9cfa76d5ea965b77a0304ff46163846c7c1ffb2695419a8dbfd4c1301e9766721a57a35e08763a27244291cb7db2ca67a711fd0569fd78aa675a21e1b019a9908d737043f786d7cdddbb22cb4d026c6c3221d34bd82bf4dc55acdd847640000000001de097ad39006362760b514f69a3aa88c66ada02085de26de23b522167df616320000000001a090ee174239a34a5d684425d09006d238c6075a61c5842d0fc26043f09ccd7001a2b7ee187c7b8ce18ebda8600bed7695b12f7d35ac971ed6ee67184a7ceebd490001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
case 1336316 ..< BlockHeight.max:
return WalletBirthday(
height: 1336316,
hash: "000000000196f12f0d91c95f0acc391454bf81901e95645e5fcd1935bd59ae27",
time: 1627567384,
tree: "0178d99ba141a858548143bfc60443bc965c8abcf4c0be7eca28b7681dfbc64c400013000141a76d7e56cf73013cb8c6549f90601a3d0a0c4057ca4f2b5515986c29d8710b01c21a76fc8075ae365db50bff0a03d674ab8dddd6e167a1c61125168365b40e40013338e3fef636235ace2523ae0d458508e795d04d7c49a77fa32032f45c482714000001fadad4c3da753327273cff5f827ac6a2da9cdf9554fb8e4ae1d73b0beb2b4a5a00012510c0b1bbca57be1267cba3c8e8e28c7457a3580f32fef3ad1ab5c117263e6401ea5e9a0276d6f23b8da7c2006a85277d92badb145c62334243205676b2ec971f012965494015cdab2ce010c1ae4ea88306c286128275de391dcf57d3fa85be7e1b01a090ee174239a34a5d684425d09006d238c6075a61c5842d0fc26043f09ccd7001a2b7ee187c7b8ce18ebda8600bed7695b12f7d35ac971ed6ee67184a7ceebd490001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
default:
return WalletBirthday(
height: 1336316,
hash: "000000000196f12f0d91c95f0acc391454bf81901e95645e5fcd1935bd59ae27",
time: 1627567384,
tree: "0178d99ba141a858548143bfc60443bc965c8abcf4c0be7eca28b7681dfbc64c400013000141a76d7e56cf73013cb8c6549f90601a3d0a0c4057ca4f2b5515986c29d8710b01c21a76fc8075ae365db50bff0a03d674ab8dddd6e167a1c61125168365b40e40013338e3fef636235ace2523ae0d458508e795d04d7c49a77fa32032f45c482714000001fadad4c3da753327273cff5f827ac6a2da9cdf9554fb8e4ae1d73b0beb2b4a5a00012510c0b1bbca57be1267cba3c8e8e28c7457a3580f32fef3ad1ab5c117263e6401ea5e9a0276d6f23b8da7c2006a85277d92badb145c62334243205676b2ec971f012965494015cdab2ce010c1ae4ea88306c286128275de391dcf57d3fa85be7e1b01a090ee174239a34a5d684425d09006d238c6075a61c5842d0fc26043f09ccd7001a2b7ee187c7b8ce18ebda8600bed7695b12f7d35ac971ed6ee67184a7ceebd490001b35fe4a943a47404f68db220c77b0573e13c3378a65c6f2396f93be7609d8f2a000125911f4524469c00ccb1ba69e64f0ee7380c8d17bbfc76ecd238421b86eb6e09000118f64df255c9c43db708255e7bf6bffd481e5c2f38fe9ed8f3d189f7f9cf2644"
)
}
}
}

View File

@ -0,0 +1,243 @@
//
// WalletBirthday+testnet.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 7/28/21.
//
import Foundation
extension WalletBirthday {
static func testnetBirthday(with height: BlockHeight) -> WalletBirthday {
switch height {
case BlockHeight.min ..< 421720:
return WalletBirthday(
height: 280000,
hash: "000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a",
time: 1535262293,
tree: "000000"
)
case 421720 ..< 425865:
return WalletBirthday(
height: 421720,
hash: "001ede53476a31a91da3313eddf4e41409fb7f4e003840700557b576024d09b4",
time: 1550762014,
tree: "015495a30aef9e18b9c774df6a9fcd583748c8bba1a6348e70f59bc9f0c2bc673b000f00000000018054b75173b577dc36f2c80dfc41f83d6716557597f74ec54436df32d4466d57000120f1825067a52ca973b07431199d5866a0d46ef231d08aa2f544665936d5b4520168d782e3d028131f59e9296c75de5a101898c5e53108e45baa223c608d6c3d3d01fb0a8d465b57c15d793c742df9470b116ddf06bd30d42123fdb7becef1fd63640001a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69"
)
case 425865 ..< 518000:
return WalletBirthday(
height: 425865,
hash: "0011c4de26004e564347b8af218ca16cd07b08c4159b1cc9c43afa6cb8807bed",
time: 1551215770,
tree: "01881e4da7e4767ee8a144a32ab8a5719a513bb05854477773bb55e6cd7f15055201f8a99a3a5ae3528ec2fc0bda9652b6728aecb08bf364e06ac511fd6654d782720f019ef0b9bdd075c38519fa4ab8210fe7e94c609f52672796e33e3cab58b1602831000001f803bf338ff1526b2ca527288974cb9be3fe240a2eadb7507e46ba59eaddb9320129fc0148ac088a6aa509f8f64ef79fda92232020369b58a12b32c05b6f428f22015e3dd0950c442940bd015c2176f7c817f22104f54c61159727483188c539dc13000000013589be9e2d9e9e38fd78b1e8eaec5b5f5167bf7fd2b1c95c316fa366a24cac4c01a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69"
)
case 518000 ..< 523240:
return WalletBirthday(
height: 518000,
hash: "000ba586d734c295f0bc034be229b1c96cb040f9d4929efdb5d2b187eeb238fb",
time: 1560645743,
tree: "01a4f5240a88a6eb4ffbda7961a1430506aad1a50ba011593f02c243d968feb0550010000140f91773b4ab669846e5bcb96f60e68256c49a27872a98e9d5ce50b30a0c434e0000018968663d6a7b444591de83f8a07223113f5de7e8203807adacc7677c3bcd4f420194c7ecac0ef6d702d475680ec32051fdf6368af0c459ab450009c001bcbf7a5300000001f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 523240 ..< 620000:
return WalletBirthday(
height: 523240,
hash: "00000c33da2196f0ed1bda71043f671fc69a0212e01f892653e212ab358f6b79",
time: 1561002603,
tree: "01d3e02bc1c2d66762f370b329a3063067701ad66c44b40285686bc8ff25f5616f00100154bff87bd0bda3b70a6d7754eca261de15fee3cd9bc53073a232e07fc3261e27000001a54dcaccb4c5e578aef89f2a3b4e3c3d8a487e6e904c5da5916118d721948d07000000000118fa9c6fef4963049dc7002a13bb0021d5e950591e48c9e5f2cbd1199429b80401f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 620000 ..< 680000:
return WalletBirthday(
height: 620000,
hash: "005f97953c8e1265d6b45f4435ffa32918e53e8f0025c286a4080c3eab167197",
time: 1569572035,
tree: "0170cf036ea1ea3c6e08432e18b6a372ca0b8b83671cc13ab0cf9e28c182f6c36f00100000013f3fc2c16ac4780f1c472ca65534ab08911f325a9edde5ea7f24364b47c9a95300017621b12e518cbbbdb7511ab423e0bddda412ed61ed3cff5be2140de65d6a0069010576153a5a2098812e7a028c37c3398e186f398c9b07bc199784ab97e5535c3e0000019a6ce2f0f7dbb2de493a315abf62d8ca96ccc701f116b6ddfae33870a2183d3c01c9d3564eff54ebc328eab2e4f1150c3637f4f47516f879a0cfebdf49fe7b1d5201c104705fac60a85596010e41260d07f3a64f38f37a112eaef41cd9d736edc5270145e3d4899fcd7f0f1236ae31eafb3f4b65ad6b11a17eae1729cec09bd3afa01a000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 680000 ..< 720000:
return WalletBirthday(
height: 680000,
hash: "00a4fbf54597d2f474f999576affad63f0ba2daa14c6fcd55c7eeec700107270",
time: 1573569367,
tree: "010a57f939a267f8b1e8b77288c783432e48fa95f7b22ead5e8ff46a788181453801d6457d98d3698a367aef4a2fe5675a575790d5d8081b731f979f0e64043fb7351001afaaf81d6d982b401444dbcf89e63c2583d234c1a60de17940a9b3a15f3494660001ba7acc730584a689413c44781d3b13cd497bfdca3fe27fb78cd9b50e9929906300000000000129e195df514840a20b95200b92d5b8d196b119cd6887508d8de077beffdbfe68016482af04b979e08e4e5760d55832292e55dbdd88143992f123840c8983db7b3f000001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 720000 ..< 740000:
return WalletBirthday(
height: 720000,
hash: "018b71dde8c9b1ee3e79961c6e3536c79226f5d6e79bb35c9ed28dcb8cb78b48",
time: 1575943651,
tree: "012cfde48dff4f20ddc50a7aca3746f7d77920eebc8cf4ef53feac34cb8719c03a012c668d234aaa485862e1d06e46d6d7093c2581e2b9cda90aafd691d6e325410610014f3a875476cb8159d46fec1aba18c201c268cd61b01811b7e5bf83998fb8222500011f19160cc75325c090f3eb3fa0cff2d94e43e2713c89e7b02a34f6ed08fbcd26000001edc05305223f7f2839abc1dc7d900468349577d6d6f5c182ef3a81a848753b5b0000000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 740000 ..< 760000:
return WalletBirthday(
height: 740000,
hash: "00163c394a1e545b4c777fc91474d92becdd0fe9300d38fb3563997d026a54ea",
time: 1577389695,
tree: "0135ee37f83d0b924eed58bcceb249a4977dcb21495561b97bc747a272ebe5d6580010000001fe65cfbb8a76e0d29ac94e5ada80c80b607d1addfc287754f37ddef531eb122500013a1d604d978f716fcb2887cdaa3c582a608b795ed1b3c57998cbede2be479931000108ffb0fbc6b653305b37cd5568b85112b996cd514fe97ec73f7169dae0cef05101baf5541e853483315273c25c1956d233513c3dabd8741972136b2f8f8cd89035000129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 760000 ..< 780000:
return WalletBirthday(
height: 760000,
hash: "005ee769f3adbd0b24a63e8e4047200e038c38df277544d40c23ac1a88c1f37b",
time: 1578766903,
tree: "01470a1a4d29374e074f07a646b95dd89892d9b84d235a89ecc9d5a52beadce901001001311898ce56df0ddb10dc573a54ea06d11415e72602daa80c01f888fbd4a9a734018610afa4925cdb8bd4dd75a53ab69a74080322cae53c630ac02ce00b09d3171601bdfbbde5011bd6c0620ed2db3e01d5daa2ff8bb5f3b58687d265dd33a5681d530197e268c82e56dfc62aeb54586a2000766da8078f09a2d15fb558ad05664b4c5301aa204407034ba59fce0eee6518688585e96b0f10befd595b8e68a8ae15328a51017389398c5634242b03ef811f6abf224df9e6fc6d4393139e526dca4cf44dcc2c0000017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 780000 ..< 798181:
return WalletBirthday(
height: 780000,
hash: "0104238cc440b6bf05b86a1b00d794c6d88fc61b8c416124a971fb5ce94b91e6",
time: 1580205978,
tree: "011ed883b7eddb4783eee5b73ceee4c78413e1f6f9db3d88d1007f5fa62292955c001001861feaeab59bc31cd97ffc89467877abf8b9fa157bc875907eb90d6e8c723325000000000001ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 798181 ..< 800000:
return WalletBirthday(
height: 798181,
hash: "02936aa4f8b6b2caad7cca19a866158656e37edfb0f32e2a473dc278fa634b71",
time: 1581521064,
tree: "01901ef0f4221f8a02d5896fda6f78cb5578fb8e9a5361d5689bfb3b6ab92072320010000101c5d791d8748f0ab0ecdb48764de29c470cc74f5d95b5a1f8cf0830bb059b66015af654e998c75460e9c1f5ba185589c53c383167e66951cfe7684321b7a77e5c013faf6b3f21f03982ada477bfddc95b18e63683c497b2f4630ab453623c28974c01aff3253410a6601ab4b5b3626f2121cb77399c634b1774a4c63f415598d16b0c01a6158d0a1a1bec9dadc601b140a9fdfc7bdab7e232739a3cc0e0e46bbe3ef44301ccc21a1d581eb6d3f35729f202f0014a59b4f9d41d92d44316b381f57dc8356b01ec0f418f21af87c0e0846b318be838bd181f25b708ee2b2fa030468399fb7932017de4c2c210c617dc61a43e124cab93e4f6143e1e9e46c2e55a541a9781cde43c0129cbee0c11a827718f126d9e037155a9e173ee2d2ecf57dc68f7b66437d44f7301a113bcf163405e4286bc080ac55aa68555d2c9e63334e7b9a5eb756872f14c470001e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 800000 ..< 850000:
return WalletBirthday(
height: 800000,
hash: "00599614a7795bbef99a598cfee887782900fa5cd95cd59900b8d6582bdc17a5",
time: 1581643886,
tree: "011ba0f16f59489a9bf9cc46c3ed1108c1dc0ff6e40f3a38def472c3229a96925e01b0eb758757bde323a6417d98365ce8f6299b0fa3de615d6cda68689e6a81573d1001438b40ff7357432d987d6ef4826fba35d38b2db531ea842ccedd4916a6aff9580000017cd705c293895c8b4613a3de3ad3b8d43ae05fff808882db4c5e19917e2f346d00000000000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 850000 ..< 900000:
return WalletBirthday(
height: 850000,
hash: "003b66bc3528dc295193108caab868e0f3b93d13db2ddcad5486225fb2b83d83",
time: 1585012771,
tree: "01e3bd906376b563d184bfbf6616e220f895001b7ef9d26bf38c6cb5c71e57a42b001001d848adf8c38d113140bb30d306b0761da6987e25ffc0d82faa63c2764aab120301de3e6a35d09192cde3430860c70a534d7b63e95a726fab052de2a9befa3cc3320189b958fa030131bb83385a3e3a8b187a166dc1b3a02050f2d2fc20788536c30e0001cb8770ef198e7de60093a339afbc561c16c16749f9f96751c2fc58a22d0ff36f01f86ff70dd512f7075d02c5ee6e28a8824832d08025a4cfaf4c1854f1fba5da10019bcac1b44a27de2c4528fa6f4b3432913511b219cb3b29d137cac0236a3d244800000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 950000 ..< 1013250:
return WalletBirthday(
height: 950000,
hash: "0005050d2ce31b9b925c7ef4ab3d3166d5833bdcfee251294f29072a2bc0f75d",
time: 1591609525,
tree: "01f0637235c4a699d49ba996457a6c4eb7c67edd8270948065683deb19ef218363019f65a9692cefc7b90b42c1538ac1f38f7a7598549089c4561315b482f378523010000000000000018d30d0039277b05ab9e0c3990d53037c45892bf17af2d04fef40ed48c164ad2201ff5d86bbbe360e31378e783b740f8b05db2cf4246b95aa3851d22ed45554750300010cefb25743d5dd6062ef3afba438731cd5b35befc1038ecca3076fd205829e550001c19052386d8bbe3c07a1faf302281d67946cc9547e7e1890ff56b3a3ec69c0310001be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1013250 ..< 1028400:
return WalletBirthday(
height: 1013250,
hash: "0017b3c49eea14e93f69adbc7a8f24eef3e9645f92e3b8d5e4091e1d5a4824b7",
time: 1595516064,
tree: "01d45e95007f8f97fe3c6a297a9d4bca917772e545fbcbb61b4f42d8a743eae31b0010013d7b7da2e6792dbfc6360f0c13a1ba879aa51a498c6dbab87aa57cef558cc35a00000001f945c15602617327026e3e0f231daf91570b32f7bb766f65e7e82131a911cc3c0000013173e9983fbd7a396e192e520d163be06cdd28abcfeba46c59dc62a400f589080001e7d5b00f0758cd3b7407c6d13e23d1a59e3f510c3dd3a4a8fc367a5305673b3f000001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1028400 ..< 1130000:
return WalletBirthday(
height: 1028400,
hash: "0006b94b304009f8a6287aa48021aed26582ce74d387c2c452aede86566179a6",
time: 1596480151,
tree: "01ac95378779cf56f0726655d248f95d63e07316ab67651ce357b346f9a7adba300107d7544edbe7d0522fe523df2ff804fc9f33f4844dd29e86a23fc7aa1818e237100001f8779a159482fd3a28c640e6d48ddfb37a44a26a102aae3822f32d2de22a1c70011f97534315f1800961bc78fcd1495e3b8047bb227e2776080fb31be6cae14e73000000000001fe15295e017fc2b8ba4ea1b7e53dd15f19860d10e7952905b7598373e143413e00019289038516ce3d6038cebe852ab5e32f7a1966fc79a1e41c7cb6e67e5a71c33d0001c787f900940720a3692e5694b085d5409dfa966017a6a48441c7e4b423b3144701be53a6cd33da0442c7c6362c0172241f42e13c6dc893436a661a1cbf49775c1f00011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1130000 ..< 1370446:
return WalletBirthday(
height: 1130000,
hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860",
time: 1603070117,
tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1370446 ..< 1414969:
return WalletBirthday(
height: 1370446,
hash: "00357a40a8d0473663f5ac32ecd4365bea097e47070b38803cbfae2b7a402233",
time: 1618587354,
tree: "01d0d36f8845f9ffad4f0a8812fbc5c4c69b45733199d7183307cb1a7d00353c0900100000017a8a6f641c487a313bb949623cca3b22b925adfef8216866aa090546bcf520000001bf48febcd2a10e51d420782990e17b746d5ce0f3292007e60a2eeb830bc46d0201ab6e0123bf72f70255ec4cacd33935b19ff834d481d67e06801073d0b8f0ea2a0121f42f607885a0158022413591af8eca7eae38b10c46e3ac81a9bfe70046e51d018229160dbe1f1d9e02d738e9d5060497e786e7434c80c32db7b8c96878e9904601034e6b1c73f09aa81f16a13cdb2188a53d8761483470f0bea01bfb84eb2cea1100018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1414969 ..< 1420000:
return WalletBirthday(
height: 1414969,
hash: "00212ba35169b77dba4eb4f5ce8c10da31a9df6dd61bb434f2f9e159d78913bd",
time: 1621459669,
tree: "01a9497fdb3add3bc2d0676f3163d94cda7c8cf8112d9dd8d2e7611b187c600a410010000143905c99f7bb45b164c636bb2443d9621db8147dba6a84a279fa8ed8f012083d00016847084e044e84059ea4b88b8af2de3f65c72adcee21522d5ee9d370d70f525b0000014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1420000 ..< 1430000:
return WalletBirthday(
height: 1420000,
hash: "0089952e8ca00ee452412c3eef20403f9bc84751fc6ceb630c8a2eb149f051ca",
time: 1621783347,
tree: "0107478e9125e3050506cbeea850266d94108997ec3ef101d9693d136611b4076c00100001dfcde451d111cd50bac54c4ed4e238ca3dd8dcfcb8b50eabccb11a12dbcad71b0001cffd776a8fd6e5df911d000876525aa1d792a4f764e252dac9af69dd8ef3046d0106d4ec443aa1194ea579a1aa179bd5a29eeb4a5a01ccbfcf7af9cadc58225a6900014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1430000 ..< 1440000:
return WalletBirthday(
height: 1430000,
hash: "01d9b2d83a7ec4ecede08df009e389b70535a5d41a1c6d1ce0906381d06006e0",
time: 1622484411,
tree: "010ea3d173a66acda751cb72a86bcc1eed2708b997ca8c7292febbd4c19b41665e001001f908af1ee7296100c06672f69834e5be2dc8b5325945270d562669bba91b825d01c4b42187eb99ab242226f6f2a48a00d4e5b3b4201c931afe9bccc86f3fbdd46501f39c0c0c1f725fa6b3ab8b58e60b280207a41199e2e218405f31ae18f0759f16000154daf736c7f68b0f22072be3e6b59434618b514c0c32d044c187048e2600c60b01f98b75b62bf721db663a442cbfa411242ec07ccb70aee42ea3618ca7b157270a014d03c61befc68d02710784399567067db98f24eda340a1fd4a3ecc549d0fd0660001b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1440000 ..< 1450000:
return WalletBirthday(
height: 1440000,
hash: "0026a36cf31a5442caa1ac6d7be2773e1e58a3ccb6ae1116e84e6c90ddc95ec9",
time: 1623136353,
tree: "018d8cc853fd33af2a13ea00f379fe882fc56ecea3e0b1ecb75ac3b9783b443d3b01922d8ec71070cbe88eef0576738169965839e841d2fbc09c85f1d64f3528d4341001ee3dbc8987d7be81ccd8a5b502e9385c447f3f8c9c34085a1d11f7b41ceb625b010c1d1b1687fd081e55598e9bdcc5c565781ec867a12dd056384890f36fef434c00011674571f7aca05cc96139d2e59b08fe7a5b7b779da40a9903755b61e73421e64000001ccb87d20316142450d34c59bc515935f9adfd053a178ae8d799ea1f9bf02664901cc23dbfe7d27d7ad768868d7a96b6b31260ca34e4fbf164f652eb8e651f2fd3801b4c1c846cae1423eaf52f1a8b1bfdde9ed9d43ced4d80dba9e72d862a0e03e4001ba0d7aa9e68417291c63b835fa64114f5899208238de59ee360f594c8b6c1b72018469338dcbdf2f7e54bca5bc3e1c5fad4a656f206040436d3d0433a901218b5e016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1450000 ..< 1460000:
return WalletBirthday(
height: 1450000,
hash: "000008a97bc133de13ca304e0c6a2a1b3f2facdceac2cde5b4141179f2a743cc",
time: 1623815069,
tree: "0175626cf9d8448de98f68fcc585dd7a276c946c11bbc3b192ee08db99c542b86b01acf5a110dc7ab911b534984c46bf56592f0c4cc8cf70dbd6a9cc4a5b47d2c81c1001c91f518ccb74093a217a640c537b69b095de058e0430046c8783f231caa1fa4201f7c982ce76b2c9343fb771e077357322f9a7dabfd7ab93b7adee32806c930d6600000170910ab6355ec614412fae56dad5fdc1747ce1b306a4b8ae03b77513b612b00800000000000000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1460000 ..< 1470000:
return WalletBirthday(
height: 1460000,
hash: "00987b79a3c78d33dcb4d65e81a48b62a40c15d379a3983c4dffdd99a0c21d35",
time: 1624454126,
tree: "01f971b9781e857ab4acd5506174daf7ced473ad5a4a98134816d0c48de197d4400010000001ce49c67660eff9e404a3e4569ffa3ba98cc4514c05fa408beecd5c63420ef30e0192152273e4cbeafd426fa7df421310d2ccefad5e78f8d3e26dc283064b4d0d480188b70932b9ad821d4c9ecd57ed729a724723d22bdee4e5d4f08c9a924e68cf1501b2533ff180b8fb171fc0450fb7d1f91b7528bc19d88fdb2385c207b149d55e53017b499fdb9fe0db4bc418689d8f45f38b127b67d0445c421bfa6892c870610e260000000000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1470000 ..< 1480000:
return WalletBirthday(
height: 1470000,
hash: "0027c8d818126cc8ab96efdcf877c1fb54fb373f41ca8f06e68b0b7b0e304ac7",
time: 1625121412,
tree: "012442af751714abfbb1f6b815b187eecbb60849e29dca1e3acccfbfd73f6bb8150010000109777ddd46c0a0e7eb91f31735f6078c54334f9a6d22d6421898bd44fd83ce140000013337975cc4704be21cbecce1c877936ce395128f6264fcb91ba8c028e7f25230015d7589dc1009350a87831e2fa9c4d9d3ca61754644f1a1d5d09499567fdcb11e0136e55cb009dd4f8bb8a3469b27ec325f06552a66bef2d898b6a72063107d03350001a7b951c79a184af5bda58c8be77db9b1e3813df0de344f26b27e3ad02c325b3b000000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1480000 ..< 1490000:
return WalletBirthday(
height: 1480000,
hash: "0019c7d1a7d9d962de329db0785f35f56c514826702714f8738d14da87f4f20d",
time: 1625795173,
tree: "01a61918852f89d4d68aa82e1d93a7ddc4285ab2cf6a2ce92e79c4b9b498662014016d8109b64819882e5d35ee6730f54dda3a4ddc8232edc22226a367542c977a23100000016891e1f6b99afb29292bd3157f89eb2b8c1f74eed9cef56f4a802939d7392a1a0001f6f393a6ab5b0bc04a6d751bdbcd64a2740ff93aef7e1527dcd5de0511c4fb3001b938c3d7a93793fa04d51cce0369e789316a72f227436e02fc0c45fdd88def3700000001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1490000 ..< 1500000:
return WalletBirthday(
height: 1490000,
hash: "00263c9eab1b6b5e37143a442a8aad242fada58bb5fc8d6a5dc9f217c8c7425c",
time: 1626460494,
tree: "01448b047d9d4611f923ceb0c01a2fc743c7b4a54f7a00e92d666cbd0f39980f3100100000000001d917913fed08004cf1c74eeb918829cb80e576187e2f8e0c0e12a7e9849a9b400130282bcf71d57c40235baa4a3e045d89803c1fe069803da86ccebf25435dd270014aad72f0f5c3cd459d6d89a68657fbd299c84be0228c1a8a50d63ff2f2f74e0a000001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1500000 ..< 1507328:
return WalletBirthday(
height: 1500000,
hash: "00047a34c61409682f44640af9352023ad92f69b827d0f2b288f152ebea50f46",
time: 1627076501,
tree: "01172b95f271c6af8f68388f08c8ef970db8ec8d8d61204ecb7b2bb2c38262b92d0010016284585a6c85dadfef27ff33f1403926b4bb391de92e8be797e4280cc4ca2971000001a1ff388639379c0120782b3929bd8871af797be4b651f694aa961bad65a9c12400000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1500000 ..< 1507328:
return WalletBirthday(
height: 1500000,
hash: "00047a34c61409682f44640af9352023ad92f69b827d0f2b288f152ebea50f46",
time: 1627076501,
tree: "01172b95f271c6af8f68388f08c8ef970db8ec8d8d61204ecb7b2bb2c38262b92d0010016284585a6c85dadfef27ff33f1403926b4bb391de92e8be797e4280cc4ca2971000001a1ff388639379c0120782b3929bd8871af797be4b651f694aa961bad65a9c12400000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
case 1507328 ..< BlockHeight.max:
return WalletBirthday(
height: 1507328,
hash: "0026c9b20540e1bde6aaa8674a4083587a6e2555bcf8bb42680a8870b8da0070",
time: 1627566512,
tree: "01beb58cd0d4ac4e0f61888c7d77c7d73d260453b526bc61a830c158319f01b22301070135db53749d6640bdfc3c3e25d71dd65dcdc2c5828fd992eaee63546194051000000105884e2f6fbe3d0754fca27e20881b74ea687d33a0ea817844330a187d20465a0192f904a39694089c3befc610fd8e1236d5e7cb3b19d2e1d5fc4019af31fbc80201870a7fec351119b307e79c83bb627b343a87668e1d68e60625212e40deb33c3d000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
default:
return WalletBirthday(
height: 1507328,
hash: "0026c9b20540e1bde6aaa8674a4083587a6e2555bcf8bb42680a8870b8da0070",
time: 1627566512,
tree: "01beb58cd0d4ac4e0f61888c7d77c7d73d260453b526bc61a830c158319f01b22301070135db53749d6640bdfc3c3e25d71dd65dcdc2c5828fd992eaee63546194051000000105884e2f6fbe3d0754fca27e20881b74ea687d33a0ea817844330a187d20465a0192f904a39694089c3befc610fd8e1236d5e7cb3b19d2e1d5fc4019af31fbc80201870a7fec351119b307e79c83bb627b343a87668e1d68e60625212e40deb33c3d000001d806c98bda9653d5ae22757eed750871e16e0fb657f52c3d771a4411668e84330001260f6e9fac0922f98d58afbcc3f391ac19d5d944081466929a33b99df19c0e6a0000013d2fd009bf8a22d68f720eac19c411c99014ed9c5f85d5942e15d1fc039e28680001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39"
)
}
}
}

View File

@ -0,0 +1,241 @@
//
// ZcashSDK.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 7/22/21.
//
import Foundation
public protocol ZcashNetwork {
var networkType: NetworkType { get }
var constants: NetworkConstants.Type { get }
}
public enum NetworkType {
case mainnet
case testnet
var networkId: UInt32 {
switch self {
case .mainnet:
return 1
case .testnet:
return 0
}
}
}
extension NetworkType {
static func forChainName(_ chainame: String) -> NetworkType? {
switch chainame {
case "test":
return .testnet
case "main":
return .mainnet
default:
return nil
}
}
}
public class ZcashNetworkBuilder {
public static func network(for networkType: NetworkType) -> ZcashNetwork {
switch networkType {
case .mainnet:
return ZcashMainnet()
case .testnet:
return ZcashTestnet()
}
}
}
class ZcashTestnet: ZcashNetwork {
var networkType: NetworkType = .testnet
var constants: NetworkConstants.Type = ZcashSDKTestnetConstants.self
}
class ZcashMainnet: ZcashNetwork {
var networkType: NetworkType = .mainnet
var constants: NetworkConstants.Type = ZcashSDKMainnetConstants.self
}
/**
Constants of ZcashLightClientKit. this constants don't
*/
public class ZcashSDK {
/**
The number of zatoshi that equal 1 ZEC.
*/
public static var ZATOSHI_PER_ZEC: BlockHeight = 100_000_000
/**
The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
*/
public static var MAX_REORG_SIZE = 100
/**
The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled
by the rust backend but it is helpful to know what it is set to and should be kept in sync.
*/
public static var EXPIRY_OFFSET = 20
//
// Defaults
//
/**
Default size of batches of blocks to request from the compact block service.
*/
public static var DEFAULT_BATCH_SIZE = 100
/**
Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average
block time.
*/
public static var DEFAULT_POLL_INTERVAL: TimeInterval = 20
/**
Default attempts at retrying.
*/
public static var DEFAULT_RETRIES: Int = 5
/**
The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
this before retyring.
*/
public static var DEFAULT_MAX_BACKOFF_INTERVAL: TimeInterval = 600
/**
Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the
reorg but smaller than the theoretical max reorg size of 100.
*/
public static var DEFAULT_REWIND_DISTANCE: Int = 10
/**
The number of blocks to allow before considering our data to be stale. This usually helps with what to do when
returning from the background and is exposed via the Synchronizer's isStale function.
*/
public static var DEFAULT_STALE_TOLERANCE: Int = 10
/**
Default Name for LibRustZcash data.db
*/
public static var DEFAULT_DATA_DB_NAME = "data.db"
/**
Default Name for Compact Block caches db
*/
public static var DEFAULT_CACHES_DB_NAME = "caches.db"
/**
Default name for pending transactions db
*/
public static var DEFAULT_PENDING_DB_NAME = "pending.db"
/**
File name for the sapling spend params
*/
public static var SPEND_PARAM_FILE_NAME = "sapling-spend.params"
/**
File name for the sapling output params
*/
public static var OUTPUT_PARAM_FILE_NAME = "sapling-output.params"
/**
The Url that is used by default in zcashd.
We'll want to make this externally configurable, rather than baking it into the SDK but
this will do for now, since we're using a cloudfront URL that already redirects.
*/
public static var CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/"
}
public protocol NetworkConstants {
/**
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
prior to this height, at all.
*/
static var SAPLING_ACTIVATION_HEIGHT: BlockHeight { get }
/**
Default Name for LibRustZcash data.db
*/
static var DEFAULT_DATA_DB_NAME: String { get }
/**
Default Name for Compact Block caches db
*/
static var DEFAULT_CACHES_DB_NAME: String { get }
/**
Default name for pending transactions db
*/
static var DEFAULT_PENDING_DB_NAME: String { get }
static var DEFAULT_DB_NAME_PREFIX: String { get }
/**
fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround
for librustzcash not figuring out the tx fee from the tx itself.
*/
static var FEE_CHANGE_HEIGHT: BlockHeight { get }
static func defaultFee(for height: BlockHeight) -> Int64
}
public extension NetworkConstants {
static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 {
guard height >= FEE_CHANGE_HEIGHT else { return 10_000 }
return 1_000
}
}
public class ZcashSDKMainnetConstants: NetworkConstants {
private init() {}
/**
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
prior to this height, at all.
*/
public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 419_200
/**
Default Name for LibRustZcash data.db
*/
public static var DEFAULT_DATA_DB_NAME = "data.db"
/**
Default Name for Compact Block caches db
*/
public static var DEFAULT_CACHES_DB_NAME = "caches.db"
/**
Default name for pending transactions db
*/
public static var DEFAULT_PENDING_DB_NAME = "pending.db"
public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_"
public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_077_550
}
public class ZcashSDKTestnetConstants: NetworkConstants {
private init() {}
/**
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
prior to this height, at all.
*/
public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 280_000
/**
Default Name for LibRustZcash data.db
*/
public static var DEFAULT_DATA_DB_NAME = "data.db"
/**
Default Name for Compact Block caches db
*/
public static var DEFAULT_CACHES_DB_NAME = "caches.db"
/**
Default name for pending transactions db
*/
public static var DEFAULT_PENDING_DB_NAME = "pending.db"
public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_testnet_"
/**
Estimated height where wallets are supposed to change the fee
*/
public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_028_500
}

View File

@ -57,13 +57,13 @@ public extension TransactionEntity {
return true
}
var anchor: BlockHeight? {
func anchor(network: ZcashNetwork) -> BlockHeight? {
if let minedHeight = self.minedHeight, minedHeight != -1 {
return max(minedHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE, ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
return max(minedHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE, network.constants.SAPLING_ACTIVATION_HEIGHT)
}
if let expiryHeight = self.expiryHeight, expiryHeight != -1 {
return max(expiryHeight - ZcashSDK.EXPIRY_OFFSET - ZcashSDK.DEFAULT_STALE_TOLERANCE, ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
return max(expiryHeight - ZcashSDK.EXPIRY_OFFSET - ZcashSDK.DEFAULT_STALE_TOLERANCE, network.constants.SAPLING_ACTIVATION_HEIGHT)
}
return nil

View File

@ -7,39 +7,6 @@
import Foundation
/**
Ideally this extension shouldn't exist. Fees should be calculated from inputs and outputs. "Perfect is the enemy of good"
*/
public extension ZcashSDK {
/**
Returns the default fee at the time of that blockheight.
*/
static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 {
guard height >= feeChangeHeight else { return 10_000 }
return 1_000
}
/**
Estimated height where wallets are supposed to change the fee
*/
private static var feeChangeHeight: BlockHeight {
ZcashSDK.isMainnet ? 1_077_550 : 1_028_500
}
/**
minimum balance needed to do a shielding transaction
*/
static let shieldingThreshold: Int64 = 10000
enum NetworkType {
case mainnet
case testnet
}
}
public typealias ConsensusBranchID = Int32
public extension ConsensusBranchID {
@ -53,12 +20,7 @@ public extension ConsensusBranchID {
}
}
extension ZcashSDK {
static var networkType: NetworkType {
self.isMainnet ? .mainnet : .testnet
}
}
extension ZcashSDK.NetworkType {
extension NetworkType {
init?(_ string: String) {
switch string {
case "main":

View File

@ -75,6 +75,7 @@ public class Initializer {
private(set) var accountRepository: AccountRepository
private(set) var storage: CompactBlockStorage
private(set) var downloader: CompactBlockDownloader
private(set) var network: ZcashNetwork
private(set) public var viewingKeys: [UnifiedViewingKey]
private(set) public var walletBirthday: WalletBirthday
/**
@ -91,10 +92,11 @@ public class Initializer {
dataDbURL: URL,
pendingDbURL: URL,
endpoint: LightWalletEndpoint,
network: ZcashNetwork,
spendParamsURL: URL,
outputParamsURL: URL,
viewingKeys: [UnifiedViewingKey],
walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT,
walletBirthday: BlockHeight,
alias: String = "",
loggerProxy: Logger? = nil) {
@ -102,6 +104,7 @@ public class Initializer {
self.init(rustBackend: ZcashRustBackend.self,
lowerBoundHeight: walletBirthday,
network: network,
cacheDbURL: cacheDbURL,
dataDbURL: dataDbURL,
pendingDbURL: pendingDbURL,
@ -124,6 +127,7 @@ public class Initializer {
*/
init(rustBackend: ZcashRustBackendWelding.Type,
lowerBoundHeight: BlockHeight,
network: ZcashNetwork,
cacheDbURL: URL,
dataDbURL: URL,
pendingDbURL: URL,
@ -156,7 +160,8 @@ public class Initializer {
self.storage = storage
self.downloader = CompactBlockDownloader(service: service, storage: storage)
self.viewingKeys = viewingKeys
self.walletBirthday = WalletBirthday.birthday(with: walletBirthday)
self.walletBirthday = WalletBirthday.birthday(with: walletBirthday, network: network)
self.network = network
}
/**
@ -182,7 +187,7 @@ public class Initializer {
}
do {
try rustBackend.initDataDb(dbData: dataDbURL)
try rustBackend.initDataDb(dbData: dataDbURL, networkType: network.networkType)
} catch RustWeldingError.dataDbNotEmpty {
// this is fine
} catch {
@ -190,7 +195,7 @@ public class Initializer {
}
do {
try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree)
try rustBackend.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthday.height), hash: walletBirthday.hash, time: walletBirthday.time, saplingTree: walletBirthday.tree, networkType: network.networkType)
} catch RustWeldingError.dataDbNotEmpty {
// this is fine
} catch {
@ -202,7 +207,7 @@ public class Initializer {
lowerBoundHeight = max(walletBirthday.height, lastDownloaded)
do {
guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys) else {
guard try rustBackend.initAccountsTable(dbData: dataDbURL, uvks: viewingKeys, networkType: network.networkType) else {
throw rustBackend.lastError() ?? InitializerError.accountInitFailed
}
} catch RustWeldingError.dataDbNotEmpty {
@ -212,7 +217,9 @@ public class Initializer {
}
let migrationManager = MigrationManager(cacheDbConnection: SimpleConnectionProvider(path: cacheDbURL.path),
dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path), pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path))
dataDbConnection: SimpleConnectionProvider(path: dataDbURL.path),
pendingDbConnection: SimpleConnectionProvider(path: pendingDbURL.path),
networkType: self.network.networkType)
try migrationManager.performMigration(uvks: viewingKeys)
}
@ -229,7 +236,7 @@ public class Initializer {
- Parameter account: the index of the account
*/
public func getBalance(account index: Int = 0) -> Int64 {
rustBackend.getBalance(dbData: dataDbURL, account: Int32(index))
rustBackend.getBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType)
}
/**
@ -237,20 +244,20 @@ public class Initializer {
- Parameter account: the index of the account
*/
public func getVerifiedBalance(account index: Int = 0) -> Int64 {
rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index))
rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType)
}
/**
checks if the provided address is a valid shielded zAddress
*/
public func isValidShieldedAddress(_ address: String) -> Bool {
(try? rustBackend.isValidShieldedAddress(address)) ?? false
(try? rustBackend.isValidShieldedAddress(address, networkType: network.networkType)) ?? false
}
/**
checks if the provided address is a transparent zAddress
*/
public func isValidTransparentAddress(_ address: String) -> Bool {
(try? rustBackend.isValidTransparentAddress(address)) ?? false
(try? rustBackend.isValidTransparentAddress(address,networkType: network.networkType)) ?? false
}
func isSpendParameterPresent() -> Bool {

View File

@ -21,23 +21,28 @@ public protocol ResourceProvider {
Convenience provider for a data db and cache db resources.
*/
public struct DefaultResourceProvider: ResourceProvider {
init(network: ZcashNetwork) {
self.network = network
}
var network: ZcashNetwork
public var dataDbURL: URL {
let constants = network.constants
do {
let url = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
return url.appendingPathComponent(ZcashSDK.DEFAULT_DATA_DB_NAME)
return url.appendingPathComponent(constants.DEFAULT_DATA_DB_NAME)
} catch {
return URL(fileURLWithPath: "file://\(ZcashSDK.DEFAULT_DATA_DB_NAME)")
return URL(fileURLWithPath: "file://\(constants.DEFAULT_DATA_DB_NAME)")
}
}
public var cacheDbURL: URL {
let constants = network.constants
do {
let path = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
return path.appendingPathComponent(ZcashSDK.DEFAULT_CACHES_DB_NAME)
return path.appendingPathComponent(constants.DEFAULT_CACHES_DB_NAME)
} catch {
return URL(fileURLWithPath: "file://\(ZcashSDK.DEFAULT_CACHES_DB_NAME)")
return URL(fileURLWithPath: "file://\(constants.DEFAULT_CACHES_DB_NAME)")
}
}

View File

@ -36,9 +36,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
/**
* Sets up the internal structure of the data database.
*/
static func initDataDb(dbData: URL) throws {
static func initDataDb(dbData: URL, networkType: NetworkType) throws {
let dbData = dbData.osStr()
guard zcashlc_init_data_database(dbData.0, dbData.1) != 0 else {
guard zcashlc_init_data_database(dbData.0, dbData.1, networkType.networkId) != 0 else {
if let error = lastError() {
throw throwDataDbError(error)
}
@ -46,12 +46,12 @@ class ZcashRustBackend: ZcashRustBackendWelding {
}
}
static func isValidShieldedAddress(_ address: String) throws -> Bool {
static func isValidShieldedAddress(_ address: String, networkType: NetworkType) throws -> Bool {
guard !address.containsCStringNullBytesBeforeStringEnding() else {
return false
}
guard zcashlc_is_valid_shielded_address([CChar](address.utf8CString)) else {
guard zcashlc_is_valid_shielded_address([CChar](address.utf8CString), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -60,12 +60,12 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return true
}
static func isValidTransparentAddress(_ address: String) throws -> Bool {
static func isValidTransparentAddress(_ address: String, networkType: NetworkType) throws -> Bool {
guard !address.containsCStringNullBytesBeforeStringEnding() else {
return false
}
guard zcashlc_is_valid_transparent_address([CChar](address.utf8CString)) else {
guard zcashlc_is_valid_transparent_address([CChar](address.utf8CString), networkType.networkId ) else {
if let error = lastError() {
throw error
}
@ -74,12 +74,12 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return true
}
static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool {
static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool {
guard !key.containsCStringNullBytesBeforeStringEnding() else {
return false
}
guard zcashlc_is_valid_viewing_key([CChar](key.utf8CString)) else {
guard zcashlc_is_valid_viewing_key([CChar](key.utf8CString), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -88,10 +88,10 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return true
}
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? {
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? {
let dbData = dbData.osStr()
var capacity = UInt(0);
let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts, &capacity)
let extsksCStr = zcashlc_init_accounts_table(dbData.0, dbData.1, seed, UInt(seed.count), accounts, &capacity, networkType.networkId)
if extsksCStr == nil {
return nil
}
@ -104,7 +104,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return extsks
}
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool {
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey], networkType: NetworkType) throws -> Bool {
let dbData = dbData.osStr()
var ffiUvks = [FFIUnifiedViewingKey]()
@ -115,6 +115,10 @@ class ZcashRustBackend: ZcashRustBackendWelding {
guard !uvk.extpub.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard try self.isValidExtendedFullViewingKey(uvk.extfvk, networkType: networkType) else {
throw RustWeldingError.malformedStringInput
}
let extfvkCStr = [CChar](String(uvk.extfvk).utf8CString)
@ -133,7 +137,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
let slice = UnsafeMutablePointer<FFIUVKBoxedSlice>.allocate(capacity: 1)
slice.initialize(to: FFIUVKBoxedSlice(ptr: p.baseAddress, len: UInt(p.count)))
result = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, slice)
result = zcashlc_init_accounts_table_with_keys(dbData.0, dbData.1, slice, networkType.networkId)
slice.deinitialize(count: 1)
}
@ -147,29 +151,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return result
}
// 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 {
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String, networkType: NetworkType) throws {
let dbData = dbData.osStr()
guard !hash.containsCStringNullBytesBeforeStringEnding() else {
@ -180,7 +163,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
throw RustWeldingError.malformedStringInput
}
guard zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString)) != 0 else {
guard zcashlc_init_blocks_table(dbData.0, dbData.1, height, [CChar](hash.utf8CString), time, [CChar](saplingTree.utf8CString), networkType.networkId) != 0 else {
if let error = lastError() {
throw error
}
@ -188,52 +171,65 @@ class ZcashRustBackend: ZcashRustBackendWelding {
}
}
static func getAddress(dbData: URL, account: Int32) -> String? {
static func getAddress(dbData: URL, account: Int32, networkType: NetworkType) -> String? {
let dbData = dbData.osStr()
guard let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account) else { return nil }
guard let addressCStr = zcashlc_get_address(dbData.0, dbData.1, account, networkType.networkId) else { return nil }
let address = String(validatingUTF8: addressCStr)
zcashlc_string_free(addressCStr)
return address
}
static func getBalance(dbData: URL, account: Int32) -> Int64 {
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 {
let dbData = dbData.osStr()
return zcashlc_get_balance(dbData.0, dbData.1, account)
return zcashlc_get_balance(dbData.0, dbData.1, account, networkType.networkId)
}
static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 {
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 {
let dbData = dbData.osStr()
return zcashlc_get_verified_balance(dbData.0, dbData.1, account)
return zcashlc_get_verified_balance(dbData.0, dbData.1, account, networkType.networkId)
}
static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 {
static func getVerifiedTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 {
guard !address.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard try isValidTransparentAddress(address, networkType: networkType) else {
throw RustWeldingError.unableToDeriveKeys
}
let dbData = dbData.osStr()
return zcashlc_get_verified_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString))
return zcashlc_get_verified_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkType.networkId)
}
static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 {
static func getTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 {
guard !address.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard try self.isValidTransparentAddress(address, networkType: networkType) else {
throw RustWeldingError.unableToDeriveKeys
}
let dbData = dbData.osStr()
return zcashlc_get_total_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString))
return zcashlc_get_total_transparent_balance(dbData.0, dbData.1, [CChar](address.utf8CString), networkType.networkId)
}
static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> Int32 {
static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 {
let dbData = dbData.osStr()
guard !address.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
let result = zcashlc_clear_utxos(dbData.0, dbData.1, [CChar](address.utf8CString), Int32(sinceHeight))
guard try isValidTransparentAddress(address, networkType: networkType) else {
throw RustWeldingError.unableToDeriveKeys
}
let result = zcashlc_clear_utxos(dbData.0, dbData.1, [CChar](address.utf8CString), Int32(sinceHeight), networkType.networkId)
guard result > 0 else {
if let error = lastError() {
@ -244,7 +240,7 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return result
}
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool {
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool {
let dbData = dbData.osStr()
@ -261,7 +257,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
script,
UInt(script.count),
value,
Int32(height)) else {
Int32(height),
networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -270,60 +267,61 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return true
}
static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance {
let verified = try getVerifiedTransparentBalance(dbData: dbData, address: address)
let total = try getTransparentBalance(dbData: dbData, address: address)
static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance {
let verified = try getVerifiedTransparentBalance(dbData: dbData, address: address, networkType: networkType)
let total = try getTransparentBalance(dbData: dbData, address: address, networkType: networkType)
return TransparentBalance(verified: verified, total: total, address: address)
}
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? {
let dbData = dbData.osStr()
guard let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote) else { return nil }
guard let memoCStr = zcashlc_get_received_memo_as_utf8(dbData.0, dbData.1, idNote, networkType.networkId) else { return nil }
let memo = String(validatingUTF8: memoCStr)
zcashlc_string_free(memoCStr)
return memo
}
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? {
let dbData = dbData.osStr()
guard let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote) else { return nil }
guard let memoCStr = zcashlc_get_sent_memo_as_utf8(dbData.0, dbData.1, idNote, networkType.networkId) else { return nil }
let memo = String(validatingUTF8: memoCStr)
zcashlc_string_free(memoCStr)
return memo
}
static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 {
static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 {
let dbCache = dbCache.osStr()
let dbData = dbData.osStr()
return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1)
return zcashlc_validate_combined_chain(dbCache.0, dbCache.1, dbData.0, dbData.1, networkType.networkId)
}
static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32 {
static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32 {
let dbData = dbData.osStr()
return zcashlc_get_nearest_rewind_height(dbData.0, dbData.1, height)
return zcashlc_get_nearest_rewind_height(dbData.0, dbData.1, height, networkType.networkId)
}
static func rewindToHeight(dbData: URL, height: Int32) -> Bool {
static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool {
let dbData = dbData.osStr()
return zcashlc_rewind_to_height(dbData.0, dbData.1, height)
return zcashlc_rewind_to_height(dbData.0, dbData.1, height, networkType.networkId)
}
static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32 = 0) -> Bool {
static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32 = 0, networkType: NetworkType) -> Bool {
let dbCache = dbCache.osStr()
let dbData = dbData.osStr()
return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit) != 0
return zcashlc_scan_blocks(dbCache.0, dbCache.1, dbData.0, dbData.1, limit, networkType.networkId) != 0
}
static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool {
static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8], networkType: NetworkType) -> Bool {
let dbData = dbData.osStr()
return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count)) != 0
return zcashlc_decrypt_and_store_transaction(dbData.0, dbData.1, tx, UInt(tx.count), networkType.networkId) != 0
}
static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 {
let dbData = dbData.osStr()
let memoBytes = memo ?? ""
@ -337,10 +335,11 @@ class ZcashRustBackend: ZcashRustBackendWelding {
spendParamsPath,
UInt(spendParamsPath.lengthOfBytes(using: .utf8)),
outputParamsPath,
UInt(outputParamsPath.lengthOfBytes(using: .utf8)))
UInt(outputParamsPath.lengthOfBytes(using: .utf8)),
networkType.networkId)
}
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 {
let dbData = dbData.osStr()
let memoBytes = memo ?? ""
@ -353,16 +352,18 @@ class ZcashRustBackend: ZcashRustBackendWelding {
spendParamsPath,
UInt(spendParamsPath.lengthOfBytes(using: .utf8)),
outputParamsPath,
UInt(outputParamsPath.lengthOfBytes(using: .utf8)))
UInt(outputParamsPath.lengthOfBytes(using: .utf8)),
networkType.networkId)
}
static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String? {
static func deriveExtendedFullViewingKey(_ spendingKey: String, networkType: NetworkType) throws -> String? {
guard !spendingKey.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard let extsk = zcashlc_derive_extended_full_viewing_key([CChar](spendingKey.utf8CString)) else {
guard let extsk = zcashlc_derive_extended_full_viewing_key([CChar](spendingKey.utf8CString),
networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -375,9 +376,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return derived
}
static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? {
static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? {
var capacity = UInt(0);
guard let extsksCStr = zcashlc_derive_extended_full_viewing_keys(seed, UInt(seed.count), accounts, &capacity) else {
guard let extsksCStr = zcashlc_derive_extended_full_viewing_keys(seed, UInt(seed.count), accounts, &capacity, networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -392,9 +393,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return extsks
}
static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? {
static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? {
var capacity = UInt(0);
guard let extsksCStr = zcashlc_derive_extended_spending_keys(seed, UInt(seed.count), accounts, &capacity) else {
guard let extsksCStr = zcashlc_derive_extended_spending_keys(seed, UInt(seed.count), accounts, &capacity, networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -409,9 +410,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return extsks
}
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] {
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedViewingKey] {
guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts)) else {
guard let uvks_struct = zcashlc_derive_unified_viewing_keys_from_seed(seed, UInt(seed.count), Int32(numberOfAccounts), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -443,8 +444,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
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 {
static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? {
guard let zaddrCStr = zcashlc_derive_shielded_address_from_seed(seed, UInt(seed.count), accountIndex, networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -457,12 +458,12 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return zAddr
}
static func deriveShieldedAddressFromViewingKey(_ extfvk: String) throws -> String? {
static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? {
guard !extfvk.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key([CChar](extfvk.utf8CString)) else {
guard let zaddrCStr = zcashlc_derive_shielded_address_from_viewing_key([CChar](extfvk.utf8CString), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -475,9 +476,9 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return zAddr
}
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? {
guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index)) else {
guard let tAddrCStr = zcashlc_derive_transparent_address_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -489,8 +490,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return tAddr
}
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index)) else {
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? {
guard let skCStr = zcashlc_derive_transparent_private_key_from_seed(seed, UInt(seed.count), Int32(account), Int32(index), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -501,12 +502,12 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return sk
}
static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String {
static func derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) 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 {
guard let tAddrCStr = zcashlc_derive_transparent_address_from_public_key([CChar](pubkey.utf8CString), networkType.networkId), let tAddr = String(validatingUTF8: tAddrCStr) else {
if let error = lastError() {
throw error
}
@ -515,12 +516,12 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return tAddr
}
static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? {
static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? {
guard !tsk.containsCStringNullBytesBeforeStringEnding() else {
throw RustWeldingError.malformedStringInput
}
guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString)) else {
guard let tAddrCStr = zcashlc_derive_transparent_address_from_secret_key([CChar](tsk.utf8CString), networkType.networkId) else {
if let error = lastError() {
throw error
}
@ -531,8 +532,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
return tAddr
}
static func consensusBranchIdFor(height: Int32) throws -> Int32 {
let branchId = zcashlc_branch_id_for_height(height)
static func consensusBranchIdFor(height: Int32, networkType: NetworkType) throws -> Int32 {
let branchId = zcashlc_branch_id_for_height(height, networkType.networkId)
guard branchId != -1 else {
throw RustWeldingError.noConsensusBranchId(height: height)

View File

@ -35,25 +35,25 @@ public protocol ZcashRustBackendWelding {
initializes the data db
- Parameter dbData: location of the data db sql file
*/
static func initDataDb(dbData: URL) throws
static func initDataDb(dbData: URL, networkType: NetworkType) throws
/**
- Returns: true when the address is valid and shielded. Returns false in any other case
- Throws: Error when the provided address belongs to another network
*/
static func isValidShieldedAddress(_ address: String) throws -> Bool
static func isValidShieldedAddress(_ address: String, networkType: NetworkType) throws -> Bool
/**
- Returns: true when the address is valid and transparent. false in any other case
- Throws: Error when the provided address belongs to another network
*/
static func isValidTransparentAddress(_ address: String) throws -> Bool
static func isValidTransparentAddress(_ address: String, networkType: NetworkType) throws -> Bool
/**
- Returns: true when the address is valid and transparent. false in any other case
- Throws: Error when there's another problem not related to validity of the string in question
*/
static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool
static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool
/**
initialize the accounts table from a given seed and a number of accounts
@ -62,7 +62,7 @@ public protocol ZcashRustBackendWelding {
- seed: byte array of the zip32 seed
- accounts: how many accounts you want to have
*/
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]?
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]?
/**
initialize the accounts table from a set of unified viewing keys
@ -70,7 +70,7 @@ public protocol ZcashRustBackendWelding {
- dbData: location of the data db
- uvks: an array of UnifiedViewingKeys
*/
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey], networkType: NetworkType) throws -> Bool
/**
initialize the blocks table from a given checkpoint (birthday)
@ -81,7 +81,7 @@ public protocol ZcashRustBackendWelding {
- time: in milliseconds from reference
- saplingTree: hash of the sapling tree
*/
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) throws
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String, networkType: NetworkType) throws
/**
gets the address from data db from the given account
@ -90,38 +90,38 @@ public protocol ZcashRustBackendWelding {
- account: index of the given account
- Returns: an optional string with the address if found
*/
static func getAddress(dbData: URL, account: Int32) -> String?
static func getAddress(dbData: URL, account: Int32, networkType: NetworkType) -> String?
/**
get the (unverified) balance from the given account
- Parameters:
- dbData: location of the data db
- account: index of the given account
*/
static func getBalance(dbData: URL, account: Int32) -> Int64
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64
/**
get the verified balance from the given account
- Parameters:
- dbData: location of the data db
- account: index of the given account
*/
static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64
/**
Get the verified cached transparent balance for the given address
*/
static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64
static func getVerifiedTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64
/**
Get the verified cached transparent balance for the given address
*/
static func getTransparentBalance(dbData: URL, address: String) throws -> Int64
static func getTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64
/**
get received memo from note
- Parameters:
- dbData: location of the data db file
- idNote: note_id of note where the memo is located
*/
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String?
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String?
/**
get sent memo from note
@ -129,7 +129,7 @@ public protocol ZcashRustBackendWelding {
- dbData: location of the data db file
- idNote: note_id of note where the memo is located
*/
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String?
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String?
/**
Checks that the scanned blocks in the data database, when combined with the recent
@ -145,7 +145,7 @@ public protocol ZcashRustBackendWelding {
* `0` if there was an error during validation unrelated to chain validity.
- Important: This function does not mutate either of the databases.
*/
static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32
static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32
/**
Returns the nearest height where a rewind is possible. Currently prunning gets rid of sapling witnesses older
@ -155,14 +155,14 @@ public protocol ZcashRustBackendWelding {
- dbData: location of the data db file
- height: height you would like to rewind to.
*/
static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32
static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32
/**
rewinds the compact block storage to the given height. clears up all derived data as well
- Parameters:
- dbData: location of the data db file
- height: height to rewind to. DON'T PASS ARBITRARY HEIGHT. Use getNearestRewindHeight when unsure
*/
static func rewindToHeight(dbData: URL, height: Int32) -> Bool
static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool
/**
Scans new blocks added to the cache for any transactions received by the tracked
@ -183,7 +183,7 @@ public protocol ZcashRustBackendWelding {
- limit: scan up to limit blocks. pass 0 to set no limit.
returns false if fails to scan.
*/
static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32) -> Bool
static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool
/**
puts a UTXO into the data db database
@ -196,7 +196,7 @@ public protocol ZcashRustBackendWelding {
- height: the mined height for the UTXO
- Returns: true if the operation succeded or false otherwise
*/
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool
/**
clears the cached utxos for the given address from the specified height on
@ -207,7 +207,7 @@ public protocol ZcashRustBackendWelding {
- Returns: the amount of UTXOs cleared or -1 on error
*/
static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight) throws -> Int32
static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32
/**
Gets the balance of the previously downloaded UTXOs
- Parameters:
@ -216,7 +216,7 @@ public protocol ZcashRustBackendWelding {
- Returns: the wallet balance containing verified and total balance.
- Throws: Rustwelding Error if something fails
*/
static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance
static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance
/**
Scans a transaction for any information that can be decrypted by the accounts in the
@ -227,7 +227,7 @@ public protocol ZcashRustBackendWelding {
- tx: the transaction to decrypt
returns false if fails to decrypt.
*/
static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool
static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8], networkType: NetworkType) -> Bool
/**
Creates a transaction to the given address from the given account
@ -241,7 +241,7 @@ public protocol ZcashRustBackendWelding {
- spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located
- outputParamsPath: path escaped String for the filesystem locations where the output parameters are located
*/
static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64
static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64
/**
Creates a transaction to shield all found UTXOs in cache db.
@ -255,7 +255,7 @@ public protocol ZcashRustBackendWelding {
- spendParamsPath: path escaped String for the filesystem locations where the spend parameters are located
- outputParamsPath: path escaped String for the filesystem locations where the output parameters are located
*/
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64
/**
Derives a full viewing key from a seed
@ -263,7 +263,7 @@ public protocol ZcashRustBackendWelding {
- Returns: the derived key
- Throws: RustBackendError if fatal error occurs
*/
static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String?
static func deriveExtendedFullViewingKey(_ spendingKey: String, networkType: NetworkType) throws -> String?
/**
Derives a set of full viewing keys from a seed
@ -272,7 +272,7 @@ public protocol ZcashRustBackendWelding {
- Returns: an array containing the derived keys
- Throws: RustBackendError if fatal error occurs
*/
static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]?
static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]?
/**
Derives a set of full viewing keys from a seed
@ -281,7 +281,7 @@ public protocol ZcashRustBackendWelding {
- Returns: an array containing the spending keys
- Throws: RustBackendError if fatal error occurs
*/
static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]?
static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]?
/**
Derives a shielded address from a seed
@ -290,7 +290,7 @@ public protocol ZcashRustBackendWelding {
- Returns: an optional String containing the Shielded address
- Throws: RustBackendError if fatal error occurs
*/
static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String?
static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String?
/**
Derives a shielded address from an Extended Full Viewing Key
@ -298,7 +298,7 @@ public protocol ZcashRustBackendWelding {
- Returns: an optional String containing the Shielded address
- Throws: RustBackendError if fatal error occurs
*/
static func deriveShieldedAddressFromViewingKey(_ extfvk: String) throws -> String?
static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String?
/**
Derives a shielded address from an Extended Full Viewing Key
@ -306,14 +306,14 @@ public protocol ZcashRustBackendWelding {
- Returns: an optional String containing the transparent address
- Throws: RustBackendError if fatal error occurs
*/
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String?
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String?
/**
Derives a transparent secret key from Seed
- Parameter seed: an array of bytes containing the seed
- Returns: an optional String containing the transparent secret (private) key
*/
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String?
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String?
/**
Derives a transparent address from a secret key
@ -321,18 +321,18 @@ public protocol ZcashRustBackendWelding {
- Returns: an optional String containing the transparent address.
*/
static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String?
static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) 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 derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) throws -> String
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey]
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedViewingKey]
/**
Gets the consensus branch id for the given height
- Parameter height: the height you what to know the branch id for
*/
static func consensusBranchIdFor(height: Int32) throws -> Int32
static func consensusBranchIdFor(height: Int32, networkType: NetworkType) throws -> Int32
}

View File

@ -336,7 +336,7 @@ extension LightWalletGRPCService: LightWalletService {
return height
}
public func fetchUTXOs(for tAddress: String, height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> [UnspentTransactionOutputEntity] {
public func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
let arg = GetAddressUtxosArg.with { (utxoArgs) in
utxoArgs.addresses = [tAddress]
utxoArgs.startHeight = UInt64(height)
@ -358,7 +358,7 @@ extension LightWalletGRPCService: LightWalletService {
}
}
public func fetchUTXOs(for tAddress: String, height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
public func fetchUTXOs(for tAddress: String, height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
queue.async { [weak self] in
guard let self = self else { return }
let arg = GetAddressUtxosArg.with { (utxoArgs) in
@ -394,7 +394,7 @@ extension LightWalletGRPCService: LightWalletService {
}
}
public func fetchUTXOs(for tAddresses: [String], height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT) throws -> [UnspentTransactionOutputEntity] {
public func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
guard tAddresses.count > 0 else {
return [] // FIXME: throw a real error

View File

@ -16,17 +16,11 @@ extension CompactBlockRange {
extension BlockID {
static let saplingActivationHeight: UInt64 = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
init(height: UInt64) {
self = BlockID()
self.height = height
}
static var saplingActivation: BlockID {
BlockID(height: saplingActivationHeight)
}
init(height: BlockHeight) {
self.init(height: UInt64(height))
}
@ -46,16 +40,6 @@ extension BlockRange {
}
}
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
}
var compactBlockRange: CompactBlockRange {
return Int(self.start.height) ... Int(self.end.height)
}

View File

@ -394,7 +394,6 @@ extension SyncStatus {
}
}
extension SyncStatus {
init(_ blockProcessorProgress: CompactBlockProgress) {
switch blockProcessorProgress {

View File

@ -107,7 +107,11 @@ public class DerivationTool: KeyDeriving {
var rustwelding: ZcashRustBackendWelding.Type = ZcashRustBackend.self
public static let `default` = DerivationTool()
var networkType: NetworkType
public init(networkType: NetworkType) {
self.networkType = networkType
}
/**
Given a seed and a number of accounts, return the associated viewing keys.
@ -123,7 +127,7 @@ public class DerivationTool: KeyDeriving {
}
do {
guard let keys = try rustwelding.deriveExtendedFullViewingKeys(seed: seed, accounts: numberOfAccounts) else {
guard let keys = try rustwelding.deriveExtendedFullViewingKeys(seed: seed, accounts: numberOfAccounts, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return keys
@ -141,7 +145,7 @@ public class DerivationTool: KeyDeriving {
*/
public func deriveViewingKey(spendingKey: String) throws -> String {
do {
guard let key = try rustwelding.deriveExtendedFullViewingKey(spendingKey) else {
guard let key = try rustwelding.deriveExtendedFullViewingKey(spendingKey, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return key
@ -165,7 +169,7 @@ public class DerivationTool: KeyDeriving {
throw KeyDerivationErrors.invalidInput
}
do {
guard let keys = try rustwelding.deriveExtendedSpendingKeys(seed: seed, accounts: numberOfAccounts) else {
guard let keys = try rustwelding.deriveExtendedSpendingKeys(seed: seed, accounts: numberOfAccounts, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return keys
@ -189,7 +193,7 @@ public class DerivationTool: KeyDeriving {
}
do {
guard let address = try rustwelding.deriveShieldedAddressFromSeed(seed: seed, accountIndex: accountIndex) else {
guard let address = try rustwelding.deriveShieldedAddressFromSeed(seed: seed, accountIndex: accountIndex, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return address
@ -209,7 +213,7 @@ public class DerivationTool: KeyDeriving {
*/
public func deriveShieldedAddress(viewingKey: String) throws -> String {
do {
guard let zaddr = try rustwelding.deriveShieldedAddressFromViewingKey(viewingKey) else {
guard let zaddr = try rustwelding.deriveShieldedAddressFromViewingKey(viewingKey, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return zaddr
@ -220,7 +224,7 @@ public class DerivationTool: KeyDeriving {
public func deriveTransparentAddress(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String {
do {
guard let zaddr = try rustwelding.deriveTransparentAddressFromSeed(seed: seed, account: account, index: index) else {
guard let zaddr = try rustwelding.deriveTransparentAddressFromSeed(seed: seed, account: account, index: index, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return zaddr
@ -234,7 +238,7 @@ public class DerivationTool: KeyDeriving {
throw KeyDerivationErrors.invalidInput
}
do {
return try rustwelding.deriveUnifiedViewingKeyFromSeed(seed, numberOfAccounts: numberOfAccounts)
return try rustwelding.deriveUnifiedViewingKeyFromSeed(seed, numberOfAccounts: numberOfAccounts, networkType: networkType)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
@ -259,7 +263,7 @@ public class DerivationTool: KeyDeriving {
}
do {
return try rustwelding.derivedTransparentAddressFromPublicKey(pubkey)
return try rustwelding.derivedTransparentAddressFromPublicKey(pubkey, networkType: networkType)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
@ -273,7 +277,7 @@ public class DerivationTool: KeyDeriving {
*/
public func deriveTransparentPrivateKey(seed: [UInt8], account: Int = 0, index: Int = 0) throws -> String {
do {
guard let sk = try rustwelding.deriveTransparentPrivateKeyFromSeed(seed: seed, account: account, index: index) else {
guard let sk = try rustwelding.deriveTransparentPrivateKeyFromSeed(seed: seed, account: account, index: index, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return sk
@ -288,7 +292,7 @@ extension DerivationTool: KeyValidation {
public func isValidExtendedViewingKey(_ extvk: String) throws -> Bool {
do {
return try rustwelding.isValidExtendedFullViewingKey(extvk)
return try rustwelding.isValidExtendedFullViewingKey(extvk, networkType: networkType)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
@ -296,7 +300,7 @@ extension DerivationTool: KeyValidation {
public func isValidTransparentAddress(_ tAddress: String) throws -> Bool {
do {
return try rustwelding.isValidTransparentAddress(tAddress)
return try rustwelding.isValidTransparentAddress(tAddress, networkType: networkType)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
@ -304,7 +308,7 @@ extension DerivationTool: KeyValidation {
public func isValidShieldedAddress(_ zAddress: String) throws -> Bool {
do {
return try rustwelding.isValidShieldedAddress(zAddress)
return try rustwelding.isValidShieldedAddress(zAddress, networkType: networkType)
} catch {
throw KeyDerivationErrors.derivationError(underlyingError: error)
}
@ -318,7 +322,7 @@ extension DerivationTool: KeyValidation {
*/
public func deriveTransparentAddressFromPrivateKey(_ tsk: String) throws -> String {
do {
guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk) else {
guard let tAddr = try rustwelding.deriveTransparentAddressFromSecretKey(tsk, networkType: networkType) else {
throw KeyDerivationErrors.unableToDerive
}
return tAddr

View File

@ -24,10 +24,16 @@ class PersistentTransactionManager: OutboundTransactionManager {
var encoder: TransactionEncoder
var service: LightWalletService
var queue: DispatchQueue
init(encoder: TransactionEncoder, service: LightWalletService, repository: PendingTransactionRepository) {
var network: NetworkType
init(encoder: TransactionEncoder,
service: LightWalletService,
repository: PendingTransactionRepository,
networkType: NetworkType) {
self.repository = repository
self.encoder = encoder
self.service = service
self.network = networkType
self.queue = DispatchQueue.init(label: "PersistentTransactionManager.serial.queue", qos: .userInitiated)
}
@ -44,7 +50,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
queue.async { [weak self] in
guard let self = self else { return }
let derivationTool = DerivationTool()
let derivationTool = DerivationTool(networkType: self.network)
guard let vk = try? derivationTool.deriveViewingKey(spendingKey: spendingKey),
let zAddr = try? derivationTool.deriveShieldedAddress(viewingKey: vk) else {
result(.failure(TransactionManagerError.shieldingEncodingFailed(tx: pendingTransaction, reason: "There was an error Deriving your keys")))
@ -243,7 +249,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
class OutboundTransactionManagerBuilder {
static func build(initializer: Initializer) throws -> OutboundTransactionManager {
return PersistentTransactionManager(encoder: TransactionEncoderbuilder.build(initializer: initializer), service: initializer.lightWalletService, repository: try PendingTransactionRepositoryBuilder.build(initializer: initializer))
return PersistentTransactionManager(encoder: TransactionEncoderbuilder.build(initializer: initializer), service: initializer.lightWalletService, repository: try PendingTransactionRepositoryBuilder.build(initializer: initializer), networkType: initializer.network.networkType)
}
}

View File

@ -16,13 +16,15 @@ class WalletTransactionEncoder: TransactionEncoder {
private var spendParamsURL: URL
private var dataDbURL: URL
private var cacheDbURL: URL
private var networkType: NetworkType
init(rust: ZcashRustBackendWelding.Type,
dataDb: URL,
cacheDb: URL,
repository: TransactionRepository,
outputParams: URL,
spendParams: URL) {
spendParams: URL,
networkType: NetworkType) {
self.rustBackend = rust
self.dataDbURL = dataDb
@ -30,6 +32,7 @@ class WalletTransactionEncoder: TransactionEncoder {
self.repository = repository
self.outputParamsURL = outputParams
self.spendParamsURL = spendParams
self.networkType = networkType
self.queue = DispatchQueue(label: "wallet.transaction.encoder.serial.queue")
}
@ -40,7 +43,8 @@ class WalletTransactionEncoder: TransactionEncoder {
cacheDb: initializer.cacheDbURL,
repository: initializer.transactionRepository,
outputParams: initializer.outputParamsURL,
spendParams: initializer.spendParamsURL)
spendParams: initializer.spendParamsURL,
networkType: initializer.network.networkType)
}
@ -86,7 +90,8 @@ class WalletTransactionEncoder: TransactionEncoder {
value: Int64(zatoshi),
memo: memo,
spendParamsPath: self.spendParamsURL.path,
outputParamsPath: self.outputParamsURL.path)
outputParamsPath: self.outputParamsURL.path,
networkType: networkType)
guard txId > 0 else {
throw rustBackend.lastError() ?? RustWeldingError.genericError(message: "create spend failed")
@ -130,7 +135,8 @@ class WalletTransactionEncoder: TransactionEncoder {
extsk: spendingKey,
memo: memo,
spendParamsPath: self.spendParamsURL.path,
outputParamsPath: self.outputParamsURL.path)
outputParamsPath: self.outputParamsURL.path,
networkType: networkType)
guard txId > 0 else {
throw rustBackend.lastError() ?? RustWeldingError.genericError(message: "create spend failed")

View File

@ -124,9 +124,9 @@ public class SDKSynchronizer: Synchronizer {
public private(set) var progress: Float = 0.0
public private(set) var blockProcessor: CompactBlockProcessor
public private(set) var initializer: Initializer
public private(set)var latestScannedHeight: BlockHeight
public private(set) var latestScannedHeight: BlockHeight
public private(set) var connectionState: ConnectionState
public private(set) var network: ZcashNetwork
private var transactionManager: OutboundTransactionManager
private var transactionRepository: TransactionRepository
private var utxoRepository: UnspentTransactionOutputRepository
@ -159,7 +159,8 @@ public class SDKSynchronizer: Synchronizer {
self.utxoRepository = utxoRepository
self.blockProcessor = blockProcessor
self.latestScannedHeight = (try? transactionRepository.lastScannedHeight()) ?? initializer.walletBirthday.height
self.subscribeToProcessorNotifications(self.blockProcessor)
self.network = initializer.network
self.subscribeToProcessorNotifications(blockProcessor)
}
deinit {
@ -443,13 +444,14 @@ public class SDKSynchronizer: Synchronizer {
public func shieldFunds(spendingKey: String, transparentSecretKey: String, memo: String?, from accountIndex: Int, resultBlock: @escaping (Result<PendingTransactionEntity, Error>) -> Void) {
// let's see if there are funds to shield
let derivationTool = DerivationTool.default
let derivationTool = DerivationTool(networkType: self.network.networkType)
do {
let tAddr = try derivationTool.deriveTransparentAddressFromPrivateKey(transparentSecretKey)
let tBalance = try utxoRepository.balance(address: tAddr, latestHeight: self.latestDownloadedHeight())
guard tBalance.verified >= ZcashSDK.shieldingThreshold else {
// Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet.
guard tBalance.verified >= self.network.constants.defaultFee(for: self.latestScannedHeight) else {
resultBlock(.failure(ShieldFundsError.insuficientTransparentFunds))
return
}
@ -562,7 +564,7 @@ public class SDKSynchronizer: Synchronizer {
return
}
initializer.lightWalletService.fetchUTXOs(for: address, height: ZcashSDK.SAPLING_ACTIVATION_HEIGHT, result: { [weak self] r in
initializer.lightWalletService.fetchUTXOs(for: address, height: network.constants.SAPLING_ACTIVATION_HEIGHT, result: { [weak self] r in
guard let self = self else { return }
switch r {
case .success(let utxos):
@ -579,7 +581,7 @@ public class SDKSynchronizer: Synchronizer {
})
}
public func refreshUTXOs(address: String, from height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT, result: @escaping (Result<RefreshedUTXOs, Error>) -> Void) {
public func refreshUTXOs(address: String, from height: BlockHeight, result: @escaping (Result<RefreshedUTXOs, Error>) -> Void) {
self.blockProcessor.refreshUTXOs(tAddress: address, startHeight: height, result: result)
}
@ -635,7 +637,7 @@ public class SDKSynchronizer: Synchronizer {
height = rewindHeight
case .transaction(let tx):
guard let txHeight = tx.anchor else {
guard let txHeight = tx.anchor(network: self.network) else {
throw SynchronizerError.rewindErrorUnknownArchorHeight
}
height = txHeight
@ -846,4 +848,3 @@ fileprivate struct NullProgress: BlockProgressReporting {
0
}
}

View File

@ -13,7 +13,7 @@ typedef struct {
uintptr_t len;
} FFIUVKBoxedSlice;
int32_t zcashlc_branch_id_for_height(int32_t height);
int32_t zcashlc_branch_id_for_height(int32_t height, uint32_t network_id);
/**
* Clears the record of the last error message.
@ -23,7 +23,8 @@ void zcashlc_clear_last_error(void);
int32_t zcashlc_clear_utxos(const uint8_t *db_data,
uintptr_t db_data_len,
const char *taddress,
int32_t above_height);
int32_t above_height,
uint32_t network_id);
/**
* Creates a transaction paying the specified address from the given account.
@ -45,18 +46,20 @@ int64_t zcashlc_create_to_address(const uint8_t *db_data,
const uint8_t *spend_params,
uintptr_t spend_params_len,
const uint8_t *output_params,
uintptr_t output_params_len);
uintptr_t output_params_len,
uint32_t network_id);
int32_t zcashlc_decrypt_and_store_transaction(const uint8_t *db_data,
uintptr_t db_data_len,
const uint8_t *tx,
uintptr_t tx_len);
uintptr_t tx_len,
uint32_t network_id);
/**
* derives a shielded address from the given extended full viewing key.
* call zcashlc_string_free with the returned pointer when done using it
*/
char *zcashlc_derive_extended_full_viewing_key(const char *extsk);
char *zcashlc_derive_extended_full_viewing_key(const char *extsk, uint32_t network_id);
/**
* Derives Extended Full Viewing Keys from the given seed into 'accounts' number of accounts.
@ -68,7 +71,8 @@ char *zcashlc_derive_extended_full_viewing_key(const char *extsk);
char **zcashlc_derive_extended_full_viewing_keys(const uint8_t *seed,
uintptr_t seed_len,
int32_t accounts,
uintptr_t *capacity_ret);
uintptr_t *capacity_ret,
uint32_t network_id);
/**
* Derives Extended Spending Keys from the given seed into 'accounts' number of accounts.
@ -80,7 +84,8 @@ char **zcashlc_derive_extended_full_viewing_keys(const uint8_t *seed,
char **zcashlc_derive_extended_spending_keys(const uint8_t *seed,
uintptr_t seed_len,
int32_t accounts,
uintptr_t *capacity_ret);
uintptr_t *capacity_ret,
uint32_t network_id);
/**
* derives a shielded address from the given seed.
@ -88,24 +93,25 @@ char **zcashlc_derive_extended_spending_keys(const uint8_t *seed,
*/
char *zcashlc_derive_shielded_address_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t account_index);
int32_t account_index,
uint32_t network_id);
/**
* derives a shielded address from the given viewing key.
* call zcashlc_string_free with the returned pointer when done using it
*/
char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk);
char *zcashlc_derive_shielded_address_from_viewing_key(const char *extfvk, uint32_t network_id);
/**
* 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);
char *zcashlc_derive_transparent_address_from_public_key(const char *pubkey, uint32_t network_id);
/**
* Derives a transparent address from the given secret key enconded as a WIF string
*/
char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk);
char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk, uint32_t network_id);
/**
* Derives a transparent address from the given seed
@ -113,7 +119,8 @@ char *zcashlc_derive_transparent_address_from_secret_key(const char *tsk);
char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t account,
int32_t index);
int32_t index,
uint32_t network_id);
/**
* TEST TEST 123 TEST
@ -124,11 +131,13 @@ char *zcashlc_derive_transparent_address_from_seed(const uint8_t *seed,
char *zcashlc_derive_transparent_private_key_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t account,
int32_t index);
int32_t index,
uint32_t network_id);
FFIUVKBoxedSlice *zcashlc_derive_unified_viewing_keys_from_seed(const uint8_t *seed,
uintptr_t seed_len,
int32_t accounts);
int32_t accounts,
uint32_t network_id);
/**
* Copies the last error message into the provided allocated buffer.
@ -142,16 +151,23 @@ void zcashlc_free_uvk_array(FFIUVKBoxedSlice *uvks);
*
* Call `zcashlc_string_free` on the returned pointer when you are finished with it.
*/
char *zcashlc_get_address(const uint8_t *db_data, uintptr_t db_data_len, int32_t account);
char *zcashlc_get_address(const uint8_t *db_data,
uintptr_t db_data_len,
int32_t account,
uint32_t network_id);
/**
* Returns the balance for the account, including all unspent notes that we know about.
*/
int64_t zcashlc_get_balance(const uint8_t *db_data, uintptr_t db_data_len, int32_t account);
int64_t zcashlc_get_balance(const uint8_t *db_data,
uintptr_t db_data_len,
int32_t account,
uint32_t network_id);
int32_t zcashlc_get_nearest_rewind_height(const uint8_t *db_data,
uintptr_t db_data_len,
int32_t height);
int32_t height,
uint32_t network_id);
/**
* Returns the memo for a received note, if it is known and a valid UTF-8 string.
@ -163,7 +179,8 @@ int32_t zcashlc_get_nearest_rewind_height(const uint8_t *db_data,
*/
char *zcashlc_get_received_memo_as_utf8(const uint8_t *db_data,
uintptr_t db_data_len,
int64_t id_note);
int64_t id_note,
uint32_t network_id);
/**
* Returns the memo for a sent note, if it is known and a valid UTF-8 string.
@ -173,7 +190,10 @@ char *zcashlc_get_received_memo_as_utf8(const uint8_t *db_data,
*
* Call `zcashlc_string_free` on the returned pointer when you are finished with it.
*/
char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_len, int64_t id_note);
char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data,
uintptr_t db_data_len,
int64_t id_note,
uint32_t network_id);
/**
* Returns the verified transparent balance for the address, which ignores utxos that have been
@ -181,7 +201,8 @@ char *zcashlc_get_sent_memo_as_utf8(const uint8_t *db_data, uintptr_t db_data_le
*/
int64_t zcashlc_get_total_transparent_balance(const uint8_t *db_data,
uintptr_t db_data_len,
const char *address);
const char *address,
uint32_t network_id);
/**
* Returns the verified balance for the account, which ignores notes that have been
@ -189,7 +210,8 @@ int64_t zcashlc_get_total_transparent_balance(const uint8_t *db_data,
*/
int64_t zcashlc_get_verified_balance(const uint8_t *db_data,
uintptr_t db_data_len,
int32_t account);
int32_t account,
uint32_t network_id);
/**
* Returns the verified transparent balance for the address, which ignores utxos that have been
@ -197,7 +219,8 @@ int64_t zcashlc_get_verified_balance(const uint8_t *db_data,
*/
int64_t zcashlc_get_verified_transparent_balance(const uint8_t *db_data,
uintptr_t db_data_len,
const char *address);
const char *address,
uint32_t network_id);
/**
* Initialises the data database with the given number of accounts using the given seed.
@ -212,7 +235,8 @@ char **zcashlc_init_accounts_table(const uint8_t *db_data,
const uint8_t *seed,
uintptr_t seed_len,
int32_t accounts,
uintptr_t *capacity_ret);
uintptr_t *capacity_ret,
uint32_t network_id);
/**
* Initialises the data database with the given extended full viewing keys
@ -220,7 +244,8 @@ 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,
FFIUVKBoxedSlice *uvks);
FFIUVKBoxedSlice *uvks,
uint32_t network_id);
/**
* Initialises the data database with the given block.
@ -233,30 +258,33 @@ int32_t zcashlc_init_blocks_table(const uint8_t *db_data,
int32_t height,
const char *hash_hex,
uint32_t time,
const char *sapling_tree_hex);
const char *sapling_tree_hex,
uint32_t network_id);
/**
* Sets up the internal structure of the data database.
*/
int32_t zcashlc_init_data_database(const uint8_t *db_data, uintptr_t db_data_len);
int32_t zcashlc_init_data_database(const uint8_t *db_data,
uintptr_t db_data_len,
uint32_t network_id);
/**
* Returns true when the address is valid and shielded.
* Returns false in any other case
* Errors when the provided address belongs to another network
*/
bool zcashlc_is_valid_shielded_address(const char *address);
bool zcashlc_is_valid_shielded_address(const char *address, uint32_t network_id);
/**
* Returns true when the address is valid and transparent.
* Returns false in any other case
*/
bool zcashlc_is_valid_transparent_address(const char *address);
bool zcashlc_is_valid_transparent_address(const char *address, uint32_t network_id);
/**
* returns whether the given viewing key is valid or not
*/
bool zcashlc_is_valid_viewing_key(const char *key);
bool zcashlc_is_valid_viewing_key(const char *key, uint32_t network_id);
/**
* Returns the length of the last error message to be logged.
@ -272,7 +300,8 @@ bool zcashlc_put_utxo(const uint8_t *db_data,
const uint8_t *script_bytes,
uintptr_t script_bytes_len,
int64_t value,
int32_t height);
int32_t height,
uint32_t network_id);
/**
* Rewinds the data database to the given height.
@ -280,7 +309,10 @@ bool zcashlc_put_utxo(const uint8_t *db_data,
* If the requested height is greater than or equal to the height of the last scanned
* block, this function does nothing.
*/
bool zcashlc_rewind_to_height(const uint8_t *db_data, uintptr_t db_data_len, int32_t height);
bool zcashlc_rewind_to_height(const uint8_t *db_data,
uintptr_t db_data_len,
int32_t height,
uint32_t network_id);
/**
* Scans new blocks added to the cache for any transactions received by the tracked
@ -302,7 +334,8 @@ int32_t zcashlc_scan_blocks(const uint8_t *db_cache,
uintptr_t db_cache_len,
const uint8_t *db_data,
uintptr_t db_data_len,
uint32_t scan_limit);
uint32_t scan_limit,
uint32_t network_id);
int64_t zcashlc_shield_funds(const uint8_t *db_data,
uintptr_t db_data_len,
@ -313,7 +346,8 @@ int64_t zcashlc_shield_funds(const uint8_t *db_data,
const uint8_t *spend_params,
uintptr_t spend_params_len,
const uint8_t *output_params,
uintptr_t output_params_len);
uintptr_t output_params_len,
uint32_t network_id);
/**
* Frees strings returned by other zcashlc functions.
@ -341,7 +375,8 @@ void zcashlc_string_free(char *s);
int32_t zcashlc_validate_combined_chain(const uint8_t *db_cache,
uintptr_t db_cache_len,
const uint8_t *db_data,
uintptr_t db_data_len);
uintptr_t db_data_len,
uint32_t network_id);
/**
* Frees vectors of strings returned by other zcashlc functions.

View File

@ -24,12 +24,15 @@ class AdvancedReOrgTests: XCTestCase {
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
let network = DarksideWalletDNetwork()
override func setUpWithError() throws {
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
}

View File

@ -20,12 +20,14 @@ class BalanceTests: XCTestCase {
let chainName = "main"
var syncedExpectation = XCTestExpectation(description: "synced")
var sentTransactionExpectation = XCTestExpectation(description: "sent")
let network: ZcashNetwork = DarksideWalletDNetwork()
override func setUpWithError() throws {
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
@ -58,10 +60,10 @@ class BalanceTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
let maxBalance = verifiedBalance - Int64(ZcashSDK.defaultFee())
let maxBalance = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight))
// 3 create a transaction for the max amount possible
// 4 send the transaction
@ -196,10 +198,10 @@ class BalanceTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
let maxBalanceMinusOne = verifiedBalance - Int64(ZcashSDK.defaultFee()) - 1
let maxBalanceMinusOne = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight)) - 1
// 3 create a transaction for the max amount possible
// 4 send the transaction
@ -333,10 +335,10 @@ class BalanceTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
let maxBalanceMinusOne = 100000 - ZcashSDK.defaultFee()
let maxBalanceMinusOne = 100000 - network.constants.defaultFee(for: defaultLatestHeight)
// 3 create a transaction for the max amount possible
// 4 send the transaction
@ -483,7 +485,7 @@ class BalanceTests: XCTestCase {
/*
there's more zatoshi to send than network fee
*/
XCTAssertTrue(presendVerifiedBalance >= (Int64(ZcashSDK.MINERS_FEE_ZATOSHI) + sendAmount))
XCTAssertTrue(presendVerifiedBalance >= (Int64(network.constants.defaultFee(for: defaultLatestHeight)) + sendAmount))
var pendingTx: PendingTransactionEntity?
coordinator.synchronizer.sendToAddress(spendingKey: spendingKey,
@ -540,8 +542,8 @@ class BalanceTests: XCTestCase {
wait(for: [mineExpectation], timeout: 5)
XCTAssertEqual(presendVerifiedBalance - self.sendAmount - ZcashSDK.defaultFee(),coordinator.synchronizer.initializer.getBalance())
XCTAssertEqual(presendVerifiedBalance - self.sendAmount - ZcashSDK.defaultFee(),coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),coordinator.synchronizer.initializer.getBalance())
XCTAssertEqual(presendVerifiedBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),coordinator.synchronizer.initializer.getVerifiedBalance())
guard let transaction = pendingTx else {
XCTFail("pending transaction nil")
@ -629,7 +631,7 @@ class BalanceTests: XCTestCase {
}
let presendBalance = coordinator.synchronizer.initializer.getBalance()
XCTAssertTrue(presendBalance >= (Int64(ZcashSDK.defaultFee()) + sendAmount)) // there's more zatoshi to send than network fee
XCTAssertTrue(presendBalance >= (Int64(network.constants.defaultFee(for: defaultLatestHeight)) + sendAmount)) // there's more zatoshi to send than network fee
var pendingTx: PendingTransactionEntity?
@ -667,7 +669,7 @@ class BalanceTests: XCTestCase {
XCTAssertEqual(Int64(transaction.value), self.sendAmount)
XCTAssertEqual(self.coordinator.synchronizer.initializer.getBalance(), presendBalance - Int64(self.sendAmount) - ZcashSDK.defaultFee())
XCTAssertEqual(self.coordinator.synchronizer.initializer.getBalance(), presendBalance - Int64(self.sendAmount) - network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertNil(transaction.errorCode)
@ -697,7 +699,7 @@ class BalanceTests: XCTestCase {
wait(for: [mineExpectation], timeout: 5)
XCTAssertEqual(presendBalance - self.sendAmount - Int64(ZcashSDK.defaultFee()),coordinator.synchronizer.initializer.getBalance())
XCTAssertEqual(presendBalance - self.sendAmount - Int64(network.constants.defaultFee(for: defaultLatestHeight)),coordinator.synchronizer.initializer.getBalance())
}
/**
@ -869,7 +871,7 @@ class BalanceTests: XCTestCase {
/*
Theres a change note of value (previous note value - sent amount)
*/
XCTAssertEqual(previousVerifiedBalance - self.sendAmount - ZcashSDK.defaultFee(), Int64(receivedNote.value))
XCTAssertEqual(previousVerifiedBalance - self.sendAmount - self.network.constants.defaultFee(for: self.defaultLatestHeight), Int64(receivedNote.value))
/*
@ -1024,7 +1026,7 @@ class BalanceTests: XCTestCase {
func totalBalanceValidation(totalBalance: Int64,
previousTotalbalance: Int64,
sentAmount: Int64) {
XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - Int64(ZcashSDK.MINERS_FEE_ZATOSHI))
XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - Int64(network.constants.defaultFee(for: defaultLatestHeight)))
}
}

View File

@ -24,17 +24,18 @@ class BlockBatchValidationTests: XCTestCase {
}
func testBranchIdFailure() throws {
let service = MockLightWalletService(latestBlockHeight: 1210000)
let network = ZcashNetworkBuilder.network(for: .mainnet)
let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = 130000
info.branch = "d34db33f"
info.chainName = "main"
info.buildUser = "test user"
info.consensusBranchID = "d34db33f"
info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
service.mockLightDInfo = info
let mockRust = MockRustBackend.self
@ -63,17 +64,18 @@ class BlockBatchValidationTests: XCTestCase {
}
func testBranchNetworkMismatchFailure() throws {
let service = MockLightWalletService(latestBlockHeight: 1210000)
let network = ZcashNetworkBuilder.network(for: .mainnet)
let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = 130000
info.branch = "d34db33f"
info.chainName = "test"
info.buildUser = "test user"
info.consensusBranchID = "d34db4d"
info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
service.mockLightDInfo = info
let mockRust = MockRustBackend.self
@ -103,17 +105,18 @@ class BlockBatchValidationTests: XCTestCase {
func testBranchNetworkTypeWrongFailure() throws {
let service = MockLightWalletService(latestBlockHeight: 1210000)
let network = ZcashNetworkBuilder.network(for: .testnet)
let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = 130000
info.branch = "d34db33f"
info.chainName = "another"
info.buildUser = "test user"
info.consensusBranchID = "d34db4d"
info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
service.mockLightDInfo = info
let mockRust = MockRustBackend.self
@ -142,10 +145,11 @@ class BlockBatchValidationTests: XCTestCase {
}
func testSaplingActivationHeightMismatch() throws {
let service = MockLightWalletService(latestBlockHeight: 1210000)
let network = ZcashNetworkBuilder.network(for: .mainnet)
let service = MockLightWalletService(latestBlockHeight: 1210000, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let repository = ZcashConsoleFakeStorage(latestBlockHeight: 1220000)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = 130000
info.branch = "d34db33f"
@ -167,7 +171,7 @@ class BlockBatchValidationTests: XCTestCase {
operation.errorHandler = { error in
expectation.fulfill()
switch error {
case CompactBlockProcessorError.saplingActivationMismatch(expected: ZcashSDK.SAPLING_ACTIVATION_HEIGHT, found: BlockHeight(info.saplingActivationHeight)):
case CompactBlockProcessorError.saplingActivationMismatch(expected: network.constants.SAPLING_ACTIVATION_HEIGHT, found: BlockHeight(info.saplingActivationHeight)):
break
default:
XCTFail("Expected CompactBlockProcessorError.saplingActivationMismatch but found \(error)")
@ -181,20 +185,22 @@ class BlockBatchValidationTests: XCTestCase {
}
func testResultIsWait() throws {
let network = ZcashNetworkBuilder.network(for: .mainnet)
let expectedLatestHeight = BlockHeight(1210000)
let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight)
let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let expectedStoreLatestHeight = BlockHeight(1220000)
let expectedResult = FigureNextBatchOperation.NextState.wait(latestHeight: expectedLatestHeight, latestDownloadHeight: expectedLatestHeight)
let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: 1210000, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = UInt64(expectedLatestHeight)
info.branch = "d34db33f"
info.chainName = "main"
info.buildUser = "test user"
info.consensusBranchID = "d34db4d"
info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
service.mockLightDInfo = info
let mockRust = MockRustBackend.self
@ -207,7 +213,7 @@ class BlockBatchValidationTests: XCTestCase {
startedExpectation.fulfill()
}
operation.errorHandler = { error in
XCTFail("this shouldn't happen")
XCTFail("this shouldn't happen: \(error)")
}
operation.completionHandler = { (finished, cancelled) in
completedExpectation.fulfill()
@ -236,21 +242,22 @@ class BlockBatchValidationTests: XCTestCase {
}
func testResultProcessNew() throws {
let network = ZcashNetworkBuilder.network(for: .mainnet)
let expectedLatestHeight = BlockHeight(1230000)
let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight)
let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let expectedStoreLatestHeight = BlockHeight(1220000)
let walletBirthday = BlockHeight(1210000)
let expectedResult = FigureNextBatchOperation.NextState.processNewBlocks(range: CompactBlockProcessor.nextBatchBlockRange(latestHeight: expectedLatestHeight, latestDownloadedHeight: expectedStoreLatestHeight, walletBirthday: walletBirthday))
let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = UInt64(expectedLatestHeight)
info.branch = "d34db33f"
info.chainName = "main"
info.buildUser = "test user"
info.consensusBranchID = "d34db4d"
info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
service.mockLightDInfo = info
let mockRust = MockRustBackend.self
@ -292,21 +299,22 @@ class BlockBatchValidationTests: XCTestCase {
}
func testResultProcessorFinished() throws {
let network = ZcashNetworkBuilder.network(for: .mainnet)
let expectedLatestHeight = BlockHeight(1230000)
let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight)
let service = MockLightWalletService(latestBlockHeight: expectedLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default))
let expectedStoreLatestHeight = BlockHeight(1230000)
let walletBirthday = BlockHeight(1210000)
let expectedResult = FigureNextBatchOperation.NextState.finishProcessing(height: expectedStoreLatestHeight)
let repository = ZcashConsoleFakeStorage(latestBlockHeight: expectedStoreLatestHeight)
let downloader = CompactBlockDownloader(service: service, storage: repository)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
let config = CompactBlockProcessor.Configuration(cacheDb: try! __cacheDbURL(), dataDb: try! __dataDbURL(), downloadBatchSize: 100, retries: 5, maxBackoffInterval: 10, rewindDistance: 100, walletBirthday: walletBirthday, saplingActivation: network.constants.SAPLING_ACTIVATION_HEIGHT, network: network)
var info = LightdInfo()
info.blockHeight = UInt64(expectedLatestHeight)
info.branch = "d34db33f"
info.chainName = "main"
info.buildUser = "test user"
info.consensusBranchID = "d34db4d"
info.saplingActivationHeight = UInt64(ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
service.mockLightDInfo = info
let mockRust = MockRustBackend.self

View File

@ -14,10 +14,18 @@ class BlockDownloaderTests: XCTestCase {
var service: LightWalletService!
var storage: CompactBlockRepository!
var cacheDB = try! __cacheDbURL()
override func setUp() {
var network = DarksideWalletDNetwork()
var darksideWalletService: DarksideWalletService!
let branchID = "2bb40e60"
let chainName = "main"
override func setUpWithError() throws {
service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
storage = try! TestDbBuilder.diskCompactBlockStorage(at: cacheDB)
downloader = CompactBlockDownloader(service: service, storage: storage)
darksideWalletService = DarksideWalletService(service: service as! LightWalletGRPCService)
try FakeChainBuilder.buildChain(darksideWallet: darksideWalletService, branchID: branchID, chainName: chainName)
try darksideWalletService.applyStaged(nextLatestHeight: 663250)
}
override func tearDown() {
@ -32,8 +40,8 @@ class BlockDownloaderTests: XCTestCase {
let expect = XCTestExpectation(description: self.description)
expect.expectedFulfillmentCount = 3
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange))
downloader.downloadBlockRange(range) { (error) in
@ -58,8 +66,8 @@ class BlockDownloaderTests: XCTestCase {
func testSmallDownload() {
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange))
var latest: BlockHeight = 0
@ -86,12 +94,12 @@ class BlockDownloaderTests: XCTestCase {
}
func testFailure() {
let awfulDownloader = CompactBlockDownloader(service: AwfulLightWalletService(latestBlockHeight: ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000), storage: ZcashConsoleFakeStorage())
let awfulDownloader = CompactBlockDownloader(service: AwfulLightWalletService(latestBlockHeight: self.network.constants.SAPLING_ACTIVATION_HEIGHT + 1000, service: darksideWalletService), storage: ZcashConsoleFakeStorage())
let expect = XCTestExpectation(description: self.description)
expect.expectedFulfillmentCount = 1
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange))

View File

@ -20,9 +20,9 @@ class BlockScanOperationTests: XCTestCase {
extpub: "02075a7f5f7507d64022dad5954849f216b0f1b09b2d588be663d8e7faeb5aaf61")
var walletBirthDay = WalletBirthday.birthday(with: 1386000)
var walletBirthDay = WalletBirthday.birthday(with: 1386000, network: ZcashNetworkBuilder.network(for: .testnet))
var network = ZcashNetworkBuilder.network(for: .testnet)
var blockRepository: BlockRepository!
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
@ -47,17 +47,17 @@ class BlockScanOperationTests: XCTestCase {
func testSingleDownloadAndScanOperation() {
logger = SampleLogger(logLevel: .debug)
XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL))
XCTAssertNoThrow(try rustWelding.initDataDb(dbData: dataDbURL, networkType: network.networkType))
let downloadStartedExpect = XCTestExpectation(description: self.description + "download started")
let downloadExpect = XCTestExpectation(description: self.description + "download")
let scanStartedExpect = XCTestExpectation(description: self.description + "scan started")
let scanExpect = XCTestExpectation(description: self.description + "scan")
let latestScannedBlockExpect = XCTestExpectation(description: self.description + "latestScannedHeight")
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
let service = LightWalletGRPCService(endpoint: LightWalletEndpoint(address: "lightwalletd.testnet.electriccoin.co", port: 9067))
let blockCount = 100
let range = ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... ZcashSDK.SAPLING_ACTIVATION_HEIGHT + blockCount
let range = network.constants.SAPLING_ACTIVATION_HEIGHT ... network.constants.SAPLING_ACTIVATION_HEIGHT + blockCount
let downloadOperation = CompactBlockDownloadOperation(downloader: CompactBlockDownloader.sqlDownloader(service: service, at: cacheDbURL)!, range: range)
let scanOperation = CompactBlockScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL)
let scanOperation = CompactBlockScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, networkType: network.networkType)
downloadOperation.startedHandler = {
downloadStartedExpect.fulfill()
@ -119,15 +119,15 @@ class BlockScanOperationTests: XCTestCase {
NotificationCenter.default.addObserver(self, selector: #selector(observeBenchmark(_:)), name: SDKMetrics.notificationName, object: nil)
try self.rustWelding.initDataDb(dbData: dataDbURL)
guard try self.rustWelding.initAccountsTable(dbData: self.dataDbURL, uvks: [uvk]) else {
try self.rustWelding.initDataDb(dbData: dataDbURL, networkType: network.networkType)
guard try self.rustWelding.initAccountsTable(dbData: self.dataDbURL, uvks: [uvk], networkType: network.networkType) else {
XCTFail("failed to init account table")
return
}
try self.rustWelding.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthDay.height), hash: walletBirthDay.hash, time: walletBirthDay.time, saplingTree: walletBirthDay.tree)
try self.rustWelding.initBlocksTable(dbData: dataDbURL, height: Int32(walletBirthDay.height), hash: walletBirthDay.hash, time: walletBirthDay.time, saplingTree: walletBirthDay.tree, networkType: network.networkType)
let service = LightWalletGRPCService(host: Constants.address, port: 9067, secure: true, singleCallTimeout: 100000, streamingCallTimeout: 1000000000)
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
let storage = CompactBlockStorage(url: cacheDbURL, readonly: false)
try storage.createTable()
@ -161,7 +161,7 @@ class BlockScanOperationTests: XCTestCase {
}
let validationOperation = CompactBlockValidationOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL)
let validationOperation = CompactBlockValidationOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, networkType: network.networkType)
validationOperation.errorHandler = { error in
self.operationQueue.cancelAllOperations()
XCTFail("failed with error \(error)")
@ -174,7 +174,7 @@ class BlockScanOperationTests: XCTestCase {
}
let transactionRepository = TransactionRepositoryBuilder.build(dataDbURL: dataDbURL)
let scanningOperation = CompactBlockBatchScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, transactionRepository: transactionRepository, range: CompactBlockRange(uncheckedBounds: (walletBirthDay.height, walletBirthDay.height + 10000)), batchSize: 1000, progressDelegate: self)
let scanningOperation = CompactBlockBatchScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL, transactionRepository: transactionRepository, range: CompactBlockRange(uncheckedBounds: (walletBirthDay.height, walletBirthDay.height + 10000)), batchSize: 1000, networkType: network.networkType, progressDelegate: self)
scanningOperation.completionHandler = { (finished,cancelled) in
XCTAssert(finished)

View File

@ -23,14 +23,14 @@ class BlockStreamingTest: XCTestCase {
try? FileManager.default.removeItem(at: __dataDbURL())
}
func testExample() throws {
func testStreamOperation() throws {
let expectation = XCTestExpectation(description: "blockstream expectation")
let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co",
let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host,
port: 9067,
secure: true,
singleCallTimeout: Int64.max,
streamingCallTimeout: 1000)
singleCallTimeout: 1000,
streamingCallTimeout: 100000)
let latestHeight = try service.latestBlockHeight()
@ -55,43 +55,10 @@ class BlockStreamingTest: XCTestCase {
}
func testStreamOperation() throws {
let expectation = XCTestExpectation(description: "blockstream expectation")
let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co",
port: 9067,
secure: true,
singleCallTimeout: 1000,
streamingCallTimeout: 1000)
let storage = try TestDbBuilder.inMemoryCompactBlockStorage()
let startHeight = try service.latestBlockHeight() - 100_000
let operation = CompactBlockStreamDownloadOperation(service: service,
storage: storage,
startHeight: startHeight,
progressDelegate: self)
operation.completionHandler = { (finished, cancelled) in
if cancelled {
XCTFail("operation cancelled")
}
expectation.fulfill()
}
operation.errorHandler = { error in
XCTFail("failed with error: \(error)")
expectation.fulfill()
}
queue.addOperation(operation)
wait(for: [expectation], timeout: 1000)
}
func testStreamOperationCancellation() throws {
let expectation = XCTestExpectation(description: "blockstream expectation")
let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co",
let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host,
port: 9067,
secure: true,
singleCallTimeout: 10000,
@ -124,7 +91,7 @@ class BlockStreamingTest: XCTestCase {
func testStreamOperationTimeout() throws {
let expectation = XCTestExpectation(description: "blockstream expectation")
let errorExpectation = XCTestExpectation(description: "blockstream error expectation")
let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co",
let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host,
port: 9067,
secure: true,
singleCallTimeout: 1000,
@ -165,25 +132,18 @@ class BlockStreamingTest: XCTestCase {
let elapsed = now.distance(to: date)
print("took \(elapsed) seconds")
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
func testBatchOperation() throws {
let expectation = XCTestExpectation(description: "blockbatch expectation")
let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co",
let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host,
port: 9067,
secure: true,
singleCallTimeout: 300000,
streamingCallTimeout: 10000)
let storage = try TestDbBuilder.diskCompactBlockStorage(at: __dataDbURL() )
let targetHeight = try service.latestBlockHeight()
let startHeight = targetHeight - 100_000
let startHeight = targetHeight - 10_000
let operation = CompactBlockBatchDownloadOperation(service: service,
storage: storage,
startHeight: startHeight, targetHeight: targetHeight,
@ -203,13 +163,13 @@ class BlockStreamingTest: XCTestCase {
queue.addOperation(operation)
wait(for: [expectation], timeout: 300)
wait(for: [expectation], timeout: 120)
}
func testBatchOperationCancellation() throws {
let expectation = XCTestExpectation(description: "blockbatch expectation")
let service = LightWalletGRPCService(host: "lightwalletd.testnet.electriccoin.co",
let service = LightWalletGRPCService(host: LightWalletEndpointBuilder.eccTestnet.host,
port: 9067,
secure: true,
singleCallTimeout: 300000,
@ -243,6 +203,6 @@ class BlockStreamingTest: XCTestCase {
extension BlockStreamingTest: CompactBlockProgressDelegate {
func progressUpdated(_ progress: CompactBlockProgress) {
// print("progressHeight: \(progress.progressHeight) startHeight: \(progress.startHeight), targetHeight: \(progress.targetHeight)")
print("progressHeight: \(String(describing: progress.progressHeight)) startHeight: \(progress.progress), targetHeight: \(String(describing: progress.targetHeight))")
}
}

View File

@ -10,7 +10,7 @@ import XCTest
@testable import ZcashLightClientKit
class CompactBlockProcessorTests: XCTestCase {
let processorConfig = CompactBlockProcessor.Configuration.standard
let processorConfig = CompactBlockProcessor.Configuration.standard(for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT)
var processor: CompactBlockProcessor!
var downloadStartedExpect: XCTestExpectation!
var updatedNotificationExpectation: XCTestExpectation!
@ -18,12 +18,26 @@ class CompactBlockProcessorTests: XCTestCase {
var startedScanningNotificationExpectation: XCTestExpectation!
var startedValidatingNotificationExpectation: XCTestExpectation!
var idleNotificationExpectation: XCTestExpectation!
let mockLatestHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 2000
let network = ZcashNetworkBuilder.network(for: .testnet)
let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT + 2000
override func setUp() {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
logger = SampleLogger(logLevel: .debug)
let service = MockLightWalletService(latestBlockHeight: mockLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet))
let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType)
service.mockLightDInfo = LightdInfo.with({ info in
info.blockHeight = UInt64(mockLatestHeight)
info.branch = "asdf"
info.buildDate = "today"
info.buildUser = "testUser"
info.chainName = "test"
info.consensusBranchID = branchID.toString()
info.estimatedHeight = UInt64(mockLatestHeight)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
})
let service = MockLightWalletService(latestBlockHeight: mockLatestHeight)
let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString))
try! storage.createTable()
@ -32,7 +46,7 @@ class CompactBlockProcessorTests: XCTestCase {
storage: storage,
backend: ZcashRustBackend.self,
config: processorConfig)
try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, networkType: .testnet)
downloadStartedExpect = XCTestExpectation(description: self.description + " downloadStartedExpect")
stopNotificationExpectation = XCTestExpectation(description: self.description + " stopNotificationExpectation")
updatedNotificationExpectation = XCTestExpectation(description: self.description + " updatedNotificationExpectation")
@ -73,7 +87,7 @@ class CompactBlockProcessorTests: XCTestCase {
updatedNotificationExpectation.subscribe(to: Notification.Name.blockProcessorUpdated, object: processor)
startedValidatingNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedValidating, object: processor)
startedScanningNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedScanning, object: processor)
idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorIdle, object: processor)
idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorFinished, object: processor)
XCTAssertNoThrow(try processor.start())
}
@ -87,7 +101,7 @@ class CompactBlockProcessorTests: XCTestCase {
startedValidatingNotificationExpectation,
startedScanningNotificationExpectation,
idleNotificationExpectation,
], timeout: 260,enforceOrder: true)
], timeout: 30,enforceOrder: true)
}
func testProgressNotifications() {
@ -109,15 +123,15 @@ class CompactBlockProcessorTests: XCTestCase {
// test first range
var latestDownloadedHeight = processorConfig.walletBirthday // this can be either this or Wallet Birthday.
var latestBlockchainHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000)
var latestBlockchainHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 1000)
var expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight, upper:latestBlockchainHeight))
XCTAssertEqual(expectedBatchRange, CompactBlockProcessor.nextBatchBlockRange(latestHeight: latestBlockchainHeight, latestDownloadedHeight: latestDownloadedHeight, walletBirthday: processorConfig.walletBirthday))
// Test mid-range
latestDownloadedHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + ZcashSDK.DEFAULT_BATCH_SIZE)
latestBlockchainHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000)
latestDownloadedHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + ZcashSDK.DEFAULT_BATCH_SIZE)
latestBlockchainHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 1000)
expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight + 1, upper: latestBlockchainHeight))
@ -125,8 +139,8 @@ class CompactBlockProcessorTests: XCTestCase {
// Test last batch range
latestDownloadedHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 950)
latestBlockchainHeight = BlockHeight(ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 1000)
latestDownloadedHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 950)
latestBlockchainHeight = BlockHeight(network.constants.SAPLING_ACTIVATION_HEIGHT + 1000)
expectedBatchRange = CompactBlockRange(uncheckedBounds: (lower: latestDownloadedHeight + 1, upper: latestBlockchainHeight))

View File

@ -11,7 +11,7 @@ import XCTest
@testable import ZcashLightClientKit
class CompactBlockReorgTests: XCTestCase {
let processorConfig = CompactBlockProcessor.Configuration.standard
let processorConfig = CompactBlockProcessor.Configuration.standard(for: ZcashNetworkBuilder.network(for: .testnet), walletBirthday: ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT)
var processor: CompactBlockProcessor!
var downloadStartedExpect: XCTestExpectation!
var updatedNotificationExpectation: XCTestExpectation!
@ -20,19 +20,36 @@ class CompactBlockReorgTests: XCTestCase {
var startedValidatingNotificationExpectation: XCTestExpectation!
var idleNotificationExpectation: XCTestExpectation!
var reorgNotificationExpectation: XCTestExpectation!
let mockLatestHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 2000
let network = ZcashNetworkBuilder.network(for: .testnet)
let mockLatestHeight = ZcashNetworkBuilder.network(for: .testnet).constants.SAPLING_ACTIVATION_HEIGHT + 2000
override func setUp() {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
let service = MockLightWalletService(latestBlockHeight: mockLatestHeight)
logger = SampleLogger(logLevel: .debug)
let service = MockLightWalletService(latestBlockHeight: mockLatestHeight, service: LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet))
let branchID = try ZcashRustBackend.consensusBranchIdFor(height: Int32(mockLatestHeight), networkType: network.networkType)
service.mockLightDInfo = LightdInfo.with({ info in
info.blockHeight = UInt64(mockLatestHeight)
info.branch = "asdf"
info.buildDate = "today"
info.buildUser = "testUser"
info.chainName = "test"
info.consensusBranchID = branchID.toString()
info.estimatedHeight = UInt64(mockLatestHeight)
info.saplingActivationHeight = UInt64(network.constants.SAPLING_ACTIVATION_HEIGHT)
})
try ZcashRustBackend.initDataDb(dbData: processorConfig.dataDb, networkType: .testnet)
let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString))
try! storage.createTable()
let mockBackend = MockRustBackend.self
mockBackend.mockValidateCombinedChainFailAfterAttempts = 3
mockBackend.mockValidateCombinedChainKeepFailing = false
mockBackend.mockValidateCombinedChainFailureHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 320
mockBackend.mockValidateCombinedChainFailureHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT + 320
processor = CompactBlockProcessor(service: service,
storage: storage,
@ -69,8 +86,8 @@ class CompactBlockReorgTests: XCTestCase {
XCTAssertNotNil(notification.userInfo)
if let reorg = notification.userInfo?[CompactBlockProcessorNotificationKey.reorgHeight] as? BlockHeight,
let rewind = notification.userInfo?[CompactBlockProcessorNotificationKey.rewindHeight] as? BlockHeight {
XCTAssertTrue( reorg == 0 || reorg > ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( rewind == 0 || rewind > ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( reorg == 0 || reorg > self.network.constants.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( rewind == 0 || rewind > self.network.constants.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( rewind <= reorg )
reorgNotificationExpectation.fulfill()
} else {
@ -98,7 +115,7 @@ class CompactBlockReorgTests: XCTestCase {
updatedNotificationExpectation.subscribe(to: Notification.Name.blockProcessorUpdated, object: processor)
startedValidatingNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedValidating, object: processor)
startedScanningNotificationExpectation.subscribe(to: Notification.Name.blockProcessorStartedScanning, object: processor)
idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorIdle, object: processor)
idleNotificationExpectation.subscribe(to: Notification.Name.blockProcessorFinished, object: processor)
reorgNotificationExpectation.subscribe(to: Notification.Name.blockProcessorHandledReOrg, object: processor)
XCTAssertNoThrow(try processor.start())

View File

@ -13,13 +13,14 @@ class CompactBlockStorageTests: XCTestCase {
var compactBlockDao: CompactBlockRepository = try! TestDbBuilder.inMemoryCompactBlockStorage()
let network = ZcashNetworkBuilder.network(for: .testnet)
func testEmptyStorage() {
XCTAssertEqual(try! compactBlockDao.latestHeight(), BlockHeight.empty())
}
func testStoreThousandBlocks() {
let initialHeight = try! compactBlockDao.latestHeight()
let startHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let startHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount
@ -62,7 +63,7 @@ class CompactBlockStorageTests: XCTestCase {
func testRewindTo() {
let startHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let startHeight = self.network.constants.SAPLING_ACTIVATION_HEIGHT
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount

View File

@ -22,15 +22,20 @@ class DarksideSanityCheckTests: XCTestCase {
var sentTransactionExpectation = XCTestExpectation(description: "sent")
var expectedReorgHeight: BlockHeight = 665188
var expectedRewindHeight: BlockHeight = 665188
var network = DarksideWalletDNetwork()
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
override func setUpWithError() throws {
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main")
try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
try coordinator.resetBlocks(dataset: .default)
}

View File

@ -12,7 +12,7 @@ import SQLite
class DownloadOperationTests: XCTestCase {
var operationQueue = OperationQueue()
var network = ZcashNetworkBuilder.network(for: .testnet)
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
operationQueue.cancelAllOperations()
@ -21,11 +21,12 @@ class DownloadOperationTests: XCTestCase {
func testSingleOperation() {
let expect = XCTestExpectation(description: self.description)
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
let service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
let storage = try! TestDbBuilder.inMemoryCompactBlockStorage()
let downloader = CompactBlockDownloader(service: service, storage: storage)
let blockCount = 100
let range = ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... ZcashSDK.SAPLING_ACTIVATION_HEIGHT + blockCount
let activationHeight = network.constants.SAPLING_ACTIVATION_HEIGHT
let range = activationHeight ... activationHeight + blockCount
let downloadOperation = CompactBlockDownloadOperation(downloader: downloader, range: range)
downloadOperation.completionHandler = { (finished, cancelled) in

View File

@ -13,10 +13,11 @@ class LightWalletServiceTests: XCTestCase {
var service: LightWalletService!
var channel: Channel!
let network: ZcashNetwork = ZcashNetworkBuilder.network(for: .testnet)
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
channel = ChannelProvider().channel()
service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.eccTestnet)
}
override func tearDown() {
@ -39,8 +40,8 @@ class LightWalletServiceTests: XCTestCase {
func testHundredBlocks() {
let expect = XCTestExpectation(description: self.description)
let count = 99
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + count
let lowerRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + count
let blockRange = lowerRange ... upperRange
service.blockRange(blockRange) { (result) in
@ -60,8 +61,8 @@ class LightWalletServiceTests: XCTestCase {
}
func testSyncBlockRange() {
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = network.constants.SAPLING_ACTIVATION_HEIGHT + 99
let blockRange = lowerRange ... upperRange
do {
@ -80,7 +81,7 @@ class LightWalletServiceTests: XCTestCase {
case .failure(let e):
XCTFail("error: \(e)")
case .success(let height):
XCTAssertTrue(height > ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue(height > self.network.constants.SAPLING_ACTIVATION_HEIGHT)
}
}

View File

@ -19,7 +19,8 @@ class NetworkUpgradeTests: XCTestCase {
let branchID = "2bb40e60"
let chainName = "main"
var coordinator: TestCoordinator!
var network = ZcashNetworkBuilder.network(for: .testnet)
override func setUpWithError() throws {
// coordinator = try TestCoordinator(
@ -28,7 +29,7 @@ class NetworkUpgradeTests: XCTestCase {
// walletBirthday: birthday,
// channelProvider: ChannelProvider()
// )
try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main")
try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
}
override func tearDownWithError() throws {
@ -59,7 +60,7 @@ class NetworkUpgradeTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 120)
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
guard verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI else {
guard verifiedBalance > network.constants.defaultFee(for: activationHeight) else {
XCTFail("not enough balance to continue test")
return
}
@ -206,7 +207,7 @@ class NetworkUpgradeTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 120)
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI)
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: activationHeight))
@ -296,7 +297,7 @@ class NetworkUpgradeTests: XCTestCase {
wait(for: [firstSyncExpectation], timeout: 120)
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
guard verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI else {
guard verifiedBalance > network.constants.defaultFee(for: activationHeight) else {
XCTFail("balance is not enough to continue with this test")
return
}
@ -403,7 +404,7 @@ class NetworkUpgradeTests: XCTestCase {
var p: PendingTransactionEntity? = nil
// spend all the funds
let spendAmount: Int64 = postActivationBalance - Int64(ZcashSDK.MINERS_FEE_ZATOSHI)
let spendAmount: Int64 = postActivationBalance - Int64(network.constants.defaultFee(for: activationHeight))
/*
send transaction to recipient address

View File

@ -8,18 +8,18 @@
import XCTest
@testable import ZcashLightClientKit
class NullBytesTests: XCTestCase {
let networkType = NetworkType.mainnet
func testZaddrNullBytes() throws {
let validZaddr = "zs1gqtfu59z20s9t20mxlxj86zpw6p69l0ev98uxrmlykf2nchj2dw8ny5e0l22kwmld2afc37gkfp" // this is a valid zAddr. if you send ZEC to it, you will be contributing to Human Rights Foundation. see more ways to help at https://paywithz.cash/
let ZaddrWithNullBytes = "\(validZaddr)\0something else that makes the address invalid"
XCTAssertFalse(try ZcashRustBackend.isValidShieldedAddress(ZaddrWithNullBytes))
XCTAssertFalse(try ZcashRustBackend.isValidShieldedAddress(ZaddrWithNullBytes, networkType: networkType))
}
func testTaddrNullBytes() throws {
let validTAddr = "t1J5pTRzJi7j8Xw9VJTrPxPEkaigr69gKVT" // this is a valid tAddr. if you send ZEC to it, you will be contributing to Human Rights Foundation. see more ways to help at https://paywithz.cash/
let TaddrWithNullBytes = "\(validTAddr)\0fasdfasdf"
XCTAssertFalse(try ZcashRustBackend.isValidTransparentAddress(TaddrWithNullBytes))
XCTAssertFalse(try ZcashRustBackend.isValidTransparentAddress(TaddrWithNullBytes, networkType: networkType))
}
func testInitAccountTableNullBytes() throws {
@ -30,7 +30,7 @@ class NullBytesTests: XCTestCase {
let wrongTree = "0161f2ff97ff6ac6a90f9bce76c11710460f4944d8695aecc7dc99e34cad0131040011015325b185e23e82562db27817be996ffade9597181244f67efc40561aeb9dde1101daeffadc9e38f755bcb55a847a1278518a0ba4a2ef33b2fe01bbb3eb242ab0070000000000011c51f9077e3f7e28e8e337eaf4bb99b41acbc853a37dcc1e172467a1c919fe4100010bb1f55481b2268ef31997dc0fb6b48a530bc17870220f156d832326c433eb0a010b3768d3bf7868a67823e022f49be67982d0588e7041c498a756024\0750065a4a0001a9e1bf4bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
let goodTree = "0161f2ff97ff6ac6a90f9bce76c11710460f4944d8695aecc7dc99e34cad0131040011015325b185e23e82562db27817be996ffade9597181244f67efc40561aeb9dde1101daeffadc9e38f755bcb55a847a1278518a0ba4a2ef33b2fe01bbb3eb242ab0070000000000011c51f9077e3f7e28e8e337eaf4bb99b41acbc853a37dcc1e172467a1c919fe4100010bb1f55481b2268ef31997dc0fb6b48a530bc17870220f156d832326c433eb0a010b3768d3bf7868a67823e022f49be67982d0588e7041c498a756024750065a4a0001a9e1bf4bccb48b14b544e770f21d48f2d3ad8d6ca54eccc92f60634e3078eb48013a1f7fb005388ac6f04099b647ed85d8b025d8ae4b178c2376b473b121b8c052000001d2ea556f49fb934dc76f087935a5c07788000b4e3aae24883adfec51b5f4d260"
XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: wrongHash, time: time, saplingTree: goodTree), "InitBlocksTable with Null bytes on hash string should have failed") { (error) in
XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: wrongHash, time: time, saplingTree: goodTree, networkType: networkType), "InitBlocksTable with Null bytes on hash string should have failed") { (error) in
guard let rustError = error as? RustWeldingError else {
XCTFail("Expected RustWeldingError")
@ -45,7 +45,7 @@ class NullBytesTests: XCTestCase {
}
}
XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: goodHash, time: time, saplingTree: wrongTree), "InitBlocksTable with Null bytes on saplingTree string should have failed") { (error) in
XCTAssertThrowsError(try ZcashRustBackend.initBlocksTable(dbData: __dataDbURL(), height: height , hash: goodHash, time: time, saplingTree: wrongTree, networkType: networkType), "InitBlocksTable with Null bytes on saplingTree string should have failed") { (error) in
guard let rustError = error as? RustWeldingError else {
XCTFail("Expected RustWeldingError")
@ -66,7 +66,7 @@ class NullBytesTests: XCTestCase {
let goodSpendingKeys = "secret-extended-key-main1qw28psv0qqqqpqr2ru0kss5equx6h0xjsuk5299xrsgdqnhe0cknkl8uqff34prwkyuegyhh5d4rdr8025nl7e0hm8r2txx3fuea5mquy3wnsr9tlajsg4wwvw0xcfk8357k4h850rgj72kt4rx3fjdz99zs9f4neda35cq8tn3848yyvlg4w38gx75cyv9jdpve77x9eq6rtl6d9qyh8det4edevlnc70tg5kse670x50764gzhy60dta0yv3wsd4fsuaz686lgszc7nc9vv"
XCTAssertThrowsError(try ZcashRustBackend.deriveExtendedFullViewingKey(wrongSpendingKeys),"Should have thrown an error but didn't! this is dangerous!") { (error) in
XCTAssertThrowsError(try ZcashRustBackend.deriveExtendedFullViewingKey(wrongSpendingKeys, networkType: networkType),"Should have thrown an error but didn't! this is dangerous!") { (error) in
guard let rustError = error as? RustWeldingError else {
XCTFail("Expected RustWeldingError")
@ -81,7 +81,7 @@ class NullBytesTests: XCTestCase {
}
}
XCTAssertNoThrow(try ZcashRustBackend.deriveExtendedFullViewingKey(goodSpendingKeys))
XCTAssertNoThrow(try ZcashRustBackend.deriveExtendedFullViewingKey(goodSpendingKeys, networkType: networkType))
}

View File

@ -13,7 +13,7 @@ class PagedTransactionRepositoryTests: XCTestCase {
var transactionRepository: TransactionRepository!
override func setUp() {
transactionRepository = MockTransactionRepository(unminedCount: 5, receivedCount: 150, sentCount: 100)
transactionRepository = MockTransactionRepository(unminedCount: 5, receivedCount: 150, sentCount: 100, network: ZcashNetworkBuilder.network(for: .testnet))
pagedTransactionRepository = PagedTransactionDAO(repository: transactionRepository)
}

View File

@ -23,12 +23,14 @@ class PendingTransactionUpdatesTest: XCTestCase {
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
let network = DarksideWalletDNetwork()
override func setUpWithError() throws {
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}

View File

@ -22,25 +22,29 @@ import XCTest
class ReOrgTests: XCTestCase {
var seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" //TODO: Parameterize this from environment?
let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" //TODO: Parameterize this from environment
let sendAmount: Int64 = 1000
var birthday: BlockHeight = 663150
let defaultLatestHeight: BlockHeight = 663175
var coordinator: TestCoordinator!
var syncedExpectation = XCTestExpectation(description: "synced")
var sentTransactionExpectation = XCTestExpectation(description: "sent")
var expectedReorgHeight: BlockHeight = 665188
var expectedRewindHeight: BlockHeight = 665188
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
override func setUpWithError() throws {
let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" //TODO: Parameterize this from environment
let sendAmount: Int64 = 1000
var birthday: BlockHeight = 663150
let defaultLatestHeight: BlockHeight = 663175
var coordinator: TestCoordinator!
var syncedExpectation = XCTestExpectation(description: "synced")
var sentTransactionExpectation = XCTestExpectation(description: "sent")
var expectedReorgHeight: BlockHeight = 665188
var expectedRewindHeight: BlockHeight = 665188
let network = DarksideWalletDNetwork()
let branchID = "2bb40e60"
let chainName = "main"
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
override func setUpWithError() throws {
NotificationCenter.default.addObserver(self, selector: #selector(handleReOrgNotification(_:)), name: Notification.Name.blockProcessorHandledReOrg, object: nil)
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main")
try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
try coordinator.resetBlocks(dataset: .default)
}
@ -75,7 +79,7 @@ class ReOrgTests: XCTestCase {
let mockLatestHeight = BlockHeight(663200)
let targetLatestHeight = BlockHeight(663202)
let reOrgHeight = BlockHeight(663195)
let walletBirthday = WalletBirthday.birthday(with: 663150).height
let walletBirthday = WalletBirthday.birthday(with: 663150, network: network).height
try basicReOrgTest(baseDataset: .beforeReOrg,
reorgDataset: .afterSmallReorg,
@ -89,7 +93,7 @@ class ReOrgTests: XCTestCase {
let mockLatestHeight = BlockHeight(663200)
let targetLatestHeight = BlockHeight(663250)
let reOrgHeight = BlockHeight(663180)
let walletBirthday = WalletBirthday.birthday(with: BlockHeight(663150)).height
let walletBirthday = WalletBirthday.birthday(with: BlockHeight(663150), network: network).height
try basicReOrgTest(baseDataset: .beforeReOrg,
reorgDataset: .afterLargeReorg,
@ -107,7 +111,7 @@ class ReOrgTests: XCTestCase {
targetHeight: BlockHeight) throws {
do {
try coordinator.reset(saplingActivation: birthday, branchID: "e9ff75a6", chainName: "main")
try coordinator.reset(saplingActivation: birthday, branchID: branchID, chainName: chainName)
try coordinator.resetBlocks(dataset: .predefined(dataset: .beforeReOrg))
try coordinator.applyStaged(blockheight: firstLatestHeight)
} catch {

View File

@ -23,12 +23,14 @@ class RewindRescanTests: XCTestCase {
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
var network = ZcashNetworkBuilder.network(for: .mainnet)
override func setUpWithError() throws {
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}
@ -68,7 +70,7 @@ class RewindRescanTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
// rewind to birthday
@ -114,12 +116,12 @@ class RewindRescanTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
// rewind to birthday
let targetHeight: BlockHeight = newChaintTip - 8000
let rewindHeight = ZcashRustBackend.getNearestRewindHeight(dbData: coordinator.databases.dataDB, height: Int32(targetHeight))
let rewindHeight = ZcashRustBackend.getNearestRewindHeight(dbData: coordinator.databases.dataDB, height: Int32(targetHeight), networkType: network.networkType)
try coordinator.synchronizer.rewind(.height(blockheight: targetHeight))
@ -179,7 +181,7 @@ class RewindRescanTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
// 2 check that there are no unconfirmed funds
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
// rewind to transaction
@ -192,7 +194,7 @@ class RewindRescanTests: XCTestCase {
// assert that after the new height is
XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),transaction.transactionEntity.anchor)
XCTAssertEqual(try coordinator.synchronizer.initializer.transactionRepository.lastScannedHeight(),transaction.transactionEntity.anchor(network: network))
let secondScanExpectation = XCTestExpectation(description: "rescan")
@ -232,10 +234,10 @@ class RewindRescanTests: XCTestCase {
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
let totalBalance = coordinator.synchronizer.initializer.getBalance()
XCTAssertTrue(verifiedBalance > ZcashSDK.defaultFee())
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
XCTAssertEqual(verifiedBalance, totalBalance)
let maxBalance = verifiedBalance - Int64(ZcashSDK.defaultFee())
let maxBalance = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight))
// 3 create a transaction for the max amount possible
// 4 send the transaction

View File

@ -23,13 +23,15 @@ class SychronizerDarksideTests: XCTestCase {
var reorgExpectation: XCTestExpectation = XCTestExpectation(description: "reorg")
let branchID = "2bb40e60"
let chainName = "main"
let network = DarksideWalletDNetwork()
var foundTransactions = [ConfirmedTransactionEntity]()
override func setUpWithError() throws {
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
channelProvider: ChannelProvider()
channelProvider: ChannelProvider(),
network: network
)
try coordinator.reset(saplingActivation: 663150, branchID: "e9ff75a6", chainName: "main")
}

View File

@ -43,32 +43,36 @@ class TestCoordinator {
var service: DarksideWalletService
var spendingKeys: [String]?
var databases: TemporaryTestDatabases
let network: ZcashNetwork
convenience init(seed: String,
walletBirthday: BlockHeight,
channelProvider: ChannelProvider) throws {
guard let spendingKey = try DerivationTool.default.deriveSpendingKeys(
channelProvider: ChannelProvider,
network: ZcashNetwork) throws {
let derivationTool = DerivationTool(networkType: network.networkType)
guard let spendingKey = try derivationTool.deriveSpendingKeys(
seed: TestSeed().seed(),
numberOfAccounts: 1).first else {
throw CoordinatorError.builderError
}
guard let uvk = try DerivationTool.default.deriveUnifiedViewingKeysFromSeed(TestSeed().seed(), numberOfAccounts: 1).first else {
guard let uvk = try derivationTool.deriveUnifiedViewingKeysFromSeed(TestSeed().seed(), numberOfAccounts: 1).first else {
throw CoordinatorError.builderError
}
try self.init(spendingKey: spendingKey, unifiedViewingKey: uvk, walletBirthday: walletBirthday, channelProvider: channelProvider)
try self.init(spendingKey: spendingKey, unifiedViewingKey: uvk, walletBirthday: walletBirthday, channelProvider: channelProvider, network: network)
}
required init(
spendingKey: String,
unifiedViewingKey: UnifiedViewingKey,
walletBirthday: BlockHeight,
channelProvider: ChannelProvider) throws {
walletBirthday: BlockHeight,
channelProvider: ChannelProvider,
network: ZcashNetwork) throws {
self.spendingKey = spendingKey
self.birthday = walletBirthday
self.channelProvider = channelProvider
self.databases = TemporaryDbBuilder.build()
self.network = network
self.service = DarksideWalletService(service: LightWalletGRPCService(host: Constants.address, port: 9067, secure: false, singleCallTimeout: 10000, streamingCallTimeout: 1000000))
let storage = CompactBlockStorage(url: databases.cacheDB, readonly: false)
try storage.createTable()
@ -89,7 +93,8 @@ class TestCoordinator {
outputParamsURL: try __outputParamsURL(),
spendingKey: spendingKey,
unifiedViewingKey: unifiedViewingKey,
walletBirthday: WalletBirthday.birthday(with: birthday),
walletBirthday: WalletBirthday.birthday(with: birthday, network: network),
network: network,
loggerProxy: SampleLogger(logLevel: .debug))
self.synchronizer = buildResult.synchronizer
@ -210,7 +215,8 @@ extension TestCoordinator {
maxBackoffInterval: config.maxBackoffInterval,
rewindDistance: config.rewindDistance,
walletBirthday: config.walletBirthday,
saplingActivation: config.saplingActivation)
saplingActivation: config.saplingActivation,
network: config.network)
try service.reset(saplingActivation: saplingActivation, branchID: branchID, chainName: chainName)
}
@ -254,11 +260,13 @@ class TestSynchronizerBuilder {
spendingKey: String,
unifiedViewingKey: UnifiedViewingKey,
walletBirthday: WalletBirthday,
network: ZcashNetwork,
loggerProxy: Logger? = nil
) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) {
let initializer = Initializer(
rustBackend: rustBackend,
lowerBoundHeight: lowerBoundHeight,
network: network,
cacheDbURL: cacheDbURL,
dataDbURL: dataDbURL,
pendingDbURL: pendingDbURL,
@ -281,7 +289,8 @@ class TestSynchronizerBuilder {
maxBackoffInterval: ZcashSDK.DEFAULT_MAX_BACKOFF_INTERVAL,
rewindDistance: ZcashSDK.DEFAULT_REWIND_DISTANCE,
walletBirthday: walletBirthday.height,
saplingActivation: lowerBoundHeight)
saplingActivation: lowerBoundHeight,
network: network)
let processor = CompactBlockProcessor(service: service,
storage: storage,
@ -318,13 +327,14 @@ class TestSynchronizerBuilder {
outputParamsURL: URL,
seedBytes: [UInt8],
walletBirthday: WalletBirthday,
network: ZcashNetwork,
loggerProxy: Logger? = nil
) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) {
guard let spendingKey = try DerivationTool().deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
guard let spendingKey = try DerivationTool(networkType: network.networkType).deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else {
throw TestCoordinator.CoordinatorError.builderError
}
guard let uvk = try DerivationTool().deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: 1).first else {
guard let uvk = try DerivationTool(networkType: network.networkType).deriveUnifiedViewingKeysFromSeed(seedBytes, numberOfAccounts: 1).first else {
throw TestCoordinator.CoordinatorError.builderError
}
return try build(rustBackend: rustBackend,
@ -341,7 +351,8 @@ class TestSynchronizerBuilder {
outputParamsURL: outputParamsURL,
spendingKey: spendingKey,
unifiedViewingKey: uvk,
walletBirthday: walletBirthday)
walletBirthday: walletBirthday,
network: network)
}
}

View File

@ -26,34 +26,12 @@ class TransactionEnhancementTests: XCTestCase {
let mockLatestHeight = BlockHeight(663250)
let targetLatestHeight = BlockHeight(663251)
let walletBirthday = BlockHeight(663150)
let network = DarksideWalletDNetwork()
let branchID = "2bb40e60"
let chainName = "main"
override func setUpWithError() throws {
logger = SampleLogger(logLevel: .debug)
var config = CompactBlockProcessor.Configuration.standard
let rustBackend = ZcashRustBackend.self
let birthday = WalletBirthday.birthday(with: walletBirthday)
config.walletBirthday = birthday.height
processorConfig = config
try? FileManager.default.removeItem(at: processorConfig.cacheDb)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
_ = rustBackend.initAccountsTable(dbData: processorConfig.dataDb, seed: TestSeed().seed(), accounts: 1)
let service = DarksideWalletService()
darksideWalletService = service
let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString))
try! storage.createTable()
downloader = CompactBlockDownloader(service: service, storage: storage)
processor = CompactBlockProcessor(service: service,
storage: storage,
backend: rustBackend,
config: processorConfig)
downloadStartedExpect = XCTestExpectation(description: self.description + " downloadStartedExpect")
stopNotificationExpectation = XCTestExpectation(description: self.description + " stopNotificationExpectation")
updatedNotificationExpectation = XCTestExpectation(description: self.description + " updatedNotificationExpectation")
@ -66,11 +44,39 @@ class TransactionEnhancementTests: XCTestCase {
waitExpectation = XCTestExpectation(description: self.description + "waitExpectation")
let birthday = WalletBirthday.birthday(with: walletBirthday, network: network)
let config = CompactBlockProcessor.Configuration.standard(for: self.network, walletBirthday: birthday.height)
let rustBackend = ZcashRustBackend.self
processorConfig = config
try? FileManager.default.removeItem(at: processorConfig.cacheDb)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
_ = rustBackend.initAccountsTable(dbData: processorConfig.dataDb, seed: TestSeed().seed(), accounts: 1,networkType: network.networkType)
_ = try rustBackend.initDataDb(dbData: processorConfig.dataDb, networkType: network.networkType)
_ = try rustBackend.initBlocksTable(dbData: processorConfig.dataDb, height: Int32(birthday.height), hash: birthday.hash, time: birthday.time, saplingTree: birthday.tree, networkType: network.networkType)
let service = DarksideWalletService()
darksideWalletService = service
let storage = CompactBlockStorage.init(connectionProvider: SimpleConnectionProvider(path: processorConfig.cacheDb.absoluteString))
try! storage.createTable()
downloader = CompactBlockDownloader(service: service, storage: storage)
processor = CompactBlockProcessor(service: service,
storage: storage,
backend: rustBackend,
config: processorConfig)
NotificationCenter.default.addObserver(self, selector: #selector(processorFailed(_:)), name: Notification.Name.blockProcessorFailed, object: processor)
}
override func tearDownWithError() throws {
try! FileManager.default.removeItem(at: processorConfig.cacheDb)
try? FileManager.default.removeItem(at: processorConfig.cacheDb)
try? FileManager.default.removeItem(at: processorConfig.dataDb)
downloadStartedExpect.unsubscribeFromNotifications()
stopNotificationExpectation.unsubscribeFromNotifications()
@ -100,7 +106,7 @@ class TransactionEnhancementTests: XCTestCase {
func testBasicEnhacement() throws {
let targetLatestHeight = BlockHeight(663250)
let walletBirthday = WalletBirthday.birthday(with: 663151).height
let walletBirthday = WalletBirthday.birthday(with: 663151, network: network).height
try basicEnhancementTest(latestHeight: targetLatestHeight, walletBirthday: walletBirthday)
}
@ -108,12 +114,15 @@ class TransactionEnhancementTests: XCTestCase {
func basicEnhancementTest(latestHeight: BlockHeight, walletBirthday: BlockHeight) throws {
do {
try darksideWalletService.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
try darksideWalletService.useDataset(DarksideDataset.beforeReOrg.rawValue)
try darksideWalletService.applyStaged(nextLatestHeight: 663200)
} catch {
XCTFail("Error: \(error)")
return
}
sleep(3)
/**
connect to dLWD
request latest height -> receive firstLatestHeight
@ -124,12 +133,13 @@ class TransactionEnhancementTests: XCTestCase {
XCTFail("Error: \(error)")
return
}
/**
download and sync blocks from walletBirthday to firstLatestHeight
*/
do {
try startProcessing()
} catch {
@ -155,3 +165,4 @@ class TransactionEnhancementTests: XCTestCase {
}
}

View File

@ -15,7 +15,8 @@ class WalletTests: XCTestCase {
var dbData: URL! = nil
var paramDestination: URL! = nil
var cacheData: URL! = nil
var network = ZcashNetworkBuilder.network(for: .testnet)
var seedData: Data = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")!
override func setUp() {
dbData = try! __dataDbURL()
@ -29,23 +30,30 @@ 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() throws {
let derivationTool = DerivationTool(networkType: network.networkType)
let uvk = try derivationTool.deriveUnifiedViewingKeysFromSeed(seedData.bytes, numberOfAccounts: 1)
let wallet = Initializer(cacheDbURL: try __cacheDbURL(),
dataDbURL: try __dataDbURL(),
pendingDbURL: try TestDbBuilder.pendingTransactionsDbURL(),
endpoint: LightWalletEndpointBuilder.default,
network: network,
spendParamsURL: try __spendParamsURL(),
outputParamsURL: try __outputParamsURL(),
viewingKeys: uvk,
walletBirthday: 663194)
let synchronizer = try SDKSynchronizer(initializer: wallet)
XCTAssertNoThrow(try synchronizer.prepare())
// 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

@ -18,7 +18,7 @@ class ZcashLightClientKitTests: XCTestCase {
var service: LightWalletGRPCService!
override func setUp() {
super.setUp()
service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
service = LightWalletGRPCService(endpoint: LightWalletEndpoint(address: Constants.address, port: 9067))
latestBlockHeight = try! service.latestBlock().compactBlockHeight()!
}

View File

@ -16,6 +16,9 @@ class ZcashRustBackendTests: XCTestCase {
let spendingKey = "secret-extended-key-test1qvpevftsqqqqpqy52ut2vv24a2qh7nsukew7qg9pq6djfwyc3xt5vaxuenshp2hhspp9qmqvdh0gs2ljpwxders5jkwgyhgln0drjqaguaenfhehz4esdl4kwlm5t9q0l6wmzcrvcf5ed6dqzvct3e2ge7f6qdvzhp02m7sp5a0qjssrwpdh7u6tq89hl3wchuq8ljq8r8rwd6xdwh3nry9at80z7amnj3s6ah4jevnvfr08gxpws523z95g6dmn4wm6l3658kd4xcq9rc0qn"
let recipientAddress = "ztestsapling1ctuamfer5xjnnrdr3xdazenljx0mu0gutcf9u9e74tr2d3jwjnt0qllzxaplu54hgc2tyjdc2p6"
let zpend: Int = 500_000
let networkType = NetworkType.testnet
override func setUp() {
dbData = try! __dataDbURL()
try? dataDbHandle.setUp()
@ -30,9 +33,9 @@ class ZcashRustBackendTests: XCTestCase {
func testInitWithShortSeedAndFail() {
let seed = "testreferencealice"
XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!))
XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!, networkType: networkType))
let _ = ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1)
let _ = ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1, networkType: networkType)
XCTAssertNotNil(ZcashRustBackend.getLastError())
}
@ -41,7 +44,7 @@ class ZcashRustBackendTests: XCTestCase {
let seed = Array("testreferencealicetestreferencealice".utf8)
var spendingKeys: [String]? = nil
XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1) }())
XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1, networkType: networkType) }())
XCTAssertNotNil(spendingKeys)
XCTAssertFalse(spendingKeys?.first?.isEmpty ?? true)
@ -52,7 +55,7 @@ class ZcashRustBackendTests: XCTestCase {
let seed = Array("testreferencealicetestreferencealice".utf8)
var fullViewingKeys: [String]? = nil
XCTAssertNoThrow(try { fullViewingKeys = try ZcashRustBackend.deriveExtendedFullViewingKeys(seed: seed, accounts: 1) }())
XCTAssertNoThrow(try { fullViewingKeys = try ZcashRustBackend.deriveExtendedFullViewingKeys(seed: seed, accounts: 1, networkType: networkType) }())
XCTAssertNotNil(fullViewingKeys)
XCTAssertFalse(fullViewingKeys?.first?.isEmpty ?? true)
@ -64,7 +67,7 @@ class ZcashRustBackendTests: XCTestCase {
var spendingKeys: [String]? = nil
XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1) }())
XCTAssertNoThrow(try { spendingKeys = try ZcashRustBackend.deriveExtendedSpendingKeys(seed: seed, accounts: 1, networkType: networkType) }())
XCTAssertNotNil(spendingKeys)
XCTAssertFalse(spendingKeys?.first?.isEmpty ?? true)
@ -74,7 +77,7 @@ class ZcashRustBackendTests: XCTestCase {
return
}
XCTAssertNoThrow(try { fullViewingKey = try ZcashRustBackend.deriveExtendedFullViewingKey(spendingKey) }())
XCTAssertNoThrow(try { fullViewingKey = try ZcashRustBackend.deriveExtendedFullViewingKey(spendingKey, networkType: networkType) }())
XCTAssertNotNil(fullViewingKey)
XCTAssertFalse(fullViewingKey?.isEmpty ?? true)
@ -86,24 +89,24 @@ class ZcashRustBackendTests: XCTestCase {
return
}
let seed = "testreferencealicetestreferencealice"
XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!))
XCTAssertNoThrow(try ZcashRustBackend.initDataDb(dbData: dbData!, networkType: networkType))
XCTAssertEqual(ZcashRustBackend.getLastError(), nil)
XCTAssertNotNil(ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1))
XCTAssertNotNil(ZcashRustBackend.initAccountsTable(dbData: dbData!, seed: Array(seed.utf8), accounts: 1, networkType: networkType))
XCTAssertEqual(ZcashRustBackend.getLastError(), nil)
let addr = ZcashRustBackend.getAddress(dbData: dbData!, account: 0)
let addr = ZcashRustBackend.getAddress(dbData: dbData!, account: 0, networkType: networkType)
XCTAssertEqual(ZcashRustBackend.getLastError(), nil)
XCTAssertEqual(addr, Optional("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc"))
XCTAssertTrue(ZcashRustBackend.scanBlocks(dbCache: cacheDb, dbData: dbData))
XCTAssertTrue(ZcashRustBackend.scanBlocks(dbCache: cacheDb, dbData: dbData, networkType: networkType))
}
func testIsValidTransparentAddressFalse() {
var isValid: Bool? = nil
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc") }())
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc", networkType: networkType) }())
if let valid = isValid {
XCTAssertFalse(valid)
@ -117,7 +120,7 @@ class ZcashRustBackendTests: XCTestCase {
func testIsValidTransparentAddressTrue() {
var isValid: Bool? = nil
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7") }())
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidTransparentAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7", networkType: networkType) }())
if let valid = isValid {
XCTAssertTrue(valid)
@ -129,7 +132,7 @@ class ZcashRustBackendTests: XCTestCase {
func testIsValidShieldedAddressTrue() {
var isValid: Bool? = nil
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc") }())
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc", networkType: networkType) }())
if let valid = isValid {
XCTAssertTrue(valid)
@ -141,7 +144,7 @@ class ZcashRustBackendTests: XCTestCase {
func testIsValidShieldedAddressFalse() {
var isValid: Bool? = nil
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7") }())
XCTAssertNoThrow(try { isValid = try ZcashRustBackend.isValidShieldedAddress("tmSwpioc7reeoNrYB9SKpWkurJz3yEj3ee7", networkType: networkType) }())
if let valid = isValid {
XCTAssertFalse(valid)

View File

@ -199,3 +199,38 @@ class DarksideWalletService: LightWalletService {
}
}
class DarksideWalletDConstants: NetworkConstants {
static var SAPLING_ACTIVATION_HEIGHT: BlockHeight {
663150
}
static var DEFAULT_DATA_DB_NAME: String {
ZcashSDKMainnetConstants.DEFAULT_DATA_DB_NAME
}
static var DEFAULT_CACHES_DB_NAME: String {
ZcashSDKMainnetConstants.DEFAULT_CACHES_DB_NAME
}
static var DEFAULT_PENDING_DB_NAME: String {
ZcashSDKMainnetConstants.DEFAULT_PENDING_DB_NAME
}
static var DEFAULT_DB_NAME_PREFIX: String {
ZcashSDKMainnetConstants.DEFAULT_DB_NAME_PREFIX
}
static var FEE_CHANGE_HEIGHT: BlockHeight {
ZcashSDKMainnetConstants.FEE_CHANGE_HEIGHT
}
}
class DarksideWalletDNetwork: ZcashNetwork {
var constants: NetworkConstants.Type = DarksideWalletDConstants.self
var networkType = NetworkType.mainnet
}

View File

@ -68,13 +68,15 @@ class MockLightWalletService: LightWalletService {
}
private var service = LightWalletGRPCService(endpoint: LightWalletEndpointBuilder.default)
private var service: LightWalletService
var latestHeight: BlockHeight
init(latestBlockHeight: BlockHeight) {
init(latestBlockHeight: BlockHeight, service: LightWalletService) {
self.latestHeight = latestBlockHeight
self.service = service
}
func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
result(.success(self.latestHeight))

View File

@ -44,10 +44,15 @@ class MockTransactionRepository: TransactionRepository {
receivedCount + sentCount
}
init(unminedCount: Int, receivedCount: Int, sentCount: Int) {
var network: ZcashNetwork
init(unminedCount: Int,
receivedCount: Int,
sentCount: Int,
network: ZcashNetwork) {
self.unminedCount = unminedCount
self.receivedCount = receivedCount
self.sentCount = sentCount
self.network = network
}
func generate() {
@ -148,7 +153,7 @@ class MockTransactionRepository: TransactionRepository {
}
func randomBlockHeight() -> BlockHeight {
BlockHeight.random(in: ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... 1_000_000)
BlockHeight.random(in: network.constants.SAPLING_ACTIVATION_HEIGHT ... 1_000_000)
}
func randomTimeInterval() -> TimeInterval {
Double.random(in: Date().timeIntervalSince1970 - 1000000.0 ... Date().timeIntervalSince1970)

View File

@ -77,104 +77,108 @@ extension LightWalletServiceMockResponse {
}
class MockRustBackend: ZcashRustBackendWelding {
static func getNearestRewindHeight(dbData: URL, height: Int32) -> Int32 {
static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 {
-1
}
static func clearUtxos(dbData: URL, address: String, sinceHeight: BlockHeight) throws -> Int32 {
static func getNearestRewindHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Int32 {
-1
}
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey]) throws -> Bool {
static func network(dbData: URL, address: String, sinceHeight: BlockHeight, networkType: NetworkType) throws -> Int32 {
-1
}
static func initAccountsTable(dbData: URL, uvks: [UnifiedViewingKey], networkType: NetworkType) throws -> Bool {
false
}
static func getVerifiedTransparentBalance(dbData: URL, address: String) throws -> Int64 {
static func getVerifiedTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 {
-1
}
static func getTransparentBalance(dbData: URL, address: String) throws -> Int64 {
static func getTransparentBalance(dbData: URL, address: String, networkType: NetworkType) throws -> Int64 {
-1
}
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight) throws -> Bool {
static func putUnspentTransparentOutput(dbData: URL, address: String, txid: [UInt8], index: Int, script: [UInt8], value: Int64, height: BlockHeight, networkType: NetworkType) throws -> Bool {
false
}
static func downloadedUtxoBalance(dbData: URL, address: String) throws -> WalletBalance {
static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) 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 {
static func createToAddress(dbData: URL, account: Int32, extsk: String, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 {
-1
}
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
static func shieldFunds(dbCache: URL, dbData: URL, account: Int32, tsk: String, extsk: String, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 {
-1
}
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
static func deriveTransparentAddressFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? {
throw KeyDerivationErrors.unableToDerive
}
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int) throws -> String? {
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], account: Int, index: Int, networkType: NetworkType) throws -> String? {
throw KeyDerivationErrors.unableToDerive
}
static func deriveTransparentAddressFromSecretKey(_ tsk: String) throws -> String? {
static func deriveTransparentAddressFromSecretKey(_ tsk: String, networkType: NetworkType) throws -> String? {
throw KeyDerivationErrors.unableToDerive
}
static func derivedTransparentAddressFromPublicKey(_ pubkey: String) throws -> String {
static func derivedTransparentAddressFromPublicKey(_ pubkey: String, networkType: NetworkType) throws -> String {
throw KeyDerivationErrors.unableToDerive
}
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int) throws -> [UnifiedViewingKey] {
static func deriveUnifiedViewingKeyFromSeed(_ seed: [UInt8], numberOfAccounts: Int, networkType: NetworkType) throws -> [UnifiedViewingKey] {
throw KeyDerivationErrors.unableToDerive
}
static func isValidExtendedFullViewingKey(_ key: String) throws -> Bool {
static func isValidExtendedFullViewingKey(_ key: String, networkType: NetworkType) throws -> Bool {
false
}
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8]) throws -> String? {
static func deriveTransparentPrivateKeyFromSeed(seed: [UInt8], networkType: NetworkType) throws -> String? {
nil
}
static func initAccountsTable(dbData: URL, exfvks: [String]) throws -> Bool {
static func initAccountsTable(dbData: URL, exfvks: [String], networkType: NetworkType) throws -> Bool {
false
}
static func deriveTransparentAddressFromSeed(seed: [UInt8]) throws -> String? {
static func deriveTransparentAddressFromSeed(seed: [UInt8], networkType: NetworkType) throws -> String? {
nil
}
static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? {
static func deriveExtendedFullViewingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? {
nil
}
static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32) throws -> [String]? {
static func deriveExtendedSpendingKeys(seed: [UInt8], accounts: Int32, networkType: NetworkType) throws -> [String]? {
nil
}
static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32) throws -> String? {
static func deriveShieldedAddressFromSeed(seed: [UInt8], accountIndex: Int32, networkType: NetworkType) throws -> String? {
nil
}
static func deriveShieldedAddressFromViewingKey(_ extfvk: String) throws -> String? {
static func deriveShieldedAddressFromViewingKey(_ extfvk: String, networkType: NetworkType) throws -> String? {
nil
}
static func consensusBranchIdFor(height: Int32) throws -> Int32 {
static func consensusBranchIdFor(height: Int32, networkType: NetworkType) throws -> Int32 {
guard let c = consensusBranchID else {
return try rustBackend.consensusBranchIdFor(height: height)
return try rustBackend.consensusBranchIdFor(height: height, networkType: networkType)
}
return c
}
static var networkType = NetworkType.testnet
static var mockDataDb = false
static var mockAcounts = false
static var mockError: RustWeldingError?
@ -202,61 +206,61 @@ class MockRustBackend: ZcashRustBackendWelding {
mockLastError ?? rustBackend.getLastError()
}
static func isValidShieldedAddress(_ address: String) throws -> Bool {
static func isValidShieldedAddress(_ address: String, networkType: NetworkType) throws -> Bool {
true
}
static func isValidTransparentAddress(_ address: String) throws -> Bool {
static func isValidTransparentAddress(_ address: String, networkType: NetworkType) throws -> Bool {
true
}
static func initDataDb(dbData: URL) throws {
static func initDataDb(dbData: URL, networkType: NetworkType) throws {
if !mockDataDb {
try rustBackend.initDataDb(dbData: dbData)
try rustBackend.initDataDb(dbData: dbData, networkType: networkType)
}
}
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32) -> [String]? {
mockAccounts ?? rustBackend.initAccountsTable(dbData: dbData, seed: seed, accounts: accounts)
static func initAccountsTable(dbData: URL, seed: [UInt8], accounts: Int32, networkType: NetworkType) -> [String]? {
mockAccounts ?? rustBackend.initAccountsTable(dbData: dbData, seed: seed, accounts: accounts, networkType: networkType)
}
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String) throws {
static func initBlocksTable(dbData: URL, height: Int32, hash: String, time: UInt32, saplingTree: String, networkType: NetworkType) throws {
if !mockDataDb {
try rustBackend.initBlocksTable(dbData: dbData, height: height, hash: hash, time: time, saplingTree: saplingTree)
try rustBackend.initBlocksTable(dbData: dbData, height: height, hash: hash, time: time, saplingTree: saplingTree, networkType: networkType)
}
}
static func getAddress(dbData: URL, account: Int32) -> String? {
mockAddresses?[Int(account)] ?? rustBackend.getAddress(dbData: dbData, account: account)
static func getAddress(dbData: URL, account: Int32, networkType: NetworkType) -> String? {
mockAddresses?[Int(account)] ?? rustBackend.getAddress(dbData: dbData, account: account, networkType: networkType)
}
static func getBalance(dbData: URL, account: Int32) -> Int64 {
mockBalance ?? rustBackend.getBalance(dbData: dbData, account: account)
static func getBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 {
mockBalance ?? rustBackend.getBalance(dbData: dbData, account: account, networkType: networkType)
}
static func getVerifiedBalance(dbData: URL, account: Int32) -> Int64 {
mockVerifiedBalance ?? rustBackend.getVerifiedBalance(dbData: dbData, account: account)
static func getVerifiedBalance(dbData: URL, account: Int32, networkType: NetworkType) -> Int64 {
mockVerifiedBalance ?? rustBackend.getVerifiedBalance(dbData: dbData, account: account, networkType: networkType)
}
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
mockMemo ?? rustBackend.getReceivedMemoAsUTF8(dbData: dbData, idNote: idNote)
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? {
mockMemo ?? rustBackend.getReceivedMemoAsUTF8(dbData: dbData, idNote: idNote, networkType: networkType)
}
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64) -> String? {
mockSentMemo ?? getSentMemoAsUTF8(dbData: dbData, idNote: idNote)
static func getSentMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? {
mockSentMemo ?? getSentMemoAsUTF8(dbData: dbData, idNote: idNote, networkType: networkType)
}
static func validateCombinedChain(dbCache: URL, dbData: URL) -> Int32 {
static func validateCombinedChain(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32 {
if let rate = self.mockValidateCombinedChainSuccessRate {
if shouldSucceed(successRate: rate) {
return validationResult(dbCache: dbCache, dbData: dbData)
return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType)
} else {
return Int32(mockValidateCombinedChainFailureHeight)
}
} else if let attempts = self.mockValidateCombinedChainFailAfterAttempts {
self.mockValidateCombinedChainFailAfterAttempts = attempts - 1
if attempts > 0 {
return validationResult(dbCache: dbCache, dbData: dbData)
return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType)
} else {
if attempts == 0 {
@ -264,38 +268,38 @@ class MockRustBackend: ZcashRustBackendWelding {
} else if attempts < 0 && mockValidateCombinedChainKeepFailing {
return Int32(mockValidateCombinedChainFailureHeight)
} else {
return validationResult(dbCache: dbCache, dbData: dbData)
return validationResult(dbCache: dbCache, dbData: dbData, networkType: networkType)
}
}
}
return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData)
return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData, networkType: networkType)
}
private static func validationResult(dbCache: URL, dbData: URL) -> Int32{
private static func validationResult(dbCache: URL, dbData: URL, networkType: NetworkType) -> Int32{
if mockDataDb {
return -1
} else {
return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData)
return rustBackend.validateCombinedChain(dbCache: dbCache, dbData: dbData, networkType: networkType)
}
}
static func rewindToHeight(dbData: URL, height: Int32) -> Bool {
mockDataDb ? true : rustBackend.rewindToHeight(dbData: dbData, height: height)
static func rewindToHeight(dbData: URL, height: Int32, networkType: NetworkType) -> Bool {
mockDataDb ? true : rustBackend.rewindToHeight(dbData: dbData, height: height, networkType: networkType)
}
static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32) -> Bool {
static func scanBlocks(dbCache: URL, dbData: URL, limit: UInt32, networkType: NetworkType) -> Bool {
if let rate = mockScanblocksSuccessRate {
if shouldSucceed(successRate: rate) {
return mockDataDb ? true : rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData)
return mockDataDb ? true : rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData, networkType: networkType)
} else {
return false
}
}
return rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData)
return rustBackend.scanBlocks(dbCache: dbCache, dbData: dbData, networkType: Self.networkType)
}
static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String) -> Int64 {
static func createToAddress(dbData: URL, account: Int32, extsk: String, consensusBranchId: Int32, to: String, value: Int64, memo: String?, spendParamsPath: String, outputParamsPath: String, networkType: NetworkType) -> Int64 {
// mockCreateToAddress ?? rustBackend.createToAddress(dbData: dbData, account: account, extsk: extsk, consensusBranchId: consensusBranchId, to: to, value: value, memo: memo, spendParamsPath: spendParamsPath, outputParamsPath: outputParamsPath)
-1
}
@ -305,19 +309,19 @@ class MockRustBackend: ZcashRustBackendWelding {
return random <= successRate
}
static func deriveExtendedFullViewingKey(_ spendingKey: String) throws -> String? {
static func deriveExtendedFullViewingKey(_ spendingKey: String, networkType: NetworkType) throws -> String? {
nil
}
static func deriveExtendedFullViewingKeys(seed: String, accounts: Int32) throws -> [String]? {
static func deriveExtendedFullViewingKeys(seed: String, accounts: Int32, networkType: NetworkType) throws -> [String]? {
nil
}
static func deriveExtendedSpendingKeys(seed: String, accounts: Int32) throws -> [String]? {
static func deriveExtendedSpendingKeys(seed: String, accounts: Int32, networkType: NetworkType) throws -> [String]? {
nil
}
static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8]) -> Bool {
static func decryptAndStoreTransaction(dbData: URL, tx: [UInt8], networkType: NetworkType) -> Bool {
false
}

View File

@ -15,6 +15,14 @@ class LightWalletEndpointBuilder {
static var `default`: LightWalletEndpoint {
LightWalletEndpoint(address: Constants.address, port: 9067, secure: false)
}
static var publicTestnet: LightWalletEndpoint {
LightWalletEndpoint(address: "testnet.lightwalletd.com", port: 9067, secure: true)
}
static var eccTestnet: LightWalletEndpoint {
LightWalletEndpoint(address: "lightwalletd.testnet.electriccoin.co", port: 9067, secure: true)
}
}
class ChannelProvider {

View File

@ -1,3 +1,50 @@
# 0.12.0-alpha.11
* [Enhancement] Network Agnostic build
# 0.12.0-alpha.10
* Fix: UNIQUE Constraint bug when coming from background. fixed and logged warning to keep investigating
* [New] latestScannedHeight added to SDKSynchronizer
# 0.12.0-alpha.9
* CompactBlockProcessor states don't propagate correctly
# 0.12.0-alpha.8
* target height reporting enhancements
# 0.12.0-alpha.7
* improve status publishing for SDKSynchronizer
* [FIX] missingStartHeight error when scanning from sapling activation
# 0.12.0-alpha.6
* Make sapling parameters default url public
# 0.12.0-alpha.5
* add output files to build phase to avoid CI failures
* fix lint warnings
# 0.12.0-alpha.4
* Tests
* [Fix] Issue #289 main thread lock when validating the server
* [Fix] info single call times out all the time
* make sure operations cancel in a timely manner
* FigureNextBatchOperation.swift tests
* make range function static
# tag: 0.12.0-alpha.3
* getInfo service times out too soon
# 0.12.0-alpha.2
* FIX: processor stalls on reconnection
* Fix warnings
# 0.12.0-alpha.1
* Replace Status for SyncStatus
* fix tests
* Fix Demo App
* fetch operation does not cancel when the previous operations do
* Fix: operations start when they have been canceled already
* fix progress being > 1
* Synchronizing by phases, preview
* Add fetch UTXO operation to compact block processor
* CompactBlock batch download and stream download operation tests pass.
# 0.11.1
* [Enhancement] Rewind API has a `.quick` option
# 0.11.0

View File

@ -11,7 +11,7 @@ use zcash_client_backend::{
data_api::{
chain::{scan_cached_blocks, validate_chain},
error::Error,
wallet::{create_spend_to_address, decrypt_and_store_transaction, shield_funds, ANCHOR_OFFSET},
wallet::{create_spend_to_address, decrypt_and_store_transaction, shield_funds},
WalletRead,
},
encoding::{
@ -43,17 +43,13 @@ use zcash_client_sqlite::{
};
use zcash_primitives::{
block::BlockHash,
consensus::{BlockHeight, BranchId, Parameters},
consensus::{BlockHeight, BranchId, Network, Parameters},
memo::{Memo, MemoBytes},
transaction::{components::Amount, components::OutPoint, Transaction},
zip32::ExtendedFullViewingKey,
legacy::TransparentAddress,
};
#[cfg(feature = "mainnet")]
use zcash_primitives::consensus::{MainNetwork, MAIN_NETWORK};
#[cfg(not(feature = "mainnet"))]
use zcash_primitives::consensus::{TestNetwork, TEST_NETWORK};
use zcash_primitives::consensus::Network::{MainNetwork, TestNetwork};
use zcash_proofs::prover::LocalTxProver;
use std::convert::{TryFrom, TryInto};
@ -78,37 +74,21 @@ where
}
}
#[cfg(feature = "mainnet")]
pub const NETWORK: MainNetwork = MAIN_NETWORK;
#[cfg(not(feature = "mainnet"))]
pub const NETWORK: TestNetwork = TEST_NETWORK;
#[cfg(feature = "mainnet")]
fn wallet_db(
db_data: *const u8,
db_data_len: usize,
) -> Result<WalletDb<MainNetwork>, failure::Error> {
network: Network,
) -> Result<WalletDb<Network>, failure::Error> {
let db_data = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(db_data, db_data_len)
}));
WalletDb::for_path(db_data, NETWORK)
WalletDb::for_path(db_data, network)
.map_err(|e| format_err!("Error opening wallet database connection: {}", e))
}
#[cfg(not(feature = "mainnet"))]
fn wallet_db(
db_data: *const u8,
db_data_len: usize,
) -> Result<WalletDb<TestNetwork>, failure::Error> {
let db_data = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(db_data, db_data_len)
}));
WalletDb::for_path(db_data, NETWORK)
.map_err(|e| format_err!("Error opening wallet database connection: {}", e))
}
fn block_db(cache_db: *const u8, cache_db_len: usize) -> Result<BlockDb, failure::Error> {
fn block_db(cache_db: *const u8,
cache_db_len: usize) -> Result<BlockDb, failure::Error> {
let cache_db = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(cache_db, cache_db_len)
}));
@ -136,13 +116,18 @@ pub extern "C" fn zcashlc_clear_last_error() {
/// Sets up the internal structure of the data database.
#[no_mangle]
pub extern "C" fn zcashlc_init_data_database(db_data: *const u8, db_data_len: usize) -> i32 {
pub extern "C" fn zcashlc_init_data_database(
db_data: *const u8,
db_data_len: usize,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let db_data = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(db_data, db_data_len)
}));
WalletDb::for_path(db_data, NETWORK)
WalletDb::for_path(db_data, network)
.map(|db| init_wallet_db(&db))
.map(|_| 1)
.map_err(|e| format_err!("Error while initializing data DB: {}", e))
@ -164,9 +149,11 @@ pub extern "C" fn zcashlc_init_accounts_table(
seed_len: usize,
accounts: i32,
capacity_ret: *mut usize,
network_id: u32,
) -> *mut *mut c_char {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let seed = unsafe { slice::from_raw_parts(seed, seed_len) };
let accounts = if accounts >= 0 {
accounts as u32
@ -175,13 +162,13 @@ pub extern "C" fn zcashlc_init_accounts_table(
};
let extsks: Vec<_> = (0..accounts)
.map(|account| spending_key(&seed, NETWORK.coin_type(), AccountId(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();
let tsk = derive_secret_key_from_seed(&network, &seed, AccountId(account), 0).unwrap();
derive_transparent_address_from_secret_key(&tsk)
}).collect();
@ -192,7 +179,7 @@ pub extern "C" fn zcashlc_init_accounts_table(
.iter()
.map(|extsk| {
let encoded = encode_extended_spending_key(
NETWORK.hrp_sapling_extended_spending_key(),
network.hrp_sapling_extended_spending_key(),
extsk,
);
CString::new(encoded).unwrap().into_raw()
@ -216,9 +203,11 @@ pub extern "C" fn zcashlc_init_accounts_table_with_keys(
db_data: *const u8,
db_data_len: usize,
uvks: *mut FFIUVKBoxedSlice,
network_id: u32,
) -> bool {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let s: Box<FFIUVKBoxedSlice> = unsafe { Box::from_raw(uvks) };
@ -230,7 +219,7 @@ pub extern "C" fn zcashlc_init_accounts_table_with_keys(
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(),
network.hrp_sapling_extended_full_viewing_key(),
&vkstr,
)
.unwrap()
@ -263,8 +252,10 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys(
seed_len: usize,
accounts: i32,
capacity_ret: *mut usize,
network_id: u32,
) -> *mut *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let seed = slice::from_raw_parts(seed, seed_len);
let accounts = if accounts > 0 {
accounts as u32
@ -273,7 +264,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys(
};
let extsks: Vec<_> = (0..accounts)
.map(|account| spending_key(&seed, NETWORK.coin_type(), AccountId(account)))
.map(|account| spending_key(&seed, network.coin_type(), AccountId(account)))
.collect();
// Return the ExtendedSpendingKeys for the created accounts.
@ -281,7 +272,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_spending_keys(
.iter()
.map(|extsk| {
let encoded = encode_extended_spending_key(
NETWORK.hrp_sapling_extended_spending_key(),
network.hrp_sapling_extended_spending_key(),
extsk,
);
CString::new(encoded).unwrap().into_raw()
@ -311,10 +302,11 @@ pub struct FFIUVKBoxedSlice {
fn unified_viewing_key_new(
extfvk: &ExtendedFullViewingKey,
extpub: &PublicKey) -> FFIUnifiedViewingKey {
extpub: &PublicKey,
network: Network) -> FFIUnifiedViewingKey {
let encoded_extfvk = encode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
network.hrp_sapling_extended_full_viewing_key(),
extfvk,
);
let encoded_pubkey = hex::encode(&extpub.serialize());
@ -323,7 +315,6 @@ fn unified_viewing_key_new(
extfvk: CString::new(encoded_extfvk).unwrap().into_raw(),
extpub: CString::new(encoded_pubkey).unwrap().into_raw()
}
}
fn uvk_vec_to_ffi (v: Vec<FFIUnifiedViewingKey>)
@ -360,8 +351,10 @@ pub unsafe extern "C" fn zcashlc_derive_unified_viewing_keys_from_seed(
seed: *const u8,
seed_len: usize,
accounts: i32,
network_id: u32,
) -> *mut FFIUVKBoxedSlice {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let seed = slice::from_raw_parts(seed, seed_len);
let accounts = if accounts > 0 {
accounts as u32
@ -371,9 +364,9 @@ pub unsafe extern "C" fn zcashlc_derive_unified_viewing_keys_from_seed(
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)
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, network)
})
.collect();
Ok(uvk_vec_to_ffi(uvks))
@ -393,8 +386,10 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys(
seed_len: usize,
accounts: i32,
capacity_ret: *mut usize,
network_id: u32,
) -> *mut *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let seed = slice::from_raw_parts(seed, seed_len);
let accounts = if accounts > 0 {
accounts as u32
@ -404,7 +399,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(), AccountId(account)))
ExtendedFullViewingKey::from(&spending_key(&seed, network.coin_type(), AccountId(account)))
})
.collect();
@ -413,7 +408,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_keys(
.iter()
.map(|extsk| {
let encoded = encode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
network.hrp_sapling_extended_full_viewing_key(),
extsk,
);
CString::new(encoded).unwrap().into_raw()
@ -434,19 +429,21 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
seed: *const u8,
seed_len: usize,
account_index: i32,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let seed = slice::from_raw_parts(seed, seed_len);
let account_index = if account_index >= 0 {
account_index as u32
} else {
return Err(format_err!("accounts argument must be greater than zero"));
};
let address = spending_key(&seed, NETWORK.coin_type(), AccountId(account_index))
let address = spending_key(&seed, network.coin_type(), AccountId(account_index))
.default_address()
.unwrap()
.1;
let address_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &address);
let address_str = encode_payment_address(network.hrp_sapling_payment_address(), &address);
Ok(CString::new(address_str).unwrap().into_raw())
});
unwrap_exc_or_null(res)
@ -457,13 +454,15 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_seed(
#[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_public_key(
pubkey: *const c_char,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
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);
.encode(&network);
Ok(CString::new(taddr).unwrap().into_raw())
});
@ -475,11 +474,13 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_public_key(
#[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key(
extfvk: *const c_char,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let extfvk_string = CStr::from_ptr(extfvk).to_str()?;
let extfvk = match decode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
network.hrp_sapling_extended_full_viewing_key(),
&extfvk_string,
) {
Ok(Some(extfvk)) => extfvk,
@ -494,7 +495,7 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key(
}
};
let address = extfvk.default_address().unwrap().1;
let address_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &address);
let address_str = encode_payment_address(network.hrp_sapling_payment_address(), &address);
Ok(CString::new(address_str).unwrap().into_raw())
});
unwrap_exc_or_null(res)
@ -505,11 +506,13 @@ pub unsafe extern "C" fn zcashlc_derive_shielded_address_from_viewing_key(
#[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key(
extsk: *const c_char,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let extsk = CStr::from_ptr(extsk).to_str()?;
let extfvk = match decode_extended_spending_key(
NETWORK.hrp_sapling_extended_spending_key(),
network.hrp_sapling_extended_spending_key(),
&extsk,
) {
Ok(Some(extsk)) => ExtendedFullViewingKey::from(&extsk),
@ -525,7 +528,7 @@ pub unsafe extern "C" fn zcashlc_derive_extended_full_viewing_key(
};
let encoded = encode_extended_full_viewing_key(
NETWORK.hrp_sapling_extended_full_viewing_key(),
network.hrp_sapling_extended_full_viewing_key(),
&extfvk,
);
@ -546,9 +549,11 @@ pub extern "C" fn zcashlc_init_blocks_table(
hash_hex: *const c_char,
time: u32,
sapling_tree_hex: *const c_char,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len,network)?;
let hash = {
let mut hash = hex::decode(unsafe { CStr::from_ptr(hash_hex) }.to_str()?).unwrap();
hash.reverse();
@ -579,9 +584,11 @@ pub extern "C" fn zcashlc_get_address(
db_data: *const u8,
db_data_len: usize,
account: i32,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let account = if account >= 0 {
account as u32
} else {
@ -592,7 +599,7 @@ pub extern "C" fn zcashlc_get_address(
match (&db_data).get_address(account) {
Ok(Some(addr)) => {
let addr_str = encode_payment_address(NETWORK.hrp_sapling_payment_address(), &addr);
let addr_str = encode_payment_address(network.hrp_sapling_payment_address(), &addr);
let c_str_addr = CString::new(addr_str).unwrap();
Ok(c_str_addr.into_raw())
}
@ -610,16 +617,19 @@ pub extern "C" fn zcashlc_get_address(
/// Returns false in any other case
/// Errors when the provided address belongs to another network
#[no_mangle]
pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_char) -> bool {
pub unsafe extern "C" fn zcashlc_is_valid_shielded_address(address: *const c_char,
network_id: u32) -> bool {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let addr = CStr::from_ptr(address).to_str()?;
Ok(is_valid_shielded_address(&addr))
Ok(is_valid_shielded_address(&addr, &network))
});
unwrap_exc_or(res, false)
}
fn is_valid_shielded_address(address: &str) -> bool {
match RecipientAddress::decode(&NETWORK, &address) {
fn is_valid_shielded_address(address: &str,
network: &Network) -> bool {
match RecipientAddress::decode(network, &address) {
Some(addr) => match addr {
RecipientAddress::Shielded(_) => true,
RecipientAddress::Transparent(_) => false,
@ -631,20 +641,24 @@ fn is_valid_shielded_address(address: &str) -> bool {
/// Returns true when the address is valid and transparent.
/// Returns false in any other case
#[no_mangle]
pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_char) -> bool {
pub unsafe extern "C" fn zcashlc_is_valid_transparent_address(address: *const c_char,
network_id: u32) -> bool {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let addr = CStr::from_ptr(address).to_str()?;
Ok(is_valid_transparent_address(&addr))
Ok(is_valid_transparent_address(&addr, &network))
});
unwrap_exc_or(res, false)
}
/// returns whether the given viewing key is valid or not
#[no_mangle]
pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char) -> bool {
pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char,
network_id: u32) -> bool {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let vkstr = CStr::from_ptr(key).to_str()?;
match decode_extended_full_viewing_key(&NETWORK.hrp_sapling_extended_full_viewing_key(), &vkstr) {
match decode_extended_full_viewing_key(&network.hrp_sapling_extended_full_viewing_key(), &vkstr) {
Ok(s) => match s {
None => Ok(false),
_ => Ok(true),
@ -654,8 +668,10 @@ pub unsafe extern "C" fn zcashlc_is_valid_viewing_key(key: *const c_char) -> boo
});
unwrap_exc_or(res, false)
}
fn is_valid_transparent_address(address: &str) -> bool {
match RecipientAddress::decode(&NETWORK, &address) {
fn is_valid_transparent_address(address: &str,
network: &Network) -> bool {
match RecipientAddress::decode(network, &address) {
Some(addr) => match addr {
RecipientAddress::Shielded(_) => false,
RecipientAddress::Transparent(_) => true,
@ -666,9 +682,15 @@ fn is_valid_transparent_address(address: &str) -> bool {
/// Returns the balance for the account, including all unspent notes that we know about.
#[no_mangle]
pub extern "C" fn zcashlc_get_balance(db_data: *const u8, db_data_len: usize, account: i32) -> i64 {
pub extern "C" fn zcashlc_get_balance(
db_data: *const u8,
db_data_len: usize,
account: i32,
network_id: u32,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
if account >= 0 {
let (_, max_height) = (&db_data)
@ -698,9 +720,11 @@ pub extern "C" fn zcashlc_get_verified_balance(
db_data: *const u8,
db_data_len: usize,
account: i32,
network_id: u32,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
if account >= 0 {
(&db_data)
.get_target_and_anchor_heights()
@ -730,11 +754,13 @@ pub extern "C" fn zcashlc_get_verified_transparent_balance(
db_data: *const u8,
db_data_len: usize,
address: *const c_char,
network_id: u32,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let addr = unsafe { CStr::from_ptr(address).to_str()? };
let taddr = TransparentAddress::decode(&NETWORK, &addr).unwrap();
let taddr = TransparentAddress::decode(&network, &addr).unwrap();
let amount = (&db_data)
.get_target_and_anchor_heights()
.map_err(|e| format_err!("Error while fetching anchor height: {}", e))
@ -764,11 +790,13 @@ pub extern "C" fn zcashlc_get_total_transparent_balance(
db_data: *const u8,
db_data_len: usize,
address: *const c_char,
network_id: u32,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let addr = unsafe { CStr::from_ptr(address).to_str()? };
let taddr = TransparentAddress::decode(&NETWORK, &addr).unwrap();
let taddr = TransparentAddress::decode(&network, &addr).unwrap();
let amount = (&db_data)
.get_target_and_anchor_heights()
.map_err(|e| format_err!("Error while fetching anchor height: {}", e))
@ -803,9 +831,11 @@ pub extern "C" fn zcashlc_get_received_memo_as_utf8(
db_data: *const u8,
db_data_len: usize,
id_note: i64,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let memo = (&db_data).get_memo(NoteId::ReceivedNoteId(id_note))
.map_err(|e| format_err!("An error occurred retrieving the memo, {}", e))
@ -833,9 +863,11 @@ pub extern "C" fn zcashlc_get_sent_memo_as_utf8(
db_data: *const u8,
db_data_len: usize,
id_note: i64,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let memo = (&db_data).get_memo(NoteId::SentNoteId(id_note))
.map_err(|e| format_err!("An error occurred retrieving the memo, {}", e))
@ -874,16 +906,18 @@ pub extern "C" fn zcashlc_validate_combined_chain(
db_cache_len: usize,
db_data: *const u8,
db_data_len: usize,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let block_db = block_db(db_cache, db_cache_len)?;
let db_data = wallet_db(db_data, db_data_len)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let validate_from = (&db_data)
.get_max_height_hash()
.map_err(|e| format_err!("Error while validating chain: {}", e))?;
let val_res = validate_chain(&NETWORK, &block_db, validate_from);
let val_res = validate_chain(&network, &block_db, validate_from);
if let Err(e) = val_res {
match e {
@ -905,12 +939,14 @@ pub extern "C" fn zcashlc_get_nearest_rewind_height(
db_data: *const u8,
db_data_len: usize,
height: i32,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
if height < 100 {
Ok(height)
} else {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let height = BlockHeight::try_from(height)?;
match get_rewind_height(&db_data) {
Ok(Some(best_height)) => {
@ -937,9 +973,11 @@ pub extern "C" fn zcashlc_rewind_to_height(
db_data: *const u8,
db_data_len: usize,
height: i32,
network_id: u32,
) -> bool {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let height = BlockHeight::try_from(height)?;
rewind_to_height(&db_data, height)
@ -970,17 +1008,19 @@ pub extern "C" fn zcashlc_scan_blocks(
db_data: *const u8,
db_data_len: usize,
scan_limit: u32,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let block_db = block_db(db_cache, db_cache_len)?;
let db_read = wallet_db(db_data, db_data_len)?;
let db_read = wallet_db(db_data, db_data_len, network)?;
let mut db_data = db_read.get_update_ops()?;
let limit = if scan_limit <= 0 {
None
} else {
Some(scan_limit)
};
match scan_cached_blocks(&NETWORK, &block_db, &mut db_data, limit) {
match scan_cached_blocks(&network, &block_db, &mut db_data, limit) {
Ok(()) => Ok(1),
Err(e) => Err(format_err!("Error while scanning blocks: {}", e)),
}
@ -1000,9 +1040,11 @@ pub extern "C" fn zcashlc_put_utxo(
script_bytes_len: usize,
value: i64,
height: i32,
network_id: u32,
) -> bool {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let mut db_data = db_data.get_update_ops()?;
let addr = unsafe { CStr::from_ptr(address_str).to_str()? };
@ -1013,7 +1055,7 @@ pub extern "C" fn zcashlc_put_utxo(
let script_bytes = unsafe { slice::from_raw_parts(script_bytes, script_bytes_len) };
let script = script_bytes.to_vec();
let address = TransparentAddress::decode(&NETWORK, &addr).unwrap();
let address = TransparentAddress::decode(&network, &addr).unwrap();
let output = WalletTransparentOutput {
address: address,
@ -1036,12 +1078,14 @@ pub unsafe extern "C" fn zcashlc_clear_utxos(
db_data_len: usize,
taddress: *const c_char,
above_height: i32,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let mut db_data = db_data.get_update_ops()?;
let addr = CStr::from_ptr(taddress).to_str()?;
let taddress = TransparentAddress::decode(&NETWORK, &addr).unwrap();
let taddress = TransparentAddress::decode(&network, &addr).unwrap();
let height = BlockHeight::from(above_height as u32);
match delete_utxos_above(&mut db_data, &taddress, height) {
Ok(rows) => Ok(rows as i32),
@ -1057,14 +1101,16 @@ pub extern "C" fn zcashlc_decrypt_and_store_transaction(
db_data_len: usize,
tx: *const u8,
tx_len: usize,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let db_read = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_read = wallet_db(db_data, db_data_len, network)?;
let mut db_data = db_read.get_update_ops()?;
let tx_bytes = unsafe { slice::from_raw_parts(tx, tx_len) };
let tx = Transaction::read(&tx_bytes[..])?;
match decrypt_and_store_transaction(&NETWORK, &mut db_data, &tx) {
match decrypt_and_store_transaction(&network, &mut db_data, &tx) {
Ok(()) => Ok(1),
Err(e) => Err(format_err!("Error while decrypting transaction: {}", e)),
}
@ -1093,9 +1139,11 @@ pub extern "C" fn zcashlc_create_to_address(
spend_params_len: usize,
output_params: *const u8,
output_params_len: usize,
network_id: u32,
) -> i64 {
let res = catch_panic(|| {
let db_read = wallet_db(db_data, db_data_len)?;
let network = parse_network(network_id)?;
let db_read = wallet_db(db_data, db_data_len, network)?;
let mut db_data = db_read.get_update_ops()?;
let account = if account >= 0 {
account as u32
@ -1118,7 +1166,7 @@ pub extern "C" fn zcashlc_create_to_address(
}));
let extsk =
match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk)
match decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), &extsk)
{
Ok(Some(extsk)) => extsk,
Ok(None) => {
@ -1129,7 +1177,7 @@ pub extern "C" fn zcashlc_create_to_address(
}
};
let to = match RecipientAddress::decode(&NETWORK, &to) {
let to = match RecipientAddress::decode(&network, &to) {
Some(to) => to,
None => {
return Err(format_err!("PaymentAddress is for the wrong network"));
@ -1149,7 +1197,7 @@ pub extern "C" fn zcashlc_create_to_address(
create_spend_to_address(
&mut db_data,
&NETWORK,
&network,
prover,
AccountId(account),
&extsk,
@ -1164,9 +1212,13 @@ pub extern "C" fn zcashlc_create_to_address(
}
#[no_mangle]
pub extern "C" fn zcashlc_branch_id_for_height(height: i32) -> i32 {
pub extern "C" fn zcashlc_branch_id_for_height(
height: i32,
network_id: u32,
) -> i32 {
let res = catch_panic(|| {
let branch: BranchId = BranchId::for_height(&NETWORK, BlockHeight::from(height as u32));
let network = parse_network(network_id)?;
let branch: BranchId = BranchId::for_height(&network, BlockHeight::from(height as u32));
let branch_id: u32 = u32::from(branch);
Ok(branch_id as i32)
});
@ -1209,9 +1261,10 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed(
seed_len: usize,
account: i32,
index: i32,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let seed = slice::from_raw_parts(seed, seed_len);
let account = if account >= 0 {
account as u32
@ -1224,7 +1277,7 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_private_key_from_seed(
} else {
return Err(format_err!("index argument must be positive"));
};
let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index).unwrap();
let sk = derive_secret_key_from_seed(&network, &seed, AccountId(account), index).unwrap();
let sk_wif = Wif::from_secret_key(&sk, true);
Ok(CString::new(sk_wif.0.to_string()).unwrap().into_raw())
@ -1239,9 +1292,11 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
seed_len: usize,
account: i32,
index: i32,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let seed = slice::from_raw_parts(seed, seed_len);
let network = parse_network(network_id)?;
let account = if account >= 0 {
account as u32
} else {
@ -1253,9 +1308,9 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
} else {
return Err(format_err!("index argument must be positive"));
};
let sk = derive_secret_key_from_seed(&NETWORK, &seed, AccountId(account), index);
let sk = derive_secret_key_from_seed(&network, &seed, AccountId(account), index);
let taddr = derive_transparent_address_from_secret_key(&sk.unwrap())
.encode(&NETWORK);
.encode(&network);
Ok(CString::new(taddr).unwrap().into_raw())
});
@ -1266,9 +1321,10 @@ pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_seed(
#[no_mangle]
pub unsafe extern "C" fn zcashlc_derive_transparent_address_from_secret_key(
tsk: *const c_char,
network_id: u32,
) -> *mut c_char {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let tsk_wif = CStr::from_ptr(tsk).to_str()?;
let sk: SecretKey = (&Wif(tsk_wif.to_string())).try_into().expect("invalid private key WIF");
@ -1276,12 +1332,91 @@ 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)
.encode(&NETWORK);
.encode(&network);
Ok(CString::new(taddr).unwrap().into_raw())
});
unwrap_exc_or_null(res)
}
#[no_mangle]
pub extern "C" fn zcashlc_shield_funds(
db_data: *const u8,
db_data_len: usize,
account: i32,
tsk: *const c_char,
extsk: *const c_char,
memo: *const c_char,
spend_params: *const u8,
spend_params_len: usize,
output_params: *const u8,
output_params_len: usize,
network_id: u32,
) -> i64 {
let res = catch_panic(|| {
let network = parse_network(network_id)?;
let db_data = wallet_db(db_data, db_data_len, network)?;
let mut update_ops = (&db_data)
.get_update_ops()
.map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?;
let account = if account >= 0 {
account as u32
} else {
return Err(format_err!("account argument must be positive"));
};
let tsk_wif = unsafe { CStr::from_ptr(tsk) }.to_str()?;
let extsk = unsafe { CStr::from_ptr(extsk) }.to_str()?;
let memo = unsafe { CStr::from_ptr(memo) }.to_str()?;
let spend_params = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(spend_params, spend_params_len)
}));
let output_params = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(output_params, output_params_len)
}));
//grab secret private key for t-funds
let sk:SecretKey = (&Wif(tsk_wif.to_string())).try_into()?;
let extsk =
match decode_extended_spending_key(network.hrp_sapling_extended_spending_key(), &extsk)
{
Ok(Some(extsk)) => extsk,
Ok(None) => {
return Err(format_err!("ExtendedSpendingKey is for the wrong network"));
},
Err(e) => {
return Err(format_err!("Invalid ExtendedSpendingKey: {}", e));
},
};
let memo = Memo::from_str(&memo).map_err(|_| format_err!("Invalid memo"))?;
let memo_bytes = MemoBytes::from(memo);
// shield_funds(&db_cache, &db_data, account, &tsk, &extsk, &memo, &spend_params, &output_params)
shield_funds(&mut update_ops,
&network,
LocalTxProver::new(spend_params, output_params),
AccountId(account),
&sk,
&extsk,
&memo_bytes,
0) // fix off-by-one error. 10 confs already added in this function
.map_err(|e| format_err!("Error while shielding transaction: {}", e))
});
unwrap_exc_or(res, -1)
}
//
// Utility functions
//
fn parse_network(value: u32) -> Result<Network, failure::Error> {
match value {
0 => Ok(TestNetwork),
1 => Ok(MainNetwork),
_ => Err(format_err!("Invalid network type: {}. Expected either 0 or 1 for Testnet or Mainnet, respectively.", value))
}
}
//
// Helper code from: https://github.com/adityapk00/zecwallet-light-cli/blob/master/lib/src/lightwallet.rs
//
@ -1310,70 +1445,4 @@ pub fn double_sha256(payload: &[u8]) -> Vec<u8> {
let h1 = Sha256::digest(&payload);
let h2 = Sha256::digest(&h1);
h2.to_vec()
}
#[no_mangle]
pub extern "C" fn zcashlc_shield_funds(
db_data: *const u8,
db_data_len: usize,
account: i32,
tsk: *const c_char,
extsk: *const c_char,
memo: *const c_char,
spend_params: *const u8,
spend_params_len: usize,
output_params: *const u8,
output_params_len: usize,
) -> i64 {
let res = catch_panic(|| {
let db_data = wallet_db(db_data, db_data_len)?;
let mut update_ops = (&db_data)
.get_update_ops()
.map_err(|e| format_err!("Could not obtain a writable database connection: {}", e))?;
let account = if account >= 0 {
account as u32
} else {
return Err(format_err!("account argument must be positive"));
};
let tsk_wif = unsafe { CStr::from_ptr(tsk) }.to_str()?;
let extsk = unsafe { CStr::from_ptr(extsk) }.to_str()?;
let memo = unsafe { CStr::from_ptr(memo) }.to_str()?;
let spend_params = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(spend_params, spend_params_len)
}));
let output_params = Path::new(OsStr::from_bytes(unsafe {
slice::from_raw_parts(output_params, output_params_len)
}));
//grab secret private key for t-funds
let sk:SecretKey = (&Wif(tsk_wif.to_string())).try_into()?;
let extsk =
match decode_extended_spending_key(NETWORK.hrp_sapling_extended_spending_key(), &extsk)
{
Ok(Some(extsk)) => extsk,
Ok(None) => {
return Err(format_err!("ExtendedSpendingKey is for the wrong network"));
},
Err(e) => {
return Err(format_err!("Invalid ExtendedSpendingKey: {}", e));
},
};
let memo = Memo::from_str(&memo).map_err(|_| format_err!("Invalid memo"))?;
let memo_bytes = MemoBytes::from(memo);
// shield_funds(&db_cache, &db_data, account, &tsk, &extsk, &memo, &spend_params, &output_params)
shield_funds(&mut update_ops,
&NETWORK,
LocalTxProver::new(spend_params, output_params),
AccountId(account),
&sk,
&extsk,
&memo_bytes,
ANCHOR_OFFSET)
.map_err(|e| format_err!("Error while shielding transaction: {}", e))
});
unwrap_exc_or(res, -1)
}
}