Skip to content

Commit e6ae082

Browse files
authored
Merge pull request #1779 from lightninglabs/channels-v1
Prepare tap channels for v1 proofs
2 parents c99891a + 9218916 commit e6ae082

File tree

12 files changed

+215
-45
lines changed

12 files changed

+215
-45
lines changed

rfq/manager_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ func createChannelWithCustomData(t *testing.T, id asset.ID, localBalance,
111111
),
112112
},
113113
nil, nil, lnwallet.CommitAuxLeaves{},
114+
false,
114115
),
115116
OpenChan: *tpchmsg.NewOpenChannel(
116117
[]*tpchmsg.AssetOutput{

server.go

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

869869
// The aux leaf creator is fully stateless, and we don't need to wait
870870
// for the server to be started before being able to use it.
871-
return tapchannel.FetchLeavesFromView(s.chainParams, in)
871+
return tapchannel.FetchLeavesFromView(
872+
s.chainParams, in, s.cfg.AuxChanNegotiator,
873+
)
872874
}
873875

874876
// FetchLeavesFromCommit attempts to fetch the auxiliary leaves that
@@ -924,7 +926,9 @@ func (s *Server) ApplyHtlcView(
924926

925927
// The aux leaf creator is fully stateless, and we don't need to wait
926928
// for the server to be started before being able to use it.
927-
return tapchannel.ApplyHtlcView(s.chainParams, in)
929+
return tapchannel.ApplyHtlcView(
930+
s.chainParams, in, s.cfg.AuxChanNegotiator,
931+
)
928932
}
929933

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

tapcfg/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
628628
AssetSyncer: addrBook,
629629
FeatureBits: lndFeatureBitsVerifier,
630630
IgnoreChecker: ignoreCheckerOpt,
631+
AuxChanNegotiator: auxChanNegotiator,
631632
ErrChan: mainErrChan,
632633
},
633634
)
@@ -659,6 +660,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
659660
GroupVerifier: groupVerifier,
660661
ChainBridge: chainBridge,
661662
IgnoreChecker: ignoreCheckerOpt,
663+
AuxChanNegotiator: auxChanNegotiator,
662664
},
663665
)
664666
auxSweeper := tapchannel.NewAuxSweeper(

tapchannel/auf_leaf_signer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func setupAuxLeafSigner(t *testing.T, numJobs int32) (*AuxLeafSigner,
111111
}
112112

113113
com := cmsg.NewCommitment(
114-
nil, nil, outgoingHtlcs, nil, lnwallet.CommitAuxLeaves{},
114+
nil, nil, outgoingHtlcs, nil, lnwallet.CommitAuxLeaves{}, false,
115115
)
116116
cancelChan := make(chan struct{})
117117

tapchannel/aux_closer.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/lightninglabs/taproot-assets/fn"
1616
"github.com/lightninglabs/taproot-assets/proof"
1717
"github.com/lightninglabs/taproot-assets/tapchannelmsg"
18+
"github.com/lightninglabs/taproot-assets/tapfeatures"
1819
"github.com/lightninglabs/taproot-assets/tapfreighter"
1920
"github.com/lightninglabs/taproot-assets/tapgarden"
2021
"github.com/lightninglabs/taproot-assets/tappsbt"
@@ -66,6 +67,11 @@ type AuxChanCloserCfg struct {
6667
// IgnoreChecker is an optional function that can be used to check if
6768
// a proof should be ignored.
6869
IgnoreChecker lfn.Option[proof.IgnoreChecker]
70+
71+
// AuxChanNegotiator is responsible for producing the extra tlv blob
72+
// that is encapsulated in the init and reestablish peer messages. This
73+
// helps us communicate custom feature bits with our peer.
74+
AuxChanNegotiator *tapfeatures.AuxChannelNegotiator
6975
}
7076

7177
// assetCloseInfo houses the information we need to finalize the close of an
@@ -454,11 +460,21 @@ func (a *AuxChanCloser) AuxCloseOutputs(
454460
"packets: %w", err)
455461
}
456462

