@@ -5,6 +5,7 @@ import fr.acinq.bitcoin.io.ByteArrayInput
55import fr.acinq.bitcoin.io.ByteArrayOutput
66import fr.acinq.bitcoin.io.Output
77import fr.acinq.lightning.CltvExpiry
8+ import fr.acinq.lightning.CltvExpiryDelta
89import fr.acinq.lightning.MilliSatoshi
910import fr.acinq.lightning.utils.toByteVector32
1011
@@ -41,10 +42,8 @@ sealed class FailureMessage {
4142 UnknownNextPeer .code -> UnknownNextPeer
4243 AmountBelowMinimum .code -> AmountBelowMinimum (MilliSatoshi (LightningCodecs .u64(stream)), readChannelUpdate(stream))
4344 FeeInsufficient .code -> FeeInsufficient (MilliSatoshi (LightningCodecs .u64(stream)), readChannelUpdate(stream))
44- TrampolineFeeInsufficient .code -> TrampolineFeeInsufficient
4545 IncorrectCltvExpiry .code -> IncorrectCltvExpiry (CltvExpiry (LightningCodecs .u32(stream).toLong()), readChannelUpdate(stream))
4646 ExpiryTooSoon .code -> ExpiryTooSoon (readChannelUpdate(stream))
47- TrampolineExpiryTooSoon .code -> TrampolineExpiryTooSoon
4847 IncorrectOrUnknownPaymentDetails .code -> {
4948 val amount = if (stream.availableBytes > 0 ) MilliSatoshi (LightningCodecs .u64(stream)) else MilliSatoshi (0 )
5049 val blockHeight = if (stream.availableBytes > 0 ) LightningCodecs .u32(stream).toLong() else 0L
@@ -56,6 +55,9 @@ sealed class FailureMessage {
5655 ExpiryTooFar .code -> ExpiryTooFar
5756 InvalidOnionPayload .code -> InvalidOnionPayload (LightningCodecs .bigSize(stream), LightningCodecs .u16(stream))
5857 PaymentTimeout .code -> PaymentTimeout
58+ TemporaryTrampolineFailure .code -> TemporaryTrampolineFailure
59+ TrampolineFeeOrExpiryInsufficient .code -> TrampolineFeeOrExpiryInsufficient (MilliSatoshi (LightningCodecs .u32(stream).toLong()), LightningCodecs .u32(stream), CltvExpiryDelta (LightningCodecs .u16(stream)))
60+ UnknownNextTrampoline .code -> UnknownNextTrampoline
5961 else -> UnknownFailureMessage (code)
6062 }
6163 }
@@ -90,13 +92,11 @@ sealed class FailureMessage {
9092 LightningCodecs .writeU64(input.amount.toLong(), out )
9193 writeChannelUpdate(input.update, out )
9294 }
93- TrampolineFeeInsufficient -> {}
9495 is IncorrectCltvExpiry -> {
9596 LightningCodecs .writeU32(input.expiry.toLong().toInt(), out )
9697 writeChannelUpdate(input.update, out )
9798 }
9899 is ExpiryTooSoon -> writeChannelUpdate(input.update, out )
99- TrampolineExpiryTooSoon -> {}
100100 is IncorrectOrUnknownPaymentDetails -> {
101101 LightningCodecs .writeU64(input.amount.toLong(), out )
102102 LightningCodecs .writeU32(input.height.toInt(), out )
@@ -114,6 +114,13 @@ sealed class FailureMessage {
114114 LightningCodecs .writeU16(input.offset, out )
115115 }
116116 PaymentTimeout -> {}
117+ TemporaryTrampolineFailure -> {}
118+ is TrampolineFeeOrExpiryInsufficient -> {
119+ LightningCodecs .writeU32(input.feeBase.toLong().toInt(), out )
120+ LightningCodecs .writeU32(input.feeProportionalMillionths, out )
121+ LightningCodecs .writeU16(input.expiryDelta.toInt(), out )
122+ }
123+ UnknownNextTrampoline -> {}
117124 is UnknownFailureMessage -> {}
118125 }
119126 }
@@ -195,10 +202,6 @@ data class FeeInsufficient(val amount: MilliSatoshi, override val update: Channe
195202 override val message get() = " payment fee was below the minimum required by the channel"
196203 companion object { const val code = UPDATE or 12 }
197204}
198- object TrampolineFeeInsufficient : FailureMessage(), Node {
199- override val code get() = NODE or 51
200- override val message get() = " payment fee was below the minimum required by the trampoline node"
201- }
202205data class IncorrectCltvExpiry (val expiry : CltvExpiry , override val update : ChannelUpdate ) : FailureMessage(), Update {
203206 override val code get() = IncorrectCltvExpiry .code
204207 override val message get() = " payment expiry doesn't match the value in the onion"
@@ -209,10 +212,6 @@ data class ExpiryTooSoon(override val update: ChannelUpdate) : FailureMessage(),
209212 override val message get() = " payment expiry is too close to the current block height for safe handling by the relaying node"
210213 companion object { const val code = UPDATE or 14 }
211214}
212- object TrampolineExpiryTooSoon : FailureMessage(), Node {
213- override val code get() = NODE or 52
214- override val message get() = " payment expiry is too close to the current block height for safe handling by the relaying node"
215- }
216215data class IncorrectOrUnknownPaymentDetails (val amount : MilliSatoshi , val height : Long ) : FailureMessage(), Perm {
217216 override val code get() = IncorrectOrUnknownPaymentDetails .code
218217 override val message get() = " incorrect payment details or unknown payment hash"
@@ -246,6 +245,19 @@ data object PaymentTimeout : FailureMessage() {
246245 override val code get() = 23
247246 override val message get() = " the complete payment amount was not received within a reasonable time"
248247}
248+ data object TemporaryTrampolineFailure : FailureMessage (), Node {
249+ override val code get() = NODE or 25
250+ override val message get() = " the trampoline node was unable to relay the payment because of downstream temporary failures"
251+ }
252+ data class TrampolineFeeOrExpiryInsufficient (val feeBase : MilliSatoshi , val feeProportionalMillionths : Int , val expiryDelta : CltvExpiryDelta ) : FailureMessage(), Node {
253+ override val code get() = TrampolineFeeOrExpiryInsufficient .code
254+ override val message get() = " trampoline fees or expiry are insufficient to relay the payment"
255+ companion object { const val code = NODE or 26 }
256+ }
257+ data object UnknownNextTrampoline : FailureMessage (), Perm {
258+ override val code get() = PERM or 27
259+ override val message get() = " the trampoline node was unable to find the next trampoline node"
260+ }
249261/* *
250262 * We allow remote nodes to send us unknown failure codes (e.g. deprecated failure codes).
251263 * By reading the PERM and NODE bits of the failure code we can still extract useful information for payment retry even
0 commit comments