Skip to content

Commit 1f110dc

Browse files
Roasbeefguggero
authored andcommitted
channeldb: consolidate root bucket TLVs into new struct
In this commit, we consolidate the root bucket TLVs into a new struct. This makes it easier to see all the new TLV fields at a glance. We also convert TLV usage to use the new type param based APis.
1 parent bb0fb86 commit 1f110dc

File tree

1 file changed

+137
-95
lines changed

1 file changed

+137
-95
lines changed

channeldb/channel.go

Lines changed: 137 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -225,27 +225,116 @@ const (
225225
// A tlv type definition used to serialize an outpoint's indexStatus
226226
// for use in the outpoint index.
227227
indexStatusType tlv.Type = 0
228+
)
228229

229-
// A tlv type definition used to serialize and deserialize a KeyLocator
230-
// from the database.
231-
keyLocType tlv.Type = 1
230+
// chanAuxData houses the auxiliary data that is stored for each channel in a
231+
// TLV stream within the root bucket. This is stored as a TLV stream appended
232+
// to the existing hard-coded fields in the channel's root bucket.
233+
type chanAuxData struct {
234+
// revokeKeyLoc is the key locator for the revocation key.
235+
revokeKeyLoc tlv.RecordT[tlv.TlvType1, keyLocRecord]
232236

233-
// A tlv type used to serialize and deserialize the
234-
// `InitialLocalBalance` field.
235-
initialLocalBalanceType tlv.Type = 2
237+
// initialLocalBalance is the initial local balance of the channel.
238+
initialLocalBalance tlv.RecordT[tlv.TlvType2, uint64]
236239

237-
// A tlv type used to serialize and deserialize the
238-
// `InitialRemoteBalance` field.
239-
initialRemoteBalanceType tlv.Type = 3
240+
// initialRemoteBalance is the initial remote balance of the channel.
241+
initialRemoteBalance tlv.RecordT[tlv.TlvType3, uint64]
240242

241-
// A tlv type definition used to serialize and deserialize the
242-
// confirmed ShortChannelID for a zero-conf channel.
243-
realScidType tlv.Type = 4
243+
// realScid is the real short channel ID of the channel corresponding to
244+
// the on-chain outpoint.
245+
realScid tlv.RecordT[tlv.TlvType4, lnwire.ShortChannelID]
244246

245-
// A tlv type definition used to serialize and deserialize the
246-
// Memo for the channel channel.
247-
channelMemoType tlv.Type = 5
248-
)
247+
// memo is an optional text field that gives context to the user about
248+
// the channel.
249+
memo tlv.OptionalRecordT[tlv.TlvType5, []byte]
250+
}
251+
252+
// encode serializes the chanAuxData to the given io.Writer.
253+
func (c *chanAuxData) encode(w io.Writer) error {
254+
tlvRecords := []tlv.Record{
255+
c.revokeKeyLoc.Record(),
256+
c.initialLocalBalance.Record(),
257+
c.initialRemoteBalance.Record(),
258+
c.realScid.Record(),
259+
}
260+
c.memo.WhenSome(func(memo tlv.RecordT[tlv.TlvType5, []byte]) {
261+
tlvRecords = append(tlvRecords, memo.Record())
262+
})
263+
264+
// Create the tlv stream.
265+
tlvStream, err := tlv.NewStream(tlvRecords...)
266+
if err != nil {
267+
return err
268+
}
269+
270+
return tlvStream.Encode(w)
271+
}
272+
273+
// decode deserializes the chanAuxData from the given io.Reader.
274+
func (c *chanAuxData) decode(r io.Reader) error {
275+
memo := c.memo.Zero()
276+
277+
// Create the tlv stream.
278+
tlvStream, err := tlv.NewStream(
279+
c.revokeKeyLoc.Record(),
280+
c.initialLocalBalance.Record(),
281+
c.initialRemoteBalance.Record(),
282+
c.realScid.Record(),
283+
memo.Record(),
284+
)
285+
if err != nil {
286+
return err
287+
}
288+
289+
tlvs, err := tlvStream.DecodeWithParsedTypes(r)
290+
if err != nil {
291+
return err
292+
}
293+
294+
if _, ok := tlvs[memo.TlvType()]; ok {
295+
c.memo = tlv.SomeRecordT(memo)
296+
}
297+
298+
return nil
299+
}
300+
301+
// toOpeChan converts the chanAuxData to an OpenChannel by setting the relevant
302+
// fields in the OpenChannel struct.
303+
func (c *chanAuxData) toOpenChan(o *OpenChannel) {
304+
o.RevocationKeyLocator = c.revokeKeyLoc.Val.KeyLocator
305+
o.InitialLocalBalance = lnwire.MilliSatoshi(c.initialLocalBalance.Val)
306+
o.InitialRemoteBalance = lnwire.MilliSatoshi(c.initialRemoteBalance.Val)
307+
o.confirmedScid = c.realScid.Val
308+
c.memo.WhenSomeV(func(memo []byte) {
309+
o.Memo = memo
310+
})
311+
}
312+
313+
// newChanAuxDataFromChan creates a new chanAuxData from the given channel.
314+
func newChanAuxDataFromChan(openChan *OpenChannel) *chanAuxData {
315+
c := &chanAuxData{
316+
revokeKeyLoc: tlv.NewRecordT[tlv.TlvType1](
317+
keyLocRecord{openChan.RevocationKeyLocator},
318+
),
319+
initialLocalBalance: tlv.NewPrimitiveRecord[tlv.TlvType2](
320+
uint64(openChan.InitialLocalBalance),
321+
),
322+
initialRemoteBalance: tlv.NewPrimitiveRecord[tlv.TlvType3](
323+
uint64(openChan.InitialRemoteBalance),
324+
),
325+
realScid: tlv.NewRecordT[tlv.TlvType4](
326+
openChan.confirmedScid,
327+
),
328+
}
329+
330+
if len(openChan.Memo) != 0 {
331+
c.memo = tlv.SomeRecordT(
332+
tlv.NewPrimitiveRecord[tlv.TlvType5](openChan.Memo),
333+
)
334+
}
335+
336+
return c
337+
}
249338

