Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,9 @@ func (s *Server) FetchLeavesFromView(

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

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

Expand Down Expand Up @@ -880,7 +883,9 @@ func (s *Server) ApplyHtlcView(

// The aux leaf creator is fully stateless, and we don't need to wait
// for the server to be started before being able to use it.
return tapchannel.ApplyHtlcView(s.chainParams, in)
return tapchannel.ApplyHtlcView(
s.chainParams, in, s.cfg.AuxChanNegotiator,
)
}

// InlineParseCustomData replaces any custom data binary blob in the given RPC
Expand Down
4 changes: 3 additions & 1 deletion tapcfg/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
DefaultCourierAddr: proofCourierAddr,
AssetSyncer: addrBook,
FeatureBits: lndFeatureBitsVerifier,
AuxChanNegotiator: auxChanNegotiator,
ErrChan: mainErrChan,
},
)
Expand Down Expand Up @@ -567,7 +568,8 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
GroupVerifier: tapgarden.GenGroupVerifier(
context.Background(), assetMintingStore,
),
ChainBridge: chainBridge,
ChainBridge: chainBridge,
AuxChanNegotiator: auxChanNegotiator,
},
)
auxSweeper := tapchannel.NewAuxSweeper(
Expand Down
32 changes: 30 additions & 2 deletions tapchannel/aux_closer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/lightninglabs/taproot-assets/fn"
"github.com/lightninglabs/taproot-assets/proof"
"github.com/lightninglabs/taproot-assets/tapchannelmsg"
"github.com/lightninglabs/taproot-assets/tapfeatures"
"github.com/lightninglabs/taproot-assets/tapfreighter"
"github.com/lightninglabs/taproot-assets/tapgarden"
"github.com/lightninglabs/taproot-assets/tappsbt"
Expand Down Expand Up @@ -62,6 +63,11 @@ type AuxChanCloserCfg struct {

// ChainBridge is used to fetch blocks from the main chain.
ChainBridge tapgarden.ChainBridge

// AuxChanNegotiator is responsible for producing the extra tlv blob
// that is encapsulated in the init and reestablish peer messages. This
// helps us communicate custom feature bits with our peer.
AuxChanNegotiator *tapfeatures.AuxChannelNegotiator
}

// assetCloseInfo houses the information we need to finalize the close of an
Expand Down Expand Up @@ -450,11 +456,21 @@ func (a *AuxChanCloser) AuxCloseOutputs(
"packets: %w", err)
}

features := a.cfg.AuxChanNegotiator.GetChannelFeatures(
lnwire.NewChanIDFromOutPoint(desc.ChanPoint),
)
supportSTXO := features.HasFeature(tapfeatures.STXOOptional)

var opts []tapsend.OutputCommitmentOption
if !supportSTXO {
opts = append(opts, tapsend.WithNoSTXOProofs())
}

