diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala b/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala
index e05dd037fc..0ec0fabc3b 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala
@@ -166,6 +166,22 @@ object NodeParams extends Logging {
def chainFromHash(chainHash: ByteVector32): String = chain2Hash.map(_.swap).getOrElse(chainHash, throw new RuntimeException(s"invalid chainHash '$chainHash'"))
+ def parseSocks5ProxyParams(config: Config): Option[Socks5ProxyParams] = {
+ if (config.getBoolean("socks5.enabled")) {
+ Some(Socks5ProxyParams(
+ address = new InetSocketAddress(config.getString("socks5.host"), config.getInt("socks5.port")),
+ credentials_opt = None,
+ randomizeCredentials = config.getBoolean("socks5.randomize-credentials"),
+ useForIPv4 = config.getBoolean("socks5.use-for-ipv4"),
+ useForIPv6 = config.getBoolean("socks5.use-for-ipv6"),
+ useForTor = config.getBoolean("socks5.use-for-tor"),
+ useForWatchdogs = config.getBoolean("socks5.use-for-watchdogs"),
+ ))
+ } else {
+ None
+ }
+ }
+
def makeNodeParams(config: Config, instanceId: UUID, nodeKeyManager: NodeKeyManager, channelKeyManager: ChannelKeyManager,
torAddress_opt: Option[NodeAddress], database: Databases, blockHeight: AtomicLong, feeEstimator: FeeEstimator,
pluginParams: Seq[PluginParams] = Nil): NodeParams = {
@@ -302,19 +318,7 @@ object NodeParams extends Logging {
val syncWhitelist: Set[PublicKey] = config.getStringList("sync-whitelist").asScala.map(s => PublicKey(ByteVector.fromValidHex(s))).toSet
- val socksProxy_opt = if (config.getBoolean("socks5.enabled")) {
- Some(Socks5ProxyParams(
- address = new InetSocketAddress(config.getString("socks5.host"), config.getInt("socks5.port")),
- credentials_opt = None,
- randomizeCredentials = config.getBoolean("socks5.randomize-credentials"),
- useForIPv4 = config.getBoolean("socks5.use-for-ipv4"),
- useForIPv6 = config.getBoolean("socks5.use-for-ipv6"),
- useForTor = config.getBoolean("socks5.use-for-tor"),
- useForWatchdogs = config.getBoolean("socks5.use-for-watchdogs"),
- ))
- } else {
- None
- }
+ val socksProxy_opt = parseSocks5ProxyParams(config)
val publicTorAddress_opt = if (config.getBoolean("tor.publish-onion-address")) torAddress_opt else None
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala
index 6fdc36afdb..9e8742c968 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala
@@ -16,8 +16,6 @@
package fr.acinq.eclair.io
-import java.net.InetSocketAddress
-
import akka.actor.{Props, _}
import akka.event.Logging.MDC
import akka.io.Tcp.SO.KeepAlive
@@ -28,14 +26,16 @@ import fr.acinq.eclair.Logs.LogCategory
import fr.acinq.eclair.crypto.Noise.KeyPair
import fr.acinq.eclair.tor.Socks5Connection.{Socks5Connect, Socks5Connected, Socks5Error}
import fr.acinq.eclair.tor.{Socks5Connection, Socks5ProxyParams}
+import fr.acinq.eclair.wire.protocol._
+import java.net.InetSocketAddress
import scala.concurrent.duration._
/**
* Created by PM on 27/10/2015.
*
*/
-class Client(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams], peerConnectionConf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef, remoteAddress: InetSocketAddress, remoteNodeId: PublicKey, origin_opt: Option[ActorRef], isPersistent: Boolean) extends Actor with DiagnosticActorLogging {
+class Client(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams], peerConnectionConf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef, remoteNodeAddress: NodeAddress, remoteNodeId: PublicKey, origin_opt: Option[ActorRef], isPersistent: Boolean) extends Actor with DiagnosticActorLogging {
import context.system
@@ -44,7 +44,14 @@ class Client(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams],
def receive: Receive = {
case Symbol("connect") =>
- val (peerOrProxyAddress, proxyParams_opt) = socks5ProxyParams_opt.map(proxyParams => (proxyParams, Socks5ProxyParams.proxyAddress(remoteAddress, proxyParams))) match {
+ // note that there is no resolution here, it's either plain ip addresses, or unresolved tor hostnames
+ val remoteAddress = remoteNodeAddress match {
+ case addr: IPv4 => new InetSocketAddress(addr.ipv4, addr.port)
+ case addr: IPv6 => new InetSocketAddress(addr.ipv6, addr.port)
+ case addr: Tor2 => InetSocketAddress.createUnresolved(addr.host, addr.port)
+ case addr: Tor3 => InetSocketAddress.createUnresolved(addr.host, addr.port)
+ }
+ val (peerOrProxyAddress, proxyParams_opt) = socks5ProxyParams_opt.map(proxyParams => (proxyParams, Socks5ProxyParams.proxyAddress(remoteNodeAddress, proxyParams))) match {
case Some((proxyParams, Some(proxyAddress))) =>
log.info(s"connecting to SOCKS5 proxy ${str(proxyAddress)}")
(proxyAddress, Some(proxyParams))
@@ -53,14 +60,14 @@ class Client(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams],
(remoteAddress, None)
}
IO(Tcp) ! Tcp.Connect(peerOrProxyAddress, timeout = Some(20 seconds), options = KeepAlive(true) :: Nil, pullMode = true)
- context become connecting(proxyParams_opt)
+ context become connecting(proxyParams_opt, remoteAddress)
}
- def connecting(proxyParams: Option[Socks5ProxyParams]): Receive = {
+ def connecting(proxyParams: Option[Socks5ProxyParams], remoteAddress: InetSocketAddress): Receive = {
case Tcp.CommandFailed(c: Tcp.Connect) =>
val peerOrProxyAddress = c.remoteAddress
log.info(s"connection failed to ${str(peerOrProxyAddress)}")
- origin_opt.foreach(_ ! PeerConnection.ConnectionResult.ConnectionFailed(remoteAddress))
+ origin_opt.foreach(_ ! PeerConnection.ConnectionResult.ConnectionFailed(remoteNodeAddress))
context stop self
case Tcp.Connected(peerOrProxyAddress, _) =>
@@ -75,7 +82,7 @@ class Client(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams],
context become {
case Tcp.CommandFailed(_: Socks5Connect) =>
log.info(s"connection failed to ${str(remoteAddress)} via SOCKS5 ${str(proxyAddress)}")
- origin_opt.foreach(_ ! PeerConnection.ConnectionResult.ConnectionFailed(remoteAddress))
+ origin_opt.foreach(_ ! PeerConnection.ConnectionResult.ConnectionFailed(remoteNodeAddress))
context stop self
case Socks5Connected(_) =>
log.info(s"connected to ${str(remoteAddress)} via SOCKS5 proxy ${str(proxyAddress)}")
@@ -127,13 +134,13 @@ class Client(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams],
switchboard = switchboard,
router = router
))
- peerConnection ! PeerConnection.PendingAuth(connection, remoteNodeId_opt = Some(remoteNodeId), address = remoteAddress, origin_opt = origin_opt, isPersistent = isPersistent)
+ peerConnection ! PeerConnection.PendingAuth(connection, remoteNodeId_opt = Some(remoteNodeId), address = remoteNodeAddress, origin_opt = origin_opt, isPersistent = isPersistent)
peerConnection
}
}
object Client {
- def props(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams], peerConnectionConf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef, address: InetSocketAddress, remoteNodeId: PublicKey, origin_opt: Option[ActorRef], isPersistent: Boolean): Props = Props(new Client(keyPair, socks5ProxyParams_opt, peerConnectionConf, switchboard, router, address, remoteNodeId, origin_opt, isPersistent))
+ def props(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams], peerConnectionConf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef, address: NodeAddress, remoteNodeId: PublicKey, origin_opt: Option[ActorRef], isPersistent: Boolean): Props = Props(new Client(keyPair, socks5ProxyParams_opt, peerConnectionConf, switchboard, router, address, remoteNodeId, origin_opt, isPersistent))
}
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/ClientSpawner.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/ClientSpawner.scala
index efcb6601d5..e570279f2e 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/ClientSpawner.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/ClientSpawner.scala
@@ -16,8 +16,6 @@
package fr.acinq.eclair.io
-import java.net.InetSocketAddress
-
import akka.actor.{Actor, ActorLogging, ActorRef, DeadLetter, Props}
import akka.cluster.Cluster
import akka.cluster.pubsub.DistributedPubSub
@@ -26,6 +24,7 @@ import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.crypto.Noise.KeyPair
import fr.acinq.eclair.remote.EclairInternalsSerializer.RemoteTypes
import fr.acinq.eclair.tor.Socks5ProxyParams
+import fr.acinq.eclair.wire.protocol.NodeAddress
class ClientSpawner(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams], peerConnectionConf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef) extends Actor with ActorLogging {
@@ -57,7 +56,7 @@ class ClientSpawner(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyP
log.warning("handling outgoing connection request locally")
self forward req
case _: DeadLetter =>
- // we don't care about other dead letters
+ // we don't care about other dead letters
}
}
@@ -65,8 +64,8 @@ object ClientSpawner {
def props(keyPair: KeyPair, socks5ProxyParams_opt: Option[Socks5ProxyParams], peerConnectionConf: PeerConnection.Conf, switchboard: ActorRef, router: ActorRef): Props = Props(new ClientSpawner(keyPair, socks5ProxyParams_opt, peerConnectionConf, switchboard, router))
- case class ConnectionRequest(address: InetSocketAddress,
- remoteNodeId: PublicKey,
+ case class ConnectionRequest(remoteNodeId: PublicKey,
+ address: NodeAddress,
origin: ActorRef,
isPersistent: Boolean) extends RemoteTypes
}
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala
index 6e7736fd28..b5f450a9c5 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala
@@ -18,11 +18,12 @@ package fr.acinq.eclair.io
import com.google.common.net.HostAndPort
import fr.acinq.bitcoin.Crypto.PublicKey
+import fr.acinq.eclair.wire.protocol.NodeAddress
import scodec.bits.ByteVector
import scala.util.{Failure, Success, Try}
-case class NodeURI(nodeId: PublicKey, address: HostAndPort) {
+case class NodeURI(nodeId: PublicKey, address: NodeAddress) {
override def toString: String = s"$nodeId@$address"
}
@@ -40,10 +41,10 @@ object NodeURI {
@throws[IllegalArgumentException]
def parse(uri: String): NodeURI = {
uri.split("@") match {
- case Array(nodeId, address) => (Try(PublicKey(ByteVector.fromValidHex(nodeId))), Try(HostAndPort.fromString(address).withDefaultPort(DEFAULT_PORT))) match {
- case (Success(pk), Success(hostAndPort)) => NodeURI(pk, hostAndPort)
- case (Failure(_), _) => throw new IllegalArgumentException("Invalid node id")
- case (_, Failure(_)) => throw new IllegalArgumentException("Invalid host:port")
+ case Array(nodeId, address) => (Try(PublicKey(ByteVector.fromValidHex(nodeId))), Try(HostAndPort.fromString(address)).flatMap(hostAndPort => NodeAddress.fromParts(hostAndPort.getHost, hostAndPort.getPortOrDefault(DEFAULT_PORT)))) match {
+ case (Success(pk), Success(nodeAddress)) => NodeURI(pk, nodeAddress)
+ case (Failure(t), _) => throw new IllegalArgumentException("Invalid node id", t)
+ case (_, Failure(t)) => throw new IllegalArgumentException("Invalid host:port", t)
}
case _ => throw new IllegalArgumentException("Invalid uri, should be nodeId@host:port")
}
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala
index 5aae20924a..8d1f399532 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala
@@ -21,7 +21,6 @@ import akka.actor.{Actor, ActorContext, ActorRef, ExtendedActorSystem, FSM, OneF
import akka.event.Logging.MDC
import akka.event.{BusLogging, DiagnosticLoggingAdapter}
import akka.util.Timeout
-import com.google.common.net.HostAndPort
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.bitcoin.{ByteVector32, Satoshi, SatoshiLong, Script}
import fr.acinq.eclair.Features.Wumbo
@@ -42,7 +41,6 @@ import fr.acinq.eclair.wire.protocol
import fr.acinq.eclair.wire.protocol.{Error, HasChannelId, HasTemporaryChannelId, LightningMessage, NodeAddress, OnionMessage, RoutingMessage, UnknownMessage, Warning}
import scodec.bits.ByteVector
-import java.net.InetSocketAddress
import scala.concurrent.ExecutionContext
/**
@@ -331,12 +329,12 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, wallet: OnChainA
def gotoConnected(connectionReady: PeerConnection.ConnectionReady, channels: Map[ChannelId, ActorRef]): State = {
require(remoteNodeId == connectionReady.remoteNodeId, s"invalid nodeid: $remoteNodeId != ${connectionReady.remoteNodeId}")
- log.debug("got authenticated connection to address {}:{}", connectionReady.address.getHostString, connectionReady.address.getPort)
+ log.debug("got authenticated connection to address {}", connectionReady.address)
if (connectionReady.outgoing) {
// we store the node address upon successful outgoing connection, so we can reconnect later
// any previous address is overwritten
- NodeAddress.fromParts(connectionReady.address.getHostString, connectionReady.address.getPort).map(nodeAddress => nodeParams.db.peers.addOrUpdatePeer(remoteNodeId, nodeAddress))
+ nodeParams.db.peers.addOrUpdatePeer(remoteNodeId, connectionReady.address)
}
// let's bring existing/requested channels online
@@ -445,7 +443,7 @@ object Peer {
}
case object Nothing extends Data { override def channels = Map.empty }
case class DisconnectedData(channels: Map[FinalChannelId, ActorRef]) extends Data
- case class ConnectedData(address: InetSocketAddress, peerConnection: ActorRef, localInit: protocol.Init, remoteInit: protocol.Init, channels: Map[ChannelId, ActorRef]) extends Data {
+ case class ConnectedData(address: NodeAddress, peerConnection: ActorRef, localInit: protocol.Init, remoteInit: protocol.Init, channels: Map[ChannelId, ActorRef]) extends Data {
val connectionInfo: ConnectionInfo = ConnectionInfo(address, peerConnection, localInit, remoteInit)
def localFeatures: Features[InitFeature] = localInit.features
def remoteFeatures: Features[InitFeature] = remoteInit.features
@@ -457,7 +455,7 @@ object Peer {
case object CONNECTED extends State
case class Init(storedChannels: Set[HasCommitments])
- case class Connect(nodeId: PublicKey, address_opt: Option[HostAndPort], replyTo: ActorRef, isPersistent: Boolean) {
+ case class Connect(nodeId: PublicKey, address_opt: Option[NodeAddress], replyTo: ActorRef, isPersistent: Boolean) {
def uri: Option[NodeURI] = address_opt.map(NodeURI(nodeId, _))
}
object Connect {
@@ -476,7 +474,7 @@ object Peer {
sealed trait PeerInfoResponse {
def nodeId: PublicKey
}
- case class PeerInfo(peer: ActorRef, nodeId: PublicKey, state: State, address: Option[InetSocketAddress], channels: Int) extends PeerInfoResponse
+ case class PeerInfo(peer: ActorRef, nodeId: PublicKey, state: State, address: Option[NodeAddress], channels: Int) extends PeerInfoResponse
case class PeerNotFound(nodeId: PublicKey) extends PeerInfoResponse { override def toString: String = s"peer $nodeId not found" }
case class PeerRoutingMessage(peerConnection: ActorRef, remoteNodeId: PublicKey, message: RoutingMessage) extends RemoteTypes
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala
index f60c7ad856..b50d589247 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerConnection.scala
@@ -32,7 +32,6 @@ import fr.acinq.eclair.{FSMDiagnosticActorLogging, Feature, Features, InitFeatur
import scodec.Attempt
import scodec.bits.ByteVector
-import java.net.InetSocketAddress
import scala.concurrent.duration._
import scala.util.Random
@@ -87,8 +86,7 @@ class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: A
when(AUTHENTICATING) {
case Event(TransportHandler.HandshakeCompleted(remoteNodeId), d: AuthenticatingData) =>
cancelTimer(AUTH_TIMER)
- import d.pendingAuth.address
- log.info(s"connection authenticated with $remoteNodeId@${address.getHostString}:${address.getPort} direction=${if (d.pendingAuth.outgoing) "outgoing" else "incoming"}")
+ log.info(s"connection authenticated (direction=${if (d.pendingAuth.outgoing) "outgoing" else "incoming"})")
Metrics.PeerConnectionsConnecting.withTag(Tags.ConnectionState, Tags.ConnectionStates.Authenticated).increment()
switchboard ! Authenticated(self, remoteNodeId)
goto(BEFORE_INIT) using BeforeInitData(remoteNodeId, d.pendingAuth, d.transport, d.isPersistent)
@@ -104,8 +102,8 @@ class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: A
d.transport ! TransportHandler.Listener(self)
Metrics.PeerConnectionsConnecting.withTag(Tags.ConnectionState, Tags.ConnectionStates.Initializing).increment()
log.info(s"using features=$localFeatures")
- val localInit = IPAddress(d.pendingAuth.address.getAddress, d.pendingAuth.address.getPort) match {
- case Some(remoteAddress) if !d.pendingAuth.outgoing && NodeAddress.isPublicIPAddress(remoteAddress) => protocol.Init(localFeatures, TlvStream(InitTlv.Networks(chainHash :: Nil), InitTlv.RemoteAddress(remoteAddress)))
+ val localInit = d.pendingAuth.address match {
+ case remoteAddress if !d.pendingAuth.outgoing && NodeAddress.isPublicIPAddress(remoteAddress) => protocol.Init(localFeatures, TlvStream(InitTlv.Networks(chainHash :: Nil), InitTlv.RemoteAddress(remoteAddress)))
case _ => protocol.Init(localFeatures, TlvStream(InitTlv.Networks(chainHash :: Nil)))
}
d.transport ! localInit
@@ -120,7 +118,7 @@ class PeerConnection(keyPair: KeyPair, conf: PeerConnection.Conf, switchboard: A
d.transport ! TransportHandler.ReadAck(remoteInit)
log.info(s"peer is using features=${remoteInit.features}, networks=${remoteInit.networks.mkString(",")}")
- remoteInit.remoteAddress_opt.foreach(address => log.info("peer reports that our IP address is {} (public={})", address.socketAddress.toString, NodeAddress.isPublicIPAddress(address)))
+ remoteInit.remoteAddress_opt.foreach(address => log.info("peer reports that our IP address is {} (public={})", address.toString, NodeAddress.isPublicIPAddress(address)))
val featureGraphErr_opt = Features.validateFeatureGraph(remoteInit.features)
if (remoteInit.networks.nonEmpty && remoteInit.networks.intersect(d.localInit.networks).isEmpty) {
@@ -552,12 +550,12 @@ object PeerConnection {
case object INITIALIZING extends State
case object CONNECTED extends State
- case class PendingAuth(connection: ActorRef, remoteNodeId_opt: Option[PublicKey], address: InetSocketAddress, origin_opt: Option[ActorRef], transport_opt: Option[ActorRef] = None, isPersistent: Boolean) {
+ case class PendingAuth(connection: ActorRef, remoteNodeId_opt: Option[PublicKey], address: NodeAddress, origin_opt: Option[ActorRef], transport_opt: Option[ActorRef] = None, isPersistent: Boolean) {
def outgoing: Boolean = remoteNodeId_opt.isDefined // if this is an outgoing connection, we know the node id in advance
}
case class Authenticated(peerConnection: ActorRef, remoteNodeId: PublicKey) extends RemoteTypes
case class InitializeConnection(peer: ActorRef, chainHash: ByteVector32, features: Features[InitFeature], doSync: Boolean) extends RemoteTypes
- case class ConnectionReady(peerConnection: ActorRef, remoteNodeId: PublicKey, address: InetSocketAddress, outgoing: Boolean, localInit: protocol.Init, remoteInit: protocol.Init) extends RemoteTypes
+ case class ConnectionReady(peerConnection: ActorRef, remoteNodeId: PublicKey, address: NodeAddress, outgoing: Boolean, localInit: protocol.Init, remoteInit: protocol.Init) extends RemoteTypes
sealed trait ConnectionResult extends RemoteTypes
object ConnectionResult {
@@ -569,7 +567,7 @@ object PeerConnection {
}
case object NoAddressFound extends ConnectionResult.Failure { override def toString: String = "no address found" }
- case class ConnectionFailed(address: InetSocketAddress) extends ConnectionResult.Failure { override def toString: String = s"connection failed to $address" }
+ case class ConnectionFailed(address: NodeAddress) extends ConnectionResult.Failure { override def toString: String = s"connection failed to $address" }
case class AuthenticationFailed(reason: String) extends ConnectionResult.Failure { override def toString: String = reason }
case class InitializationFailed(reason: String) extends ConnectionResult.Failure { override def toString: String = reason }
case class AlreadyConnected(peerConnection: ActorRef, peer: ActorRef) extends ConnectionResult.Failure with HasConnection { override def toString: String = "already connected" }
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerEvents.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerEvents.scala
index de213c5c55..73332db36f 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerEvents.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/PeerEvents.scala
@@ -19,13 +19,11 @@ package fr.acinq.eclair.io
import akka.actor.ActorRef
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.wire.protocol
-import fr.acinq.eclair.wire.protocol.UnknownMessage
-
-import java.net.InetSocketAddress
+import fr.acinq.eclair.wire.protocol.{NodeAddress, UnknownMessage}
sealed trait PeerEvent
-case class ConnectionInfo(address: InetSocketAddress, peerConnection: ActorRef, localInit: protocol.Init, remoteInit: protocol.Init)
+case class ConnectionInfo(address: NodeAddress, peerConnection: ActorRef, localInit: protocol.Init, remoteInit: protocol.Init)
case class PeerConnected(peer: ActorRef, nodeId: PublicKey, connectionInfo: ConnectionInfo) extends PeerEvent
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/ReconnectionTask.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/ReconnectionTask.scala
index d976504504..59059e03b2 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/ReconnectionTask.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/ReconnectionTask.scala
@@ -21,14 +21,12 @@ import akka.cluster.Cluster
import akka.cluster.pubsub.DistributedPubSub
import akka.cluster.pubsub.DistributedPubSubMediator.Send
import akka.event.Logging.MDC
-import com.google.common.net.HostAndPort
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.Logs.LogCategory
import fr.acinq.eclair.io.Monitoring.Metrics
import fr.acinq.eclair.wire.protocol.{NodeAddress, OnionAddress}
import fr.acinq.eclair.{FSMDiagnosticActorLogging, Logs, NodeParams, TimestampMilli}
-import java.net.InetSocketAddress
import scala.concurrent.duration.{FiniteDuration, _}
import scala.util.Random
@@ -130,12 +128,11 @@ class ReconnectionTask(nodeParams: NodeParams, remoteNodeId: PublicKey) extends
case Event(TickReconnect, _) => stay()
- case Event(Peer.Connect(_, hostAndPort_opt, replyTo, isPersistent), _) =>
+ case Event(Peer.Connect(_, address_opt, replyTo, isPersistent), _) =>
// manual connection requests happen completely independently of the automated reconnection process;
// we initiate a connection but don't modify our state.
// if we are already connecting/connected, the peer will kill any duplicate connections
- hostAndPort_opt
- .map(hostAndPort2InetSocketAddress)
+ address_opt
.orElse(getPeerAddressFromDb(nodeParams, remoteNodeId)) match {
case Some(address) => connect(address, origin = replyTo, isPersistent)
case None => replyTo ! PeerConnection.ConnectionResult.NoAddressFound
@@ -148,10 +145,10 @@ class ReconnectionTask(nodeParams: NodeParams, remoteNodeId: PublicKey) extends
// activate the extension only on demand, so that tests pass
lazy val mediator = DistributedPubSub(context.system).mediator
- private def connect(address: InetSocketAddress, origin: ActorRef, isPersistent: Boolean): Unit = {
+ private def connect(address: NodeAddress, origin: ActorRef, isPersistent: Boolean): Unit = {
log.info(s"connecting to $address")
- val req = ClientSpawner.ConnectionRequest(address, remoteNodeId, origin, isPersistent)
- if (context.system.hasExtension(Cluster) && !address.getHostName.endsWith("onion")) {
+ val req = ClientSpawner.ConnectionRequest(remoteNodeId, address, origin, isPersistent)
+ if (context.system.hasExtension(Cluster)) {
mediator ! Send(path = "/user/client-spawner", msg = req, localAffinity = false)
} else {
context.system.eventStream.publish(req)
@@ -185,7 +182,7 @@ object ReconnectionTask {
sealed trait Data
case object Nothing extends Data
case class IdleData(previousData: Data, since: TimestampMilli = TimestampMilli.now()) extends Data
- case class ConnectingData(to: InetSocketAddress, nextReconnectionDelay: FiniteDuration) extends Data
+ case class ConnectingData(to: NodeAddress, nextReconnectionDelay: FiniteDuration) extends Data
case class WaitingData(nextReconnectionDelay: FiniteDuration) extends Data
// @formatter:on
@@ -213,13 +210,11 @@ object ReconnectionTask {
}
}
- def getPeerAddressFromDb(nodeParams: NodeParams, remoteNodeId: PublicKey): Option[InetSocketAddress] = {
+ def getPeerAddressFromDb(nodeParams: NodeParams, remoteNodeId: PublicKey): Option[NodeAddress] = {
val nodeAddresses = nodeParams.db.peers.getPeer(remoteNodeId).toSeq ++ nodeParams.db.network.getNode(remoteNodeId).toSeq.flatMap(_.addresses)
- selectNodeAddress(nodeParams, nodeAddresses).map(_.socketAddress)
+ selectNodeAddress(nodeParams, nodeAddresses)
}
- def hostAndPort2InetSocketAddress(hostAndPort: HostAndPort): InetSocketAddress = new InetSocketAddress(hostAndPort.getHost, hostAndPort.getPort)
-
/**
* This helps prevent peers reconnection loops due to synchronization of reconnection attempts.
*/
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala
index b4d3542754..4dcda42af6 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala
@@ -17,7 +17,6 @@
package fr.acinq.eclair.io
import java.net.InetSocketAddress
-
import akka.Done
import akka.actor.{Actor, ActorRef, DiagnosticActorLogging, Props}
import akka.event.Logging.MDC
@@ -26,6 +25,7 @@ import akka.io.{IO, Tcp}
import fr.acinq.eclair.Logs
import fr.acinq.eclair.Logs.LogCategory
import fr.acinq.eclair.crypto.Noise.KeyPair
+import fr.acinq.eclair.wire.protocol.{IPAddress, NodeAddress}
import scala.concurrent.Promise
@@ -62,7 +62,7 @@ class Server(keyPair: KeyPair, peerConnectionConf: PeerConnection.Conf, switchbo
switchboard = switchboard,
router = router
))
- peerConnection ! PeerConnection.PendingAuth(connection, remoteNodeId_opt = None, address = remote, origin_opt = None, isPersistent = true)
+ peerConnection ! PeerConnection.PendingAuth(connection, remoteNodeId_opt = None, address = IPAddress(remote.getAddress, remote.getPort), origin_opt = None, isPersistent = true)
listener ! ResumeAccepting(batchSize = 1)
}
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/json/JsonSerializers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/json/JsonSerializers.scala
index 6ea58b28e9..7621a7704f 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/json/JsonSerializers.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/json/JsonSerializers.scala
@@ -331,7 +331,7 @@ object FailureTypeSerializer extends MinimalSerializer({
})
object NodeAddressSerializer extends MinimalSerializer({
- case n: NodeAddress => JString(HostAndPort.fromParts(n.socketAddress.getHostString, n.socketAddress.getPort).toString)
+ case n: NodeAddress => JString(n.toString)
})
// @formatter:off
@@ -426,8 +426,8 @@ object OriginSerializer extends MinimalSerializer({
private case class GlobalBalanceJson(total: Btc, onChain: CorrectedOnChainBalance, offChain: OffChainBalance)
object GlobalBalanceSerializer extends ConvertClassSerializer[GlobalBalance](b => GlobalBalanceJson(b.total, b.onChain, b.offChain))
-private case class PeerInfoJson(nodeId: PublicKey, state: String, address: Option[InetSocketAddress], channels: Int)
-object PeerInfoSerializer extends ConvertClassSerializer[Peer.PeerInfo](peerInfo => PeerInfoJson(peerInfo.nodeId, peerInfo.state.toString, peerInfo.address, peerInfo.channels))
+private case class PeerInfoJson(nodeId: PublicKey, state: String, address: Option[String], channels: Int)
+object PeerInfoSerializer extends ConvertClassSerializer[Peer.PeerInfo](peerInfo => PeerInfoJson(peerInfo.nodeId, peerInfo.state.toString, peerInfo.address.map(_.toString), peerInfo.channels))
private[json] case class MessageReceivedJson(pathId: Option[ByteVector], encodedReplyPath: Option[String], replyPath: Option[BlindedRoute], unknownTlvs: Map[String, ByteVector])
object OnionMessageReceivedSerializer extends ConvertClassSerializer[OnionMessages.ReceiveMessage](m => MessageReceivedJson(m.pathId, m.finalPayload.replyPath.map(route => blindedRouteCodec.encode(route.blindedRoute).require.bytes.toHex), m.finalPayload.replyPath.map(_.blindedRoute), m.finalPayload.records.unknown.map(tlv => tlv.tag.toString -> tlv.value).toMap))
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala
index 854ecd1ada..8acaf528f0 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/remote/EclairInternalsSerializer.scala
@@ -25,7 +25,7 @@ import fr.acinq.eclair.io.Switchboard.RouterPeerConf
import fr.acinq.eclair.io.{ClientSpawner, Peer, PeerConnection, Switchboard}
import fr.acinq.eclair.payment.relay.Relayer.RelayFees
import fr.acinq.eclair.router.Graph.{HeuristicsConstants, WeightRatios}
-import fr.acinq.eclair.router.Router.{GossipDecision, MultiPartParams, PathFindingConf, RouterConf, SearchBoundaries, SendChannelQuery}
+import fr.acinq.eclair.router.Router._
import fr.acinq.eclair.router._
import fr.acinq.eclair.wire.protocol.CommonCodecs._
import fr.acinq.eclair.wire.protocol.LightningMessageCodecs._
@@ -35,7 +35,6 @@ import fr.acinq.eclair.{CltvExpiryDelta, Feature, Features, InitFeature}
import scodec._
import scodec.codecs._
-import java.net.{InetAddress, InetSocketAddress}
import scala.concurrent.duration._
class EclairInternalsSerializer(val system: ExtendedActorSystem) extends ScodecSerializer(43, EclairInternalsSerializer.codec(system))
@@ -88,7 +87,7 @@ object EclairInternalsSerializer {
val routerConfCodec: Codec[RouterConf] = (
("watchSpentWindow" | finiteDurationCodec) ::
- ("channelExcludeDuration" | finiteDurationCodec) ::
+ ("channelExcludeDuration" | finiteDurationCodec) ::
("routerBroadcastInterval" | finiteDurationCodec) ::
("requestNodeAnnouncements" | bool(8)) ::
("encodingType" | discriminated[EncodingType].by(uint8)
@@ -131,15 +130,9 @@ object EclairInternalsSerializer {
(path: String) => system.provider.resolveActorRef(path),
(actor: ActorRef) => Serialization.serializedActorPath(actor))
- val inetAddressCodec: Codec[InetAddress] = discriminated[InetAddress].by(uint8)
- .typecase(0, ipv4address)
- .typecase(1, ipv6address)
-
- val inetSocketAddressCodec: Codec[InetSocketAddress] = (inetAddressCodec ~ uint16).xmap({ case (addr, port) => new InetSocketAddress(addr, port) }, socketAddr => (socketAddr.getAddress, socketAddr.getPort))
-
def connectionRequestCodec(system: ExtendedActorSystem): Codec[ClientSpawner.ConnectionRequest] = (
- ("address" | inetSocketAddressCodec) ::
- ("remoteNodeId" | publicKey) ::
+ ("remoteNodeId" | publicKey) ::
+ ("address" | nodeaddress) ::
("origin" | actorRefCodec(system)) ::
("isPersistent" | bool8)).as[ClientSpawner.ConnectionRequest]
@@ -152,7 +145,7 @@ object EclairInternalsSerializer {
def connectionReadyCodec(system: ExtendedActorSystem): Codec[PeerConnection.ConnectionReady] = (
("peerConnection" | actorRefCodec(system)) ::
("remoteNodeId" | publicKey) ::
- ("address" | inetSocketAddressCodec) ::
+ ("address" | nodeaddress) ::
("outgoing" | bool(8)) ::
("localInit" | lengthPrefixedInitCodec) ::
("remoteInit" | lengthPrefixedInitCodec)).as[PeerConnection.ConnectionReady]
@@ -184,7 +177,7 @@ object EclairInternalsSerializer {
.typecase(11, initializeConnectionCodec(system))
.typecase(12, connectionReadyCodec(system))
.typecase(13, provide(PeerConnection.ConnectionResult.NoAddressFound))
- .typecase(14, inetSocketAddressCodec.as[PeerConnection.ConnectionResult.ConnectionFailed])
+ .typecase(14, nodeaddress.as[PeerConnection.ConnectionResult.ConnectionFailed])
.typecase(15, variableSizeBytes(uint16, utf8).as[PeerConnection.ConnectionResult.AuthenticationFailed])
.typecase(16, variableSizeBytes(uint16, utf8).as[PeerConnection.ConnectionResult.InitializationFailed])
.typecase(17, (actorRefCodec(system) :: actorRefCodec(system)).as[PeerConnection.ConnectionResult.AlreadyConnected])
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/tor/Socks5Connection.scala b/eclair-core/src/main/scala/fr/acinq/eclair/tor/Socks5Connection.scala
index 7fa28b1118..0f27c104e7 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/tor/Socks5Connection.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/tor/Socks5Connection.scala
@@ -231,12 +231,13 @@ object Socks5ProxyParams {
)
- def proxyAddress(socketAddress: InetSocketAddress, proxyParams: Socks5ProxyParams): Option[InetSocketAddress] =
- NodeAddress.fromParts(socketAddress.getHostString, socketAddress.getPort).toOption collect {
- case _: IPv4 if proxyParams.useForIPv4 => proxyParams.address
- case _: IPv6 if proxyParams.useForIPv6 => proxyParams.address
- case _: Tor2 if proxyParams.useForTor => proxyParams.address
- case _: Tor3 if proxyParams.useForTor => proxyParams.address
+ def proxyAddress(address: NodeAddress, proxyParams: Socks5ProxyParams): Option[InetSocketAddress] =
+ address match {
+ case _: IPv4 if proxyParams.useForIPv4 => Some(proxyParams.address)
+ case _: IPv6 if proxyParams.useForIPv6 => Some(proxyParams.address)
+ case _: Tor2 if proxyParams.useForTor => Some(proxyParams.address)
+ case _: Tor3 if proxyParams.useForTor => Some(proxyParams.address)
+ case _ => None
}
def proxyCredentials(proxyParams: Socks5ProxyParams): Option[Socks5Connection.Credentials] =
diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala
index 6a60124138..7db79d5f3a 100644
--- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala
+++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/protocol/LightningMessageTypes.scala
@@ -17,14 +17,15 @@
package fr.acinq.eclair.wire.protocol
import com.google.common.base.Charsets
+import com.google.common.net.InetAddresses
import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.{ByteVector32, ByteVector64, Satoshi}
import fr.acinq.eclair.blockchain.fee.FeeratePerKw
import fr.acinq.eclair.channel.{ChannelFlags, ChannelType}
-import fr.acinq.eclair.{BlockHeight, CltvExpiry, CltvExpiryDelta, Feature, Features, InitFeature, MilliSatoshi, NodeFeature, ShortChannelId, TimestampSecond, UInt64}
+import fr.acinq.eclair.{BlockHeight, CltvExpiry, CltvExpiryDelta, Feature, Features, InitFeature, MilliSatoshi, ShortChannelId, TimestampSecond, UInt64}
import scodec.bits.ByteVector
-import java.net.{Inet4Address, Inet6Address, InetAddress, InetSocketAddress}
+import java.net.{Inet4Address, Inet6Address, InetAddress}
import java.nio.charset.StandardCharsets
import scala.util.Try
@@ -214,7 +215,7 @@ case class Color(r: Byte, g: Byte, b: Byte) {
}
// @formatter:off
-sealed trait NodeAddress { def socketAddress: InetSocketAddress }
+sealed trait NodeAddress { def host: String; def port: Int; override def toString: String = s"$host:$port" }
sealed trait OnionAddress extends NodeAddress
sealed trait IPAddress extends NodeAddress
// @formatter:on
@@ -232,7 +233,7 @@ object NodeAddress {
host match {
case _ if host.endsWith(".onion") && host.length == 22 => Tor2(host.dropRight(6), port)
case _ if host.endsWith(".onion") && host.length == 62 => Tor3(host.dropRight(6), port)
- case _ => IPAddress(InetAddress.getByName(host), port).get
+ case _ => IPAddress(InetAddress.getByName(host), port)
}
}
@@ -248,18 +249,17 @@ object NodeAddress {
}
object IPAddress {
- def apply(inetAddress: InetAddress, port: Int): Option[IPAddress] = inetAddress match {
- case address: Inet4Address => Some(IPv4(address, port))
- case address: Inet6Address => Some(IPv6(address, port))
- case _ => None
+ def apply(inetAddress: InetAddress, port: Int): IPAddress = inetAddress match {
+ case address: Inet4Address => IPv4(address, port)
+ case address: Inet6Address => IPv6(address, port)
}
}
// @formatter:off
-case class IPv4(ipv4: Inet4Address, port: Int) extends IPAddress { override def socketAddress = new InetSocketAddress(ipv4, port) }
-case class IPv6(ipv6: Inet6Address, port: Int) extends IPAddress { override def socketAddress = new InetSocketAddress(ipv6, port) }
-case class Tor2(tor2: String, port: Int) extends OnionAddress { override def socketAddress = InetSocketAddress.createUnresolved(tor2 + ".onion", port) }
-case class Tor3(tor3: String, port: Int) extends OnionAddress { override def socketAddress = InetSocketAddress.createUnresolved(tor3 + ".onion", port) }
+case class IPv4(ipv4: Inet4Address, port: Int) extends IPAddress { override def host: String = InetAddresses.toUriString(ipv4) }
+case class IPv6(ipv6: Inet6Address, port: Int) extends IPAddress { override def host: String = InetAddresses.toUriString(ipv6) }
+case class Tor2(tor2: String, port: Int) extends OnionAddress { override def host: String = tor2 + ".onion" }
+case class Tor3(tor3: String, port: Int) extends OnionAddress { override def host: String = tor3 + ".onion" }
// @formatter:on
case class NodeAnnouncement(signature: ByteVector64,
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala
index fb5c8960a2..9927d7f818 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala
@@ -16,6 +16,7 @@
package fr.acinq.eclair
+import com.google.common.net.InetAddresses
import fr.acinq.bitcoin.Crypto.PrivateKey
import fr.acinq.bitcoin.{Base58, Base58Check, Bech32, Block, ByteVector32, Crypto, Script}
import org.scalatest.funsuite.AnyFunSuite
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala
index 22c50677e5..046fac8a91 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala
@@ -19,7 +19,6 @@ package fr.acinq.eclair.integration
import akka.actor.ActorRef
import akka.pattern.pipe
import akka.testkit.TestProbe
-import com.google.common.net.HostAndPort
import com.typesafe.config.ConfigFactory
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.bitcoin.{Base58, Base58Check, Bech32, Block, BtcDouble, ByteVector32, Crypto, OP_0, OP_CHECKSIG, OP_DUP, OP_EQUAL, OP_EQUALVERIFY, OP_HASH160, OP_PUSHDATA, OutPoint, SatoshiLong, Script, ScriptFlags, Transaction}
@@ -35,7 +34,7 @@ import fr.acinq.eclair.payment.send.PaymentInitiator.SendPaymentToNode
import fr.acinq.eclair.router.Router
import fr.acinq.eclair.transactions.Transactions.{AnchorOutputsCommitmentFormat, TxOwner}
import fr.acinq.eclair.transactions.{Scripts, Transactions}
-import fr.acinq.eclair.wire.protocol.{ChannelAnnouncement, ChannelUpdate, PermanentChannelFailure, UpdateAddHtlc}
+import fr.acinq.eclair.wire.protocol._
import fr.acinq.eclair.{MilliSatoshi, MilliSatoshiLong, randomBytes32}
import org.json4s.JsonAST.{JString, JValue}
import scodec.bits.ByteVector
@@ -525,7 +524,7 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec {
// reconnection
sender.send(fundee.switchboard, Peer.Connect(
nodeId = funder.nodeParams.nodeId,
- address_opt = Some(HostAndPort.fromParts(funder.nodeParams.publicAddresses.head.socketAddress.getHostString, funder.nodeParams.publicAddresses.head.socketAddress.getPort)),
+ address_opt = funder.nodeParams.publicAddresses.headOption,
sender.ref,
isPersistent = true
))
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala
index 49656e2ef7..aba35a9b18 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala
@@ -18,7 +18,6 @@ package fr.acinq.eclair.integration
import akka.actor.ActorSystem
import akka.testkit.{TestKit, TestProbe}
-import com.google.common.net.HostAndPort
import com.typesafe.config.{Config, ConfigFactory}
import fr.acinq.bitcoin.Satoshi
import fr.acinq.eclair.Features._
@@ -29,6 +28,7 @@ import fr.acinq.eclair.payment.relay.Relayer.RelayFees
import fr.acinq.eclair.router.Graph.WeightRatios
import fr.acinq.eclair.router.RouteCalculation.ROUTE_MAX_LENGTH
import fr.acinq.eclair.router.Router.{MultiPartParams, PathFindingConf, SearchBoundaries, NORMAL => _, State => _}
+import fr.acinq.eclair.wire.protocol.NodeAddress
import fr.acinq.eclair.{BlockHeight, CltvExpiryDelta, Kit, MilliSatoshi, MilliSatoshiLong, Setup, TestKitBaseClass}
import grizzled.slf4j.Logging
import org.json4s.{DefaultFormats, Formats}
@@ -156,10 +156,9 @@ abstract class IntegrationSpec extends TestKitBaseClass with BitcoindService wit
def connect(node1: Kit, node2: Kit): Unit = {
val sender = TestProbe()
- val address = node2.nodeParams.publicAddresses.head
sender.send(node1.switchboard, Peer.Connect(
nodeId = node2.nodeParams.nodeId,
- address_opt = Some(HostAndPort.fromParts(address.socketAddress.getHostString, address.socketAddress.getPort)),
+ address_opt = node2.nodeParams.publicAddresses.headOption,
sender.ref,
isPersistent = true
))
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala
index d9ac3df090..1093ec5f34 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala
@@ -22,125 +22,59 @@ import org.scalatest.funsuite.AnyFunSuite
class NodeURISpec extends AnyFunSuite {
val PUBKEY = "03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134"
- val SHORT_PUB_KEY = "03933884aaf1d6b108397e5efe5c86bcf2d8ca"
- val NOT_HEXA_PUB_KEY = "03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fcghijklmn"
val IPV4_ENDURANCE = "34.250.234.192"
val NAME_ENDURANCE = "endurance.acinq.co"
val IPV6 = "[2405:204:66a9:536c:873f:dc4a:f055:a298]"
- val IPV6_NO_BRACKETS = "2001:db8:a0b:12f0::1"
- val IPV6_PREFIX = "[2001:db8:a0b:12f0::1/64]"
val IPV6_ZONE_IDENTIFIER = "[2001:db8:a0b:12f0::1%eth0]"
test("default port") {
assert(NodeURI.DEFAULT_PORT == 9735)
}
- // ---------- IPV4
-
- test("parse NodeURI with IPV4 and port") {
- val uri = s"$PUBKEY@$IPV4_ENDURANCE:9737"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.nodeId.toString() == PUBKEY)
- assert(nodeUri.address.getPort == 9737)
- }
-
- test("parse NodeURI with IPV4 and NO port") {
- val uri = s"$PUBKEY@$IPV4_ENDURANCE"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == NodeURI.DEFAULT_PORT)
- }
-
- test("parse NodeURI with named host and port") {
- val uri = s"$PUBKEY@$IPV4_ENDURANCE:9737"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.nodeId.toString() == PUBKEY)
- assert(nodeUri.address.getPort == 9737)
- }
-
- // ---------- IPV6 / regular with brackets
-
- test("parse NodeURI with IPV6 with brackets and port") {
- val uri = s"$PUBKEY@$IPV6:9737"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == 9737)
- }
-
- test("parse NodeURI with IPV6 with brackets and NO port") {
- val uri = s"$PUBKEY@$IPV6"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == NodeURI.DEFAULT_PORT)
- }
-
- // ---------- IPV6 / regular without brackets
-
- test("fail to parse NodeURI with IPV6 without brackets and port, and use default port") {
- // this can not be parsed because we can not tell what the port is (brackets are required) and the port is the default
- val uri = s"$PUBKEY@$IPV6_NO_BRACKETS:9737"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == NodeURI.DEFAULT_PORT)
- }
-
- test("parse NodeURI with IPV6 without brackets and NO port") {
- val uri = s"$PUBKEY@$IPV6_NO_BRACKETS"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == NodeURI.DEFAULT_PORT)
- }
-
- // ---------- IPV6 / prefix
-
- test("parse NodeURI with IPV6 with prefix and port") {
- val uri = s"$PUBKEY@$IPV6_PREFIX:9737"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == 9737)
- }
-
- test("parse NodeURI with IPV6 with prefix and NO port") {
- val uri = s"$PUBKEY@$IPV6_PREFIX"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == NodeURI.DEFAULT_PORT)
- }
-
- // ---------- IPV6 / zone identifier
-
- test("parse NodeURI with IPV6 with a zone identifier and port") {
- val uri = s"$PUBKEY@$IPV6_ZONE_IDENTIFIER:9737"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == 9737)
- }
-
- test("parse NodeURI with IPV6 with a zone identifier and NO port") {
- val uri = s"$PUBKEY@$IPV6_ZONE_IDENTIFIER"
- val nodeUri = NodeURI.parse(uri)
- assert(nodeUri.address.getPort == NodeURI.DEFAULT_PORT)
- }
-
- // ---------- fail if public key is not valid
-
- test("parsing should fail if the public key is not correct") {
- intercept[IllegalArgumentException](NodeURI.parse(s"$SHORT_PUB_KEY@$IPV4_ENDURANCE"))
- intercept[IllegalArgumentException](NodeURI.parse(s"$NOT_HEXA_PUB_KEY@$IPV4_ENDURANCE"))
+ test("NodeURI parsing success") {
+ case class TestCase(uri: String, formattedAddr: String, port: Int)
+
+ val testCases = List(
+ TestCase(s"$PUBKEY@$IPV4_ENDURANCE:9737", IPV4_ENDURANCE, 9737),
+ TestCase(s"$PUBKEY@$IPV4_ENDURANCE", IPV4_ENDURANCE, 9735),
+ TestCase(s"$PUBKEY@$NAME_ENDURANCE:9737", "13.248.222.197", 9737),
+ TestCase(s"$PUBKEY@$NAME_ENDURANCE", "13.248.222.197", 9735),
+ TestCase(s"$PUBKEY@$IPV6:9737", "[2405:204:66a9:536c:873f:dc4a:f055:a298]", 9737),
+ TestCase(s"$PUBKEY@$IPV6", "[2405:204:66a9:536c:873f:dc4a:f055:a298]", 9735),
+ TestCase(s"$PUBKEY@$IPV6_ZONE_IDENTIFIER:9737", "[2001:db8:a0b:12f0::1]", 9737),
+ TestCase(s"$PUBKEY@$IPV6_ZONE_IDENTIFIER", "[2001:db8:a0b:12f0::1]", 9735),
+ )
+
+ for (testCase <- testCases) {
+ val nodeUri = NodeURI.parse(testCase.uri)
+ assert(nodeUri.nodeId.toString() == PUBKEY)
+ assert(nodeUri.address.host == testCase.formattedAddr)
+ assert(nodeUri.address.port == testCase.port)
+ assert(nodeUri.toString === s"$PUBKEY@${testCase.formattedAddr}:${testCase.port}")
+ }
}
- // ---------- fail if host:port is not valid
-
- test("parsing should fail if host:port is not valid") {
- intercept[IllegalArgumentException](NodeURI.parse(s"$SHORT_PUB_KEY@1.2.3.4:abcd"))
- intercept[IllegalArgumentException](NodeURI.parse(s"$SHORT_PUB_KEY@1.2.3.4:999999999999999999999"))
- }
-
- test("parsing should fail if the uri is malformed") {
- intercept[IllegalArgumentException](NodeURI.parse("03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134@"))
- intercept[IllegalArgumentException](NodeURI.parse("03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134@123.45@654321"))
- intercept[IllegalArgumentException](NodeURI.parse("loremipsum"))
- intercept[IllegalArgumentException](NodeURI.parse(IPV6))
- intercept[IllegalArgumentException](NodeURI.parse(IPV4_ENDURANCE))
- intercept[IllegalArgumentException](NodeURI.parse(PUBKEY))
- intercept[IllegalArgumentException](NodeURI.parse(""))
- intercept[IllegalArgumentException](NodeURI.parse("@"))
- intercept[IllegalArgumentException](NodeURI.parse(":"))
+ test("NodeURI parsing failure") {
+ val testCases = List(
+ s"03933884aaf1d6b108397e5efe5c86bcf2d8ca@$IPV4_ENDURANCE",
+ s"03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fcghijklmn@$IPV4_ENDURANCE",
+ s"$PUBKEY@1.2.3.4:abcd",
+ s"$PUBKEY@1.2.3.4:999999999999999999999",
+ "03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134@",
+ "03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134@123.45@654321",
+ "loremipsum",
+ IPV6,
+ IPV4_ENDURANCE,
+ PUBKEY,
+ "",
+ "@",
+ ":",
+ )
+ for (testCase <- testCases) {
+ intercept[IllegalArgumentException](NodeURI.parse(testCase))
+ }
}
-
}
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala
index af9ba3e16b..a0a54e77bb 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerConnectionSpec.scala
@@ -42,7 +42,7 @@ class PeerConnectionSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wi
def ipv4FromInet4(address: InetSocketAddress): IPv4 = IPv4.apply(address.getAddress.asInstanceOf[Inet4Address], address.getPort)
- val address = new InetSocketAddress("localhost", 42000)
+ val address = NodeAddress.fromParts("localhost", 42000).get
val fakeIPAddress = NodeAddress.fromParts("1.2.3.4", 42000).get
// this map will store private keys so that we can sign new announcements at will
val pub2priv: mutable.Map[PublicKey, PrivateKey] = mutable.HashMap.empty
@@ -96,7 +96,7 @@ class PeerConnectionSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wi
test("send incoming connection's remote address in init") { f =>
import f._
val probe = TestProbe()
- val incomingConnection = PeerConnection.PendingAuth(connection.ref, None, fakeIPAddress.socketAddress, origin_opt = None, transport_opt = Some(transport.ref), isPersistent = true)
+ val incomingConnection = PeerConnection.PendingAuth(connection.ref, None, fakeIPAddress, origin_opt = None, transport_opt = Some(transport.ref), isPersistent = true)
assert(!incomingConnection.outgoing)
probe.send(peerConnection, incomingConnection)
transport.send(peerConnection, TransportHandler.HandshakeCompleted(remoteNodeId))
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala
index 58863d1f3f..3555ab0fab 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala
@@ -20,7 +20,6 @@ import akka.actor.Status.Failure
import akka.actor.typed.scaladsl.adapter.ClassicActorRefOps
import akka.actor.{ActorContext, ActorRef, FSM, PoisonPill, Status}
import akka.testkit.{TestFSMRef, TestProbe}
-import com.google.common.net.HostAndPort
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.bitcoin.{Block, Btc, SatoshiLong, Script}
import fr.acinq.eclair.FeatureSupport.{Mandatory, Optional}
@@ -90,7 +89,7 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
// let's simulate a connection
switchboard.send(peer, Peer.Init(channels))
val localInit = protocol.Init(peer.underlyingActor.nodeParams.features.initFeatures())
- switchboard.send(peer, PeerConnection.ConnectionReady(peerConnection.ref, remoteNodeId, fakeIPAddress.socketAddress, outgoing = true, localInit, remoteInit))
+ switchboard.send(peer, PeerConnection.ConnectionReady(peerConnection.ref, remoteNodeId, fakeIPAddress, outgoing = true, localInit, remoteInit))
val probe = TestProbe()
probe.send(peer, Peer.GetPeerInfo(Some(probe.ref.toTyped)))
val peerInfo = probe.expectMsgType[Peer.PeerInfo]
@@ -104,7 +103,7 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
val probe = TestProbe()
connect(remoteNodeId, peer, peerConnection, switchboard, channels = Set(ChannelCodecsSpec.normal))
probe.send(peer, Peer.GetPeerInfo(None))
- probe.expectMsg(PeerInfo(peer, remoteNodeId, Peer.CONNECTED, Some(fakeIPAddress.socketAddress), 1))
+ probe.expectMsg(PeerInfo(peer, remoteNodeId, Peer.CONNECTED, Some(fakeIPAddress), 1))
}
test("fail to connect if no address provided or found") { f =>
@@ -124,12 +123,12 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
// we create a dummy tcp server and update bob's announcement to point to it
val (mockServer, serverAddress) = createMockServer()
- val mockAddress = HostAndPort.fromParts(serverAddress.getHostName, serverAddress.getPort)
+ val mockAddress_opt = NodeAddress.fromParts(serverAddress.getHostName, serverAddress.getPort).toOption
val probe = TestProbe()
probe.send(peer, Peer.Init(Set.empty))
// we have auto-reconnect=false so we need to manually tell the peer to reconnect
- probe.send(peer, Peer.Connect(remoteNodeId, Some(mockAddress), probe.ref, isPersistent = true))
+ probe.send(peer, Peer.Connect(remoteNodeId, mockAddress_opt, probe.ref, isPersistent = true))
// assert our mock server got an incoming connection (the client was spawned with the address from node_announcement)
awaitCond(mockServer.accept() != null, max = 30 seconds, interval = 1 second)
@@ -224,14 +223,14 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
(inputReconnected.localInit, inputReconnected.remoteInit)
}
- peerConnection2.send(peer, PeerConnection.ConnectionReady(peerConnection2.ref, remoteNodeId, fakeIPAddress.socketAddress, outgoing = false, localInit, remoteInit))
+ peerConnection2.send(peer, PeerConnection.ConnectionReady(peerConnection2.ref, remoteNodeId, fakeIPAddress, outgoing = false, localInit, remoteInit))
// peer should kill previous connection
peerConnection1.expectMsg(PeerConnection.Kill(PeerConnection.KillReason.ConnectionReplaced))
channel.expectMsg(INPUT_DISCONNECTED)
channel.expectMsg(INPUT_RECONNECTED(peerConnection2.ref, localInit, remoteInit))
awaitCond(peer.stateData.asInstanceOf[Peer.ConnectedData].peerConnection === peerConnection2.ref)
- peerConnection3.send(peer, PeerConnection.ConnectionReady(peerConnection3.ref, remoteNodeId, fakeIPAddress.socketAddress, outgoing = false, localInit, remoteInit))
+ peerConnection3.send(peer, PeerConnection.ConnectionReady(peerConnection3.ref, remoteNodeId, fakeIPAddress, outgoing = false, localInit, remoteInit))
// peer should kill previous connection
peerConnection2.expectMsg(PeerConnection.Kill(PeerConnection.KillReason.ConnectionReplaced))
channel.expectMsg(INPUT_DISCONNECTED)
@@ -258,7 +257,7 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle
// we simulate a success
val dummyInit = protocol.Init(peer.underlyingActor.nodeParams.features.initFeatures())
- probe.send(peer, PeerConnection.ConnectionReady(peerConnection.ref, remoteNodeId, fakeIPAddress.socketAddress, outgoing = true, dummyInit, dummyInit))
+ probe.send(peer, PeerConnection.ConnectionReady(peerConnection.ref, remoteNodeId, fakeIPAddress, outgoing = true, dummyInit, dummyInit))
// we make sure that the reconnection task has done a full circle
monitor.expectMsg(FSM.Transition(reconnectionTask, ReconnectionTask.CONNECTING, ReconnectionTask.IDLE))
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/ReconnectionTaskSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/ReconnectionTaskSpec.scala
index d00562c2b7..db798a2654 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/io/ReconnectionTaskSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/ReconnectionTaskSpec.scala
@@ -38,7 +38,7 @@ class ReconnectionTaskSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
private val PeerNothingData = Peer.Nothing
private val PeerDisconnectedData = Peer.DisconnectedData(channels)
- private val PeerConnectedData = Peer.ConnectedData(fakeIPAddress.socketAddress, system.deadLetters, null, null, channels.map { case (k: ChannelId, v) => (k, v) })
+ private val PeerConnectedData = Peer.ConnectedData(fakeIPAddress, system.deadLetters, null, null, channels.map { case (k: ChannelId, v) => (k, v) })
case class FixtureParam(nodeParams: NodeParams, remoteNodeId: PublicKey, reconnectionTask: TestFSMRef[ReconnectionTask.State, ReconnectionTask.Data, ReconnectionTask], monitor: TestProbe)
@@ -101,7 +101,7 @@ class ReconnectionTaskSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
peer.send(reconnectionTask, Peer.Transition(PeerNothingData, PeerDisconnectedData))
val TransitionWithData(ReconnectionTask.IDLE, ReconnectionTask.WAITING, _, _) = monitor.expectMsgType[TransitionWithData]
val TransitionWithData(ReconnectionTask.WAITING, ReconnectionTask.CONNECTING, _, connectingData: ReconnectionTask.ConnectingData) = monitor.expectMsgType[TransitionWithData]
- assert(connectingData.to === fakeIPAddress.socketAddress)
+ assert(connectingData.to === fakeIPAddress)
val expectedNextReconnectionDelayInterval = (nodeParams.maxReconnectInterval.toSeconds / 2) to nodeParams.maxReconnectInterval.toSeconds
assert(expectedNextReconnectionDelayInterval contains connectingData.nextReconnectionDelay.toSeconds) // we only reconnect once
}
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala
index 5699b5ef2c..e359c19fb3 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala
@@ -90,13 +90,15 @@ class JsonSerializersSpec extends AnyFunSuite with Matchers {
}
test("NodeAddress serialization") {
- val ipv4 = NodeAddress.fromParts("10.0.0.1", 8888).get
- val ipv6LocalHost = NodeAddress.fromParts(InetAddress.getByAddress(Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)).getHostAddress, 9735).get
+ val ipv4 = IPAddress(InetAddress.getByName("10.0.0.1"), 8888)
+ val ipv6 = IPAddress(InetAddress.getByName("[2405:204:66a9:536c:873f:dc4a:f055:a298]"), 9737)
+ val ipv6LocalHost = IPAddress(InetAddress.getByAddress(Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)), 9735)
val tor2 = Tor2("aaaqeayeaudaocaj", 7777)
val tor3 = Tor3("aaaqeayeaudaocajbifqydiob4ibceqtcqkrmfyydenbwha5dypsaijc", 9999)
JsonSerializers.serialization.write(ipv4)(org.json4s.DefaultFormats + NodeAddressSerializer) shouldBe s""""10.0.0.1:8888""""
- JsonSerializers.serialization.write(ipv6LocalHost)(org.json4s.DefaultFormats + NodeAddressSerializer) shouldBe s""""[0:0:0:0:0:0:0:1]:9735""""
+ JsonSerializers.serialization.write(ipv6)(org.json4s.DefaultFormats + NodeAddressSerializer) shouldBe s""""[2405:204:66a9:536c:873f:dc4a:f055:a298]:9737""""
+ JsonSerializers.serialization.write(ipv6LocalHost)(org.json4s.DefaultFormats + NodeAddressSerializer) shouldBe s""""[::1]:9735""""
JsonSerializers.serialization.write(tor2)(org.json4s.DefaultFormats + NodeAddressSerializer) shouldBe s""""aaaqeayeaudaocaj.onion:7777""""
JsonSerializers.serialization.write(tor3)(org.json4s.DefaultFormats + NodeAddressSerializer) shouldBe s""""aaaqeayeaudaocajbifqydiob4ibceqtcqkrmfyydenbwha5dypsaijc.onion:9999""""
}
diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/tor/Socks5ConnectionSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/tor/Socks5ConnectionSpec.scala
index a89ee1d21f..a35cfb2b1f 100644
--- a/eclair-core/src/test/scala/fr/acinq/eclair/tor/Socks5ConnectionSpec.scala
+++ b/eclair-core/src/test/scala/fr/acinq/eclair/tor/Socks5ConnectionSpec.scala
@@ -16,8 +16,9 @@
package fr.acinq.eclair.tor
-import java.net.InetSocketAddress
+import fr.acinq.eclair.wire.protocol.NodeAddress
+import java.net.InetSocketAddress
import org.scalatest.funsuite.AnyFunSuite
/**
@@ -30,27 +31,27 @@ class Socks5ConnectionSpec extends AnyFunSuite {
val proxyAddress = new InetSocketAddress(9050)
assert(Socks5ProxyParams.proxyAddress(
- socketAddress = new InetSocketAddress("1.2.3.4", 9735),
+ address = NodeAddress.fromParts("1.2.3.4", 9735).get,
proxyParams = Socks5ProxyParams(address = proxyAddress, credentials_opt = None, randomizeCredentials = false, useForIPv4 = true, useForIPv6 = true, useForTor = true, useForWatchdogs = true)).contains(proxyAddress))
assert(Socks5ProxyParams.proxyAddress(
- socketAddress = new InetSocketAddress("1.2.3.4", 9735),
+ address = NodeAddress.fromParts("1.2.3.4", 9735).get,
proxyParams = Socks5ProxyParams(address = proxyAddress, credentials_opt = None, randomizeCredentials = false, useForIPv4 = false, useForIPv6 = true, useForTor = true, useForWatchdogs = true)).isEmpty)
assert(Socks5ProxyParams.proxyAddress(
- socketAddress = new InetSocketAddress("[fc92:97a3:e057:b290:abd8:9bd6:135d:7e7]", 9735),
+ address = NodeAddress.fromParts("[fc92:97a3:e057:b290:abd8:9bd6:135d:7e7]", 9735).get,
proxyParams = Socks5ProxyParams(address = proxyAddress, credentials_opt = None, randomizeCredentials = false, useForIPv4 = true, useForIPv6 = true, useForTor = true, useForWatchdogs = true)).contains(proxyAddress))
assert(Socks5ProxyParams.proxyAddress(
- socketAddress = new InetSocketAddress("[fc92:97a3:e057:b290:abd8:9bd6:135d:7e7]", 9735),
+ address = NodeAddress.fromParts("[fc92:97a3:e057:b290:abd8:9bd6:135d:7e7]", 9735).get,
proxyParams = Socks5ProxyParams(address = proxyAddress, credentials_opt = None, randomizeCredentials = false, useForIPv4 = true, useForIPv6 = false, useForTor = true, useForWatchdogs = true)).isEmpty)
assert(Socks5ProxyParams.proxyAddress(
- socketAddress = new InetSocketAddress("iq7zhmhck54vcax2vlrdcavq2m32wao7ekh6jyeglmnuuvv3js57r4id.onion", 9735),
+ address = NodeAddress.fromParts("iq7zhmhck54vcax2vlrdcavq2m32wao7ekh6jyeglmnuuvv3js57r4id.onion", 9735).get,
proxyParams = Socks5ProxyParams(address = proxyAddress, credentials_opt = None, randomizeCredentials = false, useForIPv4 = true, useForIPv6 = true, useForTor = true, useForWatchdogs = true)).contains(proxyAddress))
assert(Socks5ProxyParams.proxyAddress(
- socketAddress = new InetSocketAddress("iq7zhmhck54vcax2vlrdcavq2m32wao7ekh6jyeglmnuuvv3js57r4id.onion", 9735),
+ address = NodeAddress.fromParts("iq7zhmhck54vcax2vlrdcavq2m32wao7ekh6jyeglmnuuvv3js57r4id.onion", 9735).get,
proxyParams = Socks5ProxyParams(address = proxyAddress, credentials_opt = None, randomizeCredentials = false, useForIPv4 = true, useForIPv6 = true, useForTor = false, useForWatchdogs = true)).isEmpty)
}
diff --git a/eclair-front/src/main/scala/fr/acinq/eclair/FrontSetup.scala b/eclair-front/src/main/scala/fr/acinq/eclair/FrontSetup.scala
index 23736eddd2..3b43e3604f 100644
--- a/eclair-front/src/main/scala/fr/acinq/eclair/FrontSetup.scala
+++ b/eclair-front/src/main/scala/fr/acinq/eclair/FrontSetup.scala
@@ -85,6 +85,8 @@ class FrontSetup(datadir: File)(implicit system: ActorSystem) extends Logging {
config.getString("server.binding-ip"),
config.getInt("server.port"))
+ val socks5ProxyParams_opt = NodeParams.parseSocks5ProxyParams(config)
+
def bootstrap: Future[Unit] = {
val frontJoinedCluster = Promise[Done]()
@@ -112,7 +114,7 @@ class FrontSetup(datadir: File)(implicit system: ActorSystem) extends Logging {
frontRouter = system.actorOf(SimpleSupervisor.props(FrontRouter.props(routerConf, remoteRouter, Some(frontRouterInitialized)), "front-router", SupervisorStrategy.Resume))
_ <- frontRouterInitialized.future
- clientSpawner = system.actorOf(Props(new ClientSpawner(keyPair, None, peerConnectionConf, remoteSwitchboard, frontRouter)), name = "client-spawner")
+ clientSpawner = system.actorOf(Props(new ClientSpawner(keyPair, socks5ProxyParams_opt, peerConnectionConf, remoteSwitchboard, frontRouter)), name = "client-spawner")
server = system.actorOf(SimpleSupervisor.props(Server.props(keyPair, peerConnectionConf, remoteSwitchboard, frontRouter, serverBindingAddress, Some(tcpBound)), "server", SupervisorStrategy.Restart))
} yield ()
diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/api/handlers/Node.scala b/eclair-node/src/main/scala/fr/acinq/eclair/api/handlers/Node.scala
index da5cf1a23c..28cf82ed24 100644
--- a/eclair-node/src/main/scala/fr/acinq/eclair/api/handlers/Node.scala
+++ b/eclair-node/src/main/scala/fr/acinq/eclair/api/handlers/Node.scala
@@ -17,11 +17,11 @@
package fr.acinq.eclair.api.handlers
import akka.http.scaladsl.server.Route
-import com.google.common.net.HostAndPort
import fr.acinq.eclair.api.Service
import fr.acinq.eclair.api.directives.EclairDirectives
import fr.acinq.eclair.api.serde.FormParamExtractors._
import fr.acinq.eclair.io.NodeURI
+import fr.acinq.eclair.wire.protocol.NodeAddress
trait Node {
this: Service with EclairDirectives =>
@@ -38,7 +38,7 @@ trait Node {
} ~ formFields(nodeIdFormParam, "host".as[String], "port".as[Int].?) { (nodeId, host, port_opt) =>
complete {
eclairApi.connect(
- Left(NodeURI(nodeId, HostAndPort.fromParts(host, port_opt.getOrElse(NodeURI.DEFAULT_PORT))))
+ Left(NodeURI(nodeId, NodeAddress.fromParts(host, port_opt.getOrElse(NodeURI.DEFAULT_PORT)).get))
)
}
} ~ formFields(nodeIdFormParam) { nodeId =>
diff --git a/eclair-node/src/test/resources/api/getinfo b/eclair-node/src/test/resources/api/getinfo
index f0264a9768..c6a823114e 100644
--- a/eclair-node/src/test/resources/api/getinfo
+++ b/eclair-node/src/test/resources/api/getinfo
@@ -1 +1 @@
-{"version":"1.0.0-SNAPSHOT-e3f1ec0","nodeId":"03af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0","alias":"alice","color":"#000102","features":{"activated":{"option_data_loss_protect":"mandatory","gossip_queries_ex":"optional"},"unknown":[]},"chainHash":"06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f","network":"regtest","blockHeight":9999,"publicAddresses":["localhost:9731"],"instanceId":"01234567-0123-4567-89ab-0123456789ab"}
\ No newline at end of file
+{"version":"1.0.0-SNAPSHOT-e3f1ec0","nodeId":"03af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0","alias":"alice","color":"#000102","features":{"activated":{"option_data_loss_protect":"mandatory","gossip_queries_ex":"optional"},"unknown":[]},"chainHash":"06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f","network":"regtest","blockHeight":9999,"publicAddresses":["127.0.0.1:9731"],"instanceId":"01234567-0123-4567-89ab-0123456789ab"}
\ No newline at end of file
diff --git a/eclair-node/src/test/resources/api/peers b/eclair-node/src/test/resources/api/peers
index 3e12eddaa8..5fd9b2a1b8 100644
--- a/eclair-node/src/test/resources/api/peers
+++ b/eclair-node/src/test/resources/api/peers
@@ -1 +1 @@
-[{"nodeId":"03af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0","state":"CONNECTED","address":"localhost:9731","channels":1},{"nodeId":"039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a3585","state":"DISCONNECTED","channels":1}]
\ No newline at end of file
+[{"nodeId":"03af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0","state":"CONNECTED","address":"127.0.0.1:9731","channels":1},{"nodeId":"039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a3585","state":"DISCONNECTED","channels":1}]
\ No newline at end of file
diff --git a/eclair-node/src/test/scala/fr/acinq/eclair/api/ApiServiceSpec.scala b/eclair-node/src/test/scala/fr/acinq/eclair/api/ApiServiceSpec.scala
index 8b02196a9f..a7e7002921 100644
--- a/eclair-node/src/test/scala/fr/acinq/eclair/api/ApiServiceSpec.scala
+++ b/eclair-node/src/test/scala/fr/acinq/eclair/api/ApiServiceSpec.scala
@@ -167,7 +167,7 @@ class ApiServiceSpec extends AnyFunSuite with ScalatestRouteTest with IdiomaticM
ActorRef.noSender,
nodeId = aliceNodeId,
state = Peer.CONNECTED,
- address = Some(NodeAddress.fromParts("localhost", 9731).get.socketAddress),
+ address = Some(NodeAddress.fromParts("localhost", 9731).get),
channels = 1),
PeerInfo(
ActorRef.noSender,
diff --git a/pom.xml b/pom.xml
index 72af6be938..5c8aeeb79d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,7 +73,7 @@
10.2.7
3.4.1
0.19
- 24.0-android
+ 31.1-jre
2.4.6