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:
parent
daddee1912
commit
ca71a3c152
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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 +
|
||||
|
@ -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) ::
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
10
pom.xml
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user