// With the outputs prepared, we can now create the set of output
// commitments, then with the output index locations known, we can set
// the output indexes in the allocations.
outCommitments, err := tapsend.CreateOutputCommitments(
vPackets, tapsend.WithNoSTXOProofs(),
vPackets, opts...,
)
if err != nil {
return none, fmt.Errorf("unable to create output "+
Expand Down Expand Up @@ -723,10 +739,22 @@ func (a *AuxChanCloser) FinalizeClose(desc chancloser.AuxCloseDesc,
closeInfo.allocations,
)

features := a.cfg.AuxChanNegotiator.GetChannelFeatures(
lnwire.NewChanIDFromOutPoint(desc.ChanPoint),
)
supportSTXO := features.HasFeature(
tapfeatures.STXOOptional,
)

var opts []proof.GenOption
if !supportSTXO {
opts = append(opts, proof.WithNoSTXOProofs())
}

proofSuffix, err := tapsend.CreateProofSuffixCustom(
closeTx, vPkt, closeInfo.outputCommitments,
outIdx, closeInfo.vPackets, exclusionCreator,
proof.WithNoSTXOProofs(),
opts...,
)
if err != nil {
return fmt.Errorf("unable to create proof "+
Expand Down
89 changes: 83 additions & 6 deletions tapchannel/aux_funding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"github.com/lightninglabs/taproot-assets/rfq"
cmsg "github.com/lightninglabs/taproot-assets/tapchannelmsg"
"github.com/lightninglabs/taproot-assets/tapdb"
"github.com/lightninglabs/taproot-assets/tapfeatures"
"github.com/lightninglabs/taproot-assets/tapfreighter"
"github.com/lightninglabs/taproot-assets/tapgarden"
"github.com/lightninglabs/taproot-assets/tappsbt"
Expand All @@ -41,6 +42,7 @@
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/msgmux"
"github.com/lightningnetwork/lnd/routing/route"
)

const (
Expand Down Expand Up @@ -265,6 +267,11 @@
// to fund asset channels.
FeatureBits FeatureBitVerifer

// AuxChanNegotiator is responsible for producing the extra tlv blob
// that is encapsulated in the init and reestablish peer messages. This
// helps us communicate custom feature bits with our peer.
AuxChanNegotiator *tapfeatures.AuxChannelNegotiator

// ErrChan is used to report errors back to the main server.
ErrChan chan<- error
}
Expand Down Expand Up @@ -415,6 +422,8 @@

initiator bool

stxo bool

amt uint64

pushAmt btcutil.Amount
Expand Down Expand Up @@ -520,7 +529,8 @@
func newCommitBlobAndLeaves(pendingFunding *pendingAssetFunding,
lndOpenChan lnwallet.AuxChanState, assetOpenChan *cmsg.OpenChannel,
keyRing lntypes.Dual[lnwallet.CommitmentKeyRing],
whoseCommit lntypes.ChannelParty) ([]byte, lnwallet.CommitAuxLeaves,
whoseCommit lntypes.ChannelParty,
stxo bool) ([]byte, lnwallet.CommitAuxLeaves,
error) {

chanAssets := assetOpenChan.FundedAssets.Val.Outputs
Expand Down Expand Up @@ -567,6 +577,7 @@
fakePrevState, lndOpenChan, assetOpenChan, whoseCommit,
localSatBalance, remoteSatBalance, fakeView,
pendingFunding.chainParams, keyRing.GetForParty(whoseCommit),
stxo,
)
if err != nil {
return nil, lnwallet.CommitAuxLeaves{}, err
Expand Down Expand Up @@ -609,12 +620,14 @@
// This will be the information for the very first state (state 0).
localCommitBlob, localAuxLeaves, err := newCommitBlobAndLeaves(
p, req.openChan, openChanDesc, req.keyRing, lntypes.Local,
p.stxo,
)
if err != nil {
return nil, err
}
remoteCommitBlob, remoteAuxLeaves, err := newCommitBlobAndLeaves(
p, req.openChan, openChanDesc, req.keyRing, lntypes.Remote,
p.stxo,
)
if err != nil {
return nil, err
Expand Down Expand Up @@ -1078,12 +1091,15 @@
// complete, but unsigned PSBT packet that can be used to create out asset
// channel.
func (f *FundingController) anchorVPackets(fundedPkt *tapsend.FundedPsbt,
allPackets []*tappsbt.VPacket) ([]*proof.Proof, error) {
allPackets []*tappsbt.VPacket, stxo bool) ([]*proof.Proof, error) {

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

// Given the set of vPackets we've created, we'll now merge them all to
// create a map from output index to final tap commitment.
// We don't use STXO proofs here as we already manually added the
// corresponding alt-leaves in a previous step. Creating the commitments
// here with STXO generation will lead to a conflict in the alt leaves.
outputCommitments, err := tapsend.CreateOutputCommitments(
allPackets, tapsend.WithNoSTXOProofs(),
)
Expand Down Expand Up @@ -1114,11 +1130,16 @@
for idx := range allPackets {
vPkt := allPackets[idx]

var opts []proof.GenOption
if !stxo {
opts = append(opts, proof.WithNoSTXOProofs())
}

for vOutIdx := range vPkt.Outputs {
proofSuffix, err := tapsend.CreateProofSuffix(
fundedPkt.Pkt.UnsignedTx, fundedPkt.Pkt.Outputs,
vPkt, outputCommitments, vOutIdx, allPackets,
proof.WithNoSTXOProofs(),
opts...,
)
if err != nil {
return nil, fmt.Errorf("unable to create "+
Expand Down Expand Up @@ -1211,7 +1232,8 @@
// ultimately broadcasting the funding transaction.
func (f *FundingController) completeChannelFunding(ctx context.Context,
fundingState *pendingAssetFunding,
fundedVpkt *tapfreighter.FundedVPacket) (*wire.OutPoint, error) {
fundedVpkt *tapfreighter.FundedVPacket,
stxoEnabled bool) (*wire.OutPoint, error) {

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

Expand Down Expand Up @@ -1322,7 +1344,7 @@
// PSBT. This'll update all the pkScripts for our funding output and
// change.
fundingOutputProofs, err := f.anchorVPackets(
finalFundedPsbt, signedPkts,
finalFundedPsbt, signedPkts, stxoEnabled,
)
if err != nil {
return nil, fmt.Errorf("unable to anchor vPackets: %w", err)
Expand Down Expand Up @@ -1547,6 +1569,28 @@
"commitment: %w", err)
}

supportSTXO := f.cfg.AuxChanNegotiator.GetPeerFeatures(
route.Vertex(msg.PeerPub.SerializeCompressed()),
).HasFeature(tapfeatures.STXOOptional)

assetFunding.stxo = supportSTXO

// If we've the feature bit negotiation resulted in the use of
// STXO proofs, then we need to collect the alt leaves and
// merge them to the funding commitment.
if supportSTXO {
altLeaves, err := asset.CollectSTXO(
&assetProof.AssetOutput.Val,
)
if err != nil {
return tempPID, err
}

assetFunding.fundingAssetCommitment.MergeAltLeaves(

Check failure on line 1589 in tapchannel/aux_funding_controller.go

View workflow job for this annotation

GitHub Actions / Lint check

Error return value of `assetFunding.fundingAssetCommitment.MergeAltLeaves` is not checked (errcheck)
altLeaves,
)
}

// Do we expect more proofs to be incoming?
if !assetProof.Last.Val {
return tempPID, nil
Expand Down Expand Up @@ -1704,6 +1748,13 @@
}
}

// Now let's see if we should be using STXOs for this channel funding.
supportSTXO := f.cfg.AuxChanNegotiator.GetPeerFeatures(
route.Vertex(fundReq.PeerPub.SerializeCompressed()),
).HasFeature(tapfeatures.STXOOptional)

fundingState.stxo = supportSTXO

// Register a defer to execute if none of the setup below succeeds.
// This ensures we always unlock the UTXO.
var setupSuccess bool
Expand Down Expand Up @@ -1740,13 +1791,39 @@
"packet: %w", err)
}

// If our peer supports STXO we go ahead and append the
// appropriate alt leaves to each VOutput. This is needed in
// this step as this tapscript root will be kept as reference by
// LND to identify the funding outpoint. Later when we continue
// the funding process we'll skip creating/merging the leaves
// again to avoid a conflict in the alt leaf tree.
if supportSTXO {
for _, o := range pkt.Outputs {
altLeaves, err := asset.CollectSTXO(o.Asset)
if err != nil {
return err
}

o.AltLeaves = append(o.AltLeaves, altLeaves...)
}
}

err = fundingState.addToFundingCommitment(
fundingOut.Asset.Copy(),
)
if err != nil {
return fmt.Errorf("unable to add asset to funding "+
"commitment: %w", err)
}

// We now merge the alt leaves to the funding commitment.
for _, o := range pkt.Outputs {
commitment := fundingState.fundingAssetCommitment
err = commitment.MergeAltLeaves(o.AltLeaves)
if err != nil {
return err
}
}
}

tapsend.LogCommitment(
Expand Down Expand Up @@ -1805,7 +1882,7 @@
}

chanPoint, err := f.completeChannelFunding(
fundReq.ctx, fundingState, fundingVpkt,
fundReq.ctx, fundingState, fundingVpkt, supportSTXO,
)
if err != nil {
// If anything went wrong during the funding process,
Expand Down
Loading
Loading