Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ trait Eclair {

def updateRelayFee(nodes: List[PublicKey], feeBase: MilliSatoshi, feeProportionalMillionths: Long)(implicit timeout: Timeout): Future[Map[ApiTypes.ChannelIdentifier, Either[Throwable, CommandResponse[CMD_UPDATE_RELAY_FEE]]]]

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_GET_CHANNEL_INFO]]

def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GETINFO]]
def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GET_CHANNEL_INFO]]

def peers()(implicit timeout: Timeout): Future[Iterable[PeerInfo]]

Expand Down Expand Up @@ -216,22 +216,22 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging {
.map(_.filter(n => nodeIds_opt.forall(_.contains(n.nodeId))))
}

override def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]] = {
override def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GET_CHANNEL_INFO]] = {
val futureResponse = toRemoteNode_opt match {
case Some(pk) => (appKit.register ? Symbol("channelsTo")).mapTo[Map[ByteVector32, PublicKey]].map(_.filter(_._2 == pk).keys)
case None => (appKit.register ? Symbol("channels")).mapTo[Map[ByteVector32, ActorRef]].map(_.keys)
}

for {
channelIds <- futureResponse
channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GETINFO, CommandResponse[CMD_GETINFO]](Left(channelId), CMD_GETINFO(ActorRef.noSender))))
channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GET_CHANNEL_INFO, CommandResponse[CMD_GET_CHANNEL_INFO]](Left(channelId), CMD_GET_CHANNEL_INFO(ActorRef.noSender))))
} yield channels.collect {
case properResponse: RES_GETINFO => properResponse
case properResponse: RES_GET_CHANNEL_INFO => 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 channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GET_CHANNEL_INFO]] = {
sendToChannel[CMD_GET_CHANNEL_INFO, CommandResponse[CMD_GET_CHANNEL_INFO]](channel, CMD_GET_CHANNEL_INFO(ActorRef.noSender))
}

