Skip to content

Commit

Permalink
Merge pull request #1041 from lightninglabs/funding-fast-fail
Browse files Browse the repository at this point in the history
tapchannel: check for feature bits before opening chans
  • Loading branch information
Roasbeef authored Aug 1, 2024
2 parents 4925c31 + cf34c65 commit 6d018c0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 3 deletions.
54 changes: 54 additions & 0 deletions feature_bit_verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package taprootassets

import (
"context"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/taproot-assets/tapchannel"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)

// LndFeatureBitVerifier is a struct that verifies that the feature bits of a
// target connected peer, using our registered lnd node.
type LndFeatureBitVerifier struct {
lnd *lndclient.LndServices
}

// NewLndFeatureBitVerifier creates a new LndFeatureBitVerifier instance.
func NewLndFeatureBitVerifier(
lnd *lndclient.LndServices) *LndFeatureBitVerifier {

return &LndFeatureBitVerifier{
lnd: lnd,
}
}

// HasFeature returns true if the peer has the given feature bit set. If the
// peer can't be found, then ErrNoPeer is returned.
func (l *LndFeatureBitVerifier) HasFeature(ctx context.Context,
peerPub btcec.PublicKey, bit lnwire.FeatureBit) (bool, error) {

peerBytes := route.NewVertex(&peerPub)

peers, err := l.lnd.Client.ListPeers(ctx)
if err != nil {
return false, err
}

for _, peer := range peers {
if peer.Pubkey != peerBytes {
continue
}

return peer.Features.HasFeature(bit), nil
}

// If we get to this point, we weren't able to find the peer.
return false, tapchannel.ErrNoPeer
}

// A compile-time check to ensure that LndFeatureBitVerifier implements the
// FeatureBitVerifier interface.
var _ tapchannel.FeatureBitVerifer = (*LndFeatureBitVerifier)(nil)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/lib/pq v1.10.9
github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2
github.com/lightninglabs/lndclient v1.0.1-0.20240607082608-4ce52a1a3f27
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf
github.com/lightninglabs/neutrino/cache v1.1.2
github.com/lightningnetwork/lnd v0.18.0-beta.rc4.0.20240723043204-f09d4042aee4
github.com/lightningnetwork/lnd/cert v1.2.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ github.com/lightninglabs/lightning-node-connect v0.2.5-alpha h1:ZRVChwczFXK0CEbx
github.com/lightninglabs/lightning-node-connect v0.2.5-alpha/go.mod h1:A9Pof9fETkH+F67BnOmrBDThPKstqp73wlImWOZvTXQ=
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2 h1:Er1miPZD2XZwcfE4xoS5AILqP1mj7kqnhbBSxW9BDxY=
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2/go.mod h1:antQGRDRJiuyQF6l+k6NECCSImgCpwaZapATth2Chv4=
github.com/lightninglabs/lndclient v1.0.1-0.20240607082608-4ce52a1a3f27 h1:vm8a13EzH2Qe6j4eZx+tHPeEVoNhJ7coihFPX6K2kco=
github.com/lightninglabs/lndclient v1.0.1-0.20240607082608-4ce52a1a3f27/go.mod h1:bxd2a15cIaW8KKcmOf9nNDI/GTxxj0upEYs1EIkttqw=
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf h1:VcTK/juPtAqwEBckCcSHCsVRSbHGbWtDZgnXL5JOLkg=
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf/go.mod h1:bxd2a15cIaW8KKcmOf9nNDI/GTxxj0upEYs1EIkttqw=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk=
github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3shmlu5hIQ798g=
Expand Down
2 changes: 2 additions & 0 deletions tapcfg/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
msgTransportClient := tap.NewLndMsgTransportClient(lndServices)
lndRouterClient := tap.NewLndRouterClient(lndServices)
lndInvoicesClient := tap.NewLndInvoicesClient(lndServices)
lndFeatureBitsVerifier := tap.NewLndFeatureBitVerifier(lndServices)

uniDB := tapdb.NewTransactionExecutor(
db, func(tx *sql.Tx) tapdb.BaseUniverseStore {
Expand Down Expand Up @@ -434,6 +435,7 @@ func genServerConfig(cfg *Config, cfgLogger btclog.Logger,
TxSender: chainPorter,
DefaultCourierAddr: proofCourierAddr,
AssetSyncer: addrBook,
FeatureBits: lndFeatureBitsVerifier,
},
)
auxTrafficShaper := tapchannel.NewAuxTrafficShaper(
Expand Down
31 changes: 31 additions & 0 deletions tapchannel/aux_funding_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ type PeerMessenger interface {
msg lnwire.Message) error
}

// ErrNoPeer is returned when a peer can't be found.
var ErrNoPeer = errors.New("peer not found")

// FeatureBitVerifer is an interface that allows us to verify that a peer has a
// given feature bit set.
type FeatureBitVerifer interface {
// HasFeature returns true if the peer has the given feature bit set.
// If the peer can't be found, then ErrNoPeer is returned.
HasFeature(ctx context.Context, peerPub btcec.PublicKey,
bit lnwire.FeatureBit) (bool, error)
}

// OpenChanReq is a request to open a new asset channel with a remote peer.
type OpenChanReq struct {
// ChanAmt is the amount of BTC to put into the channel. Some BTC is
Expand Down Expand Up @@ -200,6 +212,10 @@ type FundingControllerCfg struct {
// AssetSyncer is used to ensure that we've already verified the asset
// genesis for any assets used within channels.
AssetSyncer AssetSyncer

// FeatureBits is used to verify that the peer has the required feature
// to fund asset channels.
FeatureBits FeatureBitVerifer
}

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

// Before we even attempt funding, let's make sure that the remote peer
// actually supports the feature bit.
supportsAssetChans, err := f.cfg.FeatureBits.HasFeature(
fundReq.ctx, fundReq.PeerPub,
lnwire.SimpleTaprootOverlayChansOptional,
)
if err != nil {
return fmt.Errorf("unable to query peer feature bits: %w", err)
}

if !supportsAssetChans {
return fmt.Errorf("peer %x does not support asset channels",
fundReq.PeerPub.SerializeCompressed())
}

// To start, we'll make a new pending asset funding desc. This'll be
// our scratch pad during the asset funding process.
tempPID, err := newPendingChanID()
Expand Down

0 comments on commit 6d018c0

Please sign in to comment.