250339
// indexStatus is an enum-like type that describes what state the
251340
// outpoint is in. Currently only two possible values.
@@ -856,6 +945,10 @@ type OpenChannel struct {
856945
// channel that will be useful to our future selves.
857946
Memo []byte
858947

948+
// TapscriptRoot is an optional tapscript root used to derive the MuSig2
949+
// funding output.
950+
TapscriptRoot fn.Option[chainhash.Hash]
951+
859952
// TODO(roasbeef): eww
860953
Db *ChannelStateDB
861954

@@ -4007,32 +4100,9 @@ func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
40074100
return err
40084101
}
40094102

4010-
// Convert balance fields into uint64.
4011-
localBalance := uint64(channel.InitialLocalBalance)
4012-
remoteBalance := uint64(channel.InitialRemoteBalance)
4013-
4014-
// Create the tlv stream.
4015-
tlvStream, err := tlv.NewStream(
4016-
// Write the RevocationKeyLocator as the first entry in a tlv
4017-
// stream.
4018-
MakeKeyLocRecord(
4019-
keyLocType, &channel.RevocationKeyLocator,
4020-
),
4021-
tlv.MakePrimitiveRecord(
4022-
initialLocalBalanceType, &localBalance,
4023-
),
4024-
tlv.MakePrimitiveRecord(
4025-
initialRemoteBalanceType, &remoteBalance,
4026-
),
4027-
MakeScidRecord(realScidType, &channel.confirmedScid),
4028-
tlv.MakePrimitiveRecord(channelMemoType, &channel.Memo),
4029-
)
4030-
if err != nil {
4031-
return err
4032-
}
4033-
4034-
if err := tlvStream.Encode(&w); err != nil {
4035-
return err
4103+
auxData := newChanAuxDataFromChan(channel)
4104+
if err := auxData.encode(&w); err != nil {
4105+
return fmt.Errorf("unable to encode aux data: %w", err)
40364106
}
40374107

40384108
if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
@@ -4221,45 +4291,14 @@ func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
42214291
}
42224292
}
42234293

