Skip to content

Commit 204dbe4

Browse files
committed
tapchannel: add stxo support for aux leaves
We also add stxo support for the aux leaf creation. This is crucial and needs to be the same across both channel parties. We rely on the consistency of the feature bit for whether we'll include the stxo alt leaves or not. A disagreement here could lead to a force close.
1 parent 5bad5b4 commit 204dbe4

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

server.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,9 @@ func (s *Server) FetchLeavesFromView(
824824

825825
// The aux leaf creator is fully stateless, and we don't need to wait
826826
// for the server to be started before being able to use it.
827-
return tapchannel.FetchLeavesFromView(s.chainParams, in)
827+
return tapchannel.FetchLeavesFromView(
828+
s.chainParams, in, s.cfg.AuxChanNegotiator,
829+
)
828830
}
829831

830832
// FetchLeavesFromCommit attempts to fetch the auxiliary leaves that
@@ -845,6 +847,7 @@ func (s *Server) FetchLeavesFromCommit(chanState lnwl.AuxChanState,
845847
// for the server to be started before being able to use it.
846848
return tapchannel.FetchLeavesFromCommit(
847849
s.chainParams, chanState, com, keys, whoseCommit,
850+
s.cfg.AuxChanNegotiator,
848851
)
849852
}
850853

@@ -880,7 +883,9 @@ func (s *Server) ApplyHtlcView(
880883

881884
// The aux leaf creator is fully stateless, and we don't need to wait
882885
// for the server to be started before being able to use it.
883-
return tapchannel.ApplyHtlcView(s.chainParams, in)
886+
return tapchannel.ApplyHtlcView(
887+
s.chainParams, in, s.cfg.AuxChanNegotiator,
888+
)
884889
}
885890

886891
// InlineParseCustomData replaces any custom data binary blob in the given RPC

tapchannel/aux_leaf_creator.go

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ import (
1010
"github.com/lightninglabs/taproot-assets/address"
1111
"github.com/lightninglabs/taproot-assets/fn"
1212
cmsg "github.com/lightninglabs/taproot-assets/tapchannelmsg"
13+
"github.com/lightninglabs/taproot-assets/tapfeatures"
1314
"github.com/lightningnetwork/lnd/channeldb"
1415
lfn "github.com/lightningnetwork/lnd/fn/v2"
1516
"github.com/lightningnetwork/lnd/input"
1617
"github.com/lightningnetwork/lnd/lntypes"
1718
lnwl "github.com/lightningnetwork/lnd/lnwallet"
19+
"github.com/lightningnetwork/lnd/lnwire"
20+
"github.com/lightningnetwork/lnd/routing/route"
1821
"github.com/lightningnetwork/lnd/tlv"
1922
)
2023

@@ -24,10 +27,22 @@ const (
2427
DefaultTimeout = 30 * time.Second
2528
)
2629

30+
// FeatureBitFetcher is responsible for fetching feature bits either by
31+
// referencing a remote peer, or an established channel.
32+
type FeatureBitFetcher interface {
33+
// GetPeerFeatures returns the negotiated features with the given peer.
34+
GetPeerFeatures(peer route.Vertex) *lnwire.FeatureVector
35+
36+
// GetChannelFeatures returns the negotiated features that are active
37+
// over the channel identifier by the provided channelID.
38+
GetChannelFeatures(cid lnwire.ChannelID) *lnwire.FeatureVector
39+
}
40+
2741
// FetchLeavesFromView attempts to fetch the auxiliary leaves that correspond to
2842
// the passed aux blob, and pending fully evaluated HTLC view.
2943
func FetchLeavesFromView(chainParams *address.ChainParams,
30-
in lnwl.CommitDiffAuxInput) lfn.Result[lnwl.CommitDiffAuxResult] {
44+
in lnwl.CommitDiffAuxInput,
45+
bitFetcher FeatureBitFetcher) lfn.Result[lnwl.CommitDiffAuxResult] {
3146

3247
type returnType = lnwl.CommitDiffAuxResult
3348

@@ -50,10 +65,16 @@ func FetchLeavesFromView(chainParams *address.ChainParams,
5065
"commit state: %w", err))
5166
}
5267

