1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-03-03 17:36:56 +01:00

Filter out non-standard channels from channelInfo API (#2107)

This change makes it possible for a non-standard channel to reply
with `CommandFailure` which in turn will be filtered out in `channelsInfo`.

The reason is that currently hosted channels have to return something
to make the whole API call succeed and whatever they return would
break external tools which only expect standard channel formats.
This commit is contained in:
Anton Kumaigorodski 2021-12-15 17:25:25 +02:00 committed by GitHub
parent 8ff7dc713a
commit 7e7de53d1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 16 deletions

View file

@ -94,7 +94,7 @@ trait Eclair {
def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]] def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]]
def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[RES_GETINFO] def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GETINFO]]
def peers()(implicit timeout: Timeout): Future[Iterable[PeerInfo]] def peers()(implicit timeout: Timeout): Future[Iterable[PeerInfo]]
@ -212,19 +212,22 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging {
.map(_.filter(n => nodeIds_opt.forall(_.contains(n.nodeId)))) .map(_.filter(n => nodeIds_opt.forall(_.contains(n.nodeId))))
} }
override def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]] = toRemoteNode_opt match { override def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]] = {
case Some(pk) => for { val futureResponse = toRemoteNode_opt match {
channelIds <- (appKit.register ? Symbol("channelsTo")).mapTo[Map[ByteVector32, PublicKey]].map(_.filter(_._2 == pk).keys) case Some(pk) => (appKit.register ? Symbol("channelsTo")).mapTo[Map[ByteVector32, PublicKey]].map(_.filter(_._2 == pk).keys)
channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GETINFO, RES_GETINFO](Left(channelId), CMD_GETINFO(ActorRef.noSender)))) case None => (appKit.register ? Symbol("channels")).mapTo[Map[ByteVector32, ActorRef]].map(_.keys)
} yield channels
case None => for {
channelIds <- (appKit.register ? Symbol("channels")).mapTo[Map[ByteVector32, ActorRef]].map(_.keys)
channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GETINFO, RES_GETINFO](Left(channelId), CMD_GETINFO(ActorRef.noSender))))
} yield channels
} }
override def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[RES_GETINFO] = { for {
sendToChannel[CMD_GETINFO, RES_GETINFO](channel, CMD_GETINFO(ActorRef.noSender)) channelIds <- futureResponse
channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GETINFO, CommandResponse[CMD_GETINFO]](Left(channelId), CMD_GETINFO(ActorRef.noSender))))
} yield channels.collect {
case properResponse: RES_GETINFO => properResponse
}
}
override def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GETINFO]] = {
sendToChannel[CMD_GETINFO, CommandResponse[CMD_GETINFO]](channel, CMD_GETINFO(ActorRef.noSender))
} }
override def allChannels()(implicit timeout: Timeout): Future[Iterable[ChannelDesc]] = { override def allChannels()(implicit timeout: Timeout): Future[Iterable[ChannelDesc]] = {

View file

@ -449,7 +449,7 @@ class EclairImplSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with I
assert(verifiedMessage.publicKey !== kit.nodeParams.nodeId) assert(verifiedMessage.publicKey !== kit.nodeParams.nodeId)
} }
test("get channel info (all channels)") { f => test("get channel info (filtered channels)") { f =>
import f._ import f._
val eclair = new EclairImpl(kit) val eclair = new EclairImpl(kit)
@ -468,8 +468,8 @@ class EclairImplSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with I
val c1 = register.expectMsgType[Register.Forward[CMD_GETINFO]] val c1 = register.expectMsgType[Register.Forward[CMD_GETINFO]]
register.reply(RES_GETINFO(map(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) register.reply(RES_GETINFO(map(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal))
val c2 = register.expectMsgType[Register.Forward[CMD_GETINFO]] register.expectMsgType[Register.Forward[CMD_GETINFO]]
register.reply(RES_GETINFO(map(c2.channelId), c2.channelId, NORMAL, ChannelCodecsSpec.normal)) register.reply(RES_FAILURE(CMD_GETINFO(ActorRef.noSender), new IllegalArgumentException("Non-standard channel")))
val c3 = register.expectMsgType[Register.Forward[CMD_GETINFO]] val c3 = register.expectMsgType[Register.Forward[CMD_GETINFO]]
register.reply(RES_GETINFO(map(c3.channelId), c3.channelId, NORMAL, ChannelCodecsSpec.normal)) register.reply(RES_GETINFO(map(c3.channelId), c3.channelId, NORMAL, ChannelCodecsSpec.normal))
register.expectNoMessage() register.expectNoMessage()
@ -478,7 +478,6 @@ class EclairImplSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with I
assert(res.value.get.get.toSet === Set( assert(res.value.get.get.toSet === Set(
RES_GETINFO(a, a1, NORMAL, ChannelCodecsSpec.normal), RES_GETINFO(a, a1, NORMAL, ChannelCodecsSpec.normal),
RES_GETINFO(a, a2, NORMAL, ChannelCodecsSpec.normal),
RES_GETINFO(b, b1, NORMAL, ChannelCodecsSpec.normal), RES_GETINFO(b, b1, NORMAL, ChannelCodecsSpec.normal),
)) ))
} }