Skip to content

[wallet 3/3]: group key support for channel funding #1413

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

Merged
merged 16 commits into from
Apr 15, 2025
Merged

Conversation

guggero
Copy link
Member

@guggero guggero commented Feb 26, 2025

Adds the ability to fund multiple tranches of a grouped asset into a channel.

Corresponding itest: lightninglabs/lightning-terminal#987

@coveralls
Copy link

coveralls commented Feb 26, 2025

Pull Request Test Coverage Report for Build 14358733453

Details

  • 63 of 457 (13.79%) changed or added relevant lines in 18 files are covered.
  • 53 unchanged lines in 9 files lost coverage.
  • Overall coverage decreased (-0.007%) to 28.388%

Changes Missing Coverage Covered Lines Changed/Added Lines %
universe/base.go 0 2 0.0%
tapfreighter/wallet.go 0 5 0.0%
taprpc/tapchannelrpc/tapchannel.pb.go 0 5 0.0%
taprpc/taprootassets.pb.go 0 5 0.0%
tapdb/assets_store.go 34 41 82.93%
rpcserver.go 0 11 0.0%
tapfreighter/chain_porter.go 0 21 0.0%
tapchannel/aux_sweeper.go 0 22 0.0%
tapfreighter/interface.go 0 30 0.0%
tapchannel/commitment.go 0 44 0.0%
Files with Coverage Reduction New Missed Lines %
commitment/tap.go 1 72.05%
rpcserver.go 1 0.0%
asset/group_key.go 2 57.89%
tapchannel/aux_closer.go 3 0.0%
tapchannel/commitment.go 3 7.67%
tapchannel/aux_sweeper.go 4 0.0%
tapgarden/caretaker.go 4 68.53%
asset/mock.go 8 63.99%
asset/asset.go 27 48.1%
Totals Coverage Status
Change from base Build 14334641175: -0.007%
Covered Lines: 25941
Relevant Lines: 91380

💛 - Coveralls

@guggero guggero force-pushed the allocation-refactor branch 2 times, most recently from 86112a5 to cdc7cb2 Compare March 4, 2025 13:40
@guggero guggero force-pushed the group-key-support branch from 2639fa6 to 9f24e16 Compare March 4, 2025 13:40
@guggero guggero force-pushed the allocation-refactor branch from cdc7cb2 to be499e2 Compare March 4, 2025 16:19
@guggero guggero force-pushed the group-key-support branch 2 times, most recently from db987a5 to 206da82 Compare March 4, 2025 19:22
@guggero guggero force-pushed the allocation-refactor branch from be499e2 to bb88417 Compare March 4, 2025 19:22
@GeorgeTsagk GeorgeTsagk self-requested a review March 6, 2025 10:28
@guggero guggero changed the base branch from allocation-refactor to main March 6, 2025 11:31
@guggero guggero force-pushed the group-key-support branch from 206da82 to ce40ed7 Compare March 6, 2025 11:31
@levmi levmi moved this from 🏗 In progress to 👀 In review in Taproot-Assets Project Board Mar 24, 2025
@levmi levmi moved this from 👀 In review to 🏗 In progress in Taproot-Assets Project Board Mar 24, 2025
@guggero guggero force-pushed the group-key-support branch 3 times, most recently from 7356ae4 to cd1b95b Compare March 27, 2025 17:33
@github-project-automation github-project-automation bot moved this from 🏗 In progress to 👀 In review in Taproot-Assets Project Board Apr 1, 2025
Copy link
Member

@GeorgeTsagk GeorgeTsagk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very clean changes 🧹

will use the itest to better understand certain details, overall looking good! 👍

AssetSpecifier: specifier,
Amount: amt,
CoinSelectType: tapsend.Bip86Only,
DistinctSpecifier: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after seeing that we default to true here, I'm not sure in which scenarios we'd want to use false?

Will we ever have the freedom of choosing whether we'll use the ID or the groupKey of a specifier that has both? Seems to me that the intuitive choice is always picking the groupKey, but LMK what you think

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is, we already have that case. Remember when we added the itest that creates channels from a grouped asset (but only a single tranche so it would work with the code we had before this change)?
In that case we only specify the asset ID in the funding request. But because it's a grouped asset, the new logic would then also query the DB and set the group key in the specifier. And in that case we actually want to query with both, so we only fetch exactly the asset ID we supplied (and not just any asset from the group).

