-
Notifications
You must be signed in to change notification settings - Fork 2.2k
multi: add ability to fund+use musig2 channels that commit to a tapscript root #8546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
007f968
784d236
5d18c65
733e192
1e07ba3
7d3c83b
b8cb4e6
612e93e
33e0cea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
@@ -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. | ||
|
|
@@ -267,11 +272,16 @@ func newChanAuxDataFromChan(openChan *OpenChannel) *chanAuxData { | |
| ), | ||
| } | ||
|
|
||
| if len(openChan.Memo) == 0 { | ||
| 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 | ||
| } | ||
|
|
@@ -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 | ||
|
|
@@ -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 | ||
|
|
@@ -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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: format as: instead? Or place the |
||
| tlvRecords = append(tlvRecords, root.Record()) | ||
| }) | ||
|
|
||
| // Create the tlv stream. | ||
| tlvStream, err := tlv.NewStream(tlvRecords...) | ||
|
|
@@ -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) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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" | ||
|
|
@@ -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 | ||
| } | ||
|
|
@@ -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)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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, | ||
|
|
@@ -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), | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
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?