[#444] Syncing Restarts to zero when the wallet is wiped and synced from zero in one go. (#445)

This commit changes the way walletBirthday is stored in the synchronizer and intinitializer. Wallets syncing from creation/restore would have a problem where the birthday stored in the Blocks Table would be the one corresponding to the chekpoint found a the time of syncing, but the compact block downloader would start downloading blocks from the height provided by the user when the wallet was restored. This would cause a `validationFailed` error at the height checkpoint.height + 1 and restart downloading from checkpoint.height and then resume correctly.

Darksidewalletd test setUp was changed re be able to reproduce the error since injection guaranteed correctness and it was not possible to reproduce the error with it since the wallet birthday height provided matched exactly with the checkpoint on disk and that's the only case that avoided this error.

Closes #444
This commit is contained in:
Francisco Gindre 2022-07-29 10:33:23 -03:00 committed by GitHub
parent 96520aeb7c
commit 3be694c920
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 13 additions and 45 deletions

View File

@ -78,6 +78,8 @@ public class Initializer {
private(set) var downloader: CompactBlockDownloader
private(set) var network: ZcashNetwork
private(set) public var viewingKeys: [UnifiedViewingKey]
/// The effective birthday of the wallet based on the height provided when initializing
/// and the checkpoints available on this SDK
private(set) public var walletBirthday: BlockHeight
/**
@ -200,9 +202,9 @@ public class Initializer {
} catch {
throw InitializerError.dataDbInitFailed
}
let checkpoint = Checkpoint.birthday(with: self.walletBirthday, network: network)
do {
let checkpoint = Checkpoint.birthday(with: self.walletBirthday, network: network)
try rustBackend.initBlocksTable(
dbData: dataDbURL,
height: Int32(checkpoint.height),
@ -216,6 +218,7 @@ public class Initializer {
} catch {
throw InitializerError.dataDbInitFailed
}
self.walletBirthday = checkpoint.height
let lastDownloaded = (try? downloader.storage.latestHeight()) ?? walletBirthday
// resume from last downloaded block

View File

@ -158,7 +158,6 @@ public class SDKSynchronizer: Synchronizer {
self.status = .disconnected
}
/// Starts the synchronizer
/// - Throws: CompactBlockProcessorError when failures occur
public func start(retry: Bool = false) throws {

View File

@ -35,7 +35,7 @@ class AdvancedReOrgTests: XCTestCase {
try super.setUpWithError()
coordinator = try TestCoordinator(
seed: seedPhrase,
walletBirthday: birthday,
walletBirthday: birthday + 50, //don't use an exact birthday, users never do.
channelProvider: ChannelProvider(),
network: network
)

View File

@ -125,7 +125,7 @@ class TestCoordinator {
outputParamsURL: try __outputParamsURL(),
spendingKey: spendingKey,
unifiedViewingKey: unifiedViewingKey,
walletBirthday: Checkpoint.birthday(with: birthday, network: network),
walletBirthday: walletBirthday,
network: network,
loggerProxy: SampleLogger(logLevel: .debug)
)
@ -289,59 +289,25 @@ enum TestSynchronizerBuilder {
outputParamsURL: URL,
spendingKey: String,
unifiedViewingKey: UnifiedViewingKey,
walletBirthday: Checkpoint,
walletBirthday: BlockHeight,
network: ZcashNetwork,
loggerProxy: Logger? = nil
) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) {
let initializer = Initializer(
rustBackend: rustBackend,
lowerBoundHeight: lowerBoundHeight,
network: network,
cacheDbURL: cacheDbURL,
dataDbURL: dataDbURL,
pendingDbURL: pendingDbURL,
endpoint: endpoint,
service: service,
repository: repository,
accountRepository: accountRepository,
storage: CompactBlockStorage(url: cacheDbURL, readonly: false),
network: network,
spendParamsURL: spendParamsURL,
outputParamsURL: outputParamsURL,
viewingKeys: [unifiedViewingKey],
walletBirthday: walletBirthday.height,
walletBirthday: walletBirthday,
alias: "",
loggerProxy: loggerProxy
)
let config = CompactBlockProcessor.Configuration(
cacheDb: initializer.cacheDbURL,
dataDb: initializer.dataDbURL,
downloadBatchSize: 100,
retries: 5,
maxBackoffInterval: ZcashSDK.defaultMaxBackOffInterval,
rewindDistance: ZcashSDK.defaultRewindDistance,
walletBirthday: walletBirthday.height,
saplingActivation: lowerBoundHeight,
network: network
)
let processor = CompactBlockProcessor(
service: service,
storage: storage,
backend: rustBackend,
config: config,
repository: repository,
accountRepository: accountRepository
)
let synchronizer = try SDKSynchronizer(
status: .unprepared,
initializer: initializer,
transactionManager: OutboundTransactionManagerBuilder.build(initializer: initializer),
transactionRepository: repository,
utxoRepository: UTXORepositoryBuilder.build(initializer: initializer),
blockProcessor: processor
)
let synchronizer = try SDKSynchronizer(initializer: initializer)
try synchronizer.prepare()
return ([spendingKey], synchronizer)
@ -361,7 +327,7 @@ enum TestSynchronizerBuilder {
spendParamsURL: URL,
outputParamsURL: URL,
seedBytes: [UInt8],
walletBirthday: Checkpoint,
walletBirthday: BlockHeight,
network: ZcashNetwork,
loggerProxy: Logger? = nil
) throws -> (spendingKeys: [String]?, synchronizer: SDKSynchronizer) {