mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-23 22:46:40 +01:00
Merge pull request #6075 from Roasbeef/chan-type-satisfice
funding: always send a channel type in explicit mode
This commit is contained in:
commit
d13246dbc2
4 changed files with 81 additions and 34 deletions
|
@ -5,6 +5,9 @@
|
||||||
* [Return the nearest known fee rate when a given conf target cannot be found
|
* [Return the nearest known fee rate when a given conf target cannot be found
|
||||||
from Web API fee estimator.](https://github.com/lightningnetwork/lnd/pull/6062)
|
from Web API fee estimator.](https://github.com/lightningnetwork/lnd/pull/6062)
|
||||||
|
|
||||||
|
* [We now _always_ set a channel type if the other party signals the feature
|
||||||
|
bit](https://github.com/lightningnetwork/lnd/pull/6075).
|
||||||
|
|
||||||
## Wallet
|
## Wallet
|
||||||
|
|
||||||
* A bug that prevented opening anchor-based channels from external wallets when
|
* A bug that prevented opening anchor-based channels from external wallets when
|
||||||
|
|
|
@ -26,8 +26,8 @@ var (
|
||||||
// will be attempted if the set of both local and remote features support it.
|
// will be attempted if the set of both local and remote features support it.
|
||||||
// Otherwise, implicit negotiation will be attempted.
|
// Otherwise, implicit negotiation will be attempted.
|
||||||
func negotiateCommitmentType(channelType *lnwire.ChannelType,
|
func negotiateCommitmentType(channelType *lnwire.ChannelType,
|
||||||
local, remote *lnwire.FeatureVector,
|
local, remote *lnwire.FeatureVector, mustBeExplicit bool,
|
||||||
mustBeExplicit bool) (bool, lnwallet.CommitmentType, error) {
|
) (bool, *lnwire.ChannelType, lnwallet.CommitmentType, error) {
|
||||||
|
|
||||||
if channelType != nil {
|
if channelType != nil {
|
||||||
// If the peer does know explicit negotiation, let's attempt
|
// If the peer does know explicit negotiation, let's attempt
|
||||||
|
@ -36,7 +36,7 @@ func negotiateCommitmentType(channelType *lnwire.ChannelType,
|
||||||
chanType, err := explicitNegotiateCommitmentType(
|
chanType, err := explicitNegotiateCommitmentType(
|
||||||
*channelType, local, remote,
|
*channelType, local, remote,
|
||||||
)
|
)
|
||||||
return true, chanType, err
|
return true, channelType, chanType, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're the funder, and we are attempting to use an
|
// If we're the funder, and we are attempting to use an
|
||||||
|
@ -45,11 +45,12 @@ func negotiateCommitmentType(channelType *lnwire.ChannelType,
|
||||||
// user doesn't end up with an unexpected channel type via
|
// user doesn't end up with an unexpected channel type via
|
||||||
// implicit negotiation.
|
// implicit negotiation.
|
||||||
if mustBeExplicit {
|
if mustBeExplicit {
|
||||||
return false, 0, errUnsupportedExplicitNegotiation
|
return false, nil, 0, errUnsupportedExplicitNegotiation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, implicitNegotiateCommitmentType(local, remote), nil
|
chanType, commitType := implicitNegotiateCommitmentType(local, remote)
|
||||||
|
return false, chanType, commitType, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// explicitNegotiateCommitmentType attempts to explicitly negotiate for a
|
// explicitNegotiateCommitmentType attempts to explicitly negotiate for a
|
||||||
|
@ -113,12 +114,17 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType,
|
||||||
// implicitly by choosing the latest type supported by the local and remote
|
// implicitly by choosing the latest type supported by the local and remote
|
||||||
// fetures.
|
// fetures.
|
||||||
func implicitNegotiateCommitmentType(local,
|
func implicitNegotiateCommitmentType(local,
|
||||||
remote *lnwire.FeatureVector) lnwallet.CommitmentType {
|
remote *lnwire.FeatureVector) (*lnwire.ChannelType, lnwallet.CommitmentType) {
|
||||||
|
|
||||||
// If both peers are signalling support for anchor commitments with
|
// If both peers are signalling support for anchor commitments with
|
||||||
// zero-fee HTLC transactions, we'll use this type.
|
// zero-fee HTLC transactions, we'll use this type.
|
||||||
if hasFeatures(local, remote, lnwire.AnchorsZeroFeeHtlcTxOptional) {
|
if hasFeatures(local, remote, lnwire.AnchorsZeroFeeHtlcTxOptional) {
|
||||||
return lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx
|
chanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.AnchorsZeroFeeHtlcTxRequired,
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
))
|
||||||
|
|
||||||
|
return &chanType, lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we don't want to support the "legacy" anchor type, we will fall
|
// Since we don't want to support the "legacy" anchor type, we will fall
|
||||||
|
@ -128,11 +134,16 @@ func implicitNegotiateCommitmentType(local,
|
||||||
// If both nodes are signaling the proper feature bit for tweakless
|
// If both nodes are signaling the proper feature bit for tweakless
|
||||||
// commitments, we'll use that.
|
// commitments, we'll use that.
|
||||||
if hasFeatures(local, remote, lnwire.StaticRemoteKeyOptional) {
|
if hasFeatures(local, remote, lnwire.StaticRemoteKeyOptional) {
|
||||||
return lnwallet.CommitmentTypeTweakless
|
chanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
))
|
||||||
|
|
||||||
|
return &chanType, lnwallet.CommitmentTypeTweakless
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we'll fall back to the legacy type.
|
// Otherwise we'll fall back to the legacy type.
|
||||||
return lnwallet.CommitmentTypeLegacy
|
chanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector())
|
||||||
|
return &chanType, lnwallet.CommitmentTypeLegacy
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasFeatures determines whether a set of features is supported by both the set
|
// hasFeatures determines whether a set of features is supported by both the set
|
||||||
|
|
|
@ -14,13 +14,14 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
mustBeExplicit bool
|
mustBeExplicit bool
|
||||||
channelFeatures *lnwire.RawFeatureVector
|
channelFeatures *lnwire.RawFeatureVector
|
||||||
localFeatures *lnwire.RawFeatureVector
|
localFeatures *lnwire.RawFeatureVector
|
||||||
remoteFeatures *lnwire.RawFeatureVector
|
remoteFeatures *lnwire.RawFeatureVector
|
||||||
expectsRes lnwallet.CommitmentType
|
expectsCommitType lnwallet.CommitmentType
|
||||||
expectsErr error
|
expectsChanType lnwire.ChannelType
|
||||||
|
expectsErr error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "explicit missing remote negotiation feature",
|
name: "explicit missing remote negotiation feature",
|
||||||
|
@ -37,7 +38,11 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
lnwire.StaticRemoteKeyOptional,
|
lnwire.StaticRemoteKeyOptional,
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx,
|
expectsCommitType: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx,
|
||||||
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
lnwire.AnchorsZeroFeeHtlcTxRequired,
|
||||||
|
)),
|
||||||
expectsErr: nil,
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -92,7 +97,11 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||||
lnwire.ExplicitChannelTypeOptional,
|
lnwire.ExplicitChannelTypeOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx,
|
expectsCommitType: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx,
|
||||||
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
lnwire.AnchorsZeroFeeHtlcTxRequired,
|
||||||
|
)),
|
||||||
expectsErr: nil,
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -110,7 +119,10 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||||
lnwire.ExplicitChannelTypeOptional,
|
lnwire.ExplicitChannelTypeOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeTweakless,
|
expectsCommitType: lnwallet.CommitmentTypeTweakless,
|
||||||
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
)),
|
||||||
expectsErr: nil,
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -126,9 +138,13 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||||
lnwire.ExplicitChannelTypeOptional,
|
lnwire.ExplicitChannelTypeOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeLegacy,
|
expectsCommitType: lnwallet.CommitmentTypeLegacy,
|
||||||
expectsErr: nil,
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector()),
|
||||||
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
|
// Both sides signal the explicit chan type bit, so we expect
|
||||||
|
// that we return the corresponding chan type feature bits,
|
||||||
|
// even though we didn't set an explicit channel type.
|
||||||
{
|
{
|
||||||
name: "implicit anchors",
|
name: "implicit anchors",
|
||||||
channelFeatures: nil,
|
channelFeatures: nil,
|
||||||
|
@ -142,7 +158,11 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||||
lnwire.ExplicitChannelTypeOptional,
|
lnwire.ExplicitChannelTypeOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx,
|
expectsCommitType: lnwallet.CommitmentTypeAnchorsZeroFeeHtlcTx,
|
||||||
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
lnwire.AnchorsZeroFeeHtlcTxRequired,
|
||||||
|
)),
|
||||||
expectsErr: nil,
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -155,7 +175,10 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
remoteFeatures: lnwire.NewRawFeatureVector(
|
remoteFeatures: lnwire.NewRawFeatureVector(
|
||||||
lnwire.StaticRemoteKeyOptional,
|
lnwire.StaticRemoteKeyOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeTweakless,
|
expectsCommitType: lnwallet.CommitmentTypeTweakless,
|
||||||
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector(
|
||||||
|
lnwire.StaticRemoteKeyRequired,
|
||||||
|
)),
|
||||||
expectsErr: nil,
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -166,8 +189,9 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
lnwire.StaticRemoteKeyOptional,
|
lnwire.StaticRemoteKeyOptional,
|
||||||
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
lnwire.AnchorsZeroFeeHtlcTxOptional,
|
||||||
),
|
),
|
||||||
expectsRes: lnwallet.CommitmentTypeLegacy,
|
expectsCommitType: lnwallet.CommitmentTypeLegacy,
|
||||||
expectsErr: nil,
|
expectsChanType: lnwire.ChannelType(*lnwire.NewRawFeatureVector()),
|
||||||
|
expectsErr: nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,13 +212,13 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
*testCase.channelFeatures,
|
*testCase.channelFeatures,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_, localType, err := negotiateCommitmentType(
|
_, localChanType, localCommitType, err := negotiateCommitmentType(
|
||||||
channelType, localFeatures, remoteFeatures,
|
channelType, localFeatures, remoteFeatures,
|
||||||
testCase.mustBeExplicit,
|
testCase.mustBeExplicit,
|
||||||
)
|
)
|
||||||
require.Equal(t, testCase.expectsErr, err)
|
require.Equal(t, testCase.expectsErr, err)
|
||||||
|
|
||||||
_, remoteType, err := negotiateCommitmentType(
|
_, remoteChanType, remoteCommitType, err := negotiateCommitmentType(
|
||||||
channelType, remoteFeatures, localFeatures,
|
channelType, remoteFeatures, localFeatures,
|
||||||
testCase.mustBeExplicit,
|
testCase.mustBeExplicit,
|
||||||
)
|
)
|
||||||
|
@ -205,11 +229,20 @@ func TestCommitmentTypeNegotiation(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t, testCase.expectsRes, localType,
|
t, testCase.expectsCommitType, localCommitType,
|
||||||
testCase.name,
|
testCase.name,
|
||||||
)
|
)
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t, testCase.expectsRes, remoteType,
|
t, testCase.expectsCommitType, remoteCommitType,
|
||||||
|
testCase.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
require.Equal(
|
||||||
|
t, testCase.expectsChanType, *localChanType,
|
||||||
|
testCase.name,
|
||||||
|
)
|
||||||
|
require.Equal(
|
||||||
|
t, testCase.expectsChanType, *remoteChanType,
|
||||||
testCase.name,
|
testCase.name,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1274,7 +1274,7 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
|
||||||
// the remote peer are signaling the proper feature bit if we're using
|
// the remote peer are signaling the proper feature bit if we're using
|
||||||
// implicit negotiation, and simply the channel type sent over if we're
|
// implicit negotiation, and simply the channel type sent over if we're
|
||||||
// using explicit negotiation.
|
// using explicit negotiation.
|
||||||
wasExplicit, commitType, err := negotiateCommitmentType(
|
wasExplicit, _, commitType, err := negotiateCommitmentType(
|
||||||
msg.ChannelType, peer.LocalFeatures(), peer.RemoteFeatures(),
|
msg.ChannelType, peer.LocalFeatures(), peer.RemoteFeatures(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
@ -1599,14 +1599,14 @@ func (f *Manager) handleFundingAccept(peer lnpeer.Peer,
|
||||||
// channel type in the accept_channel response if we didn't
|
// channel type in the accept_channel response if we didn't
|
||||||
// explicitly set it in the open_channel message. For now, let's
|
// explicitly set it in the open_channel message. For now, let's
|
||||||
// just log the problem instead of failing the funding flow.
|
// just log the problem instead of failing the funding flow.
|
||||||
implicitChannelType := implicitNegotiateCommitmentType(
|
_, implicitChannelType := implicitNegotiateCommitmentType(
|
||||||
peer.LocalFeatures(), peer.RemoteFeatures(),
|
peer.LocalFeatures(), peer.RemoteFeatures(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// We pass in false here as the funder since at this point, we
|
// We pass in false here as the funder since at this point, we
|
||||||
// didn't set a chan type ourselves, so falling back to
|
// didn't set a chan type ourselves, so falling back to
|
||||||
// implicit funding is acceptable.
|
// implicit funding is acceptable.
|
||||||
_, negotiatedChannelType, err := negotiateCommitmentType(
|
_, _, negotiatedChannelType, err := negotiateCommitmentType(
|
||||||
msg.ChannelType, peer.LocalFeatures(),
|
msg.ChannelType, peer.LocalFeatures(),
|
||||||
peer.RemoteFeatures(), false,
|
peer.RemoteFeatures(), false,
|
||||||
)
|
)
|
||||||
|
@ -3258,7 +3258,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
|
||||||
// Before we init the channel, we'll also check to see what commitment
|
// Before we init the channel, we'll also check to see what commitment
|
||||||
// format we can use with this peer. This is dependent on *both* us and
|
// format we can use with this peer. This is dependent on *both* us and
|
||||||
// the remote peer are signaling the proper feature bit.
|
// the remote peer are signaling the proper feature bit.
|
||||||
_, commitType, err := negotiateCommitmentType(
|
_, chanType, commitType, err := negotiateCommitmentType(
|
||||||
msg.ChannelType, msg.Peer.LocalFeatures(),
|
msg.ChannelType, msg.Peer.LocalFeatures(),
|
||||||
msg.Peer.RemoteFeatures(), true,
|
msg.Peer.RemoteFeatures(), true,
|
||||||
)
|
)
|
||||||
|
@ -3415,7 +3415,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
|
||||||
FirstCommitmentPoint: ourContribution.FirstCommitmentPoint,
|
FirstCommitmentPoint: ourContribution.FirstCommitmentPoint,
|
||||||
ChannelFlags: channelFlags,
|
ChannelFlags: channelFlags,
|
||||||
UpfrontShutdownScript: shutdown,
|
UpfrontShutdownScript: shutdown,
|
||||||
ChannelType: msg.ChannelType,
|
ChannelType: chanType,
|
||||||
LeaseExpiry: leaseExpiry,
|
LeaseExpiry: leaseExpiry,
|
||||||
}
|
}
|
||||||
if err := msg.Peer.SendMessage(true, &fundingOpen); err != nil {
|
if err := msg.Peer.SendMessage(true, &fundingOpen); err != nil {
|
||||||
|
|
Loading…
Add table
Reference in a new issue