// Then we'll create the OP_RETURN leaf with the asset ID to make the
// resulting script key unique.
opReturnLeaf, err := asset.NewNonSpendableScriptLeaf(
asset.OpReturnVersion, id[:],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could there be a proof collision here if we somehow ended up having the same id[:]?

Is this collision taking place within the transfer's namespace or is it global?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only within a single on-chain outpoint (e.g. the funding transaction). The universe has uniqueness over the tuple (group_key_or_asset_id, script_key, outpoint). Which for multiple tranches of the same group key would all be the same for the individual UTXOs committed to the channel (because group_key would be set since it's a grouped asset, see how the universe ID works). So we just need to de-duplicate the script key by adding the asset ID to its tapscript path. And since we'd only at most have one UTXO per asset ID, there should be no additional collision possible (see comments above about merging multiple inputs of the same asset ID into a single one within the channel).

if err != nil {
return lfn.Errf[wire.TxWitness]("unable to serialize control "+
"block: %w", err)
useUniqueScriptKey := len(vPackets) > 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we assume that two different vPacket's may not use the same asset ID?
if yes could throw a comment for clarity

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. The definition for a vPacket that we arrived at is that it reflects all the changes of a single assetID within one on-chain transaction. Meaning that all the inputs and all the outputs of one asset ID within a transfer would be merged into the same vPacket. Will add a comment to make more clear.

@@ -7073,7 +7073,7 @@ func (r *rpcServer) FundChannel(ctx context.Context,
}

assetID, groupKey, err := parseAssetSpecifier(
req.GetAssetId(), "", nil, "",
req.GetAssetId(), "", req.GetGroupKey(), "",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added something similar in 667080c

@lightninglabs-deploy
Copy link

@guggero, remember to re-request review from reviewers when ready

guggero added 16 commits April 9, 2025 14:40
We've decided to only ever use a single asset ID within a virtual
packet. Which means we'd use multiple virtual packets to represent
transfers for different asset IDs.
So we don't need those early TODOs anymore.
We defined a while ago that an entry in the transfer table
corresponds to one on-chain transaction.
That means, such a transfer can house multiple virtual packets
from different asset IDs. The transfer inputs already
reflect that correctly. But the outputs were lacking the
asset ID that indicates what virtual packet the output belonged
to.
This commit fixes the problem by adding the asset ID to the
transfer output struct.
The wrong error was assigned, which caused the proof delivery failures
to not surface correctly.
Not sure why the asset ID was never used in the database proof query.
But now that we potentially have multiple asset outputs with the same
script key but different asset IDs in the same anchor transaction, it's
crucial we also add this to the query.
We changed the semantics around transfers when we implemented committing
multiple asset transfers to a single TX. We now allow
multiple virtual packets to be combined in a single transfer. Which
means we have one entry in the transfer table for each on-chain
transaction. But each transfer can have inputs and outputs from
different asset IDs (meaning different active vPackets).
This implies that it's also possible to have multiple transfer outputs
with the same script key but different asset IDs, which means we need to
change the way we identify the proof files.
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.
We're doing the same thing in three places, this commit unifies the code
by using the same function everywhere.
We always add the witness to the commitment TX before we create any of
the commitment outputs. So this witness should already be correct.
To avoid a proof collision in the universe, we need to make sure we
derive unique funding output script keys for multiple asset IDs within
the same channel funding outpoint. We do that by adding a second
OP_RETURN leaf into the tapscript tree of the funding script key. That
should ensure uniqueness of the top-level Taproot output key and only
requires us to slightly alter the control block when creating the
witness (it will now include an inclusion proof element for the
OP_RETURN leaf).
@guggero guggero force-pushed the group-key-support branch from 6e98981 to 5f672a7 Compare April 9, 2025 13:42
@guggero guggero requested review from GeorgeTsagk and Roasbeef April 9, 2025 15:10
@guggero
Copy link
Member Author

guggero commented Apr 9, 2025

Addressed all comments.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🥕

Copy link
Member

@GeorgeTsagk GeorgeTsagk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ⚡
tACK ✔️

@guggero guggero merged commit 1dd4f02 into main Apr 15, 2025
18 checks passed
@github-project-automation github-project-automation bot moved this from 👀 In review to ✅ Done in Taproot-Assets Project Board Apr 15, 2025
@guggero guggero deleted the group-key-support branch April 15, 2025 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

5 participants