4224-
// Create balance fields in uint64, and Memo field as byte slice.
4225-
var (
4226-
localBalance uint64
4227-
remoteBalance uint64
4228-
memo []byte
4229-
)
4230-
4231-
// Create the tlv stream.
4232-
tlvStream, err := tlv.NewStream(
4233-
// Write the RevocationKeyLocator as the first entry in a tlv
4234-
// stream.
4235-
MakeKeyLocRecord(
4236-
keyLocType, &channel.RevocationKeyLocator,
4237-
),
4238-
tlv.MakePrimitiveRecord(
4239-
initialLocalBalanceType, &localBalance,
4240-
),
4241-
tlv.MakePrimitiveRecord(
4242-
initialRemoteBalanceType, &remoteBalance,
4243-
),
4244-
MakeScidRecord(realScidType, &channel.confirmedScid),
4245-
tlv.MakePrimitiveRecord(channelMemoType, &memo),
4246-
)
4247-
if err != nil {
4248-
return err
4249-
}
4250-
4251-
if err := tlvStream.Decode(r); err != nil {
4252-
return err
4294+
var auxData chanAuxData
4295+
if err := auxData.decode(r); err != nil {
4296+
return fmt.Errorf("unable to decode aux data: %w", err)
42534297
}
42544298

4255-
// Attach the balance fields.
4256-
channel.InitialLocalBalance = lnwire.MilliSatoshi(localBalance)
4257-
channel.InitialRemoteBalance = lnwire.MilliSatoshi(remoteBalance)
4258-
4259-
// Attach the memo field if non-empty.
4260-
if len(memo) > 0 {
4261-
channel.Memo = memo
4262-
}
4299+
// Assign all the relevant fields from the aux data into the actual
4300+
// open channel.
4301+
auxData.toOpenChan(channel)
42634302

42644303
channel.Packager = NewChannelPackager(channel.ShortChannelID)
42654304

@@ -4417,6 +4456,25 @@ func deleteThawHeight(chanBucket kvdb.RwBucket) error {
44174456
return chanBucket.Delete(frozenChanKey)
44184457
}
44194458

4459+
// keyLocRecord is a wrapper struct around keychain.KeyLocator to implement the
4460+
// tlv.RecordProducer interface.
4461+
type keyLocRecord struct {
4462+
keychain.KeyLocator
4463+
}
4464+
4465+
// Record creates a Record out of a KeyLocator using the passed Type and the
4466+
// EKeyLocator and DKeyLocator functions. The size will always be 8 as
4467+
// KeyFamily is uint32 and the Index is uint32.
4468+
//
4469+
// NOTE: This is part of the tlv.RecordProducer interface.
4470+
func (k *keyLocRecord) Record() tlv.Record {
4471+
// Note that we set the type here as zero, as when used with a
4472+
// tlv.RecordT, the type param will be used as the type.
4473+
return tlv.MakeStaticRecord(
4474+
0, &k.KeyLocator, 8, EKeyLocator, DKeyLocator,
4475+
)
4476+
}
4477+
44204478
// EKeyLocator is an encoder for keychain.KeyLocator.
44214479
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
44224480
if v, ok := val.(*keychain.KeyLocator); ok {
@@ -4445,22 +4503,6 @@ func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
44454503
return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
44464504
}
44474505

4448-
// MakeKeyLocRecord creates a Record out of a KeyLocator using the passed
4449-
// Type and the EKeyLocator and DKeyLocator functions. The size will always be
4450-
// 8 as KeyFamily is uint32 and the Index is uint32.
4451-
func MakeKeyLocRecord(typ tlv.Type, keyLoc *keychain.KeyLocator) tlv.Record {
4452-
return tlv.MakeStaticRecord(typ, keyLoc, 8, EKeyLocator, DKeyLocator)
4453-
}
4454-
4455-
// MakeScidRecord creates a Record out of a ShortChannelID using the passed
4456-
// Type and the EShortChannelID and DShortChannelID functions. The size will
4457-
// always be 8 for the ShortChannelID.
4458-
func MakeScidRecord(typ tlv.Type, scid *lnwire.ShortChannelID) tlv.Record {
4459-
return tlv.MakeStaticRecord(
4460-
typ, scid, 8, lnwire.EShortChannelID, lnwire.DShortChannelID,
4461-
)
4462-
}
4463-
44644506
// ShutdownInfo contains various info about the shutdown initiation of a
44654507
// channel.
44664508
type ShutdownInfo struct {

0 commit comments

Comments
 (0)