Use the set of addresses in the wallet when rescanning rather than generating more (#4211)

This commit is contained in:
Chris Stewart 2022-03-26 06:22:09 -05:00 committed by GitHub
parent c51db2c57a
commit 33171fd069
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 24 deletions

View file

@ -310,7 +310,7 @@ class RescanHandlingTest extends BitcoinSWalletTestCachedBitcoindNewest {
//slight delay to make sure other rescan is started //slight delay to make sure other rescan is started
val alreadyStartedF = val alreadyStartedF =
AsyncUtil.nonBlockingSleep(500.millis).flatMap { _ => AsyncUtil.nonBlockingSleep(100.millis).flatMap { _ =>
wallet.rescanNeutrinoWallet(startOpt = None, wallet.rescanNeutrinoWallet(startOpt = None,
endOpt = None, endOpt = None,
addressBatchSize = addressBatchSize =

View file

@ -147,13 +147,19 @@ private[wallet] trait RescanHandling extends WalletLogger {
addressBatchSize: Int): Future[Unit] = { addressBatchSize: Int): Future[Unit] = {
for { for {
scriptPubKeys <- generateScriptPubKeys(account, addressBatchSize) scriptPubKeys <- generateScriptPubKeys(account, addressBatchSize)
addressCount <- addressDAO.count()
_ <- matchBlocks(scriptPubKeys = scriptPubKeys, _ <- matchBlocks(scriptPubKeys = scriptPubKeys,
endOpt = endOpt, endOpt = endOpt,
startOpt = startOpt) startOpt = startOpt)
externalGap <- calcAddressGap(HDChainType.External, account) externalGap <- calcAddressGap(HDChainType.External, account)
changeGap <- calcAddressGap(HDChainType.Change, account) changeGap <- calcAddressGap(HDChainType.Change, account)
res <- res <- {
if ( logger.info(s"addressCount=$addressCount externalGap=$externalGap")
if (addressCount != 0) {
logger.info(
s"We have a small number of addresses preloaded into the wallet")
Future.unit
} else if (
externalGap >= walletConfig.addressGapLimit && changeGap >= walletConfig.addressGapLimit externalGap >= walletConfig.addressGapLimit && changeGap >= walletConfig.addressGapLimit
) { ) {
logger.info( logger.info(
@ -165,6 +171,7 @@ private[wallet] trait RescanHandling extends WalletLogger {
s"match within our address gap limit of ${walletConfig.addressGapLimit}") s"match within our address gap limit of ${walletConfig.addressGapLimit}")
doNeutrinoRescan(account, startOpt, endOpt, addressBatchSize) doNeutrinoRescan(account, startOpt, endOpt, addressBatchSize)
} }
}
} yield res } yield res
} }
@ -225,12 +232,13 @@ private[wallet] trait RescanHandling extends WalletLogger {
blocksF blocksF
} }
private def generateScriptPubKeys( /** Use to generate a list of addresses to search when restoring our wallet
* from our mneomnic seed
*/
private def generateAddressesForRescan(
account: HDAccount, account: HDAccount,
count: Int): Future[Vector[ScriptPubKey]] = { count: Int): Future[Vector[BitcoinAddress]] = {
for { val receiveAddressesF = 1
addresses <-
1
.to(count) .to(count)
.foldLeft(Future.successful(Vector.empty[BitcoinAddress])) { .foldLeft(Future.successful(Vector.empty[BitcoinAddress])) {
(prevFuture, _) => (prevFuture, _) =>
@ -239,8 +247,8 @@ private[wallet] trait RescanHandling extends WalletLogger {
address <- getNewAddress(account) address <- getNewAddress(account)
} yield prev :+ address } yield prev :+ address
} }
changeAddresses <-
1 val changeAddressesF = 1
.to(count) .to(count)
.foldLeft(Future.successful(Vector.empty[BitcoinAddress])) { .foldLeft(Future.successful(Vector.empty[BitcoinAddress])) {
(prevFuture, _) => (prevFuture, _) =>
@ -249,10 +257,33 @@ private[wallet] trait RescanHandling extends WalletLogger {
address <- getNewChangeAddress(account) address <- getNewChangeAddress(account)
} yield prev :+ address } yield prev :+ address
} }
for {
receiveAddresses <- receiveAddressesF
changeAddresses <- changeAddressesF
} yield receiveAddresses ++ changeAddresses
}
private def generateScriptPubKeys(
account: HDAccount,
count: Int): Future[Vector[ScriptPubKey]] = {
val addressCountF = addressDAO.count()
for {
addressCount <- addressCountF
addresses <- {
if (addressCount == 0) {
generateAddressesForRescan(account, count)
} else {
//we don't want to continously generate addresses
//if our wallet already has them, so just use what is in the
//database already
addressDAO.findAllAddresses().map(_.map(_.address))
}
}
spksDb <- scriptPubKeyDAO.findAll() spksDb <- scriptPubKeyDAO.findAll()
} yield { } yield {
val addrSpks = val addrSpks =
addresses.map(_.scriptPubKey) ++ changeAddresses.map(_.scriptPubKey) addresses.map(_.scriptPubKey)
val otherSpks = spksDb.map(_.scriptPubKey) val otherSpks = spksDb.map(_.scriptPubKey)
(addrSpks ++ otherSpks).distinct (addrSpks ++ otherSpks).distinct