ZcashLightClientKit/Tests/DarksideTests/AdvancedReOrgTests.swift

1343 lines
47 KiB
Swift
Raw Normal View History

//
// AdvancedReOrgTests.swift
// ZcashLightClientKit-Unit-Tests
//
// Created by Francisco Gindre on 5/14/20.
//
import Combine
import XCTest
2022-02-28 09:03:20 -08:00
@testable import TestUtils
@testable import ZcashLightClientKit
2021-09-23 06:26:41 -07:00
class AdvancedReOrgTests: XCTestCase {
let sendAmount = Zatoshi(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
2021-09-23 06:26:41 -07:00
var reorgExpectation = XCTestExpectation(description: "reorg")
2021-05-18 14:22:29 -07:00
let branchID = "2bb40e60"
let chainName = "main"
2021-07-28 09:59:10 -07:00
let network = DarksideWalletDNetwork()
var cancellables: [AnyCancellable] = []
override func setUpWithError() throws {
try super.setUpWithError()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
self.coordinator = TestCoordinator.make(
walletBirthday: birthday + 50, // don't use an exact birthday, users never do.
network: network
)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
}
override func tearDownWithError() throws {
2022-11-01 03:47:31 -07:00
try super.tearDownWithError()
NotificationCenter.default.removeObserver(self)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait { try await self.coordinator.stop() }
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
try? FileManager.default.removeItem(at: coordinator.databases.fsCacheDbRoot)
try? FileManager.default.removeItem(at: coordinator.databases.dataDB)
try? FileManager.default.removeItem(at: coordinator.databases.pendingDB)
2023-02-16 08:14:31 -08:00
coordinator = nil
cancellables = []
}
func handleReorg(event: CompactBlockProcessor.Event) {
guard case let .handledReorg(reorgHeight, rewindHeight) = event else { return XCTFail("empty reorg event") }
2021-09-23 06:26:41 -07:00
[#209] Add support for multiple instances of the SDKSynchronizer Closes #209. [#845] Introduce ZcashSynchronizerAlias enum Closes #845. [#852] SDKSynchronizer using queues label based on the alias Closes #852. [#847] Remove posibility to use DatabaseStorageManager as singleton Closes #847. [#850] Remove synchronizerConnectionStateChanged notification Closes #850. [#855] Add check if the Alias is already used Closes #855 - Added `UsedAliasesChecker` utility which is used to register aliases that are in use. - `prepare()` and `wipe()` methods now check if the current alias can't be used and if not then `InitializerError.aliasAlreadyInUse` is thrown/emitted. - Some public methods that could cause harm if used with the Alias that is already in use now throw `SynchronizerError.notPrepared`. Thanks to this the client app is forced to call `prepare()` first. And `prepare()` does check for the Alias. - Added tests for new conditions. [#849] Make InternalSyncProgress aware of the Alias Closes #849. [#853] Only instance with default Alias migrates legacy cache DB Closes #853. [#851] Apply the Alias to the URLs Closes #851. - `Initializer` now updates paths according to alias before paths are used anywhere in the SDK. - Paths update can fail. It would be incovenient for the client apps to handle errors thrown from `Initiliazer` constructor. So the error is then handled in `SDKSynchronizer.prepare()` or `SDKSynchronizer.wipe()`. [#846] Stop using SDKMetrics as singleton (#862) - metrics are not longer a singleton - tests fixed - metrics outside init of the synchronizer [#848] Make logger aware of the alias - logger is now an instance passed throughout the sdk instead of a static proxy [#848] Make logger aware of the alias (#868) - comments addressed [#848] Make logger aware of the alias (#868) - returning protocol back Fix typos [#856] Add possibility to test multiple synchronizers in the sample app Closes #856. - Added `alias` property to `Synchronizer`. - Added `SyncBlocksListViewController` which provides UI to use multiple synchronizers at once. [#209] Add changelog - Add changelog for #209. - Overall improve readability of the rendered changelog. Tickets references are now prefixed with `###` instead of `- `. Fix compilation
2023-03-22 05:47:32 -07:00
logger.debug("--- REORG DETECTED \(reorgHeight)--- RewindHeight: \(rewindHeight)", file: #file, function: #function, line: #line)
2021-09-23 06:26:41 -07:00
XCTAssertEqual(reorgHeight, expectedReorgHeight)
reorgExpectation.fulfill()
}
/// pre-condition: know balances before tx at received_Tx_height arrives
/// 1. Setup w/ default dataset
/// 2. applyStaged(received_Tx_height)
/// 3. sync up to received_Tx_height
/// 3a. verify that balance is previous balance + tx amount
/// 4. get that transaction hex encoded data
/// 5. stage 5 empty blocks w/heights received_Tx_height to received_Tx_height + 3
/// 6. stage tx at received_Tx_height + 3
/// 6a. applyheight(received_Tx_height + 1)
/// 7. sync to received_Tx_height + 1
/// 8. assert that reorg happened at received_Tx_height
/// 9. verify that balance equals initial balance
/// 10. sync up to received_Tx_height + 3
/// 11. verify that balance equals initial balance + tx amount
func testReOrgChangesInboundTxMinedHeight() async throws {
await hookToReOrgNotification()
2021-05-18 14:22:29 -07:00
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
2021-09-23 06:26:41 -07:00
var shouldContinue = false
let receivedTxHeight: BlockHeight = 663188
var initialTotalBalance = Zatoshi(-1)
var initialVerifiedBalance = Zatoshi(-1)
self.expectedReorgHeight = receivedTxHeight + 1
/*
2021-09-23 06:26:41 -07:00
precondition:know balances before tx at received_Tx_height arrives
*/
try coordinator.applyStaged(blockheight: receivedTxHeight - 1)
sleep(3)
let preTxExpectation = XCTestExpectation(description: "pre receive")
2021-09-23 06:26:41 -07:00
var synchronizer: SDKSynchronizer?
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchro in
synchronizer = synchro
initialVerifiedBalance = synchro.initializer.getVerifiedBalance()
initialTotalBalance = synchro.initializer.getBalance()
preTxExpectation.fulfill()
shouldContinue = true
},
error: self.handleError
)
} catch {
await handleError(error)
}
2021-04-08 10:18:16 -07:00
wait(for: [preTxExpectation], timeout: 10)
guard shouldContinue else {
XCTFail("pre receive sync failed")
return
}
/*
2021-09-23 06:26:41 -07:00
2. applyStaged(received_Tx_height)
*/
try coordinator.applyStaged(blockheight: receivedTxHeight)
2021-04-06 07:48:53 -07:00
sleep(2)
/*
2021-09-23 06:26:41 -07:00
3. sync up to received_Tx_height
*/
let receivedTxExpectation = XCTestExpectation(description: "received tx")
var receivedTxTotalBalance = Zatoshi(-1)
var receivedTxVerifiedBalance = Zatoshi(-1)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchro in
synchronizer = synchro
receivedTxVerifiedBalance = synchro.initializer.getVerifiedBalance()
receivedTxTotalBalance = synchro.initializer.getBalance()
receivedTxExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
}, error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
sleep(2)
wait(for: [receivedTxExpectation], timeout: 10)
2021-09-23 06:26:41 -07:00
guard let syncedSynchronizer = synchronizer else {
XCTFail("nil synchronizer")
return
}
sleep(5)
guard let receivedTx = syncedSynchronizer.receivedTransactions.first, receivedTx.minedHeight == receivedTxHeight else {
XCTFail("did not receive transaction")
return
}
/*
2021-09-23 06:26:41 -07:00
3a. verify that balance is previous balance + tx amount
*/
XCTAssertEqual(receivedTxTotalBalance, initialTotalBalance + receivedTx.value)
XCTAssertEqual(receivedTxVerifiedBalance, initialVerifiedBalance)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
4. get that transaction hex encoded data
*/
let receivedTxData = receivedTx.raw ?? Data()
let receivedRawTx = RawTransaction.with { rawTx in
rawTx.height = UInt64(receivedTxHeight)
rawTx.data = receivedTxData
}
/*
2021-09-23 06:26:41 -07:00
5. stage 5 empty blocks w/heights received_Tx_height to received_Tx_height + 4
*/
try coordinator.stageBlockCreate(height: receivedTxHeight, count: 5)
/*
2021-09-23 06:26:41 -07:00
6. stage tx at received_Tx_height + 3
*/
let reorgedTxheight = receivedTxHeight + 2
2021-09-23 06:26:41 -07:00
try coordinator.stageTransaction(receivedRawTx, at: reorgedTxheight)
/*
2021-09-23 06:26:41 -07:00
6a. applyheight(received_Tx_height + 1)
*/
try coordinator.applyStaged(blockheight: receivedTxHeight + 1)
sleep(2)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
7. sync to received_Tx_height + 1
*/
let reorgSyncexpectation = XCTestExpectation(description: "reorg expectation")
var afterReorgTxTotalBalance = Zatoshi(-1)
var afterReorgTxVerifiedBalance = Zatoshi(-1)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchronizer in
afterReorgTxTotalBalance = synchronizer.initializer.getBalance()
afterReorgTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
reorgSyncexpectation.fulfill()
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
/*
2021-09-23 06:26:41 -07:00
8. assert that reorg happened at received_Tx_height
*/
sleep(2)
wait(for: [reorgExpectation, reorgSyncexpectation], timeout: 5, enforceOrder: false)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
9. verify that balance equals initial balance
*/
XCTAssertEqual(afterReorgTxVerifiedBalance, initialVerifiedBalance)
XCTAssertEqual(afterReorgTxTotalBalance, initialTotalBalance)
/*
2021-09-23 06:26:41 -07:00
10. sync up to received_Tx_height + 3
*/
let finalsyncExpectation = XCTestExpectation(description: "final sync")
var finalReorgTxTotalBalance = Zatoshi(-1)
var finalReorgTxVerifiedBalance = Zatoshi(-1)
try coordinator.applyStaged(blockheight: reorgedTxheight + 1)
sleep(3)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchronizer in
finalReorgTxTotalBalance = synchronizer.initializer.getBalance()
finalReorgTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
finalsyncExpectation.fulfill()
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait(for: [finalsyncExpectation], timeout: 5)
sleep(3)
guard let reorgedTx = coordinator.synchronizer.receivedTransactions.first else {
XCTFail("no transactions found")
return
}
XCTAssertEqual(reorgedTx.minedHeight, reorgedTxheight)
XCTAssertEqual(initialVerifiedBalance, finalReorgTxVerifiedBalance)
XCTAssertEqual(initialTotalBalance + receivedTx.value, finalReorgTxTotalBalance)
}
/// An outbound, unconfirmed transaction in a specific block changes height in the event of a reorg
///
///
/// The wallet handles this change, reflects it appropriately in local storage, and funds remain spendable post confirmation.
///
/// Pre-conditions:
/// - Wallet has spendable funds
///
/// 1. Setup w/ default dataset
/// 2. applyStaged(received_Tx_height)
/// 3. sync up to received_Tx_height
/// 4. create transaction
/// 5. stage 10 empty blocks
/// 6. submit tx at sentTxHeight
/// a. getIncomingTx
/// b. stageTransaction(sentTx, sentTxHeight)
/// c. applyheight(sentTxHeight + 1 )
/// 7. sync to sentTxHeight + 2
/// 8. stage sentTx and otherTx at sentTxheight
/// 9. applyStaged(sentTx + 2)
/// 10. sync up to received_Tx_height + 2
/// 11. verify that the sent tx is mined and balance is correct
/// 12. applyStaged(sentTx + 10)
/// 13. verify that there's no more pending transaction
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
@MainActor func testReorgChangesOutboundTxIndex() async throws {
2021-05-18 14:22:29 -07:00
try FakeChainBuilder.buildChain(darksideWallet: self.coordinator.service, branchID: branchID, chainName: chainName)
let receivedTxHeight: BlockHeight = 663188
var initialTotalBalance = Zatoshi(-1)
/*
2021-09-23 06:26:41 -07:00
2. applyStaged(received_Tx_height)
*/
try coordinator.applyStaged(blockheight: receivedTxHeight)
sleep(2)
let preTxExpectation = XCTestExpectation(description: "pre receive")
/*
2021-09-23 06:26:41 -07:00
3. sync up to received_Tx_height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchronizer in
initialTotalBalance = synchronizer.initializer.getBalance()
preTxExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait(for: [preTxExpectation], timeout: 5)
let sendExpectation = XCTestExpectation(description: "sendToAddress")
2021-09-23 06:26:41 -07:00
var pendingEntity: PendingTransactionEntity?
var testError: Error?
let sendAmount = Zatoshi(10000)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
4. create transaction
*/
do {
let pendingTx = try await coordinator.synchronizer.sendToAddress(
spendingKey: coordinator.spendingKey,
zatoshi: sendAmount,
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
memo: try Memo(string: "test transaction")
)
pendingEntity = pendingTx
sendExpectation.fulfill()
} catch {
testError = error
XCTFail("error sending to address. Error: \(String(describing: error))")
}
wait(for: [sendExpectation], timeout: 2)
2021-09-23 06:26:41 -07:00
guard let pendingTx = pendingEntity else {
XCTFail("error sending to address. Error: \(String(describing: testError))")
return
}
/*
2021-09-23 06:26:41 -07:00
5. stage 10 empty blocks
*/
try coordinator.stageBlockCreate(height: receivedTxHeight + 1, count: 10)
let sentTxHeight = receivedTxHeight + 1
/*
2021-09-23 06:26:41 -07:00
6. stage sent tx at sentTxHeight
*/
guard let sentTx = try coordinator.getIncomingTransactions()?.first else {
XCTFail("sent transaction not present on Darksidewalletd")
return
}
try coordinator.stageTransaction(sentTx, at: sentTxHeight)
/*
2021-09-23 06:26:41 -07:00
6a. applyheight(sentTxHeight + 1 )
*/
try coordinator.applyStaged(blockheight: sentTxHeight + 1)
sleep(2)
/*
2021-09-23 06:26:41 -07:00
7. sync to sentTxHeight + 1
*/
let sentTxSyncExpectation = XCTestExpectation(description: "sent tx sync expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchronizer in
let pMinedHeight = synchronizer.pendingTransactions.first?.minedHeight
XCTAssertEqual(pMinedHeight, sentTxHeight)
sentTxSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait(for: [sentTxSyncExpectation], timeout: 5)
/*
2021-09-23 06:26:41 -07:00
8. stage sentTx and otherTx at sentTxheight
*/
try coordinator.stageBlockCreate(height: sentTxHeight, count: 20, nonce: 5)
2020-12-14 13:55:51 -08:00
try coordinator.stageTransaction(url: FakeChainBuilder.someOtherTxUrl, at: sentTxHeight)
try coordinator.stageTransaction(sentTx, at: sentTxHeight)
/*
2021-09-23 06:26:41 -07:00
9. applyStaged(sentTx + 1)
*/
try coordinator.applyStaged(blockheight: sentTxHeight + 1)
sleep(2)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
print("Starting after reorg sync")
let afterReOrgExpectation = XCTestExpectation(description: "after ReOrg Expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { synchronizer in
/*
11. verify that the sent tx is mined and balance is correct
*/
let pMinedHeight = synchronizer.pendingTransactions.first?.minedHeight
XCTAssertEqual(pMinedHeight, sentTxHeight)
// fee change on this branch
XCTAssertEqual(initialTotalBalance - sendAmount - Zatoshi(1000), synchronizer.initializer.getBalance())
afterReOrgExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait(for: [afterReOrgExpectation], timeout: 5)
/*
2021-09-23 06:26:41 -07:00
12. applyStaged(sentTx + 10)
*/
try coordinator.applyStaged(blockheight: sentTxHeight + 12)
sleep(2)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
13. verify that there's no more pending transaction
*/
let lastSyncExpectation = XCTestExpectation(description: "sync to confirmation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
lastSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait(for: [lastSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 0)
XCTAssertEqual(initialTotalBalance - pendingTx.value - Zatoshi(1000), coordinator.synchronizer.initializer.getVerifiedBalance())
let resultingBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
XCTAssertEqual(resultingBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
}
@MainActor func testIncomingTransactionIndexChange() async throws {
await hookToReOrgNotification()
self.expectedReorgHeight = 663196
self.expectedRewindHeight = 663175
try coordinator.reset(saplingActivation: birthday, branchID: "2bb40e60", chainName: "main")
try coordinator.resetBlocks(dataset: .predefined(dataset: .txIndexChangeBefore))
try coordinator.applyStaged(blockheight: 663195)
sleep(1)
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
var preReorgTotalBalance = Zatoshi.zero
var preReorgVerifiedBalance = Zatoshi.zero
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { synchronizer in
preReorgTotalBalance = synchronizer.initializer.getBalance()
preReorgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
firstSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [firstSyncExpectation], timeout: 10)
/*
2021-09-23 06:26:41 -07:00
trigger reorg
*/
try coordinator.resetBlocks(dataset: .predefined(dataset: .txIndexChangeAfter))
try coordinator.applyStaged(blockheight: 663200)
sleep(1)
let afterReorgSync = XCTestExpectation(description: "after reorg sync")
var postReorgTotalBalance = Zatoshi.zero
var postReorgVerifiedBalance = Zatoshi.zero
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { synchronizer in
postReorgTotalBalance = synchronizer.initializer.getBalance()
postReorgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
afterReorgSync.fulfill()
},
error: self.handleError
)
wait(for: [reorgExpectation, afterReorgSync], timeout: 30)
XCTAssertEqual(postReorgVerifiedBalance, preReorgVerifiedBalance)
XCTAssertEqual(postReorgTotalBalance, preReorgTotalBalance)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
func testReOrgExpiresInboundTransaction() async throws {
2021-05-18 14:22:29 -07:00
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
let receivedTxHeight = BlockHeight(663188)
try coordinator.applyStaged(blockheight: receivedTxHeight - 1)
sleep(2)
let expectation = XCTestExpectation(description: "sync to \(receivedTxHeight - 1) expectation")
var initialBalance = Zatoshi(-1)
var initialVerifiedBalance = Zatoshi(-1)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { synchronizer in
initialBalance = synchronizer.initializer.getBalance()
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
expectation.fulfill()
},
error: self.handleError
)
wait(for: [expectation], timeout: 5)
let afterTxHeight = receivedTxHeight + 1
try coordinator.applyStaged(blockheight: afterTxHeight)
sleep(2)
let afterTxSyncExpectation = XCTestExpectation(description: "sync to \(afterTxHeight) expectation")
var afterTxBalance = Zatoshi(-1)
var afterTxVerifiedBalance = Zatoshi(-1)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { synchronizer in
afterTxBalance = synchronizer.initializer.getBalance()
afterTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
XCTAssertNotNil(
synchronizer.receivedTransactions.first { $0.minedHeight == receivedTxHeight },
"Transaction not found at \(receivedTxHeight)"
)
afterTxSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [afterTxSyncExpectation], timeout: 10.0)
XCTAssertEqual(initialVerifiedBalance, afterTxVerifiedBalance)
XCTAssertNotEqual(initialBalance, afterTxBalance)
let reorgSize: Int = 3
let newBlocksCount: Int = 11 + reorgSize
try coordinator.stageBlockCreate(height: receivedTxHeight - reorgSize, count: newBlocksCount + reorgSize)
try coordinator.applyStaged(blockheight: receivedTxHeight + newBlocksCount - 1)
sleep(2)
let afterReorgExpectation = XCTestExpectation(description: "after reorg expectation")
var afterReOrgBalance = Zatoshi(-1)
var afterReOrgVerifiedBalance = Zatoshi(-1)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { synchronizer in
afterReOrgBalance = synchronizer.initializer.getBalance()
afterReOrgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
XCTAssertNil(
synchronizer.receivedTransactions.first { $0.minedHeight == receivedTxHeight },
"Transaction found at \(receivedTxHeight) after reorg"
)
afterReorgExpectation.fulfill()
},
error: self.handleError
)
wait(for: [afterReorgExpectation], timeout: 5)
XCTAssertEqual(afterReOrgBalance, initialBalance)
XCTAssertEqual(afterReOrgVerifiedBalance, initialVerifiedBalance)
}
/// Steps:
/// 1. sync up to an incoming transaction (incomingTxHeight + 1)
/// 1a. save balances
/// 2. stage 4 blocks from incomingTxHeight - 1 with different nonce
/// 3. stage otherTx at incomingTxHeight
/// 4. stage incomingTx at incomingTxHeight
/// 5. applyHeight(incomingHeight + 3)
/// 6. sync to latest height
/// 7. check that balances still match
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
func testReOrgChangesInboundTxIndexInBlock() async throws {
2021-05-18 14:22:29 -07:00
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
let incomingTxHeight = BlockHeight(663188)
try coordinator.applyStaged(blockheight: incomingTxHeight + 1)
sleep(1)
/*
2021-09-23 06:26:41 -07:00
1. sync up to an incoming transaction (incomingTxHeight + 1)
*/
let firstSyncExpectation = XCTestExpectation(description: "first sync test expectation")
var initialBalance = Zatoshi(-1)
var initialVerifiedBalance = Zatoshi(-1)
var incomingTx: ZcashTransaction.Received!
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
firstSyncExpectation.fulfill()
}, error: self.handleError
)
wait(for: [firstSyncExpectation], timeout: 5)
/*
2021-09-23 06:26:41 -07:00
1a. save balances
*/
initialBalance = coordinator.synchronizer.initializer.getBalance()
initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
incomingTx = coordinator.synchronizer.receivedTransactions.first(where: { $0.minedHeight == incomingTxHeight })
2021-09-23 06:26:41 -07:00
let txRawData = incomingTx.raw ?? Data()
2021-09-23 06:26:41 -07:00
let rawTransaction = RawTransaction.with({ rawTx in
rawTx.data = txRawData
})
/*
2021-09-23 06:26:41 -07:00
2. stage 4 blocks from incomingTxHeight - 1 with different nonce
*/
let blockCount = 4
try coordinator.stageBlockCreate(height: incomingTxHeight - 1, count: blockCount, nonce: Int.random(in: 0 ... Int.max))
/*
2021-09-23 06:26:41 -07:00
3. stage otherTx at incomingTxHeight
*/
try coordinator.stageTransaction(url: FakeChainBuilder.someOtherTxUrl, at: incomingTxHeight)
/*
2021-09-23 06:26:41 -07:00
4. stage incomingTx at incomingTxHeight
5. applyHeight(incomingHeight + 3)
6. sync to latest height
7. check that balances still match
*/
try coordinator.stageTransaction(rawTransaction, at: incomingTxHeight)
/*
2021-09-23 06:26:41 -07:00
5. applyHeight(incomingHeight + 2)
*/
try coordinator.applyStaged(blockheight: incomingTxHeight + 2)
sleep(1)
let lastSyncExpectation = XCTestExpectation(description: "last sync expectation")
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
6. sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
lastSyncExpectation.fulfill()
}, error: self.handleError
)
/*
2021-09-23 06:26:41 -07:00
7. check that balances still match
*/
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), initialVerifiedBalance)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), initialBalance)
wait(for: [lastSyncExpectation], timeout: 5)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
func testTxIndexReorg() async throws {
try coordinator.resetBlocks(dataset: .predefined(dataset: .txIndexChangeBefore))
let txReorgHeight = BlockHeight(663195)
let finalHeight = BlockHeight(663200)
try coordinator.applyStaged(blockheight: txReorgHeight)
sleep(1)
let firstSyncExpectation = XCTestExpectation(description: "first sync test expectation")
var initialBalance = Zatoshi(-1)
var initialVerifiedBalance = Zatoshi(-1)
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { synchronizer in
initialBalance = synchronizer.initializer.getBalance()
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
firstSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [firstSyncExpectation], timeout: 5)
2021-09-23 06:26:41 -07:00
try coordinator.resetBlocks(dataset: .predefined(dataset: .txIndexChangeAfter))
try coordinator.applyStaged(blockheight: finalHeight)
sleep(1)
let lastSyncExpectation = XCTestExpectation(description: "last sync expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
lastSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [lastSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), initialBalance)
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), initialVerifiedBalance)
}
/// A Re Org occurs and changes the height of an outbound transaction
/// Pre-condition: Wallet has funds
///
/// Steps:
/// 1. create fake chain
/// 1a. sync to latest height
/// 2. send transaction to recipient address
/// 3. getIncomingTransaction
/// 4. stage transaction at sentTxHeight
/// 5. applyHeight(sentTxHeight)
/// 6. sync to latest height
/// 6a. verify that there's a pending transaction with a mined height of sentTxHeight
/// 7. stage 15 blocks from sentTxHeight
/// 7. a stage sent tx to sentTxHeight + 2
/// 8. applyHeight(sentTxHeight + 1) to cause a 1 block reorg
/// 9. sync to latest height
/// 10. verify that there's a pending transaction with -1 mined height
/// 11. applyHeight(sentTxHeight + 2)
/// 11a. sync to latest height
/// 12. verify that there's a pending transaction with a mined height of sentTxHeight + 2
/// 13. apply height(sentTxHeight + 15)
/// 14. sync to latest height
/// 15. verify that there's no pending transaction and that the tx is displayed on the sentTransactions collection
func testReOrgChangesOutboundTxMinedHeight() async throws {
await hookToReOrgNotification()
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
1. create fake chain
*/
2021-05-18 14:22:29 -07:00
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
try coordinator.applyStaged(blockheight: 663188)
sleep(2)
let firstSyncExpectation = XCTestExpectation(description: "first sync")
/*
2021-09-23 06:26:41 -07:00
1a. sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
firstSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
wait(for: [firstSyncExpectation], timeout: 5)
sleep(1)
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let sendExpectation = XCTestExpectation(description: "send expectation")
2021-09-23 06:26:41 -07:00
var pendingEntity: PendingTransactionEntity?
/*
2021-09-23 06:26:41 -07:00
2. send transaction to recipient address
*/
do {
let pendingTx = try await coordinator.synchronizer.sendToAddress(
spendingKey: self.coordinator.spendingKey,
zatoshi: Zatoshi(20000),
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
memo: try Memo(string: "this is a test")
)
pendingEntity = pendingTx
sendExpectation.fulfill()
} catch {
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
await handleError(error)
}
wait(for: [sendExpectation], timeout: 11)
2021-09-23 06:26:41 -07:00
guard pendingEntity != nil else {
XCTFail("no pending transaction after sending")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.stop()
return
}
2021-09-23 06:26:41 -07:00
/**
2021-09-23 06:26:41 -07:00
3. getIncomingTransaction
*/
guard let incomingTx = try coordinator.getIncomingTransactions()?.first else {
XCTFail("no incoming transaction")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.stop()
return
}
let sentTxHeight: BlockHeight = 663189
/*
2021-09-23 06:26:41 -07:00
4. stage transaction at sentTxHeight
*/
try coordinator.stageBlockCreate(height: sentTxHeight)
try coordinator.stageTransaction(incomingTx, at: sentTxHeight)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
5. applyHeight(sentTxHeight)
*/
try coordinator.applyStaged(blockheight: sentTxHeight)
sleep(2)
/*
2021-09-23 06:26:41 -07:00
6. sync to latest height
*/
let secondSyncExpectation = XCTestExpectation(description: "after send expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
secondSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [secondSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 1)
guard let afterStagePendingTx = coordinator.synchronizer.pendingTransactions.first else {
return
}
/*
2021-09-23 06:26:41 -07:00
6a. verify that there's a pending transaction with a mined height of sentTxHeight
*/
XCTAssertEqual(afterStagePendingTx.minedHeight, sentTxHeight)
/*
2021-09-23 06:26:41 -07:00
7. stage 20 blocks from sentTxHeight
*/
try coordinator.stageBlockCreate(height: sentTxHeight, count: 25)
/*
2021-09-23 06:26:41 -07:00
7a. stage sent tx to sentTxHeight + 2
*/
try coordinator.stageTransaction(incomingTx, at: sentTxHeight + 2)
/*
2021-09-23 06:26:41 -07:00
8. applyHeight(sentTxHeight + 1) to cause a 1 block reorg
*/
try coordinator.applyStaged(blockheight: sentTxHeight + 1)
sleep(2)
/*
2021-09-23 06:26:41 -07:00
9. sync to latest height
*/
self.expectedReorgHeight = sentTxHeight + 1
let afterReorgExpectation = XCTestExpectation(description: "after reorg sync")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
afterReorgExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
2021-09-23 06:26:41 -07:00
wait(for: [reorgExpectation, afterReorgExpectation], timeout: 5)
/*
2021-09-23 06:26:41 -07:00
10. verify that there's a pending transaction with -1 mined height
*/
guard let newPendingTx = coordinator.synchronizer.pendingTransactions.first else {
XCTFail("No pending transaction")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.stop()
return
}
XCTAssertEqual(newPendingTx.minedHeight, BlockHeight.empty())
/*
2021-09-23 06:26:41 -07:00
11. applyHeight(sentTxHeight + 2)
*/
try coordinator.applyStaged(blockheight: sentTxHeight + 2)
sleep(2)
let yetAnotherExpectation = XCTestExpectation(description: "after staging expectation")
/*
2021-09-23 06:26:41 -07:00
11a. sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
yetAnotherExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [yetAnotherExpectation], timeout: 5)
/*
2021-09-23 06:26:41 -07:00
12. verify that there's a pending transaction with a mined height of sentTxHeight + 2
*/
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 1)
guard let newlyPendingTx = try coordinator.synchronizer.allPendingTransactions().first else {
XCTFail("no pending transaction")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.stop()
return
}
XCTAssertEqual(newlyPendingTx.minedHeight, sentTxHeight + 2)
/*
2021-09-23 06:26:41 -07:00
13. apply height(sentTxHeight + 25)
*/
try coordinator.applyStaged(blockheight: sentTxHeight + 25)
sleep(2)
let thisIsTheLastExpectationIPromess = XCTestExpectation(description: "last sync")
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
14. sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
thisIsTheLastExpectationIPromess.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [thisIsTheLastExpectationIPromess], timeout: 5)
/*
2021-09-23 06:26:41 -07:00
15. verify that there's no pending transaction and that the tx is displayed on the sentTransactions collection
*/
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 0)
let sentTransactions = coordinator.synchronizer.sentTransactions
.first(
where: { transaction in
return transaction.rawID == newlyPendingTx.rawTransactionId
}
)
2021-09-23 06:26:41 -07:00
XCTAssertNotNil(
sentTransactions,
2021-09-23 06:26:41 -07:00
"Sent Tx is not on sent transactions"
)
2021-09-23 06:26:41 -07:00
XCTAssertEqual(
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
2021-09-23 06:26:41 -07:00
coordinator.synchronizer.initializer.getBalance()
)
XCTAssertEqual(
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
2021-09-23 06:26:41 -07:00
coordinator.synchronizer.initializer.getVerifiedBalance()
)
}
2021-09-23 06:26:41 -07:00
/// Uses the zcash-hackworks data set.
/// A Re Org occurs at 663195, and sweeps an Inbound Tx that appears later on the chain.
/// Steps:
/// 1. reset dlwd
/// 2. load blocks from txHeightReOrgBefore
/// 3. applyStaged(663195)
/// 4. sync to latest height
/// 5. get balances
/// 6. load blocks from dataset txHeightReOrgBefore
/// 7. apply stage 663200
/// 8. sync to latest height
/// 9. verify that the balance is equal to the one before the reorg
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
func testReOrgChangesInboundMinedHeight() async throws {
try coordinator.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
sleep(2)
try coordinator.resetBlocks(dataset: .predefined(dataset: .txHeightReOrgBefore))
sleep(2)
try coordinator.applyStaged(blockheight: 663195)
sleep(2)
let firstSyncExpectation = XCTestExpectation(description: "first sync")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
firstSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [firstSyncExpectation], timeout: 5)
let initialBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
guard let initialTxHeight = try coordinator.synchronizer.allReceivedTransactions().first?.minedHeight else {
XCTFail("no incoming transaction found!")
return
}
try coordinator.resetBlocks(dataset: .predefined(dataset: .txHeightReOrgAfter))
sleep(5)
try coordinator.applyStaged(blockheight: 663200)
sleep(6)
let afterReOrgExpectation = XCTestExpectation(description: "after reorg")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
afterReOrgExpectation.fulfill()
},
error: self.handleError
)
wait(for: [afterReOrgExpectation], timeout: 5)
guard let afterReOrgTxHeight = coordinator.synchronizer.receivedTransactions.first?.minedHeight else {
XCTFail("no incoming transaction found after re org!")
return
}
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(initialBalance, coordinator.synchronizer.initializer.getBalance())
XCTAssert(afterReOrgTxHeight > initialTxHeight)
}
2021-09-23 06:26:41 -07:00
/// Re Org removes incoming transaction and is never mined
/// Steps:
/// 1. sync prior to incomingTxHeight - 1 to get balances there
/// 2. sync to latest height
/// 3. cause reorg
/// 4. sync to latest height
/// 5. verify that reorg Happened at reorgHeight
/// 6. verify that balances match initial balances
// FIXME [#644]: Test works with lightwalletd v0.4.13 but is broken when using newer lightwalletd. More info is in #644.
@MainActor func testReOrgRemovesIncomingTxForever() async throws {
await hookToReOrgNotification()
try coordinator.reset(saplingActivation: 663150, branchID: branchID, chainName: chainName)
try coordinator.resetBlocks(dataset: .predefined(dataset: .txReOrgRemovesInboundTxBefore))
let reorgHeight: BlockHeight = 663195
self.expectedReorgHeight = reorgHeight
self.expectedRewindHeight = reorgHeight - 10
try coordinator.applyStaged(blockheight: reorgHeight - 1)
sleep(2)
let firstSyncExpectation = XCTestExpectation(description: "first sync")
2021-06-19 16:41:54 -07:00
/**
2021-09-23 06:26:41 -07:00
1. sync prior to incomingTxHeight - 1 to get balances there
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
firstSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [firstSyncExpectation], timeout: 5)
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
try coordinator.applyStaged(blockheight: reorgHeight)
sleep(1)
let secondSyncExpectation = XCTestExpectation(description: "second sync expectation")
2021-06-19 16:41:54 -07:00
/**
2021-09-23 06:26:41 -07:00
2. sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
secondSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [secondSyncExpectation], timeout: 10)
2021-06-19 16:41:54 -07:00
/**
2021-09-23 06:26:41 -07:00
3. cause reorg
*/
try coordinator.resetBlocks(dataset: .predefined(dataset: .txReOrgRemovesInboundTxAfter))
try coordinator.applyStaged(blockheight: 663200)
sleep(2)
let afterReorgSyncExpectation = XCTestExpectation(description: "after reorg expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.sync(
completion: { _ in
afterReorgSyncExpectation.fulfill()
},
error: self.handleError
)
wait(for: [afterReorgSyncExpectation], timeout: 5)
XCTAssertEqual(initialVerifiedBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
XCTAssertEqual(initialTotalBalance, coordinator.synchronizer.initializer.getBalance())
}
/// Transaction was included in a block, and then is not included in a block after a reorg, and expires.
/// Steps:
/// 1. create fake chain
/// 1a. sync to latest height
/// 2. send transaction to recipient address
/// 3. getIncomingTransaction
/// 4. stage transaction at sentTxHeight
/// 5. applyHeight(sentTxHeight)
/// 6. sync to latest height
/// 6a. verify that there's a pending transaction with a mined height of sentTxHeight
/// 7. stage 15 blocks from sentTxHeigth to cause a reorg
/// 8. sync to latest height
/// 9. verify that there's an expired transaction as a pending transaction
func testReOrgRemovesOutboundTxAndIsNeverMined() async throws {
await hookToReOrgNotification()
/*
2021-09-23 06:26:41 -07:00
1. create fake chain
*/
2021-05-18 14:22:29 -07:00
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
let sentTxHeight: BlockHeight = 663195
try coordinator.applyStaged(blockheight: sentTxHeight - 1)
sleep(2)
let firstSyncExpectation = XCTestExpectation(description: "first sync")
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
1a. sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
firstSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [firstSyncExpectation], timeout: 10)
sleep(1)
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
let sendExpectation = XCTestExpectation(description: "send expectation")
2021-09-23 06:26:41 -07:00
var pendingEntity: PendingTransactionEntity?
/*
2021-09-23 06:26:41 -07:00
2. send transaction to recipient address
*/
do {
let pendingTx = try await coordinator.synchronizer.sendToAddress(
spendingKey: self.coordinator.spendingKey,
zatoshi: Zatoshi(20000),
toAddress: try Recipient(Environment.testRecipientAddress, network: self.network.networkType),
memo: try! Memo(string: "this is a test")
)
pendingEntity = pendingTx
sendExpectation.fulfill()
} catch {
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
await handleError(error)
}
wait(for: [sendExpectation], timeout: 11)
2021-09-23 06:26:41 -07:00
guard pendingEntity != nil else {
XCTFail("no pending transaction after sending")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.stop()
return
}
2021-09-23 06:26:41 -07:00
/**
2021-09-23 06:26:41 -07:00
3. getIncomingTransaction
*/
guard let incomingTx = try coordinator.getIncomingTransactions()?.first else {
XCTFail("no incoming transaction")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
try await coordinator.stop()
return
}
self.expectedReorgHeight = sentTxHeight + 1
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
4. stage transaction at sentTxHeight
*/
try coordinator.stageBlockCreate(height: sentTxHeight)
try coordinator.stageTransaction(incomingTx, at: sentTxHeight)
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
5. applyHeight(sentTxHeight)
*/
try coordinator.applyStaged(blockheight: sentTxHeight)
sleep(2)
/*
2021-09-23 06:26:41 -07:00
6. sync to latest height
*/
let secondSyncExpectation = XCTestExpectation(description: "after send expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
secondSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [secondSyncExpectation], timeout: 5)
let extraBlocks = 25
try coordinator.stageBlockCreate(height: sentTxHeight, count: extraBlocks, nonce: 5)
try coordinator.applyStaged(blockheight: sentTxHeight + 5)
sleep(2)
let reorgSyncExpectation = XCTestExpectation(description: "reorg sync expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
reorgSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [reorgExpectation, reorgSyncExpectation], timeout: 5)
guard let pendingTx = coordinator.synchronizer.pendingTransactions.first else {
XCTFail("no pending transaction after reorg sync")
return
}
XCTAssertFalse(pendingTx.isMined)
LoggerProxy.info("applyStaged(blockheight: \(sentTxHeight + extraBlocks - 1))")
try coordinator.applyStaged(blockheight: sentTxHeight + extraBlocks - 1)
sleep(2)
let lastSyncExpectation = XCTestExpectation(description: "last sync expectation")
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
lastSyncExpectation.fulfill()
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
},
error: self.handleError
)
} catch {
await handleError(error)
}
wait(for: [lastSyncExpectation], timeout: 5)
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), initialTotalBalance)
}
func testLongSync() async throws {
await hookToReOrgNotification()
/*
2021-09-23 06:26:41 -07:00
1. create fake chain
*/
let fullSyncLength = 100_000
2021-09-23 06:26:41 -07:00
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName, length: fullSyncLength)
try coordinator.applyStaged(blockheight: birthday + fullSyncLength)
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
sleep(20)
let firstSyncExpectation = XCTestExpectation(description: "first sync")
2021-09-23 06:26:41 -07:00
/*
2021-09-23 06:26:41 -07:00
sync to latest height
*/
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
do {
try await coordinator.sync(
completion: { _ in
firstSyncExpectation.fulfill()
},
error: self.handleError
)
} catch {
await handleError(error)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
- [#679] Implementation of the File-system based block cache (#679) Closes https://github.com/zcash/ZcashLightClientKit/issues/697 Closes https://github.com/zcash/ZcashLightClientKit/issues/720 Closes https://github.com/zcash/ZcashLightClientKit/issues/587 Closes https://github.com/zcash/ZcashLightClientKit/issues/667 Closes https://github.com/zcash/ZcashLightClientKit/issues/443 Closes https://github.com/zcash/ZcashLightClientKit/issues/754 - [#790] Fix ShieldFundsTests Closes #790 Removes comments on `ShieldFundsTests` since those issues have been fixed Depends on zcash-light-client-ffi changes that adopt newer versions of librustzcash crates `zcash_primitives 0.10`, `zcash_client_backend 0.7`, `zcash_proofs 0.10`, `zcash_client_sqlite 0.5.0`. Also allows wallets to define a shielding_threshold and will set foundations to customize minimum confirmations for balances, spends and shielding operations. **Test Bootstrapping** - `ZcashCompactBlockDescriptor`: struct that holds functions to describe blocks as filenames and compare those filenames `ZcashCompactBlockDescriptor.live` has the actual implementation but it can be replaced by mocks if needed on Tests main implementations are held under `FSCompactBlockRepository.filenameDescription` and `FSCompactBlockRepository.filenameComparison` on a separate extention `DirectoryListingProviders` provide two default implementations of listing a directory deterministically. `FileManager` does not define a sorting and needs to be done in-memory by calling `.sorted()` on the resulting collection. If this is a big toll on performance it can be changed to a POSIX implementation but this is good for now. `ZcashCompactBlockDescriptor` adds a `height` helper function to turn a filename into the height of the block stored. Implemented `func latestHeight() throws -> BlockHeight ` that returns the blockheight by querying the cache directory in a sorted fashion and getting the last value and turning the filename into a `BlockHeight` Added `Meta` struct to ZcashCompactBlock. Tests implemented: - `filterBlockFiles` - `testClearTheCache` - `testLatestHeightEmptyCacheThrows` - `testLatestHeightEmptyCacheThrowsAsync` - `testRewindEmptyCacheDoesNothing` - `testRewindEmptyCacheDoesNothingAsync` - `testWhenBlockIsStoredItFollowsTheDescribedFormat` - `testWhenBlockIsStoredItFollowsTheFilenameConvention` - `testGetLatestHeight` - `testRewindDeletesTheRightBlocks` test - `testPerformanceExample` test. This isn't a real performance test because the API doesn't work with async/await yet adopts `shield_funds` shielding threshold parameter Implements `initBlockMetadataDb` and fix tests Renames dbCache parameter to `fsBlockDbRoot`. Builds but tests don't pass. Removes cacheDb uses from code. Testing utilities still persist. Added needed information in MIGRATING and CHANGELOG. Added helper to perform deletion of legacy db and creation a the new file system backed cache. Renames parameters and changes code where needed. Network Constants turned into `enum` with static methods. DeletelastDownloadedBlock helper from initializer Removes CompactBlockStorage and CompactBlockEntity. Implements `latestCachedBlockHeight` on rustbackend. *Replaces dependencies on ZcashRustWelding with `FSMetadataStore`* This allows the tests to not depend in a particular implementation of either the MockRustBackend of or ZcashRustBackend. Also provides a way to test errors properly and switch implementations of critical areas like `writeBlocks`.
2023-02-02 08:58:12 -08:00
wait(for: [firstSyncExpectation], timeout: 600)
let latestScannedHeight = coordinator.synchronizer.latestScannedHeight
XCTAssertEqual(latestScannedHeight, birthday + fullSyncLength)
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
func handleError(_ error: Error?) async {
_ = try? await coordinator.stop()
guard let testError = error else {
XCTFail("failed with nil error")
return
}
XCTFail("Failed with error: \(testError)")
}
func hookToReOrgNotification() async {
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
let eventClosure: CompactBlockProcessor.EventClosure = { [weak self] event in
switch event {
case .handledReorg: self?.handleReorg(event: event)
default: break
}
[#831] Add SDKSynchronizer wrappers for non-async API This change introduces two new protocols: `ClosureSynchronizer` and `CombineSynchronizer`. These two protocols define API that doesn't use `async`. So the client can choose exactly which API it wants to use. This change also introduces two new objects: `ClosureSDKSynchronizer` and `CombineSDKSynchronizer`. These two implement the respective protocols mentioned above. Both are structures. Neither of these two keeps any state. Thanks to this each is very cheap to create. And usage of these two isn't mutually exclusive. So devs can really choose the best SDK API for each part of the client app. [#831] Use async inside of the SDKSynchronizer - In general lot of methods inside the `SDKSynchronizer` and `CompactBlockProcessoer` which weren't async are now async. And other changes are made because of this change. - `CompactBlockProcessor` no longer uses Combine to communicate with `SDKSynchronizer`. Reason for this is that Combine doesn't play great with async. Closure passed to `sink` isn't async. - Because of this and because of how our tests work (receiving signals from CBP directly) `CompactBlockProcessor` must be able to handle more event closures. Not just one. So it now has `eventClosures` dictionary. It's little bit strange but it works fine. - `SyncStatus` inside the `SDKSynchronizer` was previously protected by lock. Now it's protected by simple actor wrapper. - Changes in tests are minimal. Changes were mady only because `CompactBlockProcessor` changes from Combine to closures. [#831] Add tests for ClosureSDKSynchronizer - Added tests are testing in general if the `ClosuresSDKSynchronizer` is correctly calling `Synchronizer` and if the values are correctly returned. - `ClosuresSDKSynchronizer` doesn't contain any logic but it is public API and we should be sure that it works correctly. [#831] Add tests for CombineSDKSynchronizer [#831] Add changelog
2023-03-16 02:11:18 -07:00
}
await coordinator.synchronizer.blockProcessor.updateEventClosure(identifier: "tests", closure: eventClosure)
}
}