-
Notifications
You must be signed in to change notification settings - Fork 385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move supported-feature-set logic into the supporting modules #1707
Move supported-feature-set logic into the supporting modules #1707
Conversation
e31571a
to
d4a1bc5
Compare
d4a1bc5
to
1087e93
Compare
lightning/src/ln/channelmanager.rs
Outdated
pub fn provided_node_features() -> NodeFeatures { | ||
provided_init_features().to_context() | ||
} | ||
|
||
/// Fetches the set of [`InvoiceFeature`] flags which are provided by or required by | ||
/// [`ChannelManager`]. | ||
pub fn provided_invoice_features() -> InvoiceFeatures { | ||
provided_init_features().to_context() | ||
} | ||
|
||
/// Fetches the set of [`ChannelFeature`] flags which are provided by or required by | ||
/// [`ChannelManager`]. | ||
pub fn provided_channel_features() -> ChannelFeatures { | ||
provided_init_features().to_context() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on having one method?
pub fn provided_features<T: From<InitFeatures>>() -> T { ... }
Not sure if having it based on InitFeatures
would be weird.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, yea, From
would be weird, I guess in theory we could do it for all contexts by just bounding by a Feature<C: Context>
? I'm not 100% sure if we wouldn't want to at some point have slightly different features in different contexts? I don't immediately see a reason why we would, so can change it unless we come up with some reason.
Oh, nevermind, you even point out where we may change this in #1707 (comment) so we cant.
let mut features = InitFeatures::empty(); | ||
features.set_data_loss_protect_optional(); | ||
features.set_upfront_shutdown_script_optional(); | ||
features.set_variable_length_onion_optional(); | ||
features.set_static_remote_key_optional(); | ||
features.set_payment_secret_optional(); | ||
features.set_basic_mpp_optional(); | ||
features.set_wumbo_optional(); | ||
features.set_shutdown_any_segwit_optional(); | ||
features.set_channel_type_optional(); | ||
features.set_scid_privacy_optional(); | ||
features.set_zero_conf_optional(); | ||
features |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call the one version in channelmanager.rs
instead of duplicating?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're different - this only ever sets optional bits, never required ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have simple test that each feature in channelmanager::provided_init_features
is supported here, even if not required. Not sure if there is an easy way to do that. Otherwise, a comment on the former to update this may be in order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmmmmmmmmmm. Our current features code doesn't really have any kind of logic for iterating feature flags themselves. We could iterate the bits themselves, but it doesn't seem worth it to expose them for this? I'll leave a comment at least.
/// Fetches the set of [`InvoiceFeature`] flags which are provided by or required by | ||
/// [`ChannelManager`]. | ||
pub fn provided_invoice_features() -> InvoiceFeatures { | ||
provided_init_features().to_context() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we care that invoice-only features like option_payment_metadata
won't be returned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably when we support payment metadata for receiving we'll want to set that, but we don't support receiving with metadata today.
|
||
/// Fetches the set of [`InvoiceFeature`] flags which are provided by or required by | ||
/// [`ChannelManager`]. | ||
pub fn provided_invoice_features() -> InvoiceFeatures { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be test-only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No? lightning-invoice
requests these flags to set in the invoices we construct, or should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InvoiceBuilder
has methods for setting individual features (or sets of features) along with any necessary data needed in the invoice for the feature. A user never passes InvoiceFeatures
directly. This allows compile-time enforcement of correctness.
For example InvoiceBuilder::payment_secret
sets the supplied PaymentSecret
and the necessary feature bits. It also makes InvoiceBuilder::basic_mpp
available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like test_builder_ok
caught this because InvoiceBuilder::payment_secret
sets dependent feature variable_length_onion
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, I suppose if we ever have a feature bit in the invoice which doesn't require some additional data in the invoice we'd need this. In any case, I don't see any harm in leaving it public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.... maybe something else is going on there. Looking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, it just looks like test_builder_ok
is not manually setting variable_length_onion
. It isn't using provided_invoice_features
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, I suppose if we ever have a feature bit in the invoice which doesn't require some additional data in the invoice we'd need this. In any case, I don't see any harm in leaving it public.
We already have that with basic_mpp
, but it's just a separate builder method. I don't think we should allow users to pass in InvoiceFeatures
directly. Maybe would need to set an unknown bit, but in that case we can provide a method to do so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should allow users to pass in InvoiceFeatures directly.
Seems like something that is going to depend on the types of features. If we end up with some feature which doesn't require additional data, we'll need this.
I kinda wonder if we should have some kind of "check features are X" method - require that users pass the ChannelManager
's invoice features set to the InvoiceBuilder
so that the InvoiceBuilder
can check that the required features have all been filled in.
In any case, I realized that the invoice features we need vary anyway - if its a phantom invoice we cant set MPP - so I went ahead and made it test-cfg.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kinda wonder if we should have some kind of "check features are X" method - require that users pass the
ChannelManager
's invoice features set to theInvoiceBuilder
so that theInvoiceBuilder
can check that the required features have all been filled in.
InvoiceBuilder::build_signed
returns Result<Invoice, CreationError>
, so it could perform checks against any features, provided either at builder construction time or at invoice building time using a dedicated method.
const ASSERT_BITS_IN_MASK: u8 = | ||
((<$context>::KNOWN_FEATURE_MASK[<Self as $feature>::BYTE_OFFSET] & (<Self as $feature>::REQUIRED_MASK | <Self as $feature>::OPTIONAL_MASK)) | ||
>> (<Self as $feature>::EVEN_BIT % 8)) - 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like UnknownFeature
doesn't work so well with this.
1087e93
to
184d221
Compare
Actually, its simpler to handle the followup there first, see #1717 |
Needs rebase |
184d221
to
374f6fe
Compare
Rebased, now depends on #1720 |
Codecov ReportBase: 90.81% // Head: 90.76% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #1707 +/- ##
==========================================
- Coverage 90.81% 90.76% -0.05%
==========================================
Files 86 86
Lines 46670 46631 -39
Branches 46670 46631 -39
==========================================
- Hits 42382 42325 -57
- Misses 4288 4306 +18
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
374f6fe
to
9f74638
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a possible test addition.
let mut features = InitFeatures::empty(); | ||
features.set_data_loss_protect_optional(); | ||
features.set_upfront_shutdown_script_optional(); | ||
features.set_variable_length_onion_optional(); | ||
features.set_static_remote_key_optional(); | ||
features.set_payment_secret_optional(); | ||
features.set_basic_mpp_optional(); | ||
features.set_wumbo_optional(); | ||
features.set_shutdown_any_segwit_optional(); | ||
features.set_channel_type_optional(); | ||
features.set_scid_privacy_optional(); | ||
features.set_zero_conf_optional(); | ||
features |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have simple test that each feature in channelmanager::provided_init_features
is supported here, even if not required. Not sure if there is an easy way to do that. Otherwise, a comment on the former to update this may be in order.
Rebased and addressed feedback. |
9f74638
to
fab768a
Compare
Historically, LDK has considered the "set of known/supported feature bits" to be an LDK-level thing. Increasingly this doesn't make sense - different message handlers may provide or require different feature sets. In a previous PR, we began the process of transitioning with feature bits sent to peers being sourced from the attached message handler. This commit makes further progress by moving the concept of which feature bits are supported by our ChannelManager into channelmanager.rs itself, via the new `provided_*_features` methods, rather than in features.rs via the `known_channel_features` and `known` methods.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in the `routing` module, which was only used in tests.
This diff is commit, like the last, stops relying on the `known` feature set constructor, doing so entirely with import changes and sed rules.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in the functional_test_utils module.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in the channel modules.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in the `lightning-invoice` crate.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in the `lightning-net-tokio` crate.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in the `lightning-background-processor` and `lightning-persister` crate tests.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we stop relying on the `known` method in our fuzz tests.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. In anticipation of removing the `known` constructor, this commit removes all remaining references to it outside of features.rs.
As we move towards specify supported/required feature bits in the module(s) where they are supported, the global `known` feature set constructors no longer make sense. Here we (finally) remove the `known` constructor entirely, modifying tests in the `features` module as required.
Now that the `*Features::known` constructor has been removed, there is no reason to define feature bits as either optional required in `features.rs` - that logic now belongs in the modules that are responsible for the given features. Instead, we only list all features in each context.
Now that the features contexts track the full set of all known features, rather than the set of supported features, all defined features should be listed in the context definition macro. This adds a compile-time assertion to check that all bits for known features are set in the context known set.
9170804
fab768a
to
9170804
Compare
FIxed last comment, one bench issue, and squashed. Diff is: $ git diff-tree -U1 fab768ae5 9170804ca
diff --git a/lightning/src/ln/features.rs b/lightning/src/ln/features.rs
index da26cb0d5..b372e6af6 100644
--- a/lightning/src/ln/features.rs
+++ b/lightning/src/ln/features.rs
@@ -747,3 +747,3 @@ mod tests {
// Set a bunch of features we use, plus initial_routing_sync_required (which shouldn't get
- // converted as its only relevant in an init context).
+ // converted as it's only relevant in an init context).
init_features.set_initial_routing_sync_required();
diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs
index 4d47170d1..801acaa2e 100644
--- a/lightning/src/routing/router.rs
+++ b/lightning/src/routing/router.rs
@@ -5928,3 +5928,3 @@ mod benches {
use chain::keysinterface::{KeysManager,KeysInterface};
- use ln::channelmanager::{ChannelCounterparty, ChannelDetails};
+ use ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
use ln::features::{InitFeatures, InvoiceFeatures};
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK if CI passes
Historically, LDK has considered the "set of known/supported
feature bits" to be an LDK-level thing. Increasingly this doesn't
make sense - different message handlers may provide or require
different feature sets.
In a previous PR, we began the process of transitioning with
feature bits sent to peers being sourced from the attached message
handler.
This PR makes further progress by moving the concept of which
feature bits are supported by our various modules directly into those modules.
It then has a long series of commits which remove all usages of the
*Features::known
constructor (almost all of which are in tests). Finally, it removes the*Features::known
constructor entirely and moves the features context bit tracking set to include all defined feature bits, rather than the set of supported/required bits.provided_init_features
rather than via therequires_unknown_bits
check.