override def allChannels()(implicit timeout: Timeout): Future[Iterable[ChannelDesc]] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import fr.acinq.eclair.balance.CheckBalance.GlobalBalance
import fr.acinq.eclair.balance.Monitoring.{Metrics, Tags}
import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinCoreClient
import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinCoreClient.Utxo
import fr.acinq.eclair.channel.HasCommitments
import fr.acinq.eclair.channel.PersistentChannelData
import fr.acinq.eclair.db.Databases
import grizzled.slf4j.Logger
import org.json4s.JsonAST.JInt
Expand All @@ -25,7 +25,7 @@ object BalanceActor {
// @formatter:off
sealed trait Command
private final case object TickBalance extends Command
final case class GetGlobalBalance(replyTo: ActorRef[Try[GlobalBalance]], channels: Map[ByteVector32, HasCommitments]) extends Command
final case class GetGlobalBalance(replyTo: ActorRef[Try[GlobalBalance]], channels: Map[ByteVector32, PersistentChannelData]) extends Command
private final case class WrappedChannels(wrapped: ChannelsListener.GetChannelsResponse) extends Command
private final case class WrappedGlobalBalanceWithChannels(wrapped: Try[GlobalBalance], channelsCount: Int) extends Command
private final case class WrappedUtxoInfo(wrapped: Try[UtxoInfo]) extends Command
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
import fr.acinq.bitcoin.scalacompat.ByteVector32
import fr.acinq.eclair.balance.ChannelsListener._
import fr.acinq.eclair.channel.Helpers.Closing
import fr.acinq.eclair.channel.{ChannelPersisted, ChannelRestored, HasCommitments}
import fr.acinq.eclair.channel.{ChannelPersisted, ChannelRestored, PersistentChannelData}

import scala.concurrent.Promise
import scala.concurrent.duration.DurationInt
Expand All @@ -18,14 +18,14 @@ object ChannelsListener {

// @formatter:off
sealed trait Command
private final case class ChannelData(channelId: ByteVector32, channel: akka.actor.ActorRef, data: HasCommitments) extends Command
private final case class ChannelData(channelId: ByteVector32, channel: akka.actor.ActorRef, data: PersistentChannelData) extends Command
private final case class ChannelDied(channelId: ByteVector32) extends Command
final case class GetChannels(replyTo: typed.ActorRef[GetChannelsResponse]) extends Command
final case object SendDummyEvent extends Command
final case object DummyEvent extends Command
// @formatter:on

case class GetChannelsResponse(channels: Map[ByteVector32, HasCommitments])
case class GetChannelsResponse(channels: Map[ByteVector32, PersistentChannelData])

def apply(ready: Promise[Done]): Behavior[Command] =
Behaviors.setup { context =>
Expand Down Expand Up @@ -55,7 +55,7 @@ private class ChannelsListener(context: ActorContext[Command]) {

private val log = context.log

def running(channels: Map[ByteVector32, HasCommitments]): Behavior[Command] =
def running(channels: Map[ByteVector32, PersistentChannelData]): Behavior[Command] =
Behaviors.receiveMessage {
case ChannelData(channelId, channel, data) =>
Closing.isClosed(data, additionalConfirmedTx_opt = None) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ object CheckBalance {
* - In the other cases, we simply take our local amount
* - TODO?: we disregard anchor outputs
*/
def computeOffChainBalance(channels: Iterable[HasCommitments], knownPreimages: Set[(ByteVector32, Long)]): OffChainBalance = {
def computeOffChainBalance(channels: Iterable[PersistentChannelData], knownPreimages: Set[(ByteVector32, Long)]): OffChainBalance = {
channels
.foldLeft(OffChainBalance()) {
case (r, d: DATA_WAIT_FOR_FUNDING_CONFIRMED) => r.modify(_.waitForFundingConfirmed).using(updateMainBalance(d.commitments.localCommit))
Expand Down Expand Up @@ -293,7 +293,7 @@ object CheckBalance {
val total: Btc = onChain.total + offChain.total
}

def computeGlobalBalance(channels: Map[ByteVector32, HasCommitments], db: Databases, bitcoinClient: BitcoinCoreClient)(implicit ec: ExecutionContext): Future[GlobalBalance] = for {
def computeGlobalBalance(channels: Map[ByteVector32, PersistentChannelData], db: Databases, bitcoinClient: BitcoinCoreClient)(implicit ec: ExecutionContext): Future[GlobalBalance] = for {
onChain <- CheckBalance.computeOnChainBalance(bitcoinClient)
knownPreimages = db.pendingCommands.listSettlementCommands().collect { case (channelId, cmd: CMD_FULFILL_HTLC) => (channelId, cmd.id) }.toSet
offChainRaw = CheckBalance.computeOffChainBalance(channels.values, knownPreimages)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ case object CLOSED extends ChannelState
case object OFFLINE extends ChannelState
case object SYNCING extends ChannelState
case object WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT extends ChannelState
case object ERR_FUNDING_LOST extends ChannelState
case object ERR_INFORMATION_LEAK extends ChannelState

/*
Expand Down Expand Up @@ -96,7 +95,7 @@ case class INPUT_INIT_FUNDEE(temporaryChannelId: ByteVector32,
case object INPUT_CLOSE_COMPLETE_TIMEOUT // when requesting a mutual close, we wait for as much as this timeout, then unilateral close
case object INPUT_DISCONNECTED
case class INPUT_RECONNECTED(remote: ActorRef, localInit: Init, remoteInit: Init)
case class INPUT_RESTORED(data: HasCommitments)
case class INPUT_RESTORED(data: PersistentChannelData)

/*
.d8888b. .d88888b. 888b d888 888b d888 d8888 888b 888 8888888b. .d8888b.
Expand Down Expand Up @@ -179,9 +178,9 @@ sealed trait CloseCommand extends HasReplyToCommand
final case class CMD_CLOSE(replyTo: ActorRef, scriptPubKey: Option[ByteVector], feerates: Option[ClosingFeerates]) extends CloseCommand
final case class CMD_FORCECLOSE(replyTo: ActorRef) extends CloseCommand
final case class CMD_UPDATE_RELAY_FEE(replyTo: ActorRef, feeBase: MilliSatoshi, feeProportionalMillionths: Long, cltvExpiryDelta_opt: Option[CltvExpiryDelta]) extends HasReplyToCommand
final case class CMD_GETSTATE(replyTo: ActorRef) extends HasReplyToCommand
final case class CMD_GETSTATEDATA(replyTo: ActorRef) extends HasReplyToCommand
final case class CMD_GETINFO(replyTo: ActorRef)extends HasReplyToCommand
final case class CMD_GET_CHANNEL_STATE(replyTo: ActorRef) extends HasReplyToCommand
final case class CMD_GET_CHANNEL_DATA(replyTo: ActorRef) extends HasReplyToCommand
final case class CMD_GET_CHANNEL_INFO(replyTo: ActorRef)extends HasReplyToCommand

/*
88888888b. 8888888888 .d8888b. 88888888b. ,ad8888ba, 888b 88 .d8888b. 8888888888 .d8888b.
Expand Down Expand Up @@ -225,9 +224,9 @@ object HtlcResult {
final case class RES_ADD_SETTLED[+O <: Origin, +R <: HtlcResult](origin: O, htlc: UpdateAddHtlc, result: R) extends CommandSuccess[CMD_ADD_HTLC]

/** other specific responses */
final case class RES_GETSTATE[+S <: ChannelState](state: S) extends CommandSuccess[CMD_GETSTATE]
final case class RES_GETSTATEDATA[+D <: ChannelData](data: D) extends CommandSuccess[CMD_GETSTATEDATA]
final case class RES_GETINFO(nodeId: PublicKey, channelId: ByteVector32, state: ChannelState, data: ChannelData) extends CommandSuccess[CMD_GETINFO]
final case class RES_GET_CHANNEL_STATE(state: ChannelState) extends CommandSuccess[CMD_GET_CHANNEL_STATE]
final case class RES_GET_CHANNEL_DATA[+D <: ChannelData](data: D) extends CommandSuccess[CMD_GET_CHANNEL_DATA]
final case class RES_GET_CHANNEL_INFO(nodeId: PublicKey, channelId: ByteVector32, state: ChannelState, data: ChannelData) extends CommandSuccess[CMD_GET_CHANNEL_INFO]

/**
* Those are not response to [[Command]], but to [[fr.acinq.eclair.io.Peer.OpenChannel]]
Expand All @@ -252,19 +251,6 @@ object ChannelOpenResponse {
8888888P" d88P 888 888 d88P 888
*/

sealed trait ChannelData extends PossiblyHarmful {
def channelId: ByteVector32
}

case object Nothing extends ChannelData {
val channelId: ByteVector32 = ByteVector32.Zeroes
}

sealed trait HasCommitments extends ChannelData {
val channelId: ByteVector32 = commitments.channelId
def commitments: Commitments
}

case class ClosingTxProposed(unsignedTx: ClosingTx, localClosingSigned: ClosingSigned)

sealed trait CommitPublished {
Expand Down Expand Up @@ -375,10 +361,25 @@ case class RevokedCommitPublished(commitTx: Transaction, claimMainOutputTx: Opti
}
}

final case class DATA_WAIT_FOR_OPEN_CHANNEL(initFundee: INPUT_INIT_FUNDEE) extends ChannelData {
sealed trait ChannelData extends PossiblyHarmful {
def channelId: ByteVector32
}

sealed trait TransientChannelData extends ChannelData

case object Nothing extends TransientChannelData {
val channelId: ByteVector32 = ByteVector32.Zeroes
}

sealed trait PersistentChannelData extends ChannelData {
val channelId: ByteVector32 = commitments.channelId
def commitments: Commitments
}

final case class DATA_WAIT_FOR_OPEN_CHANNEL(initFundee: INPUT_INIT_FUNDEE) extends TransientChannelData {
val channelId: ByteVector32 = initFundee.temporaryChannelId
}
final case class DATA_WAIT_FOR_ACCEPT_CHANNEL(initFunder: INPUT_INIT_FUNDER, lastSent: OpenChannel) extends ChannelData {
final case class DATA_WAIT_FOR_ACCEPT_CHANNEL(initFunder: INPUT_INIT_FUNDER, lastSent: OpenChannel) extends TransientChannelData {
val channelId: ByteVector32 = initFunder.temporaryChannelId
}
final case class DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId: ByteVector32,
Expand All @@ -390,7 +391,7 @@ final case class DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId: ByteVector32
remoteFirstPerCommitmentPoint: PublicKey,
channelConfig: ChannelConfig,
channelFeatures: ChannelFeatures,
lastSent: OpenChannel) extends ChannelData {
lastSent: OpenChannel) extends TransientChannelData {
val channelId: ByteVector32 = temporaryChannelId
}
final case class DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId: ByteVector32,
Expand All @@ -403,7 +404,7 @@ final case class DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId: ByteVector32,
channelFlags: ChannelFlags,
channelConfig: ChannelConfig,
channelFeatures: ChannelFeatures,
lastSent: AcceptChannel) extends ChannelData {
lastSent: AcceptChannel) extends TransientChannelData {
val channelId: ByteVector32 = temporaryChannelId
}
final case class DATA_WAIT_FOR_FUNDING_SIGNED(channelId: ByteVector32,
Expand All @@ -417,26 +418,26 @@ final case class DATA_WAIT_FOR_FUNDING_SIGNED(channelId: ByteVector32,
channelFlags: ChannelFlags,
channelConfig: ChannelConfig,
channelFeatures: ChannelFeatures,
lastSent: FundingCreated) extends ChannelData
lastSent: FundingCreated) extends TransientChannelData
final case class DATA_WAIT_FOR_FUNDING_CONFIRMED(commitments: Commitments,
fundingTx: Option[Transaction],
waitingSince: BlockHeight, // how long have we been waiting for the funding tx to confirm
deferred: Option[FundingLocked],
lastSent: Either[FundingCreated, FundingSigned]) extends ChannelData with HasCommitments
final case class DATA_WAIT_FOR_FUNDING_LOCKED(commitments: Commitments, shortChannelId: ShortChannelId, lastSent: FundingLocked) extends ChannelData with HasCommitments
lastSent: Either[FundingCreated, FundingSigned]) extends PersistentChannelData
final case class DATA_WAIT_FOR_FUNDING_LOCKED(commitments: Commitments, shortChannelId: ShortChannelId, lastSent: FundingLocked) extends PersistentChannelData
final case class DATA_NORMAL(commitments: Commitments,
shortChannelId: ShortChannelId,
buried: Boolean,
channelAnnouncement: Option[ChannelAnnouncement],
channelUpdate: ChannelUpdate,
localShutdown: Option[Shutdown],
remoteShutdown: Option[Shutdown],
closingFeerates: Option[ClosingFeerates]) extends ChannelData with HasCommitments
final case class DATA_SHUTDOWN(commitments: Commitments, localShutdown: Shutdown, remoteShutdown: Shutdown, closingFeerates: Option[ClosingFeerates]) extends ChannelData with HasCommitments
closingFeerates: Option[ClosingFeerates]) extends PersistentChannelData
final case class DATA_SHUTDOWN(commitments: Commitments, localShutdown: Shutdown, remoteShutdown: Shutdown, closingFeerates: Option[ClosingFeerates]) extends PersistentChannelData
final case class DATA_NEGOTIATING(commitments: Commitments,
localShutdown: Shutdown, remoteShutdown: Shutdown,
closingTxProposed: List[List[ClosingTxProposed]], // one list for every negotiation (there can be several in case of disconnection)
bestUnpublishedClosingTx_opt: Option[ClosingTx]) extends ChannelData with HasCommitments {
bestUnpublishedClosingTx_opt: Option[ClosingTx]) extends PersistentChannelData {
require(closingTxProposed.nonEmpty, "there must always be a list for the current negotiation")
require(!commitments.localParams.isFunder || closingTxProposed.forall(_.nonEmpty), "funder must have at least one closing signature for every negotiation attempt because it initiates the closing")
}
Expand All @@ -449,12 +450,12 @@ final case class DATA_CLOSING(commitments: Commitments,
remoteCommitPublished: Option[RemoteCommitPublished] = None,
nextRemoteCommitPublished: Option[RemoteCommitPublished] = None,
futureRemoteCommitPublished: Option[RemoteCommitPublished] = None,
revokedCommitPublished: List[RevokedCommitPublished] = Nil) extends ChannelData with HasCommitments {
revokedCommitPublished: List[RevokedCommitPublished] = Nil) extends PersistentChannelData {
val spendingTxs: List[Transaction] = mutualClosePublished.map(_.tx) ::: localCommitPublished.map(_.commitTx).toList ::: remoteCommitPublished.map(_.commitTx).toList ::: nextRemoteCommitPublished.map(_.commitTx).toList ::: futureRemoteCommitPublished.map(_.commitTx).toList ::: revokedCommitPublished.map(_.commitTx)
require(spendingTxs.nonEmpty, "there must be at least one tx published in this state")
}

final case class DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(commitments: Commitments, remoteChannelReestablish: ChannelReestablish) extends ChannelData with HasCommitments
final case class DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(commitments: Commitments, remoteChannelReestablish: ChannelReestablish) extends PersistentChannelData

/**
* @param initFeatures current connection features, or last features used if the channel is disconnected. Note that these
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ trait AbstractChannelRestored extends ChannelEvent {
val remoteNodeId: PublicKey
}

case class ChannelRestored(channel: ActorRef, channelId: ByteVector32, peer: ActorRef, remoteNodeId: PublicKey, data: HasCommitments) extends AbstractChannelRestored
case class ChannelRestored(channel: ActorRef, channelId: ByteVector32, peer: ActorRef, remoteNodeId: PublicKey, data: PersistentChannelData) extends AbstractChannelRestored

case class ChannelIdAssigned(channel: ActorRef, remoteNodeId: PublicKey, temporaryChannelId: ByteVector32, channelId: ByteVector32) extends ChannelEvent

Expand All @@ -58,7 +58,7 @@ case class ChannelSignatureSent(channel: ActorRef, commitments: Commitments) ext

case class ChannelSignatureReceived(channel: ActorRef, commitments: Commitments) extends ChannelEvent

case class ChannelErrorOccurred(channel: ActorRef, channelId: ByteVector32, remoteNodeId: PublicKey, data: ChannelData, error: ChannelOpenError, isFatal: Boolean) extends ChannelEvent
case class ChannelErrorOccurred(channel: ActorRef, channelId: ByteVector32, remoteNodeId: PublicKey, error: ChannelOpenError, isFatal: Boolean) extends ChannelEvent

// NB: the fee should be set to 0 when we're not paying it.
case class TransactionPublished(channelId: ByteVector32, remoteNodeId: PublicKey, tx: Transaction, miningFee: Satoshi, desc: String) extends ChannelEvent
Expand All @@ -68,7 +68,7 @@ case class TransactionConfirmed(channelId: ByteVector32, remoteNodeId: PublicKey
// NB: this event is only sent when the channel is available.
case class AvailableBalanceChanged(channel: ActorRef, channelId: ByteVector32, shortChannelId: ShortChannelId, commitments: AbstractCommitments) extends ChannelEvent

case class ChannelPersisted(channel: ActorRef, remoteNodeId: PublicKey, channelId: ByteVector32, data: HasCommitments) extends ChannelEvent
case class ChannelPersisted(channel: ActorRef, remoteNodeId: PublicKey, channelId: ByteVector32, data: PersistentChannelData) extends ChannelEvent

case class LocalCommitConfirmed(channel: ActorRef, remoteNodeId: PublicKey, channelId: ByteVector32, refundAtBlock: BlockHeight) extends ChannelEvent

Expand Down
Loading