diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala b/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala index 9ba71086f..4de76e6e3 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala @@ -30,7 +30,7 @@ object DBCompatChecker extends Logging { def checkDBCompatibility(nodeParams: NodeParams): Unit = Try(nodeParams.db.channels.listLocalChannels()) match { case Success(_) => {} - case Failure(_) => throw IncompatibleDBException + case Failure(exception) => throw IncompatibleDBException(exception) } /** diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala index 240ea599c..2a248d27e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala @@ -303,6 +303,6 @@ case object BitcoinWalletDisabledException extends RuntimeException("bitcoind mu case object EmptyAPIPasswordException extends RuntimeException("must set a password for the json-rpc api") -case object IncompatibleDBException extends RuntimeException("database is not compatible with this version of eclair") +case class IncompatibleDBException(cause: Throwable) extends RuntimeException("database is not compatible with this version of eclair", cause) case object IncompatibleNetworkDBException extends RuntimeException("network database is not compatible with this version of eclair") diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/jdbc/JdbcUtils.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/jdbc/JdbcUtils.scala index 711f0b688..2fc9f4f9e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/jdbc/JdbcUtils.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/jdbc/JdbcUtils.scala @@ -65,10 +65,17 @@ trait JdbcUtils { * * TODO: we should use an scala.Iterator instead */ - def codecSequence[T](rs: ResultSet, codec: Codec[T]): Seq[T] = { + def codecSequence[T](rs: ResultSet, codec: Codec[T], onError: String => Unit = { _ => Unit }): Seq[T] = { var q: Queue[T] = Queue() while (rs.next()) { - q = q :+ codec.decode(BitVector(rs.getBytes("data"))).require.value + val data = BitVector(rs.getBytes("data")) + try { + q = q :+ codec.decode(data).require.value + } catch { + case t: Throwable => + onError(s"unreadable data=${data.toHex}") + throw t + } } q } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala index 3244cbbe8..535cba1e5 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala @@ -98,7 +98,7 @@ class SqliteChannelsDb(sqlite: Connection) extends ChannelsDb with Logging { override def listLocalChannels(): Seq[HasCommitments] = withMetrics("channels/list-local-channels") { using(sqlite.createStatement) { statement => val rs = statement.executeQuery("SELECT data FROM local_channels WHERE is_closed=0") - codecSequence(rs, stateDataCodec) + codecSequence(rs, stateDataCodec, onError = { message => logger.error(message) }) } }