feature: use +100 staging bit for taproot channels

In this commit, we carry out a new notion introduced during a recent
spec meeting to use a feature bit plus 100 before the feature has been
finalized in the spec.

We split into the Final and Staging bits.
This commit is contained in:
Olaoluwa Osuntokun 2023-08-18 17:04:07 -07:00
parent fcbf6f2483
commit 384b1b1c12
No known key found for this signature in database
GPG Key ID: 3BBD59E99B280306
9 changed files with 92 additions and 76 deletions

View File

@ -83,7 +83,7 @@ var defaultSetDesc = setDesc{
SetInit: {}, // I SetInit: {}, // I
SetNodeAnn: {}, // N SetNodeAnn: {}, // N
}, },
lnwire.SimpleTaprootChannelsOptional: { lnwire.SimpleTaprootChannelsOptionalStaging: {
SetInit: {}, // I SetInit: {}, // I
SetNodeAnn: {}, // N SetNodeAnn: {}, // N
}, },

View File

@ -75,7 +75,7 @@ var deps = depDesc{
lnwire.ZeroConfOptional: { lnwire.ZeroConfOptional: {
lnwire.ScidAliasOptional: {}, lnwire.ScidAliasOptional: {},
}, },
lnwire.SimpleTaprootChannelsOptional: { lnwire.SimpleTaprootChannelsOptionalStaging: {
lnwire.AnchorsZeroFeeHtlcTxOptional: {}, lnwire.AnchorsZeroFeeHtlcTxOptional: {},
lnwire.ExplicitChannelTypeOptional: {}, lnwire.ExplicitChannelTypeOptional: {},
}, },

View File

@ -176,8 +176,8 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) {
raw.Unset(lnwire.ShutdownAnySegwitRequired) raw.Unset(lnwire.ShutdownAnySegwitRequired)
} }
if cfg.NoTaprootChans { if cfg.NoTaprootChans {
raw.Unset(lnwire.SimpleTaprootChannelsOptional) raw.Unset(lnwire.SimpleTaprootChannelsOptionalStaging)
raw.Unset(lnwire.SimpleTaprootChannelsRequired) raw.Unset(lnwire.SimpleTaprootChannelsRequiredStaging)
} }
for _, custom := range cfg.CustomFeatures[set] { for _, custom := range cfg.CustomFeatures[set] {

View File

@ -241,10 +241,13 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local,
return lnwallet.CommitmentTypeTweakless, nil return lnwallet.CommitmentTypeTweakless, nil
// Simple taproot channels only. // Simple taproot channels only.
case channelFeatures.OnlyContains(lnwire.SimpleTaprootChannelsRequired): case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequiredStaging,
):
if !hasFeatures( if !hasFeatures(
local, remote, lnwire.SimpleTaprootChannelsOptional, local, remote,
lnwire.SimpleTaprootChannelsOptionalStaging,
) { ) {
return 0, errUnsupportedChannelType return 0, errUnsupportedChannelType
@ -254,13 +257,13 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local,
// Simple taproot channels with scid only. // Simple taproot channels with scid only.
case channelFeatures.OnlyContains( case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
lnwire.ScidAliasRequired, lnwire.ScidAliasRequired,
): ):
if !hasFeatures( if !hasFeatures(
local, remote, local, remote,
lnwire.SimpleTaprootChannelsOptional, lnwire.SimpleTaprootChannelsOptionalStaging,
lnwire.ScidAliasOptional, lnwire.ScidAliasOptional,
) { ) {
@ -271,13 +274,13 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local,
// Simple taproot channels with zero conf only. // Simple taproot channels with zero conf only.
case channelFeatures.OnlyContains( case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
lnwire.ZeroConfRequired, lnwire.ZeroConfRequired,
): ):
if !hasFeatures( if !hasFeatures(
local, remote, local, remote,
lnwire.SimpleTaprootChannelsOptional, lnwire.SimpleTaprootChannelsOptionalStaging,
lnwire.ZeroConfOptional, lnwire.ZeroConfOptional,
) { ) {
@ -288,14 +291,14 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local,
// Simple taproot channels with scid and zero conf. // Simple taproot channels with scid and zero conf.
case channelFeatures.OnlyContains( case channelFeatures.OnlyContains(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
lnwire.ZeroConfRequired, lnwire.ZeroConfRequired,
lnwire.ScidAliasRequired, lnwire.ScidAliasRequired,
): ):
if !hasFeatures( if !hasFeatures(
local, remote, local, remote,
lnwire.SimpleTaprootChannelsOptional, lnwire.SimpleTaprootChannelsOptionalStaging,
lnwire.ZeroConfOptional, lnwire.ZeroConfOptional,
) { ) {
@ -320,16 +323,6 @@ func implicitNegotiateCommitmentType(local,
remote *lnwire.FeatureVector) (*lnwire.ChannelType, remote *lnwire.FeatureVector) (*lnwire.ChannelType,
lnwallet.CommitmentType) { lnwallet.CommitmentType) {
// If both peers are signalling support for taproot chanenls, then
// we'll use that type.
if hasFeatures(local, remote, lnwire.SimpleTaprootChannelsOptional) {
chanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector(
lnwire.SimpleTaprootChannelsRequired,
))
return &chanType, lnwallet.CommitmentTypeSimpleTaproot
}
// 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) {

View File

@ -4077,7 +4077,9 @@ func (f *Manager) newChanAnnouncement(localPubKey,
log.Debugf("Applying taproot feature bit to "+ log.Debugf("Applying taproot feature bit to "+
"ChannelAnnouncement for %v", chanID) "ChannelAnnouncement for %v", chanID)
chanAnn.Features.Set(lnwire.SimpleTaprootChannelsRequired) chanAnn.Features.Set(
lnwire.SimpleTaprootChannelsRequiredStaging,
)
} }
// The chanFlags field indicates which directed edge of the channel is // The chanFlags field indicates which directed edge of the channel is

View File

@ -742,7 +742,7 @@ func isTaprootChanType(chanType *lnwire.ChannelType) bool {
featVec := lnwire.RawFeatureVector(*chanType) featVec := lnwire.RawFeatureVector(*chanType)
return featVec.IsSet( return featVec.IsSet(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
) )
} }
@ -1423,7 +1423,7 @@ func testNormalWorkflow(t *testing.T, chanType *lnwire.ChannelType) {
lnwire.ExplicitChannelTypeOptional, lnwire.ExplicitChannelTypeOptional,
lnwire.StaticRemoteKeyOptional, lnwire.StaticRemoteKeyOptional,
lnwire.AnchorsZeroFeeHtlcTxOptional, lnwire.AnchorsZeroFeeHtlcTxOptional,
lnwire.SimpleTaprootChannelsOptional, lnwire.SimpleTaprootChannelsOptionalStaging,
} }
alice.localFeatures = featureBits alice.localFeatures = featureBits
alice.remoteFeatures = featureBits alice.remoteFeatures = featureBits
@ -1543,7 +1543,7 @@ func TestFundingManagerNormalWorkflow(t *testing.T) {
t.Parallel() t.Parallel()
taprootChanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector( taprootChanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
)) ))
testCases := []struct { testCases := []struct {
@ -4460,7 +4460,7 @@ func testZeroConf(t *testing.T, chanType *lnwire.ChannelType) {
lnwire.ExplicitChannelTypeOptional, lnwire.ExplicitChannelTypeOptional,
lnwire.StaticRemoteKeyOptional, lnwire.StaticRemoteKeyOptional,
lnwire.AnchorsZeroFeeHtlcTxOptional, lnwire.AnchorsZeroFeeHtlcTxOptional,
lnwire.SimpleTaprootChannelsOptional, lnwire.SimpleTaprootChannelsOptionalStaging,
} }
alice.localFeatures = featureBits alice.localFeatures = featureBits
alice.remoteFeatures = featureBits alice.remoteFeatures = featureBits
@ -4476,7 +4476,7 @@ func testZeroConf(t *testing.T, chanType *lnwire.ChannelType) {
if isTaprootChanType(chanType) { if isTaprootChanType(chanType) {
channelTypeBits = []lnwire.FeatureBit{ channelTypeBits = []lnwire.FeatureBit{
lnwire.ZeroConfRequired, lnwire.ZeroConfRequired,
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
} }
} else { } else {
channelTypeBits = []lnwire.FeatureBit{ channelTypeBits = []lnwire.FeatureBit{
@ -4708,7 +4708,7 @@ func TestFundingManagerZeroConf(t *testing.T) {
t.Parallel() t.Parallel()
taprootChanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector( taprootChanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
)) ))
testCases := []struct { testCases := []struct {

View File

@ -231,13 +231,29 @@ const (
// TODO: Decide on actual feature bit value. // TODO: Decide on actual feature bit value.
ScriptEnforcedLeaseOptional FeatureBit = 2023 ScriptEnforcedLeaseOptional FeatureBit = 2023
// SimpleTaprootChannelsRequred is a required bit that indicates the // SimpleTaprootChannelsRequredFinal is a required bit that indicates
// node is able to create taproot-native channels. // the node is able to create taproot-native channels. This is the
SimpleTaprootChannelsRequired = 80 // final feature bit to be used once the channel type is finalized.
SimpleTaprootChannelsRequiredFinal = 80
// SimpleTaprootChannelsOptional is an optional bit that indicates the // SimpleTaprootChannelsOptionalFinal is an optional bit that indicates
// node is able to create taproot-native channels. // the node is able to create taproot-native channels. This is the
SimpleTaprootChannelsOptional = 81 // final
// feature bit to be used once the channel type is finalized.
SimpleTaprootChannelsOptionalFinal = 81
// SimpleTaprootChannelsRequredStaging is a required bit that indicates
// the node is able to create taproot-native channels. This is a
// feature bit used in the wild while the channel type is still being
// finalized.
SimpleTaprootChannelsRequiredStaging = 180
// SimpleTaprootChannelsOptionalStaging is an optional bit that
// indicates the node is able to create taproot-native channels. This
// is a feature
// bit used in the wild while the channel type is still being
// finalized.
SimpleTaprootChannelsOptionalStaging = 181
// MaxBolt11Feature is the maximum feature bit value allowed in bolt 11 // MaxBolt11Feature is the maximum feature bit value allowed in bolt 11
// invoices. // invoices.
@ -262,45 +278,47 @@ func (b FeatureBit) IsRequired() bool {
// feature bits must be assigned a name in this mapping, and feature bit pairs // feature bits must be assigned a name in this mapping, and feature bit pairs
// must be assigned together for correct behavior. // must be assigned together for correct behavior.
var Features = map[FeatureBit]string{ var Features = map[FeatureBit]string{
DataLossProtectRequired: "data-loss-protect", DataLossProtectRequired: "data-loss-protect",
DataLossProtectOptional: "data-loss-protect", DataLossProtectOptional: "data-loss-protect",
InitialRoutingSync: "initial-routing-sync", InitialRoutingSync: "initial-routing-sync",
UpfrontShutdownScriptRequired: "upfront-shutdown-script", UpfrontShutdownScriptRequired: "upfront-shutdown-script",
UpfrontShutdownScriptOptional: "upfront-shutdown-script", UpfrontShutdownScriptOptional: "upfront-shutdown-script",
GossipQueriesRequired: "gossip-queries", GossipQueriesRequired: "gossip-queries",
GossipQueriesOptional: "gossip-queries", GossipQueriesOptional: "gossip-queries",
TLVOnionPayloadRequired: "tlv-onion", TLVOnionPayloadRequired: "tlv-onion",
TLVOnionPayloadOptional: "tlv-onion", TLVOnionPayloadOptional: "tlv-onion",
StaticRemoteKeyOptional: "static-remote-key", StaticRemoteKeyOptional: "static-remote-key",
StaticRemoteKeyRequired: "static-remote-key", StaticRemoteKeyRequired: "static-remote-key",
PaymentAddrOptional: "payment-addr", PaymentAddrOptional: "payment-addr",
PaymentAddrRequired: "payment-addr", PaymentAddrRequired: "payment-addr",
MPPOptional: "multi-path-payments", MPPOptional: "multi-path-payments",
MPPRequired: "multi-path-payments", MPPRequired: "multi-path-payments",
AnchorsRequired: "anchor-commitments", AnchorsRequired: "anchor-commitments",
AnchorsOptional: "anchor-commitments", AnchorsOptional: "anchor-commitments",
AnchorsZeroFeeHtlcTxRequired: "anchors-zero-fee-htlc-tx", AnchorsZeroFeeHtlcTxRequired: "anchors-zero-fee-htlc-tx",
AnchorsZeroFeeHtlcTxOptional: "anchors-zero-fee-htlc-tx", AnchorsZeroFeeHtlcTxOptional: "anchors-zero-fee-htlc-tx",
WumboChannelsRequired: "wumbo-channels", WumboChannelsRequired: "wumbo-channels",
WumboChannelsOptional: "wumbo-channels", WumboChannelsOptional: "wumbo-channels",
AMPRequired: "amp", AMPRequired: "amp",
AMPOptional: "amp", AMPOptional: "amp",
PaymentMetadataOptional: "payment-metadata", PaymentMetadataOptional: "payment-metadata",
PaymentMetadataRequired: "payment-metadata", PaymentMetadataRequired: "payment-metadata",
ExplicitChannelTypeOptional: "explicit-commitment-type", ExplicitChannelTypeOptional: "explicit-commitment-type",
ExplicitChannelTypeRequired: "explicit-commitment-type", ExplicitChannelTypeRequired: "explicit-commitment-type",
KeysendOptional: "keysend", KeysendOptional: "keysend",
KeysendRequired: "keysend", KeysendRequired: "keysend",
ScriptEnforcedLeaseRequired: "script-enforced-lease", ScriptEnforcedLeaseRequired: "script-enforced-lease",
ScriptEnforcedLeaseOptional: "script-enforced-lease", ScriptEnforcedLeaseOptional: "script-enforced-lease",
ScidAliasRequired: "scid-alias", ScidAliasRequired: "scid-alias",
ScidAliasOptional: "scid-alias", ScidAliasOptional: "scid-alias",
ZeroConfRequired: "zero-conf", ZeroConfRequired: "zero-conf",
ZeroConfOptional: "zero-conf", ZeroConfOptional: "zero-conf",
ShutdownAnySegwitRequired: "shutdown-any-segwit", ShutdownAnySegwitRequired: "shutdown-any-segwit",
ShutdownAnySegwitOptional: "shutdown-any-segwit", ShutdownAnySegwitOptional: "shutdown-any-segwit",
SimpleTaprootChannelsRequired: "simple-taproot-chans", SimpleTaprootChannelsRequiredFinal: "simple-taproot-chans",
SimpleTaprootChannelsOptional: "simple-taproot-chans", SimpleTaprootChannelsOptionalFinal: "simple-taproot-chans",
SimpleTaprootChannelsRequiredStaging: "simple-taproot-chans-x",
SimpleTaprootChannelsOptionalStaging: "simple-taproot-chans-x",
} }
// RawFeatureVector represents a set of feature bits as defined in BOLT-09. A // RawFeatureVector represents a set of feature bits as defined in BOLT-09. A

View File

@ -1454,7 +1454,10 @@ func makeFundingScript(bitcoinKey1, bitcoinKey2 []byte,
chanFeatureBits := lnwire.NewFeatureVector( chanFeatureBits := lnwire.NewFeatureVector(
rawFeatures, lnwire.Features, rawFeatures, lnwire.Features,
) )
if chanFeatureBits.HasFeature(lnwire.SimpleTaprootChannelsOptional) { if chanFeatureBits.HasFeature(
lnwire.SimpleTaprootChannelsOptionalStaging,
) {
pubKey1, err := btcec.ParsePubKey(bitcoinKey1) pubKey1, err := btcec.ParsePubKey(bitcoinKey1)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -2152,7 +2152,7 @@ func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest,
channelType = new(lnwire.ChannelType) channelType = new(lnwire.ChannelType)
fv := lnwire.NewRawFeatureVector( fv := lnwire.NewRawFeatureVector(
lnwire.SimpleTaprootChannelsRequired, lnwire.SimpleTaprootChannelsRequiredStaging,
) )
// TODO(roasbeef): no need for the rest as they're now // TODO(roasbeef): no need for the rest as they're now