ZcashLightClientKit/Tests/DarksideTests/AdvancedReOrgTests.swift

1363 lines
49 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] = []
2023-03-30 10:01:47 -07:00
override func setUp() async throws {
try await super.setUp()
// don't use an exact birthday, users never do.
self.coordinator = try await TestCoordinator(walletBirthday: birthday + 50, network: network)
try coordinator.reset(saplingActivation: 663150, branchID: self.branchID, chainName: self.chainName)
}
2023-03-30 10:01:47 -07:00
override func tearDown() async throws {
try await super.tearDown()
let coordinator = self.coordinator!
self.coordinator = nil
cancellables = []
try await 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)
}
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 = try await synchro.getShieldedVerifiedBalance()
initialTotalBalance = try await synchro.getShieldedBalance()
[#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
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 = try await synchro.getShieldedVerifiedBalance()
receivedTxTotalBalance = try await synchro.getShieldedBalance()
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 = await 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 = try await synchronizer.getShieldedBalance()
afterReorgTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
[#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
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 = try await synchronizer.getShieldedBalance()
finalReorgTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
[#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
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 = await 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
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 = try await synchronizer.getShieldedBalance()
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 = await 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 = await synchronizer.pendingTransactions.first?.minedHeight
XCTAssertEqual(pMinedHeight, sentTxHeight)
// fee change on this branch
let expectedBalance = try await synchronizer.getShieldedBalance()
XCTAssertEqual(initialTotalBalance - sendAmount - Zatoshi(1000), expectedBalance)
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)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedPendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(expectedPendingTransactionsCount, 0)
XCTAssertEqual(initialTotalBalance - pendingTx.value - Zatoshi(1000), expectedVerifiedBalance)
let resultingBalance: Zatoshi = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(resultingBalance, expectedVerifiedBalance)
}
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 = try await synchronizer.getShieldedBalance()
preReorgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
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 = try await synchronizer.getShieldedBalance()
postReorgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
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 = try await synchronizer.getShieldedBalance()
initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
[#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
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 = try await synchronizer.getShieldedBalance()
afterTxVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
let receivedTransactions = await synchronizer.receivedTransactions
[#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
XCTAssertNotNil(
receivedTransactions.first { $0.minedHeight == receivedTxHeight },
[#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
"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 = try await synchronizer.getShieldedBalance()
afterReOrgVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
let receivedTransactions = await synchronizer.receivedTransactions
[#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
XCTAssertNil(
receivedTransactions.first { $0.minedHeight == receivedTxHeight },
[#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
"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 = try await coordinator.synchronizer.getShieldedBalance()
initialVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
incomingTx = await 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
*/
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedVerifiedBalance, initialVerifiedBalance)
XCTAssertEqual(expectedBalance, initialBalance)
[#959] Fix `v_transactions` view issues with value (#963) This change switches to a new (future) version of the rust crates that will get rid of the sent and received transactions Views in favor of a `v_transaction` view that will do better accounting of outgoing and incoming funds. Additionally it will support an outputs view for seeing the inner details of transactions enabling the SDKs tell the users the precise movement of value that a tx causes in its multiple possible ways according to the protocol. the `v_tx_outputs` view is not yet implemented. Sent and Received transaction sub-types are kept for compatibility purposes but they are generated from Overviews instead of queried from a specific view. In the transaction Overview the value represents the whole value transfer for the transaction from the point of view of a given account including fees. This means that the value for a single transaction Overview struct represents the addition or subtraction of ZEC value to the account's balance. Future updates will give clients the possibility to drill into the inner workings of those value changes in a per-output basis for each transaction. Also, the field `pending_unmined` field was added to `v_transactions` so that wallets can query `DataDb` for pending but yet unmined txs This will prepare the field for removing the notion of a "PendingDb" and its nuances. Also updated test database `darkside_data.db` Closes #959 Closes #971 ZcashLightClientKitSample main target broken swiftlint script Demo App improvements: Show Short date and value on transaction list
2023-04-18 05:10:56 -07:00
wait(for: [lastSyncExpectation], timeout: 30)
}
[#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 = try await synchronizer.getShieldedBalance()
initialVerifiedBalance = try await synchronizer.getShieldedVerifiedBalance()
[#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
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)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, initialBalance)
XCTAssertEqual(expectedVerifiedBalance, 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 = try await coordinator.synchronizer.getShieldedBalance()
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)
var pendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTransactionsCount, 1)
guard let afterStagePendingTx = await 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 = await 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
*/
pendingTransactionsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTransactionsCount, 1)
guard let newlyPendingTx = try await 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
*/
let pendingTranscationsCount = await coordinator.synchronizer.pendingTransactions.count
XCTAssertEqual(pendingTranscationsCount, 0)
let sentTransactions = await 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"
)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
2021-09-23 06:26:41 -07:00
XCTAssertEqual(
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
expectedBalance
2021-09-23 06:26:41 -07:00
)
XCTAssertEqual(
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
expectedVerifiedBalance
2021-09-23 06:26:41 -07:00
)
}
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 = try await coordinator.synchronizer.getShieldedBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
guard let initialTxHeight = try await 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 = await coordinator.synchronizer.receivedTransactions.first?.minedHeight else {
XCTFail("no incoming transaction found after re org!")
return
}
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(initialBalance, expectedBalance)
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.
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 = try await coordinator.synchronizer.getShieldedBalance()
let initialVerifiedBalance: Zatoshi = try await coordinator.synchronizer.getShieldedVerifiedBalance()
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)
let expectedVerifiedBalance = try await coordinator.synchronizer.getShieldedVerifiedBalance()
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(initialVerifiedBalance, expectedVerifiedBalance)
XCTAssertEqual(initialTotalBalance, expectedBalance)
}
/// 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 = try await coordinator.synchronizer.getShieldedBalance()
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 = await 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)
let expectedBalance = try await coordinator.synchronizer.getShieldedBalance()
XCTAssertEqual(expectedBalance, 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 = await coordinator.synchronizer.latestBlocksDataProvider.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)
}
}