Skip to content

Improve support for plugin-defined features#3264

Merged
t-bast merged 2 commits intomasterfrom
refactor-plugin-features
Mar 17, 2026
Merged

Improve support for plugin-defined features#3264
t-bast merged 2 commits intomasterfrom
refactor-plugin-features

Conversation

@t-bast
Copy link
Member

@t-bast t-bast commented Mar 10, 2026

We allow injecting non-official features via plugins, by extending the CustomFeaturePlugin trait. However, we previously added those features to a set of unknown features: we can do better and add them to the known features map, which provides pretty-printing in logs and simplifies debugging.

We also had an issue where hasFeature would always return false for plugin features, even when they were supported by both nodes, because we only looked at our activated features map which only contains official features.

We get rid of the UnknownFeature class entirely and keep the encoded feature bits after deserializing them. We take those feature bits into account in hasFeature, which fixes the issue.

This creates a slightly weird asymmetry because our local features, which are created based on our eclair.conf, will not have this field set while features that are read from network messages or the DB will have this field set. A better architecture would be to remove the activated map entirely and directly wrap the feature bits, while providing helper functions to interact with features without having to directly read a BitVector. This is a larger refactoring though, because we'd need to add support for filtering init / node features using bitmasks, which isn't entirely trivial to handle and requires careful management when there are plugin features.

We allow injecting non-official features via plugins, by extending the
`CustomFeaturePlugin` trait. However, we previously added those features
to a set of unknown features: we can do better and add them to the known
features map, which provides pretty-printing in logs and simplifies
debugging.

We also had an issue where `hasFeature` would always return `false` for
plugin features, even when they were supported by both nodes, because we
only looked at our `activated` features map which only contains official
features.

We get rid of the `UnknownFeature` class entirely and keep the encoded
feature bits after deserializing them. We take those feature bits into
account in `hasFeature`, which fixes the issue.

This creates a slightly weird asymmetry because our local features,
which are created based on our `eclair.conf`, will not have this field
set while features that are read from network messages or the DB will
have this field set. A better architecture would be to remove the
`activated` map entirely and directly wrap the feature bits, while
providing helper functions to interact with features without having
to directly read a `BitVector`. This is a larger refactoring though,
because we'd need to add support for filtering `init` / `node` features
using bitmasks, which isn't entirely trivial to handle and requires
careful management of plugin features.
@t-bast t-bast requested review from pm47 and sstone March 10, 2026 17:30
Copy link
Member

@pm47 pm47 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use ByteVector instead of BitVector to store encoded features:

  • it saves error-prone padding
  • we will always get byte-aligned bits from the network anyway
  • we can always convert to bits inside our methods when convenient

Note that we still need a constructor from `BitVector` for Bolt 11
invoices which use a 5-bit encoding.
@t-bast t-bast merged commit a4f4abd into master Mar 17, 2026
1 of 2 checks passed
@t-bast t-bast deleted the refactor-plugin-features branch March 17, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants