mirror of
https://github.com/ACINQ/eclair.git
synced 2025-03-15 04:11:33 +01:00
Merge branch 'android' into android-phoenix
This commit is contained in:
commit
f005a4fdb8
5 changed files with 16 additions and 33 deletions
|
@ -555,7 +555,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId
|
||||||
val shortChannelId = ShortChannelId(blockHeight, txIndex, commitments.commitInput.outPoint.index.toInt)
|
val shortChannelId = ShortChannelId(blockHeight, txIndex, commitments.commitInput.outPoint.index.toInt)
|
||||||
goto(WAIT_FOR_FUNDING_LOCKED) using DATA_WAIT_FOR_FUNDING_LOCKED(commitments, shortChannelId, fundingLocked) storing() sending fundingLocked
|
goto(WAIT_FOR_FUNDING_LOCKED) using DATA_WAIT_FOR_FUNDING_LOCKED(commitments, shortChannelId, fundingLocked) storing() sending fundingLocked
|
||||||
case Failure(t) =>
|
case Failure(t) =>
|
||||||
log.error(t, "")
|
log.error(t, s"rejecting channel with invalid funding tx: ${fundingTx.bin}")
|
||||||
goto(CLOSED)
|
goto(CLOSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -253,14 +253,12 @@ object Commitments {
|
||||||
commitments1
|
commitments1
|
||||||
}
|
}
|
||||||
|
|
||||||
def getHtlcCrossSigned(commitments: Commitments, directionRelativeToLocal: Direction, htlcId: Long): Option[UpdateAddHtlc] = {
|
def getHtlcCrossSigned(commitments: Commitments, directionRelativeToLocal: Direction, htlcId: Long): Option[UpdateAddHtlc] = for {
|
||||||
val remoteSigned = commitments.localCommit.spec.htlcs.find(htlc => htlc.direction == directionRelativeToLocal && htlc.add.id == htlcId)
|
localSigned <- commitments.remoteNextCommitInfo.left.toOption.map(_.nextRemoteCommit).getOrElse(commitments.remoteCommit).spec.findHtlcById(htlcId, directionRelativeToLocal.opposite)
|
||||||
val localSigned = commitments.remoteNextCommitInfo.left.toOption.map(_.nextRemoteCommit).getOrElse(commitments.remoteCommit)
|
remoteSigned <- commitments.localCommit.spec.findHtlcById(htlcId, directionRelativeToLocal)
|
||||||
.spec.htlcs.find(htlc => htlc.direction == directionRelativeToLocal.opposite && htlc.add.id == htlcId)
|
} yield {
|
||||||
for {
|
require(localSigned.add == remoteSigned.add)
|
||||||
htlc_out <- remoteSigned
|
localSigned.add
|
||||||
htlc_in <- localSigned
|
|
||||||
} yield htlc_in.add
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def sendFulfill(commitments: Commitments, cmd: CMD_FULFILL_HTLC): (Commitments, UpdateFulfillHtlc) =
|
def sendFulfill(commitments: Commitments, cmd: CMD_FULFILL_HTLC): (Commitments, UpdateFulfillHtlc) =
|
||||||
|
@ -534,12 +532,12 @@ object Commitments {
|
||||||
// same for fails: we need to make sure that they are in neither commitment before propagating the fail upstream
|
// same for fails: we need to make sure that they are in neither commitment before propagating the fail upstream
|
||||||
case fail: UpdateFailHtlc =>
|
case fail: UpdateFailHtlc =>
|
||||||
val origin = commitments.originChannels(fail.id)
|
val origin = commitments.originChannels(fail.id)
|
||||||
val add = commitments.remoteCommit.spec.htlcs.find(p => p.direction == IN && p.add.id == fail.id).map(_.add).get
|
val add = commitments.remoteCommit.spec.findHtlcById(fail.id, IN).map(_.add).get
|
||||||
Relayer.ForwardFail(fail, origin, add)
|
Relayer.ForwardFail(fail, origin, add)
|
||||||
// same as above
|
// same as above
|
||||||
case fail: UpdateFailMalformedHtlc =>
|
case fail: UpdateFailMalformedHtlc =>
|
||||||
val origin = commitments.originChannels(fail.id)
|
val origin = commitments.originChannels(fail.id)
|
||||||
val add = commitments.remoteCommit.spec.htlcs.find(p => p.direction == IN && p.add.id == fail.id).map(_.add).get
|
val add = commitments.remoteCommit.spec.findHtlcById(fail.id, IN).map(_.add).get
|
||||||
Relayer.ForwardFailMalformed(fail, origin, add)
|
Relayer.ForwardFailMalformed(fail, origin, add)
|
||||||
}
|
}
|
||||||
// the outgoing following htlcs have been completed (fulfilled or failed) when we received this revocation
|
// the outgoing following htlcs have been completed (fulfilled or failed) when we received this revocation
|
||||||
|
|
|
@ -509,12 +509,11 @@ object MultiPartPaymentLifecycle {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Otherwise we need to split the amount based on network statistics and pessimistic fees estimates.
|
// Otherwise we need to split the amount based on network statistics and pessimistic fees estimates.
|
||||||
// We filter out unannounced channels: they are very likely leading to a non-routing node.
|
|
||||||
// Note that this will be handled more gracefully once this logic is migrated inside the router.
|
// Note that this will be handled more gracefully once this logic is migrated inside the router.
|
||||||
val channels = if (randomize) {
|
val channels = if (randomize) {
|
||||||
Random.shuffle(localChannels.filter(p => p.commitments.announceChannel && p.nextNodeId != request.targetNodeId))
|
Random.shuffle(localChannels.filter(p => p.nextNodeId != request.targetNodeId))
|
||||||
} else {
|
} else {
|
||||||
localChannels.filter(p => p.commitments.announceChannel && p.nextNodeId != request.targetNodeId).sortBy(_.commitments.availableBalanceForSend)
|
localChannels.filter(p => p.nextNodeId != request.targetNodeId).sortBy(_.commitments.availableBalanceForSend)
|
||||||
}
|
}
|
||||||
val remotePayments = split(toSend - directPayments.map(_.finalPayload.amount).sum, Seq.empty, channels, (remaining: MilliSatoshi, channel: OutgoingChannel) => {
|
val remotePayments = split(toSend - directPayments.map(_.finalPayload.amount).sum, Seq.empty, channels, (remaining: MilliSatoshi, channel: OutgoingChannel) => {
|
||||||
// We re-generate a split threshold for each channel to randomize the amounts.
|
// We re-generate a split threshold for each channel to randomize the amounts.
|
||||||
|
|
|
@ -32,6 +32,9 @@ case object OUT extends Direction { def opposite = IN }
|
||||||
case class DirectedHtlc(direction: Direction, add: UpdateAddHtlc)
|
case class DirectedHtlc(direction: Direction, add: UpdateAddHtlc)
|
||||||
|
|
||||||
final case class CommitmentSpec(htlcs: Set[DirectedHtlc], feeratePerKw: Long, toLocal: MilliSatoshi, toRemote: MilliSatoshi) {
|
final case class CommitmentSpec(htlcs: Set[DirectedHtlc], feeratePerKw: Long, toLocal: MilliSatoshi, toRemote: MilliSatoshi) {
|
||||||
|
|
||||||
|
def findHtlcById(id: Long, direction: Direction): Option[DirectedHtlc] = htlcs.find(htlc => htlc.add.id == id && htlc.direction == direction)
|
||||||
|
|
||||||
val totalFunds = toLocal + toRemote + htlcs.toSeq.map(_.add.amountMsat).sum
|
val totalFunds = toLocal + toRemote + htlcs.toSeq.map(_.add.amountMsat).sum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ object CommitmentSpec {
|
||||||
|
|
||||||
// OUT means we are sending an UpdateFulfillHtlc message which means that we are fulfilling an HTLC that they sent
|
// OUT means we are sending an UpdateFulfillHtlc message which means that we are fulfilling an HTLC that they sent
|
||||||
def fulfillHtlc(spec: CommitmentSpec, direction: Direction, htlcId: Long): CommitmentSpec = {
|
def fulfillHtlc(spec: CommitmentSpec, direction: Direction, htlcId: Long): CommitmentSpec = {
|
||||||
spec.htlcs.find(htlc => htlc.direction != direction && htlc.add.id == htlcId) match {
|
spec.findHtlcById(htlcId, direction.opposite) match {
|
||||||
case Some(htlc) if direction == OUT => spec.copy(toLocal = spec.toLocal + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
case Some(htlc) if direction == OUT => spec.copy(toLocal = spec.toLocal + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
||||||
case Some(htlc) if direction == IN => spec.copy(toRemote = spec.toRemote + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
case Some(htlc) if direction == IN => spec.copy(toRemote = spec.toRemote + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
||||||
case None => throw new RuntimeException(s"cannot find htlc id=$htlcId")
|
case None => throw new RuntimeException(s"cannot find htlc id=$htlcId")
|
||||||
|
@ -60,7 +63,7 @@ object CommitmentSpec {
|
||||||
|
|
||||||
// OUT means we are sending an UpdateFailHtlc message which means that we are failing an HTLC that they sent
|
// OUT means we are sending an UpdateFailHtlc message which means that we are failing an HTLC that they sent
|
||||||
def failHtlc(spec: CommitmentSpec, direction: Direction, htlcId: Long): CommitmentSpec = {
|
def failHtlc(spec: CommitmentSpec, direction: Direction, htlcId: Long): CommitmentSpec = {
|
||||||
spec.htlcs.find(htlc => htlc.direction != direction && htlc.add.id == htlcId) match {
|
spec.findHtlcById(htlcId, direction.opposite) match {
|
||||||
case Some(htlc) if direction == OUT => spec.copy(toRemote = spec.toRemote + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
case Some(htlc) if direction == OUT => spec.copy(toRemote = spec.toRemote + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
||||||
case Some(htlc) if direction == IN => spec.copy(toLocal = spec.toLocal + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
case Some(htlc) if direction == IN => spec.copy(toLocal = spec.toLocal + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
|
||||||
case None => throw new RuntimeException(s"cannot find htlc id=$htlcId")
|
case None => throw new RuntimeException(s"cannot find htlc id=$htlcId")
|
||||||
|
|
|
@ -310,23 +310,6 @@ class MultiPartPaymentLifecycleSpec extends TestKit(ActorSystem("test")) with fi
|
||||||
assert(result.amount === payment.totalAmount)
|
assert(result.amount === payment.totalAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("skip unannounced channels when sending to remote node") { f =>
|
|
||||||
import f._
|
|
||||||
|
|
||||||
// The channels to b are not announced: they should be ignored so the payment should fail.
|
|
||||||
val channels = OutgoingChannels(Seq(
|
|
||||||
OutgoingChannel(b, channelUpdate_ab_1.copy(channelFlags = ChannelFlags.Empty), makeCommitments(1000 * 1000 msat, 10, announceChannel = false)),
|
|
||||||
OutgoingChannel(b, channelUpdate_ab_2.copy(channelFlags = ChannelFlags.Empty), makeCommitments(1500 * 1000 msat, 10, announceChannel = false)),
|
|
||||||
OutgoingChannel(c, channelUpdate_ac_1, makeCommitments(500 * 1000 msat, 10))
|
|
||||||
))
|
|
||||||
val payment = SendMultiPartPayment(paymentHash, randomBytes32, e, 1200 * 1000 msat, expiry, 3)
|
|
||||||
initPayment(f, payment, emptyStats.copy(capacity = Stats(Seq(1000), d => Satoshi(d.toLong))), channels)
|
|
||||||
|
|
||||||
val result = sender.expectMsgType[PaymentFailed]
|
|
||||||
assert(result.id === paymentId)
|
|
||||||
assert(result.paymentHash === paymentHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
test("retry after error") { f =>
|
test("retry after error") { f =>
|
||||||
import f._
|
import f._
|
||||||
val payment = SendMultiPartPayment(paymentHash, randomBytes32, e, 3000 * 1000 msat, expiry, 3)
|
val payment = SendMultiPartPayment(paymentHash, randomBytes32, e, 3000 * 1000 msat, expiry, 3)
|
||||||
|
|
Loading…
Add table
Reference in a new issue