Skip to content
Closed
42 changes: 38 additions & 4 deletions channeldb/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ type chanAuxData struct {
realScid tlv.RecordT[tlv.TlvType4, lnwire.ShortChannelID]

memo tlv.OptionalRecordT[tlv.TlvType5, []byte]

tapscriptRoot tlv.OptionalRecordT[tlv.TlvType6, [32]byte]
}

// toOpeChan converts the chanAuxData to an OpenChannel by setting the relevant
Expand All @@ -248,6 +250,9 @@ func (c *chanAuxData) toOpenChan(o *OpenChannel) {
c.memo.WhenSomeV(func(memo []byte) {
o.Memo = memo
})
c.tapscriptRoot.WhenSomeV(func(h [32]byte) {
o.TapscriptRoot = fn.Some(chainhash.Hash(h))
})
}

// newChanAuxDataFromChan creates a new chanAuxData from the given channel.
Expand All @@ -267,11 +272,16 @@ func newChanAuxDataFromChan(openChan *OpenChannel) *chanAuxData {
),
}

if len(openChan.Memo) == 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

was this some unrelated old typo?

if len(openChan.Memo) != 0 {
c.memo = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[tlv.TlvType5](openChan.Memo),
)
}
openChan.TapscriptRoot.WhenSome(func(h chainhash.Hash) {
c.tapscriptRoot = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[tlv.TlvType6]([32]byte(h)),
)
})

return c
}
Expand Down Expand Up @@ -353,6 +363,11 @@ const (
// SimpleTaprootFeatureBit indicates that the simple-taproot-chans
// feature bit was negotiated during the lifetime of the channel.
SimpleTaprootFeatureBit ChannelType = 1 << 10

// TapscriptRootBit indicates that this is a musig2 channel with a top
// level tapscript commitment. This MUST be set along with the
// SimpleTaprootFeatureBit.
TapscriptRootBit ChannelType = 1 << 11
)

// IsSingleFunder returns true if the channel type if one of the known single
Expand Down Expand Up @@ -423,6 +438,12 @@ func (c ChannelType) IsTaproot() bool {
return c&SimpleTaprootFeatureBit == SimpleTaprootFeatureBit
}

// HasTapscriptRoot returns true if the channel is using a top level tapscript
// root commmitment.
func (c ChannelType) HasTapscriptRoot() bool {
return c&TapscriptRootBit == TapscriptRootBit
}

// ChannelConstraints represents a set of constraints meant to allow a node to
// limit their exposure, enact flow control and ensure that all HTLCs are
// economically relevant. This struct will be mirrored for both sides of the
Expand Down Expand Up @@ -3980,6 +4001,9 @@ func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
auxData.memo.WhenSome(func(memo tlv.RecordT[tlv.TlvType5, []byte]) {
tlvRecords = append(tlvRecords, memo.Record())
})
auxData.tapscriptRoot.WhenSome(func(root tlv.RecordT[tlv.TlvType6, [32]byte]) { //nolint:lll
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: format as:

	auxData.tapscriptRoot.WhenSome(
		func(root tlv.RecordT[tlv.TlvType6, [32]byte]) {
			tlvRecords = append(tlvRecords, root.Record())
		}
	)

instead? Or place the //nolint:lll above the line instead of at the end to make it even longer?

tlvRecords = append(tlvRecords, root.Record())
})

// Create the tlv stream.
tlvStream, err := tlv.NewStream(tlvRecords...)
Expand Down Expand Up @@ -4178,24 +4202,34 @@ func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
}

var auxData chanAuxData
zeroMemo := auxData.memo.Zero()
memo := auxData.memo.Zero()
tapscriptRoot := auxData.tapscriptRoot.Zero()

// Create the tlv stream.
tlvStream, err := tlv.NewStream(
auxData.revokeKeyLoc.Record(),
auxData.initialLocalBalance.Record(),
auxData.initialRemoteBalance.Record(),
auxData.realScid.Record(),
zeroMemo.Record(),
memo.Record(),
tapscriptRoot.Record(),
)
if err != nil {
return err
}

if err := tlvStream.Decode(r); err != nil {
tlvs, err := tlvStream.DecodeWithParsedTypes(r)
if err != nil {
return err
}

if _, ok := tlvs[memo.TlvType()]; ok {
auxData.memo = tlv.SomeRecordT(memo)
}
if _, ok := tlvs[tapscriptRoot.TlvType()]; ok {
auxData.tapscriptRoot = tlv.SomeRecordT(tapscriptRoot)
}

// Assign all the relevant fields from the aux data into the actual
// open channel.
auxData.toOpenChan(channel)
Expand Down
7 changes: 6 additions & 1 deletion channeldb/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnmock"
Expand Down Expand Up @@ -171,7 +172,7 @@ func fundingPointOption(chanPoint wire.OutPoint) testChannelOption {
}

// channelIDOption is an option which sets the short channel ID of the channel.
var channelIDOption = func(chanID lnwire.ShortChannelID) testChannelOption {
func channelIDOption(chanID lnwire.ShortChannelID) testChannelOption {
return func(params *testChannelParams) {
params.channel.ShortChannelID = chanID
}
Expand Down Expand Up @@ -311,6 +312,9 @@ func createTestChannelState(t *testing.T, cdb *ChannelStateDB) *OpenChannel {
uniqueOutputIndex.Add(1)
op := wire.OutPoint{Hash: key, Index: uniqueOutputIndex.Load()}

var tapscriptRoot chainhash.Hash
copy(tapscriptRoot[:], bytes.Repeat([]byte{1}, 32))
Copy link
Collaborator

Choose a reason for hiding this comment

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

While we're at it, should we also throw in a value for the memo since that doesn't seem to be covered yet?


return &OpenChannel{
ChanType: SingleFunderBit | FrozenBit,
ChainHash: key,
Expand Down Expand Up @@ -353,6 +357,7 @@ func createTestChannelState(t *testing.T, cdb *ChannelStateDB) *OpenChannel {
ThawHeight: uint32(defaultPendingHeight),
InitialLocalBalance: lnwire.MilliSatoshi(9000),
InitialRemoteBalance: lnwire.MilliSatoshi(3000),
TapscriptRoot: fn.Some(tapscriptRoot),
}
}

Expand Down