Merge pull request #1241 from LukasKorba/1236-Use-of-recoverUntil
[#1236] Use of recoverUntil
This commit is contained in:
commit
0d56e4fcc6
|
@ -12,6 +12,12 @@ be able to write to this location after it creates this directory. It is suggest
|
|||
a subdirectory of the `Documents` directory. If this information is stored in `Documents` then the
|
||||
system itself won't remove these data.
|
||||
|
||||
### Changed
|
||||
|
||||
Synchronizer's prepare(...) public API changed, `viewingKeys: [UnifiedFullViewingKey]` has been removed and `for walletMode: WalletInitMode` added.
|
||||
`WalletInitMode` is an enum with 3 cases: .newWallet, .restoreWallet and .existingWallet. Use `.newWallet` when preparing the SDKSynchronizer for a brand new wallet
|
||||
that has been generated. Use `.restoreWallet` when wallet is about to be restored from a seed and `.existingWallet` for all other scenarios.
|
||||
|
||||
### Removed
|
||||
|
||||
### [#1181] Correct computation of progress for Spend before Sync
|
||||
|
|
|
@ -45,7 +45,8 @@ class SendViewController: UIViewController {
|
|||
|
||||
closureSynchronizer.prepare(
|
||||
with: DemoAppConfig.defaultSeed,
|
||||
walletBirthday: DemoAppConfig.defaultBirthdayHeight
|
||||
walletBirthday: DemoAppConfig.defaultBirthdayHeight,
|
||||
for: .existingWallet
|
||||
) { result in
|
||||
loggerProxy.debug("Prepare result: \(result)")
|
||||
}
|
||||
|
|
|
@ -69,7 +69,8 @@ class SyncBlocksListViewController: UIViewController {
|
|||
if syncStatus == .unprepared {
|
||||
_ = try! await synchronizer.prepare(
|
||||
with: synchronizerData.seed,
|
||||
walletBirthday: synchronizerData.birthday
|
||||
walletBirthday: synchronizerData.birthday,
|
||||
for: .existingWallet
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,8 @@ class SyncBlocksViewController: UIViewController {
|
|||
do {
|
||||
_ = try await synchronizer.prepare(
|
||||
with: DemoAppConfig.defaultSeed,
|
||||
walletBirthday: DemoAppConfig.defaultBirthdayHeight
|
||||
walletBirthday: DemoAppConfig.defaultBirthdayHeight,
|
||||
for: .existingWallet
|
||||
)
|
||||
} catch {
|
||||
loggerProxy.error(error.toZcashError().message)
|
||||
|
|
|
@ -25,6 +25,7 @@ public protocol ClosureSynchronizer {
|
|||
func prepare(
|
||||
with seed: [UInt8]?,
|
||||
walletBirthday: BlockHeight,
|
||||
for walletMode: WalletInitMode,
|
||||
completion: @escaping (Result<Initializer.InitializationResult, Error>) -> Void
|
||||
)
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ public protocol CombineSynchronizer {
|
|||
|
||||
func prepare(
|
||||
with seed: [UInt8]?,
|
||||
walletBirthday: BlockHeight
|
||||
walletBirthday: BlockHeight,
|
||||
for walletMode: WalletInitMode
|
||||
) -> SinglePublisher<Initializer.InitializationResult, Error>
|
||||
|
||||
func start(retry: Bool) -> CompletablePublisher<Error>
|
||||
|
|
|
@ -409,7 +409,7 @@ public class Initializer {
|
|||
/// - Parameter seed: ZIP-32 Seed bytes for the wallet that will be initialized
|
||||
/// - Throws: `InitializerError.dataDbInitFailed` if the creation of the dataDb fails
|
||||
/// `InitializerError.accountInitFailed` if the account table can't be initialized.
|
||||
func initialize(with seed: [UInt8]?, walletBirthday: BlockHeight) async throws -> InitializationResult {
|
||||
func initialize(with seed: [UInt8]?, walletBirthday: BlockHeight, for walletMode: WalletInitMode) async throws -> InitializationResult {
|
||||
try await storage.create()
|
||||
|
||||
if case .seedRequired = try await rustBackend.initDataDb(seed: seed) {
|
||||
|
@ -422,11 +422,16 @@ public class Initializer {
|
|||
|
||||
// If there are no accounts it must be created, the default amount of accounts is 1
|
||||
if let seed, try accountRepository.getAll().isEmpty {
|
||||
// TODO: [#1236] set the recoverUntil properly, https://github.com/zcash/ZcashLightClientKit/issues/1236
|
||||
var chainTip: UInt32?
|
||||
|
||||
if walletMode == .restoreWallet {
|
||||
chainTip = UInt32(try await lightWalletService.latestBlockHeight())
|
||||
}
|
||||
|
||||
_ = try await rustBackend.createAccount(
|
||||
seed: seed,
|
||||
treeState: try checkpoint.treeState().serializedData(partial: false).bytes,
|
||||
recoverUntil: nil
|
||||
recoverUntil: chainTip
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ public protocol Synchronizer: AnyObject {
|
|||
/// - Parameters:
|
||||
/// - seed: ZIP-32 Seed bytes for the wallet that will be initialized
|
||||
/// - walletBirthday: Birthday of wallet.
|
||||
/// - walletMode: Set `.newWallet` when preparing synchronizer for a brand new generated wallet, `.restoreWallet` when wallet is about to be restored from a seed and `.existingWallet` for all other scenarios.
|
||||
/// - Throws:
|
||||
/// - `aliasAlreadyInUse` if the Alias used to create this instance is already used by other instance.
|
||||
/// - `cantUpdateURLWithAlias` if the updating of paths in `Initilizer` according to alias fails. When this happens it means that
|
||||
|
@ -130,7 +131,8 @@ public protocol Synchronizer: AnyObject {
|
|||
/// - Some other `ZcashError` thrown by lower layer of the SDK.
|
||||
func prepare(
|
||||
with seed: [UInt8]?,
|
||||
walletBirthday: BlockHeight
|
||||
walletBirthday: BlockHeight,
|
||||
for walletMode: WalletInitMode
|
||||
) async throws -> Initializer.InitializationResult
|
||||
|
||||
/// Starts this synchronizer within the given scope.
|
||||
|
@ -407,6 +409,16 @@ enum InternalSyncStatus: Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
/// Mode of the Synchronizer's initialization for the wallet.
|
||||
public enum WalletInitMode: Equatable {
|
||||
/// For brand new wallet - typically when users creates a new wallet.
|
||||
case newWallet
|
||||
/// For a wallet that is about to be restored. Typically when a user wants to restore a wallet from a seed.
|
||||
case restoreWallet
|
||||
/// All other cases - typically when clients just start the process e.g. every regular app start for mobile apps.
|
||||
case existingWallet
|
||||
}
|
||||
|
||||
/// Kind of transactions handled by a Synchronizer
|
||||
public enum TransactionKind {
|
||||
case sent
|
||||
|
|
|
@ -34,10 +34,11 @@ extension ClosureSDKSynchronizer: ClosureSynchronizer {
|
|||
public func prepare(
|
||||
with seed: [UInt8]?,
|
||||
walletBirthday: BlockHeight,
|
||||
for walletMode: WalletInitMode,
|
||||
completion: @escaping (Result<Initializer.InitializationResult, Error>) -> Void
|
||||
) {
|
||||
AsyncToClosureGateway.executeThrowingAction(completion) {
|
||||
return try await self.synchronizer.prepare(with: seed, walletBirthday: walletBirthday)
|
||||
return try await self.synchronizer.prepare(with: seed, walletBirthday: walletBirthday, for: walletMode)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,10 +33,11 @@ extension CombineSDKSynchronizer: CombineSynchronizer {
|
|||
|
||||
public func prepare(
|
||||
with seed: [UInt8]?,
|
||||
walletBirthday: BlockHeight
|
||||
walletBirthday: BlockHeight,
|
||||
for walletMode: WalletInitMode
|
||||
) -> SinglePublisher<Initializer.InitializationResult, Error> {
|
||||
AsyncToCombineGateway.executeThrowingAction() {
|
||||
return try await self.synchronizer.prepare(with: seed, walletBirthday: walletBirthday)
|
||||
return try await self.synchronizer.prepare(with: seed, walletBirthday: walletBirthday, for: walletMode)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ public class SDKSynchronizer: Synchronizer {
|
|||
|
||||
public func prepare(
|
||||
with seed: [UInt8]?,
|
||||
walletBirthday: BlockHeight
|
||||
walletBirthday: BlockHeight,
|
||||
for walletMode: WalletInitMode
|
||||
) async throws -> Initializer.InitializationResult {
|
||||
guard await status == .unprepared else { return .success }
|
||||
|
||||
|
@ -137,7 +138,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
|
||||
try await utxoRepository.initialise()
|
||||
|
||||
if case .seedRequired = try await self.initializer.initialize(with: seed, walletBirthday: walletBirthday) {
|
||||
if case .seedRequired = try await self.initializer.initialize(with: seed, walletBirthday: walletBirthday, for: walletMode) {
|
||||
return .seedRequired
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testPrepareSucceed() throws {
|
||||
synchronizerMock.prepareWithWalletBirthdayClosure = { receivedSeed, receivedWalletBirthday in
|
||||
synchronizerMock.prepareWithWalletBirthdayForClosure = { receivedSeed, receivedWalletBirthday, _ in
|
||||
XCTAssertEqual(receivedSeed, self.data.seed)
|
||||
XCTAssertEqual(receivedWalletBirthday, self.data.birthday)
|
||||
return .success
|
||||
|
@ -109,7 +109,7 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
|
|||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday) { result in
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday, for: .newWallet) { result in
|
||||
switch result {
|
||||
case let .success(status):
|
||||
XCTAssertEqual(status, .success)
|
||||
|
@ -123,13 +123,13 @@ class ClosureSynchronizerOfflineTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testPrepareThrowsError() throws {
|
||||
synchronizerMock.prepareWithWalletBirthdayClosure = { _, _ in
|
||||
synchronizerMock.prepareWithWalletBirthdayForClosure = { _, _, _ in
|
||||
throw "Some error"
|
||||
}
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday) { result in
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday, for: .newWallet) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Error should be thrown.")
|
||||
|
|
|
@ -101,8 +101,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testPrepareSucceed() throws {
|
||||
let mockedViewingKey = self.data.viewingKey
|
||||
synchronizerMock.prepareWithWalletBirthdayClosure = { receivedSeed, receivedWalletBirthday in
|
||||
synchronizerMock.prepareWithWalletBirthdayForClosure = { receivedSeed, receivedWalletBirthday, _ in
|
||||
XCTAssertEqual(receivedSeed, self.data.seed)
|
||||
XCTAssertEqual(receivedWalletBirthday, self.data.birthday)
|
||||
return .success
|
||||
|
@ -110,7 +109,7 @@ class CombineSynchronizerOfflineTests: XCTestCase {
|
|||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday)
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday, for: .newWallet)
|
||||
.sink(
|
||||
receiveCompletion: { result in
|
||||
switch result {
|
||||
|
@ -130,14 +129,13 @@ class CombineSynchronizerOfflineTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testPrepareThrowsError() throws {
|
||||
let mockedViewingKey = self.data.viewingKey
|
||||
synchronizerMock.prepareWithWalletBirthdayClosure = { _, _ in
|
||||
synchronizerMock.prepareWithWalletBirthdayForClosure = { _, _, _ in
|
||||
throw "Some error"
|
||||
}
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday)
|
||||
synchronizer.prepare(with: data.seed, walletBirthday: data.birthday, for: .newWallet)
|
||||
.sink(
|
||||
receiveCompletion: { result in
|
||||
switch result {
|
||||
|
|
|
@ -304,7 +304,7 @@ class SynchronizerOfflineTests: ZcashTestCase {
|
|||
let synchronizer = SDKSynchronizer(initializer: initializer)
|
||||
|
||||
do {
|
||||
_ = try await synchronizer.prepare(with: Environment.seedBytes, walletBirthday: 123000)
|
||||
_ = try await synchronizer.prepare(with: Environment.seedBytes, walletBirthday: 123000, for: .newWallet)
|
||||
XCTFail("Failure of prepare is expected.")
|
||||
} catch {
|
||||
if let error = error as? ZcashError, case let .initializerCantUpdateURLWithAlias(failedURL) = error {
|
||||
|
|
|
@ -32,11 +32,15 @@ class WalletTests: ZcashTestCase {
|
|||
}
|
||||
|
||||
func testWalletInitialization() async throws {
|
||||
let derivationTool = TestsData(networkType: network.networkType).derivationTools
|
||||
let spendingKey = try derivationTool.deriveUnifiedSpendingKey(seed: seedData.bytes, accountIndex: 0)
|
||||
let viewingKey = try derivationTool.deriveUnifiedFullViewingKey(from: spendingKey)
|
||||
let mockContainer = DIContainer()
|
||||
mockContainer.isTestEnvironment = true
|
||||
|
||||
let serviceMock = LightWalletServiceMock()
|
||||
mockContainer.mock(type: LightWalletService.self, isSingleton: true) { _ in serviceMock }
|
||||
serviceMock.latestBlockHeightReturnValue = 1
|
||||
|
||||
let wallet = Initializer(
|
||||
container: mockContainer,
|
||||
cacheDbURL: nil,
|
||||
fsBlockDbRoot: testTempDirectory,
|
||||
generalStorageURL: testGeneralStorageDirectory,
|
||||
|
@ -50,7 +54,7 @@ class WalletTests: ZcashTestCase {
|
|||
|
||||
let synchronizer = SDKSynchronizer(initializer: wallet)
|
||||
do {
|
||||
guard case .success = try await synchronizer.prepare(with: seedData.bytes, walletBirthday: 663194) else {
|
||||
guard case .success = try await synchronizer.prepare(with: seedData.bytes, walletBirthday: 663194, for: .newWallet) else {
|
||||
XCTFail("Failed to initDataDb. Expected `.success` got: `.seedRequired`")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1185,25 +1185,25 @@ class SynchronizerMock: Synchronizer {
|
|||
|
||||
// MARK: - prepare
|
||||
|
||||
var prepareWithWalletBirthdayThrowableError: Error?
|
||||
var prepareWithWalletBirthdayCallsCount = 0
|
||||
var prepareWithWalletBirthdayCalled: Bool {
|
||||
return prepareWithWalletBirthdayCallsCount > 0
|
||||
var prepareWithWalletBirthdayForThrowableError: Error?
|
||||
var prepareWithWalletBirthdayForCallsCount = 0
|
||||
var prepareWithWalletBirthdayForCalled: Bool {
|
||||
return prepareWithWalletBirthdayForCallsCount > 0
|
||||
}
|
||||
var prepareWithWalletBirthdayReceivedArguments: (seed: [UInt8]?, walletBirthday: BlockHeight)?
|
||||
var prepareWithWalletBirthdayReturnValue: Initializer.InitializationResult!
|
||||
var prepareWithWalletBirthdayClosure: (([UInt8]?, BlockHeight) async throws -> Initializer.InitializationResult)?
|
||||
var prepareWithWalletBirthdayForReceivedArguments: (seed: [UInt8]?, walletBirthday: BlockHeight, walletMode: WalletInitMode)?
|
||||
var prepareWithWalletBirthdayForReturnValue: Initializer.InitializationResult!
|
||||
var prepareWithWalletBirthdayForClosure: (([UInt8]?, BlockHeight, WalletInitMode) async throws -> Initializer.InitializationResult)?
|
||||
|
||||
func prepare(with seed: [UInt8]?, walletBirthday: BlockHeight) async throws -> Initializer.InitializationResult {
|
||||
if let error = prepareWithWalletBirthdayThrowableError {
|
||||
func prepare(with seed: [UInt8]?, walletBirthday: BlockHeight, for walletMode: WalletInitMode) async throws -> Initializer.InitializationResult {
|
||||
if let error = prepareWithWalletBirthdayForThrowableError {
|
||||
throw error
|
||||
}
|
||||
prepareWithWalletBirthdayCallsCount += 1
|
||||
prepareWithWalletBirthdayReceivedArguments = (seed: seed, walletBirthday: walletBirthday)
|
||||
if let closure = prepareWithWalletBirthdayClosure {
|
||||
return try await closure(seed, walletBirthday)
|
||||
prepareWithWalletBirthdayForCallsCount += 1
|
||||
prepareWithWalletBirthdayForReceivedArguments = (seed: seed, walletBirthday: walletBirthday, walletMode: walletMode)
|
||||
if let closure = prepareWithWalletBirthdayForClosure {
|
||||
return try await closure(seed, walletBirthday, walletMode)
|
||||
} else {
|
||||
return prepareWithWalletBirthdayReturnValue
|
||||
return prepareWithWalletBirthdayForReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ class TestCoordinator {
|
|||
}
|
||||
|
||||
func prepare(seed: [UInt8]) async throws -> Initializer.InitializationResult {
|
||||
return try await synchronizer.prepare(with: seed, walletBirthday: self.birthday)
|
||||
return try await synchronizer.prepare(with: seed, walletBirthday: self.birthday, for: .newWallet)
|
||||
}
|
||||
|
||||
func stop() async throws {
|
||||
|
|
Loading…
Reference in New Issue