@@ -576,15 +576,18 @@ func newCommitBlobAndLeaves(pendingFunding *pendingAssetFunding,
576576// both sides are able to construct the funding output, and will be able to
577577// store the appropriate funding blobs.
578578func (p * pendingAssetFunding ) toAuxFundingDesc (req * bindFundingReq ,
579- decimalDisplay uint8 ) (* lnwallet.AuxFundingDesc , error ) {
579+ decimalDisplay uint8 ,
580+ groupKey * btcec.PublicKey ) (* lnwallet.AuxFundingDesc , error ) {
580581
581582 // First, we'll map all the assets into asset outputs that'll be stored
582583 // in the open channel struct on the lnd side.
583584 assetOutputs := p .assetOutputs ()
584585
585586 // With all the outputs assembled, we'll now map that to the open
586587 // channel wrapper that'll go in the set of TLV blobs.
587- openChanDesc := cmsg .NewOpenChannel (assetOutputs , decimalDisplay )
588+ openChanDesc := cmsg .NewOpenChannel (
589+ assetOutputs , decimalDisplay , groupKey ,
590+ )
588591
589592 // Now we'll encode the 3 TLV blobs that lnd will store: the main one
590593 // for the funding details, and then the blobs for the local and remote
@@ -1933,8 +1936,20 @@ func (f *FundingController) chanFunder() {
19331936 continue
19341937 }
19351938
1939+ groupKey , err := f .fundingAssetGroupKey (
1940+ ctxc , fundingFlow .assetOutputs (),
1941+ )
1942+ if err != nil {
1943+ fErr := fmt .Errorf ("unable to determine group " +
1944+ "key: %w" , err )
1945+ f .cfg .ErrReporter .ReportError (
1946+ ctxc , fundingFlow .peerPub , pid , fErr ,
1947+ )
1948+ continue
1949+ }
1950+
19361951 fundingDesc , err := fundingFlow .toAuxFundingDesc (
1937- req , decimalDisplay ,
1952+ req , decimalDisplay , groupKey ,
19381953 )
19391954 if err != nil {
19401955 fErr := fmt .Errorf ("unable to create aux " +
@@ -2029,6 +2044,65 @@ func (f *FundingController) fundingAssetDecimalDisplay(ctx context.Context,
20292044 return decimalDisplay , nil
20302045}
20312046
2047+ // fundingAssetGroupKey determines the group key of the funding asset(s). If no
2048+ // group key was used to fund the channel, then nil is returned.
2049+ func (f * FundingController ) fundingAssetGroupKey (ctx context.Context ,
2050+ assetOutputs []* cmsg.AssetOutput ) (* btcec.PublicKey , error ) {
2051+
2052+ // We now check the group key of each funding asset, to make sure we
2053+ // know the meta information for each asset. And we also verify that
2054+ // each asset tranche has the same group key.
2055+ var groupKey * btcec.PublicKey
2056+ for _ , a := range assetOutputs {
2057+ info , err := f .cfg .AssetSyncer .QueryAssetInfo (
2058+ ctx , a .AssetID .Val ,
2059+ )
2060+ switch {
2061+ // If the asset isn't a grouped asset (or we don't know the
2062+ // asset), then we just continue.
2063+ case errors .Is (err , address .ErrAssetGroupUnknown ):
2064+ continue
2065+
2066+ case err != nil :
2067+ return nil , fmt .Errorf ("unable to fetch group info: %w" ,
2068+ err )
2069+ }
2070+
2071+ switch {
2072+ // We haven't set the group key before and have found one now,
2073+ // perfect. Let's assume that's our group key we'll use.
2074+ case groupKey == nil && info .GroupKey != nil :
2075+ groupKey = & info .GroupKey .GroupPubKey
2076+
2077+ // If we already have a group key, then we need to verify that
2078+ // the group key of this asset matches the one we already have.
2079+ case groupKey != nil && info .GroupKey != nil :
2080+ if ! groupKey .IsEqual (& info .GroupKey .GroupPubKey ) {
2081+ return nil , fmt .Errorf ("group key mismatch: " +
2082+ "expected %x, got %x" ,
2083+ groupKey .SerializeCompressed (),
2084+ info .GroupPubKey .SerializeCompressed ())
2085+ }
2086+
2087+ // If a previous asset resulted in a group key, every following
2088+ // one must also result in the same one. If we can't find one
2089+ // now, it means we either don't know about the asset (not
2090+ // synced) or it's not a grouped asset.
2091+ case groupKey != nil && info .GroupKey == nil :
2092+ return nil , fmt .Errorf ("group key mismatch: " +
2093+ "expected %x, got nil" ,
2094+ groupKey .SerializeCompressed ())
2095+
2096+ // If we don't have a group key yet, and the asset isn't a
2097+ // grouped asset, then we just continue.
2098+ case groupKey == nil && info .GroupKey == nil :
2099+ continue
2100+ }
2101+ }
2102+
2103+ return groupKey , nil
2104+ }
2105+
20322106// channelAcceptor is a callback that's called by the lnd client when a new
20332107// channel is proposed. This function is responsible for deciding whether to
20342108// accept the channel based on the channel parameters, and to also set some
0 commit comments