Skip to content

Commit ce40ed7

Browse files
committed
tapchannel: fix allocation handling
One allocation entry means one on-chain output. So we should not create multiple allocations for the same balance (e.g. if there are multiple asset pieces with different asset IDs in the local or remote balance). Instead we just create one allocation for the sum, then let the coin distribution algorithm decide what output goes where.
1 parent 6ddd26a commit ce40ed7

File tree

2 files changed

+37
-34
lines changed

2 files changed

+37
-34
lines changed

Diff for: tapchannel/aux_closer.go

+22-25
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,9 @@ func (a *AuxChanCloser) ShutdownBlob(
484484
none := lfn.None[lnwire.CustomRecords]()
485485

486486
// If there's no custom blob, then we don't need to do anything.
487-
if req.CommitBlob.IsNone() {
488-
log.Debugf("No commit blob for ChannelPoint(%v)", req.ChanPoint)
487+
if req.FundingBlob.IsNone() {
488+
log.Debugf("No funding blob for ChannelPoint(%v)",
489+
req.ChanPoint)
489490
return none, nil
490491
}
491492

@@ -500,16 +501,16 @@ func (a *AuxChanCloser) ShutdownBlob(
500501
log.Infof("Creating shutdown blob for close of ChannelPoint(%v)",
501502
req.ChanPoint)
502503

503-
// Otherwise, we'll decode the commitment, so we can examine the current
504-
// state.
505-
var commitState tapchannelmsg.Commitment
506-
err = lfn.MapOptionZ(req.CommitBlob, func(blob tlv.Blob) error {
507-
c, err := tapchannelmsg.DecodeCommitment(blob)
504+
// Otherwise, we'll decode the funding state, so we can examine the
505+
// different asset IDs in the channel.
506+
var fundingState tapchannelmsg.OpenChannel
507+
err = lfn.MapOptionZ(req.FundingBlob, func(blob tlv.Blob) error {
508+
c, err := tapchannelmsg.DecodeOpenChannel(blob)
508509
if err != nil {
509510
return err
510511
}
511512

512-
commitState = *c
513+
fundingState = *c
513514

514515
return nil
515516
})
@@ -528,38 +529,34 @@ func (a *AuxChanCloser) ShutdownBlob(
528529
return none, err
529530
}
530531

531-
// Next, we'll collect all the assets that we own in this channel.
532-
assets := commitState.LocalAssets.Val.Outputs
532+
// Next, we'll collect all the asset IDs that were committed to the
533+
// channel.
534+
assetIDs := fn.Map(
535+
fundingState.FundedAssets.Val.Outputs,
536+
func(o *tapchannelmsg.AssetOutput) asset.ID {
537+
return o.AssetID.Val
538+
},
539+
)
533540

534541
// Now that we have all the asset IDs, we'll query for a new key for
535542
// each of them which we'll use as both the internal key and the script
536543
// key.
537544
scriptKeys := make(tapchannelmsg.ScriptKeyMap)
538-
for idx := range assets {
539-
channelAsset := assets[idx]
540-
545+
for _, assetID := range assetIDs {
541546
newKey, err := a.cfg.AddrBook.NextScriptKey(
542547
ctx, asset.TaprootAssetsKeyFamily,
543548
)
544549
if err != nil {
545550
return none, err
546551
}
547552

548-
// We now add the a
549-
// TODO(guggero): This only works if there's only a single asset
550-
// in the channel. We need to extend this to support multiple
551-
// assets.
552-
_, err = a.cfg.AddrBook.NewAddressWithKeys(
553-
ctx, address.V1, channelAsset.AssetID.Val,
554-
channelAsset.Amount.Val, newKey, newInternalKey, nil,
555-
*a.cfg.DefaultCourierAddr,
556-
)
553+
err = a.cfg.AddrBook.InsertScriptKey(ctx, newKey, true)
557554
if err != nil {
558-
return none, fmt.Errorf("error adding new address: %w",
559-
err)
555+
return none, fmt.Errorf("error declaring script key: "+
556+
"%w", err)
560557
}
561558

562-
scriptKeys[channelAsset.AssetID.Val] = *newKey.PubKey
559+
scriptKeys[assetID] = *newKey.PubKey
563560
}
564561

565562
// Finally, we'll map the extra shutdown info to a TLV record map we

Diff for: tapchannel/aux_sweeper.go

+15-9
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,9 @@ func (a *AuxSweeper) resolveContract(
18761876
return lfn.Err[tlv.Blob](err)
18771877
}
18781878

1879+
type packetList = []*tappsbt.VPacket
18791880
var (
1880-
secondLevelPkts []*tappsbt.VPacket
1881+
secondLevelPkts packetList
18811882
secondLevelSigDesc lfn.Option[cmsg.TapscriptSigDesc]
18821883
)
18831884

@@ -1886,25 +1887,30 @@ func (a *AuxSweeper) resolveContract(
18861887
if needsSecondLevel {
18871888
log.Infof("Creating+signing 2nd level vPkts")
18881889

1889-
// We'll make a place holder for the second level output based
1890-
// on the assetID+value tuple.
1891-
secondLevelInputs := []*cmsg.AssetOutput{cmsg.NewAssetOutput(
1892-
assetOutputs[0].AssetID.Val,
1893-
assetOutputs[0].Amount.Val, assetOutputs[0].Proof.Val,
1894-
)}
1890+
// We'll make a placeholder for the second level output based
1891+
// on the assetID+value tuples.
1892+
secondLevelInputs := fn.Map(
1893+
assetOutputs,
1894+
func(a *cmsg.AssetOutput) *cmsg.AssetOutput {
1895+
return cmsg.NewAssetOutput(
1896+
a.AssetID.Val, a.Amount.Val,
1897+
a.Proof.Val,
1898+
)
1899+
},
1900+
)
18951901

18961902
// Unlike the first level packets, we can't yet sign the second
18971903
// level packets yet, as we don't know what the sweeping
18981904
// transaction will look like. So we'll just create them.
18991905
secondLevelPkts, err = lfn.MapOption(
19001906
//nolint:lll
1901-
func(desc tapscriptSweepDesc) lfn.Result[[]*tappsbt.VPacket] {
1907+
func(desc tapscriptSweepDesc) lfn.Result[packetList] {
19021908
return a.createSweepVpackets(
19031909
secondLevelInputs, lfn.Ok(desc), req,
19041910
)
19051911
},
19061912
)(tapSweepDesc.secondLevel).UnwrapOr(
1907-
lfn.Ok[[]*tappsbt.VPacket](nil),
1913+
lfn.Ok[packetList](nil),
19081914
).Unpack()
19091915
if err != nil {
19101916
return lfn.Errf[tlv.Blob]("unable to make "+

0 commit comments

Comments
 (0)