463+
features := a.cfg.AuxChanNegotiator.GetChannelFeatures(
464+
lnwire.NewChanIDFromOutPoint(desc.ChanPoint),
465+
)
466+
supportSTXO := features.HasFeature(tapfeatures.STXOOptional)
467+
468+
var opts []tapsend.OutputCommitmentOption
469+
if !supportSTXO {
470+
opts = append(opts, tapsend.WithNoSTXOProofs())
471+
}
472+
457473
// With the outputs prepared, we can now create the set of output
458474
// commitments, then with the output index locations known, we can set
459475
// the output indexes in the allocations.
460476
outCommitments, err := tapsend.CreateOutputCommitments(
461-
vPackets, tapsend.WithNoSTXOProofs(),
477+
vPackets, opts...,
462478
)
463479
if err != nil {
464480
return none, fmt.Errorf("unable to create output "+
@@ -733,10 +749,22 @@ func (a *AuxChanCloser) FinalizeClose(desc chancloser.AuxCloseDesc,
733749
closeInfo.allocations,
734750
)
735751

752+
features := a.cfg.AuxChanNegotiator.GetChannelFeatures(
753+
lnwire.NewChanIDFromOutPoint(desc.ChanPoint),
754+
)
755+
supportSTXO := features.HasFeature(
756+
tapfeatures.STXOOptional,
757+
)
758+
759+
var opts []proof.GenOption
760+
if !supportSTXO {
761+
opts = append(opts, proof.WithNoSTXOProofs())
762+
}
763+
736764
proofSuffix, err := tapsend.CreateProofSuffixCustom(
737765
closeTx, vPkt, closeInfo.outputCommitments,
738766
outIdx, closeInfo.vPackets, exclusionCreator,
739-
proof.WithNoSTXOProofs(),
767+
opts...,
740768
)
741769
if err != nil {
742770
return fmt.Errorf("unable to create proof "+

tapchannel/aux_funding_controller.go

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/lightninglabs/taproot-assets/rfq"
2929
cmsg "github.com/lightninglabs/taproot-assets/tapchannelmsg"
3030
"github.com/lightninglabs/taproot-assets/tapdb"
31+
"github.com/lightninglabs/taproot-assets/tapfeatures"
3132
"github.com/lightninglabs/taproot-assets/tapfreighter"
3233
"github.com/lightninglabs/taproot-assets/tapgarden"
3334
"github.com/lightninglabs/taproot-assets/tappsbt"
@@ -41,6 +42,7 @@ import (
4142
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
4243
"github.com/lightningnetwork/lnd/lnwire"
4344
"github.com/lightningnetwork/lnd/msgmux"
45+
"github.com/lightningnetwork/lnd/routing/route"
4446
)
4547

4648
const (
@@ -269,6 +271,11 @@ type FundingControllerCfg struct {
269271
// a proof should be ignored.
270272
IgnoreChecker lfn.Option[proof.IgnoreChecker]
271273

274+
// AuxChanNegotiator is responsible for producing the extra tlv blob
275+
// that is encapsulated in the init and reestablish peer messages. This
276+
// helps us communicate custom feature bits with our peer.
277+
AuxChanNegotiator *tapfeatures.AuxChannelNegotiator
278+
272279
// ErrChan is used to report errors back to the main server.
273280
ErrChan chan<- error
274281
}
@@ -419,6 +426,8 @@ type pendingAssetFunding struct {
419426

420427
initiator bool
421428

429+
stxo bool
430+
422431
amt uint64
423432

424433
pushAmt btcutil.Amount
@@ -462,14 +471,32 @@ func (p *pendingAssetFunding) assetOutputs() []*cmsg.AssetOutput {
462471
}
463472

464473
// addToFundingCommitment adds a new asset to the funding commitment.
465-
func (p *pendingAssetFunding) addToFundingCommitment(a *asset.Asset) error {
474+
func (p *pendingAssetFunding) addToFundingCommitment(a *asset.Asset,
475+
stxo bool) error {
476+
466477
newCommitment, err := commitment.FromAssets(
467478
fn.Ptr(commitment.TapCommitmentV2), a,
468479
)
469480
if err != nil {
470481
return fmt.Errorf("unable to create commitment: %w", err)
471482
}
472483

484+
// If our peer supports STXO we go ahead and append the
485+
// appropriate alt leaves to the VOutput.
486+
if stxo {
487+
altLeaves, err := asset.CollectSTXO(a)
488+
if err != nil {
489+
return err
490+
}
491+
492+
err = newCommitment.MergeAltLeaves(altLeaves)
493+
if err != nil {
494+
return err
495+
}
496+
497+
p.stxo = stxo
498+
}
499+
473500
newCommitment, err = commitment.TrimSplitWitnesses(
474501
&newCommitment.Version, newCommitment,
475502
)
@@ -524,7 +551,8 @@ func (p *pendingAssetFunding) addInputProofChunk(
524551
func newCommitBlobAndLeaves(pendingFunding *pendingAssetFunding,
525552
lndOpenChan lnwallet.AuxChanState, assetOpenChan *cmsg.OpenChannel,
526553
keyRing lntypes.Dual[lnwallet.CommitmentKeyRing],
527-
whoseCommit lntypes.ChannelParty) ([]byte, lnwallet.CommitAuxLeaves,
554+
whoseCommit lntypes.ChannelParty,
555+
stxo bool) ([]byte, lnwallet.CommitAuxLeaves,
528556
error) {
529557

530558
chanAssets := assetOpenChan.FundedAssets.Val.Outputs
@@ -559,6 +587,7 @@ func newCommitBlobAndLeaves(pendingFunding *pendingAssetFunding,
559587
// needs the sum of the remote+local assets, so we'll populate that.
560588
fakePrevState := cmsg.NewCommitment(
561589
localAssets, remoteAssets, nil, nil, lnwallet.CommitAuxLeaves{},
590+
stxo,
562591
)
563592

564593
// Just like above, we don't have a real HTLC view here, so we'll pass
@@ -571,6 +600,7 @@ func newCommitBlobAndLeaves(pendingFunding *pendingAssetFunding,
571600
fakePrevState, lndOpenChan, assetOpenChan, whoseCommit,
572601
localSatBalance, remoteSatBalance, fakeView,
573602
pendingFunding.chainParams, keyRing.GetForParty(whoseCommit),
603+
stxo,
574604
)
575605
if err != nil {
576606
return nil, lnwallet.CommitAuxLeaves{}, err
@@ -613,12 +643,14 @@ func (p *pendingAssetFunding) toAuxFundingDesc(req *bindFundingReq,
613643
// This will be the information for the very first state (state 0).
614644
localCommitBlob, localAuxLeaves, err := newCommitBlobAndLeaves(
615645
p, req.openChan, openChanDesc, req.keyRing, lntypes.Local,
646+
p.stxo,
616647
)
617648
if err != nil {
618649
return nil, err
619650
}
620651
remoteCommitBlob, remoteAuxLeaves, err := newCommitBlobAndLeaves(
621652
p, req.openChan, openChanDesc, req.keyRing, lntypes.Remote,
653+
p.stxo,
622654
)
623655
if err != nil {
624656
return nil, err
@@ -1086,14 +1118,19 @@ func (f *FundingController) signAllVPackets(ctx context.Context,
10861118
// complete, but unsigned PSBT packet that can be used to create out asset
10871119
// channel.
10881120
func (f *FundingController) anchorVPackets(fundedPkt *tapsend.FundedPsbt,
1089-
allPackets []*tappsbt.VPacket) ([]*proof.Proof, error) {
1121+
allPackets []*tappsbt.VPacket, stxo bool) ([]*proof.Proof, error) {
10901122

10911123
log.Infof("Anchoring funding vPackets to funding PSBT")
10921124

1125+
var opts []tapsend.OutputCommitmentOption
1126+
if !stxo {
1127+
opts = append(opts, tapsend.WithNoSTXOProofs())
1128+
}
1129+
10931130
// Given the set of vPackets we've created, we'll now merge them all to
10941131
// create a map from output index to final tap commitment.
10951132
outputCommitments, err := tapsend.CreateOutputCommitments(
1096-
allPackets, tapsend.WithNoSTXOProofs(),
1133+
allPackets, opts...,
10971134
)
10981135
if err != nil {
10991136
return nil, fmt.Errorf("unable to create new output "+
@@ -1122,11 +1159,16 @@ func (f *FundingController) anchorVPackets(fundedPkt *tapsend.FundedPsbt,
11221159
for idx := range allPackets {
11231160
vPkt := allPackets[idx]
11241161

1162+
var opts []proof.GenOption
1163+
if !stxo {
1164+
opts = append(opts, proof.WithNoSTXOProofs())
1165+
}
1166+
11251167
for vOutIdx := range vPkt.Outputs {
11261168
proofSuffix, err := tapsend.CreateProofSuffix(
11271169
fundedPkt.Pkt.UnsignedTx, fundedPkt.Pkt.Outputs,
11281170
vPkt, outputCommitments, vOutIdx, allPackets,
1129-
proof.WithNoSTXOProofs(),
1171+
opts...,
11301172
)
11311173
if err != nil {
11321174
return nil, fmt.Errorf("unable to create "+
@@ -1219,7 +1261,8 @@ func (f *FundingController) sendAssetFundingCreated(ctx context.Context,
12191261
// ultimately broadcasting the funding transaction.
12201262
func (f *FundingController) completeChannelFunding(ctx context.Context,
12211263
fundingState *pendingAssetFunding,
1222-
fundedVpkt *tapfreighter.FundedVPacket) (*wire.OutPoint, error) {
1264+
fundedVpkt *tapfreighter.FundedVPacket,
1265+
stxoEnabled bool) (*wire.OutPoint, error) {
12231266

12241267
log.Debugf("Finalizing funding vPackets and PSBT...")
12251268

@@ -1330,7 +1373,7 @@ func (f *FundingController) completeChannelFunding(ctx context.Context,
13301373
// PSBT. This'll update all the pkScripts for our funding output and
13311374
// change.
13321375
fundingOutputProofs, err := f.anchorVPackets(
1333-
finalFundedPsbt, signedPkts,
1376+
finalFundedPsbt, signedPkts, stxoEnabled,
13341377
)
13351378
if err != nil {
13361379
return nil, fmt.Errorf("unable to anchor vPackets: %w", err)
@@ -1545,11 +1588,17 @@ func (f *FundingController) processFundingMsg(ctx context.Context,
15451588
"proof: %w", err)
15461589
}
15471590

1591+
features := f.cfg.AuxChanNegotiator.GetPeerFeatures(
1592+
route.Vertex(msg.PeerPub.SerializeCompressed()),
1593+
)
1594+
1595+
supportSTXO := features.HasFeature(tapfeatures.STXOOptional)
1596+
15481597
// If we reached this point, then the asset output and all
15491598
// inputs are valid, so we'll store the funding asset
15501599
// commitment.
15511600
err = assetFunding.addToFundingCommitment(
1552-
&assetProof.AssetOutput.Val,
1601+
&assetProof.AssetOutput.Val, supportSTXO,
15531602
)
15541603
if err != nil {
15551604
return tempPID, fmt.Errorf("unable to create "+
@@ -1738,6 +1787,15 @@ func (f *FundingController) processFundingReq(fundingFlows fundingFlowIndex,
17381787
maxNumAssetIDs)
17391788
}
17401789

1790+
// Now let's see if we should be using STXOs for this channel funding.
1791+
features := f.cfg.AuxChanNegotiator.GetPeerFeatures(
1792+
route.Vertex(fundReq.PeerPub.SerializeCompressed()),
1793+
)
1794+
1795+
supportSTXO := features.HasFeature(tapfeatures.STXOOptional)
1796+
1797+
fundingState.stxo = supportSTXO
1798+
17411799
// Now that we know the final funding asset root along with the splits,
17421800
// we can derive the tapscript root that'll be used alongside the
17431801
// internal key (which we'll only learn from lnd later as we finalize
@@ -1750,7 +1808,7 @@ func (f *FundingController) processFundingReq(fundingFlows fundingFlowIndex,
17501808
}
17511809

17521810
err = fundingState.addToFundingCommitment(
1753-
fundingOut.Asset.Copy(),
1811+
fundingOut.Asset.Copy(), supportSTXO,
17541812
)
17551813
if err != nil {
17561814
return fmt.Errorf("unable to add asset to funding "+
@@ -1814,7 +1872,7 @@ func (f *FundingController) processFundingReq(fundingFlows fundingFlowIndex,
18141872
}
18151873

18161874
chanPoint, err := f.completeChannelFunding(
1817-
fundReq.ctx, fundingState, fundingVpkt,
1875+
fundReq.ctx, fundingState, fundingVpkt, supportSTXO,
18181876
)
18191877
if err != nil {
18201878
// If anything went wrong during the funding process,

0 commit comments

Comments
 (0)