[#610] Fix block download regression
This includes a few different fixes that prevented the demo app and other SDK consumers from working. First, initialization of the demo app was fixed to use the sapling activation height rather than the current latest checkpoint. Second, CompactBlockProcessor wasn’t downloading blocks. Third, a few potential thread safety issues were resolved by making fields that are accessed by multiple threads volatile.
This commit is contained in:
parent
b53b09d40d
commit
8e3c4a636f
|
@ -48,12 +48,18 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
|
|||
// have the seed stored
|
||||
val seed = Mnemonics.MnemonicCode(seedPhrase).toSeed()
|
||||
|
||||
initializer = runBlocking {
|
||||
Initializer.new(requireApplicationContext()) {
|
||||
runBlocking { it.newWallet(seed, network = ZcashNetwork.fromResources(requireApplicationContext())) }
|
||||
it.setNetwork(ZcashNetwork.fromResources(requireApplicationContext()))
|
||||
initializer = Initializer.newBlocking(
|
||||
requireApplicationContext(),
|
||||
Initializer.Config {
|
||||
runBlocking {
|
||||
it.importWallet(
|
||||
seed,
|
||||
birthday = null,
|
||||
network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
address = runBlocking {
|
||||
DerivationTool.deriveShieldedAddress(
|
||||
seed,
|
||||
|
|
|
@ -72,7 +72,8 @@ class DataDbScannerUtil {
|
|||
BlockHeight.new(
|
||||
ZcashNetwork.Mainnet,
|
||||
birthdayHeight
|
||||
)
|
||||
),
|
||||
false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ class Initializer private constructor(
|
|||
* transactions. Again, this value is only considered when [height] is null.
|
||||
*
|
||||
*/
|
||||
fun setBirthdayHeight(height: BlockHeight?, defaultToOldestHeight: Boolean = false): Config =
|
||||
fun setBirthdayHeight(height: BlockHeight?, defaultToOldestHeight: Boolean): Config =
|
||||
apply {
|
||||
this.birthdayHeight = height
|
||||
this.defaultToOldestHeight = defaultToOldestHeight
|
||||
|
@ -329,12 +329,23 @@ class Initializer private constructor(
|
|||
config: Config
|
||||
): Initializer {
|
||||
config.validate()
|
||||
val heightToUse = config.birthdayHeight
|
||||
?: (if (config.defaultToOldestHeight == true) config.network.saplingActivationHeight else null)
|
||||
val loadedBirthday =
|
||||
CheckpointTool.loadNearest(context, config.network, heightToUse)
|
||||
|
||||
val rustBackend = initRustBackend(context, config.network, config.alias, loadedBirthday.height)
|
||||
val loadedCheckpoint = run {
|
||||
val height = config.birthdayHeight
|
||||
?: if (config.defaultToOldestHeight == true) {
|
||||
config.network.saplingActivationHeight
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
CheckpointTool.loadNearest(
|
||||
context,
|
||||
config.network,
|
||||
height
|
||||
)
|
||||
}
|
||||
|
||||
val rustBackend = initRustBackend(context, config.network, config.alias, loadedCheckpoint.height)
|
||||
|
||||
return Initializer(
|
||||
context.applicationContext,
|
||||
|
@ -345,7 +356,7 @@ class Initializer private constructor(
|
|||
config.port,
|
||||
config.viewingKeys,
|
||||
config.overwriteVks,
|
||||
loadedBirthday
|
||||
loadedCheckpoint
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,9 @@ class CompactBlockProcessor internal constructor(
|
|||
* sequentially, due to the way sqlite works so it is okay for this not to be threadsafe or
|
||||
* coroutine safe because processing cannot be concurrent.
|
||||
*/
|
||||
// This accessed by the Dispatchers.IO thread, which means multiple threads are reading/writing
|
||||
// concurrently.
|
||||
@Volatile
|
||||
internal var currentInfo = ProcessorInfo(null, null, null, null, null)
|
||||
|
||||
/**
|
||||
|
@ -325,13 +328,14 @@ class CompactBlockProcessor internal constructor(
|
|||
} else {
|
||||
null
|
||||
},
|
||||
lastDownloadRange = if (initialInfo.lastDownloadedHeight != null && initialInfo.lastScannedHeight != null && initialInfo.networkBlockHeight != null) {
|
||||
lastDownloadRange = if (initialInfo.networkBlockHeight != null) {
|
||||
BlockHeight.new(
|
||||
network,
|
||||
max(
|
||||
initialInfo.lastDownloadedHeight.value,
|
||||
initialInfo.lastScannedHeight.value
|
||||
) + 1
|
||||
buildList {
|
||||
add(network.saplingActivationHeight.value)
|
||||
initialInfo.lastDownloadedHeight?.let { add(it.value + 1) }
|
||||
initialInfo.lastScannedHeight?.let { add(it.value + 1) }
|
||||
}.max()
|
||||
)..initialInfo.networkBlockHeight
|
||||
} else {
|
||||
null
|
||||
|
@ -633,7 +637,8 @@ class CompactBlockProcessor internal constructor(
|
|||
metrics.beginBatch()
|
||||
result = rustBackend.scanBlocks(SCAN_BATCH_SIZE)
|
||||
metrics.endBatch()
|
||||
val lastScannedHeight = BlockHeight.new(network, range.start.value + metrics.cumulativeItems - 1)
|
||||
val lastScannedHeight =
|
||||
BlockHeight.new(network, range.start.value + metrics.cumulativeItems - 1)
|
||||
val percentValue =
|
||||
(lastScannedHeight.value - range.start.value) / (range.endInclusive.value - range.start.value + 1).toFloat() * 100.0f
|
||||
val percent = "%.0f".format(percentValue.coerceAtMost(100f).coerceAtLeast(0f))
|
||||
|
@ -674,7 +679,7 @@ class CompactBlockProcessor internal constructor(
|
|||
lastDownloadedHeight: BlockHeight? = currentInfo.lastDownloadedHeight,
|
||||
lastScanRange: ClosedRange<BlockHeight>? = currentInfo.lastScanRange,
|
||||
lastDownloadRange: ClosedRange<BlockHeight>? = currentInfo.lastDownloadRange
|
||||
): Unit = withContext(IO) {
|
||||
) {
|
||||
currentInfo = currentInfo.copy(
|
||||
networkBlockHeight = networkBlockHeight,
|
||||
lastScannedHeight = lastScannedHeight,
|
||||
|
@ -682,8 +687,11 @@ class CompactBlockProcessor internal constructor(
|
|||
lastScanRange = lastScanRange,
|
||||
lastDownloadRange = lastDownloadRange
|
||||
)
|
||||
_networkHeight.value = networkBlockHeight
|
||||
_processorInfo.send(currentInfo)
|
||||
|
||||
withContext(IO) {
|
||||
_networkHeight.value = networkBlockHeight
|
||||
_processorInfo.send(currentInfo)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleChainError(errorHeight: BlockHeight) {
|
||||
|
|
|
@ -75,6 +75,7 @@ interface Twig {
|
|||
* @see [Twig.clip]
|
||||
*/
|
||||
object Bush {
|
||||
@Volatile
|
||||
var trunk: Twig = SilentTwig()
|
||||
val leaves: MutableSet<Leaf> = CopyOnWriteArraySet<Leaf>()
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ internal object CheckpointTool {
|
|||
context: Context,
|
||||
network: ZcashNetwork,
|
||||
directory: String,
|
||||
birthday: BlockHeight? = null
|
||||
birthday: BlockHeight?
|
||||
): List<String> {
|
||||
val unfilteredTreeFiles = listCheckpointDirectoryContents(context, directory)
|
||||
if (unfilteredTreeFiles.isNullOrEmpty()) {
|
||||
|
|
Loading…
Reference in New Issue