1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-03-13 19:37:35 +01:00

Merge branch 'android' into android-phoenix

This commit is contained in:
dpad85 2020-01-21 10:35:24 +01:00
commit f005a4fdb8
No known key found for this signature in database
GPG key ID: 574C8C6A1673E987
5 changed files with 16 additions and 33 deletions

View file

@ -555,7 +555,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId
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
case Failure(t) =>
log.error(t, "")
log.error(t, s"rejecting channel with invalid funding tx: ${fundingTx.bin}")
goto(CLOSED)
}

View file

@ -253,14 +253,12 @@ object Commitments {
commitments1
}
def getHtlcCrossSigned(commitments: Commitments, directionRelativeToLocal: Direction, htlcId: Long): Option[UpdateAddHtlc] = {
val remoteSigned = commitments.localCommit.spec.htlcs.find(htlc => htlc.direction == directionRelativeToLocal && htlc.add.id == htlcId)
val localSigned = commitments.remoteNextCommitInfo.left.toOption.map(_.nextRemoteCommit).getOrElse(commitments.remoteCommit)
.spec.htlcs.find(htlc => htlc.direction == directionRelativeToLocal.opposite && htlc.add.id == htlcId)
for {
htlc_out <- remoteSigned
htlc_in <- localSigned
} yield htlc_in.add
def getHtlcCrossSigned(commitments: Commitments, directionRelativeToLocal: Direction, htlcId: Long): Option[UpdateAddHtlc] = for {
localSigned <- commitments.remoteNextCommitInfo.left.toOption.map(_.nextRemoteCommit).getOrElse(commitments.remoteCommit).spec.findHtlcById(htlcId, directionRelativeToLocal.opposite)
remoteSigned <- commitments.localCommit.spec.findHtlcById(htlcId, directionRelativeToLocal)
} yield {
require(localSigned.add == remoteSigned.add)
localSigned.add
}
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
case fail: UpdateFailHtlc =>
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)
// same as above
case fail: UpdateFailMalformedHtlc =>
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)
}
// the outgoing following htlcs have been completed (fulfilled or failed) when we received this revocation

View file

@ -509,12 +509,11 @@ object MultiPartPaymentLifecycle {
})
// 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.
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 {
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) => {
// We re-generate a split threshold for each channel to randomize the amounts.

View file

@ -32,6 +32,9 @@ case object OUT extends Direction { def opposite = IN }
case class DirectedHtlc(direction: Direction, add: UpdateAddHtlc)
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
}
@ -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
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 == IN => spec.copy(toRemote = spec.toRemote + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
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
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 == IN => spec.copy(toLocal = spec.toLocal + htlc.add.amountMsat, htlcs = spec.htlcs - htlc)
case None => throw new RuntimeException(s"cannot find htlc id=$htlcId")

View file

@ -310,23 +310,6 @@ class MultiPartPaymentLifecycleSpec extends TestKit(ActorSystem("test")) with fi
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 =>
import f._
val payment = SendMultiPartPayment(paymentHash, randomBytes32, e, 3000 * 1000 msat, expiry, 3)