Skip to content

Commit 6d018c0

Browse files
authored
Merge pull request #1041 from lightninglabs/funding-fast-fail
tapchannel: check for feature bits before opening chans
2 parents 4925c31 + cf34c65 commit 6d018c0

File tree

5 files changed

+90
-3
lines changed

5 files changed

+90
-3
lines changed

feature_bit_verifier.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package taprootassets
2+
3+
import (
4+
"context"
5+
6+
"github.com/btcsuite/btcd/btcec/v2"
7+
"github.com/lightninglabs/lndclient"
8+
"github.com/lightninglabs/taproot-assets/tapchannel"
9+
"github.com/lightningnetwork/lnd/lnwire"
10+
"github.com/lightningnetwork/lnd/routing/route"
11+
)
12+
13+
// LndFeatureBitVerifier is a struct that verifies that the feature bits of a
14+
// target connected peer, using our registered lnd node.
15+
type LndFeatureBitVerifier struct {
16+
lnd *lndclient.LndServices
17+
}
18+
19+
// NewLndFeatureBitVerifier creates a new LndFeatureBitVerifier instance.
20+
func NewLndFeatureBitVerifier(
21+
lnd *lndclient.LndServices) *LndFeatureBitVerifier {
22+
23+
return &LndFeatureBitVerifier{
24+
lnd: lnd,
25+
}
26+
}
27+
28+
// HasFeature returns true if the peer has the given feature bit set. If the
29+
// peer can't be found, then ErrNoPeer is returned.
30+
func (l *LndFeatureBitVerifier) HasFeature(ctx context.Context,
31+
peerPub btcec.PublicKey, bit lnwire.FeatureBit) (bool, error) {
32+
33+
peerBytes := route.NewVertex(&peerPub)
34+
35+
peers, err := l.lnd.Client.ListPeers(ctx)
36+
if err != nil {
37+
return false, err
38+
}
39+
40+
for _, peer := range peers {
41+
if peer.Pubkey != peerBytes {
42+
continue
43+
}
44+
45+
return peer.Features.HasFeature(bit), nil
46+
}
47+
48+
// If we get to this point, we weren't able to find the peer.
49+
return false, tapchannel.ErrNoPeer
50+
}
51+
52+
// A compile-time check to ensure that LndFeatureBitVerifier implements the
53+
// FeatureBitVerifier interface.
54+
var _ tapchannel.FeatureBitVerifer = (*LndFeatureBitVerifier)(nil)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/lib/pq v1.10.9
2929
github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030
3030
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2
31-
github.com/lightninglabs/lndclient v1.0.1-0.20240607082608-4ce52a1a3f27
31+
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf
3232
github.com/lightninglabs/neutrino/cache v1.1.2
3333
github.com/lightningnetwork/lnd v0.18.0-beta.rc4.0.20240723043204-f09d4042aee4
3434
github.com/lightningnetwork/lnd/cert v1.2.2

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,8 @@ github.com/lightninglabs/lightning-node-connect v0.2.5-alpha h1:ZRVChwczFXK0CEbx
480480
github.com/lightninglabs/lightning-node-connect v0.2.5-alpha/go.mod h1:A9Pof9fETkH+F67BnOmrBDThPKstqp73wlImWOZvTXQ=
481481
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2 h1:Er1miPZD2XZwcfE4xoS5AILqP1mj7kqnhbBSxW9BDxY=
482482
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2/go.mod h1:antQGRDRJiuyQF6l+k6NECCSImgCpwaZapATth2Chv4=
483-
github.com/lightninglabs/lndclient v1.0.1-0.20240607082608-4ce52a1a3f27 h1:vm8a13EzH2Qe6j4eZx+tHPeEVoNhJ7coihFPX6K2kco=
484-
github.com/lightninglabs/lndclient v1.0.1-0.20240607082608-4ce52a1a3f27/go.mod h1:bxd2a15cIaW8KKcmOf9nNDI/GTxxj0upEYs1EIkttqw=
483+
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf h1:VcTK/juPtAqwEBckCcSHCsVRSbHGbWtDZgnXL5JOLkg=
484+
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf/go.mod h1:bxd2a15cIaW8KKcmOf9nNDI/GTxxj0upEYs1EIkttqw=
485485
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s=
486486
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk=
487487
github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3shmlu5hIQ798g=

tapcfg/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
102102
msgTransportClient := tap.NewLndMsgTransportClient(lndServices)
103103
lndRouterClient := tap.NewLndRouterClient(lndServices)
104104
lndInvoicesClient := tap.NewLndInvoicesClient(lndServices)
105+
lndFeatureBitsVerifier := tap.NewLndFeatureBitVerifier(lndServices)
105106

106107
uniDB := tapdb.NewTransactionExecutor(
107108
db, func(tx *sql.Tx) tapdb.BaseUniverseStore {
@@ -434,6 +435,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
434435
TxSender: chainPorter,
435436
DefaultCourierAddr: proofCourierAddr,
436437
AssetSyncer: addrBook,
438+
FeatureBits: lndFeatureBitsVerifier,
437439
},
438440
)
439441
auxTrafficShaper := tapchannel.NewAuxTrafficShaper(

tapchannel/aux_funding_controller.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ type PeerMessenger interface {
7070
msg lnwire.Message) error
7171
}
7272

73+
// ErrNoPeer is returned when a peer can't be found.
74+
var ErrNoPeer = errors.New("peer not found")
75+
76+
// FeatureBitVerifer is an interface that allows us to verify that a peer has a
77+
// given feature bit set.
78+
type FeatureBitVerifer interface {
79+
// HasFeature returns true if the peer has the given feature bit set.
80+
// If the peer can't be found, then ErrNoPeer is returned.
81+
HasFeature(ctx context.Context, peerPub btcec.PublicKey,
82+
bit lnwire.FeatureBit) (bool, error)
83+
}
84+
7385
// OpenChanReq is a request to open a new asset channel with a remote peer.
7486
type OpenChanReq struct {
7587
// ChanAmt is the amount of BTC to put into the channel. Some BTC is
@@ -200,6 +212,10 @@ type FundingControllerCfg struct {
200212
// AssetSyncer is used to ensure that we've already verified the asset
201213
// genesis for any assets used within channels.
202214
AssetSyncer AssetSyncer
215+
216+
// FeatureBits is used to verify that the peer has the required feature
217+
// to fund asset channels.
218+
FeatureBits FeatureBitVerifer
203219
}
204220

205221
// bindFundingReq is a request to bind a pending channel ID to a complete aux
@@ -1322,6 +1338,21 @@ func (f *FundingController) processFundingMsg(ctx context.Context,
13221338
func (f *FundingController) processFundingReq(fundingFlows fundingFlowIndex,
13231339
fundReq *FundReq) error {
13241340

1341+
// Before we even attempt funding, let's make sure that the remote peer
1342+
// actually supports the feature bit.
1343+
supportsAssetChans, err := f.cfg.FeatureBits.HasFeature(
1344+
fundReq.ctx, fundReq.PeerPub,
1345+
lnwire.SimpleTaprootOverlayChansOptional,
1346+
)
1347+
if err != nil {
1348+
return fmt.Errorf("unable to query peer feature bits: %w", err)
1349+
}
1350+
1351+
if !supportsAssetChans {
1352+
return fmt.Errorf("peer %x does not support asset channels",
1353+
fundReq.PeerPub.SerializeCompressed())
1354+
}
1355+
13251356
// To start, we'll make a new pending asset funding desc. This'll be
13261357
// our scratch pad during the asset funding process.
13271358
tempPID, err := newPendingChanID()

0 commit comments

Comments
 (0)