68+
supportsSTXO := bitFetcher.GetChannelFeatures(
69+
lnwire.NewChanIDFromOutPoint(
70+
in.ChannelState.FundingOutpoint,
71+
),
72+
).HasFeature(tapfeatures.STXOOptional)
73+
5374
allocations, newCommitment, err := GenerateCommitmentAllocations(
5475
prevState, in.ChannelState, chanAssetState, in.WhoseCommit,
5576
in.OurBalance, in.TheirBalance, in.UnfilteredView, chainParams,
56-
in.KeyRing, false,
77+
in.KeyRing, supportsSTXO,
5778
)
5879
if err != nil {
5980
return lfn.Err[returnType](fmt.Errorf("unable to generate "+
@@ -80,8 +101,8 @@ func FetchLeavesFromView(chainParams *address.ChainParams,
80101
// to the passed aux blob, and an existing channel commitment.
81102
func FetchLeavesFromCommit(chainParams *address.ChainParams,
82103
chanState lnwl.AuxChanState, com channeldb.ChannelCommitment,
83-
keys lnwl.CommitmentKeyRing,
84-
whoseCommit lntypes.ChannelParty) lfn.Result[lnwl.CommitDiffAuxResult] {
104+
keys lnwl.CommitmentKeyRing, whoseCommit lntypes.ChannelParty,
105+
bitFetcher FeatureBitFetcher) lfn.Result[lnwl.CommitDiffAuxResult] {
85106

86107
type returnType = lnwl.CommitDiffAuxResult
87108

@@ -90,6 +111,9 @@ func FetchLeavesFromCommit(chainParams *address.ChainParams,
90111
return lfn.Ok(lnwl.CommitDiffAuxResult{})
91112
}
92113

114+
supportSTXO := bitFetcher.GetPeerFeatures(chanState.PeerPubKey).
115+
HasFeature(tapfeatures.STXOOptional)
116+
93117
commitment, err := cmsg.DecodeCommitment(
94118
com.CustomBlob.UnsafeFromSome(),
95119
)
@@ -129,7 +153,7 @@ func FetchLeavesFromCommit(chainParams *address.ChainParams,
129153
leaf, err := CreateSecondLevelHtlcTx(
130154
chanState, com.CommitTx, htlc.Amt.ToSatoshis(),
131155
keys, chainParams, htlcOutputs, cltvTimeout,
132-
htlc.HtlcIndex, false,
156+
htlc.HtlcIndex, supportSTXO,
133157
)
134158
if err != nil {
135159
return lfn.Err[returnType](fmt.Errorf("unable "+
@@ -170,7 +194,7 @@ func FetchLeavesFromCommit(chainParams *address.ChainParams,
170194
leaf, err := CreateSecondLevelHtlcTx(
171195
chanState, com.CommitTx, htlc.Amt.ToSatoshis(),
172196
keys, chainParams, htlcOutputs, cltvTimeout,
173-
htlc.HtlcIndex, false,
197+
htlc.HtlcIndex, supportSTXO,
174198
)
175199
if err != nil {
176200
return lfn.Err[returnType](fmt.Errorf("unable "+
@@ -225,7 +249,8 @@ func FetchLeavesFromRevocation(
225249
// channel's blob. Given the old blob, and an HTLC view, then a new
226250
// blob should be returned that reflects the pending updates.
227251
func ApplyHtlcView(chainParams *address.ChainParams,
228-
in lnwl.CommitDiffAuxInput) lfn.Result[lfn.Option[tlv.Blob]] {
252+
in lnwl.CommitDiffAuxInput,
253+
bitFetcher FeatureBitFetcher) lfn.Result[lfn.Option[tlv.Blob]] {
229254

230255
type returnType = lfn.Option[tlv.Blob]
231256

@@ -248,10 +273,18 @@ func ApplyHtlcView(chainParams *address.ChainParams,
248273
"commit state: %w", err))
249274
}
250275

276+
supportSTXO := bitFetcher.GetChannelFeatures(
277+
lnwire.NewChanIDFromOutPoint(
278+
in.ChannelState.FundingOutpoint,
279+
),
280+
).HasFeature(
281+
tapfeatures.STXOOptional,
282+
)
283+
251284
_, newCommitment, err := GenerateCommitmentAllocations(
252285
prevState, in.ChannelState, chanAssetState, in.WhoseCommit,
253286
in.OurBalance, in.TheirBalance, in.UnfilteredView, chainParams,
254-
in.KeyRing, false,
287+
in.KeyRing, supportSTXO,
255288
)
256289
if err != nil {
257290
return lfn.Err[returnType](fmt.Errorf("unable to generate "+

0 commit comments

Comments
 (0)