@@ -5,6 +5,7 @@ import fr.acinq.bitcoin.io.ByteArrayInput
5
5
import fr.acinq.bitcoin.io.ByteArrayOutput
6
6
import fr.acinq.bitcoin.io.Output
7
7
import fr.acinq.lightning.CltvExpiry
8
+ import fr.acinq.lightning.CltvExpiryDelta
8
9
import fr.acinq.lightning.MilliSatoshi
9
10
import fr.acinq.lightning.utils.toByteVector32
10
11
@@ -41,10 +42,8 @@ sealed class FailureMessage {
41
42
UnknownNextPeer .code -> UnknownNextPeer
42
43
AmountBelowMinimum .code -> AmountBelowMinimum (MilliSatoshi (LightningCodecs .u64(stream)), readChannelUpdate(stream))
43
44
FeeInsufficient .code -> FeeInsufficient (MilliSatoshi (LightningCodecs .u64(stream)), readChannelUpdate(stream))
44
- TrampolineFeeInsufficient .code -> TrampolineFeeInsufficient
45
45
IncorrectCltvExpiry .code -> IncorrectCltvExpiry (CltvExpiry (LightningCodecs .u32(stream).toLong()), readChannelUpdate(stream))
46
46
ExpiryTooSoon .code -> ExpiryTooSoon (readChannelUpdate(stream))
47
- TrampolineExpiryTooSoon .code -> TrampolineExpiryTooSoon
48
47
IncorrectOrUnknownPaymentDetails .code -> {
49
48
val amount = if (stream.availableBytes > 0 ) MilliSatoshi (LightningCodecs .u64(stream)) else MilliSatoshi (0 )
50
49
val blockHeight = if (stream.availableBytes > 0 ) LightningCodecs .u32(stream).toLong() else 0L
@@ -56,6 +55,9 @@ sealed class FailureMessage {
56
55
ExpiryTooFar .code -> ExpiryTooFar
57
56
InvalidOnionPayload .code -> InvalidOnionPayload (LightningCodecs .bigSize(stream), LightningCodecs .u16(stream))
58
57
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
59
61
else -> UnknownFailureMessage (code)
60
62
}
61
63
}
@@ -90,13 +92,11 @@ sealed class FailureMessage {
90
92
LightningCodecs .writeU64(input.amount.toLong(), out )
91
93
writeChannelUpdate(input.update, out )
92
94
}
93
- TrampolineFeeInsufficient -> {}
94
95
is IncorrectCltvExpiry -> {
95
96
LightningCodecs .writeU32(input.expiry.toLong().toInt(), out )
96
97
writeChannelUpdate(input.update, out )
97
98
}
98
99
is ExpiryTooSoon -> writeChannelUpdate(input.update, out )
99
- TrampolineExpiryTooSoon -> {}
100
100
is IncorrectOrUnknownPaymentDetails -> {
101
101
LightningCodecs .writeU64(input.amount.toLong(), out )
102
102
LightningCodecs .writeU32(input.height.toInt(), out )
@@ -114,6 +114,13 @@ sealed class FailureMessage {
114
114
LightningCodecs .writeU16(input.offset, out )
115
115
}
116
116
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 -> {}
117
124
is UnknownFailureMessage -> {}
118
125
}
119
126
}
@@ -195,10 +202,6 @@ data class FeeInsufficient(val amount: MilliSatoshi, override val update: Channe
195
202
override val message get() = " payment fee was below the minimum required by the channel"
196
203
companion object { const val code = UPDATE or 12 }
197
204
}
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
- }
202
205
data class IncorrectCltvExpiry (val expiry : CltvExpiry , override val update : ChannelUpdate ) : FailureMessage(), Update {
203
206
override val code get() = IncorrectCltvExpiry .code
204
207
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(),
209
212
override val message get() = " payment expiry is too close to the current block height for safe handling by the relaying node"
210
213
companion object { const val code = UPDATE or 14 }
211
214
}
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
- }
216
215
data class IncorrectOrUnknownPaymentDetails (val amount : MilliSatoshi , val height : Long ) : FailureMessage(), Perm {
217
216
override val code get() = IncorrectOrUnknownPaymentDetails .code
218
217
override val message get() = " incorrect payment details or unknown payment hash"
@@ -246,6 +245,19 @@ data object PaymentTimeout : FailureMessage() {
246
245
override val code get() = 23
247
246
override val message get() = " the complete payment amount was not received within a reasonable time"
248
247
}
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
+ }
249
261
/* *
250
262
* We allow remote nodes to send us unknown failure codes (e.g. deprecated failure codes).
251
263
* By reading the PERM and NODE bits of the failure code we can still extract useful information for payment retry even
0 commit comments