From 45b0f7523b9bdc73cbfe44a53bd260f154d3f653 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Fri, 30 Oct 2020 20:45:54 -0300 Subject: [PATCH 1/6] WIP - testSpendPriorFundsAfterActivation --- .../NetworkUpgradeTests.swift | 145 ++++++++++++++++++ .../utils/FakeChainBuilder.swift | 4 + 2 files changed, 149 insertions(+) create mode 100644 ZcashLightClientKitTests/NetworkUpgradeTests.swift diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift new file mode 100644 index 00000000..e3184741 --- /dev/null +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -0,0 +1,145 @@ +// +// NetworkUpgradeTests.swift +// ZcashLightClientKit-Unit-Tests +// +// Created by Francisco Gindre on 10/30/20. +// + +import XCTest +@testable import ZcashLightClientKit +class NetworkUpgradeTests: XCTestCase { + + let activationHeight: BlockHeight = 1_046_400 + 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! + + override func setUpWithError() throws { + + coordinator = try TestCoordinator( + seed: seedPhrase, + walletBirthday: birthday, + channelProvider: ChannelProvider() + ) + try coordinator.reset(saplingActivation: 663150) + } + + override func tearDownWithError() throws { + NotificationCenter.default.removeObserver(self) + try coordinator.stop() + try? FileManager.default.removeItem(at: coordinator.databases.cacheDB) + try? FileManager.default.removeItem(at: coordinator.databases.dataDB) + try? FileManager.default.removeItem(at: coordinator.databases.pendingDB) + } + + + /** + Given that a wallet had funds prior to activation it can spend them after activation + */ + func testSpendPriorFundsAfterActivation() throws { + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + + let firstSyncExpectation = XCTestExpectation(description: "first sync") + + try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.EXPIRY_OFFSET) + sleep(3) + + try coordinator.sync(completion: { (synchronizer) in + + firstSyncExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [firstSyncExpectation], timeout: 10) + let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() + XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) + + + try coordinator.applyStaged(blockheight: activationHeight + 1) + sleep(2) + + + let sendExpectation = XCTestExpectation(description: "send expectation") + var p: PendingTransactionEntity? = nil + let spendAmount: Int64 = 10000 + /* + send transaction to recipient address + */ + coordinator.synchronizer.sendToAddress(spendingKey: self.coordinator.spendingKeys!.first!, zatoshi: spendAmount, toAddress: self.testRecipientAddress, memo: "this is a test", from: 0, resultBlock: { (result) in + switch result { + case .failure(let e): + self.handleError(e) + case .success(let pendingTx): + p = pendingTx + } + sendExpectation.fulfill() + }) + + wait(for: [sendExpectation], timeout: 11) + + guard let _ = p else { + XCTFail("no pending transaction after sending") + try coordinator.stop() + return + } + + try coordinator.applyStaged(blockheight: activationHeight + 1 + 10) + + let afterSendExpectation = XCTestExpectation(description: "aftersend") + + try coordinator.sync(completion: { (synchronizer) in + + afterSendExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [afterSendExpectation], timeout: 10) + + XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), verifiedBalance - Int64(ZcashSDK.MINERS_FEE_ZATOSHI) - spendAmount) + + } + + /** + Given that a wallet receives funds after activation it can spend them when confirmed + */ + func testSpendPostActivationFundsAfterConfirmation() throws { + XCTFail() + } + /** + Given that a wallet sends funds some between (activation - expiry_height) and activation, those funds are shown as sent if mined. + + */ + func testSpendMinedSpendThatExpiresOnActivation() throws { + XCTFail() + } + + /** + Given that a wallet sends funds some between (activation - expiry_height) and activation, those funds are available if expired after expiration height. + */ + + func testExpiredSpendAfterActivation() throws { + XCTFail() + } + + /** + Given that a wallet has notes both received prior and after activation these can be combined to supply a larger amount spend. + */ + func testCombinePreActivationNotesAndPostActivationNotesOnSpend() throws { + XCTFail() + } + + + func handleError(_ error: Error?) { + _ = try? coordinator.stop() + guard let testError = error else { + XCTFail("failed with nil error") + return + } + XCTFail("Failed with error: \(testError)") + } +} diff --git a/ZcashLightClientKitTests/utils/FakeChainBuilder.swift b/ZcashLightClientKitTests/utils/FakeChainBuilder.swift index 02079652..c2d96f91 100644 --- a/ZcashLightClientKitTests/utils/FakeChainBuilder.swift +++ b/ZcashLightClientKitTests/utils/FakeChainBuilder.swift @@ -42,6 +42,10 @@ class FakeChainBuilder { } + static func buildChain(darksideWallet: DarksideWalletService, networkActivationHeight: BlockHeight, length: Int) throws { + + } + static func buildTxUrl(for id: String) -> String { "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/transactions/recv/\(id).txt" } From 4d77455033bc28d12c8d53c7915973f9056502ff Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 2 Nov 2020 11:04:30 -0300 Subject: [PATCH 2/6] WIP - testSpendPostActivationFundsAfterConfirmation --- .../NetworkUpgradeTests.swift | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index e3184741..2cf045ee 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -108,7 +108,65 @@ class NetworkUpgradeTests: XCTestCase { Given that a wallet receives funds after activation it can spend them when confirmed */ func testSpendPostActivationFundsAfterConfirmation() throws { - XCTFail() + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + + let firstSyncExpectation = XCTestExpectation(description: "first sync") + + try coordinator.applyStaged(blockheight: activationHeight + 10) + sleep(3) + + try coordinator.sync(completion: { (synchronizer) in + + firstSyncExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [firstSyncExpectation], timeout: 10) + guard try coordinator.synchronizer.allReceivedTransactions().filter({$0.minedHeight > activationHeight}).count > 0 else { + XCTFail("this test requires funds received after activation height") + return + } + + try coordinator.applyStaged(blockheight: activationHeight + 20) + sleep(2) + + + let sendExpectation = XCTestExpectation(description: "send expectation") + var p: PendingTransactionEntity? = nil + let spendAmount: Int64 = 10000 + /* + send transaction to recipient address + */ + coordinator.synchronizer.sendToAddress(spendingKey: self.coordinator.spendingKeys!.first!, zatoshi: spendAmount, toAddress: self.testRecipientAddress, memo: "this is a test", from: 0, resultBlock: { (result) in + switch result { + case .failure(let e): + self.handleError(e) + case .success(let pendingTx): + p = pendingTx + } + sendExpectation.fulfill() + }) + + wait(for: [sendExpectation], timeout: 11) + + guard let _ = p else { + XCTFail("no pending transaction after sending") + try coordinator.stop() + return + } + + try coordinator.applyStaged(blockheight: activationHeight + 1 + 10) + + let afterSendExpectation = XCTestExpectation(description: "aftersend") + + try coordinator.sync(completion: { (synchronizer) in + + afterSendExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [afterSendExpectation], timeout: 10) + } /** Given that a wallet sends funds some between (activation - expiry_height) and activation, those funds are shown as sent if mined. From 71940c8d405819d2c5dae2c963e9d3f223a0d96b Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 2 Nov 2020 11:53:49 -0300 Subject: [PATCH 3/6] WIP - testSpendMinedSpendThatExpiresOnActivation --- .../NetworkUpgradeTests.swift | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index 2cf045ee..77ec75fa 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -173,7 +173,87 @@ class NetworkUpgradeTests: XCTestCase { */ func testSpendMinedSpendThatExpiresOnActivation() throws { - XCTFail() + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + + let firstSyncExpectation = XCTestExpectation(description: "first sync") + + try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.EXPIRY_OFFSET) + sleep(3) + + try coordinator.sync(completion: { (synchronizer) in + + firstSyncExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [firstSyncExpectation], timeout: 10) + let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() + XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) + + + + let sendExpectation = XCTestExpectation(description: "send expectation") + var p: PendingTransactionEntity? = nil + let spendAmount: Int64 = 10000 + /* + send transaction to recipient address + */ + coordinator.synchronizer.sendToAddress(spendingKey: self.coordinator.spendingKeys!.first!, zatoshi: spendAmount, toAddress: self.testRecipientAddress, memo: "this is a test", from: 0, resultBlock: { (result) in + switch result { + case .failure(let e): + self.handleError(e) + case .success(let pendingTx): + p = pendingTx + } + sendExpectation.fulfill() + }) + + wait(for: [sendExpectation], timeout: 11) + + guard let pendingTx = p else { + XCTFail("no pending transaction after sending") + try coordinator.stop() + return + } + + /* + getIncomingTransaction + */ + guard let incomingTx = try coordinator.getIncomingTransactions()?.first else { + XCTFail("no incoming transaction") + try coordinator.stop() + return + } + + let sentTxHeight: BlockHeight = activationHeight - 5 + + + /* + stage transaction at sentTxHeight + */ + + + try coordinator.stageTransaction(incomingTx, at: sentTxHeight) + + try coordinator.applyStaged(blockheight: activationHeight + 5) + sleep(2) + + let afterSendExpectation = XCTestExpectation(description: "aftersend") + + try coordinator.sync(completion: { (synchronizer) in + + afterSendExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [afterSendExpectation], timeout: 10) + + guard let confirmedTx = try coordinator.synchronizer.allConfirmedTransactions(from: nil, limit: Int.max)?.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId }) else { + XCTFail("the sent transaction is not listed as a confirmed transaction") + return + } + + XCTAssertEqual(confirmedTx.minedHeight, sentTxHeight) } /** From 29db874bec0c4d53b4f76db1107e3434a25efde8 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 2 Nov 2020 11:58:45 -0300 Subject: [PATCH 4/6] WIP - testExpiredSpendAfterActivation --- .../NetworkUpgradeTests.swift | 81 ++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index 77ec75fa..cd6915e1 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -257,11 +257,88 @@ class NetworkUpgradeTests: XCTestCase { } /** - Given that a wallet sends funds some between (activation - expiry_height) and activation, those funds are available if expired after expiration height. + Given that a wallet sends funds somewhere between (activation - expiry_height) and activation, those funds are available if expired after expiration height. */ func testExpiredSpendAfterActivation() throws { - XCTFail() + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + + let firstSyncExpectation = XCTestExpectation(description: "first sync") + let offset = 5 + try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.EXPIRY_OFFSET) + sleep(3) + + let verifiedBalancePreActivation = coordinator.synchronizer.initializer.getVerifiedBalance() + + try coordinator.sync(completion: { (synchronizer) in + + firstSyncExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [firstSyncExpectation], timeout: 10) + let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() + XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) + + + + let sendExpectation = XCTestExpectation(description: "send expectation") + var p: PendingTransactionEntity? = nil + let spendAmount: Int64 = 10000 + /* + send transaction to recipient address + */ + coordinator.synchronizer.sendToAddress(spendingKey: self.coordinator.spendingKeys!.first!, zatoshi: spendAmount, toAddress: self.testRecipientAddress, memo: "this is a test", from: 0, resultBlock: { (result) in + switch result { + case .failure(let e): + self.handleError(e) + case .success(let pendingTx): + p = pendingTx + } + sendExpectation.fulfill() + }) + + wait(for: [sendExpectation], timeout: 11) + + guard let pendingTx = p else { + XCTFail("no pending transaction after sending") + try coordinator.stop() + return + } + + /* + getIncomingTransaction + */ + guard let _ = try coordinator.getIncomingTransactions()?.first else { + XCTFail("no incoming transaction") + try coordinator.stop() + return + } + + /* + don't stage transaction + */ + + + try coordinator.applyStaged(blockheight: activationHeight + offset) + sleep(2) + + let afterSendExpectation = XCTestExpectation(description: "aftersend") + + try coordinator.sync(completion: { (synchronizer) in + + afterSendExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [afterSendExpectation], timeout: 10) + + guard try coordinator.synchronizer.allConfirmedTransactions(from: nil, limit: Int.max)?.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId }) == nil else { + XCTFail("the sent transaction should not be not listed as a confirmed transaction") + return + } + + XCTAssertEqual(verifiedBalancePreActivation, coordinator.synchronizer.initializer.getVerifiedBalance()) } /** From 552c01195102b710476d908c9e3efedac8a7b505 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 2 Nov 2020 14:15:52 -0300 Subject: [PATCH 5/6] WIP - testCombinePreActivationNotesAndPostActivationNotesOnSpend --- .../NetworkUpgradeTests.swift | 60 ++++++++++++++++++- .../utils/FakeChainBuilder.swift | 4 ++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index cd6915e1..56ab83f3 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -345,10 +345,64 @@ class NetworkUpgradeTests: XCTestCase { Given that a wallet has notes both received prior and after activation these can be combined to supply a larger amount spend. */ func testCombinePreActivationNotesAndPostActivationNotesOnSpend() throws { - XCTFail() + try FakeChainBuilder.buildChainMixedFunds(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + + let firstSyncExpectation = XCTestExpectation(description: "first sync") + + try coordinator.applyStaged(blockheight: activationHeight + -1) + sleep(3) + + try coordinator.sync(completion: { (synchronizer) in + + firstSyncExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [firstSyncExpectation], timeout: 10) + + let preActivationBalance = coordinator.synchronizer.initializer.getVerifiedBalance() + + guard try coordinator.synchronizer.allReceivedTransactions().filter({$0.minedHeight > activationHeight}).count > 0 else { + XCTFail("this test requires funds received after activation height") + return + } + + try coordinator.applyStaged(blockheight: activationHeight + 20) + sleep(2) + + let postActivationBalance = coordinator.synchronizer.initializer.getVerifiedBalance() + + XCTAssertTrue(preActivationBalance > postActivationBalance, "This test requires that funds post activation are greater that pre activation") + let sendExpectation = XCTestExpectation(description: "send expectation") + var p: PendingTransactionEntity? = nil + + // spend all the funds + let spendAmount: Int64 = postActivationBalance - Int64(ZcashSDK.MINERS_FEE_ZATOSHI) + + /* + send transaction to recipient address + */ + coordinator.synchronizer.sendToAddress(spendingKey: self.coordinator.spendingKeys!.first!, zatoshi: spendAmount, toAddress: self.testRecipientAddress, memo: "this is a test", from: 0, resultBlock: { (result) in + switch result { + case .failure(let e): + self.handleError(e) + case .success(let pendingTx): + p = pendingTx + } + sendExpectation.fulfill() + }) + + wait(for: [sendExpectation], timeout: 11) + + guard let _ = p else { + XCTFail("no pending transaction after sending") + try coordinator.stop() + return + } + + XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 0) } - - + func handleError(_ error: Error?) { _ = try? coordinator.stop() guard let testError = error else { diff --git a/ZcashLightClientKitTests/utils/FakeChainBuilder.swift b/ZcashLightClientKitTests/utils/FakeChainBuilder.swift index c2d96f91..f84655a7 100644 --- a/ZcashLightClientKitTests/utils/FakeChainBuilder.swift +++ b/ZcashLightClientKitTests/utils/FakeChainBuilder.swift @@ -46,6 +46,10 @@ class FakeChainBuilder { } + static func buildChainMixedFunds(darksideWallet: DarksideWalletService, networkActivationHeight: BlockHeight, length: Int) throws { + + } + static func buildTxUrl(for id: String) -> String { "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/transactions/recv/\(id).txt" } From 1926ea68249e6ff9ea0b8748400443425a0dc622 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Thu, 5 Nov 2020 19:02:01 -0300 Subject: [PATCH 6/6] Canopy Tests Successfully pass --- .../DemoAppConfig.swift | 2 +- .../WalletBirthday+saplingtree.stencil | 40 ++++--- .../NetworkUpgradeTests.swift | 102 +++++++++++------- .../TestCoordinator.swift | 71 +++++++++--- .../utils/DarkSideWalletService.swift | 2 +- .../utils/FakeChainBuilder.swift | 32 +++++- 6 files changed, 179 insertions(+), 70 deletions(-) diff --git a/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift b/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift index 3281eae9..71323484 100644 --- a/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift +++ b/Example/ZcashLightClientSample/ZcashLightClientSample/DemoAppConfig.swift @@ -10,7 +10,7 @@ import Foundation import ZcashLightClientKit import MnemonicSwift struct DemoAppConfig { - static var host = ZcashSDK.isMainnet ? "localhost" : "localhost" + static var host = ZcashSDK.isMainnet ? "localhost" : "lightwalletd.testnet.electriccoin.co" static var port: Int = 9067 static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 663174 : 620_000 static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet diff --git a/ZcashLightClientKit/Stencil/WalletBirthday+saplingtree.stencil b/ZcashLightClientKit/Stencil/WalletBirthday+saplingtree.stencil index c2489775..0e9d2771 100644 --- a/ZcashLightClientKit/Stencil/WalletBirthday+saplingtree.stencil +++ b/ZcashLightClientKit/Stencil/WalletBirthday+saplingtree.stencil @@ -352,27 +352,41 @@ public extension WalletBirthday { time: 1585012771, tree: "01e3bd906376b563d184bfbf6616e220f895001b7ef9d26bf38c6cb5c71e57a42b001001d848adf8c38d113140bb30d306b0761da6987e25ffc0d82faa63c2764aab120301de3e6a35d09192cde3430860c70a534d7b63e95a726fab052de2a9befa3cc3320189b958fa030131bb83385a3e3a8b187a166dc1b3a02050f2d2fc20788536c30e0001cb8770ef198e7de60093a339afbc561c16c16749f9f96751c2fc58a22d0ff36f01f86ff70dd512f7075d02c5ee6e28a8824832d08025a4cfaf4c1854f1fba5da10019bcac1b44a27de2c4528fa6f4b3432913511b219cb3b29d137cac0236a3d244800000000016f6df9b95ef63866bdf0e8b4b97701cd09232ec3e4e240808c0546d01bc7bb0501e3ec5d790cc9acc2586fc6e9ce5aae5f5aba32d33e386165c248c4a03ec8ed670000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" ) - case 950000 ..< 1130000: + 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 ..< BlockHeight.max: - return WalletBirthday( - height: 1130000, - hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", - time: 1603070117, - tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) + return WalletBirthday( + height: 1130000, + hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", + time: 1603070117, + tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) default: - return WalletBirthday( - height: 1130000, - hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", - time: 1603070117, - tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" - ) + return WalletBirthday( + height: 1130000, + hash: "001f6563cf2863d36501dee00e41795f2fdb482970ea5f648791bbf7da4e6860", + time: 1603070117, + tree: "01b00c3e6d98e706fdb2d40f082096505aaa70fb87c067baf1a8a6d25cccff7258015a5334276509c93b855db0c2a1252e2ca725821c9274add1c2e92631bbbfa12b100151ba8342564941385670cd7346dc753bb5cc61164f000f65044cc09baa175917019ed834b8b9c8ca58969b3f239d74c2dd4a7d0a462afb1e856cf76209b866eb660135de9af32480f38eeca478a33a95f495abe7470e93d5aa4813fab7ea4fd12c4c0000017ce3fc7ebc2f8cfc2e1ee9f8e92b6e45065679ee3b48b5b2f0ce053305f5a95c011f1e8fe8f4a1cb5a700614218b8bebf2113c8a660abd255f67448b684b82d76e00000000016d559de7a1a382349cf97fe01a2fba41a49bb5e3b306d9ff8c2bcc301c731c00000001f08f39275112dd8905b854170b7f247cf2df18454d4fa94e6e4f9320cca05f24011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39" + ) } } } diff --git a/ZcashLightClientKitTests/NetworkUpgradeTests.swift b/ZcashLightClientKitTests/NetworkUpgradeTests.swift index 56ab83f3..00d982e5 100644 --- a/ZcashLightClientKitTests/NetworkUpgradeTests.swift +++ b/ZcashLightClientKitTests/NetworkUpgradeTests.swift @@ -9,24 +9,24 @@ import XCTest @testable import ZcashLightClientKit class NetworkUpgradeTests: XCTestCase { - let activationHeight: BlockHeight = 1_046_400 - 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 activationHeight: BlockHeight = 1028500 + var spendingKey = "secret-extended-key-test1qv2vf437qqqqpqpfc0arpv55ncq33p2p895hlcx0ra6d0g739v93luqdjpxun3kt050j9qnrqjyp8d7fdxgedfyxpjmuyha2ulxa6hmqvm2gnvuc3tvs3enpxwuz768qfkd286vr3jgyrgr5ddx2ukrdl95ak3tzqylzjeqw3pnmgtmwsvemrj3sk6vqgwxm9khlv46wccn33ayw52prr233ea069c9u8m3839dvw30sdf6k32xddhpte6p6qsuxval6usyh6lr55pgypkgtz" - let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a" //TODO: Parameterize this from environment + let testRecipientAddress = "ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc" //TODO: Parameterize this from environment let sendAmount: Int64 = 1000 - var birthday: BlockHeight = 663150 - let defaultLatestHeight: BlockHeight = 663175 + var birthday: BlockHeight = 1013250 + var coordinator: TestCoordinator! override func setUpWithError() throws { coordinator = try TestCoordinator( - seed: seedPhrase, + spendingKey: spendingKey, walletBirthday: birthday, channelProvider: ChannelProvider() ) - try coordinator.reset(saplingActivation: 663150) + try coordinator.reset(saplingActivation: birthday) } override func tearDownWithError() throws { @@ -42,12 +42,12 @@ class NetworkUpgradeTests: XCTestCase { Given that a wallet had funds prior to activation it can spend them after activation */ func testSpendPriorFundsAfterActivation() throws { - try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, birthday: birthday, networkActivationHeight: activationHeight, length: 15300) let firstSyncExpectation = XCTestExpectation(description: "first sync") - try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.EXPIRY_OFFSET) - sleep(3) + try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.DEFAULT_STALE_TOLERANCE) + sleep(5) try coordinator.sync(completion: { (synchronizer) in @@ -55,15 +55,16 @@ class NetworkUpgradeTests: XCTestCase { }, error: self.handleError) - wait(for: [firstSyncExpectation], timeout: 10) + wait(for: [firstSyncExpectation], timeout: 120) let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) - - + guard verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI else { + XCTFail("not enough balance to continue test") + return + } + try coordinator.applyStaged(blockheight: activationHeight + 1) sleep(2) - - + let sendExpectation = XCTestExpectation(description: "send expectation") var p: PendingTransactionEntity? = nil let spendAmount: Int64 = 10000 @@ -87,9 +88,24 @@ class NetworkUpgradeTests: XCTestCase { try coordinator.stop() return } + /* + getIncomingTransaction + */ + guard let incomingTx = try coordinator.getIncomingTransactions()?.first else { + XCTFail("no incoming transaction") + try coordinator.stop() + return + } - try coordinator.applyStaged(blockheight: activationHeight + 1 + 10) - + let sentTxHeight: BlockHeight = activationHeight + 2 + + /* + stage transaction at sentTxHeight + */ + + try coordinator.stageTransaction(incomingTx, at: sentTxHeight) + try coordinator.applyStaged(blockheight: activationHeight + 20) + sleep(1) let afterSendExpectation = XCTestExpectation(description: "aftersend") try coordinator.sync(completion: { (synchronizer) in @@ -100,7 +116,7 @@ class NetworkUpgradeTests: XCTestCase { wait(for: [afterSendExpectation], timeout: 10) - XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), verifiedBalance - Int64(ZcashSDK.MINERS_FEE_ZATOSHI) - spendAmount) + XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), verifiedBalance - spendAmount) } @@ -108,7 +124,7 @@ class NetworkUpgradeTests: XCTestCase { Given that a wallet receives funds after activation it can spend them when confirmed */ func testSpendPostActivationFundsAfterConfirmation() throws { - try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + try FakeChainBuilder.buildChainPostActivationFunds(darksideWallet: coordinator.service, birthday: birthday, networkActivationHeight: activationHeight, length: 15300) let firstSyncExpectation = XCTestExpectation(description: "first sync") @@ -121,7 +137,7 @@ class NetworkUpgradeTests: XCTestCase { }, error: self.handleError) - wait(for: [firstSyncExpectation], timeout: 10) + wait(for: [firstSyncExpectation], timeout: 120) guard try coordinator.synchronizer.allReceivedTransactions().filter({$0.minedHeight > activationHeight}).count > 0 else { XCTFail("this test requires funds received after activation height") return @@ -173,11 +189,11 @@ class NetworkUpgradeTests: XCTestCase { */ func testSpendMinedSpendThatExpiresOnActivation() throws { - try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, birthday: birthday, networkActivationHeight: activationHeight, length: 15300) let firstSyncExpectation = XCTestExpectation(description: "first sync") - try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.EXPIRY_OFFSET) + try coordinator.applyStaged(blockheight: activationHeight - 10) sleep(3) try coordinator.sync(completion: { (synchronizer) in @@ -186,7 +202,7 @@ class NetworkUpgradeTests: XCTestCase { }, error: self.handleError) - wait(for: [firstSyncExpectation], timeout: 10) + wait(for: [firstSyncExpectation], timeout: 120) let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) @@ -261,11 +277,11 @@ class NetworkUpgradeTests: XCTestCase { */ func testExpiredSpendAfterActivation() throws { - try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, birthday: birthday, networkActivationHeight: activationHeight, length: 15300) let firstSyncExpectation = XCTestExpectation(description: "first sync") let offset = 5 - try coordinator.applyStaged(blockheight: activationHeight - ZcashSDK.EXPIRY_OFFSET) + try coordinator.applyStaged(blockheight: activationHeight - 10) sleep(3) let verifiedBalancePreActivation = coordinator.synchronizer.initializer.getVerifiedBalance() @@ -276,11 +292,12 @@ class NetworkUpgradeTests: XCTestCase { }, error: self.handleError) - wait(for: [firstSyncExpectation], timeout: 10) + wait(for: [firstSyncExpectation], timeout: 120) let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance() - XCTAssertTrue(verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI) - - + guard verifiedBalance > ZcashSDK.MINERS_FEE_ZATOSHI else { + XCTFail("balance is not enough to continue with this test") + return + } let sendExpectation = XCTestExpectation(description: "send expectation") var p: PendingTransactionEntity? = nil @@ -345,11 +362,11 @@ class NetworkUpgradeTests: XCTestCase { Given that a wallet has notes both received prior and after activation these can be combined to supply a larger amount spend. */ func testCombinePreActivationNotesAndPostActivationNotesOnSpend() throws { - try FakeChainBuilder.buildChainMixedFunds(darksideWallet: coordinator.service, networkActivationHeight: activationHeight, length: 100) + try FakeChainBuilder.buildChainMixedFunds(darksideWallet: coordinator.service, birthday: birthday, networkActivationHeight: activationHeight, length: 15300) let firstSyncExpectation = XCTestExpectation(description: "first sync") - try coordinator.applyStaged(blockheight: activationHeight + -1) + try coordinator.applyStaged(blockheight: activationHeight - 1) sleep(3) try coordinator.sync(completion: { (synchronizer) in @@ -358,21 +375,28 @@ class NetworkUpgradeTests: XCTestCase { }, error: self.handleError) - wait(for: [firstSyncExpectation], timeout: 10) + wait(for: [firstSyncExpectation], timeout: 120) let preActivationBalance = coordinator.synchronizer.initializer.getVerifiedBalance() + try coordinator.applyStaged(blockheight: activationHeight + 30) + sleep(2) + + let secondSyncExpectation = XCTestExpectation(description: "second sync") + try coordinator.sync(completion: { (synchronizer) in + + secondSyncExpectation.fulfill() + + }, error: self.handleError) + + wait(for: [secondSyncExpectation], timeout: 10) guard try coordinator.synchronizer.allReceivedTransactions().filter({$0.minedHeight > activationHeight}).count > 0 else { XCTFail("this test requires funds received after activation height") return } - - try coordinator.applyStaged(blockheight: activationHeight + 20) - sleep(2) - let postActivationBalance = coordinator.synchronizer.initializer.getVerifiedBalance() - XCTAssertTrue(preActivationBalance > postActivationBalance, "This test requires that funds post activation are greater that pre activation") + XCTAssertTrue(preActivationBalance < postActivationBalance, "This test requires that funds post activation are greater that pre activation") let sendExpectation = XCTestExpectation(description: "send expectation") var p: PendingTransactionEntity? = nil @@ -392,7 +416,7 @@ class NetworkUpgradeTests: XCTestCase { sendExpectation.fulfill() }) - wait(for: [sendExpectation], timeout: 11) + wait(for: [sendExpectation], timeout: 15) guard let _ = p else { XCTFail("no pending transaction after sending") diff --git a/ZcashLightClientKitTests/TestCoordinator.swift b/ZcashLightClientKitTests/TestCoordinator.swift index c647f14e..3d59b287 100644 --- a/ZcashLightClientKitTests/TestCoordinator.swift +++ b/ZcashLightClientKitTests/TestCoordinator.swift @@ -20,6 +20,7 @@ class TestCoordinator { case notDarksideWallet case notificationFromUnknownSynchronizer case notMockLightWalletService + case builderError } enum SyncThreshold { @@ -35,7 +36,7 @@ class TestCoordinator { var completionHandler: ((SDKSynchronizer) -> Void)? var errorHandler: ((Error?) -> Void)? - var seed: String + var spendingKey: String var birthday: BlockHeight var channelProvider: ChannelProvider var synchronizer: SDKSynchronizer @@ -43,10 +44,20 @@ class TestCoordinator { var spendingKeys: [String]? var databases: TemporaryTestDatabases - init(seed: String, + convenience init(seed: String, walletBirthday: BlockHeight, channelProvider: ChannelProvider) throws { - self.seed = seed + guard let spendingKey = try DerivationTool.default.deriveSpendingKeys(seed: TestSeed().seed(),// todo: fix this + numberOfAccounts: 1).first else { + throw CoordinatorError.builderError + } + try self.init(spendingKey: spendingKey, walletBirthday: walletBirthday, channelProvider: channelProvider) + } + + required init(spendingKey: String, + walletBirthday: BlockHeight, + channelProvider: ChannelProvider) throws { + self.spendingKey = spendingKey self.birthday = walletBirthday self.channelProvider = channelProvider self.databases = TemporaryDbBuilder.build() @@ -69,7 +80,7 @@ class TestCoordinator { downloader: downloader, spendParamsURL: try __spendParamsURL(), outputParamsURL: try __outputParamsURL(), - seedBytes: TestSeed().seed(), + spendingKey: spendingKey, walletBirthday: WalletBirthday.birthday(with: birthday), loggerProxy: SampleLogger(logLevel: .debug)) @@ -210,7 +221,41 @@ class TemporaryDbBuilder { } class TestSynchronizerBuilder { - + static func build( + rustBackend: ZcashRustBackendWelding.Type, + lowerBoundHeight: BlockHeight, + cacheDbURL: URL, + dataDbURL: URL, + pendingDbURL: URL, + endpoint: LightWalletEndpoint, + service: LightWalletService, + repository: TransactionRepository, + downloader: CompactBlockDownloader, + spendParamsURL: URL, + outputParamsURL: URL, + spendingKey: String, + walletBirthday: WalletBirthday, + loggerProxy: Logger? = nil + ) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) { + let initializer = Initializer( + rustBackend: rustBackend, + lowerBoundHeight: lowerBoundHeight, + cacheDbURL: cacheDbURL, + dataDbURL: dataDbURL, + pendingDbURL: pendingDbURL, + endpoint: endpoint, + service: service, + repository: repository, + downloader: downloader, + spendParamsURL: spendParamsURL, + outputParamsURL: outputParamsURL, + loggerProxy: loggerProxy + ) + try initializer.initialize(viewingKeys: [try DerivationTool().deriveViewingKey(spendingKey: spendingKey)], walletBirthday: walletBirthday.height) + + return ([spendingKey], try SDKSynchronizer(initializer: initializer) + ) + } static func build( rustBackend: ZcashRustBackendWelding.Type, lowerBoundHeight: BlockHeight, @@ -227,9 +272,10 @@ class TestSynchronizerBuilder { walletBirthday: WalletBirthday, loggerProxy: Logger? = nil ) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) { - - let initializer = Initializer( - rustBackend: rustBackend, + guard let spendingKey = try DerivationTool().deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1).first else { + throw TestCoordinator.CoordinatorError.builderError + } + return try build(rustBackend: rustBackend, lowerBoundHeight: lowerBoundHeight, cacheDbURL: cacheDbURL, dataDbURL: dataDbURL, @@ -240,12 +286,9 @@ class TestSynchronizerBuilder { downloader: downloader, spendParamsURL: spendParamsURL, outputParamsURL: outputParamsURL, - loggerProxy: loggerProxy - ) - try initializer.initialize(viewingKeys: try DerivationTool().deriveViewingKeys(seed: seedBytes, numberOfAccounts: 1), walletBirthday: walletBirthday.height) - let credentials = try DerivationTool().deriveSpendingKeys(seed: seedBytes, numberOfAccounts: 1) - return (credentials, try SDKSynchronizer(initializer: initializer) - ) + spendingKey: spendingKey, + walletBirthday: walletBirthday) + } } diff --git a/ZcashLightClientKitTests/utils/DarkSideWalletService.swift b/ZcashLightClientKitTests/utils/DarkSideWalletService.swift index c7747fc8..af2773af 100644 --- a/ZcashLightClientKitTests/utils/DarkSideWalletService.swift +++ b/ZcashLightClientKitTests/utils/DarkSideWalletService.swift @@ -118,7 +118,7 @@ class DarksideWalletService: LightWalletService { } } - func reset(saplingActivation: BlockHeight) throws { + func reset(saplingActivation: BlockHeight, branchID: String = "d3adb33f", chainName: String = "test") throws { var metaState = DarksideMetaState() metaState.saplingActivation = Int32(saplingActivation) metaState.branchID = "d3adb33f" diff --git a/ZcashLightClientKitTests/utils/FakeChainBuilder.swift b/ZcashLightClientKitTests/utils/FakeChainBuilder.swift index f84655a7..1035eca3 100644 --- a/ZcashLightClientKitTests/utils/FakeChainBuilder.swift +++ b/ZcashLightClientKitTests/utils/FakeChainBuilder.swift @@ -14,6 +14,14 @@ enum FakeChainBuilderError: Error { class FakeChainBuilder { static let someOtherTxUrl = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/transactions/t-shielded-spend.txt" static let txMainnetBlockUrl = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/663150.txt" + + static let testnetCanopyUpdateUrl = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/1028400-1028600.txt" + + static let testnetCanopyStartBlock = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/1013250.txt" + static let testnetPreCanopyTx = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/pre-activation-txs/61088726aaa7c25b0568dd7bf19955f4a57f7173034e720c924107ff05cd3649.txt" + + static let testnetPostCanopyTx = "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/testnet-canopy/post-activation-txs/ecaa6c03709d70aa25446a81690b18ddb11daac96a03fe4b5cfd0d89a49fb963.txt" + static func buildChain(darksideWallet: DarksideWalletService) throws { try darksideWallet.reset(saplingActivation: 663150) try darksideWallet.useDataset(from: txMainnetBlockUrl) @@ -42,11 +50,31 @@ class FakeChainBuilder { } - static func buildChain(darksideWallet: DarksideWalletService, networkActivationHeight: BlockHeight, length: Int) throws { + static func buildChain(darksideWallet: DarksideWalletService, birthday: BlockHeight, networkActivationHeight: BlockHeight, length: Int) throws { + + try darksideWallet.reset(saplingActivation: birthday, branchID: "e9ff75a6" , chainName: "testnet") + + try darksideWallet.useDataset(testnetCanopyStartBlock) + try darksideWallet.stageBlocksCreate(from: birthday + 1, count: length) + try darksideWallet.stageTransaction(from: testnetPreCanopyTx, at: networkActivationHeight - ZcashSDK.EXPIRY_OFFSET) + } - static func buildChainMixedFunds(darksideWallet: DarksideWalletService, networkActivationHeight: BlockHeight, length: Int) throws { + static func buildChainPostActivationFunds(darksideWallet: DarksideWalletService, birthday: BlockHeight, networkActivationHeight: BlockHeight, length: Int) throws { + + try darksideWallet.reset(saplingActivation: birthday, branchID: "e9ff75a6" , chainName: "testnet") + + try darksideWallet.useDataset(testnetCanopyStartBlock) + try darksideWallet.stageBlocksCreate(from: birthday + 1, count: length) + try darksideWallet.stageTransaction(from: testnetPostCanopyTx, at: networkActivationHeight + 1) + + } + + static func buildChainMixedFunds(darksideWallet: DarksideWalletService, birthday: BlockHeight, networkActivationHeight: BlockHeight, length: Int) throws { + try buildChain(darksideWallet: darksideWallet, birthday: birthday, networkActivationHeight: networkActivationHeight, length: length) + + try darksideWallet.stageTransaction(from: testnetPostCanopyTx, at: networkActivationHeight + ZcashSDK.EXPIRY_OFFSET) }