Make it so bitcoind backend exceptions don't get swallowed (#3697)

* Make it so bitcoind backend exceptions don't get swallowed when doing IBD against bitcoind

* Move zmq polling into syncWalletWithBitcoindAndStartPolling() method
This commit is contained in:
Chris Stewart 2021-09-28 17:55:47 -05:00 committed by GitHub
parent bf16bab881
commit 4e56fb7901
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 17 deletions

View file

@ -26,6 +26,7 @@ import org.bitcoins.feeprovider._
import org.bitcoins.node._
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.models.Peer
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.rpc.config.{BitcoindRpcAppConfig, ZmqConfig}
import org.bitcoins.server.routes.{BitcoinSServerRunner, CommonRoutes, Server}
import org.bitcoins.server.util.BitcoinSAppScalaDaemon
@ -210,23 +211,11 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
if err.getMessage.contains("If we have spent a spendinginfodb") =>
handleMissingSpendingInfoDb(err, wallet)
}
_ = BitcoindRpcBackendUtil
.syncWalletToBitcoind(bitcoind, wallet)
.flatMap(_ => wallet.updateUtxoPendingStates())
.flatMap { _ =>
if (bitcoindRpcConf.zmqConfig == ZmqConfig.empty) {
BitcoindRpcBackendUtil.startBitcoindBlockPolling(wallet, bitcoind)
} else Future.unit
}
// Create callbacks for processing new blocks
_ =
if (bitcoindRpcConf.zmqConfig != ZmqConfig.empty) {
BitcoindRpcBackendUtil.startZMQWalletCallbacks(
wallet,
bitcoindRpcConf.zmqConfig)
}
//intentionally doesn't map on this otherwise we
//wait until we are done syncing the entire wallet
//which could take 1 hour
_ = syncWalletWithBitcoindAndStartPolling(bitcoind, wallet)
dlcNode = dlcNodeConf.createDLCNode(wallet)
_ <- dlcNode.start()
@ -430,6 +419,40 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
} yield clearedWallet
walletF.map(_ => ())
}
/** Syncs the bitcoin-s wallet against bitcoind and then
* starts rpc polling if zmq isn't enabled, otherwise it starts zmq polling.
*
* The key thing this helper method does is it logs errors based on the
* future returned by this method. This is needed because we don't want
* to block the rest of the application from starting if we have to
* do a ton of syncing. However, we don't want to swallow
* exceptions thrown by this method.
*/
private def syncWalletWithBitcoindAndStartPolling(
bitcoind: BitcoindRpcClient,
wallet: Wallet): Future[Unit] = {
val f = BitcoindRpcBackendUtil
.syncWalletToBitcoind(bitcoind, wallet)
.flatMap(_ => wallet.updateUtxoPendingStates())
.flatMap { _ =>
if (bitcoindRpcConf.zmqConfig == ZmqConfig.empty) {
BitcoindRpcBackendUtil
.startBitcoindBlockPolling(wallet, bitcoind)
.map(_ => ())
} else {
Future {
BitcoindRpcBackendUtil.startZMQWalletCallbacks(
wallet,
bitcoindRpcConf.zmqConfig)
}
}
}
f.failed.foreach(err =>
logger.error(s"Error syncing bitcoin-s wallet with bitcoind", err))
f
}
}
object BitcoinSServerMain extends BitcoinSAppScalaDaemon {

View file

@ -5,6 +5,7 @@ import akka.actor.{ActorSystem, Cancellable}
import akka.stream.scaladsl.{Keep, Sink, Source}
import grizzled.slf4j.Logging
import org.bitcoins.core.api.node.NodeApi
import org.bitcoins.core.api.wallet.WalletApi
import org.bitcoins.core.gcs.FilterType
import org.bitcoins.core.protocol.blockchain.Block
import org.bitcoins.core.protocol.transaction.Transaction
@ -259,7 +260,7 @@ object BitcoindRpcBackendUtil extends Logging {
* as the wallet will need to process the new blocks
*/
def startBitcoindBlockPolling(
wallet: Wallet,
wallet: WalletApi,
bitcoind: BitcoindRpcClient,
interval: FiniteDuration = 10.seconds)(implicit
system: ActorSystem,