Fix: change rewind behavior to correct for witnesses

Addresses SDK side of https://github.com/zcash/librustzcash/issues/373
This commit is contained in:
Kevin Gorham 2021-04-14 18:44:17 -04:00
parent e07317c7d5
commit 5dd0df7619
No known key found for this signature in database
GPG Key ID: CCA55602DF49FC38
5 changed files with 37 additions and 21 deletions

View File

@ -303,8 +303,11 @@ class SdkSynchronizer internal constructor(
)
}
override suspend fun rewindToHeight(height: Int, alsoClearBlockCache: Boolean) {
processor.rewindToHeight(height, alsoClearBlockCache)
override suspend fun getNearestRewindHeight(height: Int): Int =
processor.getNearestRewindHeight(height)
override suspend fun rewindToNearestHeight(height: Int, alsoClearBlockCache: Boolean) {
processor.rewindToNearestHeight(height, alsoClearBlockCache)
}
//
@ -385,7 +388,7 @@ class SdkSynchronizer internal constructor(
twig("Synchronizer onReady complete. Processor start has exited!")
}
private fun onCriticalError(unused: CoroutineContext, error: Throwable) {
private fun onCriticalError(unused: CoroutineContext?, error: Throwable) {
twig("********")
twig("******** ERROR: $error")
if (error.cause != null) twig("******** caused by ${error.cause}")

View File

@ -281,7 +281,15 @@ interface Synchronizer {
*/
suspend fun getTransparentBalance(tAddr: String): WalletBalance
suspend fun rewindToHeight(height: Int, alsoClearBlockCache: Boolean = false)
suspend fun getNearestRewindHeight(height: Int): Int
/**
* Returns the safest height to which we can rewind, given a desire to rewind to the height
* provided. Due to how witness incrementing works, a wallet cannot simply rewind to any
* arbitrary height. This handles all that complexity yet remains flexible in the future as
* improvements are made.
*/
suspend fun rewindToNearestHeight(height: Int, alsoClearBlockCache: Boolean = false)
//
// Error Handling

View File

@ -588,7 +588,15 @@ class CompactBlockProcessor(
determineLowerBound(errorHeight).let { lowerBound ->
twig("handling chain error at $errorHeight by rewinding to block $lowerBound")
onChainErrorListener?.invoke(errorHeight, lowerBound)
rewindToHeight(lowerBound, true)
rewindToNearestHeight(lowerBound, true)
}
}
suspend fun getNearestRewindHeight(height: Int): Int {
return if (height < lowerBoundHeight) {
lowerBoundHeight
} else {
rustBackend.getNearestRewindHeight(height)
}
}
@ -596,12 +604,11 @@ class CompactBlockProcessor(
* @param alsoClearBlockCache when true, also clear the block cache which forces a redownload of
* blocks. Otherwise, the cached blocks will be used in the rescan, which in most cases, is fine.
*/
suspend fun rewindToHeight(height: Int, alsoClearBlockCache: Boolean = false) = withContext(IO) {
suspend fun rewindToNearestHeight(height: Int, alsoClearBlockCache: Boolean = false) = withContext(IO) {
processingMutex.withLockLogged("rewindToHeight") {
val lastScannedHeight = currentInfo.lastScannedHeight
val targetHeight = determineTargetHeight(height)
val targetHeight = getNearestRewindHeight(height)
twig("Rewinding from $lastScannedHeight to requested height: $height using target height: $targetHeight")
// TODO: think about how we might pause all processing during a rewind
if (targetHeight < lastScannedHeight) {
rustBackend.rewindToHeight(targetHeight)
} else {
@ -681,19 +688,6 @@ class CompactBlockProcessor(
}
}
/**
* Given a height to rewind to, check whether it goes beyond our checkpoint. Of so, we cannot
* use that height so go to our checkpoint instead.
*/
private fun determineTargetHeight(rewindHeight: Int): Int {
return if (rewindHeight == network.saplingActivationHeight) {
rewindHeight
} else {
val checkpointHeight = repository.firstScannedHeight()
rewindHeight.coerceAtLeast(checkpointHeight)
}
}
/**
* Poll on time boundaries. Per Issue #95, we want to avoid exposing computation time to a
* network observer. Instead, we poll at regular time intervals that are large enough for all

View File

@ -97,6 +97,8 @@ class RustBackend private constructor() : RustBackendWelding {
override fun validateCombinedChain() = validateCombinedChain(pathCacheDb, pathDataDb, networkId = network.id,)
override fun getNearestRewindHeight(height: Int): Int = getNearestRewindHeight(pathDataDb, height, networkId = network.id)
/**
* Deletes data for all blocks above the given height. Boils down to:
*
@ -315,6 +317,13 @@ class RustBackend private constructor() : RustBackendWelding {
networkId: Int,
): Int
@JvmStatic
private external fun getNearestRewindHeight(
dbDataPath: String,
height: Int,
networkId: Int,
): Int
@JvmStatic
private external fun rewindToHeight(
dbDataPath: String,

View File

@ -59,6 +59,8 @@ interface RustBackendWelding {
// fun parseTransactionDataList(tdl: LocalRpcTypes.TransactionDataList): LocalRpcTypes.TransparentTransactionList
fun getNearestRewindHeight(height: Int): Int
fun rewindToHeight(height: Int): Boolean
fun scanBlocks(limit: Int = -1): Boolean