1
0
mirror of https://github.com/ACINQ/eclair.git synced 2025-01-19 05:33:59 +01:00

Update a few dependencies (#2166)

This updates versions of a few major dependencies: scala, akka, postgres, etc.
This commit is contained in:
Pierre-Marie Padiou 2022-02-08 11:37:24 +01:00 committed by GitHub
parent daddee1912
commit ca71a3c152
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 106 additions and 113 deletions

View File

@ -160,7 +160,7 @@
</dependency>
<!-- HTTP CLIENT -->
<dependency>
<groupId>com.softwaremill.sttp</groupId>
<groupId>com.softwaremill.sttp.client3</groupId>
<artifactId>okhttp-backend_${scala.version.short}</artifactId>
<version>${sttp.version}</version>
</dependency>
@ -168,10 +168,10 @@
<dependency>
<groupId>org.json4s</groupId>
<artifactId>json4s-jackson_${scala.version.short}</artifactId>
<version>3.6.11</version>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>com.softwaremill.sttp</groupId>
<groupId>com.softwaremill.sttp.client3</groupId>
<artifactId>json4s_${scala.version.short}</artifactId>
<version>${sttp.version}</version>
</dependency>
@ -202,13 +202,13 @@
<dependency>
<groupId>org.scodec</groupId>
<artifactId>scodec-core_${scala.version.short}</artifactId>
<version>1.11.8</version>
<version>1.11.9</version>
</dependency>
<dependency>
<!-- needed to fix "No implicit Ordering defined for scodec.bits.ByteVector" -->
<groupId>org.scodec</groupId>
<artifactId>scodec-bits_${scala.version.short}</artifactId>
<version>1.1.25</version>
<version>1.1.30</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
@ -234,8 +234,8 @@
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<version>42.2.23</version>
<artifactId>postgresql</artifactId>
<version>42.3.2</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>

View File

@ -22,7 +22,6 @@ import akka.actor.typed.scaladsl.adapter.{ClassicActorRefOps, ClassicActorSystem
import akka.actor.{ActorRef, ActorSystem, Props, SupervisorStrategy, typed}
import akka.pattern.after
import akka.util.Timeout
import com.softwaremill.sttp.okhttp.OkHttpFutureBackend
import fr.acinq.bitcoin.{Block, ByteVector32, Satoshi}
import fr.acinq.eclair.Setup.Seeds
import fr.acinq.eclair.balance.{BalanceActor, ChannelsListener}
@ -49,6 +48,7 @@ import fr.acinq.eclair.wire.protocol.NodeAddress
import grizzled.slf4j.Logging
import org.json4s.JsonAST.JArray
import scodec.bits.ByteVector
import sttp.client3.okhttp.OkHttpFutureBackend
import java.io.File
import java.net.InetSocketAddress

View File

@ -16,14 +16,15 @@
package fr.acinq.eclair.blockchain.bitcoind.rpc
import com.softwaremill.sttp._
import com.softwaremill.sttp.json4s._
import fr.acinq.bitcoin.ByteVector32
import fr.acinq.eclair.KamonExt
import fr.acinq.eclair.blockchain.Monitoring.{Metrics, Tags}
import org.json4s.JsonAST.{JString, JValue}
import org.json4s.jackson.Serialization
import org.json4s.{CustomSerializer, DefaultFormats}
import sttp.client3._
import sttp.client3.json4s._
import sttp.model.StatusCode
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path}
@ -31,7 +32,7 @@ import java.util.concurrent.atomic.AtomicReference
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Failure, Success, Try}
class BasicBitcoinJsonRPCClient(rpcAuthMethod: BitcoinJsonRPCAuthMethod, host: String = "127.0.0.1", port: Int = 8332, ssl: Boolean = false, wallet: Option[String] = None)(implicit http: SttpBackend[Future, Nothing]) extends BitcoinJsonRPCClient {
class BasicBitcoinJsonRPCClient(rpcAuthMethod: BitcoinJsonRPCAuthMethod, host: String = "127.0.0.1", port: Int = 8332, ssl: Boolean = false, wallet: Option[String] = None)(implicit sb: SttpBackend[Future, _]) extends BitcoinJsonRPCClient {
// necessary to properly serialize ByteVector32 into String readable by bitcoind
object ByteVector32Serializer extends CustomSerializer[ByteVector32](_ => ( {
@ -57,18 +58,18 @@ class BasicBitcoinJsonRPCClient(rpcAuthMethod: BitcoinJsonRPCAuthMethod, host: S
case o => o
}
private def send(requests: Seq[JsonRPCRequest], user: String, password: String)(implicit ec: ExecutionContext): Future[Response[Seq[JsonRPCResponse]]] = {
private def send(requests: Seq[JsonRPCRequest], user: String, password: String)(implicit ec: ExecutionContext): Future[Response[Either[ResponseException[String, Exception], Seq[JsonRPCResponse]]]] = {
requests.groupBy(_.method).foreach {
case (method, calls) => Metrics.RpcBasicInvokeCount.withTag(Tags.Method, method).increment(calls.size)
}
KamonExt.timeFuture(Metrics.RpcBasicInvokeDuration.withoutTags()) {
for {
response <- sttp
response <- basicRequest
.post(serviceUri)
.body(requests)
.auth.basic(user, password)
.response(asJson[Seq[JsonRPCResponse]])
.send()
.send(sb)
} yield response
}
}
@ -78,18 +79,18 @@ class BasicBitcoinJsonRPCClient(rpcAuthMethod: BitcoinJsonRPCAuthMethod, host: S
send(requests, user, password).flatMap {
response =>
response.code match {
case StatusCodes.Unauthorized => rpcAuthMethod match {
case StatusCode.Unauthorized => rpcAuthMethod match {
case _: BitcoinJsonRPCAuthMethod.UserPassword => Future.failed(new IllegalArgumentException("could not authenticate to bitcoind RPC server: check your configured user/password"))
case BitcoinJsonRPCAuthMethod.SafeCookie(path, _) =>
// bitcoind may have restarted and generated a new cookie file, let's read it again and retry
BitcoinJsonRPCAuthMethod.readCookie(path) match {
case Success(cookie) =>
credentials.set(cookie.credentials)
send(requests, cookie.credentials.user, cookie.credentials.password).map(_.unsafeBody)
send(requests, cookie.credentials.user, cookie.credentials.password).map(_.body.fold(exc => throw exc, jvalue => jvalue))
case Failure(e) => Future.failed(e)
}
}
case _ => Future.successful(response.unsafeBody)
case _ => Future.successful(response.body.fold(exc => throw exc, jvalue => jvalue))
}
}
}

View File

@ -16,10 +16,9 @@
package fr.acinq.eclair.blockchain.bitcoind.rpc
import java.io.IOException
import org.json4s.JsonAST.JValue
import java.io.IOException
import scala.concurrent.{ExecutionContext, Future}
trait BitcoinJsonRPCClient {

View File

@ -19,13 +19,12 @@ package fr.acinq.eclair.blockchain.watchdogs
import akka.actor.typed.Behavior
import akka.actor.typed.eventstream.EventStream
import akka.actor.typed.scaladsl.Behaviors
import com.softwaremill.sttp.SttpBackend
import fr.acinq.bitcoin.BlockHeader
import fr.acinq.eclair.NotificationsLogger.NotifyNodeOperator
import fr.acinq.eclair.blockchain.CurrentBlockHeight
import fr.acinq.eclair.blockchain.watchdogs.Monitoring.{Metrics, Tags}
import fr.acinq.eclair.tor.Socks5ProxyParams
import fr.acinq.eclair.{BlockHeight, NodeParams, NotificationsLogger}
import sttp.client3.SttpBackend
import java.util.UUID
import scala.concurrent.Future
@ -43,11 +42,6 @@ object BlockchainWatchdog {
case class BlockHeaderAt(blockHeight: BlockHeight, blockHeader: BlockHeader)
case object NoBlockReceivedTimer
trait SupportsTor {
/** Tor proxy connection parameters */
def socksProxy_opt: Option[Socks5ProxyParams]
}
sealed trait BlockchainWatchdogEvent
/**
* We are missing too many blocks compared to one of our blockchain watchdogs.
@ -72,12 +66,13 @@ object BlockchainWatchdog {
def apply(nodeParams: NodeParams, maxRandomDelay: FiniteDuration, blockTimeout: FiniteDuration = 15 minutes): Behavior[Command] = {
Behaviors.setup { context =>
val socksProxy_opt = nodeParams.socksProxy_opt.flatMap(params => if (params.useForWatchdogs) Some(params) else None)
implicit val sttpBackend: SttpBackend[Future, Nothing] = ExplorerApi.createSttpBackend(socksProxy_opt)
implicit val sb: SttpBackend[Future, _] = ExplorerApi.createSttpBackend(socksProxy_opt)
val explorers = Seq(
ExplorerApi.BlockstreamExplorer(socksProxy_opt),
ExplorerApi.BlockcypherExplorer(socksProxy_opt),
ExplorerApi.MempoolSpaceExplorer(socksProxy_opt)
ExplorerApi.BlockcypherExplorer(),
// NB: if there is a proxy, we assume it is a tor proxy
ExplorerApi.BlockstreamExplorer(useTorEndpoints = socksProxy_opt.isDefined),
ExplorerApi.MempoolSpaceExplorer(useTorEndpoints = socksProxy_opt.isDefined)
).filter { e =>
val enabled = nodeParams.blockchainWatchdogSources.contains(e.name)
if (!enabled) {

View File

@ -20,17 +20,18 @@ import akka.actor.ActorSystem
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import akka.actor.typed.{ActorRef, Behavior}
import akka.pattern.after
import com.softwaremill.sttp.json4s.asJson
import com.softwaremill.sttp.okhttp.OkHttpFutureBackend
import com.softwaremill.sttp.{StatusCodes, SttpBackend, SttpBackendOptions, Uri, UriContext, sttp}
import fr.acinq.bitcoin.{Block, BlockHeader, ByteVector32}
import fr.acinq.eclair.blockchain.watchdogs.BlockchainWatchdog.{BlockHeaderAt, LatestHeaders, SupportsTor}
import fr.acinq.eclair.blockchain.watchdogs.BlockchainWatchdog.{BlockHeaderAt, LatestHeaders}
import fr.acinq.eclair.blockchain.watchdogs.Monitoring.{Metrics, Tags}
import fr.acinq.eclair.tor.Socks5ProxyParams
import fr.acinq.eclair.{BlockHeight, randomBytes}
import org.json4s.JsonAST.{JArray, JInt, JObject, JString}
import org.json4s.jackson.Serialization
import org.json4s.{DefaultFormats, Serialization}
import sttp.client3._
import sttp.client3.json4s._
import sttp.client3.okhttp.OkHttpFutureBackend
import sttp.model.{StatusCode, Uri}
import java.time.OffsetDateTime
import scala.concurrent.duration.DurationInt
@ -92,9 +93,9 @@ object ExplorerApi {
}
}
def createSttpBackend(socksProxy_opt: Option[Socks5ProxyParams]): SttpBackend[Future, Nothing] = {
def createSttpBackend(socksProxy_opt: Option[Socks5ProxyParams]): SttpBackend[Future, _] = {
val options = SttpBackendOptions(connectionTimeout = 30.seconds, proxy = None)
val sttpBackendOptions = socksProxy_opt match {
val sttpBackendOptions: SttpBackendOptions = socksProxy_opt match {
case Some(proxy) =>
val host = proxy.address.getHostString
val port = proxy.address.getPort
@ -111,7 +112,7 @@ object ExplorerApi {
* Query https://blockcypher.com/ to fetch block headers.
* See https://www.blockcypher.com/dev/bitcoin/#introduction.
*/
case class BlockcypherExplorer(socksProxy_opt: Option[Socks5ProxyParams])(implicit val sb: SttpBackend[Future, Nothing]) extends Explorer with SupportsTor {
case class BlockcypherExplorer()(implicit val sb: SttpBackend[Future, _]) extends Explorer {
override val name = "blockcypher.com"
override val baseUris = Map(
Block.TestnetGenesisBlock.hash -> uri"https://api.blockcypher.com/v1/btc/test3",
@ -130,60 +131,58 @@ object ExplorerApi {
} yield headers
}
private def getTip(baseUri: Uri)(implicit ec: ExecutionContext, sb: SttpBackend[Future, Nothing]): Future[BlockHeight] = {
private def getTip(baseUri: Uri)(implicit ec: ExecutionContext): Future[BlockHeight] = {
for {
tip <- sttp.readTimeout(30 seconds).get(baseUri)
tip <- basicRequest.readTimeout(30 seconds).get(baseUri)
.headers(Socks5ProxyParams.FakeFirefoxHeaders)
.response(asJson[JObject])
.send()
.map(r => {
val JInt(latestHeight) = r.unsafeBody \ "height"
.send(sb)
.map(_.body.fold(exc => throw exc, jvalue => jvalue))
.map(json => {
val JInt(latestHeight) = json \ "height"
BlockHeight(latestHeight.toLong)
})
} yield tip
}
private def getHeader(baseUri: Uri, blockCount: Long)(implicit ec: ExecutionContext, sb: SttpBackend[Future, Nothing]): Future[Seq[BlockHeaderAt]] = for {
header <- sttp.readTimeout(30 seconds).get(baseUri.path(baseUri.path :+ "blocks" :+ blockCount.toString))
private def getHeader(baseUri: Uri, blockCount: Long)(implicit ec: ExecutionContext): Future[Seq[BlockHeaderAt]] = for {
header <- basicRequest.readTimeout(30 seconds).get(baseUri.addPath("blocks", blockCount.toString))
.headers(Socks5ProxyParams.FakeFirefoxHeaders)
.response(asJson[JObject])
.send()
.map(r => r.code match {
.send(sb)
.map(r => r.body match {
// HTTP 404 is a "normal" error: we're trying to lookup future blocks that haven't been mined.
case StatusCodes.NotFound => Seq.empty
case _ => r.unsafeBody \ "error" match {
case JString(error) if error == s"Block $blockCount not found." => Seq.empty
case _ => Seq(r.unsafeBody)
}
case Left(res: HttpError[_]) if res.statusCode == StatusCode.NotFound => Seq.empty
case Left(otherError) => throw otherError
case Right(json) if json \ "error" == JString(s"Block $blockCount not found.") => Seq.empty
case Right(block) =>
val JInt(height) = block \ "height"
val JInt(version) = block \ "ver"
val JString(time) = block \ "time"
val JInt(bits) = block \ "bits"
val JInt(nonce) = block \ "nonce"
val previousBlockHash = (block \ "prev_block").extractOpt[String].map(ByteVector32.fromValidHex(_).reverse).getOrElse(ByteVector32.Zeroes)
val merkleRoot = (block \ "mrkl_root").extractOpt[String].map(ByteVector32.fromValidHex(_).reverse).getOrElse(ByteVector32.Zeroes)
val header = BlockHeader(version.toLong, previousBlockHash, merkleRoot, OffsetDateTime.parse(time).toEpochSecond, bits.toLong, nonce.toLong)
Seq(BlockHeaderAt(BlockHeight(height.toLong), header))
})
.map(blocks => blocks.map(block => {
val JInt(height) = block \ "height"
val JInt(version) = block \ "ver"
val JString(time) = block \ "time"
val JInt(bits) = block \ "bits"
val JInt(nonce) = block \ "nonce"
val previousBlockHash = (block \ "prev_block").extractOpt[String].map(ByteVector32.fromValidHex(_).reverse).getOrElse(ByteVector32.Zeroes)
val merkleRoot = (block \ "mrkl_root").extractOpt[String].map(ByteVector32.fromValidHex(_).reverse).getOrElse(ByteVector32.Zeroes)
val header = BlockHeader(version.toLong, previousBlockHash, merkleRoot, OffsetDateTime.parse(time).toEpochSecond, bits.toLong, nonce.toLong)
BlockHeaderAt(BlockHeight(height.toLong), header)
}))
} yield header
}
/** Explorer API based on Esplora: see https://github.com/Blockstream/esplora/blob/master/API.md. */
sealed trait Esplora extends Explorer with SupportsTor {
implicit val sb: SttpBackend[Future, Nothing]
sealed trait Esplora extends Explorer {
implicit val sb: SttpBackend[Future, _]
override def getLatestHeaders(baseUri: Uri, currentBlockHeight: BlockHeight)(implicit context: ActorContext[Command]): Future[LatestHeaders] = {
implicit val ec: ExecutionContext = context.system.executionContext
for {
headers <- sttp.readTimeout(10 seconds).get(baseUri.path(baseUri.path :+ "blocks"))
headers <- basicRequest.readTimeout(10 seconds).get(baseUri.addPath("blocks"))
.response(asJson[JArray])
.send()
.send(sb)
.map(r => r.code match {
// HTTP 404 is a "normal" error: we're trying to lookup future blocks that haven't been mined.
case StatusCodes.NotFound => Seq.empty
case _ => r.unsafeBody.arr
case StatusCode.NotFound => Seq.empty
case _ => r.body.fold(exc => throw exc, jvalue => jvalue).arr
})
.map(blocks => blocks.map(block => {
val JInt(height) = block \ "height"
@ -202,36 +201,34 @@ object ExplorerApi {
}
/** Query https://blockstream.info/ to fetch block headers. */
case class BlockstreamExplorer(socksProxy_opt: Option[Socks5ProxyParams])(implicit val sb: SttpBackend[Future, Nothing]) extends Esplora {
case class BlockstreamExplorer(useTorEndpoints: Boolean)(implicit val sb: SttpBackend[Future, _]) extends Esplora {
override val name = "blockstream.info"
override val baseUris = socksProxy_opt match {
case Some(_) =>
Map(
Block.TestnetGenesisBlock.hash -> uri"http://explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"http://explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion/api"
)
case None =>
Map(
Block.TestnetGenesisBlock.hash -> uri"https://blockstream.info/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"https://blockstream.info/api"
)
override val baseUris = if (useTorEndpoints) {
Map(
Block.TestnetGenesisBlock.hash -> uri"http://explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"http://explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion/api"
)
} else {
Map(
Block.TestnetGenesisBlock.hash -> uri"https://blockstream.info/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"https://blockstream.info/api"
)
}
}
/** Query https://mempool.space/ to fetch block headers. */
case class MempoolSpaceExplorer(socksProxy_opt: Option[Socks5ProxyParams])(implicit val sb: SttpBackend[Future, Nothing]) extends Esplora {
case class MempoolSpaceExplorer(useTorEndpoints: Boolean)(implicit val sb: SttpBackend[Future, _]) extends Esplora {
override val name = "mempool.space"
override val baseUris = socksProxy_opt match {
case Some(_) =>
Map(
Block.TestnetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api"
)
case None =>
Map(
Block.TestnetGenesisBlock.hash -> uri"https://mempool.space/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"https://mempool.space/api"
)
override val baseUris = if (useTorEndpoints) {
Map(
Block.TestnetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api"
)
} else {
Map(
Block.TestnetGenesisBlock.hash -> uri"https://mempool.space/testnet/api",
Block.LivenetGenesisBlock.hash -> uri"https://mempool.space/api"
)
}
}

View File

@ -177,7 +177,7 @@ class TransportHandler[T: ClassTag](keyPair: KeyPair, rs: Option[ByteVector], co
when(Normal) {
handleExceptions {
case Event(Tcp.Received(data), d: NormalData[T]) =>
case Event(Tcp.Received(data), d: NormalData[T @unchecked]) =>
val (dec1, plaintextMessages) = d.decryptor.copy(buffer = d.decryptor.buffer ++ data).decrypt()
if (plaintextMessages.isEmpty) {
connection ! Tcp.ResumeReading
@ -188,7 +188,7 @@ class TransportHandler[T: ClassTag](keyPair: KeyPair, rs: Option[ByteVector], co
stay() using NormalData(d.encryptor, dec1, d.listener, d.sendBuffer, unackedReceived, d.unackedSent)
}
case Event(ReadAck(msg: T), d: NormalData[T]) =>
case Event(ReadAck(msg: T), d: NormalData[T @unchecked]) =>
// how many occurences of this message are still unacked?
val remaining = d.unackedReceived.getOrElse(msg, 0) - 1
log.debug("acking message {}", msg)
@ -203,7 +203,7 @@ class TransportHandler[T: ClassTag](keyPair: KeyPair, rs: Option[ByteVector], co
stay() using d.copy(unackedReceived = unackedReceived1)
}
case Event(t: T, d: NormalData[T]) =>
case Event(t: T, d: NormalData[T @unchecked]) =>
if (d.sendBuffer.normalPriority.size + d.sendBuffer.lowPriority.size >= MAX_BUFFERED) {
log.warning("send buffer overrun, closing connection")
connection ! PoisonPill
@ -224,7 +224,7 @@ class TransportHandler[T: ClassTag](keyPair: KeyPair, rs: Option[ByteVector], co
stay() using d.copy(encryptor = enc1, unackedSent = Some(t))
}
case Event(WriteAck, d: NormalData[T]) =>
case Event(WriteAck, d: NormalData[T @unchecked]) =>
def send(t: T) = {
diag(t, "OUT")
val blob = codec.encode(t).require.toByteVector
@ -262,7 +262,7 @@ class TransportHandler[T: ClassTag](keyPair: KeyPair, rs: Option[ByteVector], co
case Event(msg, d) =>
d match {
case n: NormalData[T] => log.warning(s"unhandled message $msg in state normal unackedSent=${n.unackedSent.size} unackedReceived=${n.unackedReceived.size} sendBuffer.lowPriority=${n.sendBuffer.lowPriority.size} sendBuffer.normalPriority=${n.sendBuffer.normalPriority.size}")
case n: NormalData[_] => log.warning(s"unhandled message $msg in state normal unackedSent=${n.unackedSent.size} unackedReceived=${n.unackedReceived.size} sendBuffer.lowPriority=${n.sendBuffer.lowPriority.size} sendBuffer.normalPriority=${n.sendBuffer.normalPriority.size}")
case _ => log.warning(s"unhandled message $msg in state ${d.getClass.getSimpleName}")
}
stay()

View File

@ -432,16 +432,17 @@ object OnionMessageReceivedSerializer extends ConvertClassSerializer[OnionMessag
case class CustomTypeHints(custom: Map[Class[_], String]) extends TypeHints {
val reverse: Map[String, Class[_]] = custom.map(_.swap)
override def typeHintFieldName: String = "type"
override val hints: List[Class[_]] = custom.keys.toList
override def hintFor(clazz: Class[_]): String = custom.getOrElse(clazz, {
throw new IllegalArgumentException(s"No type hint mapping found for $clazz")
})
override def hintFor(clazz: Class[_]): Option[String] = custom.get(clazz)
override def classFor(hint: String): Option[Class[_]] = reverse.get(hint)
override def classFor(hint: String, parent: Class[_]): Option[Class[_]] = reverse.get(hint)
}
object CustomTypeHints {
val incomingPaymentStatus: CustomTypeHints = CustomTypeHints(Map(
IncomingPaymentStatus.Pending.getClass -> "pending",
IncomingPaymentStatus.Expired.getClass -> "expired",
@ -482,14 +483,14 @@ object CustomTypeHints {
classOf[DATA_NEGOTIATING],
classOf[DATA_CLOSING],
classOf[DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT]
))
), typeHintFieldName = "type")
}
object JsonSerializers {
implicit val serialization: Serialization.type = jackson.Serialization
implicit val formats: Formats = org.json4s.DefaultFormats.withTypeHintFieldName("type") +
implicit val formats: Formats = org.json4s.DefaultFormats +
CustomTypeHints.incomingPaymentStatus +
CustomTypeHints.outgoingPaymentStatus +
CustomTypeHints.paymentEvent +

View File

@ -46,7 +46,7 @@ object EclairInternalsSerializer {
def finiteDurationCodec: Codec[FiniteDuration] = int64.xmap(_.milliseconds, _.toMillis)
def iterable[A](codec: Codec[A]): Codec[Iterable[A]] = listOfN(uint16, codec).xmap(_.toIterable, _.toList)
def iterable[A](codec: Codec[A]): Codec[Iterable[A]] = listOfN(uint16, codec).xmap(_.toList, _.toList)
val searchBoundariesCodec: Codec[SearchBoundaries] = (
("maxFee" | millisatoshi) ::

View File

@ -28,7 +28,7 @@ import scala.concurrent.{ExecutionContext, Future}
/**
* Created by PM on 26/04/2016.
*/
class TestBitcoinCoreClient()(implicit system: ActorSystem) extends BitcoinCoreClient(new BasicBitcoinJsonRPCClient(UserPassword("", ""), "", 0)(http = null)) {
class TestBitcoinCoreClient()(implicit system: ActorSystem) extends BitcoinCoreClient(new BasicBitcoinJsonRPCClient(UserPassword("", ""), "", 0)(sb = null)) {
import scala.concurrent.ExecutionContext.Implicits.global

View File

@ -19,7 +19,6 @@ package fr.acinq.eclair.blockchain.bitcoind
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.pattern.pipe
import akka.testkit.{TestKitBase, TestProbe}
import com.softwaremill.sttp.okhttp.OkHttpFutureBackend
import fr.acinq.bitcoin.Crypto.PrivateKey
import fr.acinq.bitcoin.{Block, Btc, BtcAmount, ByteVector32, MilliBtc, OutPoint, Satoshi, Transaction, computeP2WpkhAddress}
import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinJsonRPCAuthMethod.{SafeCookie, UserPassword}
@ -28,6 +27,7 @@ import fr.acinq.eclair.integration.IntegrationSpec
import fr.acinq.eclair.{BlockHeight, TestUtils, randomKey}
import grizzled.slf4j.Logging
import org.json4s.JsonAST._
import sttp.client3.okhttp.OkHttpFutureBackend
import java.io.File
import java.nio.file.Files

View File

@ -28,7 +28,7 @@ class ExplorerApiSpec extends ScalaTestWithActorTestKit(ConfigFactory.load("appl
implicit val sttpBackend = ExplorerApi.createSttpBackend(None)
val explorers = Seq(BlockcypherExplorer(None), BlockstreamExplorer(None), MempoolSpaceExplorer(None))
val explorers = Seq(BlockcypherExplorer(), BlockstreamExplorer(useTorEndpoints = false), MempoolSpaceExplorer(useTorEndpoints = false))
test("fetch latest block headers", TestTags.ExternalApi) {
for (explorer <- explorers) {

View File

@ -19,7 +19,7 @@ package fr.acinq.eclair.router
import akka.actor.ActorSystem
import akka.pattern.pipe
import akka.testkit.TestProbe
import com.softwaremill.sttp.okhttp.OkHttpFutureBackend
import sttp.client3.okhttp.OkHttpFutureBackend
import fr.acinq.bitcoin.Crypto.PrivateKey
import fr.acinq.bitcoin.{Block, Satoshi, SatoshiLong, Script, Transaction}
import fr.acinq.eclair.blockchain.bitcoind.ZmqWatcher.ValidateResult

View File

@ -101,7 +101,7 @@
<dependency>
<groupId>de.heikoseeberger</groupId>
<artifactId>akka-http-json4s_${scala.version.short}</artifactId>
<version>1.37.0</version>
<version>1.39.2</version>
</dependency>
<!-- metrics -->
<dependency>

10
pom.xml
View File

@ -67,14 +67,14 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<scala.version>2.13.6</scala.version>
<scala.version>2.13.8</scala.version>
<scala.version.short>2.13</scala.version.short>
<akka.version>2.6.15</akka.version>
<akka.http.version>10.2.4</akka.http.version>
<sttp.version>1.7.2</sttp.version>
<akka.version>2.6.18</akka.version>
<akka.http.version>10.2.7</akka.http.version>
<sttp.version>3.4.1</sttp.version>
<bitcoinlib.version>0.19</bitcoinlib.version>
<guava.version>24.0-android</guava.version>
<kamon.version>2.2.2</kamon.version>
<kamon.version>2.4.6</kamon.version>
</properties>
<build>