From 384b1b1c12d8400d5973da2dfb33dad198ea98b4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 18 Aug 2023 17:04:07 -0700 Subject: [PATCH] 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. --- feature/default_sets.go | 2 +- feature/deps.go | 2 +- feature/manager.go | 4 +- funding/commitment_type_negotiation.go | 29 +++---- funding/manager.go | 4 +- funding/manager_test.go | 12 +-- lnwire/features.go | 108 ++++++++++++++----------- routing/router.go | 5 +- rpcserver.go | 2 +- 9 files changed, 92 insertions(+), 76 deletions(-) diff --git a/feature/default_sets.go b/feature/default_sets.go index cefa1c0bc..4227691aa 100644 --- a/feature/default_sets.go +++ b/feature/default_sets.go @@ -83,7 +83,7 @@ var defaultSetDesc = setDesc{ SetInit: {}, // I SetNodeAnn: {}, // N }, - lnwire.SimpleTaprootChannelsOptional: { + lnwire.SimpleTaprootChannelsOptionalStaging: { SetInit: {}, // I SetNodeAnn: {}, // N }, diff --git a/feature/deps.go b/feature/deps.go index 314dd3a6d..479fd1d01 100644 --- a/feature/deps.go +++ b/feature/deps.go @@ -75,7 +75,7 @@ var deps = depDesc{ lnwire.ZeroConfOptional: { lnwire.ScidAliasOptional: {}, }, - lnwire.SimpleTaprootChannelsOptional: { + lnwire.SimpleTaprootChannelsOptionalStaging: { lnwire.AnchorsZeroFeeHtlcTxOptional: {}, lnwire.ExplicitChannelTypeOptional: {}, }, diff --git a/feature/manager.go b/feature/manager.go index 5a6034593..991d5c611 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -176,8 +176,8 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { raw.Unset(lnwire.ShutdownAnySegwitRequired) } if cfg.NoTaprootChans { - raw.Unset(lnwire.SimpleTaprootChannelsOptional) - raw.Unset(lnwire.SimpleTaprootChannelsRequired) + raw.Unset(lnwire.SimpleTaprootChannelsOptionalStaging) + raw.Unset(lnwire.SimpleTaprootChannelsRequiredStaging) } for _, custom := range cfg.CustomFeatures[set] { diff --git a/funding/commitment_type_negotiation.go b/funding/commitment_type_negotiation.go index ec25ce078..f931b4702 100644 --- a/funding/commitment_type_negotiation.go +++ b/funding/commitment_type_negotiation.go @@ -241,10 +241,13 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local, return lnwallet.CommitmentTypeTweakless, nil // Simple taproot channels only. - case channelFeatures.OnlyContains(lnwire.SimpleTaprootChannelsRequired): + case channelFeatures.OnlyContains( + lnwire.SimpleTaprootChannelsRequiredStaging, + ): if !hasFeatures( - local, remote, lnwire.SimpleTaprootChannelsOptional, + local, remote, + lnwire.SimpleTaprootChannelsOptionalStaging, ) { return 0, errUnsupportedChannelType @@ -254,13 +257,13 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local, // Simple taproot channels with scid only. case channelFeatures.OnlyContains( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, lnwire.ScidAliasRequired, ): if !hasFeatures( local, remote, - lnwire.SimpleTaprootChannelsOptional, + lnwire.SimpleTaprootChannelsOptionalStaging, lnwire.ScidAliasOptional, ) { @@ -271,13 +274,13 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local, // Simple taproot channels with zero conf only. case channelFeatures.OnlyContains( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, lnwire.ZeroConfRequired, ): if !hasFeatures( local, remote, - lnwire.SimpleTaprootChannelsOptional, + lnwire.SimpleTaprootChannelsOptionalStaging, lnwire.ZeroConfOptional, ) { @@ -288,14 +291,14 @@ func explicitNegotiateCommitmentType(channelType lnwire.ChannelType, local, // Simple taproot channels with scid and zero conf. case channelFeatures.OnlyContains( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, lnwire.ZeroConfRequired, lnwire.ScidAliasRequired, ): if !hasFeatures( local, remote, - lnwire.SimpleTaprootChannelsOptional, + lnwire.SimpleTaprootChannelsOptionalStaging, lnwire.ZeroConfOptional, ) { @@ -320,16 +323,6 @@ func implicitNegotiateCommitmentType(local, remote *lnwire.FeatureVector) (*lnwire.ChannelType, 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 // zero-fee HTLC transactions, we'll use this type. if hasFeatures(local, remote, lnwire.AnchorsZeroFeeHtlcTxOptional) { diff --git a/funding/manager.go b/funding/manager.go index d409ffbf6..3f97747ea 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -4077,7 +4077,9 @@ func (f *Manager) newChanAnnouncement(localPubKey, log.Debugf("Applying taproot feature bit to "+ "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 diff --git a/funding/manager_test.go b/funding/manager_test.go index e5b3ca116..93da8095d 100644 --- a/funding/manager_test.go +++ b/funding/manager_test.go @@ -742,7 +742,7 @@ func isTaprootChanType(chanType *lnwire.ChannelType) bool { featVec := lnwire.RawFeatureVector(*chanType) return featVec.IsSet( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, ) } @@ -1423,7 +1423,7 @@ func testNormalWorkflow(t *testing.T, chanType *lnwire.ChannelType) { lnwire.ExplicitChannelTypeOptional, lnwire.StaticRemoteKeyOptional, lnwire.AnchorsZeroFeeHtlcTxOptional, - lnwire.SimpleTaprootChannelsOptional, + lnwire.SimpleTaprootChannelsOptionalStaging, } alice.localFeatures = featureBits alice.remoteFeatures = featureBits @@ -1543,7 +1543,7 @@ func TestFundingManagerNormalWorkflow(t *testing.T) { t.Parallel() taprootChanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, )) testCases := []struct { @@ -4460,7 +4460,7 @@ func testZeroConf(t *testing.T, chanType *lnwire.ChannelType) { lnwire.ExplicitChannelTypeOptional, lnwire.StaticRemoteKeyOptional, lnwire.AnchorsZeroFeeHtlcTxOptional, - lnwire.SimpleTaprootChannelsOptional, + lnwire.SimpleTaprootChannelsOptionalStaging, } alice.localFeatures = featureBits alice.remoteFeatures = featureBits @@ -4476,7 +4476,7 @@ func testZeroConf(t *testing.T, chanType *lnwire.ChannelType) { if isTaprootChanType(chanType) { channelTypeBits = []lnwire.FeatureBit{ lnwire.ZeroConfRequired, - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, } } else { channelTypeBits = []lnwire.FeatureBit{ @@ -4708,7 +4708,7 @@ func TestFundingManagerZeroConf(t *testing.T) { t.Parallel() taprootChanType := lnwire.ChannelType(*lnwire.NewRawFeatureVector( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, )) testCases := []struct { diff --git a/lnwire/features.go b/lnwire/features.go index 2383bb6ae..3d29aaf73 100644 --- a/lnwire/features.go +++ b/lnwire/features.go @@ -231,13 +231,29 @@ const ( // TODO: Decide on actual feature bit value. ScriptEnforcedLeaseOptional FeatureBit = 2023 - // SimpleTaprootChannelsRequred is a required bit that indicates the - // node is able to create taproot-native channels. - SimpleTaprootChannelsRequired = 80 + // SimpleTaprootChannelsRequredFinal is a required bit that indicates + // the node is able to create taproot-native channels. This is the + // final feature bit to be used once the channel type is finalized. + SimpleTaprootChannelsRequiredFinal = 80 - // SimpleTaprootChannelsOptional is an optional bit that indicates the - // node is able to create taproot-native channels. - SimpleTaprootChannelsOptional = 81 + // SimpleTaprootChannelsOptionalFinal is an optional bit that indicates + // the node is able to create taproot-native channels. This is the + // 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 // invoices. @@ -262,45 +278,47 @@ func (b FeatureBit) IsRequired() bool { // feature bits must be assigned a name in this mapping, and feature bit pairs // must be assigned together for correct behavior. var Features = map[FeatureBit]string{ - DataLossProtectRequired: "data-loss-protect", - DataLossProtectOptional: "data-loss-protect", - InitialRoutingSync: "initial-routing-sync", - UpfrontShutdownScriptRequired: "upfront-shutdown-script", - UpfrontShutdownScriptOptional: "upfront-shutdown-script", - GossipQueriesRequired: "gossip-queries", - GossipQueriesOptional: "gossip-queries", - TLVOnionPayloadRequired: "tlv-onion", - TLVOnionPayloadOptional: "tlv-onion", - StaticRemoteKeyOptional: "static-remote-key", - StaticRemoteKeyRequired: "static-remote-key", - PaymentAddrOptional: "payment-addr", - PaymentAddrRequired: "payment-addr", - MPPOptional: "multi-path-payments", - MPPRequired: "multi-path-payments", - AnchorsRequired: "anchor-commitments", - AnchorsOptional: "anchor-commitments", - AnchorsZeroFeeHtlcTxRequired: "anchors-zero-fee-htlc-tx", - AnchorsZeroFeeHtlcTxOptional: "anchors-zero-fee-htlc-tx", - WumboChannelsRequired: "wumbo-channels", - WumboChannelsOptional: "wumbo-channels", - AMPRequired: "amp", - AMPOptional: "amp", - PaymentMetadataOptional: "payment-metadata", - PaymentMetadataRequired: "payment-metadata", - ExplicitChannelTypeOptional: "explicit-commitment-type", - ExplicitChannelTypeRequired: "explicit-commitment-type", - KeysendOptional: "keysend", - KeysendRequired: "keysend", - ScriptEnforcedLeaseRequired: "script-enforced-lease", - ScriptEnforcedLeaseOptional: "script-enforced-lease", - ScidAliasRequired: "scid-alias", - ScidAliasOptional: "scid-alias", - ZeroConfRequired: "zero-conf", - ZeroConfOptional: "zero-conf", - ShutdownAnySegwitRequired: "shutdown-any-segwit", - ShutdownAnySegwitOptional: "shutdown-any-segwit", - SimpleTaprootChannelsRequired: "simple-taproot-chans", - SimpleTaprootChannelsOptional: "simple-taproot-chans", + DataLossProtectRequired: "data-loss-protect", + DataLossProtectOptional: "data-loss-protect", + InitialRoutingSync: "initial-routing-sync", + UpfrontShutdownScriptRequired: "upfront-shutdown-script", + UpfrontShutdownScriptOptional: "upfront-shutdown-script", + GossipQueriesRequired: "gossip-queries", + GossipQueriesOptional: "gossip-queries", + TLVOnionPayloadRequired: "tlv-onion", + TLVOnionPayloadOptional: "tlv-onion", + StaticRemoteKeyOptional: "static-remote-key", + StaticRemoteKeyRequired: "static-remote-key", + PaymentAddrOptional: "payment-addr", + PaymentAddrRequired: "payment-addr", + MPPOptional: "multi-path-payments", + MPPRequired: "multi-path-payments", + AnchorsRequired: "anchor-commitments", + AnchorsOptional: "anchor-commitments", + AnchorsZeroFeeHtlcTxRequired: "anchors-zero-fee-htlc-tx", + AnchorsZeroFeeHtlcTxOptional: "anchors-zero-fee-htlc-tx", + WumboChannelsRequired: "wumbo-channels", + WumboChannelsOptional: "wumbo-channels", + AMPRequired: "amp", + AMPOptional: "amp", + PaymentMetadataOptional: "payment-metadata", + PaymentMetadataRequired: "payment-metadata", + ExplicitChannelTypeOptional: "explicit-commitment-type", + ExplicitChannelTypeRequired: "explicit-commitment-type", + KeysendOptional: "keysend", + KeysendRequired: "keysend", + ScriptEnforcedLeaseRequired: "script-enforced-lease", + ScriptEnforcedLeaseOptional: "script-enforced-lease", + ScidAliasRequired: "scid-alias", + ScidAliasOptional: "scid-alias", + ZeroConfRequired: "zero-conf", + ZeroConfOptional: "zero-conf", + ShutdownAnySegwitRequired: "shutdown-any-segwit", + ShutdownAnySegwitOptional: "shutdown-any-segwit", + SimpleTaprootChannelsRequiredFinal: "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 diff --git a/routing/router.go b/routing/router.go index 15686557c..0b09003f1 100644 --- a/routing/router.go +++ b/routing/router.go @@ -1454,7 +1454,10 @@ func makeFundingScript(bitcoinKey1, bitcoinKey2 []byte, chanFeatureBits := lnwire.NewFeatureVector( rawFeatures, lnwire.Features, ) - if chanFeatureBits.HasFeature(lnwire.SimpleTaprootChannelsOptional) { + if chanFeatureBits.HasFeature( + lnwire.SimpleTaprootChannelsOptionalStaging, + ) { + pubKey1, err := btcec.ParsePubKey(bitcoinKey1) if err != nil { return nil, err diff --git a/rpcserver.go b/rpcserver.go index 646bc3046..e43ce1bf3 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2152,7 +2152,7 @@ func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest, channelType = new(lnwire.ChannelType) fv := lnwire.NewRawFeatureVector( - lnwire.SimpleTaprootChannelsRequired, + lnwire.SimpleTaprootChannelsRequiredStaging, ) // TODO(roasbeef): no need for the rest as they're now