Skip to content

Channeldb: Store HTLC Extra TLVs in Onion Blob Varbytes#7710

Merged
Roasbeef merged 3 commits intolightningnetwork:masterfrom
carlaKC:7297-updateaddtlvs
Jun 16, 2023
Merged

Channeldb: Store HTLC Extra TLVs in Onion Blob Varbytes#7710
Roasbeef merged 3 commits intolightningnetwork:masterfrom
carlaKC:7297-updateaddtlvs

Conversation

@carlaKC
Copy link
Copy Markdown
Collaborator

@carlaKC carlaKC commented May 19, 2023

Opening this in draft to illustrate the scope of a possible solution for #7297.

This PR demonstrates a workaround for persisting TLV data that is transmitted in update_add_hltc:

  • HTLCs are serialized inline (so we can't easily add on another field, because we wouldn't know when it is / isn't there easily).
  • The OnionBlob for HTLCs is serialized as var bytes, but we know this will always be 1366 bytes (as the spec demands).
  • We can use this variable encoding to squeeze in our TLVs as follows:
    • Write OnionBlob + TLVStream as a single var bytes blob where we previously had just OnionBlob
    • This will write a lengh prefix of 1366 + len(TLV stream)
    • To deserialize, read the full var bytes blob, copy the first 1366 into the OnionBlob and treat the rest as our TLV Stream

When we want to save extra data (as provided in our PaymentDescriptor, all we have to do is encode the TLVs and set channeldb.HTLC.ExtraData (see last commit for example of where we'd need to set this).

Copy link
Copy Markdown
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to see you came around to this approach! May not be the ideal path, but it gets the job done and also lets us avoid migrations in this area as well. Before proceeding we should still do a manual comb through and ensure there're no other areas where an exact length is used (not serialized as var bytes).

@carlaKC
Copy link
Copy Markdown
Collaborator Author

carlaKC commented May 24, 2023

Happy to see you came around to this approach! May not be the ideal path, but it gets the job done and also lets us avoid migrations in this area as well.

Took me a minute to grok, ngl, but seems like the lesser evil (by far)!

Before proceeding we should still do a manual comb through and ensure there're no other areas where an exact length is used (not serialized as var bytes).

Will post separately! WDYT about this PR going in as-is vs combining in a larger preparatory route blinding PR? I lean towards to former, keeping DB workaround PRs more isolated but happy with either approach.

@carlaKC
Copy link
Copy Markdown
Collaborator Author

carlaKC commented May 24, 2023

References to HTLC.OnionBlob

channeldb/channel.go

Serialized/Deserialized with updated functions - always stored as varbytes.

File Line Reference
channeldb/channel.go 2004 onionHash := sha256.Sum256(htlc.OnionBlob[:])
channeldb/channel.go 2012 onionHash := sha256.Sum256(htlc.OnionBlob[:])
channeldb/channel.go 2104 copy(onionAndExtraData, htlc.OnionBlob[:])
channeldb/channel.go 2162 htlcs[i].OnionBlob[:]

contractcourt

decodePayload reads the HTLC's fixed size blob - these HTLCs are serialized and deserialized with our updated logic as part of commitSet.

Legacy nodes used LogChainActions/FetchChainActions which also serializes and deserializes using var bytes.

File Line Reference
contractcourt/htlc_incoming_contest_resolver.go 490 onionReader := bytes.NewReader(h.htlc.OnionBlob[:])

lnwallet/channel.go

HTLCs are stored as var bytes in ChannelCommitment and re-loaded into memory.

File Line Reference
lnwallet/channel.go 748 copy(h.OnionBlob[:], htlc.OnionBlob)
lnwallet/channel.go 772 copy(h.OnionBlob[:], htlc.OnionBlob)
lnwallet/channel.go 860 OnionBlob: htlc.OnionBlob[:]

@carlaKC carlaKC force-pushed the 7297-updateaddtlvs branch from a629a22 to 2850989 Compare May 24, 2023 18:58
@carlaKC carlaKC marked this pull request as ready for review May 25, 2023 16:57
Copy link
Copy Markdown
Member

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love how small and focused this PR is🙏 Because the onion packet is enforced with the 1366 bytes restriction at the encoding/decoding level, I think it's safe to go with this approach. Nice workaround! Left a few comments and I think this is almost good to go⛵️

@carlaKC carlaKC force-pushed the 7297-updateaddtlvs branch 2 times, most recently from 724d177 to 08ede0f Compare May 26, 2023 18:51
@yyforyongyu yyforyongyu added this to the v0.17.0 milestone May 30, 2023
Copy link
Copy Markdown
Member

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM🏖

@carlaKC carlaKC force-pushed the 7297-updateaddtlvs branch from 08ede0f to d1b5c0a Compare May 31, 2023 14:35
@carlaKC carlaKC requested a review from Roasbeef May 31, 2023 14:37
Copy link
Copy Markdown
Collaborator

@ziggie1984 ziggie1984 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smart workaround, chapeau 🎓 :)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Wondering where this testcase came from, I think onion-blobs were always 1366 in size also before this change ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well previously a OnionBlob was just a byte slice, so they could be less than 1366. They never would be, as we wouldn't be able to read them, but unit tests could get away with junk data.

TL;DR: past selves be short-cuttin :')

carlaKC added 3 commits June 2, 2023 11:01
We know that onion blobs in lightning are _exactly_ 1366 bytes in
lightning, but they are currently expressed as a byte slice in
channeldb's HTLC struct. Blobs are currently serialized as var bytes,
so we can take advantage of this known length and variable length
to add additional data to the inline serialization of our HTLCs, which
are otherwise not easily extensible (without creating a new bucket).
Take advantage of the variable byte encoding for a known length field
to extend HLTCs with additional data.
@carlaKC carlaKC force-pushed the 7297-updateaddtlvs branch from d1b5c0a to 8a9dd10 Compare June 2, 2023 15:02
@carlaKC
Copy link
Copy Markdown
Collaborator Author

carlaKC commented Jun 2, 2023

Latest push just addresses nits and adds some comments, no functionality changes.

@lightninglabs-deploy
Copy link
Copy Markdown
Collaborator

@Roasbeef: review reminder

@saubyk saubyk requested a review from ellemouton June 15, 2023 17:10
Copy link
Copy Markdown

@Torakushi Torakushi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome changes! very clear and concise. Well done!

Copy link
Copy Markdown
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🌴

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

No open projects
Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

6 participants