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
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,14 @@ object Upstream {
object Cold {
def apply(hot: Hot): Cold = hot match {
case Local(id) => Local(id)
case Hot.Channel(add, _, _, _) => Cold.Channel(add.channelId, add.id, add.amountMsat)
case Hot.Trampoline(received) => Cold.Trampoline(received.map(r => Cold.Channel(r.add.channelId, r.add.id, r.add.amountMsat)))
case Hot.Channel(add, _, receivedFrom, _) => Cold.Channel(add.channelId, receivedFrom, add.id, add.amountMsat)
case Hot.Trampoline(received) => Cold.Trampoline(received.map(r => Cold.Channel(r.add.channelId, r.receivedFrom, r.add.id, r.add.amountMsat)))
}

/** Our node is forwarding a single incoming HTLC. */
case class Channel(originChannelId: ByteVector32, originHtlcId: Long, amountIn: MilliSatoshi) extends Cold
case class Channel(originChannelId: ByteVector32, originNodeId: PublicKey, originHtlcId: Long, amountIn: MilliSatoshi) extends Cold
object Channel {
def apply(add: UpdateAddHtlc): Channel = Channel(add.channelId, add.id, add.amountMsat)
def apply(add: UpdateAddHtlc, remoteNodeId: PublicKey): Channel = Channel(add.channelId, remoteNodeId, add.id, add.amountMsat)
}

/** Our node is forwarding a payment based on a set of HTLCs from potentially multiple upstream channels. */
Expand Down Expand Up @@ -313,7 +313,7 @@ object HtlcResult {
case object ChannelFailureBeforeSigned extends Fail
case class DisconnectedBeforeSigned(channelUpdate: ChannelUpdate) extends Fail { require(!channelUpdate.channelFlags.isEnabled, "channel update must have disabled flag set") }
}
final case class RES_ADD_SETTLED[+O <: Origin, +R <: HtlcResult](origin: O, htlc: UpdateAddHtlc, result: R) extends CommandSuccess[CMD_ADD_HTLC]
final case class RES_ADD_SETTLED[+O <: Origin, +R <: HtlcResult](origin: O, remoteNodeId: PublicKey, htlc: UpdateAddHtlc, result: R) extends CommandSuccess[CMD_ADD_HTLC]

/** other specific responses */
final case class RES_BUMP_FUNDING_FEE(rbfIndex: Int, fundingTxId: TxId, fee: Satoshi) extends CommandSuccess[CMD_BUMP_FUNDING_FEE]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import fr.acinq.eclair.channel.fsm.Channel.ChannelConf
import fr.acinq.eclair.crypto.keymanager.{ChannelKeys, LocalCommitmentKeys, RemoteCommitmentKeys}
import fr.acinq.eclair.crypto.{NonceGenerator, ShaChain}
import fr.acinq.eclair.payment.OutgoingPaymentPacket
import fr.acinq.eclair.reputation.Reputation
import fr.acinq.eclair.router.Announcements
import fr.acinq.eclair.transactions.Transactions._
import fr.acinq.eclair.transactions._
Expand Down Expand Up @@ -460,7 +459,7 @@ case class Commitment(fundingTxIndex: Long,
localCommit.spec.htlcs.collect(DirectedHtlc.incoming).filter(nearlyExpired)
}

def canSendAdd(amount: MilliSatoshi, params: ChannelParams, changes: CommitmentChanges, feeConf: OnChainFeeConf, reputationScore: Reputation.Score): Either[ChannelException, Unit] = {
def canSendAdd(amount: MilliSatoshi, params: ChannelParams, changes: CommitmentChanges, feeConf: OnChainFeeConf): Either[ChannelException, Unit] = {
// let's compute the current commitments *as seen by them* with the additional htlc
// we need to base the next current commitment on the last sig we sent, even if we didn't yet receive their revocation
val remoteCommit1 = nextRemoteCommit_opt.getOrElse(remoteCommit)
Expand Down Expand Up @@ -901,7 +900,7 @@ case class Commitments(channelParams: ChannelParams,
val changes1 = changes.addLocalProposal(add).copy(localNextHtlcId = changes.localNextHtlcId + 1)
val originChannels1 = originChannels + (add.id -> cmd.origin)
// we verify that this htlc is allowed in every active commitment
val failures = active.map(_.canSendAdd(add.amountMsat, channelParams, changes1, feeConf, cmd.reputationScore))
val failures = active.map(_.canSendAdd(add.amountMsat, channelParams, changes1, feeConf))
// and that we don't exceed the authorized channel occupancy (jamming)
.appended(cmd.reputationScore.checkIncomingChannelOccupancy(cmd.origin.upstream.incomingChannelOccupancy, channelId))
.collect { case Left(f) => f }
Expand Down Expand Up @@ -1144,12 +1143,12 @@ case class Commitments(channelParams: ChannelParams,
case fail: UpdateFailHtlc =>
val origin = originChannels(fail.id)
val add = remoteSpec.findIncomingHtlcById(fail.id).map(_.add).get
RES_ADD_SETTLED(origin, add, HtlcResult.RemoteFail(fail))
RES_ADD_SETTLED(origin, remoteNodeId, add, HtlcResult.RemoteFail(fail))
// same as above
case fail: UpdateFailMalformedHtlc =>
val origin = originChannels(fail.id)
val add = remoteSpec.findIncomingHtlcById(fail.id).map(_.add).get
RES_ADD_SETTLED(origin, add, HtlcResult.RemoteFailMalformed(fail))
RES_ADD_SETTLED(origin, remoteNodeId, add, HtlcResult.RemoteFailMalformed(fail))
}
val (acceptedHtlcs, rejectedHtlcs) = {
// the received htlcs have already been added to commitments (they've been signed by our peer), and may already
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
// We forward preimages as soon as possible to the upstream channel because it allows us to pull funds.
msg match {
case fulfill: UpdateFulfillHtlc => d.commitments.receiveFulfill(fulfill) match {
case Right((_, origin, htlc)) => relayer ! RES_ADD_SETTLED(origin, htlc, HtlcResult.RemoteFulfill(fulfill))
case Right((_, origin, htlc)) => relayer ! RES_ADD_SETTLED(origin, remoteNodeId, htlc, HtlcResult.RemoteFulfill(fulfill))
case _ => ()
}
case _ => ()
Expand Down Expand Up @@ -562,7 +562,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
d.commitments.receiveFulfill(fulfill) match {
case Right((commitments1, origin, htlc)) =>
// we forward preimages as soon as possible to the upstream channel because it allows us to pull funds
relayer ! RES_ADD_SETTLED(origin, htlc, HtlcResult.RemoteFulfill(fulfill))
relayer ! RES_ADD_SETTLED(origin, remoteNodeId, htlc, HtlcResult.RemoteFulfill(fulfill))
context.system.eventStream.publish(OutgoingHtlcFulfilled(fulfill))
log.info("OutgoingHtlcFulfilled: channelId={}, id={}", fulfill.channelId.toHex, fulfill.id)
stay() using d.copy(commitments = commitments1)
Expand Down Expand Up @@ -1562,7 +1562,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
val channelUpdate1 = Helpers.channelUpdate(nodeParams, scidForChannelUpdate(d), d.commitments, d.channelUpdate.relayFees, enable = false)
// NB: the htlcs stay in the commitments.localChange, they will be cleaned up after reconnection
d.commitments.changes.localChanges.proposed.collect {
case add: UpdateAddHtlc => relayer ! RES_ADD_SETTLED(d.commitments.originChannels(add.id), add, HtlcResult.DisconnectedBeforeSigned(channelUpdate1))
case add: UpdateAddHtlc => relayer ! RES_ADD_SETTLED(d.commitments.originChannels(add.id), remoteNodeId, add, HtlcResult.DisconnectedBeforeSigned(channelUpdate1))
}
goto(OFFLINE) using d1.copy(channelUpdate = channelUpdate1) storing()
} else {
Expand Down Expand Up @@ -1599,7 +1599,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
d.commitments.receiveFulfill(fulfill) match {
case Right((commitments1, origin, htlc)) =>
// we forward preimages as soon as possible to the upstream channel because it allows us to pull funds
relayer ! RES_ADD_SETTLED(origin, htlc, HtlcResult.RemoteFulfill(fulfill))
relayer ! RES_ADD_SETTLED(origin, remoteNodeId, htlc, HtlcResult.RemoteFulfill(fulfill))
stay() using d.copy(commitments = commitments1)
case Left(cause) => handleLocalError(cause, d, Some(fulfill))
}
Expand Down Expand Up @@ -2153,7 +2153,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
d.commitments.originChannels.get(add.id) match {
case Some(origin) =>
log.info("failing htlc #{} paymentHash={} origin={}: overridden by revoked remote commit", add.id, add.paymentHash, origin)
relayer ! RES_ADD_SETTLED(origin, add, HtlcResult.OnChainFail(HtlcOverriddenByLocalCommit(d.channelId, add)))
relayer ! RES_ADD_SETTLED(origin, remoteNodeId, add, HtlcResult.OnChainFail(HtlcOverriddenByLocalCommit(d.channelId, add)))
case None => ()
}
}
Expand All @@ -2176,7 +2176,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
d.commitments.originChannels.get(htlc.id) match {
case Some(origin) =>
log.info("fulfilling htlc #{} paymentHash={} origin={}", htlc.id, htlc.paymentHash, origin)
relayer ! RES_ADD_SETTLED(origin, htlc, HtlcResult.OnChainFulfill(preimage))
relayer ! RES_ADD_SETTLED(origin, remoteNodeId, htlc, HtlcResult.OnChainFulfill(preimage))
case None =>
// If we don't have the origin, it means that we already have forwarded the fulfill so that's not a big deal.
// This can happen if they send a signature containing the fulfill, then fail the channel before we have time to sign it.
Expand Down Expand Up @@ -2254,7 +2254,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
d.commitments.originChannels.get(add.id) match {
case Some(origin) =>
log.info("failing htlc #{} paymentHash={} origin={}: htlc timed out", add.id, add.paymentHash, origin)
relayer ! RES_ADD_SETTLED(origin, add, HtlcResult.OnChainFail(HtlcsTimedoutDownstream(d.channelId, Set(add))))
relayer ! RES_ADD_SETTLED(origin, remoteNodeId, add, HtlcResult.OnChainFail(HtlcsTimedoutDownstream(d.channelId, Set(add))))
case None =>
// same as for fulfilling the htlc (no big deal)
log.info("cannot fail timed out htlc #{} paymentHash={} (origin not found)", add.id, add.paymentHash)
Expand All @@ -2266,7 +2266,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
d.commitments.originChannels.get(add.id) match {
case Some(origin) =>
log.info("failing htlc #{} paymentHash={} origin={}: overridden by local commit", add.id, add.paymentHash, origin)
relayer ! RES_ADD_SETTLED(origin, add, HtlcResult.OnChainFail(HtlcOverriddenByLocalCommit(d.channelId, add)))
relayer ! RES_ADD_SETTLED(origin, remoteNodeId, add, HtlcResult.OnChainFail(HtlcOverriddenByLocalCommit(d.channelId, add)))
case None =>
// same as for fulfilling the htlc (no big deal)
log.info("cannot fail overridden htlc #{} paymentHash={} (origin not found)", add.id, add.paymentHash)
Expand Down Expand Up @@ -3189,7 +3189,7 @@ class Channel(val nodeParams: NodeParams, val channelKeys: ChannelKeys, val wall
nextStateData match {
case d: DATA_CLOSING =>
d.commitments.changes.localChanges.proposed.collect {
case add: UpdateAddHtlc => relayer ! RES_ADD_SETTLED(d.commitments.originChannels(add.id), add, HtlcResult.ChannelFailureBeforeSigned)
case add: UpdateAddHtlc => relayer ! RES_ADD_SETTLED(d.commitments.originChannels(add.id), remoteNodeId, add, HtlcResult.ChannelFailureBeforeSigned)
}
case _ => ()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class DbEventHandler(nodeParams: NodeParams) extends Actor with DiagnosticActorL
PaymentMetrics.PaymentFees.withTag(PaymentTags.Direction, PaymentTags.Directions.Sent).record(e.feesPaid.truncateToSatoshi.toLong)
PaymentMetrics.PaymentParts.withTag(PaymentTags.Direction, PaymentTags.Directions.Sent).record(e.parts.length)
auditDb.add(e)
e.parts.foreach(p => channelsDb.updateChannelMeta(p.toChannelId, ChannelEvent.EventType.PaymentSent))
e.parts.foreach(p => channelsDb.updateChannelMeta(p.channelId, ChannelEvent.EventType.PaymentSent))

case _: PaymentFailed =>
PaymentMetrics.PaymentFailed.withTag(PaymentTags.Direction, PaymentTags.Directions.Sent).increment()
Expand All @@ -72,7 +72,7 @@ class DbEventHandler(nodeParams: NodeParams) extends Actor with DiagnosticActorL
PaymentMetrics.PaymentAmount.withTag(PaymentTags.Direction, PaymentTags.Directions.Received).record(e.amount.truncateToSatoshi.toLong)
PaymentMetrics.PaymentParts.withTag(PaymentTags.Direction, PaymentTags.Directions.Received).record(e.parts.length)
auditDb.add(e)
e.parts.foreach(p => channelsDb.updateChannelMeta(p.fromChannelId, ChannelEvent.EventType.PaymentReceived))
e.parts.foreach(p => channelsDb.updateChannelMeta(p.channelId, ChannelEvent.EventType.PaymentReceived))

case e: PaymentRelayed =>
PaymentMetrics.PaymentAmount
Expand All @@ -89,9 +89,9 @@ class DbEventHandler(nodeParams: NodeParams) extends Actor with DiagnosticActorL
PaymentMetrics.PaymentParts.withTag(PaymentTags.Direction, PaymentTags.Directions.Sent).record(outgoing.length)
incoming.foreach(p => channelsDb.updateChannelMeta(p.channelId, ChannelEvent.EventType.PaymentReceived))
outgoing.foreach(p => channelsDb.updateChannelMeta(p.channelId, ChannelEvent.EventType.PaymentSent))
case ChannelPaymentRelayed(_, _, _, fromChannelId, toChannelId, _, _) =>
channelsDb.updateChannelMeta(fromChannelId, ChannelEvent.EventType.PaymentReceived)
channelsDb.updateChannelMeta(toChannelId, ChannelEvent.EventType.PaymentSent)
case ChannelPaymentRelayed(_, incoming, outgoing) =>
channelsDb.updateChannelMeta(incoming.channelId, ChannelEvent.EventType.PaymentReceived)
channelsDb.updateChannelMeta(outgoing.channelId, ChannelEvent.EventType.PaymentSent)
case OnTheFlyFundingPaymentRelayed(_, incoming, outgoing) =>
incoming.foreach(p => channelsDb.updateChannelMeta(p.channelId, ChannelEvent.EventType.PaymentReceived))
outgoing.foreach(p => channelsDb.updateChannelMeta(p.channelId, ChannelEvent.EventType.PaymentSent))
Expand Down
Loading