lnd: temporary_channel_failure messages wrong

“unable to route payment” messages usually looks like this:

unable to route payment to destination: TemporaryChannelFailure(update=(*lnwire.ChannelUpdate)(0xc426c713b0)({
 Signature: (lnwire.Sig) (len=64 cap=64) {
  00000000  34 16 83 fb aa 67 a7 05  13 f1 85 a8 e5 8a 88 5c  |4....g.........\|
  00000010  38 f6 51 38 20 af 78 51  a3 c2 57 94 c7 56 20 46  |8.Q8 .xQ..W..V F|
  00000020  5b c0 07 2d a7 5c 3e b2  bc 7a ce d1 c7 06 0c c5  |[..-.\>..z......|
  00000030  6a 16 59 ff 59 2e 51 23  14 cd 12 c3 a6 3b ff cd  |j.Y.Y.Q#.....;..|
 },
 ChainHash: (chainhash.Hash) (len=32 cap=32) 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f,
 ShortChannelID: (lnwire.ShortChannelID) 524753:1823:0,
 Timestamp: (uint32) 1532149421,
 Flags: (lnwire.ChanUpdateFlag) 0,
 TimeLockDelta: (uint16) 144,
 HtlcMinimumMsat: (lnwire.MilliSatoshi) 0 mSAT,
 BaseFee: (uint32) 1000,
 FeeRate: (uint32) 1
})
)

with correct chainhash and otherwise sane data .

but sometimes they look like this. it seems the entire message is skewed by 2 bytes, and the first two bytes look like a length specification and are always 01 02

unable to route payment to destination: TemporaryChannelFailure(update=(*lnwire.ChannelUpdate)(0xc43701cab0)({
 Signature: (lnwire.Sig) (len=64 cap=64) {
  00000000  01 02 9f 8a 5b a1 4f 54  e8 3b 79 4e 18 12 03 a8  |....[.OT.;yN....|
  00000010  e5 ab fc 97 39 6f 8d bf  f5 b3 0f 99 2d b0 03 a6  |....9o......-...|
  00000020  34 f9 03 2f 7c 25 71 20  f6 12 cf 39 1f 4a 0c f3  |4../|%q ...9.J..|
  00000030  7a 28 e7 85 b2 b5 0c 19  24 5a 85 77 45 f3 3d 32  |z(......$Z.wE.=2|
 },
 ChainHash: (chainhash.Hash) (len=32 cap=32) 00000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26faadb,
 ShortChannelID: (lnwire.ShortChannelID) 8:1422336:1659,
 Timestamp: (uint32) 23379,
 Flags: (lnwire.ChanUpdateFlag) 6389,
 TimeLockDelta: (uint16) 0,
 HtlcMinimumMsat: (lnwire.MilliSatoshi) 3940649673949184 mSAT,
 BaseFee: (uint32) 0,
 FeeRate: (uint32) 65536000
})
)

it seems the messages that look like this are sent from c-lightning nodes.

according to the rfc it looks like there should be a length specification in those messages

data:
[2:len]
[len:channel_update]

thus i suspect lnd is doing it wrong both when crafting these messages and when parsing them. apart from cosmetic issues, this also affects channel pruning in both lnd other implementations.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 25 (15 by maintainers)

Most upvoted comments

Thank you guys!

I guess you will also check other message types used in similar cases. amount_below_minimum, fee_insufficient , incorrect_cltv_expiry , expiry_too_soon, channel_disabled all include a channel_update

I haven’t done much interoperability tests myself. I started investigating this particular problem while trying to make my rebalancer understand which channels are down, however the symptoms themselves have been known for half a year now, and probably affecting the efficiency of routing for all implementations.

I suggest the implementations will make a fix that will be able to handle both formats, until all nodes are upgraded according to the concensus.

since channel_update is fixed size it is very easy and fixable with a couple of lines of code.

also don’t forget to get ACINQ involved.

Yep, that looks a lot like there are two different interpretations of what it means to send back a channel_update: do we include the type or not? c-lightning includes it lnd seems not to.

For reference the 0x0102 bytes are indeed the message type 258 which is channel_update

OK, @cdecker has submitted a patch to c-lightning which will accept both (https://github.com/ElementsProject/lightning/pull/1775/commits/e32802191e3b305ed49c60d5e502dc911f7f8ae2), then we’ll patch to send out the un-prefixed one as a separate PR.

In the mean time, we can just parse both based on the length to bridge the gap a bit.

i think we should always including the type. including message type makes it flexible and easy to add other types instead of channel_update in the future.